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 )
 
   86   if ( lf->
size().width() < 0 || lf->
size().height() < 0 )
 
   89   QMutexLocker locker( &
mMutex );
 
  103   bool addedFeature = 
false;
 
  105   double geom_size = -1, biggest_size = -1;
 
  106   std::unique_ptr<FeaturePart> biggestPart;
 
  109   std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries( 
Util::unmulti( lf->
geometry() ) );
 
  110   if ( !simpleGeometries ) 
 
  119   while ( !simpleGeometries->isEmpty() )
 
  121     const GEOSGeometry *geom = simpleGeometries->takeFirst();
 
  124     if ( GEOSisValid_r( geosctxt, geom ) != 1 ) 
 
  129     int type = GEOSGeomTypeId_r( geosctxt, geom );
 
  131     if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
 
  136     std::unique_ptr<FeaturePart> fpart = std::make_unique<FeaturePart>( lf, geom );
 
  139     if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
 
  140          ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
 
  152     bool labelWellDefined = ( lf->
size().width() > 0.0000001 && lf->
size().height() > 0.0000001 );
 
  175     if ( !lf->
labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
 
  177       if ( type == GEOS_LINESTRING )
 
  178         geom_size = fpart->length();
 
  179       else if ( type == GEOS_POLYGON )
 
  180         geom_size = fpart->area();
 
  182       if ( geom_size > biggest_size )
 
  184         biggest_size = geom_size;
 
  185         biggestPart = std::move( fpart );
 
  207         QgsDebugMsg( QStringLiteral( 
"Obstacle geometry passed to PAL labeling engine could not be converted to GEOS! %1" ).arg( ( *it )->asWkt() ) );
 
  212       if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 ) 
 
  215         QgsDebugMsg( QStringLiteral( 
"Obstacle geometry passed to PAL labeling engine is not valid! %1" ).arg( ( *it )->asWkt() ) );
 
  219       int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
 
  221       if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
 
  226       std::unique_ptr<FeaturePart> fpart = std::make_unique<FeaturePart>( lf, geom.get() );
 
  229       if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
 
  230            ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
 
  285 static FeaturePart *_findConnectedPart( 
FeaturePart *partCheck, 
const QVector<FeaturePart *> &otherParts )
 
  288   auto it = otherParts.constBegin();
 
  289   while ( it != otherParts.constEnd() )
 
  305   int connectedFeaturesId = 0;
 
  308     QVector<FeaturePart *> partsToMerge = it.value();
 
  314       return a->length() > b->length();
 
  318     while ( partsToMerge.count() > 1 )
 
  320       connectedFeaturesId++;
 
  323       FeaturePart *partToJoinTo = partsToMerge.takeFirst();
 
  327       QVector< FeaturePart *> partsLeftToTryThisRound = partsToMerge;
 
  328       while ( !partsLeftToTryThisRound.empty() )
 
  330         if ( 
FeaturePart *otherPart = _findConnectedPart( partToJoinTo, partsLeftToTryThisRound ) )
 
  332           partsLeftToTryThisRound.removeOne( otherPart );
 
  338             partsToMerge.removeAll( otherPart );
 
  339             auto matchingPartIt = std::find_if( 
mFeatureParts.begin(), 
mFeatureParts.end(), [otherPart]( 
const std::unique_ptr< FeaturePart> &part ) { return part.get() == otherPart; } );
 
  357     if ( part->feature()->minimumSize() != 0.0 && part->length() < part->feature()->minimumSize() )
 
  362   } ), mFeatureParts.end() );
 
  373   std::deque< std::unique_ptr< FeaturePart > > newFeatureParts;
 
  376     std::unique_ptr< FeaturePart > fpart = std::move( 
mFeatureParts.front() );
 
  379     const GEOSGeometry *geom = fpart->geos();
 
  380     double chopInterval = fpart->repeatDistance();
 
  383     bool canChop = 
false;
 
  384     double featureLen = 0;
 
  385     if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
 
  387       featureLen = fpart->length();
 
  388       if ( featureLen > chopInterval )
 
  393     bool shouldChop = canChop;
 
  394     int possibleSegments = 0;
 
  398       chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
 
  401       possibleSegments = 
