Krita Source Code Documentation
Loading...
Searching...
No Matches
ExtensionSnapStrategy Class Reference

snaps extension lines of path shapes More...

#include <KoSnapStrategy.h>

+ Inheritance diagram for ExtensionSnapStrategy:

Public Member Functions

QPainterPath decoration (const KoViewConverter &converter) const override
 returns the current snap strategy decoration
 
 ExtensionSnapStrategy ()
 
bool snap (const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) override
 
- Public Member Functions inherited from KoSnapStrategy
 KoSnapStrategy (KoSnapGuide::Strategy type)
 
QPointF snappedPosition () const
 returns the snapped position form the last call to snapToPoints
 
SnapType snappedType () const
 
KoSnapGuide::Strategy type () const
 returns the strategies type
 
virtual ~KoSnapStrategy ()
 

Private Member Functions

QPointF extensionDirection (KoPathPoint *point, const QTransform &matrix)
 
qreal project (const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point)
 
bool snapToExtension (QPointF &position, KoPathPoint *point, const QTransform &matrix)
 

Private Attributes

QList< QLineF > m_lines
 

Friends

class TestSnapStrategy
 

Additional Inherited Members

- Public Types inherited from KoSnapStrategy
enum  SnapType { ToPoint = 0 , ToLine }
 
- Static Public Member Functions inherited from KoSnapStrategy
static qreal scalarProduct (const QPointF &p1, const QPointF &p2)
 
static qreal squareDistance (const QPointF &p1, const QPointF &p2)
 
- Protected Member Functions inherited from KoSnapStrategy
void setSnappedPosition (const QPointF &position, SnapType snapType)
 sets the current snapped position
 

Detailed Description

snaps extension lines of path shapes

Definition at line 86 of file KoSnapStrategy.h.

Constructor & Destructor Documentation

◆ ExtensionSnapStrategy()

ExtensionSnapStrategy::ExtensionSnapStrategy ( )

Definition at line 172 of file KoSnapStrategy.cpp.

174{
175}
KoSnapStrategy(KoSnapGuide::Strategy type)

Member Function Documentation

◆ decoration()

QPainterPath ExtensionSnapStrategy::decoration ( const KoViewConverter & converter) const
overridevirtual

returns the current snap strategy decoration

Implements KoSnapStrategy.

Definition at line 287 of file KoSnapStrategy.cpp.

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}
QPainterPath decoration(const KoViewConverter &converter) const override
returns the current snap strategy decoration
QList< QLineF > m_lines

References decoration(), and m_lines.

◆ extensionDirection()

QPointF ExtensionSnapStrategy::extensionDirection ( KoPathPoint * point,
const QTransform & matrix )
private

Definition at line 331 of file KoSnapStrategy.cpp.

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}
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
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
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.
QAction * next(const QObject *recvr, const char *slot, QObject *parent)

References KoPathPoint::activeControlPoint1, KoPathPoint::activeControlPoint2, KoPathPoint::controlPoint1, KoPathPoint::controlPoint2, KoPathPoint::parent(), KoPathShape::pathPointIndex(), KoPathPoint::point, KoPathPoint::properties, and KoPathPoint::StartSubpath.

◆ project()

qreal ExtensionSnapStrategy::project ( const QPointF & lineStart,
const QPointF & lineEnd,
const QPointF & point )
private

Definition at line 314 of file KoSnapStrategy.cpp.

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}

◆ snap()

bool ExtensionSnapStrategy::snap ( const QPointF & mousePosition,
KoSnapProxy * proxy,
qreal maxSnapDistance )
overridevirtual

Implements KoSnapStrategy.

Definition at line 177 of file KoSnapStrategy.cpp.

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}
QPointF s1
QPointF s2
qreal distance(const QPointF &p1, const QPointF &p2)
unsigned int uint
bool snapToExtension(QPointF &position, KoPathPoint *point, const QTransform &matrix)
A KoPathSegment consist of two neighboring KoPathPoints.
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
QList< KoShape * > shapes(bool omitEditedShape=false)
returns list of all shapes
void setSnappedPosition(const QPointF &position, SnapType snapType)
sets the current snapped position
static qreal squareDistance(const QPointF &p1, const QPointF &p2)

References KoShape::absoluteTransformation(), distance(), m_lines, KoPathPoint::point, s1, s2, KoSnapStrategy::setSnappedPosition(), KoSnapProxy::shapes(), snapToExtension(), KoSnapStrategy::squareDistance(), and KoSnapStrategy::ToLine.

◆ snapToExtension()

bool ExtensionSnapStrategy::snapToExtension ( QPointF & position,
KoPathPoint * point,
const QTransform & matrix )
private

Definition at line 297 of file KoSnapStrategy.cpp.

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}
qreal project(const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point)
QPointF extensionDirection(KoPathPoint *point, const QTransform &matrix)

References extensionDirection(), KoPathPoint::point, and project().

Friends And Related Symbol Documentation

◆ TestSnapStrategy

friend class TestSnapStrategy
friend

Definition at line 88 of file KoSnapStrategy.h.

Member Data Documentation

◆ m_lines

QList<QLineF> ExtensionSnapStrategy::m_lines
private

Definition at line 97 of file KoSnapStrategy.h.


The documentation for this class was generated from the following files: