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

#include <TwoPointAssistant.h>

+ Inheritance diagram for TwoPointAssistant:

Public Types

enum  TwoPointHandle {
  FirstHandle , SecondHandle , VerticalHandle , LocalFirstHandle ,
  LocalSecondHandle
}
 

Public Member Functions

void adjustLine (QPointF &point, QPointF &strokeBegin) override
 
QPointF adjustPosition (const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
 
bool canBeLocal () const override
 canBeLocal
 
KisPaintingAssistantSP clone (QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
 
void endStroke () override
 
QPointF getDefaultEditorPosition () const override
 
double gridDensity ()
 
bool isAssistantComplete () const override
 
bool loadCustomXml (QXmlStreamReader *xml) override
 
QTransform localTransform (QPointF vp_a, QPointF vp_b, QPointF pt_c, qreal *size)
 
int numHandles () const override
 
void saveCustomXml (QXmlStreamWriter *xml) override
 
void setGridDensity (double density)
 
void setUseVertical (bool value)
 
 TwoPointAssistant ()
 
bool useVertical ()
 
- Public Member Functions inherited from KisPaintingAssistant
void addHandle (KisPaintingAssistantHandleSP handle, HandleType type)
 
bool areTwoPointsClose (const QPointF &pointOne, const QPointF &pointTwo)
 
QColor assistantCustomColor ()
 
KisPaintingAssistantHandleSP bottomLeft ()
 
const KisPaintingAssistantHandleSP bottomLeft () const
 
KisPaintingAssistantHandleSP bottomMiddle ()
 
const KisPaintingAssistantHandleSP bottomMiddle () const
 
KisPaintingAssistantHandleSP bottomRight ()
 
const KisPaintingAssistantHandleSP bottomRight () const
 
KisPaintingAssistantHandleSP closestCornerHandleFromPoint (QPointF point)
 
void copySharedData (KisPaintingAssistantSP assistant)
 
void drawError (QPainter &painter, const QPainterPath &path)
 
void drawPath (QPainter &painter, const QPainterPath &path, bool drawActive=true)
 
void drawPreview (QPainter &painter, const QPainterPath &path)
 
void drawX (QPainter &painter, const QPointF &pt)
 
QPointF editorWidgetOffset ()
 
QColor effectiveAssistantColor () const
 
void findPerspectiveAssistantHandleLocation ()
 
virtual QPointF getEditorPosition () const
 
QList< KisPaintingAssistantHandleSPhandles ()
 
const QList< KisPaintingAssistantHandleSP > & handles () const
 
const QString & id () const
 
bool isDuplicating ()
 isDuplicating
 
bool isLocal () const
 isLocal
 
bool isLocked ()
 isLocked
 
bool isSnappingActive () const
 
 KisPaintingAssistant (const QString &id, const QString &name)
 
KisPaintingAssistantHandleSP leftMiddle ()
 
const KisPaintingAssistantHandleSP leftMiddle () const
 
void loadXml (KoStore *store, QMap< int, KisPaintingAssistantHandleSP > &handleMap, QString path)
 
const QString & name () const
 
KisPaintingAssistantHandleSP oppHandleOne ()
 
void replaceHandle (KisPaintingAssistantHandleSP _handle, KisPaintingAssistantHandleSP _with)
 
KisPaintingAssistantHandleSP rightMiddle ()
 
const KisPaintingAssistantHandleSP rightMiddle () const
 
QByteArray saveXml (QMap< KisPaintingAssistantHandleSP, int > &handleMap)
 
void saveXmlList (QDomDocument &doc, QDomElement &assistantsElement, int count)
 
virtual void setAdjustedBrushPosition (const QPointF position)
 
void setAssistantCustomColor (QColor color)
 
void setAssistantGlobalColorCache (const QColor &color)
 
void setDecorationThickness (int thickness)
 
void setDuplicating (bool value)
 setDuplicating
 
void setEditorWidgetOffset (QPointF offset)
 
virtual void setFollowBrushPosition (bool follow)
 
void setLocal (bool value)
 setLocal
 
void setLocked (bool value)
 setLocked
 
void setSnappingActive (bool set)
 
void setUseCustomColor (bool useCustomColor)
 
QList< KisPaintingAssistantHandleSPsideHandles ()
 
const QList< KisPaintingAssistantHandleSP > & sideHandles () const
 
KisPaintingAssistantHandleSP topLeft ()
 
const KisPaintingAssistantHandleSP topLeft () const
 
KisPaintingAssistantHandleSP topMiddle ()
 
const KisPaintingAssistantHandleSP topMiddle () const
 
KisPaintingAssistantHandleSP topRight ()
 
const KisPaintingAssistantHandleSP topRight () const
 
virtual void transform (const QTransform &transform)
 
void uncache ()
 
bool useCustomColor ()
 
QPointF viewportConstrainedEditorPosition (const KisCoordinatesConverter *converter, const QSize editorSize)
 
virtual ~KisPaintingAssistant ()
 

Protected Member Functions

void drawAssistant (QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached=true, KisCanvas2 *canvas=nullptr, bool assistantVisible=true, bool previewVisible=true) override
 
void drawCache (QPainter &gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override
 performance layer where the graphics can be drawn from a cache instead of generated every render update
 
KisPaintingAssistantHandleSP firstLocalHandle () const override
 firstLocalHandle Note: this doesn't guarantee it will be the topleft corner! For that, use getLocalRect().topLeft() The only purpose of those functions to exist is to be able to put getLocalRect() function in the KisPaintingAssistant instead of reimplementing it in every specific assistant.
 
KisPaintingAssistantHandleSP secondLocalHandle () const override
 secondLocalHandle Note: this doesn't guarantee it will be the bottomRight corner! For that, use getLocalRect().bottomRight() (and remember that for QRect bottomRight() works differently than for QRectF, so don't convert to QRect before accessing the corner)
 
- Protected Member Functions inherited from KisPaintingAssistant
virtual QRect boundingRect () const
 
QPointF effectiveBrushPosition (const KisCoordinatesConverter *converter, KisCanvas2 *canvas) const
 Query the effective brush position to be used for preview lines. This is intended to be used for painting the dynamic preview lines for assistants that feature them. Affected by setAdjustedBrushPosition() and setFollowBrushPosition().
 
QRectF getLocalRect () const
 getLocalRect The function deals with local handles not being topLeft and bottomRight gracefully and returns a correct rectangle. Thanks to that the user can place handles in a "wrong" order or move them around but the local rectangle will still be correct.
 
void initHandles (QList< KisPaintingAssistantHandleSP > _handles)
 
 KisPaintingAssistant (const KisPaintingAssistant &rhs, QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap)
 
QPointF pixelToView (const QPoint pixelCoords) const
 

Private Member Functions

QPointF project (const QPointF &pt, const QPointF &strokeBegin, const bool snapToAny, qreal moveThreshold)
 
 TwoPointAssistant (const TwoPointAssistant &rhs, QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap)
 

Private Attributes

KisCanvas2m_canvas {nullptr}
 
double m_gridDensity {1.0}
 
int m_lastUsedPoint {-1}
 
QLineF m_snapLine
 
bool m_useVertical {true}
 

Additional Inherited Members

- Static Public Member Functions inherited from KisPaintingAssistant
static QList< KisPaintingAssistantSPcloneAssistantList (const QList< KisPaintingAssistantSP > &list)
 
static double norm2 (const QPointF &p)
 
- Protected Attributes inherited from KisPaintingAssistant
QList< KisPaintingAssistantHandleSPm_handles
 
bool m_hasBeenInsideLocalRect {false}
 

Detailed Description

Definition at line 17 of file TwoPointAssistant.h.

Member Enumeration Documentation

◆ TwoPointHandle

Enumerator
FirstHandle 
SecondHandle 
VerticalHandle 
LocalFirstHandle 
LocalSecondHandle 

Definition at line 21 of file TwoPointAssistant.h.

Constructor & Destructor Documentation

◆ TwoPointAssistant() [1/2]

TwoPointAssistant::TwoPointAssistant ( )

Definition at line 26 of file TwoPointAssistant.cc.

27 : KisPaintingAssistant("two point", i18n("Two point assistant"))
28{
29}
KisPaintingAssistant(const QString &id, const QString &name)

◆ TwoPointAssistant() [2/2]

TwoPointAssistant::TwoPointAssistant ( const TwoPointAssistant & rhs,
QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > & handleMap )
explicitprivate

Member Function Documentation

◆ adjustLine()

void TwoPointAssistant::adjustLine ( QPointF & point,
QPointF & strokeBegin )
overridevirtual

Implements KisPaintingAssistant.

Definition at line 145 of file TwoPointAssistant.cc.

146{
147 QPointF p = project(point, strokeBegin, true, 0.0);
148 point = p;
149}
const Params2D p
QPointF project(const QPointF &pt, const QPointF &strokeBegin, const bool snapToAny, qreal moveThreshold)

References p, and project().

◆ adjustPosition()

QPointF TwoPointAssistant::adjustPosition ( const QPointF & point,
const QPointF & strokeBegin,
const bool snapToAny,
qreal moveThresholdPt )
overridevirtual

Adjust the position given in parameter.

Parameters
pointthe coordinates in point in the document reference
strokeBeginthe coordinates of the beginning of the stroke
snapToAnybecause now assistants can be composited out of multiple inside assistants. snapToAny true means that you can use any of the inside assistant, while it being false means you should use the last used one. The logic determining when it happens (first stroke etc.) is in the decoration, so those two options are enough.
moveThresholdPtthe threshold for the "move" of the cursor measured in pt (usually equals to 2px in screen coordinates converted to pt)

Implements KisPaintingAssistant.

Definition at line 140 of file TwoPointAssistant.cc.

141{
142 return project(pt, strokeBegin, snapToAny, moveThresholdPt);
143}

References project().

◆ canBeLocal()

bool TwoPointAssistant::canBeLocal ( ) const
overridevirtual

canBeLocal

Returns
if the assistant can be potentially a "local assistant" (limited to rectangular area) or not

Reimplemented from KisPaintingAssistant.

Definition at line 480 of file TwoPointAssistant.cc.

481{
482 return true;
483}

◆ clone()

KisPaintingAssistantSP TwoPointAssistant::clone ( QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > & handleMap) const
overridevirtual

Implements KisPaintingAssistant.

Definition at line 41 of file TwoPointAssistant.cc.

42{
43 return KisPaintingAssistantSP(new TwoPointAssistant(*this, handleMap));
44}
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
Definition kis_types.h:189

References TwoPointAssistant().

◆ drawAssistant()

void TwoPointAssistant::drawAssistant ( QPainter & gc,
const QRectF & updateRect,
const KisCoordinatesConverter * converter,
bool cached = true,
KisCanvas2 * canvas = nullptr,
bool assistantVisible = true,
bool previewVisible = true )
overrideprotectedvirtual

Reimplemented from KisPaintingAssistant.

Definition at line 151 of file TwoPointAssistant.cc.

152{
153 Q_UNUSED(updateRect);
154 Q_UNUSED(cached);
155 gc.save();
156 gc.resetTransform();
157
158 const QTransform initialTransform = converter->documentToWidgetTransform();
159 bool isEditing = false;
160 bool showLocal = isLocal() && handles().size() == 5;
161
162 if (canvas) {
163 isEditing = canvas->paintingAssistantsDecoration()->isEditingAssistants();
164 }
165
166 if (isEditing) {
167 Q_FOREACH (const QPointF* handle, handles()) {
168 QPointF h = initialTransform.map(*handle);
169 QRectF ellipse = QRectF(QPointF(h.x() -15, h.y() -15), QSizeF(30, 30));
170
171 QPainterPath pathCenter;
172 pathCenter.addEllipse(ellipse);
173 drawPath(gc, pathCenter, isSnappingActive());
174
175 // Draw circle to represent center of vision
176 if (handles().length() == 3 && handle == handles()[2]) {
177 const QLineF horizon = QLineF(*handles()[0],*handles()[1]);
178 QLineF normal = horizon.normalVector();
179 normal.translate(*handles()[2]-normal.p1());
180 QPointF cov = horizon.center();
181 normal.intersects(horizon,&cov);
182 const QPointF center = initialTransform.map(cov);
183 QRectF center_ellipse = QRectF(QPointF(center.x() -15, center.y() -15), QSizeF(30, 30));
184 QPainterPath pathCenter;
185 pathCenter.addEllipse(center_ellipse);
186 drawPath(gc, pathCenter, isSnappingActive());
187 }
188 }
189
190 if (handles().size() <= 2) {
191 QPainterPath path;
192 int tempDensity = m_gridDensity * 10; // the vanishing point density seems visibly more dense, hence let's make it less dense
193 QRect viewport = gc.viewport();
194
195 for (int i = 0; i < handles().size(); i++) {
196 const QPointF p = initialTransform.map(*handles()[i]);
197 for (int currentAngle=0; currentAngle <= 180; currentAngle = currentAngle + tempDensity) {
198
199 // determine the correct angle based on the iteration
200 float xPos = cos(currentAngle * M_PI / 180);
201 float yPos = sin(currentAngle * M_PI / 180);
202 float length = 100;
203 QPointF unit = QPointF(length*xPos, length*yPos);
204
205 // find point
206 QLineF snapLine = QLineF(p, p + unit);
207 if (KisAlgebra2D::intersectLineRect(snapLine, viewport, false)) {
208 // make a line from VP center to edge of canvas with that angle
209
210 path.moveTo(snapLine.p1());
211 path.lineTo(snapLine.p2());
212 }
213
214 QLineF snapLine2 = QLineF(p, p - unit);
215 if (KisAlgebra2D::intersectLineRect(snapLine2, viewport, false)) {
216 // make a line from VP center to edge of canvas with that angle
217
218 path.moveTo(snapLine2.p1());
219 path.lineTo(snapLine2.p2());
220 }
221
222
223 }
224
225 drawPreview(gc, path);//and we draw the preview.
226
227 }
228 }
229
230 }
231
232 if (handles().size() >= 2) {
233 QPointF mousePos = effectiveBrushPosition(converter, canvas);
234 const QPointF p1 = *handles()[0];
235 const QPointF p2 = *handles()[1];
236 const QRect viewport= gc.viewport();
237
238 const QPolygonF localPoly = (isLocal() && handles().size() == 5) ? initialTransform.map(QPolygonF(getLocalRect())) : QPolygonF();
239 const QPolygonF viewportAndLocalPoly = !localPoly.isEmpty() ? QPolygonF(QRectF(viewport)).intersected(localPoly) : QRectF(viewport);
240
241
242 QPainterPath path;
243 QPainterPath previewPath; // part of the preview, instead of the assistant itself
244
245 // draw the horizon
246 if (assistantVisible == true || isEditing == true) {
247 QLineF horizonLine = initialTransform.map(QLineF(p1,p2));
248 KisAlgebra2D::cropLineToConvexPolygon(horizonLine, viewportAndLocalPoly, true, true);
249 path.moveTo(horizonLine.p1());
250 path.lineTo(horizonLine.p2());
251 }
252
253 // draw the VP-->mousePos lines
254 if (isEditing == false && previewVisible == true && isSnappingActive() == true) {
255 // draw the line vp <-> mouse even outside of the local rectangle
256 // but only if the mouse pos is inside the rectangle
257 QLineF snapMouse1 = QLineF(initialTransform.map(p1), mousePos);
258 QLineF snapMouse2 = QLineF(initialTransform.map(p2), mousePos);
259 KisAlgebra2D::cropLineToConvexPolygon(snapMouse1, viewportAndLocalPoly, false, true);
260 KisAlgebra2D::cropLineToConvexPolygon(snapMouse2, viewportAndLocalPoly, false, true);
261 previewPath.moveTo(snapMouse1.p1());
262 previewPath.lineTo(snapMouse1.p2());
263 previewPath.moveTo(snapMouse2.p1());
264 previewPath.lineTo(snapMouse2.p2());
265 }
266
267 // draw the side handle bars
268 if (isEditing == true && !sideHandles().isEmpty()) {
269 path.moveTo(initialTransform.map(p1));
270 path.lineTo(initialTransform.map(*sideHandles()[0]));
271 path.lineTo(initialTransform.map(*sideHandles()[1]));
272 path.moveTo(initialTransform.map(p2));
273 path.lineTo(initialTransform.map(*sideHandles()[2]));
274 path.lineTo(initialTransform.map(*sideHandles()[3]));
275 path.moveTo(initialTransform.map(p1));
276 path.lineTo(initialTransform.map(*sideHandles()[4]));
277 path.lineTo(initialTransform.map(*sideHandles()[5]));
278 path.moveTo(initialTransform.map(p2));
279 path.lineTo(initialTransform.map(*sideHandles()[6]));
280 path.lineTo(initialTransform.map(*sideHandles()[7]));
281 }
282
283 // draw the local rectangle
284 if (showLocal && assistantVisible) {
285 QPointF p1 = *handles()[(int)LocalFirstHandle];
286 QPointF p3 = *handles()[(int)LocalSecondHandle];
287 QPointF p2 = QPointF(p1.x(), p3.y());
288 QPointF p4 = QPointF(p3.x(), p1.y());
289
290 path.moveTo(initialTransform.map(p1));
291
292 path.lineTo(initialTransform.map(p2));
293 path.lineTo(initialTransform.map(p3));
294 path.lineTo(initialTransform.map(p4));
295 path.lineTo(initialTransform.map(p1));
296 }
297
298
299 drawPreview(gc,previewPath);
300 drawPath(gc, path, isSnappingActive());
301
302 if (handles().size() >= 3 && isSnappingActive()) {
303 path = QPainterPath(); // clear
304 const QPointF p3 = *handles()[2];
305
306 qreal size = 0;
307 const QTransform t = localTransform(p1,p2,p3,&size);
308 const QTransform inv = t.inverted();
309 const QPointF vp_a = t.map(p1);
310 const QPointF vp_b = t.map(p2);
311
312 if ((vp_a.x() < 0 && vp_b.x() > 0) ||
313 (vp_a.x() > 0 && vp_b.x() < 0)) {
314 if (m_useVertical) {
315 // Draw vertical line, but only if the center is between both VPs
316 QLineF vertical = initialTransform.map(inv.map(QLineF::fromPolar(1,90)));
317 if (!isEditing) vertical.translate(mousePos - vertical.p1());
318 KisAlgebra2D::cropLineToConvexPolygon(vertical, viewportAndLocalPoly, true, true);
319 if (previewVisible) {
320 path.moveTo(vertical.p1());
321 path.lineTo(vertical.p2());
322 }
323
324 if (assistantVisible) {
325 // Display a notch to represent the center of vision
326 path.moveTo(initialTransform.map(inv.map(QPointF(0,vp_a.y()-10))));
327 path.lineTo(initialTransform.map(inv.map(QPointF(0,vp_a.y()+10))));
328 }
329 drawPreview(gc,path);
330 path = QPainterPath(); // clear
331 }
332 }
333
334 const QPointF upper = QPointF(0,vp_a.y() + size);
335 const QPointF lower = QPointF(0,vp_a.y() - size);
336
337 // Set up the fading effect for the grid lines
338 // Needed so the grid density doesn't look distracting
339 QColor color = effectiveAssistantColor();
340 QGradient fade = QLinearGradient(initialTransform.map(inv.map(upper)),
341 initialTransform.map(inv.map(lower)));
342 color.setAlphaF(0);
343 fade.setColorAt(0.4, effectiveAssistantColor());
344 fade.setColorAt(0.5, color);
345 fade.setColorAt(0.6, effectiveAssistantColor());
346 const QPen pen = gc.pen();
347 const QBrush new_brush = QBrush(fade);
348 int width = 1;
349 const QPen new_pen = QPen(new_brush, width, pen.style());
350 gc.setPen(new_pen);
351
352 const QList<QPointF> station_points = {upper, lower};
353 const QList<QPointF> vanishing_points = {vp_a, vp_b};
354
355 // Draw grid lines above and below the horizon
356 Q_FOREACH (const QPointF sp, station_points) {
357
358 // Draw grid lines towards each vanishing point
359 Q_FOREACH (const QPointF vp, vanishing_points) {
360
361 // Interval between each grid line, uses grid density specified by user
362 const qreal initial_angle = QLineF(sp, vp).angle();
363 const qreal interval = size*m_gridDensity / cos((initial_angle - 90) * M_PI/180);
364 const QPointF translation = QPointF(interval, 0);
365
366 // Draw grid lines originating from both the left and right of the central vertical line
367 Q_FOREACH (const int dir, QList<int>({-1, 1})) {
368
369 // Limit at 300 grid lines per direction, reasonable even for m_gridDensity=0.1;
370 for (int i = 0; i <= 300; i++) {
371 const QLineF gridline = QLineF(sp + translation * i * dir, vp);
372
373 // Don't bother drawing lines that are nearly parallel to horizon
374 const qreal angle = gridline.angle();
375 if (angle < 0.25 || angle > 359.75 || (angle < 180.25 && angle > 179.75)) {
376 break;
377 }
378
379 QLineF drawn_gridline = initialTransform.map(inv.map(gridline));
380 KisAlgebra2D::cropLineToConvexPolygon(drawn_gridline, viewportAndLocalPoly, true, false);
381
382 if (assistantVisible || isEditing == true) {
383 path.moveTo(drawn_gridline.p2());
384 path.lineTo(drawn_gridline.p1());
385 }
386 }
387 }
388 }
389 }
390 gc.drawPath(path);
391 }
392 }
393
394 gc.restore();
395 //KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
396}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
QPointF p2
QPointF p3
QPointF p1
KisPaintingAssistantsDecorationSP paintingAssistantsDecoration() const
QPointF effectiveBrushPosition(const KisCoordinatesConverter *converter, KisCanvas2 *canvas) const
Query the effective brush position to be used for preview lines. This is intended to be used for pain...
void drawPath(QPainter &painter, const QPainterPath &path, bool drawActive=true)
void drawPreview(QPainter &painter, const QPainterPath &path)
QRectF getLocalRect() const
getLocalRect The function deals with local handles not being topLeft and bottomRight gracefully and r...
const QList< KisPaintingAssistantHandleSP > & sideHandles() const
const QList< KisPaintingAssistantHandleSP > & handles() const
QTransform localTransform(QPointF vp_a, QPointF vp_b, QPointF pt_c, qreal *size)
#define M_PI
Definition kis_global.h:111
void cropLineToConvexPolygon(QLineF &line, const QPolygonF polygon, bool extendFirst, bool extendSecond)
bool intersectLineRect(QLineF &line, const QRect rect, bool extend)
int size(const Forest< T > &forest)
Definition KisForest.h:1232

References KisAlgebra2D::cropLineToConvexPolygon(), KisCoordinatesConverter::documentToWidgetTransform(), KisPaintingAssistant::drawPath(), KisPaintingAssistant::drawPreview(), KisPaintingAssistant::effectiveAssistantColor(), KisPaintingAssistant::effectiveBrushPosition(), KisPaintingAssistant::getLocalRect(), KisPaintingAssistant::handles(), KisAlgebra2D::intersectLineRect(), KisPaintingAssistantsDecoration::isEditingAssistants(), KisPaintingAssistant::isLocal(), KisPaintingAssistant::isSnappingActive(), length(), LocalFirstHandle, LocalSecondHandle, localTransform(), m_gridDensity, M_PI, m_useVertical, p, p1, p2, p3, KisCanvas2::paintingAssistantsDecoration(), and KisPaintingAssistant::sideHandles().

◆ drawCache()

void TwoPointAssistant::drawCache ( QPainter & gc,
const KisCoordinatesConverter * converter,
bool assistantVisible = true )
overrideprotectedvirtual

performance layer where the graphics can be drawn from a cache instead of generated every render update

Implements KisPaintingAssistant.

Definition at line 398 of file TwoPointAssistant.cc.

399{
400 Q_UNUSED(gc);
401 Q_UNUSED(converter);
402 Q_UNUSED(assistantVisible);
403 if (!m_canvas || !isAssistantComplete()) {
404 return;
405 }
406
407 if (assistantVisible == false || m_canvas->paintingAssistantsDecoration()->isEditingAssistants()) {
408 return;
409 }
410}
bool isAssistantComplete() const override

References isAssistantComplete(), KisPaintingAssistantsDecoration::isEditingAssistants(), m_canvas, and KisCanvas2::paintingAssistantsDecoration().

◆ endStroke()

void TwoPointAssistant::endStroke ( )
overridevirtual

Reimplemented from KisPaintingAssistant.

Definition at line 133 of file TwoPointAssistant.cc.

134{
135 m_snapLine = QLineF();
136 m_lastUsedPoint = -1;
138}

References KisPaintingAssistant::endStroke(), m_lastUsedPoint, and m_snapLine.

◆ firstLocalHandle()

KisPaintingAssistantHandleSP TwoPointAssistant::firstLocalHandle ( ) const
overrideprotectedvirtual

firstLocalHandle Note: this doesn't guarantee it will be the topleft corner! For that, use getLocalRect().topLeft() The only purpose of those functions to exist is to be able to put getLocalRect() function in the KisPaintingAssistant instead of reimplementing it in every specific assistant.

Returns
the first handle of the rectangle of the limited area

Reimplemented from KisPaintingAssistant.

Definition at line 412 of file TwoPointAssistant.cc.

413{
414 if (handles().size() > LocalFirstHandle) {
415 return handles().at(LocalFirstHandle);
416 } else {
417 return nullptr;
418 }
419}

References KisPaintingAssistant::handles(), and LocalFirstHandle.

◆ getDefaultEditorPosition()

QPointF TwoPointAssistant::getDefaultEditorPosition ( ) const
overridevirtual

Implements KisPaintingAssistant.

Definition at line 430 of file TwoPointAssistant.cc.

431{
432 int centerOfVisionHandle = 2;
433 if (handles().size() > centerOfVisionHandle) {
434 return *handles().at(centerOfVisionHandle);
435 } else if (handles().size() > 0) {
437 return *handles().at(0);
438 } else {
439 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(false, QPointF(0, 0));
440 return QPointF(0, 0);
441 }
442}
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129

References KisPaintingAssistant::handles(), and KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE.

◆ gridDensity()

double TwoPointAssistant::gridDensity ( )

Definition at line 459 of file TwoPointAssistant.cc.

460{
461 return m_gridDensity;
462}

References m_gridDensity.

◆ isAssistantComplete()

bool TwoPointAssistant::isAssistantComplete ( ) const
overridevirtual

determines if the assistant has enough handles to be considered created new assistants get in a "creation" phase where they are currently being made on the canvas it will return false if we are in the middle of creating the assistant.

Reimplemented from KisPaintingAssistant.

Definition at line 475 of file TwoPointAssistant.cc.

476{
477 return handles().size() >= numHandles();
478}
int numHandles() const override

References KisPaintingAssistant::handles(), and numHandles().

◆ loadCustomXml()

bool TwoPointAssistant::loadCustomXml ( QXmlStreamReader * xml)
overridevirtual

Reimplemented from KisPaintingAssistant.

Definition at line 499 of file TwoPointAssistant.cc.

500{
501 if (xml && xml->name() == "gridDensity") {
502 this->setGridDensity((float)KisDomUtils::toDouble(xml->attributes().value("value").toString()));
503 }
504 if (xml && xml->name() == "useVertical") {
505 this->setUseVertical((bool)KisDomUtils::toInt(xml->attributes().value("value").toString()));
506 }
507 if (xml && xml->name() == "isLocal") {
508 this->setLocal((bool)KisDomUtils::toInt(xml->attributes().value("value").toString()));
509 }
510 return true;
511}
void setLocal(bool value)
setLocal
void setGridDensity(double density)
void setUseVertical(bool value)
double toDouble(const QString &str, bool *ok=nullptr)
int toInt(const QString &str, bool *ok=nullptr)

References setGridDensity(), KisPaintingAssistant::setLocal(), setUseVertical(), KisDomUtils::toDouble(), and KisDomUtils::toInt().

◆ localTransform()

QTransform TwoPointAssistant::localTransform ( QPointF vp_a,
QPointF vp_b,
QPointF pt_c,
qreal * size )

Definition at line 464 of file TwoPointAssistant.cc.

465{
466 QTransform t = QTransform();
467 t.rotate(QLineF(vp_a, vp_b).angle());
468 t.translate(-pt_c.x(),-pt_c.y());
469 const QLineF horizon = QLineF(t.map(vp_a), QPointF(t.map(vp_b).x(),t.map(vp_a).y()));
470 *size = sqrt(pow(horizon.length()/2.0,2) - pow(abs(horizon.center().x()),2));
471
472 return t;
473}
Point abs(const Point &pt)

◆ numHandles()

int TwoPointAssistant::numHandles ( ) const
inlineoverridevirtual

Implements KisPaintingAssistant.

Definition at line 37 of file TwoPointAssistant.h.

37{ return isLocal() ? 5 : 3; }

References KisPaintingAssistant::isLocal().

◆ project()

QPointF TwoPointAssistant::project ( const QPointF & pt,
const QPointF & strokeBegin,
const bool snapToAny,
qreal moveThreshold )
private

Definition at line 46 of file TwoPointAssistant.cc.

47{
48 Q_ASSERT(isAssistantComplete());
49
50 QPointF best_pt = point;
51 double best_dist = DBL_MAX;
52 QList<int> possibleHandles;
53
54 // must be above or equal to 0;
55 // if useVertical, then last used point must be below 3, because 2 means vertical
56 // and it's the last possible point here (sanity check)
57 // if !useVertical, then it must be below 2, because 2 means vertical
58 bool isLastUsedPointCorrectNow = m_lastUsedPoint >= 0 && (m_useVertical ? m_lastUsedPoint < 3 : m_lastUsedPoint < 2);
59
60 if (isLocal() && handles().size() == 5) {
61 // here we can just return since we don't want to do anything
62 // so we're returning a NaN
63 // but only if we don't have a point/axes it was already using
64
65 QRectF rect = getLocalRect();
66 bool insideLocalRect = rect.contains(point);
67 if (!insideLocalRect && (!isLastUsedPointCorrectNow || !m_hasBeenInsideLocalRect)) {
68 return QPointF(qQNaN(), qQNaN());
69 } else if (insideLocalRect) {
71 }
72 }
73
74 if (!isLastUsedPointCorrectNow && KisAlgebra2D::norm(point - strokeBegin) < moveThreshold) {
75 return strokeBegin;
76 }
77
78 if (!snapToAny && isLastUsedPointCorrectNow) {
79 possibleHandles = QList<int>({m_lastUsedPoint});
80 } else {
81 if (m_useVertical) {
82 possibleHandles = QList<int>({0, 1, 2});
83 } else {
84 possibleHandles = QList<int>({0, 1});
85 }
86 }
87
88 Q_FOREACH (int vpIndex, possibleHandles) {
89 QPointF vp = *handles()[vpIndex];
90 double dist = 0;
91 QPointF pt = QPointF();
92 QLineF snapLine = QLineF();
93
94 // TODO: Would be a good idea to generalize this whole routine
95 // in KisAlgebra2d, as it's all lifted from the vanishing
96 // point assistant and parallel ruler assistant, and by
97 // extension the perspective assistant...
98 qreal dx = point.x() - strokeBegin.x();
99 qreal dy = point.y() - strokeBegin.y();
100
101 if (vp != *handles()[2]) {
102 snapLine = QLineF(vp, strokeBegin);
103 } else {
104 QLineF vertical = QLineF(*handles()[0],*handles()[1]).normalVector();
105 snapLine = QLineF(vertical.p1(), vertical.p2());
106 QPointF translation = (vertical.p1()-strokeBegin)*-1.0;
107 snapLine = snapLine.translated(translation);
108 }
109
110 dx = snapLine.dx();
111 dy = snapLine.dy();
112
113 const qreal dx2 = dx * dx;
114 const qreal dy2 = dy * dy;
115 const qreal invsqrlen = 1.0 / (dx2 + dy2);
116
117 pt = QPointF(dx2 * point.x() + dy2 * snapLine.x1() + dx * dy * (point.y() - snapLine.y1()),
118 dx2 * snapLine.y1() + dy2 * point.y() + dx * dy * (point.x() - snapLine.x1()));
119
120 pt *= invsqrlen;
121 dist = qAbs(pt.x() - point.x()) + qAbs(pt.y() - point.y());
122
123 if (dist < best_dist) {
124 best_pt = pt;
125 best_dist = dist;
126 m_lastUsedPoint = vpIndex;
127 }
128 }
129
130 return best_pt;
131}
qreal norm(const T &a)

References KisPaintingAssistant::getLocalRect(), KisPaintingAssistant::handles(), isAssistantComplete(), KisPaintingAssistant::isLocal(), KisPaintingAssistant::m_hasBeenInsideLocalRect, m_lastUsedPoint, m_useVertical, and KisAlgebra2D::norm().

◆ saveCustomXml()

void TwoPointAssistant::saveCustomXml ( QXmlStreamWriter * xml)
overridevirtual

Reimplemented from KisPaintingAssistant.

Definition at line 485 of file TwoPointAssistant.cc.

486{
487 xml->writeStartElement("gridDensity");
488 xml->writeAttribute("value", KisDomUtils::toString( this->gridDensity()));
489 xml->writeEndElement();
490 xml->writeStartElement("useVertical");
491 xml->writeAttribute("value", KisDomUtils::toString( (int)this->useVertical()));
492 xml->writeEndElement();
493 xml->writeStartElement("isLocal");
494 xml->writeAttribute("value", KisDomUtils::toString( (int)this->isLocal()));
495 xml->writeEndElement();
496
497}
QString toString(const QString &value)

References gridDensity(), KisPaintingAssistant::isLocal(), KisDomUtils::toString(), and useVertical().

◆ secondLocalHandle()

KisPaintingAssistantHandleSP TwoPointAssistant::secondLocalHandle ( ) const
overrideprotectedvirtual

secondLocalHandle Note: this doesn't guarantee it will be the bottomRight corner! For that, use getLocalRect().bottomRight() (and remember that for QRect bottomRight() works differently than for QRectF, so don't convert to QRect before accessing the corner)

Returns

Reimplemented from KisPaintingAssistant.

Definition at line 421 of file TwoPointAssistant.cc.

422{
423 if (handles().size() > LocalSecondHandle) {
424 return handles().at(LocalSecondHandle);
425 } else {
426 return nullptr;
427 }
428}

References KisPaintingAssistant::handles(), and LocalSecondHandle.

◆ setGridDensity()

void TwoPointAssistant::setGridDensity ( double density)

Definition at line 444 of file TwoPointAssistant.cc.

445{
446 m_gridDensity = density;
447}

References m_gridDensity.

◆ setUseVertical()

void TwoPointAssistant::setUseVertical ( bool value)

Definition at line 454 of file TwoPointAssistant.cc.

455{
457}
float value(const T *src, size_t ch)

References m_useVertical, and value().

◆ useVertical()

bool TwoPointAssistant::useVertical ( )

Definition at line 449 of file TwoPointAssistant.cc.

450{
451 return m_useVertical;
452}

References m_useVertical.

Member Data Documentation

◆ m_canvas

KisCanvas2* TwoPointAssistant::m_canvas {nullptr}
private

Definition at line 76 of file TwoPointAssistant.h.

76{nullptr};

◆ m_gridDensity

double TwoPointAssistant::m_gridDensity {1.0}
private

Definition at line 79 of file TwoPointAssistant.h.

79{1.0};

◆ m_lastUsedPoint

int TwoPointAssistant::m_lastUsedPoint {-1}
private

Definition at line 82 of file TwoPointAssistant.h.

82{-1}; // last used vanishing point

◆ m_snapLine

QLineF TwoPointAssistant::m_snapLine
private

Definition at line 78 of file TwoPointAssistant.h.

◆ m_useVertical

bool TwoPointAssistant::m_useVertical {true}
private

Definition at line 80 of file TwoPointAssistant.h.

80{true};

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