45 : mProvider( provider )
49 , mLabelLayer( toLabel )
50 , mDisplayAll( displayAll )
51 , mCentroidInside( false )
52 , mArrangement( arrangement )
53 , mMergeLines( false )
54 , mUpsidedownLabels( Upright )
56 if ( defaultPriority < 0.0001 )
58 else if ( defaultPriority > 1.0 )
76 if ( priority >= 1.0 )
78 else if ( priority <= 0.0001 )
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> biggest_part;
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 = qgis::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 );
154 if ( lf->obstacleSettings().isObstacle() && featureGeomIsObstacleGeom )
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 biggest_part.reset( fpart.release() );
206 if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 )
211 int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
213 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
218 std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom.get() );
221 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
222 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
277 static FeaturePart *_findConnectedPart(
FeaturePart *partCheck,
const QVector<FeaturePart *> &otherParts )
280 auto it = otherParts.constBegin();
281 while ( it != otherParts.constEnd() )
297 int connectedFeaturesId = 0;
300 QVector<FeaturePart *> parts = it.value();
301 connectedFeaturesId++;
307 return a->
length() > b->length();
311 while ( parts.count() > 1 )
316 FeaturePart *otherPart = _findConnectedPart( partCheck, parts );
342 QLinkedList<FeaturePart *> newFeatureParts;
345 std::unique_ptr< FeaturePart > fpart(
mFeatureParts.takeFirst() );
346 const GEOSGeometry *geom = fpart->geos();
347 double chopInterval = fpart->repeatDistance();
350 bool canChop =
false;
351 double featureLen = 0;
352 if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
354 featureLen = fpart->length();
355 if ( featureLen > chopInterval )
360 bool shouldChop = canChop;
361 int possibleSegments = 0;
365 chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
368 possibleSegments =
static_cast< int >( std::floor( featureLen / chopInterval ) );
380 chopInterval = featureLen / possibleSegments;
382 shouldChop = possibleSegments > 1;
387 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
391 GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
394 std::vector<Point> points( n );
395 for (
unsigned int i = 0; i < n; ++i )
397 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 398 GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
400 GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
401 GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
406 std::vector<double> len( n, 0 );
407 for (
unsigned int i = 1; i < n; ++i )
409 double dx = points[i].x - points[i - 1].x;
410 double dy = points[i].y - points[i - 1].y;
411 len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
415 unsigned int cur = 0;
417 std::vector<Point> part;
419 QList<FeaturePart *> repeatParts;
420 repeatParts.reserve( possibleSegments );
422 for (
int segment = 0; segment < possibleSegments; segment++ )
424 lambda += chopInterval;
425 for ( ; cur < n && lambda > len[cur]; ++cur )
427 part.push_back( points[cur] );
432 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, static_cast< unsigned int >( part.size() ), 2 );
433 for (
unsigned int i = 0; i < part.size(); ++i )
435 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 436 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
438 GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
439 GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
442 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
444 newFeatureParts.append( newfpart );
445 repeatParts.push_back( newfpart );
449 double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
451 p.
x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x );
452 p.
y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y );
454 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, static_cast< unsigned int >( part.size() ), 2 );
455 for ( std::size_t i = 0; i < part.size(); ++i )
457 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 458 GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
460 GEOSCoordSeq_setX_r( geosctxt, cooSeq, static_cast< unsigned int >( i ), part[i].x );
461 GEOSCoordSeq_setY_r( geosctxt, cooSeq, static_cast< unsigned int >( i ), part[i].y );
465 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
467 newFeatureParts.append( newfpart );
470 repeatParts.push_back( newfpart );
474 partPtr->setTotalRepeats( repeatParts.count() );
478 newFeatureParts.append( fpart.release() );
QList< FeaturePart * > mObstacleParts
List of obstacle parts.
QHash< QgsFeatureId, int > mConnectedFeaturesIds
QString labelText() const
Text of the label.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)
QHash< QgsFeatureId, QgsLabelFeature * > mHashtable
Lookup table of label features (owned by the label feature provider that created them) ...
static QLinkedList< const GEOSGeometry * > * unmulti(const GEOSGeometry *the_geom)
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
void setPriority(double priority)
Sets the layer's priority.
void chopFeaturesAtRepeatDistance()
Chop layer features at the repeat distance *.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
A geometry is the spatial representation of a 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 GEOSContextHandle_t getGEOSHandler()
QHash< QString, QVector< FeaturePart * > > mConnectedHashtable
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
double priority() const
Returns the layer's priority, between 0 and 1.
void joinConnectedFeatures()
Join connected features with the same label text.
QgsGeometry obstacleGeometry() const
Returns the label's obstacle geometry, if different to the feature geometry.
void addObstaclePart(FeaturePart *fpart)
Add newly created obstacle part into r tree and to the list.
void setLayer(pal::Layer *layer)
Assign PAL layer to the label feature. Should be only used internally in PAL.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Layer(QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll=false)
Create a new layer.
Main class to handle feature.
A generic rtree spatial index based on a libspatialindex backend.
The QgsAbstractLabelProvider class is an interface class.
Thrown when a geometry type is not like expected.
const QgsLabelObstacleSettings & obstacleSettings() const
Returns the label's obstacle settings.
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
Placement
Placement modes which determine how label candidates are generated for a feature. ...
static int reorderPolygon(int nbPoints, 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...
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
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...
double length() const
Returns length of line geometry.
QLinkedList< FeaturePart * > mFeatureParts
List of feature parts.
QSizeF size(double angle=0.0) const
Size of the label (in map units)
std::vector< geos::unique_ptr > mGeosObstacleGeometries
bool isObstacle() const
Returns true if the features are obstacles to labels of other layers.
bool labelAllParts() const
Returns true if all parts of the feature should be labeled.
void addFeaturePart(FeaturePart *fpart, const QString &labelText=QString())
Add newly created feature part into r tree and to the list.
int connectedFeatureId(QgsFeatureId featureId) const
Returns the connected feature ID for a label feature ID, which is unique for all features which have ...