42 #include <QLinkedList> 47 #define M_PI 3.14159265358979323846 56 mGeos =
const_cast<GEOSGeometry*
>( geom );
62 for (
int i = 0; i <
mHoles.count(); i++ )
64 mHoles.at( i )->holeOf =
this;
76 mHoles.last()->holeOf =
this;
90 const GEOSCoordSequence *coordSeq;
93 type = GEOSGeomTypeId_r( geosctxt, geom );
95 if (
type == GEOS_POLYGON )
97 if ( GEOSGetNumInteriorRings_r( geosctxt, geom ) > 0 )
99 int numHoles = GEOSGetNumInteriorRings_r( geosctxt, geom );
101 for (
int i = 0; i < numHoles; ++i )
103 const GEOSGeometry* interior = GEOSGetInteriorRingN_r( geosctxt, geom, i );
115 geom = GEOSGetExteriorRing_r( geosctxt, geom );
124 nbPoints = GEOSGetNumCoordinates_r( geosctxt, geom );
125 coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, geom );
136 for (
int i = 0; i <
nbPoints; ++i )
138 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &
x[i] );
139 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &
y[i] );
181 qreal quadOffsetX = quadOffset.
x(), quadOffsetY = quadOffset.
y();
183 if ( quadOffsetX < 0 )
185 if ( quadOffsetY < 0 )
189 else if ( quadOffsetY > 0 )
198 else if ( quadOffsetX > 0 )
200 if ( quadOffsetY < 0 )
204 else if ( quadOffsetY > 0 )
215 if ( quadOffsetY < 0 )
219 else if ( quadOffsetY > 0 )
238 double cost = 0.0001;
241 double xdiff = -labelW / 2.0;
242 double ydiff = -labelH / 2.0;
257 double xd = xdiff * cos( angle ) - ydiff * sin( angle );
258 double yd = xdiff * sin( angle ) + ydiff * cos( angle );
294 double lx = x + xdiff;
295 double ly = y + ydiff;
305 lPos <<
new LabelPosition(
id, lx, ly, labelW, labelH, angle, cost,
this,
false, quadrantFromOffset() );
320 double cost = 0.0001;
333 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
334 deltaY = -visualMargin.
bottom + symbolHeightOffset;
340 deltaX = -labelWidth / 4.0 - visualMargin.
left;
341 deltaY = -visualMargin.
bottom + symbolHeightOffset;
347 deltaX = -labelWidth / 2.0;
348 deltaY = -visualMargin.
bottom + symbolHeightOffset;
354 deltaX = -labelWidth * 3.0 / 4.0 + visualMargin.
right;
355 deltaY = -visualMargin.
bottom + symbolHeightOffset;
361 deltaX = - visualMargin.
left + symbolWidthOffset;
362 deltaY = -visualMargin.
bottom + symbolHeightOffset;
368 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
369 deltaY = -labelHeight / 2.0;
375 deltaX = -visualMargin.
left + symbolWidthOffset;
376 deltaY = -labelHeight / 2.0;
382 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
383 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
389 deltaX = -labelWidth / 4.0 - visualMargin.
left;
390 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
396 deltaX = -labelWidth / 2.0;
397 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
403 deltaX = -labelWidth * 3.0 / 4.0 + visualMargin.
right;
404 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
410 deltaX = -visualMargin.
left + symbolWidthOffset;
411 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
416 double referenceX = cos( alpha ) * distanceToLabel +
x;
417 double referenceY = sin( alpha ) * distanceToLabel +
y;
419 double labelX = referenceX + deltaX;
420 double labelY = referenceY + deltaY;
422 lPos <<
new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost,
this,
false, quadrant );
444 double candidateAngleIncrement = 2 *
M_PI / numberCandidates;
447 double a90 =
M_PI / 2;
449 double a270 = a180 + a90;
450 double a360 = 2 *
M_PI;
452 double gamma1, gamma2;
454 if ( distanceToLabel > 0 )
456 gamma1 = atan2( labelHeight / 2, distanceToLabel + labelWidth / 2 );
457 gamma2 = atan2( labelWidth / 2, distanceToLabel + labelHeight / 2 );
461 gamma1 = gamma2 = a90 / 3.0;
464 if ( gamma1 > a90 / 3.0 )
467 if ( gamma2 > a90 / 3.0 )
473 double angleToCandidate;
474 for ( i = 0, angleToCandidate =
M_PI / 4; i < numberCandidates; i++, angleToCandidate += candidateAngleIncrement )
479 if ( angleToCandidate > a360 )
480 angleToCandidate -= a360;
484 if ( angleToCandidate < gamma1 || angleToCandidate > a360 - gamma1 )
486 labelX += distanceToLabel;
487 double iota = ( angleToCandidate + gamma1 );
488 if ( iota > a360 - gamma1 )
492 labelY += -labelHeight + labelHeight * iota / ( 2 * gamma1 );
496 else if ( angleToCandidate < a90 - gamma2 )
498 labelX += distanceToLabel * cos( angleToCandidate );
499 labelY += distanceToLabel * sin( angleToCandidate );
502 else if ( angleToCandidate < a90 + gamma2 )
505 labelX += -labelWidth * ( angleToCandidate - a90 + gamma2 ) / ( 2 * gamma2 );
506 labelY += distanceToLabel;
509 else if ( angleToCandidate < a180 - gamma1 )
511 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
512 labelY += distanceToLabel * sin( angleToCandidate );
515 else if ( angleToCandidate < a180 + gamma1 )
517 labelX += -distanceToLabel - labelWidth;
519 labelY += - ( angleToCandidate - a180 + gamma1 ) * labelHeight / ( 2 * gamma1 );
522 else if ( angleToCandidate < a270 - gamma2 )
524 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
525 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
528 else if ( angleToCandidate < a270 + gamma2 )
530 labelY += -distanceToLabel - labelHeight;
532 labelX += -labelWidth + ( angleToCandidate - a270 + gamma2 ) * labelWidth / ( 2 * gamma2 );
535 else if ( angleToCandidate < a360 )
537 labelX += distanceToLabel * cos( angleToCandidate );
538 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
544 if ( numberCandidates == 1 )
547 cost = 0.0001 + 0.0020 * double( icost ) / double( numberCandidates - 1 );
558 candidates <<
new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost,
this,
false, quadrant );
562 if ( icost == numberCandidates )
564 icost = numberCandidates - 1;
567 else if ( icost > numberCandidates )
569 icost = numberCandidates - 2;
577 for (
int i = 0; i < candidates.
count(); ++i )
579 lPos << candidates.
at( i );
583 return candidates.
count();
599 double bx, by, ex, ey;
619 d =
new double[nbPoints-1];
623 for ( i = 0; i < line->
nbPoints - 1; i++ )
628 ad[i] = ad[i-1] + d[i-1];
636 nbls =
static_cast< int >( ll / xrm );
644 dist = qMin( yrm, xrm );
648 l = - ( xrm - ll ) / 2.0;
656 while ( l < ll - xrm )
665 birdfly = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
666 + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
668 birdfly = sqrt(( ex - bx ) * ( ex - bx ) + ( ey - by ) * ( ey - by ) );
670 cost = birdfly / xrm;
674 cost = ( 1 - cost ) / 100;
677 double costCenter = qAbs( ll / 2 - ( l + xrm / 2 ) ) / ll;
678 cost += costCenter / 1000;
685 alpha = atan2( ey - by, ex - bx );
687 beta = alpha +
M_PI / 2;
692 bool isRightToLeft = ( alpha >
M_PI / 2 || alpha <= -
M_PI / 2 );
702 positions.
append(
new LabelPosition( i, bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha, cost,
this, isRightToLeft ) );
707 positions.
append(
new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost,
this, isRightToLeft ) );
712 positions.
append(
new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost,
this, isRightToLeft ) );
717 positions.
append(
new LabelPosition( i, bx - xrm / 2, by - yrm / 2, xrm, yrm, 0, cost,
this ) );
737 int nbp = positions.
size();
750 while ( distance < 0 && index > 1 )
753 distance += path_distances[
index];
756 if ( index <= 1 && distance < 0 )
762 while ( index < path_positions->
nbPoints && distance > path_distances[index] )
764 distance -= path_distances[
index];
767 if ( index >= path_positions->
nbPoints )
775 int initial_index =
index;
776 double initial_distance = distance;
779 double old_x = path_positions->
x[index-1];
780 double old_y = path_positions->
y[index-1];
782 double new_x = path_positions->
x[
index];
783 double new_y = path_positions->
y[
index];
785 double dx = new_x - old_x;
786 double dy = new_y - old_y;
788 double segment_length = path_distances[
index];
798 double angle = atan2( -dy, dx );
800 bool orientation_forced = ( orientation != 0 );
801 if ( !orientation_forced )
802 orientation = ( angle > 0.55 *
M_PI || angle < -0.45 *
M_PI ? -1 : 1 );
804 int upside_down_char_count = 0;
806 for (
int i = 0; i < li->
char_num; i++ )
808 double last_character_angle =
angle;
821 double start_x = old_x + dx * distance / segment_length;
822 double start_y = old_y + dy * distance / segment_length;
827 if ( segment_length - distance >= ci.
width )
830 distance += ci.
width;
831 end_x = old_x + dx * distance / segment_length;
832 end_y = old_y + dy * distance / segment_length;
843 if ( index >= path_positions->
nbPoints )
848 new_x = path_positions->
x[
index];
849 new_y = path_positions->
y[
index];
852 segment_length = path_distances[
index];
854 while ( sqrt( pow( start_x - new_x, 2 ) + pow( start_y - new_y, 2 ) ) < ci.
width );
860 distance = sqrt( pow( old_x - end_x, 2 ) + pow( old_y - end_y, 2 ) );
864 angle = atan2( start_y - end_y, end_x - start_x );
870 double angle_delta = last_character_angle -
angle;
872 while ( angle_delta >
M_PI ) angle_delta -= 2 *
M_PI;
873 while ( angle_delta < -
M_PI ) angle_delta += 2 *
M_PI;
877 && angle_delta < li->max_char_angle_outside*(
M_PI / 180 ) ) )
883 double render_angle =
angle;
885 double render_x = start_x;
886 double render_y = start_y;
892 if ( orientation < 0 )
895 render_x += ci.
width * cos( render_angle );
896 render_y -= ci.
width * sin( render_angle );
897 render_angle +=
M_PI;
912 while ( render_angle >= 2*
M_PI ) render_angle -= 2 *
M_PI;
913 while ( render_angle < 0 ) render_angle += 2 *
M_PI;
915 if ( render_angle >
M_PI / 2 && render_angle < 1.5*
M_PI )
916 upside_down_char_count++;
921 if ( upside_down_char_count >= li->
char_num / 2.0 )
924 if ( !orientation_forced )
926 orientation = -orientation;
957 double* path_distances =
new double[mapShape->
nbPoints];
958 double total_distance = 0;
959 double old_x = -1.0, old_y = -1.0;
960 for (
int i = 0; i < mapShape->
nbPoints; i++ )
963 path_distances[i] = 0;
965 path_distances[i] = sqrt( pow( old_x - mapShape->
x[i], 2 ) + pow( old_y - mapShape->
y[i], 2 ) );
966 old_x = mapShape->
x[i];
967 old_y = mapShape->
y[i];
969 total_distance += path_distances[i];
974 delete[] path_distances;
980 double bx = mapShape->
x[0];
981 double by = mapShape->
y[0];
982 double ex = mapShape->
x[ mapShape->
nbPoints - 1 ];
983 double ey = mapShape->
y[ mapShape->
nbPoints - 1 ];
989 lineAngle = atan2( ey - by, ex - bx );
992 bool isRightToLeft = ( lineAngle >
M_PI / 2 || lineAngle <= -
M_PI / 2 );
995 double delta = qMax( li->
label_height, total_distance / 10.0 );
1005 for (
int i = 0; i*delta < total_distance; i++ )
1012 double angle_diff = 0.0, angle_last = 0.0, diff;
1014 double sin_avg = 0, cos_avg = 0;
1019 diff = fabs( tmp->
getAlpha() - angle_last );
1020 if ( diff > 2*
M_PI ) diff -= 2 *
M_PI;
1021 diff = qMin( diff, 2 *
M_PI - diff );
1031 double angle_diff_avg = li->
char_num > 1 ? ( angle_diff / ( li->
char_num - 1 ) ) : 0;
1032 double cost = angle_diff_avg / 100;
1033 if ( cost < 0.0001 ) cost = 0.0001;
1037 double costCenter = qAbs( total_distance / 2 - labelCenter ) / total_distance;
1038 cost += costCenter / 1000;
1042 double angle_avg = atan2( sin_avg / li->
char_num, cos_avg / li->
char_num );
1048 if (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) )
1057 int nbp = positions.
size();
1058 for (
int i = 0; i < nbp; i++ )
1063 delete[] path_distances;
1094 mapShape->
parent =
nullptr;
1096 shapes_toProcess.
append( mapShape );
1098 splitPolygons( shapes_toProcess, shapes_final, labelWidth, labelHeight );
1102 if ( !shapes_final.
isEmpty() )
1114 double diago = sqrt( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 );
1120 while ( !shapes_final.
isEmpty() )
1132 dx = labelWidth / 2.0;
1133 dy = labelHeight / 2.0;
1144 for ( bbid = 0; bbid < j; bbid++ )
1157 if ( box->
length < labelWidth || box->
width < labelHeight )
1164 bool enoughPlace =
false;
1168 px = ( box->
x[0] + box->
x[2] ) / 2 - labelWidth;
1169 py = ( box->
y[0] + box->
y[2] ) / 2 - labelHeight;
1175 for ( rx = px, i = 0; i < 2; rx = rx + 2 * labelWidth, i++ )
1177 for ( ry = py, j = 0; j < 2; ry = ry + 2 * labelHeight, j++ )
1181 enoughPlace =
false;
1197 else if ( box->
length > 1.5*labelWidth && box->
width > 1.5*labelWidth )
1217 beta = atan2( labelHeight, labelWidth ) + alpha;
1223 dlx = cos( beta ) * diago;
1224 dly = sin( beta ) * diago;
1228 px0 = box->
width / 2.0;
1231 px0 -= ceil( px0 / dx ) * dx;
1232 py0 -= ceil( py0 / dy ) * dy;
1234 for ( px = px0; px <= box->
width; px += dx )
1236 for ( py = py0; py <= box->
length; py += dy )
1248 if ( candidateAcceptable )
1251 positions.
append(
new LabelPosition(
id++, rx - dlx, ry - dly, labelWidth, labelHeight, alpha, 0.0001,
this ) );
1257 nbp = positions.
size();
1265 while ( nbp == 0 && numTry < maxTry );
1267 nbp = positions.
size();
1269 for ( i = 0; i < nbp; i++ )
1274 for ( bbid = 0; bbid < j; bbid++ )
1290 double bboxMin[2],
double bboxMax[2],
1295 bbox[0] = bboxMin[0];
1296 bbox[1] = bboxMin[1];
1297 bbox[2] = bboxMax[0];
1298 bbox[3] = bboxMax[1];
1318 case GEOS_LINESTRING:
1353 bool outside =
false;
1370 return lPos.
count();
1379 int geomType = GEOSGeomTypeId_r( ctxt,
mGeos );
1381 double sizeCost = 0;
1382 if ( geomType == GEOS_LINESTRING )
1387 if ( GEOSLength_r( ctxt,
mGeos, &length ) != 1 )
1390 catch ( GEOSException &e )
1395 double bbox_length = qMax( bbx[2] - bbx[0], bby[2] - bby[0] );
1396 if ( length >= bbox_length / 4 )
1399 sizeCost = 1 - ( length / ( bbox_length / 4 ) );
1401 else if ( geomType == GEOS_POLYGON )
1406 if ( GEOSArea_r( ctxt,
mGeos, &area ) != 1 )
1409 catch ( GEOSException &e )
1414 double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] );
1415 if ( area >= bbox_area / 16 )
1418 sizeCost = 1 - ( area / ( bbox_area / 16 ) );
1424 for (
int i = 0; i < nbp; i++ )
1426 lPos.
at( i )->setCost( lPos.
at( i )->cost() + sizeCost / 100 );
1439 catch ( GEOSException &e )
1450 if ( !other->
mGeos )
1456 GEOSGeometry* g1 = GEOSGeom_clone_r( ctxt,
mGeos );
1457 GEOSGeometry* g2 = GEOSGeom_clone_r( ctxt, other->
mGeos );
1458 GEOSGeometry* geoms[2] = { g1, g2 };
1459 GEOSGeometry* g = GEOSGeom_createCollection_r( ctxt, GEOS_MULTILINESTRING, geoms, 2 );
1460 GEOSGeometry* gTmp = GEOSLineMerge_r( ctxt, g );
1461 GEOSGeom_destroy_r( ctxt, g );
1463 if ( GEOSGeomTypeId_r( ctxt, gTmp ) != GEOS_LINESTRING )
1466 GEOSGeom_destroy_r( ctxt, gTmp );
1481 catch ( GEOSException &e )
Label below point, slightly right of center.
pal::Layer * layer() const
Get PAL layer of the label feature. Should be only used internally in PAL.
Label on bottom-left of point.
virtual ~FeaturePart()
Delete the feature.
bool isIntersect(double *bbox)
Is the labelposition intersect the bounding-box ?
static bool candidateSortGrow(const LabelPosition *c1, const LabelPosition *c2)
Sorts label candidates in ascending order of cost.
QList< FeaturePart * > mHoles
double max_char_angle_outside
bool alwaysShow() const
Whether label should be always shown (sets very high label priority)
double getLabelHeight() const
Label on top-left of point.
void setCost(double newCost)
Sets the candidate label position's geographical cost.
A set of features which influence the labelling process.
PredefinedPointPosition
Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode...
int createCandidatesAlongLine(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate candidates for line feature.
void offsetPosition(double xOffset, double yOffset)
Shift the label by specified offset.
const T & at(int i) const
Candidates are placed in predefined positions around a point.
friend class LabelPosition
static void findLineCircleIntersection(double cx, double cy, double radius, double x1, double y1, double x2, double y2, double &xRes, double &yRes)
Label on top of point, slightly right of center.
QPointF quadOffset() const
Applies to "offset from point" placement strategy and "around point" (in case hasFixedQuadrant() retu...
void createGeosGeom() const
double getLabelWidth() const
double priority() const
Returns the layer's priority, between 0 and 1.
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged)...
bool centroidInside() const
Returns whether labels placed at the centroid of features within the layer are forced to be placed in...
double priority() const
Returns the feature's labeling priority.
bool isConnected(FeaturePart *p2)
Check whether this part is connected with some other part.
void addSizePenalty(int nbp, QList< LabelPosition * > &lPos, double bbx[4], double bby[4])
void getCentroid(double &px, double &py, bool forceInside=false) const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
double x() const
Get the x value of the point.
int createCurvedCandidatesAlongLine(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate curved candidates for line features.
QgsPalLayerSettings::OffsetType offsetType() const
Returns the offset type, which determines how offsets and distance to label behaves.
Arranges candidates following the curvature of a line feature.
CharacterInfo * char_info
pal::LabelInfo * curvedLabelInfo() const
Get additional infor required for curved label placement. Returns null if not set.
bool isInside(double *bbox)
Is the labelposition inside the bounding-box ?
QgsPalLayerSettings::Placement arrangement() const
Returns the layer's arrangement policy.
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
const GEOSPreparedGeometry * preparedGeom() const
int count(const T &value) const
bool getShowPartial()
Get flag show partial label.
void getPointByDistance(double *d, double *ad, double dl, double *px, double *py)
Get a point a set distance along a line geometry.
double calculatePriority() const
Calculates the priority for the feature.
bool hasSameLabelFeatureAs(FeaturePart *part) const
Tests whether this feature part belongs to the same QgsLabelFeature as another feature part...
double getLabelDistance() const
const QSizeF & symbolSize() const
Returns the size of the rendered symbol associated with this feature, if applicable.
QgsPoint fixedPosition() const
Coordinates of the fixed position (relevant only if hasFixedPosition() returns true) ...
static LabelPosition * _createCurvedCandidate(LabelPosition *lp, double angle, double dist)
bool hasFixedQuadrant() const
Returns whether the quadrant for the label is fixed.
Arranges candidates in a circle around a point (or centroid of a polygon).
double bottom
Bottom margin.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
Optional additional info about label (for curved labels)
Layer * layer()
Returns the layer that feature belongs to.
double length() const
Returns length of line geometry.
void insertIntoIndex(RTree< LabelPosition *, double, 2, double > *index)
static double dist_euc2d(double x1, double y1, double x2, double y2)
LabelPosition * getNextPart() const
GEOSContextHandle_t geosContext()
Get GEOS context handle to be used in all GEOS library calls with reentrant API.
Stores visual margins for labels (left, right, top and bottom)
Main class to handle feature.
bool containsLabelCandidate(double x, double y, double width, double height, double alpha=0) const
Tests whether a possible label candidate will fit completely within the shape.
Offset distance applies from rendered symbol bounds.
bool fitInPolygonOnly() const
Returns whether labels which do not fit completely within a polygon feature are discarded.
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
static void splitPolygons(QLinkedList< PointSet * > &shapes_toProcess, QLinkedList< PointSet * > &shapes_final, double xrm, double yrm)
Split a concave shape into several convex shapes.
double getAlpha() const
get alpha
const VisualMargin & visualMargin() const
Returns the visual margin for the label feature.
int createCandidatesForPolygon(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate candidates for polygon features.
void setNextPart(LabelPosition *next)
CHullBox * compute_chull_bbox()
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point...
QgsPoint positionOffset() const
Applies only to "offset from point" placement strategy.
int createCandidates(QList< LabelPosition * > &lPos, double bboxMin[2], double bboxMax[2], PointSet *mapShape, RTree< LabelPosition *, double, 2, double > *candidates)
Generic method to generate label candidates for the feature.
int createCandidatesOverPoint(double x, double y, QList< LabelPosition * > &lPos, double angle, PointSet *mapShape=nullptr)
Generate one candidate over or offset the specified point.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
int createCandidatesAroundPoint(double x, double y, QList< LabelPosition * > &lPos, double angle, PointSet *mapShape=nullptr)
Generate candidates for point feature, located around a specified point.
int connectedFeatureId(QgsFeatureId featureId) const
Returns the connected feature ID for a label feature ID, which is unique for all features which have ...
QVector< QgsPalLayerSettings::PredefinedPointPosition > predefinedPositionOrder() const
Returns the priority ordered list of predefined positions for label candidates.
double max_char_angle_inside
double right
Right margin.
int createCandidatesAtOrderedPositionsOverPoint(double x, double y, QList< LabelPosition * > &lPos, double angle)
Generates candidates following a prioritised list of predefined positions around a point...
Label below point, slightly left of center.
void extractCoords(const GEOSGeometry *geom)
read coordinates from a GEOS geom
double distLabel() const
Applies to "around point" placement strategy or linestring features.
LabelPosition is a candidate feature label position.
QString name() const
Returns the layer's name.
LineArrangementFlags arrangementFlags() const
Returns the layer's arrangement flags.
Label on top of point, slightly left of center.
double y() const
Get the y value of the point.
Quadrant
Position of label candidate relative to feature.
static int reorderPolygon(int nbPoints, double *x, double *y)
Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside...
bool hasFixedAngle() const
Whether the label should use a fixed angle instead of using angle from automatic placement.
FeaturePart(QgsLabelFeature *lf, const GEOSGeometry *geom)
Creates a new generic feature.
LabelPosition * curvedPlacementAtOffset(PointSet *path_positions, double *path_distances, int orientation, int index, double distance)
double fixedAngle() const
Angle in degrees of the fixed angle (relevant only if hasFixedAngle() returns true) ...
void append(const T &value)
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Arranges candidates scattered throughout a polygon feature.