Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPathPointTypeCommand.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2006, 2008 Jan Hambrecht <jaham@gmx.net>
3 * SPDX-FileCopyrightText: 2006, 2007 Thorsten Zachmann <zachmann@kde.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
9
10#include <klocalizedstring.h>
11#include <math.h>
12
13#include "KoPathSegment.h"
14
16 const QList<KoPathPointData> & pointDataList,
17 PointType pointType,
18 KUndo2Command *parent)
19 : KoPathBaseCommand(parent)
20 , m_pointType(pointType)
21{
22 QList<KoPathPointData>::const_iterator it(pointDataList.begin());
23 for (; it != pointDataList.end(); ++it) {
24 KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
25 if (point) {
26 PointData pointData(*it);
27 pointData.m_oldControlPoint1 = it->pathShape->shapeToDocument(point->controlPoint1());
28 pointData.m_oldControlPoint2 = it->pathShape->shapeToDocument(point->controlPoint2());
29 pointData.m_oldProperties = point->properties();
30 pointData.m_hadControlPoint1 = point->activeControlPoint1();
31 pointData.m_hadControlPoint2 = point->activeControlPoint2();
32 m_oldPointData.append(pointData);
33 m_shapes.insert(it->pathShape);
34 }
35 }
36 setText(kundo2_i18n("Set point type"));
37}
38
42
44{
46 repaint(false);
48
50 for (; it != m_oldPointData.end(); ++it) {
51 KoPathPoint *point = it->m_pointData.pathShape->pointByIndex(it->m_pointData.pointIndex);
52 KoPathPoint::PointProperties properties = point->properties();
53
54 switch (m_pointType) {
55 case Line: {
56 point->removeControlPoint1();
57 point->removeControlPoint2();
58 break;
59 }
60 case Curve: {
61 KoPathPointIndex pointIndex = it->m_pointData.pointIndex;
62 KoPathPointIndex prevIndex;
63 KoPathPointIndex nextIndex;
64 KoPathShape * path = it->m_pointData.pathShape;
65 // get previous path node
66 if (pointIndex.second > 0)
67 prevIndex = KoPathPointIndex(pointIndex.first, pointIndex.second - 1);
68 else if (pointIndex.second == 0 && path->isClosedSubpath(pointIndex.first))
69 prevIndex = KoPathPointIndex(pointIndex.first, path->subpathPointCount(pointIndex.first) - 1);
70 // get next node
71 if (pointIndex.second < path->subpathPointCount(pointIndex.first) - 1)
72 nextIndex = KoPathPointIndex(pointIndex.first, pointIndex.second + 1);
73 else if (pointIndex.second < path->subpathPointCount(pointIndex.first) - 1
74 && path->isClosedSubpath(pointIndex.first))
75 nextIndex = KoPathPointIndex(pointIndex.first, 0);
76
77 KoPathPoint * prevPoint = path->pointByIndex(prevIndex);
78 KoPathPoint * nextPoint = path->pointByIndex(nextIndex);
79
80 if (prevPoint && ! point->activeControlPoint1() && appendPointData(KoPathPointData(path, prevIndex))) {
81 KoPathSegment cubic = KoPathSegment(prevPoint, point).toCubic();
82 if (prevPoint->activeControlPoint2()) {
83 prevPoint->setControlPoint2(cubic.first()->controlPoint2());
84 point->setControlPoint1(cubic.second()->controlPoint1());
85 } else
86 point->setControlPoint1(cubic.second()->controlPoint1());
87 }
88 if (nextPoint && ! point->activeControlPoint2() && appendPointData(KoPathPointData(path, nextIndex))) {
89 KoPathSegment cubic = KoPathSegment(point, nextPoint).toCubic();
90 if (nextPoint->activeControlPoint1()) {
91 point->setControlPoint2(cubic.first()->controlPoint2());
92 nextPoint->setControlPoint1(cubic.second()->controlPoint1());
93 } else
94 point->setControlPoint2(cubic.first()->controlPoint2());
95 }
96 point->setProperties(properties);
97 break;
98 }
99 case Symmetric: {
100 properties &= ~KoPathPoint::IsSmooth;
101 properties |= KoPathPoint::IsSymmetric;
102
103 // calculate vector from node point to first control point and normalize it
104 QPointF directionC1 = point->controlPoint1() - point->point();
105 qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * directionC1.y());
106 directionC1 /= dirLengthC1;
107 // calculate vector from node point to second control point and normalize it
108 QPointF directionC2 = point->controlPoint2() - point->point();
109 qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * directionC2.y());
110 directionC2 /= dirLengthC2;
111 // calculate the average distance of the control points to the node point
112 qreal averageLength = 0.5 * (dirLengthC1 + dirLengthC2);
113 // compute position of the control points so that they lie on a line going through the node point
114 // the new distance of the control points is the average distance to the node point
115 point->setControlPoint1(point->point() + 0.5 * averageLength * (directionC1 - directionC2));
116 point->setControlPoint2(point->point() + 0.5 * averageLength * (directionC2 - directionC1));
117 point->setProperties(properties);
118 }
119 break;
120 case Smooth: {
122 }
123 break;
124 case Corner:
125 default:
126 properties &= ~KoPathPoint::IsSymmetric;
127 properties &= ~KoPathPoint::IsSmooth;
128 point->setProperties(properties);
129 break;
130 }
131 }
132 repaint(true);
133}
134
136{
138 repaint(false);
139
140 /*
141 QList<PointData>::iterator it(m_oldPointData.begin());
142 for (; it != m_oldPointData.end(); ++it)
143 {
144 KoPathShape *pathShape = it->m_pointData.pathShape;
145 KoPathPoint *point = pathShape->pointByIndex(it->m_pointData.pointIndex);
146
147 point->setProperties(it->m_oldProperties);
148 if (it->m_hadControlPoint1)
149 point->setControlPoint1(pathShape->documentToShape(it->m_oldControlPoint1));
150 else
151 point->removeControlPoint1();
152 if (it->m_hadControlPoint2)
153 point->setControlPoint2(pathShape->documentToShape(it->m_oldControlPoint2));
154 else
155 point->removeControlPoint2();
156 }
157 */
160
161 repaint(true);
162}
163
165{
166 KoPathPoint::PointProperties properties = point->properties();
167
168 properties &= ~KoPathPoint::IsSymmetric;
169 properties |= KoPathPoint::IsSmooth;
170
171 // calculate vector from node point to first control point and normalize it
172 QPointF directionC1 = point->controlPoint1() - point->point();
173 qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * directionC1.y());
174 directionC1 /= dirLengthC1;
175 // calculate vector from node point to second control point and normalize it
176 QPointF directionC2 = point->controlPoint2() - point->point();
177 qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * directionC2.y());
178 directionC2 /= dirLengthC2;
179 // compute position of the control points so that they lie on a line going through the node point
180 // the new distance of the control points is the average distance to the node point
181 point->setControlPoint1(point->point() + 0.5 * dirLengthC1 * (directionC1 - directionC2));
182 point->setControlPoint2(point->point() + 0.5 * dirLengthC2 * (directionC2 - directionC1));
183
184 point->setProperties(properties);
185}
186
188{
189 QList<PointData>::const_iterator it(data.begin());
190 for (; it != data.end(); ++it) {
191 KoPathShape *pathShape = it->m_pointData.pathShape;
192 KoPathPoint *point = pathShape->pointByIndex(it->m_pointData.pointIndex);
193
194 point->setProperties(it->m_oldProperties);
195 if (it->m_hadControlPoint1)
196 point->setControlPoint1(pathShape->documentToShape(it->m_oldControlPoint1));
197 else
198 point->removeControlPoint1();
199 if (it->m_hadControlPoint2)
200 point->setControlPoint2(pathShape->documentToShape(it->m_oldControlPoint2));
201 else
202 point->removeControlPoint2();
203 }
204}
205
207{
208 KoPathPoint *point = data.pathShape->pointByIndex(data.pointIndex);
209 if (! point)
210 return false;
211
212 PointData pointData(data);
213 pointData.m_oldControlPoint1 = data.pathShape->shapeToDocument(point->controlPoint1());
214 pointData.m_oldControlPoint2 = data.pathShape->shapeToDocument(point->controlPoint2());
215 pointData.m_oldProperties = point->properties();
216 pointData.m_hadControlPoint1 = point->activeControlPoint1();
217 pointData.m_hadControlPoint2 = point->activeControlPoint2();
218
219 m_additionalPointData.append(pointData);
220
221 return true;
222}
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
virtual void undo()
void setText(const KUndo2MagicString &text)
virtual void redo()
the base command for commands altering a path shape
QSet< KoPathShape * > m_shapes
the shapes the command operates on
void repaint(bool normalizeShapes)
Describe a KoPathPoint by a KoPathShape and its indices.
KoPathPointIndex pointIndex
position of the point in the path shape
KoPathShape * pathShape
path shape the path point belongs too
void undo() override
revert the actions done in redo
static void makeCubicPointSmooth(KoPathPoint *point)
QList< PointData > m_additionalPointData
void redo() override
redo the command
PointType
The type of the point.
QList< PointData > m_oldPointData
bool appendPointData(KoPathPointData data)
KoPathPointTypeCommand(const QList< KoPathPointData > &pointDataList, PointType pointType, KUndo2Command *parent=0)
void undoChanges(const QList< PointData > &data)
A KoPathPoint represents a point in a path.
PointProperties properties
void setProperties(PointProperties properties)
Set the properties of a point.
void setControlPoint1(const QPointF &point)
Set the control point 1.
QPointF point
void setControlPoint2(const QPointF &point)
Set the control point 2.
void removeControlPoint1()
Removes the first control point.
QPointF controlPoint1
@ IsSmooth
it is smooth, both control points on a line through the point
Definition KoPathPoint.h:41
@ IsSymmetric
it is symmetric, like smooth but control points have same distance to point
Definition KoPathPoint.h:42
bool activeControlPoint1
void removeControlPoint2()
Removes the second control point.
bool activeControlPoint2
QPointF controlPoint2
A KoPathSegment consist of two neighboring KoPathPoints.
KoPathPoint * first
KoPathPoint * second
KoPathSegment toCubic() const
Returns cubic bezier curve segment of this segment.
The position of a path point within a path shape.
Definition KoPathShape.h:63
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.
QPointF shapeToDocument(const QPointF &point) const
Transforms point from shape coordinates to document coordinates.
Definition KoShape.cpp:1201
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1211
KUndo2MagicString kundo2_i18n(const char *text)
KoPathPoint::PointProperties m_oldProperties