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

#include <CurvilinearPerspectiveAssistant.h>

+ Inheritance diagram for CurvilinearPerspectiveAssistant:

Public Member Functions

void adjustLine (QPointF &point, QPointF &strokeBegin) override
 
QPointF adjustPosition (const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
 
KisPaintingAssistantSP clone (QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
 
 CurvilinearPerspectiveAssistant ()
 
QPointF getDefaultEditorPosition () const override
 
bool isAssistantComplete () const override
 
int numHandles () const override
 
- 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
 
virtual bool canBeLocal () const
 canBeLocal
 
KisPaintingAssistantHandleSP closestCornerHandleFromPoint (QPointF point)
 
void copySharedData (KisPaintingAssistantSP assistant)
 
void drawError (QPainter &painter, const QPainterPath &path, const KoColorDisplayRendererInterface *displayRenderInterface)
 
void drawPath (QPainter &painter, const QPainterPath &path, const KoColorDisplayRendererInterface *displayRenderInterface, bool drawActive=true)
 
void drawPreview (QPainter &painter, const QPainterPath &path, const KoColorDisplayRendererInterface *displayRenderInterface)
 
void drawX (QPainter &painter, const QPointF &pt, const KoColorDisplayRendererInterface *displayRenderInterface)
 
QPointF editorWidgetOffset ()
 
QColor effectiveAssistantColor () const
 
virtual void endStroke ()
 
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
 
virtual bool loadCustomXml (QXmlStreamReader *xml)
 
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
 
virtual void saveCustomXml (QXmlStreamWriter *xml)
 
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, const KoColorDisplayRendererInterface *displayRenderInterface, bool cached=true, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true) override
 
void drawCache (QPainter &gc, const KisCoordinatesConverter *converter, const KoColorDisplayRendererInterface *displayRenderInterface, bool assistantVisible=true) override
 performance layer where the graphics can be drawn from a cache instead of generated every render update
 
- 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().
 
virtual KisPaintingAssistantHandleSP firstLocalHandle () const
 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.
 
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
 
virtual KisPaintingAssistantHandleSP secondLocalHandle () const
 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)
 

Private Member Functions

 CurvilinearPerspectiveAssistant (const CurvilinearPerspectiveAssistant &rhs, QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap)
 
QLineF identifyCircle (const QPointF thirdPoint)
 

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 18 of file CurvilinearPerspectiveAssistant.h.

Constructor & Destructor Documentation

◆ CurvilinearPerspectiveAssistant() [1/2]

CurvilinearPerspectiveAssistant::CurvilinearPerspectiveAssistant ( )

Definition at line 28 of file CurvilinearPerspectiveAssistant.cc.

29 : KisPaintingAssistant("curvilinear-perspective", i18n("Curvilinear Perspective assistant"))
30{
31}
KisPaintingAssistant(const QString &id, const QString &name)

◆ CurvilinearPerspectiveAssistant() [2/2]

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

Definition at line 33 of file CurvilinearPerspectiveAssistant.cc.

34 : KisPaintingAssistant(rhs, handleMap)
35{
36}

Member Function Documentation

◆ adjustLine()

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

Implements KisPaintingAssistant.

Definition at line 43 of file CurvilinearPerspectiveAssistant.cc.

44{
45 point = QPointF();
46 strokeBegin = QPointF();
47}

◆ adjustPosition()

QPointF CurvilinearPerspectiveAssistant::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 226 of file CurvilinearPerspectiveAssistant.cc.

227{
228 // Get the center and radius for the given point
229 QLineF initialCircle = identifyCircle(strokeBegin);
230
231 // Set the new point onto the circle.
232 QLineF magnetizedCircle(initialCircle.p1(), pt);
233 magnetizedCircle.setLength(initialCircle.length());
234
235 return magnetizedCircle.p2();
236
237}
QLineF identifyCircle(const QPointF thirdPoint)

References identifyCircle().

◆ clone()

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

Implements KisPaintingAssistant.

Definition at line 38 of file CurvilinearPerspectiveAssistant.cc.

39{
40 return KisPaintingAssistantSP(new CurvilinearPerspectiveAssistant(*this, handleMap));
41}
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
Definition kis_types.h:189

References CurvilinearPerspectiveAssistant().

◆ drawAssistant()

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

Reimplemented from KisPaintingAssistant.

Definition at line 49 of file CurvilinearPerspectiveAssistant.cc.

