Krita Source Code Documentation
Loading...
Searching...
No Matches
PerspectiveBasedAssistantHelper Class Reference

#include <PerspectiveBasedAssistantHelper.h>

Classes

class  CacheData
 

Static Public Member Functions

static qreal distanceInGrid (const CacheData &cache, const QPointF &point)
 
static qreal distanceInGrid (const QList< KisPaintingAssistantHandleSP > &handles, bool isAssistantComplete, const QPointF &point)
 
static QPolygonF getAllConnectedTetragon (const QList< KisPaintingAssistantHandleSP > &handles)
 
static bool getTetragon (const QList< KisPaintingAssistantHandleSP > &handles, bool isAssistantComplete, QPolygonF &outPolygon)
 
static bool getVanishingPointsOptional (const QPolygonF &poly, boost::optional< QPointF > &vp1, boost::optional< QPointF > &vp2)
 
static qreal inverseMaxLocalScale (const QTransform &transform)
 
static qreal localScale (const QTransform &transform, QPointF pt)
 
static qreal pdot (const QPointF &a, const QPointF &b)
 
static void updateCacheData (CacheData &cache, const QPolygonF &poly)
 

Private Member Functions

 PerspectiveBasedAssistantHelper ()
 
 ~PerspectiveBasedAssistantHelper ()
 

Detailed Description

Definition at line 18 of file PerspectiveBasedAssistantHelper.h.

Constructor & Destructor Documentation

◆ PerspectiveBasedAssistantHelper()

PerspectiveBasedAssistantHelper::PerspectiveBasedAssistantHelper ( )
private

◆ ~PerspectiveBasedAssistantHelper()

PerspectiveBasedAssistantHelper::~PerspectiveBasedAssistantHelper ( )
private

Member Function Documentation

◆ distanceInGrid() [1/2]

qreal PerspectiveBasedAssistantHelper::distanceInGrid ( const CacheData & cache,
const QPointF & point )
static

Definition at line 186 of file PerspectiveBasedAssistantHelper.cpp.

187{
188 qreal defaultValue = 1;
189 if (cache.maxDistanceFromPoint == 0.0) {
190 return defaultValue;
191 }
192
193 if (!cache.vanishingPoint1 && !cache.vanishingPoint2) {
194 return defaultValue; // possibly wrong shape
195 } else if (!cache.vanishingPoint1 || !cache.vanishingPoint2) {
196 // result should be:
197 // dist from horizon / max dist from horizon
198 // horizon is parallel to the parallel sides of the tetragon (two must be parallel if there is only one vp)
199 qreal dist = kisDistanceToLine(point, cache.horizon);
200 return dist/cache.maxDistanceFromPoint;
201 } else if (cache.vanishingPoint1 && cache.vanishingPoint2) {
202 // should be:
203 // dist from vp-line / max dist from vp-line
204 qreal dist = kisDistanceToLine(point, cache.horizon);
205 return dist/cache.maxDistanceFromPoint;
206 }
207
208 return defaultValue;
209}
qreal kisDistanceToLine(const QPointF &m, const QLineF &line)
Definition kis_global.h:234

References PerspectiveBasedAssistantHelper::CacheData::horizon, kisDistanceToLine(), PerspectiveBasedAssistantHelper::CacheData::maxDistanceFromPoint, PerspectiveBasedAssistantHelper::CacheData::vanishingPoint1, and PerspectiveBasedAssistantHelper::CacheData::vanishingPoint2.

◆ distanceInGrid() [2/2]

qreal PerspectiveBasedAssistantHelper::distanceInGrid ( const QList< KisPaintingAssistantHandleSP > & handles,
bool isAssistantComplete,
const QPointF & point )
static

Definition at line 122 of file PerspectiveBasedAssistantHelper.cpp.

