Skip to content

Commit 4b8ea28

Browse files
committedJan 20, 2015
Add QgsSnappingUtils::snapToCurrentLayer() + utility methods in QgsTolerance
Also added missing SIP wrappers for new classes QgsPointLocator and QgsSnappingUtils
1 parent 488e7f1 commit 4b8ea28

File tree

9 files changed

+309
-57
lines changed

9 files changed

+309
-57
lines changed
 

‎python/core/qgspointlocator.sip

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
2+
class QgsPointLocator : QObject
3+
{
4+
%TypeHeaderCode
5+
#include <qgspointlocator.h>
6+
%End
7+
8+
public:
9+
explicit QgsPointLocator( QgsVectorLayer* layer, const QgsCoordinateReferenceSystem* destCRS = 0 );
10+
11+
~QgsPointLocator();
12+
13+
enum Type { Invalid, Vertex, Edge, Area, All };
14+
15+
/** Prepare the indexes for given or-ed combination of query types (Vertex, Edge, Area).
16+
* If not initialized explicitly, index of particular type will be inited when first such query is issued.
17+
*/
18+
void init( int types = All, bool force = false );
19+
20+
//! check whether index for given query type exists
21+
bool hasIndex( Type t ) const;
22+
23+
struct Match
24+
{
25+
//! consruct invalid match
26+
Match();
27+
28+
Match( QgsPointLocator::Type t, QgsVectorLayer* vl, QgsFeatureId fid, double dist, const QgsPoint& pt, int vertexIndex = 0 );
29+
30+
QgsPointLocator::Type type() const;
31+
32+
bool isValid() const;
33+
bool hasVertex() const;
34+
bool hasEdge() const;
35+
bool hasArea() const;
36+
37+
//! for vertex / edge match
38+
//! units depending on what class returns it (geom.cache: layer units, map canvas snapper: dest crs units)
39+
double distance() const;
40+
41+
//! for vertex / edge match
42+
//! coords depending on what class returns it (geom.cache: layer coords, map canvas snapper: dest coords)
43+
QgsPoint point() const;
44+
45+
//! for vertex / edge match (first vertex of the edge)
46+
int vertexIndex();
47+
48+
//! reference vector layer
49+
QgsVectorLayer* layer();
50+
51+
QgsFeatureId featureId();
52+
53+
void replaceIfBetter( const QgsPointLocator::Match& m, double maxDistance );
54+
55+
//! Only for a valid edge match - obtain endpoints of the edge
56+
void edgePoints( QgsPoint& pt1 /Out/, QgsPoint& pt2 /Out/ ) const;
57+
};
58+
59+
typedef QList<QgsPointLocator::Match> MatchList;
60+
61+
//! Interface that allows rejection of some matches in intersection queries
62+
//! (e.g. a match can only belong to a particular feature / match must not be a particular point).
63+
//! Implement the interface and pass its instance to QgsPointLocator or QgsSnappingUtils methods.
64+
struct MatchFilter
65+
{
66+
virtual bool acceptMatch( const QgsPointLocator::Match& match ) = 0;
67+
};
68+
69+
// 1-NN queries
70+
71+
//! find nearest vertex to the specified point
72+
QgsPointLocator::Match nearestVertex( const QgsPoint& point );
73+
74+
//! find nearest edge to the specified point
75+
QgsPointLocator::Match nearestEdge( const QgsPoint& point );
76+
77+
// k-NN queries
78+
79+
//! find nearest vertices to the specified point - sorted by distance
80+
//! will return up to maxMatches matches
81+
MatchList nearestVertices( const QgsPoint& point, int maxMatches );
82+
//! find nearest edges to the specified point - sorted by distance
83+
MatchList nearestEdges( const QgsPoint& point, int maxMatches );
84+
85+
// intersection queries
86+
87+
//! Find nearest vertices to the specified point - sorted by distance.
88+
//! Will return matches up to distance given by tolerance.
89+
//! Optional filter may discard unwanted matches.
90+
MatchList verticesInTolerance( const QgsPoint& point, double tolerance, QgsPointLocator::MatchFilter* filter = 0 );
91+
//! Find nearest edges to the specified point - sorted by distance.
92+
//! Will return matches up to distance given by tolerance.
93+
//! Optional filter may discard unwanted matches.
94+
MatchList edgesInTolerance( const QgsPoint& point, double tolerance, QgsPointLocator::MatchFilter* filter = 0 );
95+
96+
//! Find vertices within given rectangle.
97+
//! If distToPoint is given, the matches will be sorted by distance to that point.
98+
//! Optional filter may discard unwanted matches.
99+
MatchList verticesInRect( const QgsRectangle& rect, const QgsPoint* distToPoint = 0, QgsPointLocator::MatchFilter* filter = 0 );
100+
//! Find edges within given rectangle.
101+
//! If distToPoint is given, the matches will be sorted by distance to that point.
102+
//! Optional filter may discard unwanted matches.
103+
MatchList edgesInRect( const QgsRectangle& rect, const QgsPoint* distToPoint = 0, QgsPointLocator::MatchFilter* filter = 0 );
104+
105+
// point-in-polygon query
106+
107+
// TODO: function to return just the first match?
108+
//! find out if the point is in any polygons
109+
MatchList pointInPolygon( const QgsPoint& point );
110+
111+
112+
};