50{
51 Q_UNUSED(cached);
52 Q_UNUSED(updateRect);
53
54 gc.save();
55 gc.resetTransform();
56
57 const QColor canvasAssistantColor = displayRenderInterface->convertColorToDisplayColorSpace(KoColor(effectiveAssistantColor(), KoColorSpaceRegistry::instance()->rgb8()));
58
59 if (isSnappingActive()) {
60
61 QTransform initialTransform = converter->documentToWidgetTransform();
62 QPainterPath baseGuidePath;
63 QPainterPath mouseGuidePath;
64
65 gc.setTransform(initialTransform);
66
67 /*
68 * Curvilinear perspective is created by circular arcs that intersect 2 vanishing points.
69 * As such, the center of the circle and the radius of the circle need to be determined.
70 *
71 * Create guidelines by selecting incremental multipliers for the assistant size between [-1, 1),
72 * and calculating the center location and radius of the circle to include the point
73 * at the location specified by the multiplier (the "arbitrary point").
74 *
75 * Formulas:
76 * Radius^2 = HalfHandleDist^2 + CenterDist^2 (b.c. The circle must include both vanishing points.)
77 * Radius^2 = (CenterDist + Multiplier * HalfHandleDist)^2 (b.c. The circle must include the arbitrary point)
78 *
79 * Solve for CenterDist and Radius:
80 * CenterDist = HalfHandleDist * (1 - Multiplier * Multiplier) / ( 2 * Multiplier)
81 * Radius = HalfHandleDist * (1 + Multiplier * Multiplier) / ( 2 * Multiplier)
82 *
83 */
84
85 QPointF p1 = *handles()[0];
86 QPointF p2 = *handles()[1];
87
88 double deltaX = p2.x() - p1.x();
89 double deltaY = p2.y() - p1.y();
90
91 // Copied from Two-Point Perspective's fading effect for approaching vanishing points.
92 // Set up the fading effect for the grid lines
93 // Needed so the grid density doesn't look distracting
94 QColor color = canvasAssistantColor;
95 QGradient fade = QLinearGradient(
96 QPointF(p1.x() - deltaY, p1.y() + deltaX),
97 QPointF(p1.x() + deltaY, p1.y() - deltaX));
98
99 color.setAlphaF(0.0);
100 fade.setColorAt(0.42, canvasAssistantColor);
101 fade.setColorAt(0.5, color);
102 fade.setColorAt(0.58, canvasAssistantColor);
103 const QPen pen = gc.pen();
104 const QBrush new_brush = QBrush(fade);
105 int width = 0;
106 const QPen new_pen = QPen(new_brush, width, pen.style());
107 gc.setPen(new_pen);
108
109 double handleDistance = KisAlgebra2D::norm(QPointF(deltaX, deltaY));
110 double halfHandleDist = handleDistance / 2.0;
111
112 double avgX = deltaX / 2.0 + p1.x();
113 double avgY = deltaY / 2.0 + p1.y();
114
115 // Rotate 90 degrees by formula: (-y, x)
116 // Then normalize vector.
117 double dirX = -deltaY / handleDistance;
118 double dirY = deltaX / handleDistance;
119
120 int resolution = halfHandleDist / 3;
121
122 if(assistantVisible) {
123
124 for(int i = -resolution; i < resolution; i++) {
125 // If i = 0, the circle would be infinitely far away with an infinite radius (aka a line)
126 if(i == 0) {
127 baseGuidePath.moveTo(QPointF(p1.x() - deltaX*2, p1.y() - deltaY*2));
128 baseGuidePath.lineTo(QPointF(p2.x() + deltaX*2, p2.y() + deltaY*2));
129 continue;
130 }
131 // Map loop iterator to multiplier. This line gives the depth-like effect.
132 double mult = 1.0 / i;
133 // Use formula to calculate CenterDist
134 double centerDist = halfHandleDist * (1 - pow2(mult)) / (2*mult);
135
136 // Use the distance to the center (from the average point) to calculate the center location.
137 double circleCenterX = centerDist * dirX + avgX;
138 double circleCenterY = centerDist * dirY + avgY;
139 // Use formula to calculate Radius
140 double radius = halfHandleDist * (1 + pow2(mult)) / (2*mult);
141
142 baseGuidePath.addEllipse(QPointF(circleCenterX, circleCenterY), radius, radius);
143
144 }
145 gc.drawPath(baseGuidePath);//drawPath(gc, baseGuidePath);
146 }
147
148 if(previewVisible) {
149 // Draw guideline for the mouse, based on mouse position.
150 QPointF mousePos = effectiveBrushPosition(converter, canvas);
151 // Get location on the screen of handles.
152 QPointF screenP1 = initialTransform.map(*handles()[0]);
153 QPointF screenP2 = initialTransform.map(*handles()[1]);
154 // Don't draw if mouse is too close to vanishing points (will flicker if not)
155 // Use distance squared to avoid expensive sqrt.
156 if(
157 kisSquareDistance(mousePos, screenP2) > 9 &&
158 kisSquareDistance(mousePos, screenP1) > 9
159 ) {
160 QLineF circle = identifyCircle(initialTransform.inverted().map(mousePos));
161 double radius = circle.length();
162 mouseGuidePath.addEllipse(circle.p1(), radius, radius);
163 }
164
165 gc.drawPath(mouseGuidePath);//drawPath(gc, mouseGuidePath);
166 }
167
168 }
169 gc.restore();
170
171 //KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
172
173}
QPointF p2
QPointF p1
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...
const QList< KisPaintingAssistantHandleSP > & handles() const
virtual QColor convertColorToDisplayColorSpace(const KoColor color) const =0
convertColorToDisplayColorSpace
T pow2(const T &x)
Definition kis_global.h:166
qreal kisSquareDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:194
qreal norm(const T &a)
static KoColorSpaceRegistry * instance()

