QWT API (中文) 7.3.0
Qt绘图库 - 中文API文档
载入中...
搜索中...
未找到
qwt_math.h
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *
9 * Modified by ChenZongYan in 2024 <czy.t@163.com>
10 * Summary of major modifications (see ChangeLog.md for full history):
11 * 1. CMake build system & C++11 throughout.
12 * 2. Core panner/ zoomer refactored:
13 * - QwtPanner → QwtCachePanner (pixmap-cache version)
14 * - New real-time QwtPlotPanner derived from QwtPicker.
15 * 3. Zoomer supports multi-axis.
16 * 4. Parasite-plot framework:
17 * - QwtFigure, QwtPlotParasiteLayout, QwtPlotTransparentCanvas,
18 * - QwtPlotScaleEventDispatcher, built-in pan/zoom on axis.
19 * 5. New picker: QwtPlotSeriesDataPicker (works with date axis).
20 * 6. Raster & color-map extensions:
21 * - QwtGridRasterData (2-D table + interpolation)
22 * - QwtLinearColorMap::stopColors(), stopPos() API rename.
23 * 7. Bar-chart: expose pen/brush control.
24 * 8. Amalgamated build: single QwtPlot.h / QwtPlot.cpp pair in src-amalgamate.
25 *****************************************************************************/
26
27#ifndef QWT_MATH_H
28#define QWT_MATH_H
29// stl
30#include <iterator>
31#include <type_traits>
32#include <algorithm>
33// qt
34#include <QPointF>
35#include <QtMath>
36// qwt
37#include "qwtcore_global.h"
38/*
39 Microsoft says:
40
41 Define _USE_MATH_DEFINES before including math.h to expose these macro
42 definitions for common math constants. These are placed under an #ifdef
43 since these commonly-defined names are not part of the C/C++ standards.
44 */
45
46#ifndef _USE_MATH_DEFINES
47#define _USE_MATH_DEFINES
48#define undef_USE_MATH_DEFINES
49#endif
50
51#include <cmath>
52
53#ifdef undef_USE_MATH_DEFINES
54#undef _USE_MATH_DEFINES
55#undef undef_USE_MATH_DEFINES
56#endif
57
58#ifndef M_E
59#define M_E (2.7182818284590452354)
60#endif
61
62#ifndef M_LOG2E
63#define M_LOG2E (1.4426950408889634074)
64#endif
65
66#ifndef M_LOG10E
67#define M_LOG10E (0.43429448190325182765)
68#endif
69
70#ifndef M_LN2
71#define M_LN2 (0.69314718055994530942)
72#endif
73
74#ifndef M_LN10
75#define M_LN10 (2.30258509299404568402)
76#endif
77
78#ifndef M_PI
79#define M_PI (3.14159265358979323846)
80#endif
81
82#ifndef M_PI_2
83#define M_PI_2 (1.57079632679489661923)
84#endif
85
86#ifndef M_PI_4
87#define M_PI_4 (0.78539816339744830962)
88#endif
89
90#ifndef M_1_PI
91#define M_1_PI (0.31830988618379067154)
92#endif
93
94#ifndef M_2_PI
95#define M_2_PI (0.63661977236758134308)
96#endif
97
98#ifndef M_2_SQRTPI
99#define M_2_SQRTPI (1.12837916709551257390)
100#endif
101
102#ifndef M_SQRT2
103#define M_SQRT2 (1.41421356237309504880)
104#endif
105
106#ifndef M_SQRT1_2
107#define M_SQRT1_2 (0.70710678118654752440)
108#endif
109
110#if defined(QT_WARNING_PUSH)
111/*
112 early Qt versions not having QT_WARNING_PUSH is full of warnings
113 so that we do not care of suppressing those from below
114 */
115QT_WARNING_PUSH
116QT_WARNING_DISABLE_CLANG("-Wdouble-promotion")
117QT_WARNING_DISABLE_GCC("-Wdouble-promotion")
118#endif
119
120/*
121 On systems, where qreal is a float you often run into
122 compiler issues with qMin/qMax.
123 */
124
126constexpr inline float qwtMinF(float a, float b)
127{
128 return (a < b) ? a : b;
129}
130
132constexpr inline double qwtMinF(double a, double b)
133{
134 return (a < b) ? a : b;
135}
136
138constexpr inline qreal qwtMinF(float a, double b)
139{
140 return (a < b) ? a : b;
141}
142
144constexpr inline qreal qwtMinF(double a, float b)
145{
146 return (a < b) ? a : b;
147}
148
150constexpr inline float qwtMaxF(float a, float b)
151{
152 return (a < b) ? b : a;
153}
154
156constexpr inline double qwtMaxF(double a, double b)
157{
158 return (a < b) ? b : a;
159}
160
162constexpr inline qreal qwtMaxF(float a, double b)
163{
164 return (a < b) ? b : a;
165}
166
168constexpr inline qreal qwtMaxF(double a, float b)
169{
170 return (a < b) ? b : a;
171}
172
173#if defined(QT_WARNING_POP)
174QT_WARNING_POP
175#endif
176
177QWTCORE_EXPORT double qwtNormalizeRadians(double radians);
178QWTCORE_EXPORT double qwtNormalizeDegrees(double degrees);
179QWTCORE_EXPORT quint32 qwtRand();
180
190inline int qwtFuzzyCompare(double value1, double value2, double intervalSize)
191{
192 const double eps = qAbs(1.0e-6 * intervalSize);
193
194 if (value2 - value1 > eps)
195 return -1;
196
197 if (value1 - value2 > eps)
198 return 1;
199
200 return 0;
201}
202
204inline int qwtSign(double x)
205{
206 if (x > 0.0)
207 return 1;
208 else if (x < 0.0)
209 return (-1);
210 else
211 return 0;
212}
213
215inline constexpr double qwtSqr(double x)
216{
217 return x * x;
218}
219
221inline double qwtFastAtan(double x)
222{
223 if (x < -1.0)
224 return -M_PI_2 - x / (x * x + 0.28);
225
226 if (x > 1.0)
227 return M_PI_2 - x / (x * x + 0.28);
228
229 return x / (1.0 + x * x * 0.28);
230}
231
233inline double qwtFastAtan2(double y, double x)
234{
235 if (x > 0)
236 return qwtFastAtan(y / x);
237
238 if (x < 0) {
239 const double d = qwtFastAtan(y / x);
240 return (y >= 0) ? d + M_PI : d - M_PI;
241 }
242
243 if (y < 0.0)
244 return -M_PI_2;
245
246 if (y > 0.0)
247 return M_PI_2;
248
249 return 0.0;
250}
251
261inline constexpr double qwtCubicPolynomial(double x, double a, double b, double c, double d)
262{
263 return (((a * x) + b) * x + c) * x + d;
264}
265
267inline constexpr double qwtRadians(double degrees)
268{
269 return degrees * M_PI / 180.0;
270}
271
273inline constexpr double qwtDegrees(double degrees)
274{
275 return degrees * 180.0 / M_PI;
276}
277
282inline int qwtCeil(qreal value)
283{
284 using std::ceil;
285 return int(ceil(value));
286}
291inline int qwtFloor(qreal value)
292{
293 using std::floor;
294 return int(floor(value));
295}
296
307inline int qwtVerifyRange(int size, int& i1, int& i2)
308{
309 if (size < 1)
310 return 0;
311
312 i1 = qBound(0, i1, size - 1);
313 i2 = qBound(0, i2, size - 1);
314
315 if (i1 > i2)
316 qSwap(i1, i2);
317
318 return (i2 - i1 + 1);
319}
320
327inline double qwtDistance(const QPointF& p1, const QPointF& p2)
328{
329 double dx = p2.x() - p1.x();
330 double dy = p2.y() - p1.y();
331 return qSqrt(dx * dx + dy * dy);
332}
333
345template< typename T >
346inline typename std::enable_if< std::is_floating_point< T >::value, bool >::type qwt_is_nan_or_inf(const T& value)
347{
348 return !std::isfinite(value);
349}
350
359inline bool qwt_is_nan_or_inf(const QPointF& point)
360{
361 return !std::isfinite(point.x()) || !std::isfinite(point.y());
362}
363
364// Default check function - for other types
369template< typename T >
370typename std::enable_if< !std::is_floating_point< T >::value && !std::is_same< T, QPointF >::value,
371 bool >::type inline qwt_is_nan_or_inf(const T& /*value*/)
372{
373 return false;
374}
375
385template< typename InputIt >
386inline bool qwtContainsNanOrInf(InputIt first, InputIt last)
387{
388 // Iterate using iterator, calling the appropriate qwt_is_nan_or_inf function for each element
389 for (InputIt it = first; it != last; ++it) {
390 if (qwt_is_nan_or_inf(*it)) {
391 return true;
392 }
393 }
394 return false;
395}
396
405template< typename Container >
406inline std::size_t qwtRemoveNanOrInf(Container& container)
407{
408 // Use std::remove_if algorithm to move retained elements to the front of the container
409 auto new_end = std::remove_if(container.begin(), container.end(), [](const typename Container::value_type& value) {
410 return qwt_is_nan_or_inf(value);
411 });
412
413 // Calculate the number of removed elements
414 std::size_t removed_count = std::distance(new_end, container.end());
415
416 // Actually erase the unwanted elements
417 if (removed_count > 0) {
418 container.erase(new_end, container.end());
419 }
420
421 return removed_count;
422}
423
431template< typename Container >
432inline Container qwtRemoveNanOrInfCopy(const Container& container)
433{
434 Container result;
435 result.reserve(container.size()); // pre-allocate for efficiency
436
437 // Copy only elements that are not NaN or Inf
438 std::copy_if(container.begin(),
439 container.end(),
440 std::back_inserter(result),
441 [](const typename Container::value_type& value) { return !qwt_is_nan_or_inf(value); });
442
443 return result;
444}
445
462template< typename It1, typename It2 >
463bool fuzzyRangeEqual(It1 first1, It1 last1, It2 first2, It2 last2)
464{
465 // 1. Different lengths => not equal
466 if (std::distance(first1, last1) != std::distance(first2, last2))
467 return false;
468
469 // 2. Element-wise qFuzzyCompare
470 for (; first1 != last1; ++first1, ++first2) {
471 if (!qFuzzyCompare(*first1, *first2))
472 return false;
473 }
474 return true;
475}
476
477#endif