46 : mProvider( provider )
50 , mLabelLayer( toLabel )
51 , mDisplayAll( displayAll )
52 , mCentroidInside( false )
53 , mArrangement( arrangement )
54 , mMergeLines( false )
55 , mUpsidedownLabels( Upright )
57 if ( defaultPriority < 0.0001 )
59 else if ( defaultPriority > 1.0 )
87 if ( lf->
size().width() < 0 || lf->
size().height() < 0 )
90 QMutexLocker locker( &
mMutex );
104 bool addedFeature =
false;
106 double geom_size = -1, biggest_size = -1;
107 std::unique_ptr<FeaturePart> biggest_part;
110 std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries(
Util::unmulti( lf->
geometry() ) );
111 if ( !simpleGeometries )
120 while ( !simpleGeometries->isEmpty() )
122 const GEOSGeometry *geom = simpleGeometries->takeFirst();
125 if ( GEOSisValid_r( geosctxt, geom ) != 1 )
130 int type = GEOSGeomTypeId_r( geosctxt, geom );
132 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
137 std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom );
140 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
141 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
153 bool labelWellDefined = ( lf->
size().width() > 0.0000001 && lf->
size().height() > 0.0000001 );
176 if ( !lf->
labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
178 if ( type == GEOS_LINESTRING )
179 geom_size = fpart->length();
180 else if ( type == GEOS_POLYGON )
181 geom_size = fpart->area();
183 if ( geom_size > biggest_size )
185 biggest_size = geom_size;
186 biggest_part.reset( fpart.release() );
208 QgsDebugMsg( QStringLiteral(
"Obstacle geometry passed to PAL labeling engine could not be converted to GEOS! %1" ).arg( ( *it )->asWkt() ) );
213 if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 )
216 QgsDebugMsg( QStringLiteral(
"Obstacle geometry passed to PAL labeling engine is not valid! %1" ).arg( ( *it )->asWkt() ) );
220 int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
222 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
227 std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom.get() );
230 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
231 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
286 static FeaturePart *_findConnectedPart(
FeaturePart *partCheck,
const QVector<FeaturePart *> &otherParts )
289 auto it = otherParts.constBegin();
290 while ( it != otherParts.constEnd() )
306 int connectedFeaturesId = 0;
309 QVector<FeaturePart *> parts = it.value();
310 connectedFeaturesId++;
316 return a->length() > b->length();
320 while ( parts.count() > 1 )
325 FeaturePart *otherPart = _findConnectedPart( partCheck, parts );
351 QLinkedList<FeaturePart *> newFeatureParts;
354 std::unique_ptr< FeaturePart > fpart(
mFeatureParts.takeFirst() );
355 const GEOSGeometry *geom = fpart->geos();
356 double chopInterval = fpart->repeatDistance();
359 bool canChop =
false;
360 double featureLen = 0;
361 if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
363 featureLen = fpart->length();
364 if ( featureLen > chopInterval )
369 bool shouldChop = canChop;
370 int possibleSegments = 0;
374 chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
377 possibleSegments =
static_cast< int >( std::floor( featureLen / chopInterval ) );
389 chopInterval = featureLen / possibleSegments;
391 shouldChop = possibleSegments > 1;
396 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
400 GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
403 std::vector<Point> points( n );
404 for (
unsigned int i = 0; i < n; ++i )
406 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
407 GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
409 GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
410 GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
415 std::vector<double> len( n, 0 );
416 for (
unsigned int i = 1; i < n; ++i )
418 double dx = points[i].x - points[i - 1].x;
419 double dy = points[i].y - points[i - 1].y;
420 len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
424 unsigned int cur = 0;
426 std::vector<Point> part;
428 QList<FeaturePart *> repeatParts;
429 repeatParts.reserve( possibleSegments );
431 for (
int segment = 0; segment < possibleSegments; segment++ )
433 lambda += chopInterval;
434 for ( ; cur < n && lambda > len[cur]; ++cur )
436 part.push_back( points[cur] );
441 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt,
static_cast< unsigned int >( part.size() ), 2 );
442 for (
unsigned int i = 0; i < part.size(); ++i )
444 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
445 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
447 GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
448 GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
451 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
453 newFeatureParts.append( newfpart );
454 repeatParts.push_back( newfpart );
458 double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
460 p.
x = points[cur - 1].x +
c * ( points[cur].x - points[cur - 1].x );
461 p.
y = points[cur - 1].y +
c * ( points[cur].y - points[cur - 1].y );
463 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt,
static_cast< unsigned int >( part.size() ), 2 );
464 for ( std::size_t i = 0; i < part.size(); ++i )
466 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
467 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
469 GEOSCoordSeq_setX_r( geosctxt, cooSeq,
static_cast< unsigned int >( i ), part[i].x );
470 GEOSCoordSeq_setY_r( geosctxt, cooSeq,
static_cast< unsigned int >( i ), part[i].y );
474 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
476 newFeatureParts.append( newfpart );
479 repeatParts.push_back( newfpart );
483 partPtr->setTotalRepeats( repeatParts.count() );
487 newFeatureParts.append( fpart.release() );