17#include <QPainterPath>
21#if defined(_MSC_VER) && (_MSC_VER < 1800)
22#define isfinite(x) (double)(x)
26 : m_snapStrategyType(type)
53 const qreal dx =
p1.x() -
p2.x();
54 const qreal dy =
p1.y() -
p2.y();
61 return p1.x() *
p2.x() +
p1.y() *
p2.y();
71 Q_ASSERT(std::isfinite(maxSnapDistance));
72 QPointF horzSnap, vertSnap;
73 qreal minVertDist = HUGE_VAL;
74 qreal minHorzDist = HUGE_VAL;
77 Q_FOREACH (
KoShape * shape, shapes) {
79 foreach (
const QPointF &point, points) {
80 qreal dx = fabs(point.x() - mousePosition.x());
81 if (dx < minHorzDist && dx < maxSnapDistance) {
85 qreal dy = fabs(point.y() - mousePosition.y());
86 if (dy < minVertDist && dy < maxSnapDistance) {
93 QPointF snappedPoint = mousePosition;
96 if (minHorzDist < HUGE_VAL)
97 snappedPoint.setX(horzSnap.x());
98 if (minVertDist < HUGE_VAL)
99 snappedPoint.setY(vertSnap.y());
101 if (minHorzDist < HUGE_VAL) {
102 m_hLine = QLineF(horzSnap, snappedPoint);
108 if (minVertDist < HUGE_VAL) {
109 m_vLine = QLineF(vertSnap, snappedPoint);
117 return (minHorzDist < HUGE_VAL || minVertDist < HUGE_VAL);
141 Q_ASSERT(std::isfinite(maxSnapDistance));
142 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
143 qreal minDistance = HUGE_VAL;
145 QRectF
rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
146 rect.moveCenter(mousePosition);
148 QPointF snappedPoint = mousePosition;
150 foreach (
const QPointF &point, points) {
153 snappedPoint = point;
160 return (minDistance < HUGE_VAL);
165 QRectF unzoomedRect = converter.
viewToDocument(QRectF(0, 0, 11, 11));
179 Q_ASSERT(std::isfinite(maxSnapDistance));
181 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
182 qreal minDistances[2] = { HUGE_VAL, HUGE_VAL };
184 QPointF snappedPoints[2] = { mousePosition, mousePosition };
185 QPointF startPoints[2];
189 Q_FOREACH (
KoShape * shape, shapes) {
196 const int subpathCount = path->subpathCount();
197 for (
int subpathIndex = 0; subpathIndex < subpathCount; ++subpathIndex) {
198 if (path->isClosedSubpath(subpathIndex))
201 int pointCount = path->subpathPointCount(subpathIndex);
205 QPointF firstSnapPosition = mousePosition;
210 minDistances[1] = minDistances[0];
211 snappedPoints[1] = snappedPoints[0];
212 startPoints[1] = startPoints[0];
215 snappedPoints[0] = firstSnapPosition;
216 startPoints[0] = matrix.map(first->
point());
218 else if (
distance < minDistances[1]) {
220 snappedPoints[1] = firstSnapPosition;
221 startPoints[1] = matrix.map(first->
point());
228 QPointF lastSnapPosition = mousePosition;
233 minDistances[1] = minDistances[0];
234 snappedPoints[1] = snappedPoints[0];
235 startPoints[1] = startPoints[0];
238 snappedPoints[0] = lastSnapPosition;
239 startPoints[0] = matrix.map(last->
point());
241 else if (
distance < minDistances[1]) {
243 snappedPoints[1] = lastSnapPosition;
244 startPoints[1] = matrix.map(last->
point());
254 if (minDistances[0] < HUGE_VAL && minDistances[1] < HUGE_VAL) {
256 KoPathSegment s1(startPoints[0], snappedPoints[0] + snappedPoints[0]-startPoints[0]);
257 KoPathSegment s2(startPoints[1], snappedPoints[1] + snappedPoints[1]-startPoints[1]);
259 if (isects.count() == 1 &&
squareDistance(isects[0], mousePosition) < maxDistance) {
261 m_lines.append(QLineF(startPoints[0], isects[0]));
262 m_lines.append(QLineF(startPoints[1], isects[0]));
267 uint index = minDistances[0] < minDistances[1] ? 0 : 1;
268 m_lines.append(QLineF(startPoints[index], snappedPoints[index]));
272 else if (minDistances[0] < HUGE_VAL) {
273 m_lines.append(QLineF(startPoints[0], snappedPoints[0]));
276 else if (minDistances[1] < HUGE_VAL) {
277 m_lines.append(QLineF(startPoints[1], snappedPoints[1]));
290 foreach (
const QLineF &line,
m_lines) {
301 if (direction.isNull())
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)
310 position = extensionStart + posOnExtension * direction;
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)
327 qreal scalar = relPoint.x() * diff.x() + relPoint.y() * diff.y();
328 return scalar /= diffLength;
347 else if (next->activeControlPoint1()) {
348 return matrix.map(point->
point()) - matrix.map(next->controlPoint1());
351 return matrix.map(point->
point()) - matrix.map(next->point());
368 return matrix.map(point->
point()) - matrix.map(prev->
point());
381 Q_ASSERT(std::isfinite(maxSnapDistance));
382 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
383 qreal minDistance = HUGE_VAL;
385 QRectF
rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
386 rect.moveCenter(mousePosition);
387 QPointF snappedPoint = mousePosition;
390 int segmentCount = segments.count();
391 for (
int i = 0; i < segmentCount; ++i) {
393 for (
int j = i + 1; j < segmentCount; ++j) {
395 Q_FOREACH (
const QPointF &point, isects) {
396 if (!
rect.contains(point))
400 snappedPoint = point;
409 return (minDistance < HUGE_VAL);
414 QRectF unzoomedRect = converter.
viewToDocument(QRectF(0, 0, 11, 11));
428 Q_ASSERT(std::isfinite(maxSnapDistance));
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;
447 qreal distToCol = qAbs(offset.x() + col * spacing.width() - mousePosition.x());
448 qreal distToNextCol = qAbs(offset.x() + nextCol * spacing.width() - mousePosition.x());
450 if (distToCol > distToNextCol) {
452 distToCol = distToNextCol;
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) {
459 distToRow = distToNextRow;
462 QPointF snappedPoint = mousePosition;
465 bool pointIsSnapped =
false;
467 const qreal sqDistance = distToCol * distToCol + distToRow * distToRow;
468 const qreal maxSqDistance = maxSnapDistance * maxSnapDistance;
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();
476 pointIsSnapped =
true;
477 }
else if (distToCol < maxSnapDistance) {
478 snappedPoint.rx() = offset.x() + col * spacing.width();
480 pointIsSnapped =
true;
485 return pointIsSnapped;
506 Q_ASSERT(std::isfinite(maxSnapDistance));
507 const qreal maxDistance = maxSnapDistance * maxSnapDistance;
508 qreal minDistance = HUGE_VAL;
510 QRectF
rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
512 rect.moveCenter(mousePosition);
513 QPointF snappedPoint = mousePosition;
525 Q_FOREACH (
KoShape * shape, shapes) {
526 qreal shapeMinDistance = HUGE_VAL;
528 for (
int i = 0; i < 5; ++i) {
531 if (d < minDistance && d < maxDistance) {
532 shapeMinDistance = d;
539 if (shapeMinDistance < maxDistance)
543 for (
int i = 0; i < 4; ++i) {
546 if (d < minDistance && d < maxDistance) {
548 snappedPoint = pointOnLine;
555 return (minDistance < maxDistance);
560 QPointF diff = lineB - lineA;
563 const qreal diffLength = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
568 if (scalar < 0.0 || scalar > diffLength)
571 pointOnLine = lineA + scalar / diffLength * diff;
572 QPointF distVec = pointOnLine - point;
573 return distVec.x()*distVec.x() + distVec.y()*distVec.y();
qreal distance(const QPointF &p1, const QPointF &p2)
QPair< int, int > KoPathPointIndex
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
BoundingBoxSnapStrategy()
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)
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
IntersectionSnapStrategy()
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
KoPathShape * parent() const
Get the path shape the point belongs to.
@ StartSubpath
it starts a new subpath by a moveTo command
A KoPathSegment consist of two neighboring KoPathPoints.
The position of a path point within a path shape.
KoPathPointIndex pathPointIndex(const KoPathPoint *point) const
Returns the path point index of a given path point.
QPointF absolutePosition(KoFlake::AnchorPosition anchor=KoFlake::Center) const
QTransform absoluteTransformation() const
Strategy
the different possible snap Strategies
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
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