/
qgstracer.h
211 lines (177 loc) · 7.63 KB
/
qgstracer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/***************************************************************************
qgstracer.h
--------------------------------------
Date : January 2016
Copyright : (C) 2016 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSTRACER_H
#define QGSTRACER_H
class QgsVectorLayer;
#include "qgis_core.h"
#include <QSet>
#include <QVector>
#include <memory>
#include "qgsfeatureid.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsrectangle.h"
#include "qgsgeometry.h"
struct QgsTracerGraph;
class QgsFeatureRenderer;
class QgsRenderContext;
/**
* \ingroup core
* Utility class that construct a planar graph from the input vector
* layers and provides shortest path search for tracing of existing
* features.
*
* \since QGIS 2.14
*/
class CORE_EXPORT QgsTracer : public QObject
{
Q_OBJECT
public:
/**
* Constructor for QgsTracer.
*/
QgsTracer();
~QgsTracer() override;
//! Gets layers used for tracing
QList<QgsVectorLayer *> layers() const { return mLayers; }
//! Sets layers used for tracing
void setLayers( const QList<QgsVectorLayer *> &layers );
/**
* Returns the CRS used for tracing.
* \see setDestinationCrs()
*/
QgsCoordinateReferenceSystem destinationCrs() const { return mCRS; }
/**
* Sets the \a crs and transform \a context used for tracing.
* \see destinationCrs()
*/
void setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transform );
/**
* Sets the \a render context used for tracing only on visible features.
*/
void setRenderContext( const QgsRenderContext *render );
//! Gets extent to which graph's features will be limited (empty extent means no limit)
QgsRectangle extent() const { return mExtent; }
//! Sets extent to which graph's features will be limited (empty extent means no limit)
void setExtent( const QgsRectangle &extent );
/**
* Gets offset in map units that should be applied to the traced paths returned from findShortestPath().
* Positive offset for right side, negative offset for left side.
* \since QGIS 3.0
*/
double offset() const { return mOffset; }
/**
* Set offset in map units that should be applied to the traced paths returned from findShortestPath().
* Positive offset for right side, negative offset for left side.
* \since QGIS 3.0
*/
void setOffset( double offset );
/**
* Gets extra parameters for offset curve algorithm (used when offset is non-zero)
* \since QGIS 3.0
*/
void offsetParameters( int &quadSegments SIP_OUT, int &joinStyle SIP_OUT, double &miterLimit SIP_OUT );
/**
* Set extra parameters for offset curve algorithm (used when offset is non-zero)
* \since QGIS 3.0
*/
void setOffsetParameters( int quadSegments, int joinStyle, double miterLimit );
//! Gets maximum possible number of features in graph. If the number is exceeded, graph is not created.
int maxFeatureCount() const { return mMaxFeatureCount; }
//! Gets maximum possible number of features in graph. If the number is exceeded, graph is not created.
void setMaxFeatureCount( int count ) { mMaxFeatureCount = count; }
/**
* Build the internal data structures. This may take some time
* depending on how big the input layers are. It is not necessary
* to call this method explicitly - it will be called by findShortestPath()
* if necessary.
*/
bool init();
//! Whether the internal data structures have been initialized
bool isInitialized() const { return static_cast< bool >( mGraph ); }
/**
* Whether there was an error during graph creation due to noding exception,
* indicating some input data topology problems
* \since QGIS 2.16
*/
bool hasTopologyProblem() const { return mHasTopologyProblem; }
//! Possible errors that may happen when calling findShortestPath()
enum PathError
{
ErrNone, //!< No error
ErrTooManyFeatures, //!< Max feature count threshold was reached while reading features
ErrPoint1, //!< Start point cannot be joined to the graph
ErrPoint2, //!< End point cannot be joined to the graph
ErrNoPath, //!< Points are not connected in the graph
};
/**
* Given two points, find the shortest path and return points on the way.
* The optional "error" argument may receive error code (PathError enum) if it is not null
* \returns array of points - trace of linestrings of other features (empty array one error)
*/
QVector<QgsPointXY> findShortestPath( const QgsPointXY &p1, const QgsPointXY &p2, PathError *error SIP_OUT = nullptr );
//! Find out whether the point is snapped to a vertex or edge (i.e. it can be used for tracing start/stop)
bool isPointSnapped( const QgsPointXY &pt );
protected:
/**
* Allows derived classes to setup the settings just before the tracer is initialized.
* This allows the configuration to be set in a lazy way only when it is really necessary.
* Default implementation does nothing.
*/
virtual void configure() {}
protected slots:
//! Destroy the existing graph structure if any (de-initialize)
void invalidateGraph();
private:
bool initGraph();
private slots:
void onFeatureAdded( QgsFeatureId fid );
void onFeatureDeleted( QgsFeatureId fid );
void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
void onDataChanged( );
void onLayerDestroyed( QObject *obj );
private:
//! Graph data structure for path searching
std::unique_ptr< QgsTracerGraph > mGraph;
//! Input layers for the graph building
QList<QgsVectorLayer *> mLayers;
//! Destination CRS in which graph is built and tracing done
QgsCoordinateReferenceSystem mCRS;
//! Coordinate transform context
QgsCoordinateTransformContext mTransformContext;
//! Render context
std::unique_ptr<QgsRenderContext> mRenderContext;
//! Extent for graph building (empty extent means no limit)
QgsRectangle mExtent;
//! Offset in map units that should be applied to the traced paths
double mOffset = 0;
//! Offset parameter: Number of segments (approximation of circle quarter) when using round join style
int mOffsetSegments = 8;
//! Offset parameter: Join style (1 = round, 2 = miter, 3 = bevel)
int mOffsetJoinStyle = 2;
//! Offset parameter: Limit for miter join style
double mOffsetMiterLimit = 5.;
/**
* Limit of how many features can be in the graph (0 means no limit).
* This is to avoid possibly long graph preparation for complicated layers
*/
int mMaxFeatureCount = 0;
/**
* A flag indicating that there was an error during graph creation
* due to noding exception, indicating some input data topology problems
*/
bool mHasTopologyProblem = false;
};
#endif // QGSTRACER_H