References KoColorDisplayRendererInterface::convertColorToDisplayColorSpace(), KisCoordinatesConverter::documentToWidgetTransform(), KisPaintingAssistant::effectiveAssistantColor(), KisPaintingAssistant::effectiveBrushPosition(), KisPaintingAssistant::handles(), identifyCircle(), KoColorSpaceRegistry::instance(), KisPaintingAssistant::isSnappingActive(), kisSquareDistance(), KisAlgebra2D::norm(), p1, p2, and pow2().

◆ drawCache()

void CurvilinearPerspectiveAssistant::drawCache ( QPainter & gc,
const KisCoordinatesConverter * converter,
const KoColorDisplayRendererInterface * displayRenderInterface,
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 175 of file CurvilinearPerspectiveAssistant.cc.

176{
177 Q_UNUSED(gc);
178 Q_UNUSED(converter);
179 Q_UNUSED(assistantVisible);
180 Q_UNUSED(displayRenderInterface);
181}

◆ getDefaultEditorPosition()

QPointF CurvilinearPerspectiveAssistant::getDefaultEditorPosition ( ) const
overridevirtual

Implements KisPaintingAssistant.

Definition at line 239 of file CurvilinearPerspectiveAssistant.cc.

240{
241 return (*handles()[0] + *handles()[1]) * 0.5;
242}

References KisPaintingAssistant::handles().

◆ identifyCircle()

QLineF CurvilinearPerspectiveAssistant::identifyCircle ( const QPointF thirdPoint)
private

Definition at line 183 of file CurvilinearPerspectiveAssistant.cc.

183 {
184 /*
185 * Calculate center location and radius for an arbitrary point (usually the mouse location).
186 * Given Formulas:
187 * Radius^2 = HalfHandleDist^2 + CenterDist^2
188 * avgX + CenterDist * dirX = CenterX
189 * avgY + CenterDist * dirY = CenterY
190 *
191 * For ease of use, let BetaX = MouseX - AvgX, BetaY = MouseY - AvgY
192 * Calculated Formula for CenterDist:
193 * CenterDist = (BetaX^2 + BetaY^2 - HalfHandleDist^2) / (2 * DirY * BetaX + 2 * DirY * BetaY)
194 *
195 * Returns line from center to the arbitrary point.
196 *
197 */
198 QPointF p1 = *handles()[0];
199 QPointF p2 = *handles()[1];
200
201 double deltaX = p2.x() - p1.x();
202 double deltaY = p2.y() - p1.y();
203
204 double handleDistance = KisAlgebra2D::norm(QPointF(deltaX, deltaY));
205 double halfHandleDist = handleDistance / 2.0;
206
207 double avgX = deltaX / 2.0 + p1.x();
208 double avgY = deltaY / 2.0 + p1.y();
209
210 double dirX = -deltaY / handleDistance;
211 double dirY = deltaX / handleDistance;
212
213 double betaX = thirdPoint.x() - avgX;
214 double betaY = thirdPoint.y() - avgY;
215
216 double centerDist =
217 (pow2(betaX) + pow2(betaY) - pow2(halfHandleDist))
218 /
219 (2 * dirX * betaX + 2 * dirY * betaY);
220
221 double circleCenterX = centerDist*dirX + avgX;
222 double circleCenterY = centerDist*dirY + avgY;
223 return QLineF(QPointF(circleCenterX, circleCenterY), thirdPoint);
224}

References KisPaintingAssistant::handles(), KisAlgebra2D::norm(), p1, p2, and pow2().

◆ isAssistantComplete()

bool CurvilinearPerspectiveAssistant::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 244 of file CurvilinearPerspectiveAssistant.cc.

245{
246 return handles().size() >= 2;
247}

References KisPaintingAssistant::handles().

◆ numHandles()

int CurvilinearPerspectiveAssistant::numHandles ( ) const
inlineoverridevirtual

Implements KisPaintingAssistant.

Definition at line 28 of file CurvilinearPerspectiveAssistant.h.

28{ return 2; }

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