Krita Source Code Documentation
Loading...
Searching...
No Matches
KarbonSimplifyPath Namespace Reference

Functions

bool isSufficientlyFlat (QPointF curve[4])
 
void mergeSubpaths (QList< KoSubpath * > subpaths, KoPathShape *path)
 
void removeDuplicates (KoPathShape *path)
 
void simplifySubpath (KoSubpath *subpath, qreal error)
 
void simplifySubpaths (QList< KoSubpath * > *subpaths, qreal error)
 
QList< KoSubpath * > split (const KoPathShape &path)
 
void subdivide (KoSubpath *subpath)
 
KoSubpath subdivideAux (KoPathPoint *p1, KoPathPoint *p2)
 

Variables

const int MAX_RECURSIVE_DEPTH = 1024
 
int recursiveDepth
 
const qreal SUBDIVISION_COEFF = 100
 

Function Documentation

◆ isSufficientlyFlat()

bool KarbonSimplifyPath::isSufficientlyFlat ( QPointF curve[4])

Definition at line 201 of file KarbonSimplifyPath.cpp.

202{
203 qreal ux = 3 * curve[1].x() - 2 * curve[0].x() - curve[3].x();
204 qreal uy = 3 * curve[1].y() - 2 * curve[0].y() - curve[3].y();
205 qreal vx = 3 * curve[2].x() - 2 * curve[3].x() - curve[0].x();
206 qreal vy = 3 * curve[2].x() - 2 * curve[3].x() - curve[0].x();
207
208 // calculate the square of the distance between the points
209 qreal dx = curve[0].x() - curve[3].y();
210 qreal dy = curve[0].y() - curve[3].y();
211 qreal dist2 = dx * dx + dy * dy;
212 qreal max2 = qMax(ux * ux, vx * vx) + qMax(uy * uy, vy * vy);
214
215 return max2 <= dist2;
216}

References SUBDIVISION_COEFF.

◆ mergeSubpaths()

void KarbonSimplifyPath::mergeSubpaths ( QList< KoSubpath * > subpaths,
KoPathShape * path )

Definition at line 249 of file KarbonSimplifyPath.cpp.

250{
251 path->clear();
252 path->moveTo(subpaths.first()->first()->point());
253
254 // TODO: to make the code more readable use foreach and explicit
255 // counters with full name
256 // si: subpath index, pi: point index
257 for (int si = 0; si < subpaths.size(); ++si) {
258 for (int pi = 1; pi < subpaths[si]->size(); ++pi) {
259 KoPathPoint *point = (*subpaths[si])[pi];
260 path->lineTo(point->point());
261
262 // set the first control point
263 KoPathPointIndex index(0, path->pointCount() - 1);
264 KoPathPoint *p = path->pointByIndex(index);
265 if (point->activeControlPoint1()) {
267 }
268
269 // set the second control point of the previous point
270 index = KoPathPointIndex(0, path->pointCount() - 2);
271 p = path->pointByIndex(index);
272 KoPathPoint *prev = (*subpaths[si])[pi - 1];
273 if (prev->activeControlPoint2()) {
275 }
276 }
277 }
278}
const Params2D p
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
A KoPathPoint represents a point in a path.
void setControlPoint1(const QPointF &point)
Set the control point 1.
QPointF point
void setControlPoint2(const QPointF &point)
Set the control point 2.
QPointF controlPoint1
bool activeControlPoint1
bool activeControlPoint2
QPointF controlPoint2

References KoPathPoint::activeControlPoint1, KoPathPoint::activeControlPoint2, KoPathShape::clear(), KoPathPoint::controlPoint1, KoPathPoint::controlPoint2, p, KoPathPoint::point, KoPathPoint::setControlPoint1(), and KoPathPoint::setControlPoint2().

◆ removeDuplicates()

void KarbonSimplifyPath::removeDuplicates ( KoPathShape * path)

Definition at line 93 of file KarbonSimplifyPath.cpp.

94{
95 // NOTE: works because path has only has one subshape, if this ever moves in
96 // KoPathPoint it should be changed
97 for (int i = 1; i < path->pointCount(); ++i) {
98 KoPathPoint *p = path->pointByIndex(KoPathPointIndex(0, i));
99 KoPathPoint *prev = path->pointByIndex(KoPathPointIndex(0, i - 1));
100 QPointF diff = p->point() - prev->point();
101 // if diff = 0 remove point
102 if (qFuzzyCompare(diff.x() + 1, 1) && qFuzzyCompare(diff.y() + 1, 1)) {
103 if (prev->activeControlPoint1()) {
104 p->setControlPoint1(prev->controlPoint1());
105 } else {
106 p->removeControlPoint1();
107 }
108 delete path->removePoint(KoPathPointIndex(0, i - 1));
109 --i;
110 }
111 }
112}
static bool qFuzzyCompare(half p1, half p2)

References KoPathPoint::activeControlPoint1, KoPathPoint::controlPoint1, p, KoPathPoint::point, and qFuzzyCompare().

◆ simplifySubpath()

void KarbonSimplifyPath::simplifySubpath ( KoSubpath * subpath,
qreal error )

Definition at line 228 of file KarbonSimplifyPath.cpp.

