Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_green_coordinates_math.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <cmath>
10#include <kis_global.h>
11#include <kis_algebra_2d.h>
12using namespace KisAlgebra2D;
13
14
23{
24 QVector<qreal> psi; // for each edge
25 QVector<qreal> phi; // for each vertex
26};
27
28
29struct Q_DECL_HIDDEN KisGreenCoordinatesMath::Private
30{
31 Private () : transformedCageDirection(0) {}
32
36
38
39 void precalculateOnePoint(const QVector<QPointF> &originalCage,
40 PrecalculatedCoords *coords,
41 const QPointF &pt,
43
44 inline void precalculateOneEdge(const QPointF &pt,
45 const QPointF &v1,
46 const QPointF &v2,
47 qreal *edge_psi,
48 qreal *vertex1_phi,
49 qreal *vertex2_phi,
51};
52
53inline void KisGreenCoordinatesMath::
54Private::precalculateOneEdge(const QPointF &pt,
55 const QPointF &v1,
56 const QPointF &v2,
57 qreal *edge_psi,
58 qreal *vertex1_phi,
59 qreal *vertex2_phi,
61{
62 QPointF a = v2 - v1;
63 QPointF b = v1 - pt;
64 qreal Q = dotProduct(a, a);
65 qreal S = dotProduct(b, b);
66 qreal R = dotProduct(2 * a, b);
67
68 qreal BA = dotProduct(b, norm(a) * inwardUnitNormal(a, polygonDirection));
69 qreal SRT = std::sqrt(4 * S * Q - pow2(R));
70 qreal L0 = std::log(S);
71 qreal L1 = std::log(S + Q + R);
72 qreal A0 = std::atan(R / SRT) / SRT;
73 qreal A1 = std::atan((2 * Q + R) / SRT) / SRT;
74 qreal A10 = A1 - A0;
75 qreal L10 = L1 - L0;
76
82 static const qreal magicMultiplier = -1.0;
83
84 *edge_psi = -magicMultiplier * norm(a) / (4 * M_PI) *
85 ((4 * S - pow2(R) / Q) * A10 + R / (2 * Q) * L10 + L1 - 2);
86
87 *vertex2_phi += -BA / (2 * M_PI) * (L10 / (2 * Q) - A10 * R / Q);
88 *vertex1_phi += BA / (2 * M_PI) * (L10 / (2 * Q) - A10 * (2 + R / Q));
89}
90
91void KisGreenCoordinatesMath::Private::precalculateOnePoint(const QVector<QPointF> &originalCage,
92 PrecalculatedCoords *coords,
93 const QPointF &pt,
95{
96 const int numCagePoints = originalCage.size();
97
98 // edge index is defined by the index of the start point
99 // that is: v0-v1 -> e0, v1-v2 -> e1.
100
101 for (int i = 1; i <= numCagePoints; i++) {
102 int endIndex = i != numCagePoints ? i : 0;
103 int startIndex = i - 1;
104
105 precalculateOneEdge(pt,
106 originalCage[startIndex],
107 originalCage[endIndex],
108 &coords->psi[startIndex],
109 &coords->phi[startIndex],
110 &coords->phi[endIndex],
112 }
113}
114
119
123
125{
126 const int cageDirection = polygonDirection(originalCage);
127 const int numPoints = points.size();
128 const int numCagePoints = originalCage.size();
129
130 m_d->originalCageEdgeSizes.resize(numCagePoints);
131
132 for (int i = 1; i <= numCagePoints; i++) {
133 int endIndex = i != numCagePoints ? i : 0;
134 int startIndex = i - 1;
135
136 m_d->originalCageEdgeSizes[startIndex] =
137 norm(originalCage[endIndex] - originalCage[startIndex]);
138 }
139
140 m_d->precalculatedCoords.resize(numPoints);
141
142 for (int i = 0; i < numPoints; i++) {
143 m_d->precalculatedCoords[i].psi.resize(numCagePoints);
144 m_d->precalculatedCoords[i].phi.resize(numCagePoints);
145
146 m_d->precalculateOnePoint(originalCage,
147 &m_d->precalculatedCoords[i],
148 points[i],
149 cageDirection);
150 }
151}
152
154{
155 m_d->transformedCageDirection = polygonDirection(transformedCage);
156
157 const int numCagePoints = transformedCage.size();
158 m_d->transformedCageNormals.resize(numCagePoints);
159
160 for (int i = 1; i <= numCagePoints; i++) {
161 int endIndex = i != numCagePoints ? i : 0;
162 int startIndex = i - 1;
163
164 QPointF transformedEdge =
165 transformedCage[endIndex] - transformedCage[startIndex];
166
167 qreal scaleCoeff =
168 norm(transformedEdge) / m_d->originalCageEdgeSizes[startIndex];
169
170 m_d->transformedCageNormals[startIndex] =
171 scaleCoeff * inwardUnitNormal(transformedEdge, m_d->transformedCageDirection);
172 }
173}
174
175QPointF KisGreenCoordinatesMath::transformedPoint(int pointIndex, const QVector<QPointF> &transformedCage)
176{
177 QPointF result;
178
179 const int numCagePoints = transformedCage.size();
180
181
182 PrecalculatedCoords *coords = &m_d->precalculatedCoords[pointIndex];
183
184 for (int i = 0; i < numCagePoints; i++) {
185 result += coords->phi[i] * transformedCage[i];
186 result += coords->psi[i] * m_d->transformedCageNormals[i];
187 }
188
189 return result;
190}
191
Eigen::Matrix< double, 4, 2 > Q
Eigen::Matrix< double, 4, 2 > S
Eigen::Matrix< double, 4, 2 > R
T pow2(const T &x)
Definition kis_global.h:166
#define M_PI
Definition kis_global.h:111
qreal norm(const T &a)
PointTypeTraits< T >::value_type dotProduct(const T &a, const T &b)
int polygonDirection(const QVector< T > &polygon)
T inwardUnitNormal(const T &a, int polygonDirection)
void generateTransformedCageNormals(const QVector< QPointF > &transformedCage)
void precalculateOneEdge(const QPointF &pt, const QPointF &v1, const QPointF &v2, qreal *edge_psi, qreal *vertex1_phi, qreal *vertex2_phi, int polygonDirection)
QVector< PrecalculatedCoords > precalculatedCoords
QPointF transformedPoint(int pointIndex, const QVector< QPointF > &transformedCage)
const QScopedPointer< Private > m_d
void precalculateGreenCoordinates(const QVector< QPointF > &originalCage, const QVector< QPointF > &points)
void precalculateOnePoint(const QVector< QPointF > &originalCage, PrecalculatedCoords *coords, const QPointF &pt, int polygonDirection)