QGIS API Documentation 3.99.0-Master (e9821da5c6b)
Loading...
Searching...
No Matches
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
19#include <cmath>
20
21#include "qgssettings.h"
22
23#include <QString>
24
25using namespace Qt::StringLiterals;
26
28{
29 const QgsSettings s;
30 mTolerance = s.value( u"/Processing/Modeler/snapTolerancePixels"_s, 40 ).toInt();
31}
32
34{
35 mTolerance = snapTolerance;
36}
37
39{
40 mSnapToGrid = enabled;
41}
42
43QPointF QgsModelSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
44{
45 snapped = false;
46
47 bool snappedXToGrid = false;
48 bool snappedYToGrid = false;
49 const QPointF res = snapPointToGrid( point, scaleFactor, snappedXToGrid, snappedYToGrid );
50 if ( snappedXToGrid && snapVertical )
51 {
52 snapped = true;
53 point.setX( res.x() );
54 }
55 if ( snappedYToGrid && snapHorizontal )
56 {
57 snapped = true;
58 point.setY( res.y() );
59 }
60
61 return point;
62}
63
64QRectF QgsModelSnapper::snapRect( const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
65{
66 snapped = false;
67 QRectF snappedRect = rect;
68
69 bool snappedXToGrid = false;
70 bool snappedYToGrid = false;
71 QList<QPointF> points;
72 points << rect.topLeft() << rect.topRight() << rect.bottomLeft() << rect.bottomRight();
73 const QPointF res = snapPointsToGrid( points, scaleFactor, snappedXToGrid, snappedYToGrid );
74 if ( snappedXToGrid && snapVertical )
75 {
76 snapped = true;
77 snappedRect.translate( res.x(), 0 );
78 }
79 if ( snappedYToGrid && snapHorizontal )
80 {
81 snapped = true;
82 snappedRect.translate( 0, res.y() );
83 }
84
85 return snappedRect;
86}
87
88QRectF QgsModelSnapper::snapRectWithResize( const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
89{
90 snapped = false;
91 QRectF snappedRect = rect;
92
93 bool snappedXToGrid = false;
94 bool snappedYToGrid = false;
95 QPointF res = snapPointsToGrid( QList<QPointF>() << rect.topLeft(), scaleFactor, snappedXToGrid, snappedYToGrid );
96 if ( snappedXToGrid && snapVertical )
97 {
98 snapped = true;
99 snappedRect.setLeft( snappedRect.left() + res.x() );
100 }
101 if ( snappedYToGrid && snapHorizontal )
102 {
103 snapped = true;
104 snappedRect.setTop( snappedRect.top() + res.y() );
105 }
106 res = snapPointsToGrid( QList<QPointF>() << rect.bottomRight(), scaleFactor, snappedXToGrid, snappedYToGrid );
107 if ( snappedXToGrid && snapVertical )
108 {
109 snapped = true;
110 snappedRect.setRight( snappedRect.right() + res.x() );
111 }
112 if ( snappedYToGrid && snapHorizontal )
113 {
114 snapped = true;
115 snappedRect.setBottom( snappedRect.bottom() + res.y() );
116 }
117
118 return snappedRect;
119}
120
121QPointF QgsModelSnapper::snapPointToGrid( QPointF point, double scaleFactor, bool &snappedX, bool &snappedY ) const
122{
123 const QPointF delta = snapPointsToGrid( QList<QPointF>() << point, scaleFactor, snappedX, snappedY );
124 return point + delta;
125}
126
127QPointF QgsModelSnapper::snapPointsToGrid( const QList<QPointF> &points, double scaleFactor, bool &snappedX, bool &snappedY ) const
128{
129 snappedX = false;
130 snappedY = false;
131 if ( !mSnapToGrid )
132 {
133 return QPointF( 0, 0 );
134 }
135#if 0
136 const QgsLayoutGridSettings &grid = mLayout->gridSettings();
137 if ( grid.resolution().length() <= 0 )
138 return QPointF( 0, 0 );
139#endif
140
141 double deltaX = 0;
142 double deltaY = 0;
143 double smallestDiffX = std::numeric_limits<double>::max();
144 double smallestDiffY = std::numeric_limits<double>::max();
145 for ( const QPointF point : points )
146 {
147 //snap x coordinate
148 const double gridRes = 30; //mLayout->convertToLayoutUnits( grid.resolution() );
149 int xRatio = static_cast<int>( ( point.x() ) / gridRes + 0.5 ); //NOLINT
150 int yRatio = static_cast<int>( ( point.y() ) / gridRes + 0.5 ); //NOLINT
151
152 const double xSnapped = xRatio * gridRes;
153 const double ySnapped = yRatio * gridRes;
154
155 const double currentDiffX = std::fabs( xSnapped - point.x() );
156 if ( currentDiffX < smallestDiffX )
157 {
158 smallestDiffX = currentDiffX;
159 deltaX = xSnapped - point.x();
160 }
161
162 const double currentDiffY = std::fabs( ySnapped - point.y() );
163 if ( currentDiffY < smallestDiffY )
164 {
165 smallestDiffY = currentDiffY;
166 deltaY = ySnapped - point.y();
167 }
168 }
169
170 //convert snap tolerance from pixels to layout units
171 const double alignThreshold = mTolerance / scaleFactor;
172
173 QPointF delta( 0, 0 );
174 if ( smallestDiffX <= alignThreshold )
175 {
176 //snap distance is inside of tolerance
177 snappedX = true;
178 delta.setX( deltaX );
179 }
180 if ( smallestDiffY <= alignThreshold )
181 {
182 //snap distance is inside of tolerance
183 snappedY = true;
184 delta.setY( deltaY );
185 }
186
187 return delta;
188}
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.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.