31
31
32
32
// standard includes
33
33
#include < limits>
34
+ #include < algorithm>
35
+
36
+ class QgsPointCompare
37
+ {
38
+ public:
39
+ QgsPointCompare ( double tolerance ) :
40
+ mTolerance ( tolerance )
41
+ { }
42
+
43
+ bool operator ()( const QgsPoint& p1, const QgsPoint& p2 ) const
44
+ {
45
+ if ( mTolerance <= 0 )
46
+ return p1.x () == p2.x () ? p1.y () < p2.y () : p1.x () < p2.x ();
47
+
48
+ double tx1 = ceil ( p1.x ()/mTolerance );
49
+ double tx2 = ceil ( p2.x ()/mTolerance );
50
+ if ( tx1 == tx2 )
51
+ return ceil ( p1.y ()/mTolerance ) < ceil ( p2.y ()/mTolerance );
52
+ return tx1 < tx2;
53
+ }
54
+
55
+ private:
56
+ double mTolerance ;
57
+ };
58
+
59
+ template <typename RandIter, typename Type, typename CompareOp > RandIter my_binary_search ( RandIter begin, RandIter end, Type val, CompareOp comp)
60
+ {
61
+ // result if not found
62
+ RandIter not_found = end;
63
+
64
+ while ( true )
65
+ {
66
+ RandIter avg = begin + (end-begin)/2 ;
67
+ if ( begin == avg || end == avg )
68
+ {
69
+ if ( !comp ( *begin, val ) && !comp ( val, *begin ) )
70
+ return begin;
71
+ if ( !comp ( *end, val ) && !comp ( val, *end ) )
72
+ return end;
73
+
74
+ return not_found;
75
+ }
76
+ if ( comp ( val, *avg ) )
77
+ end = avg;
78
+ else if ( comp ( *avg, val ) )
79
+ begin = avg;
80
+ else
81
+ return avg;
82
+ }
83
+
84
+ return not_found;
85
+ }
34
86
35
87
QgsLineVectorLayerDirector::QgsLineVectorLayerDirector ( const QString& layerId,
36
88
int directionFieldId,
@@ -80,12 +132,16 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
80
132
}
81
133
82
134
tiedPoint = QVector< QgsPoint >( additionalPoints.size (), QgsPoint ( 0.0 , 0.0 ) );
135
+
83
136
TiePointInfo tmpInfo;
84
137
tmpInfo.mLength = std::numeric_limits<double >::infinity ();
85
138
86
139
QVector< TiePointInfo > pointLengthMap ( additionalPoints.size (), tmpInfo );
87
140
QVector< TiePointInfo >::iterator pointLengthIt;
88
141
142
+ // Graph's points;
143
+ QVector< QgsPoint > points;
144
+
89
145
// begin: tie points to the graph
90
146
QgsAttributeList la;
91
147
vl->select ( la );
@@ -98,7 +154,9 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
98
154
QgsPolyline::iterator pointIt;
99
155
for ( pointIt = pl.begin (); pointIt != pl.end (); ++pointIt )
100
156
{
101
- pt2 = builder->addVertex ( ct.transform ( *pointIt ) );
157
+ pt2 = ct.transform ( *pointIt );
158
+ points.push_back ( pt2 );
159
+
102
160
if ( !isFirstPoint )
103
161
{
104
162
int i = 0 ;
@@ -131,7 +189,6 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
131
189
}
132
190
emit buildProgress ( ++step, featureCount );
133
191
}
134
-
135
192
// end: tie points to graph
136
193
137
194
// add tied point to graph
@@ -140,10 +197,21 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
140
197
{
141
198
if ( tiedPoint[ i ] != QgsPoint ( 0.0 , 0.0 ) )
142
199
{
143
- tiedPoint[ i ] = builder->addVertex ( tiedPoint[ i ] );
144
- pointLengthMap[ i ].mTiedPoint = tiedPoint[ i ];
200
+ points.push_back ( tiedPoint [ i ] );
145
201
}
146
202
}
203
+
204
+ QgsPointCompare pointCompare ( builder->topologyTolerance () );
205
+
206
+ qSort ( points.begin (), points.end (), pointCompare );
207
+ QVector< QgsPoint >::iterator tmp = std::unique ( points.begin (), points.end () );
208
+ points.resize ( tmp - points.begin () );
209
+
210
+ for (i=0 ;i<points.size ();++i)
211
+ builder->addVertex ( i, points[ i ] );
212
+
213
+ for ( i = 0 ; i < tiedPoint.size () ; ++i)
214
+ tiedPoint[ i ] = *(my_binary_search ( points.begin (), points.end (), tiedPoint[ i ], pointCompare ) );
147
215
148
216
{ // fill attribute list 'la'
149
217
QgsAttributeList tmpAttr;
@@ -216,10 +284,10 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
216
284
QgsPolyline::iterator pointIt;
217
285
for ( pointIt = pl.begin (); pointIt != pl.end (); ++pointIt )
218
286
{
219
- pt2 = builder->addVertex ( ct.transform ( *pointIt ) );
287
+ pt2 = ct.transform ( *pointIt );
288
+
220
289
if ( !isFirstPoint )
221
290
{
222
-
223
291
std::map< double , QgsPoint > pointsOnArc;
224
292
pointsOnArc[ 0.0 ] = pt1;
225
293
pointsOnArc[ pt1.sqrDist ( pt2 )] = pt2;
@@ -236,11 +304,16 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
236
304
std::map< double , QgsPoint >::iterator pointsIt;
237
305
QgsPoint pt1;
238
306
QgsPoint pt2;
307
+ int pt1idx = -1 , pt2idx = -1 ;
239
308
bool isFirstPoint = true ;
240
309
for ( pointsIt = pointsOnArc.begin (); pointsIt != pointsOnArc.end (); ++pointsIt )
241
310
{
242
311
pt2 = pointsIt->second ;
243
- if ( !isFirstPoint )
312
+ tmp = my_binary_search ( points.begin (), points.end (), pt2, pointCompare );
313
+ pt2 = *tmp;
314
+ pt2idx = tmp - points.begin ();
315
+
316
+ if ( !isFirstPoint && pt1 != pt2 )
244
317
{
245
318
double distance = builder->distanceArea ()->measureLine ( pt1, pt2 );
246
319
QVector< QVariant > prop;
@@ -253,14 +326,15 @@ void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, c
253
326
if ( directionType == 1 ||
254
327
directionType == 3 )
255
328
{
256
- builder->addArc ( pt1, pt2, prop );
329
+ builder->addArc ( pt1idx, pt1, pt2idx , pt2, prop );
257
330
}
258
331
if ( directionType == 2 ||
259
332
directionType == 3 )
260
333
{
261
- builder->addArc ( pt2, pt1, prop );
334
+ builder->addArc ( pt2idx, pt2, pt1idx , pt1, prop );
262
335
}
263
336
}
337
+ pt1idx = pt2idx;
264
338
pt1 = pt2;
265
339
isFirstPoint = false ;
266
340
}
0 commit comments