mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
Scenario: just zoom in in a graph Fix: - Do not truncate labels. - Label size is computed depending on available size and number of labels. - If labels cannot be displayed properly, just display the minimal and maximal labels!
128 lines
5.6 KiB
C++
128 lines
5.6 KiB
C++
#include "curve_view_range.h"
|
|
#include "curve_view.h"
|
|
#include <cmath>
|
|
#include <ion.h>
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
#include <float.h>
|
|
|
|
namespace Shared {
|
|
|
|
uint32_t CurveViewRange::rangeChecksum() {
|
|
float data[4] = {xMin(), xMax(), yMin(), yMax()};
|
|
size_t dataLengthInBytes = 4*sizeof(float);
|
|
assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
|
|
return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
|
|
}
|
|
|
|
float CurveViewRange::yGridUnit() {
|
|
return 0.0f;
|
|
}
|
|
|
|
float CurveViewRange::computeGridUnit(Axis axis, float range1) {
|
|
float range = axis == Axis::Y ? range1 : ((1.0f-2.0f*CurveView::k_labelsHorizontalMarginRatio)*range1);
|
|
// TODO share the axis enum of curve_view and then call a static method CurveView::marginRatio(Axis)
|
|
int a = 0;
|
|
int b = 0;
|
|
float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits;
|
|
float minNumberOfUnits = (axis == Axis::X) ? k_minNumberOfXGridUnits : k_minNumberOfYGridUnits;
|
|
constexpr int unitsCount = 3;
|
|
float units[unitsCount] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa};
|
|
for (int k = 0; k < unitsCount; k++) {
|
|
float currentA = units[k];
|
|
int b1 = std::floor(std::log10(range/(currentA*maxNumberOfUnits)));
|
|
int b2 = std::floor(std::log10(range/(currentA*minNumberOfUnits)));
|
|
if (b1 != b2) {
|
|
b = b2;
|
|
a = currentA;
|
|
}
|
|
}
|
|
return a*std::pow(10.0f,b);
|
|
|
|
/* Proof of the algorithm:
|
|
*
|
|
* We want to find gridUnit = a*10^b, with a in {1; 2; 5} and b an integer
|
|
* We want: minNumberOfUnits <= range/gridUnit < maxNumberOfUnits
|
|
*
|
|
* A solution thus needs to verify:
|
|
*
|
|
* minNumberOfUnits/range <= 1/(a*10^b) < maxNumberOfUnits/range
|
|
* => range/minNumberOfUnits >= a*10^b > range/maxNumberOfUnits
|
|
* => range/(a*minNumberOfUnits) >= 10^b > range/(a*maxNumberOfUnits)
|
|
* => log10(range/(a*minNumberOfUnits)) >= b > log10(range/(a*maxNumberOfUnits))
|
|
* => (1) log10(range/(a*maxNumberOfUnits)) < b <= log10(range/(a*minNumberOfUnits))
|
|
* And, because b must be an integer,
|
|
* => floor(log10(range/(a*maxNumberOfUnits))) != floor(log10(range/(a*minNumberOfUnits)))
|
|
* The solution is then b = floor(log10(range/(a*minNumberOfUnits)))
|
|
*
|
|
* Is there always at least one solution ?
|
|
*
|
|
* (1) also gives:
|
|
* E1 = log10(range)-log10(a)-log10(maxNumberOfUnits) < b <= log10(range)-log10(a)-log10(maxNumberOfUnits) = E2
|
|
*
|
|
* Let's compute E2-E1:
|
|
* E2-E1 = log10(maxNumberOfUnits) - log10(minNumberOfUnits)
|
|
* For minNumberOfUnits=7 and maxNumberOfUnits=18, E2-E1 = 0.41...
|
|
* For minNumberOfUnits=5 and maxNumberOfUnits=13, E2-E1 = 0.41...
|
|
*
|
|
* Let's compute the union of the [E1;E2] for a in {1; 2; 5}:
|
|
* [E1;E2 for a=1] U [E1;E2 for a=2] U [E1;E2 for a=5]
|
|
* = [e1;e2] U [e1-log10(2); e2-log10(2)] U [e1-log10(5); e2-log10(5)]
|
|
* = [e1;e2] U [e1-0.3; e2-0.3] U [e1-0.7; e2-0.7]
|
|
* = [e1-0.7; e2-0.7] U [e1-0.3; e2-0.3] U [e1;e2]
|
|
* = [e1-0.7; e2] because e2-0.7 > e1-0.3 as e2-e1 > 0.7-0.3 and e2-e1 = E2-E1 = 0.41...
|
|
* and e2-0.3 > e1 as e2-e1 > 0.3
|
|
*
|
|
* The union of the [E1;E2] for a in {1; 2; 5} is an interval of size
|
|
* e2-e1+0.7 = 1.1 > 1.
|
|
* We will thus always have at least one a in {1; 2; 5} for which E1 and E2
|
|
* are on each side of an integer.
|
|
*
|
|
* Let's make a drawing.
|
|
*
|
|
* n n+1 n+2 n+3 n+4 n+5
|
|
* |.........|.........|.........|.........|.........|...
|
|
* E1^---^E2
|
|
* 0.41
|
|
* *
|
|
* To have a solution, we need E1 and E2 to be on each side of an integer.
|
|
*
|
|
* --------------------------------------------------------------------------------------------
|
|
* --------------------------------------------------------------------------------------------
|
|
*
|
|
* If e1 - floor(e1) > 1-(e2-e1) = 0.58..., a=1 is a solution
|
|
*
|
|
* n n+0.2 n+0.4 n+0.6 n+0.8 n+1
|
|
* .........||....|....|....|....|....|....|....|....|....|....||... a=1
|
|
* e1^--------------------^e2
|
|
*
|
|
* --------------------------------------------------------------------------------------------
|
|
* --------------------------------------------------------------------------------------------
|
|
*
|
|
* If log10(5)-(e2-e1) = 0.29... < e1 - floor(e1) < log10(5) = 0.69..., a=5 is a solution
|
|
*
|
|
* n n+0.2 n+0.4 n+0.6 n+0.8 n+1
|
|
* .........||....|....|....|....|....|....|....|....|....|....||...
|
|
* e1^--------------------^e2
|
|
*
|
|
* n n+0.2 n+0.4 n+0.6 n+0.8 n+1
|
|
* .........||....|....|....|....|....|....|....|....|....|....||... a=5
|
|
* E1^--------------------^E2 <- shift by log10(5) = 0.7
|
|
*
|
|
* --------------------------------------------------------------------------------------------
|
|
* --------------------------------------------------------------------------------------------
|
|
*
|
|
* If e1 - floor(e1) < log10(2) = 0.3..., a=2 is a solution
|
|
* n n+0.2 n+0.4 n+0.6 n+0.8 n+1
|
|
* .........||....|....|....|....|....|....|....|....|....|....||...
|
|
* e1^--------------------^e2
|
|
*
|
|
* n n+0.2 n+0.4 n+0.6 n+0.8 n+1
|
|
* .........||....|....|....|....|....|....|....|....|....|....||... a=2
|
|
* E1^--------------------^E2 <- shift by log10(2) = 0.3
|
|
*
|
|
* */
|
|
}
|
|
|
|
}
|