Krita Source Code Documentation
Loading...
Searching...
No Matches
KoSnapStrategy.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2008 Jan Hambrecht <jaham@gmx.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "KoSnapStrategy.h"
8#include "KoSnapProxy.h"
9#include "KoSnapGuide.h"
10#include <KoPathShape.h>
11#include <KoPathPoint.h>
12#include <KoPathSegment.h>
13#include <KoCanvasBase.h>
14#include <KoViewConverter.h>
15
16#include <QPainter>
17#include <QPainterPath>
18
19#include <cmath>
20
21#if defined(_MSC_VER) && (_MSC_VER < 1800)
22#define isfinite(x) (double)(x)
23#endif
24
26 : m_snapStrategyType(type)
27{
28}
29
31{
32 return m_snappedPosition;
33}
34
39
40void KoSnapStrategy::setSnappedPosition(const QPointF &position, SnapType snapType)
41{
42 m_snappedPosition = position;
43 m_snappedType = snapType;
44}
45
50
51qreal KoSnapStrategy::squareDistance(const QPointF &p1, const QPointF &p2)
52{
53 const qreal dx = p1.x() - p2.x();
54 const qreal dy = p1.y() - p2.y();
55
56 return dx*dx + dy*dy;
57}
58
59qreal KoSnapStrategy::scalarProduct(const QPointF &p1, const QPointF &p2)
60{
61 return p1.x() * p2.x() + p1.y() * p2.y();
62}
63
68
69bool OrthogonalSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
70{
71 Q_ASSERT(std::isfinite(maxSnapDistance));
72 QPointF horzSnap, vertSnap;
73 qreal minVertDist = HUGE_VAL;
74 qreal minHorzDist = HUGE_VAL;
75
76 QList<KoShape*> shapes = proxy->shapes(true);
77 Q_FOREACH (KoShape * shape, shapes) {
78 QList<QPointF> points = proxy->pointsFromShape(shape);
79 foreach (const QPointF &point, points) {
80 qreal dx = fabs(point.x() - mousePosition.x());
81 if (dx < minHorzDist && dx < maxSnapDistance) {
82 minHorzDist = dx;
83 horzSnap = point;
84 }
85 qreal dy = fabs(point.y() - mousePosition.y());
86 if (dy < minVertDist && dy < maxSnapDistance) {
87 minVertDist = dy;
88 vertSnap = point;
89 }
90 }
91 }
92
93 QPointF snappedPoint = mousePosition;
95
96 if (minHorzDist < HUGE_VAL)
97 snappedPoint.setX(horzSnap.x());
98 if (minVertDist < HUGE_VAL)
99 snappedPoint.setY(vertSnap.y());
100
101 if (minHorzDist < HUGE_VAL) {
102 m_hLine = QLineF(horzSnap, snappedPoint);
103 } else {
104 m_hLine = QLineF();
106 }
107
108 if (minVertDist < HUGE_VAL) {
109 m_vLine = QLineF(vertSnap, snappedPoint);
110 } else {
111 m_vLine = QLineF();
113 }
114
115 setSnappedPosition(snappedPoint, snappedType);
116
117 return (minHorzDist < HUGE_VAL || minVertDist < HUGE_VAL);
118}
119
120QPainterPath OrthogonalSnapStrategy::decoration(const KoViewConverter &/*converter*/) const
121{
122 QPainterPath decoration;
123 if (! m_hLine.isNull()) {
124 decoration.moveTo(m_hLine.p1());
125 decoration.lineTo(m_hLine.p2());
126 }
127 if (! m_vLine.isNull()) {
128 decoration.moveTo(m_vLine.p1());
129 decoration.lineTo(m_vLine.p2());
130 }
131 return decoration;
132}
133
138
139bool NodeSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
140{
141 Q_ASSERT(std::isfinite(maxSnapDistance));
142 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
143 qreal minDistance = HUGE_VAL;
144
145 QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
146 rect.moveCenter(mousePosition);
147 QList<QPointF> points = proxy->pointsInRect(rect, false);
148 QPointF snappedPoint = mousePosition;
149
150 foreach (const QPointF &point, points) {
151 qreal distance = squareDistance(mousePosition, point);
152 if (distance < maxDistance && distance < minDistance) {
153 snappedPoint = point;
154 minDistance = distance;
155 }
156 }
157
158 setSnappedPosition(snappedPoint, ToPoint);
159
160 return (minDistance < HUGE_VAL);
161}
162
163QPainterPath NodeSnapStrategy::decoration(const KoViewConverter &converter) const
164{
165 QRectF unzoomedRect = converter.viewToDocument(QRectF(0, 0, 11, 11));
166 unzoomedRect.moveCenter(snappedPosition());
167 QPainterPath decoration;
168 decoration.addEllipse(unzoomedRect);
169 return decoration;
170}
171
176
177bool ExtensionSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
178{
179 Q_ASSERT(std::isfinite(maxSnapDistance));
180
181 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
182 qreal minDistances[2] = { HUGE_VAL, HUGE_VAL };
183
184 QPointF snappedPoints[2] = { mousePosition, mousePosition };
185 QPointF startPoints[2];
186
187 QList<KoShape*> shapes = proxy->shapes(true);
188
189 Q_FOREACH (KoShape * shape, shapes) {
190 KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
191 if (! path) {
192 continue;
193 }
194 QTransform matrix = path->absoluteTransformation();
195
196 const int subpathCount = path->subpathCount();
197 for (int subpathIndex = 0; subpathIndex < subpathCount; ++subpathIndex) {
198 if (path->isClosedSubpath(subpathIndex))
199 continue;
200
201 int pointCount = path->subpathPointCount(subpathIndex);
202
203 // check the extension from the start point
204 KoPathPoint * first = path->pointByIndex(KoPathPointIndex(subpathIndex, 0));
205 QPointF firstSnapPosition = mousePosition;
206 if (snapToExtension(firstSnapPosition, first, matrix)) {
207 qreal distance = squareDistance(firstSnapPosition, mousePosition);
208 if (distance < maxDistance) {
209 if (distance < minDistances[0]) {
210 minDistances[1] = minDistances[0];
211 snappedPoints[1] = snappedPoints[0];
212 startPoints[1] = startPoints[0];
213
214 minDistances[0] = distance;
215 snappedPoints[0] = firstSnapPosition;
216 startPoints[0] = matrix.map(first->point());
217 }
218 else if (distance < minDistances[1]) {
219 minDistances[1] = distance;
220 snappedPoints[1] = firstSnapPosition;
221 startPoints[1] = matrix.map(first->point());
222 }
223 }
224 }
225
226 // now check the extension from the last point
227 KoPathPoint * last = path->pointByIndex(KoPathPointIndex(subpathIndex, pointCount - 1));
228 QPointF lastSnapPosition = mousePosition;
229 if (snapToExtension(lastSnapPosition, last, matrix)) {
230 qreal distance = squareDistance(lastSnapPosition, mousePosition);
231 if (distance < maxDistance) {
232 if (distance < minDistances[0]) {
233 minDistances[1] = minDistances[0];
234 snappedPoints[1] = snappedPoints[0];
235 startPoints[1] = startPoints[0];
236
237 minDistances[0] = distance;
238 snappedPoints[0] = lastSnapPosition;
239 startPoints[0] = matrix.map(last->point());
240 }
241 else if (distance < minDistances[1]) {
242 minDistances[1] = distance;
243 snappedPoints[1] = lastSnapPosition;
244 startPoints[1] = matrix.map(last->point());
245 }
246 }
247 }
248 }
249 }
250
251 m_lines.clear();
252 // if we have to extension near our mouse position, they might have an intersection
253 // near our mouse position which we want to use as the snapped position
254 if (minDistances[0] < HUGE_VAL && minDistances[1] < HUGE_VAL) {
255 // check if intersection of extension lines is near mouse position
256 KoPathSegment s1(startPoints[0], snappedPoints[0] + snappedPoints[0]-startPoints[0]);
257 KoPathSegment s2(startPoints[1], snappedPoints[1] + snappedPoints[1]-startPoints[1]);
258 QList<QPointF> isects = s1.intersections(s2);
259 if (isects.count() == 1 && squareDistance(isects[0], mousePosition) < maxDistance) {
260 // add both extension lines
261 m_lines.append(QLineF(startPoints[0], isects[0]));
262 m_lines.append(QLineF(startPoints[1], isects[0]));
263 setSnappedPosition(isects[0], ToLine);
264 }
265 else {
266 // only add nearest extension line of both
267 uint index = minDistances[0] < minDistances[1] ? 0 : 1;
268 m_lines.append(QLineF(startPoints[index], snappedPoints[index]));
269 setSnappedPosition(snappedPoints[index], ToLine);
270 }
271 }
272 else if (minDistances[0] < HUGE_VAL) {
273 m_lines.append(QLineF(startPoints[0], snappedPoints[0]));
274 setSnappedPosition(snappedPoints[0], ToLine);
275 }
276 else if (minDistances[1] < HUGE_VAL) {
277 m_lines.append(QLineF(startPoints[1], snappedPoints[1]));
278 setSnappedPosition(snappedPoints[1], ToLine);
279 }
280 else {
281 // none of the extension lines is near our mouse position
282 return false;
283 }
284 return true;
285}
286
287QPainterPath ExtensionSnapStrategy::decoration(const KoViewConverter &/*converter*/) const
288{
289 QPainterPath decoration;
290 foreach (const QLineF &line, m_lines) {
291 decoration.moveTo(line.p1());
292 decoration.lineTo(line.p2());
293 }
294 return decoration;
295}
296
297bool ExtensionSnapStrategy::snapToExtension(QPointF &position, KoPathPoint * point, const QTransform &matrix)
298{
299 Q_ASSERT(point);
300 QPointF direction = extensionDirection(point, matrix);
301 if (direction.isNull())
302 return false;
303
304 QPointF extensionStart = matrix.map(point->point());
305 QPointF extensionStop = matrix.map(point->point()) + direction;
306 float posOnExtension = project(extensionStart, extensionStop, position);
307 if (posOnExtension < 0.0)
308 return false;
309
310 position = extensionStart + posOnExtension * direction;
311 return true;
312}
313
314qreal ExtensionSnapStrategy::project(const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point)
315{
316 // This is how the returned value should be used to get the
317 // projectionPoint: ProjectionPoint = lineStart(1-resultingReal) + resultingReal*lineEnd;
318
319 QPointF diff = lineEnd - lineStart;
320 QPointF relPoint = point - lineStart;
321 qreal diffLength = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
322 if (diffLength == 0.0)
323 return 0.0;
324
325 diff /= diffLength;
326 // project mouse position relative to stop position on extension line
327 qreal scalar = relPoint.x() * diff.x() + relPoint.y() * diff.y();
328 return scalar /= diffLength;
329}
330
331QPointF ExtensionSnapStrategy::extensionDirection(KoPathPoint * point, const QTransform &matrix)
332{
333 Q_ASSERT(point);
334
335 KoPathShape * path = point->parent();
336 KoPathPointIndex index = path->pathPointIndex(point);
337
338 // check if it is a start point
339 if (point->properties() & KoPathPoint::StartSubpath) {
340 if (point->activeControlPoint2()) {
341 return matrix.map(point->point()) - matrix.map(point->controlPoint2());
342 } else {
343 KoPathPoint * next = path->pointByIndex(KoPathPointIndex(index.first, index.second + 1));
344 if (! next){
345 return QPointF();
346 }
347 else if (next->activeControlPoint1()) {
348 return matrix.map(point->point()) - matrix.map(next->controlPoint1());
349 }
350 else {
351 return matrix.map(point->point()) - matrix.map(next->point());
352 }
353 }
354 }
355 else {
356 if (point->activeControlPoint1()) {
357 return matrix.map(point->point()) - matrix.map(point->controlPoint1());
358 }
359 else {
360 KoPathPoint * prev = path->pointByIndex(KoPathPointIndex(index.first, index.second - 1));
361 if (! prev){
362 return QPointF();
363 }
364 else if (prev->activeControlPoint2()) {
365 return matrix.map(point->point()) - matrix.map(prev->controlPoint2());
366 }
367 else {
368 return matrix.map(point->point()) - matrix.map(prev->point());
369 }
370 }
371 }
372}
373
378
379bool IntersectionSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
380{
381 Q_ASSERT(std::isfinite(maxSnapDistance));
382 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
383 qreal minDistance = HUGE_VAL;
384
385 QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
386 rect.moveCenter(mousePosition);
387 QPointF snappedPoint = mousePosition;
388
389 QList<KoPathSegment> segments = proxy->segmentsInRect(rect, false);
390 int segmentCount = segments.count();
391 for (int i = 0; i < segmentCount; ++i) {
392 const KoPathSegment &s1 = segments[i];
393 for (int j = i + 1; j < segmentCount; ++j) {
394 QList<QPointF> isects = s1.intersections(segments[j]);
395 Q_FOREACH (const QPointF &point, isects) {
396 if (! rect.contains(point))
397 continue;
398 qreal distance = squareDistance(mousePosition, point);
399 if (distance < maxDistance && distance < minDistance) {
400 snappedPoint = point;
401 minDistance = distance;
402 }
403 }
404 }
405 }
406
407 setSnappedPosition(snappedPoint, ToPoint);
408
409 return (minDistance < HUGE_VAL);
410}
411
412QPainterPath IntersectionSnapStrategy::decoration(const KoViewConverter &converter) const
413{
414 QRectF unzoomedRect = converter.viewToDocument(QRectF(0, 0, 11, 11));
415 unzoomedRect.moveCenter(snappedPosition());
416 QPainterPath decoration;
417 decoration.addRect(unzoomedRect);
418 return decoration;
419}
420
425
426bool GridSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
427{
428 Q_ASSERT(std::isfinite(maxSnapDistance));
429 if (! proxy->canvas()->snapToGrid())
430 return false;
431
432 // The 1e-10 here is a workaround for some weird division problem.
433 // 360.00062366 / 2.83465058 gives 127 'exactly' when shown as a qreal,
434 // but when casting into an int, we get 126. In fact it's 127 - 5.64e-15 !
435 QPointF offset;
436 QSizeF spacing;
437 proxy->canvas()->gridSize(&offset, &spacing);
438
439 // we want to snap to the nearest grid point, so calculate
440 // the grid rows/columns before and after the points position
441 int col = static_cast<int>((mousePosition.x() - offset.x()) / spacing.width() + 1e-10);
442 int nextCol = col + 1;
443 int row = static_cast<int>((mousePosition.y() - offset.y()) / spacing.height() + 1e-10);
444 int nextRow = row + 1;
445
446 // now check which grid line has less distance to the point
447 qreal distToCol = qAbs(offset.x() + col * spacing.width() - mousePosition.x());
448 qreal distToNextCol = qAbs(offset.x() + nextCol * spacing.width() - mousePosition.x());
449
450 if (distToCol > distToNextCol) {
451 col = nextCol;
452 distToCol = distToNextCol;
453 }
454
455 qreal distToRow = qAbs(offset.y() + row * spacing.height() - mousePosition.y());
456 qreal distToNextRow = qAbs(offset.y() + nextRow * spacing.height() - mousePosition.y());
457 if (distToRow > distToNextRow) {
458 row = nextRow;
459 distToRow = distToNextRow;
460 }
461
462 QPointF snappedPoint = mousePosition;
463 SnapType snapType = ToPoint;
464
465 bool pointIsSnapped = false;
466
467 const qreal sqDistance = distToCol * distToCol + distToRow * distToRow;
468 const qreal maxSqDistance = maxSnapDistance * maxSnapDistance;
469 // now check if we are inside the snap distance
470 if (sqDistance < maxSqDistance) {
471 snappedPoint = QPointF(offset.x() + col * spacing.width(), offset.y() + row * spacing.height());
472 pointIsSnapped = true;
473 } else if (distToRow < maxSnapDistance) {
474 snappedPoint.ry() = offset.y() + row * spacing.height();
475 snapType = ToLine;
476 pointIsSnapped = true;
477 } else if (distToCol < maxSnapDistance) {
478 snappedPoint.rx() = offset.x() + col * spacing.width();
479 snapType = ToLine;
480 pointIsSnapped = true;
481 }
482
483 setSnappedPosition(snappedPoint, snapType);
484
485 return pointIsSnapped;
486}
487
488QPainterPath GridSnapStrategy::decoration(const KoViewConverter &converter) const
489{
490 QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
491 QPainterPath decoration;
492 decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0));
493 decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0));
494 decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height()));
495 decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height()));
496 return decoration;
497}
498
503
504bool BoundingBoxSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
505{
506 Q_ASSERT(std::isfinite(maxSnapDistance));
507 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
508 qreal minDistance = HUGE_VAL;
509
510 QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
511
512 rect.moveCenter(mousePosition);
513 QPointF snappedPoint = mousePosition;
514 SnapType snapType = ToPoint;
515
516 KoFlake::AnchorPosition pointId[5] = {
522 };
523
524 QList<KoShape*> shapes = proxy->shapesInRect(rect, true);
525 Q_FOREACH (KoShape * shape, shapes) {
526 qreal shapeMinDistance = HUGE_VAL;
527 // first check the corner and center points
528 for (int i = 0; i < 5; ++i) {
529 m_boxPoints[i] = shape->absolutePosition(pointId[i]);
530 qreal d = squareDistance(mousePosition, m_boxPoints[i]);
531 if (d < minDistance && d < maxDistance) {
532 shapeMinDistance = d;
533 minDistance = d;
534 snappedPoint = m_boxPoints[i];
535 snapType = ToPoint;
536 }
537 }
538 // prioritize points over edges
539 if (shapeMinDistance < maxDistance)
540 continue;
541
542 // now check distances to edges of bounding box
543 for (int i = 0; i < 4; ++i) {
544 QPointF pointOnLine;
545 qreal d = squareDistanceToLine(m_boxPoints[i], m_boxPoints[(i+1)%4], mousePosition, pointOnLine);
546 if (d < minDistance && d < maxDistance) {
547 minDistance = d;
548 snappedPoint = pointOnLine;
549 snapType = ToLine;
550 }
551 }
552 }
553 setSnappedPosition(snappedPoint, snapType);
554
555 return (minDistance < maxDistance);
556}
557
558qreal BoundingBoxSnapStrategy::squareDistanceToLine(const QPointF &lineA, const QPointF &lineB, const QPointF &point, QPointF &pointOnLine)
559{
560 QPointF diff = lineB - lineA;
561 if(lineA == lineB)
562 return HUGE_VAL;
563 const qreal diffLength = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
564
565 // project mouse position relative to start position on line
566 const qreal scalar = KoSnapStrategy::scalarProduct(point - lineA, diff / diffLength);
567
568 if (scalar < 0.0 || scalar > diffLength)
569 return HUGE_VAL;
570 // calculate vector between relative mouse position and projected mouse position
571 pointOnLine = lineA + scalar / diffLength * diff;
572 QPointF distVec = pointOnLine - point;
573 return distVec.x()*distVec.x() + distVec.y()*distVec.y();
574}
575
576QPainterPath BoundingBoxSnapStrategy::decoration(const KoViewConverter &converter) const
577{
578 QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
579
580 QPainterPath decoration;
581 decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), unzoomedSize.height()));
582 decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), unzoomedSize.height()));
583 decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), -unzoomedSize.height()));
584 decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), -unzoomedSize.height()));
585
586 return decoration;
587}
588
589// KoGuidesData has been moved into Krita. Please port this class!
590
591// LineGuideSnapStrategy::LineGuideSnapStrategy()
592// : KoSnapStrategy(KoSnapGuide::GuideLineSnapping)
593// {
594// }
595
596// bool LineGuideSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
597// {
598// Q_ASSERT(std::isfinite(maxSnapDistance));
599
600// KoGuidesData * guidesData = proxy->canvas()->guidesData();
601
602// if (!guidesData || !guidesData->showGuideLines())
603// return false;
604
605// QPointF snappedPoint = mousePosition;
606// m_orientation = 0;
607
608// qreal minHorzDistance = maxSnapDistance;
609// Q_FOREACH (qreal guidePos, guidesData->horizontalGuideLines()) {
610// qreal distance = qAbs(guidePos - mousePosition.y());
611// if (distance < minHorzDistance) {
612// snappedPoint.setY(guidePos);
613// minHorzDistance = distance;
614// m_orientation |= Qt::Horizontal;
615// }
616// }
617// qreal minVertSnapDistance = maxSnapDistance;
618// Q_FOREACH (qreal guidePos, guidesData->verticalGuideLines()) {
619// qreal distance = qAbs(guidePos - mousePosition.x());
620// if (distance < minVertSnapDistance) {
621// snappedPoint.setX(guidePos);
622// minVertSnapDistance = distance;
623// m_orientation |= Qt::Vertical;
624// }
625// }
626// setSnappedPosition(snappedPoint);
627// return (minHorzDistance < maxSnapDistance || minVertSnapDistance < maxSnapDistance);
628// }
629
630// QPainterPath LineGuideSnapStrategy::decoration(const KoViewConverter &converter) const
631// {
632// QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
633// Q_ASSERT(unzoomedSize.isValid());
634
635// QPainterPath decoration;
636// if (m_orientation & Qt::Horizontal) {
637// decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0));
638// decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0));
639// }
640// if (m_orientation & Qt::Vertical) {
641// decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height()));
642// decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height()));
643// }
644
645// return decoration;
646// }
QPointF s1
QPointF s2
QPointF p2
QPointF p1
qreal distance(const QPointF &p1, const QPointF &p2)
unsigned int uint
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
qreal squareDistanceToLine(const QPointF &lineA, const QPointF &lineB, const QPointF &point, QPointF &pointOnLine)
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
qreal project(const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point)
QList< QLineF > m_lines
QPointF extensionDirection(KoPathPoint *point, const QTransform &matrix)
bool snapToExtension(QPointF &position, KoPathPoint *point, const QTransform &matrix)
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
virtual void gridSize(QPointF *offset, QSizeF *spacing) const =0
virtual bool snapToGrid() const =0
A KoPathPoint represents a point in a path.
PointProperties properties
QPointF point
QPointF controlPoint1
KoPathShape * parent() const
Get the path shape the point belongs to.
@ StartSubpath
it starts a new subpath by a moveTo command
Definition KoPathPoint.h:38
bool activeControlPoint1
bool activeControlPoint2
QPointF controlPoint2
A KoPathSegment consist of two neighboring KoPathPoints.
The position of a path point within a path shape.
Definition KoPathShape.h:63
KoPathPointIndex pathPointIndex(const KoPathPoint *point) const
Returns the path point index of a given path point.
QPointF absolutePosition(KoFlake::AnchorPosition anchor=KoFlake::Center) const
Definition KoShape.cpp:653
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
Strategy
the different possible snap Strategies
Definition KoSnapGuide.h:49
QList< QPointF > pointsFromShape(KoShape *shape)
returns list of points from given shape
QList< KoShape * > shapesInRect(const QRectF &rect, bool omitEditedShape=false)
returns list of shape in given rectangle in document coordinates
KoCanvasBase * canvas()
returns canvas we are working on
QList< KoPathSegment > segmentsInRect(const QRectF &rect, bool omitEditedShape)
returns list of points in given rectangle in document coordinates
QList< QPointF > pointsInRect(const QRectF &rect, bool omitEditedShape)
returns list of points in given rectangle in document coordinates
QList< KoShape * > shapes(bool omitEditedShape=false)
returns list of all shapes
QPointF m_snappedPosition
void setSnappedPosition(const QPointF &position, SnapType snapType)
sets the current snapped position
SnapType m_snappedType
static qreal squareDistance(const QPointF &p1, const QPointF &p2)
static qreal scalarProduct(const QPointF &p1, const QPointF &p2)
KoSnapGuide::Strategy type() const
returns the strategies type
KoSnapStrategy(KoSnapGuide::Strategy type)
KoSnapGuide::Strategy m_snapStrategyType
SnapType snappedType() const
QPointF snappedPosition() const
returns the snapped position form the last call to snapToPoints
virtual QPointF viewToDocument(const QPointF &viewPoint) const
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
bool snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
AnchorPosition
Definition KoFlake.h:85
@ BottomRight
Definition KoFlake.h:94
@ TopRight
Definition KoFlake.h:88
@ TopLeft
Definition KoFlake.h:86
@ BottomLeft
Definition KoFlake.h:92
@ Center
Definition KoFlake.h:90