Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_fast_math.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 *
6 * adopted from here http://web.archive.org/web/20090728150504/http://www.snippetcenter.org/en/a-fast-atan2-function-s1868.aspx
7 */
8
9#include "kis_fast_math.h"
10
11#include <cmath>
12#include <cstdio>
13#include <cstdlib>
14#include <QtGlobal>
15#include <QGlobalStatic>
16
17// Algorithm from http://web.archive.org/web/20090728150504/http://www.snippetcenter.org/en/a-fast-atan2-function-s1868.aspx
18const qreal MAX_SECOND_DERIV_IN_RANGE = 0.6495;
19
21const qreal MAX_ERROR = 0.0001;
22
24
26 qreal nf = ::sqrt(MAX_SECOND_DERIV_IN_RANGE / (8 * MAX_ERROR));
27 NUM_ATAN_ENTRIES = int(nf) + 1;
28 // Build table
29 qreal y = 10.0;
30 qreal x;
31 ATanTable = new qreal[NUM_ATAN_ENTRIES + 1];
32 ATanTable[0] = 0.0;
33 for (quint32 i = 1; i <= NUM_ATAN_ENTRIES; i++) {
34 x = (y / i) * NUM_ATAN_ENTRIES;
35 ATanTable[i] = (qreal)::atan2(y, x);
36 }
37
38 }
39
41 delete [] ATanTable;
42 }
43
45 qreal* ATanTable;
46};
47
48Q_GLOBAL_STATIC(KisATanTable, kisATanTable)
49
50
51
52inline qreal interp(qreal r, qreal a, qreal b)
53{
54 return r*(b - a) + a;
55}
56
57inline qreal calcAngle(qreal x, qreal y)
58{
59 static qreal af = kisATanTable->NUM_ATAN_ENTRIES;
60 static int ai = kisATanTable->NUM_ATAN_ENTRIES;
61 static qreal* ATanTable = kisATanTable->ATanTable;
62 qreal di = (y / x) * af;
63 int i = (int)(di);
64 if (i >= ai) return ::atan2(y, x);
65 return interp(di - i, ATanTable[i], ATanTable[i+1]);
66}
67
68qreal KisFastMath::atan2(qreal y, qreal x)
69{
70
71 if (y == 0.0) { // the line is horizontal
72 if (x >= 0.0) { // towards the right
73 return(0.0);// the angle is 0
74 }
75 // toward the left
76 return qreal(M_PI);
77 } // we now know that y is not 0 check x
78 if (x == 0.0) { // the line is vertical
79 if (y > 0.0) {
80 return M_PI_2;
81 }
82 return -M_PI_2;
83 }
84 // from here on we know that neither x nor y is 0
85 if (x > 0.0) {
86 // we are in quadrant 1 or 4
87 if (y > 0.0) {
88 // we are in quadrant 1
89 // now figure out which side of the 45 degree line
90 if (x > y) {
91 return(calcAngle(x, y));
92 }
93 return(M_PI_2 - calcAngle(y, x));
94 }
95 // we are in quadrant 4
96 y = -y;
97 // now figure out which side of the 45 degree line
98 if (x > y) {
99 return(-calcAngle(x, y));
100 }
101 return(-M_PI_2 + calcAngle(y, x));
102 }
103 // we are in quadrant 2 or 3
104 x = -x;
105 // flip x so we can use it as a positive
106 if (y > 0.0) {
107 // we are in quadrant 2
108 // now figure out which side of the 45 degree line
109 if (x > y) {
110 return(M_PI - calcAngle(x, y));
111 } return(M_PI_2 + calcAngle(y, x));
112 }
113 // we are in quadrant 3
114 y = -y;
115 // flip y so we can use it as a positive
116 // now figure out which side of the 45 degree line
117 if (x > y) {
118 return(-M_PI + calcAngle(x, y));
119 } return(-M_PI_2 - calcAngle(y, x));
120}
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
qreal interp(qreal r, qreal a, qreal b)
private functions
const qreal MAX_SECOND_DERIV_IN_RANGE
qreal calcAngle(qreal x, qreal y)
const qreal MAX_ERROR
precision
#define M_PI
Definition kis_global.h:111
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement
quint32 NUM_ATAN_ENTRIES