@@ -61,7 +61,8 @@ namespace pal
61
61
, mMergeLines ( false )
62
62
, mUpsidedownLabels ( Upright )
63
63
{
64
- rtree = new RTree<FeaturePart*, double , 2 , double >();
64
+ mFeatureIndex = new RTree<FeaturePart*, double , 2 , double >();
65
+ mObstacleIndex = new RTree<FeaturePart*, double , 2 , double >();
65
66
66
67
if ( defaultPriority < 0.0001 )
67
68
mDefaultPriority = 0.0001 ;
@@ -76,13 +77,13 @@ namespace pal
76
77
mMutex .lock ();
77
78
78
79
qDeleteAll ( mFeatureParts );
79
- mFeatureParts . clear ( );
80
+ qDeleteAll ( mObstacleParts );
80
81
81
82
// should already be empty
82
83
qDeleteAll ( mConnectedHashtable );
83
- mConnectedHashtable .clear ();
84
84
85
- delete rtree;
85
+ delete mFeatureIndex ;
86
+ delete mObstacleIndex ;
86
87
87
88
mMutex .unlock ();
88
89
}
@@ -132,6 +133,8 @@ namespace pal
132
133
133
134
GEOSContextHandle_t geosctxt = geosContext ();
134
135
136
+ bool featureGeomIsObstacleGeom = !lf->obstacleGeometry ();
137
+
135
138
while ( simpleGeometries->size () > 0 )
136
139
{
137
140
const GEOSGeometry* geom = simpleGeometries->takeFirst ();
@@ -168,6 +171,32 @@ namespace pal
168
171
continue ;
169
172
}
170
173
174
+ // is the feature well defined? TODO Check epsilon
175
+ bool labelWellDefined = ( lf->size ().width () > 0.0000001 && lf->size ().height () > 0.0000001 );
176
+
177
+ if ( lf->isObstacle () && featureGeomIsObstacleGeom )
178
+ {
179
+ // if we are not labelling the layer, only insert it into the obstacle list and avoid an
180
+ // unnecessary copy
181
+ if ( mLabelLayer && labelWellDefined )
182
+ {
183
+ addObstaclePart ( new FeaturePart ( *fpart ) );
184
+ }
185
+ else
186
+ {
187
+ addObstaclePart ( fpart );
188
+ fpart = 0 ;
189
+ }
190
+ }
191
+
192
+ // feature has to be labeled?
193
+ if ( !mLabelLayer || !labelWellDefined )
194
+ {
195
+ // nothing more to do for this part
196
+ delete fpart;
197
+ continue ;
198
+ }
199
+
171
200
if ( mMode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
172
201
{
173
202
if ( type == GEOS_LINESTRING )
@@ -186,7 +215,6 @@ namespace pal
186
215
delete fpart;
187
216
}
188
217
continue ; // don't add the feature part now, do it later
189
- // TODO: we should probably add also other parts to act just as obstacles
190
218
}
191
219
192
220
// feature part is ready!
@@ -195,6 +223,57 @@ namespace pal
195
223
}
196
224
delete simpleGeometries;
197
225
226
+ if ( !featureGeomIsObstacleGeom )
227
+ {
228
+ // do the same for the obstacle geometry
229
+ simpleGeometries = unmulti ( lf->obstacleGeometry () );
230
+ if ( simpleGeometries == NULL ) // unmulti() failed?
231
+ {
232
+ mMutex .unlock ();
233
+ throw InternalException::UnknownGeometry ();
234
+ }
235
+
236
+ while ( simpleGeometries->size () > 0 )
237
+ {
238
+ const GEOSGeometry* geom = simpleGeometries->takeFirst ();
239
+
240
+ // ignore invalid geometries (e.g. polygons with self-intersecting rings)
241
+ if ( GEOSisValid_r ( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
242
+ {
243
+ continue ;
244
+ }
245
+
246
+ int type = GEOSGeomTypeId_r ( geosctxt, geom );
247
+
248
+ if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
249
+ {
250
+ mMutex .unlock ();
251
+ throw InternalException::UnknownGeometry ();
252
+ }
253
+
254
+ FeaturePart* fpart = new FeaturePart ( lf, geom );
255
+
256
+ // ignore invalid geometries
257
+ if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
258
+ ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
259
+ {
260
+ delete fpart;
261
+ continue ;
262
+ }
263
+
264
+ // polygons: reorder coordinates
265
+ if ( type == GEOS_POLYGON && reorderPolygon ( fpart->nbPoints , fpart->x , fpart->y ) != 0 )
266
+ {
267
+ delete fpart;
268
+ continue ;
269
+ }
270
+
271
+ // feature part is ready!
272
+ addObstaclePart ( fpart );
273
+ }
274
+ delete simpleGeometries;
275
+ }
276
+
198
277
mMutex .unlock ();
199
278
200
279
// if using only biggest parts...
@@ -224,7 +303,7 @@ namespace pal
224
303
mFeatureParts << fpart;
225
304
226
305
// add to r-tree for fast spatial access
227
- rtree ->Insert ( bmin, bmax, fpart );
306
+ mFeatureIndex ->Insert ( bmin, bmax, fpart );
228
307
229
308
// add to hashtable with equally named feature parts
230
309
if ( mMergeLines && !labelText.isEmpty () )
@@ -245,6 +324,19 @@ namespace pal
245
324
}
246
325
}
247
326
327
+ void Layer::addObstaclePart ( FeaturePart* fpart )
328
+ {
329
+ double bmin[2 ];
330
+ double bmax[2 ];
331
+ fpart->getBoundingBox ( bmin, bmax );
332
+
333
+ // add to list of layer's feature parts
334
+ mObstacleParts .append ( fpart );
335
+
336
+ // add to obstacle r-tree
337
+ mObstacleIndex ->Insert ( bmin, bmax, fpart );
338
+ }
339
+
248
340
static FeaturePart* _findConnectedPart ( FeaturePart* partCheck, QLinkedList<FeaturePart*>* otherParts )
249
341
{
250
342
// iterate in the rest of the parts with the same label
@@ -286,7 +378,7 @@ namespace pal
286
378
// remove partCheck from r-tree
287
379
double bmin[2 ], bmax[2 ];
288
380
partCheck->getBoundingBox ( bmin, bmax );
289
- rtree ->Remove ( bmin, bmax, partCheck );
381
+ mFeatureIndex ->Remove ( bmin, bmax, partCheck );
290
382
mFeatureParts .removeOne ( partCheck );
291
383
292
384
otherPart->getBoundingBox ( bmin, bmax );
@@ -295,9 +387,9 @@ namespace pal
295
387
if ( otherPart->mergeWithFeaturePart ( partCheck ) )
296
388
{
297
389
// reinsert p->item to r-tree (probably not needed)
298
- rtree ->Remove ( bmin, bmax, otherPart );
390
+ mFeatureIndex ->Remove ( bmin, bmax, otherPart );
299
391
otherPart->getBoundingBox ( bmin, bmax );
300
- rtree ->Insert ( bmin, bmax, otherPart );
392
+ mFeatureIndex ->Insert ( bmin, bmax, otherPart );
301
393
}
302
394
delete partCheck;
303
395
}
@@ -331,7 +423,7 @@ namespace pal
331
423
332
424
double bmin[2 ], bmax[2 ];
333
425
fpart->getBoundingBox ( bmin, bmax );
334
- rtree ->Remove ( bmin, bmax, fpart );
426
+ mFeatureIndex ->Remove ( bmin, bmax, fpart );
335
427
336
428
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r ( geosctxt, geom );
337
429
@@ -387,7 +479,7 @@ namespace pal
387
479
FeaturePart* newfpart = new FeaturePart ( fpart->feature (), newgeom );
388
480
newFeatureParts.append ( newfpart );
389
481
newfpart->getBoundingBox ( bmin, bmax );
390
- rtree ->Insert ( bmin, bmax, newfpart );
482
+ mFeatureIndex ->Insert ( bmin, bmax, newfpart );
391
483
part.clear ();
392
484
part.push_back ( p );
393
485
}
@@ -404,7 +496,7 @@ namespace pal
404
496
FeaturePart* newfpart = new FeaturePart ( fpart->feature (), newgeom );
405
497
newFeatureParts.append ( newfpart );
406
498
newfpart->getBoundingBox ( bmin, bmax );
407
- rtree ->Insert ( bmin, bmax, newfpart );
499
+ mFeatureIndex ->Insert ( bmin, bmax, newfpart );
408
500
delete fpart;
409
501
}
410
502
else
0 commit comments