45  : mProvider( provider )
 
   49  , mLabelLayer( toLabel )
 
   50  , mArrangement( arrangement )
 
   52  if ( defaultPriority < 0.0001 )
 
   54  else if ( defaultPriority > 1.0 )
 
 
   81  if ( lf->
size().width() < 0 || lf->
size().height() < 0 )
 
   84  QMutexLocker locker( &
mMutex );
 
   98  bool addedFeature = 
false;
 
  100  double geom_size = -1, biggest_size = -1;
 
  101  std::unique_ptr<FeaturePart> biggestPart;
 
  104  std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries( 
Util::unmulti( lf->
geometry() ) );
 
  105  if ( !simpleGeometries ) 
 
  114  while ( !simpleGeometries->isEmpty() )
 
  116    const GEOSGeometry *geom = simpleGeometries->takeFirst();
 
  119    if ( GEOSisValid_r( geosctxt, geom ) != 1 ) 
 
  124    const int type = GEOSGeomTypeId_r( geosctxt, geom );
 
  126    if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
 
  131    auto fpart = std::make_unique<FeaturePart>( lf, geom );
 
  134    if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
 
  135         ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
 
  147    const bool labelWellDefined = ( lf->
size().width() > 0.0000001 && lf->
size().height() > 0.0000001 );
 
  170    if ( !lf->
labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
 
  172      if ( type == GEOS_LINESTRING )
 
  173        geom_size = fpart->length();
 
  174      else if ( type == GEOS_POLYGON )
 
  175        geom_size = fpart->area();
 
  177      if ( geom_size > biggest_size )
 
  179        biggest_size = geom_size;
 
  180        biggestPart = std::move( fpart );
 
  202        QgsDebugError( QStringLiteral( 
"Obstacle geometry passed to PAL labeling engine could not be converted to GEOS! %1" ).arg( ( *it )->asWkt() ) );
 
  207      if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 ) 
 
  210        QgsDebugError( QStringLiteral( 
"Obstacle geometry passed to PAL labeling engine is not valid! %1" ).arg( ( *it )->asWkt() ) );
 
  214      const int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
 
  216      if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
 
  221      auto fpart = std::make_unique<FeaturePart>( lf, geom.get() );
 
  224      if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
 
  225           ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
 
 
  283  auto it = otherParts.constBegin();
 
  284  while ( it != otherParts.constEnd() )
 
  300  int connectedFeaturesId = 0;
 
  303    QVector<FeaturePart *> partsToMerge = it.value();
 
  309      return a->length() > b->length();
 
  313    while ( partsToMerge.count() > 1 )
 
  315      connectedFeaturesId++;
 
  318      FeaturePart *partToJoinTo = partsToMerge.takeFirst();
 
  322      QVector< FeaturePart *> partsLeftToTryThisRound = partsToMerge;
 
  323      while ( !partsLeftToTryThisRound.empty() )
 
  325        if ( 
FeaturePart *otherPart = _findConnectedPart( partToJoinTo, partsLeftToTryThisRound ) )
 
  327          partsLeftToTryThisRound.removeOne( otherPart );
 
  333            partsToMerge.removeAll( otherPart );
 
  334            const auto matchingPartIt = std::find_if( 
mFeatureParts.begin(), 
mFeatureParts.end(), [otherPart]( 
const std::unique_ptr< FeaturePart> &part ) { return part.get() == otherPart; } );
 
  352    if ( part->feature()->minimumSize() != 0.0 && part->length() < part->feature()->minimumSize() )
 
  357  } ), mFeatureParts.end() );
 
 
  368  std::deque< std::unique_ptr< FeaturePart > > newFeatureParts;
 
  371    std::unique_ptr< FeaturePart > fpart = std::move( 
mFeatureParts.front() );
 
  375    double chopInterval = fpart->repeatDistance();
 
  378    bool canChop = 
false;
 
  379    double featureLen = 0;
 
  380    if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
 
  382      featureLen = fpart->length();
 
  383      if ( featureLen > chopInterval )
 
  388    bool shouldChop = canChop;
 
  389    int possibleSegments = 0;
 
  393      chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
 
  396      possibleSegments = 
static_cast< int >( std::floor( featureLen / chopInterval ) );
 
  408      chopInterval = featureLen / possibleSegments;
 
  410      shouldChop = possibleSegments > 1;
 
  415      const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
 
  419      GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
 
  422      std::vector<Point> points( n );
 
  423      for ( 
unsigned int i = 0; i < n; ++i )
 
  425        GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
 
  429      std::vector<double> len( n, 0 );
 
  430      for ( 
unsigned int i = 1; i < n; ++i )
 
  432        const double dx = points[i].x - points[i - 1].x;
 
  433        const double dy = points[i].y - points[i - 1].y;
 
  434        len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
 
  438      unsigned int cur = 0;
 
  440      std::vector<Point> part;
 
  442      QList<FeaturePart *> repeatParts;
 
  443      repeatParts.reserve( possibleSegments );
 
  447        lambda += chopInterval;
 
  448        for ( ; cur < n && lambda > len[cur]; ++cur )
 
  450          part.push_back( points[cur] );
 
  455          GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, 
static_cast< unsigned int >( part.size() ), 2 );
 
  456          for ( 
unsigned int i = 0; i < part.size(); ++i )
 
  458            GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
 
  460          GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
 
  461          auto newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
 
  462          repeatParts.push_back( newfpart.get() );
 
  463          newFeatureParts.emplace_back( std::move( newfpart ) );
 
  466        const double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
 
  468        p.
x = points[cur - 1].x + 
c * ( points[cur].x - points[cur - 1].x );
 
  469        p.
y = points[cur - 1].y + 
c * ( points[cur].y - points[cur - 1].y );
 
  471        GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, 
static_cast< unsigned int >( part.size() ), 2 );
 
  472        for ( std::size_t i = 0; i < part.size(); ++i )
 
  474          GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
 
  477        GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
 
  478        auto newfpart = std::make_unique< FeaturePart >( fpart->feature(), newgeom );
 
  479        repeatParts.push_back( newfpart.get() );
 
  480        newFeatureParts.emplace_back( std::move( newfpart ) );
 
  489        partPtr->setTotalRepeats( repeatParts.count() );
 
  494      newFeatureParts.emplace_back( std::move( fpart ) );
 
 
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
 
An abstract interface class for label providers.
 
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 GEOSContextHandle_t get()
Returns a thread local instance of a GEOS context, safe for use in the current thread.
 
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
 
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.
 
GEOSGeometry * geometry() const
Gets access to the associated geometry.
 
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.
 
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.
 
Represents a part of a label 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.
 
int connectedFeatureId(QgsFeatureId featureId) const
Returns the connected feature ID for a label feature ID, which is unique for all features which have ...
 
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
 
Layer(QgsAbstractLabelProvider *provider, const QString &name, Qgis::LabelPlacement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal)
Create a new layer.
 
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.
 
double priority() const
Returns the layer's priority, between 0 and 1.
 
static QLinkedList< const GEOSGeometry * > * unmulti(const GEOSGeometry *the_geom)
 
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
 
#define QgsDebugError(str)
 
QLineF segment(int index, QRectF rect, double radius)
 
struct GEOSGeom_t GEOSGeometry