‎python/core/qgssnappingutils.sip

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
class QgsSnappingUtils : QObject
3+
{
4+
%TypeHeaderCode
5+
#include <qgssnappingutils.h>
6+
%End
7+
8+
public:
9+
QgsSnappingUtils( QObject* parent /TransferThis/ = 0 );
10+
~QgsSnappingUtils();
11+
12+
// main actions
13+
14+
/** get a point locator for the given layer. If such locator does not exist, it will be created */
15+
QgsPointLocator* locatorForLayer( QgsVectorLayer* vl );
16+
17+
/** snap to map according to the current configuration (mode). Optional filter allows to discard unwanted matches. */
18+
QgsPointLocator::Match snapToMap( const QPoint& point, QgsPointLocator::MatchFilter* filter = 0 );
19+
QgsPointLocator::Match snapToMap( const QgsPoint& pointMap, QgsPointLocator::MatchFilter* filter = 0 );
20+
// TODO: multi-variant
21+
22+
/** snap to current layer */
23+
QgsPointLocator::Match snapToCurrentLayer( const QPoint& point, int type, QgsPointLocator::MatchFilter* filter = 0 );
24+
25+
// environment setup
26+
27+
/** assign current map settings to the utils - used for conversion between screen coords to map coords */
28+
void setMapSettings( const QgsMapSettings& settings );
29+
const QgsMapSettings& mapSettings() const;
30+
31+
/** set current layer so that if mode is SnapCurrentLayer we know which layer to use */
32+
void setCurrentLayer( QgsVectorLayer* layer );
33+
QgsVectorLayer* currentLayer() const;
34+
35+
36+
// configuration
37+
38+
//! modes for "snap to background"
39+
enum SnapToMapMode
40+
{
41+
SnapCurrentLayer, //!< snap just to current layer (tolerance+type from QSettings)
42+
SnapPerLayerConfig, //!< snap according to the configuration set in setLayers()
43+
};
44+
45+
/** Set how the snapping to map is done */
46+
void setSnapToMapMode( SnapToMapMode mode );
47+
/** Find out how the snapping to map is done */
48+
SnapToMapMode snapToMapMode() const;
49+
50+
/** configure options used when the mode is snap to current layer */
51+
void setDefaultSettings( int type, double tolerance, QgsTolerance::UnitType unit );
52+
/** query options used when the mode is snap to current layer */
53+
void defaultSettings( int& type /Out/, double& tolerance /Out/, QgsTolerance::UnitType& unit /Out/ );
54+
55+
struct LayerConfig
56+
{
57+
LayerConfig( QgsVectorLayer* l, int t, double tol, QgsTolerance::UnitType u );
58+
59+
QgsVectorLayer* layer;
60+
int type;
61+
double tolerance;
62+
QgsTolerance::UnitType unit;
63+
};
64+
65+
/** Set layers which will be used for snapping */
66+
void setLayers( const QList<QgsSnappingUtils::LayerConfig>& layers );
67+
/** Query layers used for snapping */
68+
QList<QgsSnappingUtils::LayerConfig> layers() const;
69+
70+
/** Set whether to consider intersections of nearby segments for snapping */
71+
void setSnapOnIntersections( bool enabled );
72+
/** Query whether to consider intersections of nearby segments for snapping */
73+
bool snapOnIntersections() const;
74+
75+
public slots:
76+
/** Read snapping configuration from the project */
77+
void readConfigFromProject();
78+
79+
};