123{
124 // TODO: make it not calculate the poly max distance over and over
125 qreal defaultValue = 1;
126 int vertexCount = 4;
127
128 QPolygonF poly;
129 if (!PerspectiveBasedAssistantHelper::getTetragon(handles, isAssistantComplete, poly)) {
130 return defaultValue;
131 }
132
133 boost::optional<QPointF> vp1;
134 boost::optional<QPointF> vp2;
135
137 if (!vp1 && !vp2) {
138 return defaultValue; // possibly wrong shape
139 } else if (!vp1 || !vp2) {
140 // result should be:
141 // dist from horizon / max dist from horizon
142 // horizon is parallel to the parallel sides of the tetragon (two must be parallel if there is only one vp)
143 QLineF horizon;
144 if (vp1) {
145 // that means the 0-1 line is the horizon parallel line
146 horizon = QLineF(vp1.get(), vp1.get() + poly[1] - poly[0]);
147 } else {
148 horizon = QLineF(vp2.get(), vp2.get() + poly[2] - poly[1]);
149 }
150
151 qreal dist = kisDistanceToLine(point, horizon);
152 qreal distMax = 0;
153 for (int i = 0; i < vertexCount; i++) {
154 qreal vertexDist = kisDistanceToLine(poly[i], horizon);
155 if (vertexDist > distMax) {
156 distMax = vertexDist;
157 }
158 }
159 if (distMax == 0) {
160 return defaultValue;
161 }
162 return dist/distMax;
163 } else if (vp1 && vp2) {
164 // should be:
165 // dist from vp-line / max dist from vp-line
166 QLineF horizon = QLineF(vp1.get(), vp2.get());
167
168 qreal dist = kisDistanceToLine(point, horizon);
169 qreal distMax = 0;
170 for (int i = 0; i < vertexCount; i++) {
171 qreal vertexDist = kisDistanceToLine(poly[i], horizon);
172 if (vertexDist > distMax) {
173 distMax = vertexDist;
174 }
175 }
176 if (distMax == 0) {
177 return defaultValue;
178 }
179 return dist/distMax;
180 }
181
182 return defaultValue;
183
184}
static bool getVanishingPointsOptional(const QPolygonF &poly, boost::optional< QPointF > &vp1, boost::optional< QPointF > &vp2)
static bool getTetragon(const QList< KisPaintingAssistantHandleSP > &handles, bool isAssistantComplete, QPolygonF &outPolygon)

References getTetragon(), getVanishingPointsOptional(), and kisDistanceToLine().

◆ getAllConnectedTetragon()

QPolygonF PerspectiveBasedAssistantHelper::getAllConnectedTetragon ( const QList< KisPaintingAssistantHandleSP > & handles)
static

Definition at line 79 of file PerspectiveBasedAssistantHelper.cpp.

80{
81 QPolygonF polyAllConnected;
82 if (handles.size() < 4) {
83 return polyAllConnected;
84 }
85 polyAllConnected << *handles[0] << *handles[1] << *handles[2] << *handles[3] << *handles[0] << *handles[2] << *handles[1] << *handles[3];
86 return polyAllConnected;
87}

◆ getTetragon()

bool PerspectiveBasedAssistantHelper::getTetragon ( const QList< KisPaintingAssistantHandleSP > & handles,
bool isAssistantComplete,
QPolygonF & outPolygon )
static

Definition at line 27 of file PerspectiveBasedAssistantHelper.cpp.

28{
29 outPolygon.clear();
30 for (int i = 0; i < handles.size(); ++i) {
31 outPolygon.push_back(*handles[i]);
32 }
33
34 if (!isAssistantComplete) {
35 return false;
36 }
37
38 int sum = 0;
39 int signs[4];
40
41 for (int i = 0; i < 4; ++i) {
42 int j = (i == 3) ? 0 : (i + 1);
43 int k = (j == 3) ? 0 : (j + 1);
44 signs[i] = KisAlgebra2D::signZZ(pdot(outPolygon[j] - outPolygon[i], outPolygon[k] - outPolygon[j]));
45 sum += signs[i];
46 }
47
48 if (sum == 0) {
49 // complex (crossed)
50 for (int i = 0; i < 4; ++i) {
51 int j = (i == 3) ? 0 : (i + 1);
52 if (signs[i] * signs[j] == -1) {
53 // opposite signs: uncross
54 std::swap(outPolygon[i], outPolygon[j]);
55 return true;
56 }
57 }
58 // okay, maybe it's just a line
59 return false;
60 } else if (sum != 4 && sum != -4) {
61 // concave, or a triangle
62 if (sum == 2 || sum == -2) {
63 // concave, let's return a triangle instead
64 for (int i = 0; i < 4; ++i) {
65 int j = (i == 3) ? 0 : (i + 1);
66 if (signs[i] != KisAlgebra2D::signZZ(sum)) {
67 // wrong sign: drop the inside node
68 outPolygon.remove(j);
69 return false;
70 }
71 }
72 }
73 return false;
74 }
75 // convex
76 return true;
77}
static qreal pdot(const QPointF &a, const QPointF &b)

