45 : mProvider( provider )
50 , mLabelLayer( toLabel )
51 , mDisplayAll( displayAll )
52 , mCentroidInside( false )
53 , mArrangement( arrangement )
54 , mMergeLines( false )
55 , mUpsidedownLabels( Upright )
57 mFeatureIndex =
new RTree<FeaturePart *, double, 2, double>();
60 if ( defaultPriority < 0.0001 )
62 else if ( defaultPriority > 1.0 )
83 if ( priority >= 1.0 )
85 else if ( priority <= 0.0001 )
93 if ( lf->
size().width() < 0 || lf->
size().height() < 0 )
96 QMutexLocker locker( &
mMutex );
110 bool addedFeature =
false;
112 double geom_size = -1, biggest_size = -1;
113 std::unique_ptr<FeaturePart> biggest_part;
116 std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries(
Util::unmulti( lf->
geometry() ) );
117 if ( !simpleGeometries )
126 while ( !simpleGeometries->isEmpty() )
128 const GEOSGeometry *geom = simpleGeometries->takeFirst();
131 if ( GEOSisValid_r( geosctxt, geom ) != 1 )
136 int type = GEOSGeomTypeId_r( geosctxt, geom );
138 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
143 std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom );
146 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
147 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
159 bool labelWellDefined = ( lf->size().width() > 0.0000001 && lf->size().height() > 0.0000001 );
161 if ( lf->isObstacle() && featureGeomIsObstacleGeom )
182 if ( !lf->labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
184 if ( type == GEOS_LINESTRING )
185 GEOSLength_r( geosctxt, geom, &geom_size );
186 else if ( type == GEOS_POLYGON )
187 GEOSArea_r( geosctxt, geom, &geom_size );
189 if ( geom_size > biggest_size )
191 biggest_size = geom_size;
192 biggest_part.reset( fpart.release() );
202 if ( lf->
isObstacle() && !featureGeomIsObstacleGeom )
206 if ( !simpleGeometries )
211 while ( !simpleGeometries->isEmpty() )
213 const GEOSGeometry *geom = simpleGeometries->takeFirst();
216 if ( GEOSisValid_r( geosctxt, geom ) != 1 )
221 int type = GEOSGeomTypeId_r( geosctxt, geom );
223 if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
228 std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom );
231 if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
232 ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
299 static FeaturePart *_findConnectedPart(
FeaturePart *partCheck,
const QVector<FeaturePart *> &otherParts )
302 auto it = otherParts.constBegin();
303 while ( it != otherParts.constEnd() )
319 int connectedFeaturesId = 0;
322 QVector<FeaturePart *> parts = it.value();
323 connectedFeaturesId++;
329 return a->
length() > b->length();
333 while ( parts.count() > 1 )
338 FeaturePart *otherPart = _findConnectedPart( partCheck, parts );
342 double checkpartBMin[2], checkpartBMax[2];
345 double otherPartBMin[2], otherPartBMax[2];
352 mFeatureIndex->Remove( checkpartBMin, checkpartBMax, partCheck );
353 mFeatureIndex->Remove( otherPartBMin, otherPartBMax, otherPart );
357 mFeatureIndex->Insert( otherPartBMin, otherPartBMax, otherPart );
379 QLinkedList<FeaturePart *> newFeatureParts;
382 std::unique_ptr< FeaturePart > fpart(
mFeatureParts.takeFirst() );
383 const GEOSGeometry *geom = fpart->geos();
384 double chopInterval = fpart->repeatDistance();
387 bool canChop =
false;
388 double featureLen = 0;
389 if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
391 ( void )GEOSLength_r( geosctxt, geom, &featureLen );
392 if ( featureLen > chopInterval )
397 bool shouldChop = canChop;
398 int possibleSegments = 0;
402 chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
405 possibleSegments =
static_cast< int >( std::floor( featureLen / chopInterval ) );
417 chopInterval = featureLen / possibleSegments;
419 shouldChop = possibleSegments > 1;
424 double bmin[2], bmax[2];
425 fpart->getBoundingBox( bmin, bmax );
428 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
432 GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
435 std::vector<Point> points( n );
436 for (
unsigned int i = 0; i < n; ++i )
438 GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
439 GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
443 std::vector<double> len( n, 0 );
444 for (
unsigned int i = 1; i < n; ++i )
446 double dx = points[i].x - points[i - 1].x;
447 double dy = points[i].y - points[i - 1].y;
448 len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
452 unsigned int cur = 0;
456 QList<FeaturePart *> repeatParts;
457 repeatParts.reserve( possibleSegments );
459 for (
int segment = 0; segment < possibleSegments; segment++ )
461 lambda += chopInterval;
462 for ( ; cur < n && lambda > len[cur]; ++cur )
464 part.push_back( points[cur] );
469 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
470 for (
int i = 0; i < part.size(); ++i )
472 GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
473 GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
475 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
477 newFeatureParts.append( newfpart );
480 repeatParts.push_back( newfpart );
484 double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
486 p.
x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x );
487 p.
y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y );
489 GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
490 for (
int i = 0; i < part.size(); ++i )
492 GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
493 GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
496 GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
498 newFeatureParts.append( newfpart );
503 repeatParts.push_back( newfpart );
507 part->setTotalRepeats( repeatParts.count() );
511 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)
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.
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged)...
bool isObstacle() const
Returns whether the feature will act as an obstacle for labels.
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.
RTree< FeaturePart *, double, 2, double, 8, 4 > * mFeatureIndex
void joinConnectedFeatures()
Join connected features with the same label text.
void getBoundingBox(double min[2], double max[2]) const
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.
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.
The QgsAbstractLabelProvider class is an interface class.
Thrown when a geometry type is not like expected.
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...
double length() const
Returns length of line geometry.
GEOSGeometry * obstacleGeometry() const
Returns the label's obstacle geometry, if different to the feature geometry.
QLinkedList< FeaturePart * > mFeatureParts
List of feature parts.
RTree< FeaturePart *, double, 2, double, 8, 4 > * mObstacleIndex
QSizeF size(double angle=0.0) const
Size of the label (in map units)
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 ...