‎python/core/qgstolerance.sip

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,53 +15,71 @@ class QgsTolerance
1515
Pixels
1616
};
1717

18+
/**
19+
* Static function to get vertex tolerance value.
20+
* The value is read from settings and transformed if necessary.
21+
* @return value of vertex tolerance in map units (not layer units)
22+
* @note added in 2.8
23+
*/
24+
static double vertexSearchRadius( const QgsMapSettings& mapSettings );
25+
1826
/**
1927
* Static function to get vertex tolerance value for a layer.
2028
* The value is read from settings and transformed if necessary.
21-
* @return value of vertex tolerance in map units
29+
* @return value of vertex tolerance in layer units
2230
*/
2331
static double vertexSearchRadius( QgsMapLayer* layer, const QgsMapSettings& mapSettings );
2432

2533
/**
2634
* Static function to get vertex tolerance value for a layer.
2735
* The value is read from settings and transformed if necessary.
28-
* @return value of vertex tolerance in map units
36+
* @return value of vertex tolerance in layer units
2937
*/
3038
//! @deprecated since 2.4 - use override with QgsMapSettings
3139
static double vertexSearchRadius( QgsMapLayer* layer, QgsMapRenderer* renderer ) /Deprecated/;
3240

3341
/**
3442
* Static function to get default tolerance value for a layer.
3543
* The value is read from settings and transformed if necessary.
36-
* @return value of default tolerance in map units
44+
* @return value of vertex tolerance in layer units
3745
*/
3846
static double defaultTolerance( QgsMapLayer* layer, const QgsMapSettings& mapSettings );
3947

4048
/**
4149
* Static function to get default tolerance value for a layer.
4250
* The value is read from settings and transformed if necessary.
43-
* @return value of default tolerance in map units
51+
* @return value of vertex tolerance in layer units
4452
*/
4553
//! @deprecated since 2.4 - use override with QgsMapSettings
4654
static double defaultTolerance( QgsMapLayer* layer, QgsMapRenderer* renderer ) /Deprecated/;
4755

4856
/**
49-
* Static function to translate tolerance value into current map unit value
57+
* Static function to translate tolerance value into map units
5058
* @param tolerance tolerance value to be translated
51-
* @param layer reference layer
5259
* @param mapSettings settings of the map
5360
* @param units type of units to be translated
5461
* @return value of tolerance in map units
62+
* @note added in 2.8
63+
*/
64+
static double toleranceInMapUnits( double tolerance, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units );
65+
66+
/**
67+
* Static function to translate tolerance value into layer units
68+
* @param tolerance tolerance value to be translated
69+
* @param layer reference layer
70+
* @param mapSettings settings of the map
71+
* @param units type of units to be translated
72+
* @return value of tolerance in layer units
5573
*/
5674
static double toleranceInMapUnits( double tolerance, QgsMapLayer* layer, const QgsMapSettings& mapSettings, UnitType units = MapUnits );
5775

5876
/**
59-
* Static function to translate tolerance value into current map unit value
77+
* Static function to translate tolerance value into layer units
6078
* @param tolerance tolerance value to be translated
6179
* @param layer reference layer
6280
* @param renderer renderer
6381
* @param units type of units to be translated
64-
* @return value of tolerance in map units
82+
* @return value of tolerance in layer units
6583
*/
6684
//! @deprecated since 2.4 - use the override with QgsMapSettings
6785
static double toleranceInMapUnits( double tolerance, QgsMapLayer* layer, QgsMapRenderer* renderer, UnitType units = MapUnits ) /Deprecated/;

‎src/app/qgsmaptooldeletepart.cpp

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgsvertexmarker.h"
2020
#include "qgsvectorlayer.h"
2121
#include "qgsgeometry.h"
22+
#include "qgssnappingutils.h"
2223
#include "qgstolerance.h"
2324

2425
#include <QMouseEvent>
@@ -122,38 +123,33 @@ QgsGeometry* QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId& f
122123
case QGis::Point:
123124
case QGis::Line:
124125
{
125-
if ( mSnapper.snapToCurrentLayer( point, mRecentSnappingResults, QgsSnapper::SnapToVertexAndSegment ) == 0 )
126+
QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Vertex | QgsPointLocator::Edge );
127+
if ( !match.isValid() )
128+
return geomPart;
129+
130+
int snapVertex = match.vertexIndex();
131+
vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f );
132+
QgsGeometry* g = f.geometry();
133+
if ( !g->isMultipart() )
134+
return geomPart;
135+
if ( g->wkbType() == QGis::WKBMultiPoint || g->wkbType() == QGis::WKBMultiPoint25D )
126136
{
127-
if ( mRecentSnappingResults.length() > 0 )
137+
fid = match.featureId();
138+
partNum = snapVertex;
139+
return QgsGeometry::fromPoint( match.point() );
140+
}
141+
if ( g->wkbType() == QGis::WKBMultiLineString || g->wkbType() == QGis::WKBMultiLineString25D )
142+
{
143+
QgsMultiPolyline mline = g->asMultiPolyline();
144+
for ( int part = 0; part < mline.count(); part++ )
128145
{
129-
QgsSnappingResult sr = mRecentSnappingResults.first();
130-
int snapVertex = sr.snappedVertexNr;
131-
if ( snapVertex == -1 )
132-
snapVertex = sr.beforeVertexNr;
133-
vlayer->getFeatures( QgsFeatureRequest().setFilterFid( sr.snappedAtGeometry ) ).nextFeature( f );
134-
QgsGeometry* g = f.geometry();
135-
if ( !g->isMultipart() )
136-
return geomPart;
137-
if ( g->wkbType() == QGis::WKBMultiPoint || g->wkbType() == QGis::WKBMultiPoint25D )
138-
{
139-
fid = sr.snappedAtGeometry;
140-
partNum = snapVertex;
141-
return QgsGeometry::fromPoint( sr.snappedVertex );
142-
}
143-
if ( g->wkbType() == QGis::WKBMultiLineString || g->wkbType() == QGis::WKBMultiLineString25D )
146+
if ( snapVertex < mline[part].count() )
144147
{
145-
QgsMultiPolyline mline = g->asMultiPolyline();
146-
for ( int part = 0; part < mline.count(); part++ )
147-
{
148-
if ( snapVertex < mline[part].count() )
149-
{
150-
fid = sr.snappedAtGeometry;
151-
partNum = part;
152-
return QgsGeometry::fromPolyline( mline[part] );
153-
}
154-
snapVertex -= mline[part].count();
155-
}
148+
fid = match.featureId();
149+
partNum = part;
150+
return QgsGeometry::fromPolyline( mline[part] );
156151
}
152+
snapVertex -= mline[part].count();
157153
}
158154
}
159155
break;

‎src/app/qgsmaptooldeletepart.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class APP_EXPORT QgsMapToolDeletePart: public QgsMapToolEdit
4141

4242
private:
4343
QgsVectorLayer* vlayer;
44-
QList<QgsSnappingResult> mRecentSnappingResults;
4544

4645
QgsGeometry* partUnderPoint( QPoint p, QgsFeatureId &fid, int &partNum );
4746

0 commit comments

Comments
 (0)