QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  QgsSettings s;
24  mTolerance = s.value( QStringLiteral( "/Processing/Modeler/snapTolerancePixels" ), 40 ).toInt();
25 }
26 
27 void QgsModelSnapper::setSnapTolerance( const int snapTolerance )
28 {
29  mTolerance = snapTolerance;
30 }
31 
32 void QgsModelSnapper::setSnapToGrid( bool enabled )
33 {
34  mSnapToGrid = enabled;
35 }
36 
37 QPointF 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  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 
58 QRectF 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  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 
82 QRectF 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 
115 QPointF QgsModelSnapper::snapPointToGrid( QPointF point, double scaleFactor, bool &snappedX, bool &snappedY ) const
116 {
117  QPointF delta = snapPointsToGrid( QList< QPointF >() << point, scaleFactor, snappedX, snappedY );
118  return point + delta;
119 }
120 
121 QPointF 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 ( QPointF point : points )
140  {
141  //snap x coordinate
142  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  double xSnapped = xRatio * gridRes;
147  double ySnapped = yRatio * gridRes;
148 
149  double currentDiffX = std::fabs( xSnapped - point.x() );
150  if ( currentDiffX < smallestDiffX )
151  {
152  smallestDiffX = currentDiffX;
153  deltaX = xSnapped - point.x();
154  }
155 
156  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  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 }
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsModelSnapper::snapTolerance
int snapTolerance() const
Returns the snap tolerance (in pixels) to use when snapping.
Definition: qgsmodelsnapper.h:53
QgsLayoutMeasurement::length
double length() const
Returns the length of the measurement.
Definition: qgslayoutmeasurement.h:48
QgsModelSnapper::snapPoint
QPointF snapPoint(QPointF point, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate point.
Definition: qgsmodelsnapper.cpp:37
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsModelSnapper::snapPointToGrid
QPointF snapPointToGrid(QPointF point, double scaleFactor, bool &snappedX, bool &snappedY) const
Snaps a layout coordinate point to the grid.
Definition: qgsmodelsnapper.cpp:115
QgsModelSnapper::snapPointsToGrid
QPointF snapPointsToGrid(const QList< QPointF > &points, double scaleFactor, bool &snappedX, bool &snappedY) const
Snaps a set of points to the grid.
Definition: qgsmodelsnapper.cpp:121
QgsModelSnapper::setSnapTolerance
void setSnapTolerance(int snapTolerance)
Sets the snap tolerance (in pixels) to use when snapping.
Definition: qgsmodelsnapper.cpp:27
qgsmodelsnapper.h
QgsModelSnapper::snapRect
QRectF snapRect(const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate rect.
Definition: qgsmodelsnapper.cpp:58
QgsModelSnapper::snapRectWithResize
QRectF snapRectWithResize(const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal=true, bool snapVertical=true) const
Snaps a layout coordinate rect.
Definition: qgsmodelsnapper.cpp:82
QgsLayoutGridSettings
Contains settings relating to the appearance, spacing and offset for layout grids.
Definition: qgslayoutgridsettings.h:36
qgssettings.h
QgsModelSnapper::QgsModelSnapper
QgsModelSnapper()
Constructor for QgsModelSnapper, attached to the specified layout.
Definition: qgsmodelsnapper.cpp:21
QgsModelSnapper::setSnapToGrid
void setSnapToGrid(bool enabled)
Sets whether snapping to grid is enabled.
Definition: qgsmodelsnapper.cpp:32
QgsLayoutGridSettings::resolution
QgsLayoutMeasurement resolution() const
Returns the page/snap grid resolution.
Definition: qgslayoutgridsettings.h:68