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 ) );