static_cast< int >( std::floor( featureLen / chopInterval ) );
 
  413       chopInterval = featureLen / possibleSegments;
 
  415       shouldChop = possibleSegments > 1;
 
  420       const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
 
  424       GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
 
  427       std::vector<Point> points( n );
 
  428       for ( 
unsigned int i = 0; i < n; ++i )
 
  430 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  431         GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
 
  433         GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
 
  434         GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
 
  439       std::vector<double> len( n, 0 );
 
  440       for ( 
unsigned int i = 1; i < n; ++i )
 
  442         double dx = points[i].x - points[i - 1].x;
 
  443         double dy = points[i].y - points[i - 1].y;
 
  444         len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
 
  448       unsigned int cur = 0;
 
  450       std::vector<Point> part;
 
  452       QList<FeaturePart *> repeatParts;
 
  453       repeatParts.reserve( possibleSegments );
 
  457         lambda += chopInterval;
 
  458         for ( ; cur < n && lambda > len[cur]; ++cur )
 
  460           part.push_back( points[cur] );
 
  465           GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, 
static_cast< unsigned int >( part.size() ), 2 );
 
  466           for ( 
unsigned int i = 0; i < part.size(); ++i )
 
  468 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  469             GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
 
  471             GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
 
  472             GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
 
  475           GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
 
  476           std::unique_ptr< FeaturePart > newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
 
  477           repeatParts.push_back( newfpart.get() );
 
  478           newFeatureParts.emplace_back( std::move( newfpart ) );
 
  481         double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
 
  483         p.
x = points[cur - 1].x + 
c * ( points[cur].x - points[cur - 1].x );
 
  484         p.
y = points[cur - 1].y + 
c * ( points[cur].y - points[cur - 1].y );
 
  486         GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, 
static_cast< unsigned int >( part.size() ), 2 );
 
  487         for ( std::size_t i = 0; i < part.size(); ++i )
 
  489 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  490           GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
 
  492           GEOSCoordSeq_setX_r( geosctxt, cooSeq, 
static_cast< unsigned int >( i ), part[i].x );
 
  493           GEOSCoordSeq_setY_r( geosctxt, cooSeq, 
static_cast< unsigned int >( i ), part[i].y );
 
  497         GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
 
  498         std::unique_ptr< FeaturePart > newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
 
  499         repeatParts.push_back( newfpart.get() );
 
  500         newFeatureParts.emplace_back( std::move( newfpart ) );
 
  506         partPtr->setTotalRepeats( repeatParts.count() );
 
  510       newFeatureParts.emplace_back( std::move( fpart ) );
 
The QgsAbstractLabelProvider class is an interface class.
A generic rtree spatial index based on a libspatialindex backend.
A geometry is the spatial representation of a feature.
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0)
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
static GEOSContextHandle_t getGEOSHandler()
The QgsLabelFeature class describes a feature that should be used within the labeling engine.
const QgsLabelObstacleSettings & obstacleSettings() const
Returns the label's obstacle settings.
QSizeF size(double angle=0.0) const
Size of the label (in map units)
void setLayer(pal::Layer *layer)
Assign PAL layer to the label feature. Should be only used internally in PAL.
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
QString labelText() const
Text of the label.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
bool labelAllParts() const
Returns true if all parts of the feature should be labeled.
bool isObstacle() const
Returns true if the features are obstacles to labels of other layers.
QgsGeometry obstacleGeometry() const
Returns the label's obstacle geometry, if different to the feature geometry.
Placement
Placement modes which determine how label candidates are generated for a feature.
Main class to handle feature.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged).
bool isConnected(FeaturePart *p2)
Check whether this part is connected with some other part.
static bool reorderPolygon(std::vector< double > &x, std::vector< double > &y)
Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside.
Thrown when a geometry type is not like expected.
QHash< QString, QVector< FeaturePart * > > mConnectedHashtable
std::deque< std::unique_ptr< FeaturePart > > mFeatureParts
List of feature parts.
QList< FeaturePart * > mObstacleParts
List of obstacle parts.
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
void addFeaturePart(std::unique_ptr< FeaturePart > fpart, const QString &labelText=QString())
Add newly created feature part into r tree and to the list.
QHash< QgsFeatureId, int > mConnectedFeaturesIds
void joinConnectedFeatures()
Join connected features with the same label text.
QHash< QgsFeatureId, QgsLabelFeature * > mHashtable
Lookup table of label features (owned by the label feature provider that created them)
void chopFeaturesAtRepeatDistance()
Chop layer features at the repeat distance.
std::vector< geos::unique_ptr > mGeosObstacleGeometries
void addObstaclePart(FeaturePart *fpart)
Add newly created obstacle part into r tree and to the list.
void setPriority(double priority)
Sets the layer's priority.
Layer(QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll=false)
Create a new layer.
double priority() const
Returns the layer's priority, between 0 and 1.
static QLinkedList< const GEOSGeometry * > * unmulti(const GEOSGeometry *the_geom)
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QLineF segment(int index, QRectF rect, double radius)