QWT API (中文) 7.0.1
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 "qwt_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
177QWT_EXPORT double qwtNormalizeRadians(double radians);
178QWT_EXPORT double qwtNormalizeDegrees(double degrees);
179QWT_EXPORT quint32 qwtRand();
180
200inline int qwtFuzzyCompare(double value1, double value2, double intervalSize)
201{
202 const double eps = qAbs(1.0e-6 * intervalSize);
203
204 if (value2 - value1 > eps)
205 return -1;
206
207 if (value1 - value2 > eps)
208 return 1;
209
210 return 0;
211}
212
214inline int qwtSign(double x)
215{
216 if (x > 0.0)
217 return 1;
218 else if (x < 0.0)
219 return (-1);
220 else
221 return 0;
222}
223
225inline double qwtSqr(double x)
226{
227 return x * x;
228}
229
231inline double qwtFastAtan(double x)
232{
233 if (x < -1.0)
234 return -M_PI_2 - x / (x * x + 0.28);
235
236 if (x > 1.0)
237 return M_PI_2 - x / (x * x + 0.28);
238
239 return x / (1.0 + x * x * 0.28);
240}
241
243inline double qwtFastAtan2(double y, double x)
244{
245 if (x > 0)
246 return qwtFastAtan(y / x);
247
248 if (x < 0) {
249 const double d = qwtFastAtan(y / x);
250 return (y >= 0) ? d + M_PI : d - M_PI;
251 }
252
253 if (y < 0.0)
254 return -M_PI_2;
255
256 if (y > 0.0)
257 return M_PI_2;
258
259 return 0.0;
260}
261
282inline double qwtCubicPolynomial(double x, double a, double b, double c, double d)
283{
284 return (((a * x) + b) * x + c) * x + d;
285}
286
288inline double qwtRadians(double degrees)
289{
290 return degrees * M_PI / 180.0;
291}
292
294inline double qwtDegrees(double degrees)
295{
296 return degrees * 180.0 / M_PI;
297}
298
309inline int qwtCeil(qreal value)
310{
311 using std::ceil;
312 return int(ceil(value));
313}
324inline int qwtFloor(qreal value)
325{
326 using std::floor;
327 return int(floor(value));
328}
329
352inline int qwtVerifyRange(int size, int& i1, int& i2)
353{
354 if (size < 1)
355 return 0;
356
357 i1 = qBound(0, i1, size - 1);
358 i2 = qBound(0, i2, size - 1);
359
360 if (i1 > i2)
361 qSwap(i1, i2);
362
363 return (i2 - i1 + 1);
364}
365
380inline double qwtDistance(const QPointF& p1, const QPointF& p2)
381{
382 double dx = p2.x() - p1.x();
383 double dy = p2.y() - p1.y();
384 return qSqrt(dx * dx + dy * dy);
385}
386
411template< typename T >
412inline typename std::enable_if< std::is_floating_point< T >::value, bool >::type qwt_is_nan_or_inf(const T& value)
413{
414 return !std::isfinite(value);
415}
416
435inline bool qwt_is_nan_or_inf(const QPointF& point)
436{
437 return !std::isfinite(point.x()) || !std::isfinite(point.y());
438}
439
440// Default check function - for other types
451template< typename T >
452typename std::enable_if< !std::is_floating_point< T >::value && !std::is_same< T, QPointF >::value,
453 bool >::type inline qwt_is_nan_or_inf(const T& /*value*/)
454{
455 return false;
456}
457
478template< typename InputIt >
479inline bool qwtContainsNanOrInf(InputIt first, InputIt last)
480{
481 // 使用迭代器遍历,对每个元素调用适当的 qwt_is_nan_or_inf 函数
482 for (InputIt it = first; it != last; ++it) {
483 if (qwt_is_nan_or_inf(*it)) {
484 return true;
485 }
486 }
487 return false;
488}
489
508template< typename Container >
509inline std::size_t qwtRemoveNanOrInf(Container& container)
510{
511 // 使用 std::remove_if 算法将需要保留的元素移动到容器前部
512 auto new_end = std::remove_if(container.begin(), container.end(), [](const typename Container::value_type& value) {
513 return qwt_is_nan_or_inf(value);
514 });
515
516 // 计算被删除的元素数量
517 std::size_t removed_count = std::distance(new_end, container.end());
518
519 // 实际删除不需要的元素
520 if (removed_count > 0) {
521 container.erase(new_end, container.end());
522 }
523
524 return removed_count;
525}
526
543template< typename Container >
544inline Container qwtRemoveNanOrInfCopy(const Container& container)
545{
546 Container result;
547 result.reserve(container.size()); // 预分配空间以提高效率
548
549 // 只复制不是 NaN 或 Inf 的元素
550 std::copy_if(container.begin(),
551 container.end(),
552 std::back_inserter(result),
553 [](const typename Container::value_type& value) { return !qwt_is_nan_or_inf(value); });
554
555 return result;
556}
557
592template< typename It1, typename It2 >
593bool fuzzyRangeEqual(It1 first1, It1 last1, It2 first2, It2 last2)
594{
595 // 1. 长度不同 => 不相等
596 if (std::distance(first1, last1) != std::distance(first2, last2))
597 return false;
598
599 // 2. 逐元素 qFuzzyCompare
600 for (; first1 != last1; ++first1, ++first2) {
601 if (!qFuzzyCompare(*first1, *first2))
602 return false;
603 }
604 return true;
605}
606
607#endif