mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps/shared] New automatic zoom on curves
Initial zoom for displaying curves is computed according to the
following rules :
- For polar and parametric curves, the algorithm has not changed.
Vertical and horizontal ranges are chosen in order to display the
full curve with orthonormal graduations.
- For cartesian curves, the horizontal range is chosen in order to
display all points of interest (roots, extrema, asymptotes...).
The vertical range is fitted to be able to display those points, but
also cuts out points outside of the function's order of magnitude.
Change-Id: Idf8233fc2e6586b85d34c4da152c83e75513d85c
This commit is contained in:
committed by
Émilie Feral
parent
1917999f6d
commit
8104caea50
@@ -73,53 +73,6 @@ void FunctionGraphController::reloadBannerView() {
|
||||
reloadBannerViewForCursorOnFunction(m_cursor, record, functionStore(), AppsContainer::sharedAppsContainer()->globalContext());
|
||||
}
|
||||
|
||||
InteractiveCurveViewRangeDelegate::Range FunctionGraphController::computeYRange(InteractiveCurveViewRange * interactiveCurveViewRange) {
|
||||
Poincare::Context * context = textFieldDelegateApp()->localContext();
|
||||
float min = FLT_MAX;
|
||||
float max = -FLT_MAX;
|
||||
float xMin = interactiveCurveViewRange->xMin();
|
||||
float xMax = interactiveCurveViewRange->xMax();
|
||||
assert(functionStore()->numberOfActiveFunctions() > 0);
|
||||
for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) {
|
||||
ExpiringPointer<Function> f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i));
|
||||
/* Scan x-range from the middle to the extrema in order to get balanced
|
||||
* y-range for even functions (y = 1/x). */
|
||||
double tMin = f->tMin();
|
||||
if (std::isnan(tMin)) {
|
||||
tMin = xMin;
|
||||
} else if (f->shouldClipTRangeToXRange()) {
|
||||
tMin = std::max<double>(tMin, xMin);
|
||||
}
|
||||
double tMax = f->tMax();
|
||||
if (std::isnan(tMax)) {
|
||||
tMax = xMax;
|
||||
} else if (f->shouldClipTRangeToXRange()) {
|
||||
tMax = std::min<double>(tMax, xMax);
|
||||
}
|
||||
/* In practice, a step smaller than a pixel's width is needed for sampling
|
||||
* the values of a function. Otherwise some relevant extremal values may be
|
||||
* missed. */
|
||||
float rangeStep = f->rangeStep();
|
||||
const float step = std::isnan(rangeStep) ? curveView()->pixelWidth() / 2.0f : rangeStep;
|
||||
const int balancedBound = std::floor((tMax-tMin)/2/step);
|
||||
for (int j = -balancedBound; j <= balancedBound ; j++) {
|
||||
float t = (tMin+tMax)/2 + step * j;
|
||||
Coordinate2D<float> xy = f->evaluateXYAtParameter(t, context);
|
||||
float x = xy.x1();
|
||||
if (!std::isnan(x) && !std::isinf(x) && x >= xMin && x <= xMax) {
|
||||
float y = xy.x2();
|
||||
if (!std::isnan(y) && !std::isinf(y)) {
|
||||
min = std::min(min, y);
|
||||
max = std::max(max, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InteractiveCurveViewRangeDelegate::Range range;
|
||||
range.min = min;
|
||||
range.max = max;
|
||||
return range;
|
||||
}
|
||||
|
||||
double FunctionGraphController::defaultCursorT(Ion::Storage::Record record) {
|
||||
return (interactiveCurveViewRange()->xMin()+interactiveCurveViewRange()->xMax())/2.0f;
|
||||
|
||||
Reference in New Issue
Block a user