Skip to content

Commit

Permalink
Merge pull request #269 from ABRG-Models/268-review-the-autorescale
Browse files Browse the repository at this point in the history
GraphVisual auto-rescaling review. Seems to be working nicely, including on some in-work systems.
  • Loading branch information
sebjameswml authored Oct 17, 2024
2 parents b5f016c + 658e28a commit e6c856b
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 192 deletions.
7 changes: 5 additions & 2 deletions docs/ref/coremaths/range.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ morph::range<float> r(0.0f, 10.0f); // Construct with a defined range
**Update** the range to include a value
```c++
morph::range<int> r; // range initially 0 to 0
r.update (100); // range now 0 to 100
r.update (-100); // range now -100 to 100
bool changed1 = r.update (100); // range now 0 to 100
bool changed2 = r.update (-100); // range now -100 to 100
bool changed3 = r.update (50); // range unchanged; still -100 to 100
```

`update` returns a `bool` which will be true if the range was changed and false if the range is not changed. In the example above, `changed1` and changed2` will both be `true`, but `changed3` will contain `false`.

**Set** the range manually in a single function call
```c++
morph::range<int> r; // range initially 0 to 0
Expand Down
10 changes: 9 additions & 1 deletion docs/ref/coremaths/scale.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,15 @@ s.output_range.max = 5;
s.compute_scaling (-10, 10);
```

You can also trigger the computation of the scaling function if you have a container of data by using `compute_scaling_from_data`, which is the function that is automatically called by `transform` when `do_autoscale` is `true`.
You can also pass the input range to `Scale<>::compute_scaling` and set the `output_range` using `morph::range<>` objects:

```c++
morph::Scale<int, float> s;
s.output_range = morph::range<float>{0, 5};
s.compute_scaling (morph::range<int>{-10, 10});
```
You can trigger the computation of the scaling function if you have a container of data by using `compute_scaling_from_data`, which is the function that is automatically called by `transform` when `do_autoscale` is `true`.
```c++
morph::Scale<int, float> s;
Expand Down
2 changes: 1 addition & 1 deletion examples/graph_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ int main()
ds.linewidth = ds.markersize/8.0f;
// Bar graphs usually need to extend up from 0, so set scaling policy for the y axis accordingly:
gv->scalingpolicy_y = morph::scalingpolicy::manual_min;
gv->datamin_y = 0;
gv->datarange_y.min = 0;
// Set the data-to-axis distance based on the markersize.
gv->setdataaxisdist (0.04f + ds.markersize/2.0f);
gv->setdata (absc, ord, ds);
Expand Down
400 changes: 216 additions & 184 deletions morph/GraphVisual.h

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions morph/Scale.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ namespace morph {
*/
virtual void compute_autoscale (T input_min, T input_max) = 0; // deprecated name, left to avoid breaking client code
virtual void compute_scaling (const T input_min, const T input_max) = 0;
virtual void compute_scaling (const morph::range<T>& input_range) = 0;

/*!
* \brief Compute scaling function from data
Expand Down Expand Up @@ -366,6 +367,7 @@ namespace morph {
this->compute_scaling (input_min, input_max);
}

virtual void compute_scaling (const morph::range<T>& input_range) { this->compute_scaling (input_range.min, input_range.max); }
virtual void compute_scaling (const T input_min, const T input_max)
{
if (this->type != ScaleFn::Linear) {
Expand Down Expand Up @@ -527,6 +529,7 @@ namespace morph {
this->compute_scaling (input_min, input_max);
}

virtual void compute_scaling (const morph::range<T>& input_range) { this->compute_scaling (input_range.min, input_range.max); }
virtual void compute_scaling (const T input_min, const T input_max)
{
if (this->type == ScaleFn::Logarithmic) {
Expand Down
10 changes: 6 additions & 4 deletions morph/range.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ namespace morph {
this->max = std::numeric_limits<T>::lowest();
}

// Extend the range to include the given datum
constexpr void update (const T& d)
// Extend the range to include the given datum. Return true if the range changed.
constexpr bool update (const T& d)
{
this->min = d < this->min ? d : this->min;
this->max = d > this->max ? d : this->max;
bool changed = false;
this->min = d < this->min ? changed = true, d : this->min;
this->max = d > this->max ? changed = true, d : this->max;
return changed;
}

// Does the range include v?
Expand Down
3 changes: 3 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ add_test(testMathAlgo2 testMathAlgo2)
add_executable(testScale testScale.cpp)
add_test(testScale testScale)

add_executable(testrange testrange.cpp)
add_test(testrange testrange)

# Test the colour mapping
add_executable(testColourMap testColourMap.cpp)
add_test(testColourMap testColourMap)
Expand Down
7 changes: 7 additions & 0 deletions tests/testScale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,12 @@ int main () {
// Fifth element should be NaN still:
if (!std::isnan(resultnan[5])) { --rtn; }

morph::Scale<int, float> sif;
sif.output_range = morph::range<float>{0, 5};
sif.compute_scaling (morph::range<int>{-10, 10});
std::cout << "input 8(int) transforms to float: " << sif.transform_one (8) << std::endl;
if (sif.transform_one (8) != 4.5f) { --rtn; }

std::cout << "testScale " << (rtn == 0 ? "Passed" : "Failed") << std::endl;
return rtn;
}
16 changes: 16 additions & 0 deletions tests/testrange.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <iostream>
#include <morph/range.h>
#include <morph/mathconst.h>

int main()
{
int rtn = 0;

morph::range<float> r(2.0f, 4.0f);
if (r.update (1.0f) == false) { --rtn; } // Update with 1 should change the range and return true
if (r.update (5.0f) == false) { --rtn; } // Update with 5 should change the range and return true
if (r.update (3.0f) == true) { --rtn; } // Update with 3 should not change the range

std::cout << "Test " << (rtn == 0 ? "Passed" : "Failed") << std::endl;
return rtn;
}

0 comments on commit e6c856b

Please sign in to comment.