46 : mProvider( provider )
50 , mLabelLayer( toLabel )
51 , mArrangement( arrangement )
53 if ( defaultPriority < 0.0001 )
55 else if ( defaultPriority > 1.0 )
82 if ( lf->
size().width() < 0 || lf->
size().height() < 0 )
85 QMutexLocker locker( &
mMutex );
99 bool addedFeature =
false;
101 double geom_size = -1, biggest_size = -1;
102 std::unique_ptr<FeaturePart> biggestPart;
105 std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries(
Util::unmulti( lf->
geometry() ) );
106 if ( !simpleGeometries )
115 while ( !simpleGeometries->isEmpty() )
117 const GEOSGeometry *geom = simpleGeometries->takeFirst();
120 if ( GEOSisValid_r( geosctxt, geom ) != 1 )
125 const int type = GEOSGeomTypeId_r( geosctxt, geom );
127 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
132 std::unique_ptr<FeaturePart> fpart = std::make_unique<FeaturePart>( lf, geom );
135 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
136 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
148 const bool labelWellDefined = ( lf->
size().width() > 0.0000001 && lf->
size().height() > 0.0000001 );
171 if ( !lf->
labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
173 if ( type == GEOS_LINESTRING )
174 geom_size = fpart->length();
175 else if ( type == GEOS_POLYGON )
176 geom_size = fpart->area();
178 if ( geom_size > biggest_size )
180 biggest_size = geom_size;
181 biggestPart = std::move( fpart );
203 QgsDebugMsg( QStringLiteral(
"Obstacle geometry passed to PAL labeling engine could not be converted to GEOS! %1" ).arg( ( *it )->asWkt() ) );
208 if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 )
211 QgsDebugMsg( QStringLiteral(
"Obstacle geometry passed to PAL labeling engine is not valid! %1" ).arg( ( *it )->asWkt() ) );
215 const int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
217 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
222 std::unique_ptr<FeaturePart> fpart = std::make_unique<FeaturePart>( lf, geom.get() );
225 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
226 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
281 static FeaturePart *_findConnectedPart(
FeaturePart *partCheck,
const QVector<FeaturePart *> &otherParts )
284 auto it = otherParts.constBegin();
285 while ( it != otherParts.constEnd() )
301 int connectedFeaturesId = 0;
304 QVector<FeaturePart *> partsToMerge = it.value();
310 return a->length() > b->length();
314 while ( partsToMerge.count() > 1 )
316 connectedFeaturesId++;
319 FeaturePart *partToJoinTo = partsToMerge.takeFirst();
323 QVector< FeaturePart *> partsLeftToTryThisRound = partsToMerge;
324 while ( !partsLeftToTryThisRound.empty() )
326 if (
FeaturePart *otherPart = _findConnectedPart( partToJoinTo, partsLeftToTryThisRound ) )
328 partsLeftToTryThisRound.removeOne( otherPart );
334 partsToMerge.removeAll( otherPart );
335 const auto matchingPartIt = std::find_if(
mFeatureParts.begin(),
mFeatureParts.end(), [otherPart](
const std::unique_ptr< FeaturePart> &part ) { return part.get() == otherPart; } );
353 if ( part->feature()->minimumSize() != 0.0 && part->length() < part->feature()->minimumSize() )
358 } ), mFeatureParts.end() );
369 std::deque< std::unique_ptr< FeaturePart > > newFeatureParts;
372 std::unique_ptr< FeaturePart > fpart = std::move(
mFeatureParts.front() );
375 const GEOSGeometry *geom = fpart->geos();
376 double chopInterval = fpart->repeatDistance();
379 bool canChop =
false;
380 double featureLen = 0;
381 if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
383 featureLen = fpart->length();
384 if ( featureLen > chopInterval )
389 bool shouldChop = canChop;
390 int possibleSegments = 0;
394 chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
397 possibleSegments =
static_cast< int >( std::floor( featureLen / chopInterval ) );
409 chopInterval = featureLen / possibleSegments;
411 shouldChop = possibleSegments > 1;
416 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
420 GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
423 std::vector<Point> points( n );
424 for (
unsigned int i = 0; i < n; ++i )
426 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
427 GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
429 GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
430 GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
435 std::vector<double> len( n, 0 );
436 for (
unsigned int i = 1; i < n; ++i )
438 const double dx = points[i].x - points[i - 1].x;
439 const double dy = points[i].y - points[i - 1].y;
440 len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
444 unsigned int cur = 0;
446 std::vector<Point> part;
448 QList<FeaturePart *> repeatParts;
449 repeatParts.reserve( possibleSegments );
453 lambda += chopInterval;
454 for ( ; cur < n && lambda > len[cur]; ++cur )
456 part.push_back( points[cur] );
461 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt,
static_cast< unsigned int >( part.size() ), 2 );
462 for (
unsigned int i = 0; i < part.size(); ++i )
464 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
465 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
467 GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
468 GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
471 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
472 std::unique_ptr< FeaturePart > newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
473 repeatParts.push_back( newfpart.get() );
474 newFeatureParts.emplace_back( std::move( newfpart ) );
477 const double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
479 p.
x = points[cur - 1].x +
c * ( points[cur].x - points[cur - 1].x );
480 p.
y = points[cur - 1].y +
c * ( points[cur].y - points[cur - 1].y );
482 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt,
static_cast< unsigned int >( part.size() ), 2 );
483 for ( std::size_t i = 0; i < part.size(); ++i )
485 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
486 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
488 GEOSCoordSeq_setX_r( geosctxt, cooSeq,
static_cast< unsigned int >( i ), part[i].x );
489 GEOSCoordSeq_setY_r( geosctxt, cooSeq,
static_cast< unsigned int >( i ), part[i].y );
493 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
494 std::unique_ptr< FeaturePart > newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
495 repeatParts.push_back( newfpart.get() );
496 newFeatureParts.emplace_back( std::move( newfpart ) );
502 partPtr->setTotalRepeats( repeatParts.count() );
506 newFeatureParts.emplace_back( std::move( fpart ) );