Krita Source Code Documentation
Loading...
Searching...
No Matches
ConcentricEllipseAssistant.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: 2017 Scott Petrovic <scottpetrovic@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8
10
11#include <klocalizedstring.h>
12#include "kis_debug.h"
13#include <QPainter>
14#include <QPainterPath>
15#include <QLinearGradient>
16#include <QTransform>
17#include <kis_canvas2.h>
19#include <kis_algebra_2d.h>
20
21#include <math.h>
22
24 : KisPaintingAssistant("concentric ellipse", i18n("Concentric Ellipse assistant"))
25{
26}
27
28KisPaintingAssistantSP ConcentricEllipseAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
29{
30 return KisPaintingAssistantSP(new ConcentricEllipseAssistant(*this, handleMap));
31}
32
33ConcentricEllipseAssistant::ConcentricEllipseAssistant(const ConcentricEllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
34 : KisPaintingAssistant(rhs, handleMap)
35 , m_ellipse(rhs.m_ellipse)
36 , m_extraEllipse(rhs.m_extraEllipse)
37{
38}
39
40QPointF ConcentricEllipseAssistant::project(const QPointF& pt, const QPointF& strokeBegin) const
41{
42 Q_ASSERT(isAssistantComplete());
43 m_ellipse.set(*handles()[0], *handles()[1], *handles()[2]);
44
45 //calculate ratio
46 QPointF initial = m_ellipse.project(strokeBegin);
47 QPointF center = m_ellipse.boundingRect().center();
48 qreal Ratio = QLineF(center, strokeBegin).length() /QLineF(center, initial).length();
49
50 //calculate the points of the extrapolated ellipse.
51 QLineF extrapolate0 = QLineF(center, *handles()[0]);
52 extrapolate0.setLength(extrapolate0.length()*Ratio);
53 QLineF extrapolate1 = QLineF(center, *handles()[1]);
54 extrapolate1.setLength(extrapolate1.length()*Ratio);
55 QLineF extrapolate2 = QLineF(center, *handles()[2]);
56 extrapolate2.setLength(extrapolate2.length()*Ratio);
57
58 //set the extrapolation ellipse.
59 m_extraEllipse.set(extrapolate0.p2(), extrapolate1.p2(), extrapolate2.p2());
60
61 return m_extraEllipse.project(pt);
62}
63
64QPointF ConcentricEllipseAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin, const bool /*snapToAny*/, qreal /*moveThresholdPt*/)
65{
66 return project(pt, strokeBegin);
67}
68
69void ConcentricEllipseAssistant::adjustLine(QPointF &point, QPointF &strokeBegin)
70{
71 point = project(point, strokeBegin);
72}
73
74void ConcentricEllipseAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
75{
76 gc.save();
77 gc.resetTransform();
78
79 if (isSnappingActive() && previewVisible == true){
80
82
83 QTransform initialTransform = converter->documentToWidgetTransform();
84
85 if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) {
86 QPointF mousePos = effectiveBrushPosition(converter, canvas);
87 QPointF initial = m_ellipse.project(initialTransform.inverted().map(mousePos));
88 QPointF center = m_ellipse.boundingRect().center();
89 qreal Ratio = QLineF(center, initialTransform.inverted().map(mousePos)).length() /QLineF(center, initial).length();
90 //line from center to handle 1 * difference.
91 //set handle1 translated to
92 // valid ellipse
93 gc.setTransform(initialTransform);
94 gc.setTransform(m_ellipse.getInverse(), true);
95 QPainterPath path;
96 // Draw the ellipse
97 path.addEllipse(QPointF(0, 0), m_ellipse.semiMajor()*Ratio, m_ellipse.semiMinor()*Ratio);
98 drawPreview(gc, path);
99 }
100 }
101 }
102 gc.restore();
103 KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
104
105}
106
107
108void ConcentricEllipseAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible)
109{
110 if (assistantVisible == false || handles().size() < 2) { // 2 points means a line, so we can continue after 1 point
111 return;
112 }
113
114 QTransform initialTransform = converter->documentToWidgetTransform();
115
116 if (handles().size() == 2) {
117 // just draw the axis
118 gc.setTransform(initialTransform);
119 QPainterPath path;
120 path.moveTo(*handles()[0]);
121 path.lineTo(*handles()[1]);
122 drawPath(gc, path, isSnappingActive());
123 return;
124 }
125
126 if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) {
127 // valid ellipse
128
129 gc.setTransform(initialTransform);
130 gc.setTransform(m_ellipse.getInverse(), true);
131 QPainterPath path;
132 path.moveTo(QPointF(-m_ellipse.semiMajor(), 0)); path.lineTo(QPointF(m_ellipse.semiMajor(), 0));
133 path.moveTo(QPointF(0, -m_ellipse.semiMinor())); path.lineTo(QPointF(0, m_ellipse.semiMinor()));
134 // Draw the ellipse
135 path.addEllipse(QPointF(0, 0), m_ellipse.semiMajor(), m_ellipse.semiMinor());
136 drawPath(gc, path, isSnappingActive());
137 }
138}
139
141{
142 if (!isAssistantComplete()) {
144 }
145
146 if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) {
147 return m_ellipse.boundingRect().adjusted(-2, -2, 2, 2).toAlignedRect();
148 } else {
149 return QRect();
150 }
151}
152
154{
155 return (*handles()[0] + *handles()[1]) * 0.5;
156}
157
159{
160 return handles().size() >= 3;
161}
162
163void ConcentricEllipseAssistant::transform(const QTransform &transform)
164{
165 m_ellipse.set(*handles()[0], *handles()[1], *handles()[2]);
166
167 QPointF newAxes;
168 QTransform newTransform;
169
170 std::tie(newAxes, newTransform) = KisAlgebra2D::transformEllipse(QPointF(m_ellipse.semiMajor(), m_ellipse.semiMinor()), m_ellipse.getInverse() * transform);
171
172 const QPointF p1 = newTransform.map(QPointF(newAxes.x(), 0));
173 const QPointF p2 = newTransform.map(QPointF(-newAxes.x(), 0));
174 const QPointF p3 = newTransform.map(QPointF(0, newAxes.y()));
175
176 *handles()[0] = p1;
177 *handles()[1] = p2;
178 *handles()[2] = p3;
179
180 uncache();
181}
182
186
190
192{
193 return "concentric ellipse";
194}
195
197{
198 return i18n("Concentric Ellipse");
199}
200
QPointF p2
QPointF p3
QPointF p1
KisPaintingAssistant * createPaintingAssistant() const override
KisPaintingAssistantSP clone(QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
QPointF getDefaultEditorPosition() const override
void adjustLine(QPointF &point, QPointF &strokeBegin) 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
void transform(const QTransform &transform) override
void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas, bool assistantVisible=true, bool previewVisible=true) override
QPointF project(const QPointF &pt, const QPointF &strokeBegin) const
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
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
std::pair< QPointF, QTransform > transformEllipse(const QPointF &axes, const QTransform &fullLocalToGlobal)
static double extrapolate2(struct osn_context *ctx, int xsb, int ysb, double dx, double dy)