QGIS API Documentation 3.29.0-Master (8c80f25a4f)
qgsmodelsnapper.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmodelsnapper.cpp
3 --------------------
4 begin : March 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#include "qgsmodelsnapper.h"
18#include "qgssettings.h"
19#include <cmath>
20
22{
23 const QgsSettings s;
24 mTolerance = s.value( QStringLiteral( "/Processing/Modeler/snapTolerancePixels" ), 40 ).toInt();
25}
26
27void QgsModelSnapper::setSnapTolerance( const int snapTolerance )
28{
29 mTolerance = snapTolerance;
30}
31
33{
34 mSnapToGrid = enabled;
35}
36
37QPointF QgsModelSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
38{
39 snapped = false;
40
41 bool snappedXToGrid = false;
42 bool snappedYToGrid = false;
43 const QPointF res = snapPointToGrid( point, scaleFactor, snappedXToGrid, snappedYToGrid );
44 if ( snappedXToGrid && snapVertical )
45 {
46 snapped = true;
47 point.setX( res.x() );
48 }
49 if ( snappedYToGrid && snapHorizontal )
50 {
51 snapped = true;
52 point.setY( res.y() );
53 }
54
55 return point;
56}
57
58QRectF QgsModelSnapper::snapRect( const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
59{
60 snapped = false;
61 QRectF snappedRect = rect;
62
63 bool snappedXToGrid = false;
64 bool snappedYToGrid = false;
65 QList< QPointF > points;
66 points << rect.topLeft() << rect.topRight() << rect.bottomLeft() << rect.bottomRight();
67 const QPointF res = snapPointsToGrid( points, scaleFactor, snappedXToGrid, snappedYToGrid );
68 if ( snappedXToGrid && snapVertical )
69 {
70 snapped = true;
71 snappedRect.translate( res.x(), 0 );
72 }
73 if ( snappedYToGrid && snapHorizontal )
74 {
75 snapped = true;
76 snappedRect.translate( 0, res.y() );
77 }
78
79 return snappedRect;
80}
81
82QRectF QgsModelSnapper::snapRectWithResize( const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
83{
84 snapped = false;
85 QRectF snappedRect = rect;
86
87 bool snappedXToGrid = false;
88 bool snappedYToGrid = false;
89 QPointF res = snapPointsToGrid( QList< QPointF >() << rect.topLeft(), scaleFactor, snappedXToGrid, snappedYToGrid );
90 if ( snappedXToGrid && snapVertical )
91 {
92 snapped = true;
93 snappedRect.setLeft( snappedRect.left() + res.x() );
94 }
95 if ( snappedYToGrid && snapHorizontal )
96 {
97 snapped = true;
98 snappedRect.setTop( snappedRect.top() + res.y() );
99 }
100 res = snapPointsToGrid( QList< QPointF >() << rect.bottomRight(), scaleFactor, snappedXToGrid, snappedYToGrid );
101 if ( snappedXToGrid && snapVertical )
102 {
103 snapped = true;
104 snappedRect.setRight( snappedRect.right() + res.x() );
105 }
106 if ( snappedYToGrid && snapHorizontal )
107 {
108 snapped = true;
109 snappedRect.setBottom( snappedRect.bottom() + res.y() );
110 }
111
112 return snappedRect;
113}
114
115QPointF QgsModelSnapper::snapPointToGrid( QPointF point, double scaleFactor, bool &snappedX, bool &snappedY ) const
116{
117 const QPointF delta = snapPointsToGrid( QList< QPointF >() << point, scaleFactor, snappedX, snappedY );
118 return point + delta;
119}
120
121QPointF QgsModelSnapper::snapPointsToGrid( const QList<QPointF> &points, double scaleFactor, bool &snappedX, bool &snappedY ) const
122{
123 snappedX = false;
124 snappedY = false;
125 if ( !mSnapToGrid )
126 {
127 return QPointF( 0, 0 );
128 }
129#if 0
130 const QgsLayoutGridSettings &grid = mLayout->gridSettings();
131 if ( grid.resolution().length() <= 0 )
132 return QPointF( 0, 0 );
133#endif
134
135 double deltaX = 0;
136 double deltaY = 0;
137 double smallestDiffX = std::numeric_limits<double>::max();
138 double smallestDiffY = std::numeric_limits<double>::max();
139 for ( const QPointF point : points )
140 {
141 //snap x coordinate
142 const double gridRes = 30; //mLayout->convertToLayoutUnits( grid.resolution() );
143 int xRatio = static_cast< int >( ( point.x() ) / gridRes + 0.5 ); //NOLINT
144 int yRatio = static_cast< int >( ( point.y() ) / gridRes + 0.5 ); //NOLINT
145
146 const double xSnapped = xRatio * gridRes;
147 const double ySnapped = yRatio * gridRes;
148
149 const double currentDiffX = std::fabs( xSnapped - point.x() );
150 if ( currentDiffX < smallestDiffX )
151 {
152 smallestDiffX = currentDiffX;
153 deltaX = xSnapped - point.x();
154 }
155
156 const double currentDiffY = std::fabs( ySnapped - point.y() );
157 if ( currentDiffY < smallestDiffY )
158 {
159 smallestDiffY = currentDiffY;
160 deltaY = ySnapped - point.y();
161 }
162 }
163
164 //convert snap tolerance from pixels to layout units
165 const double alignThreshold = mTolerance / scaleFactor;
166
167 QPointF delta( 0, 0 );
168 if ( smallestDiffX <= alignThreshold )
169 {
170 //snap distance is inside of tolerance
171 snappedX = true;
172 delta.setX( deltaX );
173 }
174 if ( smallestDiffY <= alignThreshold )
175 {
176 //snap distance is inside of tolerance
177 snappedY = true;
178 delta.setY( deltaY );
179 }
180
181 return delta;
182}
Contains settings relating to the appearance, spacing and offset for layout grids.
QgsLayoutMeasurement resolution() const
Returns the page/snap grid resolution.
double length() const
Returns the length of the measurement.
int snapTolerance() const
Returns the snap tolerance (in pixels) to use when snapping.
void setSnapTolerance(int snapTolerance)
Sets the snap tolerance (in pixels) to use when snapping.
QPointF snapPointsToGrid(const QList< QPointF > &points, double scaleFactor, bool &snappedX, bool &snappedY) const
Snaps a set of points to the grid.
QRectF snapRect(const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate rect.
QgsModelSnapper()
Constructor for QgsModelSnapper, attached to the specified layout.
QPointF snapPoint(QPointF point, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate point.
QRectF snapRectWithResize(const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate rect.
QPointF snapPointToGrid(QPointF point, double scaleFactor, bool &snappedX, bool &snappedY) const
Snaps a layout coordinate point to the grid.
void setSnapToGrid(bool enabled)
Sets whether snapping to grid is enabled.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.