References pdot(), and KisAlgebra2D::signZZ().

◆ getVanishingPointsOptional()

bool PerspectiveBasedAssistantHelper::getVanishingPointsOptional ( const QPolygonF & poly,
boost::optional< QPointF > & vp1,
boost::optional< QPointF > & vp2 )
static

Definition at line 252 of file PerspectiveBasedAssistantHelper.cpp.

253{
254 bool either = false;
255 vp1 = boost::none;
256 vp2 = boost::none;
257
258 if (poly.size() < 4) { // four points are required for a tetragon
259 return false;
260 }
261
262 QPointF intersection(0, 0);
263 // note: in code it seems like vp1 and vp2 are swapped, but it's all correct if you read carefully
264
265 if (fmod(QLineF(poly[0], poly[1]).angle(), 180.0)>=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)+2.0
266 || fmod(QLineF(poly[0], poly[1]).angle(), 180.0)<=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)-2.0) {
267 if (QLineF(poly[0], poly[1]).intersects(QLineF(poly[2], poly[3]), &intersection) != QLineF::NoIntersection) {
268 vp2 = intersection;
269 either = true;
270 }
271 }
272 if (fmod(QLineF(poly[1], poly[2]).angle(), 180.0)>=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)+2.0
273 || fmod(QLineF(poly[1], poly[2]).angle(), 180.0)<=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)-2.0){
274 if (QLineF(poly[1], poly[2]).intersects(QLineF(poly[3], poly[0]), &intersection) != QLineF::NoIntersection) {
275 vp1 = intersection;
276 either = true;
277 }
278 }
279 return either;
280}

◆ inverseMaxLocalScale()

qreal PerspectiveBasedAssistantHelper::inverseMaxLocalScale ( const QTransform & transform)
static

Definition at line 109 of file PerspectiveBasedAssistantHelper.cpp.

110{
111 const qreal a = fabs((transform.m33() + transform.m13()) * (transform.m33() + transform.m23())),
112 b = fabs((transform.m33()) * (transform.m13() + transform.m33() + transform.m23())),
113 d00 = transform.m33() * transform.m33(),
114 d11 = (transform.m33() + transform.m23() + transform.m13())*(transform.m33() + transform.m23() + transform.m13()),
115 s0011 = qMin(d00, d11) / a,
116 d10 = (transform.m33() + transform.m13()) * (transform.m33() + transform.m13()),
117 d01 = (transform.m33() + transform.m23()) * (transform.m33() + transform.m23()),
118 s1001 = qMin(d10, d01) / b;
119 return qMin(s0011, s1001);
120}

◆ localScale()

qreal PerspectiveBasedAssistantHelper::localScale ( const QTransform & transform,
QPointF pt )
static

Definition at line 89 of file PerspectiveBasedAssistantHelper.cpp.

90{
91 // const qreal epsilon = 1e-5, epsilonSquared = epsilon * epsilon;
92 // qreal xSizeSquared = lengthSquared(transform.map(pt + QPointF(epsilon, 0.0)) - orig) / epsilonSquared;
93 // qreal ySizeSquared = lengthSquared(transform.map(pt + QPointF(0.0, epsilon)) - orig) / epsilonSquared;
94 // xSizeSquared /= lengthSquared(transform.map(QPointF(0.0, pt.y())) - transform.map(QPointF(1.0, pt.y())));
95 // ySizeSquared /= lengthSquared(transform.map(QPointF(pt.x(), 0.0)) - transform.map(QPointF(pt.x(), 1.0)));
96 // when taking the limit epsilon->0:
97 // xSizeSquared=((m23*y+m33)^2*(m23*y+m33+m13)^2)/(m23*y+m13*x+m33)^4
98 // ySizeSquared=((m23*y+m33)^2*(m23*y+m33+m13)^2)/(m23*y+m13*x+m33)^4
99 // xSize*ySize=(abs(m13*x+m33)*abs(m13*x+m33+m23)*abs(m23*y+m33)*abs(m23*y+m33+m13))/(m23*y+m13*x+m33)^4
100 const qreal x = transform.m13() * pt.x(),
101 y = transform.m23() * pt.y(),
102 a = x + transform.m33(),
103 b = y + transform.m33(),
104 c = x + y + transform.m33(),
105 d = c * c;
106 return fabs(a*(a + transform.m23())*b*(b + transform.m13()))/(d * d);
107}

◆ pdot()

qreal PerspectiveBasedAssistantHelper::pdot ( const QPointF & a,
const QPointF & b )
static

Definition at line 282 of file PerspectiveBasedAssistantHelper.cpp.

283{
284 return a.x() * b.y() - a.y() * b.x();
285}

◆ updateCacheData()

void PerspectiveBasedAssistantHelper::updateCacheData ( PerspectiveBasedAssistantHelper::CacheData & cache,
const QPolygonF & poly )
static

Definition at line 211 of file PerspectiveBasedAssistantHelper.cpp.

212{
213 cache.polygon = poly;
215 Q_UNUSED(r);
216
217 if (cache.vanishingPoint1 && cache.vanishingPoint2) {
218 cache.type = CacheData::TwoVps;
219 } else if (cache.vanishingPoint1 || cache.vanishingPoint2) {
220 cache.type = CacheData::OneVp;
221 } else {
222 cache.type = CacheData::None;
223 cache.horizon = QLineF();
225 cache.maxDistanceFromPoint = 0.0;
226 return;
227 }
228
229 if (cache.type == CacheData::TwoVps) {
230 cache.horizon = QLineF(cache.vanishingPoint1.get(), cache.vanishingPoint2.get());
231 } else if (cache.type == CacheData::OneVp) {
232 if (cache.vanishingPoint1) {
233 // that means the 0-1 line is the horizon parallel line
234 cache.horizon = QLineF(cache.vanishingPoint1.get(), cache.vanishingPoint1.get() + cache.polygon[1] - cache.polygon[0]);
235 } else { // the other vp
236 cache.horizon = QLineF(cache.vanishingPoint2.get(), cache.vanishingPoint2.get() + cache.polygon[2] - cache.polygon[1]);
237 }
238 }
239
240 int vertexCount = 4;
241 cache.distancesFromPoints.fill(0.0, vertexCount);
242 for (int i = 0; i < vertexCount; i++) {
243 qreal vertexDist = kisDistanceToLine(cache.polygon[i], cache.horizon);
244 if (vertexDist > cache.maxDistanceFromPoint) {
245 cache.maxDistanceFromPoint = vertexDist;
246 }
247 cache.distancesFromPoints[i] = vertexDist;
248 }
249
250}

References PerspectiveBasedAssistantHelper::CacheData::distancesFromPoints, getVanishingPointsOptional(), PerspectiveBasedAssistantHelper::CacheData::horizon, kisDistanceToLine(), PerspectiveBasedAssistantHelper::CacheData::maxDistanceFromPoint, PerspectiveBasedAssistantHelper::CacheData::None, PerspectiveBasedAssistantHelper::CacheData::OneVp, PerspectiveBasedAssistantHelper::CacheData::polygon, PerspectiveBasedAssistantHelper::CacheData::TwoVps, PerspectiveBasedAssistantHelper::CacheData::type, PerspectiveBasedAssistantHelper::CacheData::vanishingPoint1, and PerspectiveBasedAssistantHelper::CacheData::vanishingPoint2.


The documentation for this class was generated from the following files: