QGIS API Documentation  2.14.11-Essen
qgstracer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstracer.cpp
3  --------------------------------------
4  Date : January 2016
5  Copyright : (C) 2016 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgstracer.h"
17 
18 #include "qgsgeometry.h"
19 #include "qgsgeometryutils.h"
20 #include "qgsgeos.h"
21 #include "qgslogger.h"
22 #include "qgsvectorlayer.h"
23 
24 #include <queue>
25 #include <vector>
26 
27 typedef std::pair<int, double> DijkstraQueueItem; // first = vertex index, second = distance
28 
29 // utility comparator for queue items based on distance
30 struct comp
31 {
33  {
34  return a.second > b.second;
35  }
36 };
37 
38 
39 // TODO: move to geometry utils
40 double distance2D( const QgsPolyline& coords )
41 {
42  int np = coords.count();
43  if ( np == 0 )
44  return 0;
45 
46  double x0 = coords[0].x(), y0 = coords[0].y();
47  double x1, y1;
48  double dist = 0;
49  for ( int i = 1; i < np; ++i )
50  {
51  x1 = coords[i].x();
52  y1 = coords[i].y();
53  dist += sqrt(( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
54  x0 = x1;
55  y0 = y1;
56  }
57  return dist;
58 }
59 
60 
61 // TODO: move to geometry utils
62 double closestSegment( const QgsPolyline& pl, const QgsPoint& pt, int& vertexAfter, double epsilon )
63 {
64  double sqrDist = std::numeric_limits<double>::max();
65  const QgsPoint* pldata = pl.constData();
66  int plcount = pl.count();
67  double prevX = pldata[0].x(), prevY = pldata[0].y();
68  double segmentPtX, segmentPtY;
69  for ( int i = 1; i < plcount; ++i )
70  {
71  double currentX = pldata[i].x();
72  double currentY = pldata[i].y();
73  double testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY, segmentPtX, segmentPtY, epsilon );
74  if ( testDist < sqrDist )
75  {
76  sqrDist = testDist;
77  vertexAfter = i;
78  }
79  prevX = currentX;
80  prevY = currentY;
81  }
82  return sqrDist;
83 }
84 
86 
89 {
90  struct E // bidirectional edge
91  {
93  int v1, v2;
96 
97  int otherVertex( int v0 ) const { return v1 == v0 ? v2 : v1; }
98  double weight() const { return distance2D( coords ); }
99  };
100 
101  struct V
102  {
107  };
108 
113 
118 };
119 
120 
122 {
124  g->joinedVertices = 0;
126 
127  Q_FOREACH ( const QgsPolyline& line, edges )
128  {
129  QgsPoint p1( line[0] );
130  QgsPoint p2( line[line.count() - 1] );
131 
132  int v1 = -1, v2 = -1;
133  // get or add vertex 1
134  if ( point2vertex.contains( p1 ) )
135  v1 = point2vertex.value( p1 );
136  else
137  {
138  v1 = g->v.count();
140  v.pt = p1;
141  g->v.append( v );
142  point2vertex[p1] = v1;
143  }
144 
145  // get or add vertex 2
146  if ( point2vertex.contains( p2 ) )
147  v2 = point2vertex.value( p2 );
148  else
149  {
150  v2 = g->v.count();
152  v.pt = p2;
153  g->v.append( v );
154  point2vertex[p2] = v2;
155  }
156 
157  // add edge
159  e.v1 = v1;
160  e.v2 = v2;
161  e.coords = line;
162  g->e.append( e );
163 
164  // link edge to vertices
165  int eIdx = g->e.count() - 1;
166  g->v[v1].edges << eIdx;
167  g->v[v2].edges << eIdx;
168  }
169 
170  return g;
171 }
172 
173 
174 QVector<QgsPoint> shortestPath( const QgsTracerGraph& g, int v1, int v2 )
175 {
176  if ( v1 == -1 || v2 == -1 )
177  return QVector<QgsPoint>(); // invalid input
178 
179  // priority queue to drive Dijkstra:
180  // first of the pair is vertex index, second is distance
181  std::priority_queue< DijkstraQueueItem, std::vector< DijkstraQueueItem >, comp > Q;
182 
183  // shortest distances to each vertex
185  D[v1] = 0;
186 
187  // whether vertices have been already processed
188  QVector<bool> F( g.v.count() );
189 
190  // using which edge there is shortest path to each vertex
191  QVector<int> S( g.v.count(), -1 );
192 
193  int u = -1;
194  Q.push( DijkstraQueueItem( v1, 0 ) );
195 
196  while ( !Q.empty() )
197  {
198  u = Q.top().first; // new vertex to visit
199  Q.pop();
200 
201  if ( u == v2 )
202  break; // we can stop now, there won't be a shorter path
203 
204  if ( F[u] )
205  continue; // ignore previously added path which is actually longer
206 
207  const QgsTracerGraph::V& vu = g.v[u];
208  const int* vuEdges = vu.edges.constData();
209  int count = vu.edges.count();
210  for ( int i = 0; i < count; ++i )
211  {
212  const QgsTracerGraph::E& edge = g.e[ vuEdges[i] ];
213  int v = edge.otherVertex( u );
214  double w = edge.weight();
215  if ( !F[v] && D[u] + w < D[v] )
216  {
217  // found a shorter way to the vertex
218  D[v] = D[u] + w;
219  S[v] = vuEdges[i];
220  Q.push( DijkstraQueueItem( v, D[v] ) );
221  }
222  }
223  F[u] = 1; // mark the vertex as processed (we know the fastest path to it)
224  }
225 
226  if ( u != v2 ) // there's no path to the end vertex
227  return QVector<QgsPoint>();
228 
229  //qDebug("dist %f", D[u]);
230 
231  QVector<QgsPoint> points;
232  QList<int> path;
233  while ( S[u] != -1 )
234  {
235  path << S[u];
236  const QgsTracerGraph::E& e = g.e[S[u]];
237  QVector<QgsPoint> edgePoints = e.coords;
238  if ( edgePoints[0] != g.v[u].pt )
239  std::reverse( edgePoints.begin(), edgePoints.end() );
240  if ( !points.isEmpty() )
241  points.remove( points.count() - 1 ); // chop last one (will be used from next edge)
242  points << edgePoints;
243  u = e.otherVertex( u );
244  }
245 
246  std::reverse( path.begin(), path.end() );
247  //Q_FOREACH (int x, path)
248  // qDebug("e: %d", x);
249 
250  std::reverse( points.begin(), points.end() );
251  return points;
252 }
253 
254 
255 int point2vertex( const QgsTracerGraph& g, const QgsPoint& pt, double epsilon = 1e-6 )
256 {
257  // TODO: use spatial index
258 
259  for ( int i = 0; i < g.v.count(); ++i )
260  {
261  const QgsTracerGraph::V& v = g.v.at( i );
262  if ( v.pt == pt || ( fabs( v.pt.x() - pt.x() ) < epsilon && fabs( v.pt.y() - pt.y() ) < epsilon ) )
263  return i;
264  }
265 
266  return -1;
267 }
268 
269 
270 int point2edge( const QgsTracerGraph& g, const QgsPoint& pt, int& lineVertexAfter, double epsilon = 1e-6 )
271 {
272  int vertexAfter;
273 
274  for ( int i = 0; i < g.e.count(); ++i )
275  {
276  if ( g.inactiveEdges.contains( i ) )
277  continue; // ignore temporarily disabled edges
278 
279  const QgsTracerGraph::E& e = g.e.at( i );
280  double dist = closestSegment( e.coords, pt, vertexAfter, epsilon );
281  if ( dist == 0 )
282  {
283  lineVertexAfter = vertexAfter;
284  return i;
285  }
286  }
287  return -1;
288 }
289 
290 
291 void splitLinestring( const QgsPolyline& points, const QgsPoint& pt, int lineVertexAfter, QgsPolyline& pts1, QgsPolyline& pts2 )
292 {
293  int count1 = lineVertexAfter;
294  int count2 = points.count() - lineVertexAfter;
295 
296  for ( int i = 0; i < count1; ++i )
297  pts1 << points[i];
298  if ( points[lineVertexAfter-1] != pt )
299  pts1 << pt; // repeat if not split exactly at that point
300 
301  if ( pt != points[lineVertexAfter] )
302  pts2 << pt; // repeat if not split exactly at that point
303  for ( int i = 0; i < count2; ++i )
304  pts2 << points[i + lineVertexAfter];
305 }
306 
307 
309 {
310  // find edge where the point is
311  int lineVertexAfter;
312  int eIdx = point2edge( g, pt, lineVertexAfter );
313 
314  //qDebug("e: %d", eIdx);
315 
316  if ( eIdx == -1 )
317  return -1;
318 
319  const QgsTracerGraph::E& e = g.e[eIdx];
320  QgsTracerGraph::V& v1 = g.v[e.v1];
321  QgsTracerGraph::V& v2 = g.v[e.v2];
322 
323  QgsPolyline out1, out2;
324  splitLinestring( e.coords, pt, lineVertexAfter, out1, out2 );
325 
326  int vIdx = g.v.count();
327  int e1Idx = g.e.count();
328  int e2Idx = e1Idx + 1;
329 
330  // prepare new vertex and edges
331 
333  v.pt = pt;
334  v.edges << e1Idx << e2Idx;
335 
337  e1.v1 = e.v1;
338  e1.v2 = vIdx;
339  e1.coords = out1;
340 
342  e2.v1 = vIdx;
343  e2.v2 = e.v2;
344  e2.coords = out2;
345 
346  // update edge connectivity of existing vertices
347  v1.edges.replace( v1.edges.indexOf( eIdx ), e1Idx );
348  v2.edges.replace( v2.edges.indexOf( eIdx ), e2Idx );
349  g.inactiveEdges << eIdx;
350 
351  // add new vertex and edges to the graph
352  g.v.append( v );
353  g.e.append( e1 );
354  g.e.append( e2 );
355  g.joinedVertices++;
356 
357  return vIdx;
358 }
359 
360 
362 {
363  // try to use existing vertex in the graph
364  int v = point2vertex( g, pt );
365  if ( v != -1 )
366  return v;
367 
368  // try to add the vertex to an edge (may fail if point is not on edge)
369  return joinVertexToGraph( g, pt );
370 }
371 
372 
374 {
375  // remove extra vertices and edges
376  g.v.resize( g.v.count() - g.joinedVertices );
377  g.e.resize( g.e.count() - g.joinedVertices * 2 );
378  g.joinedVertices = 0;
379 
380  // fix vertices of deactivated edges
381  Q_FOREACH ( int eIdx, g.inactiveEdges )
382  {
383  if ( eIdx >= g.e.count() )
384  continue;
385  const QgsTracerGraph::E& e = g.e[eIdx];
386  QgsTracerGraph::V& v1 = g.v[e.v1];
387  for ( int i = 0; i < v1.edges.count(); ++i )
388  {
389  if ( v1.edges[i] >= g.e.count() )
390  v1.edges.remove( i-- );
391  }
392  v1.edges << eIdx;
393 
394  QgsTracerGraph::V& v2 = g.v[e.v2];
395  for ( int i = 0; i < v2.edges.count(); ++i )
396  {
397  if ( v2.edges[i] >= g.e.count() )
398  v2.edges.remove( i-- );
399  }
400  v2.edges << eIdx;
401  }
402 
403  g.inactiveEdges.clear();
404 }
405 
406 
408 {
409  switch ( QgsWKBTypes::flatType( g->geometry()->wkbType() ) )
410  {
412  mpl << g->asPolyline();
413  break;
414 
416  Q_FOREACH ( const QgsPolyline& ring, g->asPolygon() )
417  mpl << ring;
418  break;
419 
421  Q_FOREACH ( const QgsPolyline& linestring, g->asMultiPolyline() )
422  mpl << linestring;
423  break;
424 
426  Q_FOREACH ( const QgsPolygon& polygon, g->asMultiPolygon() )
427  Q_FOREACH ( const QgsPolyline& ring, polygon )
428  mpl << ring;
429  break;
430 
431  default:
432  break; // unknown type - do nothing
433  }
434 }
435 
436 // -------------
437 
438 
440  : mGraph( 0 )
441  , mReprojectionEnabled( false )
442  , mMaxFeatureCount( 0 )
443  , mHasTopologyProblem( false )
444 {
445 }
446 
447 
448 bool QgsTracer::initGraph()
449 {
450  if ( mGraph )
451  return true; // already initialized
452 
453  mHasTopologyProblem = false;
454 
455  QgsFeature f;
456  QgsMultiPolyline mpl;
457 
458  // extract linestrings
459 
460  // TODO: use QgsPointLocator as a source for the linework
461 
462  QTime t1, t2, t2a, t3;
463 
464  t1.start();
465  int featuresCounted = 0;
466  Q_FOREACH ( QgsVectorLayer* vl, mLayers )
467  {
468  QgsCoordinateTransform ct( vl->crs(), mCRS );
469 
470  QgsFeatureRequest request;
472  if ( !mExtent.isEmpty() )
473  request.setFilterRect( mReprojectionEnabled ? ct.transformBoundingBox( mExtent, QgsCoordinateTransform::ReverseTransform ) : mExtent );
474 
475  QgsFeatureIterator fi = vl->getFeatures( request );
476  while ( fi.nextFeature( f ) )
477  {
478  if ( !f.constGeometry() )
479  continue;
480 
481  if ( mReprojectionEnabled && !ct.isShortCircuited() )
482  {
483  try
484  {
485  f.geometry()->transform( ct );
486  }
487  catch ( QgsCsException& )
488  {
489  continue; // ignore if the transform failed
490  }
491  }
492 
493  extractLinework( f.constGeometry(), mpl );
494 
495  ++featuresCounted;
496  if ( mMaxFeatureCount != 0 && featuresCounted >= mMaxFeatureCount )
497  return false;
498  }
499  }
500  int timeExtract = t1.elapsed();
501 
502  // resolve intersections
503 
504  t2.start();
505 
506  int timeNodingCall = 0;
507 
508 #if 0
509  // without noding - if data are known to be noded beforehand
510 #else
512 
513  try
514  {
515  t2a.start();
516  // GEOSNode_r may throw an exception
517  GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom->asGeos() );
518  timeNodingCall = t2a.elapsed();
519 
520  QgsGeometry* noded = new QgsGeometry;
521  noded->fromGeos( allNoded );
522  delete allGeom;
523 
524  mpl = noded->asMultiPolyline();
525 
526  delete noded;
527  }
528  catch ( GEOSException &e )
529  {
530  // no big deal... we will just not have nicely noded linework, potentially
531  // missing some intersections
532 
533  mHasTopologyProblem = true;
534 
535  QgsDebugMsg( "Tracer Noding Exception: " + e.what() );
536  }
537 #endif
538 
539  int timeNoding = t2.elapsed();
540 
541  t3.start();
542 
543  mGraph = makeGraph( mpl );
544 
545  int timeMake = t3.elapsed();
546 
547  Q_UNUSED( timeExtract );
548  Q_UNUSED( timeNoding );
549  Q_UNUSED( timeNodingCall );
550  Q_UNUSED( timeMake );
551  QgsDebugMsg( QString( "tracer extract %1 ms, noding %2 ms (call %3 ms), make %4 ms" )
552  .arg( timeExtract ).arg( timeNoding ).arg( timeNodingCall ).arg( timeMake ) );
553  return true;
554 }
555 
557 {
558  invalidateGraph();
559 }
560 
562 {
563  if ( mLayers == layers )
564  return;
565 
566  Q_FOREACH ( QgsVectorLayer* layer, mLayers )
567  {
568  disconnect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
569  disconnect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
570  disconnect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
571  disconnect( layer, SIGNAL( destroyed( QObject* ) ), this, SLOT( onLayerDestroyed( QObject* ) ) );
572  }
573 
574  mLayers = layers;
575 
576  Q_FOREACH ( QgsVectorLayer* layer, mLayers )
577  {
578  connect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
579  connect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
580  connect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
581  connect( layer, SIGNAL( destroyed( QObject* ) ), this, SLOT( onLayerDestroyed( QObject* ) ) );
582  }
583 
584  invalidateGraph();
585 }
586 
588 {
589  if ( mReprojectionEnabled == enabled )
590  return;
591 
592  mReprojectionEnabled = enabled;
593  invalidateGraph();
594 }
595 
597 {
598  if ( mCRS == crs )
599  return;
600 
601  mCRS = crs;
602  invalidateGraph();
603 }
604 
606 {
607  if ( mExtent == extent )
608  return;
609 
610  mExtent = extent;
611  invalidateGraph();
612 }
613 
615 {
616  if ( mGraph )
617  return true;
618 
619  // configuration from derived class?
620  configure();
621 
622  return initGraph();
623 }
624 
625 
627 {
628  delete mGraph;
629  mGraph = 0;
630 }
631 
632 void QgsTracer::onFeatureAdded( QgsFeatureId fid )
633 {
634  Q_UNUSED( fid );
635  invalidateGraph();
636 }
637 
638 void QgsTracer::onFeatureDeleted( QgsFeatureId fid )
639 {
640  Q_UNUSED( fid );
641  invalidateGraph();
642 }
643 
644 void QgsTracer::onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom )
645 {
646  Q_UNUSED( fid );
647  Q_UNUSED( geom );
648  invalidateGraph();
649 }
650 
651 void QgsTracer::onLayerDestroyed( QObject* obj )
652 {
653  // remove the layer before it is completely invalid (static_cast should be the safest cast)
654  mLayers.removeAll( static_cast<QgsVectorLayer*>( obj ) );
655  invalidateGraph();
656 }
657 
659 {
660  init(); // does nothing if the graph exists already
661  if ( !mGraph )
662  {
663  if ( error ) *error = ErrTooManyFeatures;
664  return QVector<QgsPoint>();
665  }
666 
667  QTime t;
668  t.start();
669  int v1 = pointInGraph( *mGraph, p1 );
670  int v2 = pointInGraph( *mGraph, p2 );
671  int tPrep = t.elapsed();
672 
673  if ( v1 == -1 )
674  {
675  if ( error ) *error = ErrPoint1;
676  return QVector<QgsPoint>();
677  }
678  if ( v2 == -1 )
679  {
680  if ( error ) *error = ErrPoint2;
681  return QVector<QgsPoint>();
682  }
683 
684  QTime t2;
685  t2.start();
686  QgsPolyline points = shortestPath( *mGraph, v1, v2 );
687  int tPath = t2.elapsed();
688 
689  Q_UNUSED( tPrep );
690  Q_UNUSED( tPath );
691  QgsDebugMsg( QString( "path timing: prep %1 ms, path %2 ms" ).arg( tPrep ).arg( tPath ) );
692 
693  resetGraph( *mGraph );
694 
695  if ( error )
696  *error = points.isEmpty() ? ErrNoPath : ErrNone;
697 
698  return points;
699 }
700 
702 {
703  init(); // does nothing if the graph exists already
704  if ( !mGraph )
705  return false;
706 
707  if ( point2vertex( *mGraph, pt ) != -1 )
708  return true;
709 
710  int lineVertexAfter;
711  int e = point2edge( *mGraph, pt, lineVertexAfter );
712  return e != -1;
713 }
QgsPolygon asPolygon() const
Return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
QVector< E > e
Edges of the graph.
Definition: qgstracer.cpp:112
Wrapper for iterator of features from vector data provider or vector layer.
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
double weight() const
Definition: qgstracer.cpp:98
QVector< QgsPoint > shortestPath(const QgsTracerGraph &g, int v1, int v2)
Definition: qgstracer.cpp:174
iterator begin()
int joinedVertices
Temporarily added vertices (for each there are two extra edges)
Definition: qgstracer.cpp:117
virtual void configure()
Allows derived classes to setup the settings just before the tracer is initialized.
Definition: qgstracer.h:106
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
int indexOf(const T &value, int from) const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
int pointInGraph(QgsTracerGraph &g, const QgsPoint &pt)
Definition: qgstracer.cpp:361
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
void setExtent(const QgsRectangle &extent)
Set extent to which graph&#39;s features will be limited (empty extent means no limit) ...
Definition: qgstracer.cpp:605
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
int point2vertex(const QgsTracerGraph &g, const QgsPoint &pt, double epsilon=1e-6)
Definition: qgstracer.cpp:255
QList< QgsVectorLayer * > layers() const
Get layers used for tracing.
Definition: qgstracer.h:46
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
QgsTracerGraph * makeGraph(const QVector< QgsPolyline > &edges)
Definition: qgstracer.cpp:121
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
T & first()
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
double closestSegment(const QgsPolyline &pl, const QgsPoint &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:62
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
std::pair< int, double > DijkstraQueueItem
Definition: qgstracer.cpp:27
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
double y() const
Get the y value of the point.
Definition: qgspoint.h:136
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
int elapsed() const
bool isEmpty() const
test if rectangle is empty.
QSet< int > inactiveEdges
Temporarily removed edges.
Definition: qgstracer.cpp:115
Max feature count threshold was reached while reading features.
Definition: qgstracer.h:88
int removeAll(const T &value)
void remove(int i)
PathError
Possible errors that may happen when calling findShortestPath()
Definition: qgstracer.h:85
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
void fromGeos(GEOSGeometry *geos)
Set the geometry, feeding in a geometry in GEOS format.
void splitLinestring(const QgsPolyline &points, const QgsPoint &pt, int lineVertexAfter, QgsPolyline &pts1, QgsPolyline &pts2)
Definition: qgstracer.cpp:291
const T * constData() const
Simple graph structure for shortest path search.
Definition: qgstracer.cpp:88
A class to represent a point.
Definition: qgspoint.h:65
iterator end()
const T value(const Key &key) const
void resetGraph(QgsTracerGraph &g)
Definition: qgstracer.cpp:373
QgsGeometry * geometry()
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:76
bool contains(const T &value) const
static QgsGeometry * fromMultiPolyline(const QgsMultiPolyline &multiline)
Creates a new geometry from a QgsMultiPolyline object.
End point cannot be joined to the graph.
Definition: qgstracer.h:90
QVector< V > v
Vertices of the graph.
Definition: qgstracer.cpp:110
void setCrsTransformEnabled(bool enabled)
Set whether to do reprojection to destination CRS.
Definition: qgstracer.cpp:587
QVector< int > edges
indices of adjacent edges (used in Dijkstra algorithm)
Definition: qgstracer.cpp:106
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
bool isEmpty() const
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
QgsPoint pt
location of the vertex
Definition: qgstracer.cpp:104
void invalidateGraph()
Destroy the existing graph structure if any (de-initialize)
Definition: qgstracer.cpp:626
const GEOSGeometry * asGeos(double precision=0) const
Returns a geos geometry.
Class for storing a coordinate reference system (CRS)
int count(const T &value) const
bool isPointSnapped(const QgsPoint &pt)
Find out whether the point is snapped to a vertex or edge (i.e. it can be used for tracing start/stop...
Definition: qgstracer.cpp:701
QgsRectangle extent() const
Get extent to which graph&#39;s features will be limited (empty extent means no limit) ...
Definition: qgstracer.h:61
Class for doing transforms between two map coordinate systems.
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
qint64 QgsFeatureId
Definition: qgsfeature.h:31
No error.
Definition: qgstracer.h:87
void replace(int i, const T &value)
QVector< QgsPoint > coords
coordinates of the edge (including endpoints)
Definition: qgstracer.cpp:95
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
bool init()
Build the internal data structures.
Definition: qgstracer.cpp:614
void start()
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
bool contains(const Key &key) const
Custom exception class for Coordinate Reference System related exceptions.
double distance2D(const QgsPolyline &coords)
Definition: qgstracer.cpp:40
bool nextFeature(QgsFeature &f)
void clear()
int otherVertex(int v0) const
Definition: qgstracer.cpp:97
bool operator()(DijkstraQueueItem a, DijkstraQueueItem b)
Definition: qgstracer.cpp:32
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
bool empty() const
iterator end()
void extractLinework(const QgsGeometry *g, QgsMultiPolyline &mpl)
Definition: qgstracer.cpp:407
int point2edge(const QgsTracerGraph &g, const QgsPoint &pt, int &lineVertexAfter, double epsilon=1e-6)
Definition: qgstracer.cpp:270
iterator begin()
void setLayers(const QList< QgsVectorLayer *> &layers)
Set layers used for tracing.
Definition: qgstracer.cpp:561
void destroyed(QObject *obj)
QVector< QgsPoint > findShortestPath(const QgsPoint &p1, const QgsPoint &p2, PathError *error=nullptr)
Given two points, find the shortest path and return points on the way.
Definition: qgstracer.cpp:658
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
Points are not connected in the graph.
Definition: qgstracer.h:91
double x() const
Get the x value of the point.
Definition: qgspoint.h:128
Start point cannot be joined to the graph.
Definition: qgstracer.h:89
int v1
vertices that the edge connects
Definition: qgstracer.cpp:93
int joinVertexToGraph(QgsTracerGraph &g, const QgsPoint &pt)
Definition: qgstracer.cpp:308
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Set CRS used for tracing.
Definition: qgstracer.cpp:596