Numworks Epsilon  1.4.1
Graphing Calculator Operating System
interactive_curve_view_range.cpp
Go to the documentation of this file.
2 #include <poincare.h>
3 #include <ion.h>
4 #include <cmath>
5 #include <stddef.h>
6 #include <assert.h>
7 
8 using namespace Poincare;
9 
10 namespace Shared {
11 
12 InteractiveCurveViewRange::InteractiveCurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate) :
14  m_yAuto(true),
15  m_delegate(delegate),
16  m_cursor(cursor)
17 {
18 }
19 
21  m_delegate = delegate;
22 }
23 
25  m_cursor = cursor;
26 }
27 
29  float data[5] = {m_xMin, m_xMax, m_yMin, m_yMax, m_yAuto ? 1.0f : 0.0f};
30  size_t dataLengthInBytes = 5*sizeof(float);
31  assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
32  return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
33 }
34 
36  return m_yAuto;
37 }
38 
40  float newXMin = xMin;
42  if (m_xMax - newXMin < k_minFloat) {
43  newXMin = m_xMax - k_minFloat;
45  }
46  if (m_delegate) {
48  }
49 }
50 
52  float newXMax = xMax;
54  if (newXMax - m_xMin < k_minFloat) {
55  newXMax = m_xMin + k_minFloat;
57  }
58  if (m_delegate) {
60  }
61 }
62 
64  float newYMin = yMin;
66  if (m_yMax - newYMin < k_minFloat) {
67  newYMin = m_yMax - k_minFloat;
69  }
70 }
71 
73  float newYMax = yMax;
75  if (newYMax - m_yMin < k_minFloat) {
76  newYMax = m_yMin + k_minFloat;
78  }
79 }
80 
82  m_yAuto = yAuto;
83  if (m_delegate) {
85  }
86 }
87 
88 void InteractiveCurveViewRange::zoom(float ratio, float x, float y) {
89  float xMin = m_xMin;
90  float xMax = m_xMax;
91  float yMin = m_yMin;
92  float yMax = m_yMax;
93  if (ratio*std::fabs(xMax-xMin) < k_minFloat || ratio*std::fabs(yMax-yMin) < k_minFloat) {
94  return;
95  }
96  float newXMin = clipped(x*(1.0f-ratio)+ratio*xMin, false);
97  float newXMax = clipped(x*(1.0f-ratio)+ratio*xMax, true);
98  if (!std::isnan(newXMin) && !std::isnan(newXMax)) {
99  m_xMax = newXMax;
101  }
102  m_yAuto = false;
103  float newYMin = clipped(y*(1.0f-ratio)+ratio*yMin, false);
104  float newYMax = clipped(y*(1.0f-ratio)+ratio*yMax, true);
105  if (!std::isnan(newYMin) && !std::isnan(newYMax)) {
106  m_yMax = newYMax;
108  }
109 }
110 
112  m_yAuto = false;
113  if (clipped(m_xMin + x, false) != m_xMin + x || clipped(m_xMax + x, true) != m_xMax + x || clipped(m_yMin + y, false) != m_yMin + y || clipped(m_yMax + y, true) != m_yMax + y || std::isnan(clipped(m_xMin + x, false)) || std::isnan(clipped(m_xMax + x, true)) || std::isnan(clipped(m_yMin + y, false)) || std::isnan(clipped(m_yMax + y, true))) {
114  return;
115  }
116  m_xMax = clipped(m_xMax + x, true);
118  m_yMax = clipped(m_yMax + y, true);
120 }
121 
123  float xMin = m_xMin;
124  float xMax = m_xMax;
125  float newXMin = clipped(std::round((xMin+xMax)/2) - (float)Ion::Display::Width/2.0f, false);
126  float newXMax = clipped(std::round((xMin+xMax)/2) + (float)Ion::Display::Width/2.0f-1.0f, true);
127  if (std::isnan(newXMin) || std::isnan(newXMax)) {
128  return;
129  }
130  m_xMax = newXMax;
132  if (m_delegate) {
133  m_delegate->didChangeRange(this);
134  }
135 }
136 
138  float xMin = m_xMin;
139  float xMax = m_xMax;
140  float yMin = m_yMin;
141  float yMax = m_yMax;
142  float newXMin = clipped((xMin+xMax)/2 - 5.3f, false);
143  float newXMax = clipped((xMin+xMax)/2 + 5.3f, true);
144  if (!std::isnan(newXMin) && !std::isnan(newXMax)) {
145  m_xMax = newXMax;
147  }
148  m_yAuto = false;
149  float newYMin = clipped((yMin+yMax)/2 - 3.1f, false);
150  float newYMax = clipped((yMin+yMax)/2 + 3.1f, true);
151  if (!std::isnan(newYMin) && !std::isnan(newYMax)) {
152  m_yMax = newYMax;
154  }
155 }
156 
158  m_xMax = 10.5f;
160  if (Preferences::sharedPreferences()->angleUnit() == Expression::AngleUnit::Degree) {
161  m_xMax = 600.0f;
163  }
164  m_yAuto = false;
165  m_yMax = 1.6f;
167 }
168 
170  if (m_delegate == nullptr) {
171  return;
172  }
175  setYAuto(true);
176 }
177 
179  if (std::isnan(position)) {
180  return;
181  }
182  if (axis == Axis::X) {
183  float range = m_xMax - m_xMin;
184  if (std::fabs(position/range) > k_maxRatioPositionRange) {
185  range = std::pow(10.0f, std::floor(std::log10(std::fabs(position)))-1.0f);
186  }
187  m_xMax = clipped(position + range/2.0f, true);
188  MemoizedCurveViewRange::setXMin(clipped(position - range/2.0f, false));
189  } else {
190  m_yAuto = false;
191  float range = m_yMax - m_yMin;
192  if (std::fabs(position/range) > k_maxRatioPositionRange) {
193  range = std::pow(10.0f, std::floor(std::log10(std::fabs(position)))-1.0f);
194  }
195  m_yMax = clipped(position + range/2.0f, true);
196  MemoizedCurveViewRange::setYMin(clipped(position - range/2.0f, false));
197  }
198 }
199 
200 void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation) {
201  float xRange = m_xMax - m_xMin;
202  float yRange = m_yMax - m_yMin;
203  if (x < m_xMin + leftMarginRation*xRange && !std::isinf(x) && !std::isnan(x)) {
204  float newXMin = clipped(x - leftMarginRation*xRange, false);
205  m_xMax = clipped(newXMin + xRange, true);
207  m_yAuto = false;
208  }
209  if (x > m_xMax - rightMarginRatio*xRange && !std::isinf(x) && !std::isnan(x)) {
210  m_xMax = clipped(x + rightMarginRatio*xRange, true);
212  m_yAuto = false;
213  }
214  if (y < m_yMin + bottomMarginRation*yRange && !std::isinf(y) && !std::isnan(y)) {
215  float newYMin = clipped(y - bottomMarginRation*yRange, false);
216  m_yMax = clipped(newYMin + yRange, true);
218  m_yAuto = false;
219  }
220  if (y > m_yMax - topMarginRatio*yRange && !std::isinf(y) && !std::isnan(y)) {
221  m_yMax = clipped(y + topMarginRatio*yRange, true);
223  m_yAuto = false;
224  }
225 }
226 
227 bool InteractiveCurveViewRange::isCursorVisible(float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation) {
228  float xRange = m_xMax - m_xMin;
229  float yRange = m_yMax - m_yMin;
230  return m_cursor->x() >= m_xMin + leftMarginRation*xRange && m_cursor->x() <= m_xMax - rightMarginRatio*xRange && m_cursor->y() >= m_yMin + bottomMarginRation*yRange && m_cursor->y() <= m_yMax - topMarginRatio*yRange;
231 }
232 
233 float InteractiveCurveViewRange::clipped(float x, bool isMax) {
234  float max = isMax ? k_upperMaxFloat : k_lowerMaxFloat;
235  float min = isMax ? -k_lowerMaxFloat : -k_upperMaxFloat;
236  float clippedX = x > max ? max : x;
237  clippedX = clippedX < min ? min : clippedX;
238  return clippedX;
239 }
240 
241 }
#define assert(e)
Definition: assert.h:9
#define isinf(x)
Definition: math.h:44
def data
Definition: i18n.py:176
constexpr int Width
Definition: display.h:26
InteractiveCurveViewRangeDelegate * m_delegate
void zoom(float ratio, float x, float y)
#define fabs(x)
Definition: math.h:178
unsigned int uint32_t
Definition: stdint.h:6
#define round(x)
Definition: math.h:192
#define pow(x, y)
Definition: math.h:190
#define log10(x)
Definition: math.h:186
#define isnan(x)
Definition: math.h:43
bool isCursorVisible(float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation)
void panToMakePointVisible(float x, float y, float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation)
bool didChangeRange(InteractiveCurveViewRange *interactiveCurveViewRange)
uint32_t crc32(const uint32_t *data, size_t length)
Definition: device.cpp:37
void centerAxisAround(Axis axis, float position)
void setDelegate(InteractiveCurveViewRangeDelegate *delegate)
#define floor(x)
Definition: math.h:179
constexpr Poincare::Expression::AngleUnit Degree
Definition: helper.h:3
static float clipped(float f, bool isMax)
#define true
Definition: stdbool.h:8