Krita Source Code Documentation
Loading...
Searching...
No Matches
FisheyePointAssistant.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2010 Geoffry Song <goffrie@gmail.com>
4 * SPDX-FileCopyrightText: 2014 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
5 * SPDX-FileCopyrightText: 2017 Scott Petrovic <scottpetrovic@gmail.com>
6 *
7 * SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9
11
12#include "kis_debug.h"
13#include <klocalizedstring.h>
14
15#include <QPainter>
16#include <QPainterPath>
17#include <QLinearGradient>
18#include <QTransform>
19
20#include <kis_canvas2.h>
22#include <kis_algebra_2d.h>
23
24#include <math.h>
25#include <limits>
26
28 : KisPaintingAssistant("fisheye-point", i18n("Fish Eye Point assistant"))
29{
30}
31
32FisheyePointAssistant::FisheyePointAssistant(const FisheyePointAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
33 : KisPaintingAssistant(rhs, handleMap)
34 , e(rhs.e)
35 , extraE(rhs.extraE)
36{
37}
38
39KisPaintingAssistantSP FisheyePointAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
40{
41 return KisPaintingAssistantSP(new FisheyePointAssistant(*this, handleMap));
42}
43
44QPointF FisheyePointAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
45{
46 const static QPointF nullPoint(std::numeric_limits<qreal>::quiet_NaN(), std::numeric_limits<qreal>::quiet_NaN());
47 Q_ASSERT(isAssistantComplete());
48 e.set(*handles()[0], *handles()[1], *handles()[2]);
49
50 //set the extrapolation ellipse.
51 if (e.set(*handles()[0], *handles()[1], *handles()[2])){
52 QLineF radius(*handles()[1], *handles()[0]);
53 radius.setAngle(fmod(radius.angle()+180.0,360.0));
54 QLineF radius2(*handles()[0], *handles()[1]);
55 radius2.setAngle(fmod(radius2.angle()+180.0,360.0));
56 if ( extraE.set(*handles()[0], *handles()[1],strokeBegin ) ) {
57 return extraE.project(pt);
58 } else if (extraE.set(radius.p1(), radius.p2(),strokeBegin)) {
59 return extraE.project(pt);
60 } else if (extraE.set(radius2.p1(), radius2.p2(),strokeBegin)){
61 return extraE.project(pt);
62 }
63 }
64
65 return nullPoint;
66
67}
68
69QPointF FisheyePointAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin, const bool /*snapToAny*/, qreal /*moveThresholdPt*/)
70{
71 return project(pt, strokeBegin);
72}
73
74void FisheyePointAssistant::adjustLine(QPointF &point, QPointF &strokeBegin)
75{
76 point = QPointF();
77 strokeBegin = QPointF();
78}
79
80void FisheyePointAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
81{
82 gc.save();
83 gc.resetTransform();
84
85 if (isSnappingActive() && previewVisible == true ) {
86
88
89 QTransform initialTransform = converter->documentToWidgetTransform();
90
91 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
92 QPointF mousePos = effectiveBrushPosition(converter, canvas);
93 if (extraE.set(*handles()[0], *handles()[1], initialTransform.inverted().map(mousePos))){
94 gc.setTransform(initialTransform);
95 gc.setTransform(e.getInverse(), true);
96 QPainterPath path;
97 // Draw the ellipse
98 path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
99 drawPreview(gc, path);
100 }
101 QLineF radius(*handles()[1], *handles()[0]);
102 radius.setAngle(fmod(radius.angle()+180.0,360.0));
103 if (extraE.set(radius.p1(), radius.p2(), initialTransform.inverted().map(mousePos))){
104 gc.setTransform(initialTransform);
105 gc.setTransform(extraE.getInverse(), true);
106 QPainterPath path;
107 // Draw the ellipse
108 path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
109 drawPreview(gc, path);
110 }
111 QLineF radius2(*handles()[0], *handles()[1]);
112 radius2.setAngle(fmod(radius2.angle()+180.0,360.0));
113 if (extraE.set(radius2.p1(), radius2.p2(), initialTransform.inverted().map(mousePos))){
114 gc.setTransform(initialTransform);
115 gc.setTransform(extraE.getInverse(), true);
116 QPainterPath path;
117 // Draw the ellipse
118 path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
119 drawPreview(gc, path);
120 }
121
122 }
123 }
124 }
125 gc.restore();
126
127 KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
128
129}
130
131void FisheyePointAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible)
132{
133 if (assistantVisible == false){
134 return;
135 }
136
137 QTransform initialTransform = converter->documentToWidgetTransform();
138
139 if (handles().size() == 2) {
140 // just draw the axis
141 gc.setTransform(initialTransform);
142 QPainterPath path;
143 path.moveTo(*handles()[0]);
144 path.lineTo(*handles()[1]);
145 drawPath(gc, path, isSnappingActive());
146 return;
147 }
148 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
149 // valid ellipse
150
151 gc.setTransform(initialTransform);
152 gc.setTransform(e.getInverse(), true);
153 QPainterPath path;
154 //path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), -e.semiMinor()));
155 path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(-e.semiMajor(), e.semiMinor()));
156 //path.moveTo(QPointF(-e.semiMajor(), e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor()));
157 path.moveTo(QPointF(e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor()));
158 path.moveTo(QPointF(-(e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF(-(e.semiMajor()*3), e.semiMinor()));
159 path.moveTo(QPointF((e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF((e.semiMajor()*3), e.semiMinor()));
160 path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0));
161 //path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor()));
162 // Draw the ellipse
163 path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor());
164 drawPath(gc, path, isSnappingActive());
165 }
166
167}
168
170{
171 if (!isAssistantComplete()) {
173 }
174
175 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
176 return e.boundingRect().adjusted(-(e.semiMajor()*2), -2, (e.semiMajor()*2), 2).toAlignedRect();
177 } else {
178 return QRect();
179 }
180}
181
183{
184 return (*handles()[0] + *handles()[1]) * 0.5;
185}
186
188{
189 return handles().size() >= 3;
190}
191
192
196
200
202{
203 return "fisheye-point";
204}
205
207{
208 return i18n("Fish Eye Point");
209}
210
qreal semiMajor() const
Definition Ellipse.h:33
const QTransform & getInverse() const
Definition Ellipse.h:32
bool set(const QPointF &m1, const QPointF &m2, const QPointF &p)
Definition Ellipse.cc:23
QRectF boundingRect() const
Definition Ellipse.cc:62
qreal semiMinor() const
Definition Ellipse.h:34
QPointF project(const QPointF &) const
Definition Ellipse.cc:39
KisPaintingAssistant * createPaintingAssistant() const override
QRect boundingRect() const override
KisPaintingAssistantSP clone(QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
void adjustLine(QPointF &point, QPointF &strokeBegin) override
QPointF project(const QPointF &pt, const QPointF &strokeBegin)
QPointF getDefaultEditorPosition() const override
bool isAssistantComplete() const override
void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached=true, KisCanvas2 *canvas=0, 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 upda...
QPointF adjustPosition(const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
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 pain...
void drawPath(QPainter &painter, const QPainterPath &path, bool drawActive=true)
void drawPreview(QPainter &painter, const QPainterPath &path)
virtual void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true)
const QList< KisPaintingAssistantHandleSP > & handles() const
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
Definition kis_types.h:189