229{
230 QList<QPointF> points;
231
232 for (int i = 0; i < subpath->size(); ++i) {
233 points.append((*subpath)[i]->point());
234 }
235
236 KoPathShape *simplified = bezierFit(points, error);
237
238 qDeleteAll(*subpath);
239 subpath->clear();
240
241 for (int i = 0; i < simplified->pointCount(); ++i) {
242 KoPathPointIndex index(0, i);
243 subpath->append(new KoPathPoint(*simplified->pointByIndex(index)));
244 }
245 //res->setPosition( position() );
246 delete simplified;
247}
KoPathShape * bezierFit(const QList< QPointF > &points, float error)
The position of a path point within a path shape.
Definition KoPathShape.h:63
int pointCount() const
Returns the number of points in the path.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.

References bezierFit(), KoPathShape::pointByIndex(), and KoPathShape::pointCount().

◆ simplifySubpaths()

void KarbonSimplifyPath::simplifySubpaths ( QList< KoSubpath * > * subpaths,
qreal error )

Definition at line 218 of file KarbonSimplifyPath.cpp.

220{
221 Q_FOREACH (KoSubpath *subpath, *subpaths) {
222 if (subpath->size() > 2) {
223 simplifySubpath(subpath, error);
224 }
225 }
226}
void simplifySubpath(KoSubpath *subpath, qreal error)

References simplifySubpath().

◆ split()

QList< KoSubpath * > KarbonSimplifyPath::split ( const KoPathShape & path)

Definition at line 114 of file KarbonSimplifyPath.cpp.

115{
117 KoSubpath *subpath = new KoSubpath;
118 res.append(subpath);
119
120 for (int i = 0; i < path.pointCount(); ++i) {
121 KoPathPoint *p = path.pointByIndex(KoPathPointIndex(0, i));
122 // if the path separates two subpaths
123 // (if it isn't smooth nor the first or last point)
124 if (i != 0 && i != path.pointCount() - 1) {
125 KoPathPoint *prev = path.pointByIndex(KoPathPointIndex(0, i - 1));
126 KoPathPoint *next = path.pointByIndex(KoPathPointIndex(0, i + 1));
127 if (!p->isSmooth(prev, next)) {
128 // create a new subpath
129 subpath->append(new KoPathPoint(*p));
130 subpath = new KoSubpath;
131 res.append(subpath);
132 }
133 }
134 subpath->append(new KoPathPoint(*p));
135 }
136
137 return res;
138}
QList< KoPathPoint * > KoSubpath
a KoSubpath contains a path from a moveTo until a close or a new moveTo
Definition KoPathShape.h:31

References p.

◆ subdivide()

void KarbonSimplifyPath::subdivide ( KoSubpath * subpath)

Definition at line 140 of file KarbonSimplifyPath.cpp.

141{
142 for (int i = 1; i < subpath->size(); ++i) {
143 recursiveDepth = 0;
144 KoSubpath newPoints = subdivideAux((*subpath)[i - 1], (*subpath)[i]);
145 Q_FOREACH (KoPathPoint *p, newPoints) {
146 subpath->insert(i, p);
147 ++i;
148 }
149 }
150}
KoSubpath subdivideAux(KoPathPoint *p1, KoPathPoint *p2)

References p, recursiveDepth, and subdivideAux().

◆ subdivideAux()

KoSubpath KarbonSimplifyPath::subdivideAux ( KoPathPoint * p1,
KoPathPoint * p2 )

Definition at line 152 of file KarbonSimplifyPath.cpp.

154{
155 if (!p1->activeControlPoint1() && !p2->activeControlPoint2()) {
156 return QList<KoPathPoint *>();
157 }
158
159 QPointF curve[4] = {
160 p1->point(),
161 p1->activeControlPoint2() ? p1->controlPoint2() : p1->point(),
162 p2->activeControlPoint1() ? p2->controlPoint1() : p2->point(),
163 p2->point()
164 };
165
166 // if there is no need to add points do nothing
167 if (isSufficientlyFlat(curve)) {
168 return QList<KoPathPoint *>();
169 }
170
173 qDebug() << "reached MAX_RECURSIVE_DEPTH";
175 return QList<KoPathPoint *>();
176 }
177
178 // calculate the new point using the de Casteljau algorithm
179 QPointF p[3];
180
181 for (unsigned short j = 1; j <= 3; ++j) {
182 for (unsigned short i = 0; i <= 3 - j; ++i) {
183 curve[i] = (curve[i] + curve[i + 1]) / 2.0;
184 }
185 // modify the new segment.
186 p[j - 1] = curve[0];
187 }
188
189 KoPathPoint *pm = new KoPathPoint(0, p[2]);
190 pm->setControlPoint1(p[1]);
191 pm->setControlPoint2(curve[1]);
192 p1->setControlPoint2(p[0]);
193 p2->setControlPoint1(curve[2]);
194
195 KoSubpath res;
196 res << subdivideAux(p1, pm) << pm << subdivideAux(pm, p2);
198 return res;
199}
QPointF p2
QPointF p1
bool isSufficientlyFlat(QPointF curve[4])

References isSufficientlyFlat(), MAX_RECURSIVE_DEPTH, p, p1, p2, recursiveDepth, KoPathPoint::setControlPoint1(), KoPathPoint::setControlPoint2(), and subdivideAux().

Variable Documentation

◆ MAX_RECURSIVE_DEPTH

const int KarbonSimplifyPath::MAX_RECURSIVE_DEPTH = 1024

Definition at line 32 of file KarbonSimplifyPath.cpp.

◆ recursiveDepth

int KarbonSimplifyPath::recursiveDepth

Definition at line 33 of file KarbonSimplifyPath.cpp.

◆ SUBDIVISION_COEFF

const qreal KarbonSimplifyPath::SUBDIVISION_COEFF = 100

Definition at line 31 of file KarbonSimplifyPath.cpp.