Krita Source Code Documentation
Loading...
Searching...
No Matches
SpiralShape.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2007 Rob Buis <buis@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "SpiralShape.h"
8
10#include <KoPathPoint.h>
12#include <KoXmlWriter.h>
13#include <KoXmlNS.h>
14
15#include <math.h>
16#include "kis_assert.h"
17
18
20 : m_fade(.9)
21 , m_kindAngle(M_PI)
22 , m_radii(100.0, 100.0)
23 , m_type(Curve)
24 , m_clockwise(true)
25{
26 //m_handles.push_back(QPointF(50, 0));
27 //m_handles.push_back(QPointF(50, 50));
28 //m_handles.push_back(QPointF(0, 50));
29 createPath(QSizeF(m_radii.x(), m_radii.y()));
30}
31
33 : KoParameterShape(rhs),
34 m_fade(rhs.m_fade),
35 m_kindAngle(rhs.m_kindAngle),
36 m_center(rhs.m_center),
37 m_radii(rhs.m_radii),
38 m_type(rhs.m_type),
39 m_clockwise(rhs.m_clockwise)
40
41{
42 Q_FOREACH(KoPathPoint *point, rhs.m_points) {
43 KIS_ASSERT_RECOVER(point) { continue; }
44 m_points << new KoPathPoint(*point, this);
45 }
46}
47
48
52
54{
55 return new SpiralShape(*this);
56}
57
58void SpiralShape::setSize(const QSizeF &newSize)
59{
60 QTransform matrix(resizeMatrix(newSize));
61 m_center = matrix.map(m_center);
62 m_radii = matrix.map(m_radii);
64}
65
67{
68 QPointF offset(KoParameterShape::normalize());
69 QTransform matrix;
70 matrix.translate(-offset.x(), -offset.y());
71 m_center = matrix.map(m_center);
72 return offset;
73}
74
75void SpiralShape::moveHandleAction(int handleId, const QPointF &point, Qt::KeyboardModifiers modifiers)
76{
77 Q_UNUSED(handleId);
78 Q_UNUSED(point);
79 Q_UNUSED(modifiers);
80#if 0
81 QPointF p(point);
82
83 QPointF diff(m_center - point);
84 diff.setX(-diff.x());
85 qreal angle = 0;
86 if (diff.x() == 0) {
87 angle = (diff.y() < 0 ? 270 : 90) * M_PI / 180.0;
88 } else {
89 diff.setY(diff.y() * m_radii.x() / m_radii.y());
90 angle = atan(diff.y() / diff.x());
91 if (angle < 0) {
92 angle = M_PI + angle;
93 }
94 if (diff.y() < 0) {
95 angle += M_PI;
96 }
97 }
98
99 switch (handleId) {
100 case 0:
101 p = QPointF(m_center + QPointF(cos(angle) * m_radii.x(), -sin(angle) * m_radii.y()));
102 m_handles[handleId] = p;
104 break;
105 case 1:
106 p = QPointF(m_center + QPointF(cos(angle) * m_radii.x(), -sin(angle) * m_radii.y()));
107 m_handles[handleId] = p;
109 break;
110 case 2: {
111 QList<QPointF> kindHandlePositions;
112 kindHandlePositions.push_back(QPointF(m_center + QPointF(cos(m_kindAngle) * m_radii.x(), -sin(m_kindAngle) * m_radii.y())));
113 kindHandlePositions.push_back(m_center);
114 kindHandlePositions.push_back((m_handles[0] + m_handles[1]) / 2.0);
115
116 QPointF diff = m_center * 2.0;
117 int handlePos = 0;
118 for (int i = 0; i < kindHandlePositions.size(); ++i) {
119 QPointF pointDiff(p - kindHandlePositions[i]);
120 if (i == 0 || qAbs(pointDiff.x()) + qAbs(pointDiff.y()) < qAbs(diff.x()) + qAbs(diff.y())) {
121 diff = pointDiff;
122 handlePos = i;
123 }
124 }
125 m_handles[handleId] = kindHandlePositions[handlePos];
126 m_type = SpiralType(handlePos);
127 } break;
128 }
129#endif
130}
131
132void SpiralShape::updatePath(const QSizeF &size)
133{
135 normalize();
136#if 0
137 Q_UNUSED(size);
138 QPointF startpoint(m_handles[0]);
139
140 QPointF curvePoints[12];
141
142 int pointCnt = arcToCurve(m_radii.x(), m_radii.y(), m_startAngle, sweepAngle(), startpoint, curvePoints);
143
144 int cp = 0;
145 m_points[cp]->setPoint(startpoint);
146 m_points[cp]->unsetProperty(KoPathPoint::HasControlPoint1);
147 for (int i = 0; i < pointCnt; i += 3) {
148 m_points[cp]->setControlPoint2(curvePoints[i]);
149 m_points[++cp]->setControlPoint1(curvePoints[i + 1]);
150 m_points[cp]->setPoint(curvePoints[i + 2]);
151 m_points[cp]->unsetProperty(KoPathPoint::HasControlPoint2);
152 }
153 if (m_type == Curve) {
154 m_points[++cp]->setPoint(m_center);
155 m_points[cp]->unsetProperty(KoPathPoint::HasControlPoint1);
156 m_points[cp]->unsetProperty(KoPathPoint::HasControlPoint2);
157 } else if (m_type == Line && m_startAngle == m_endAngle) {
158 m_points[0]->setControlPoint1(m_points[cp]->controlPoint1());
159 m_points[0]->setPoint(m_points[cp]->point());
160 --cp;
161 }
162
163 d->m_subpaths[0]->clear();
164 for (int i = 0; i <= cp; ++i) {
165 if (i < cp || (m_type == Line && m_startAngle != m_endAngle)) {
166 m_points[i]->unsetProperty(KoPathPoint::CloseSubpath);
167 } else {
168 m_points[i]->setProperty(KoPathPoint::CloseSubpath);
169 }
170 d->m_subpaths[0]->push_back(m_points[i]);
171 }
172
173#endif
174}
175
176void SpiralShape::createPath(const QSizeF &size)
177{
178 Q_UNUSED(size);
179 clear();
180 QPointF center = QPointF(m_radii.x() / 2.0, m_radii.y() / 2.0);
181 //moveTo(QPointF(size.width(), m_radii.y()));
182 qreal adv_ang = (m_clockwise ? -1.0 : 1.0) * M_PI_2;
183 // radius of first segment is non-faded radius:
184 qreal m_radius = m_radii.x() / 2.0;
185 qreal r = m_radius;
186
187 QPointF oldP(center.x(), (m_clockwise ? -1.0 : 1.0) * m_radius + center.y());
188 QPointF newP;
189 QPointF newCenter(center);
190 moveTo(oldP);
191 uint m_segments = 10;
192 //m_handles[0] = oldP;
193
194 for (uint i = 0; i < m_segments; ++i) {
195 newP.setX(r * cos(adv_ang * (i + 2)) + newCenter.x());
196 newP.setY(r * sin(adv_ang * (i + 2)) + newCenter.y());
197
198 if (m_type == Curve) {
199 qreal rx = qAbs(oldP.x() - newP.x());
200 qreal ry = qAbs(oldP.y() - newP.y());
201 if (m_clockwise) {
202 arcTo(rx, ry, ((i + 1) % 4) * 90, 90);
203 } else {
204 arcTo(rx, ry, 360 - ((i + 1) % 4) * 90, -90);
205 }
206 } else {
207 lineTo(newP);
208 }
209
210 newCenter += (newP - newCenter) * (1.0 - m_fade);
211 oldP = newP;
212 r *= m_fade;
213 }
214 //m_handles[1] = QPointF(center.x(), (m_clockwise ? -1.0 : 1.0) * m_radius + center.y());
215 m_points = *subpaths()[0];
216
218}
219
221{
222 /*
223 m_kindAngle = (m_startAngle + m_endAngle) * M_PI / 360.0;
224 if (m_startAngle > m_endAngle)
225 {
226 m_kindAngle += M_PI;
227 }
228 switch (m_type)
229 {
230 case Curve:
231 m_handles[2] = m_center + QPointF(cos(m_kindAngle) * m_radii.x(), -sin(m_kindAngle) * m_radii.y());
232 break;
233 case Line:
234 m_handles[2] = m_center;
235 break;
236 }
237 */
238}
239
241{
242// qreal startRadian = m_startAngle * M_PI / 180.0;
243// qreal endRadian = m_endAngle * M_PI / 180.0;
244// m_handles[0] = m_center + QPointF(cos(startRadian) * m_radii.x(), -sin(startRadian) * m_radii.y());
245// m_handles[1] = m_center + QPointF(cos(endRadian) * m_radii.x(), -sin(endRadian) * m_radii.y());
246}
247
249{
250 m_type = type;
252 updatePath(size());
253}
254
259
260void SpiralShape::setFade(qreal fade)
261{
262 m_fade = fade;
264 //updateAngleHandles();
265 updatePath(size());
266}
267
268qreal SpiralShape::fade() const
269{
270 return m_fade;
271}
272
274{
275 return m_clockwise;
276}
277
278void SpiralShape::setClockWise(bool clockWise)
279{
282 //updateAngleHandles();
283 updatePath(size());
284}
285
287{
288 return SpiralShapeId;
289}
const Params2D p
unsigned int uint
#define SpiralShapeId
Definition SpiralShape.h:12
QSharedDataPointer< Private > d
QPointF normalize() override
Normalizes the path data.
void setSize(const QSizeF &size) override
reimplemented from KoShape
A KoPathPoint represents a point in a path.
@ CloseSubpath
it closes a subpath (only applicable on StartSubpath and StopSubpath)
Definition KoPathPoint.h:40
const KoSubpathList & subpaths() const
QTransform resizeMatrix(const QSizeF &newSize) const
KoPathPoint * lineTo(const QPointF &p)
Adds a new line segment.
QSizeF size() const override
reimplemented
void notifyPointsChanged()
KoPathPoint * moveTo(const QPointF &p)
Starts a new Subpath.
int arcToCurve(qreal rx, qreal ry, qreal startAngle, qreal sweepAngle, const QPointF &offset, QPointF *curvePoints) const
Add an arc.
KoPathPoint * arcTo(qreal rx, qreal ry, qreal startAngle, qreal sweepAngle)
Add an arc.
void clear()
Removes all subpaths and their points from the path.
void updateKindHandle()
void updatePath(const QSizeF &size) override
Update the path of the parameter shape.
void setSize(const QSizeF &newSize) override
reimplemented from KoShape
SpiralType
the possible spiral types
Definition SpiralShape.h:22
@ Line
spiral uses lines
Definition SpiralShape.h:24
@ Curve
spiral uses curves
Definition SpiralShape.h:23
KoShape * cloneShape() const override
creates a deep copy of the shape or shape's subtree
qreal m_kindAngle
Definition SpiralShape.h:73
QPointF m_center
Definition SpiralShape.h:75
QPointF normalize() override
Normalizes the path data.
void moveHandleAction(int handleId, const QPointF &point, Qt::KeyboardModifiers modifiers=Qt::NoModifier) override
Updates the internal state of a KoParameterShape.
SpiralType m_type
Definition SpiralShape.h:79
void setType(SpiralType type)
QString pathShapeId() const override
reimplemented
bool clockWise() const
void setClockWise(bool clockwise)
~SpiralShape() override
KoSubpath m_points
Definition SpiralShape.h:83
qreal fade() const
Returns the actual fade parameter.
void updateAngleHandles()
bool m_clockwise
Definition SpiralShape.h:81
QPointF m_radii
Definition SpiralShape.h:77
SpiralType type() const
Returns the actual spiral type.
void createPath(const QSizeF &size)
void setFade(qreal fade)
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
#define M_PI
Definition kis_global.h:111