30 #define _CRT_SECURE_NO_DEPRECATE
33 #if defined(_VERBOSE_) || (_DEBUG_)
49 #include <QLinkedList>
54 #define M_PI 3.14159265358979323846
64 mGeos =
const_cast<GEOSGeometry*
>( geom );
70 for (
int i = 0; i <
mHoles.count(); i++ )
72 mHoles.at( i )->holeOf =
this;
88 const GEOSCoordSequence *coordSeq;
91 type = GEOSGeomTypeId_r( geosctxt, geom );
93 if (
type == GEOS_POLYGON )
95 if ( GEOSGetNumInteriorRings_r( geosctxt, geom ) > 0 )
97 int numHoles = GEOSGetNumInteriorRings_r( geosctxt, geom );
99 for (
int i = 0; i < numHoles; ++i )
101 const GEOSGeometry* interior = GEOSGetInteriorRingN_r( geosctxt, geom, i );
113 geom = GEOSGetExteriorRing_r( geosctxt, geom );
122 nbPoints = GEOSGetNumCoordinates_r( geosctxt, geom );
123 coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, geom );
134 for (
int i = 0; i <
nbPoints; ++i )
136 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &
x[i] );
137 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &
y[i] );
160 qreal quadOffsetX = quadOffset.
x(), quadOffsetY = quadOffset.
y();
162 if ( quadOffsetX < 0 )
164 if ( quadOffsetY < 0 )
168 else if ( quadOffsetY > 0 )
177 else if ( quadOffsetX > 0 )
179 if ( quadOffsetY < 0 )
183 else if ( quadOffsetY > 0 )
194 if ( quadOffsetY < 0 )
198 else if ( quadOffsetY > 0 )
217 double cost = 0.0001;
220 double xdiff = -labelW / 2.0;
221 double ydiff = -labelH / 2.0;
236 double xd = xdiff * cos( angle ) - ydiff * sin( angle );
237 double yd = xdiff * sin( angle ) + ydiff * cos( angle );
273 double lx = x + xdiff;
274 double ly = y + ydiff;
284 lPos <<
new LabelPosition(
id, lx, ly, labelW, labelH, angle, cost,
this,
false, quadrantFromOffset() );
292 std::cout <<
"SetPosition (point) : " <<
layer->
name <<
"/" << uid << std::endl;
305 double candidateAngleIncrement = 2 *
M_PI / numberCandidates;
308 double a90 =
M_PI / 2;
310 double a270 = a180 + a90;
311 double a360 = 2 *
M_PI;
313 double gamma1, gamma2;
315 if ( distanceToLabel > 0 )
317 gamma1 = atan2( labelHeight / 2, distanceToLabel + labelWidth / 2 );
318 gamma2 = atan2( labelWidth / 2, distanceToLabel + labelHeight / 2 );
322 gamma1 = gamma2 = a90 / 3.0;
325 if ( gamma1 > a90 / 3.0 )
328 if ( gamma2 > a90 / 3.0 )
332 if ( gamma1 == 0 || gamma2 == 0 )
334 std::cout <<
"Oups... label size error..." << std::endl;
340 double angleToCandidate;
341 for ( i = 0, angleToCandidate =
M_PI / 4; i < numberCandidates; i++, angleToCandidate += candidateAngleIncrement )
346 if ( angleToCandidate > a360 )
347 angleToCandidate -= a360;
351 if ( angleToCandidate < gamma1 || angleToCandidate > a360 - gamma1 )
353 labelX += distanceToLabel;
354 double iota = ( angleToCandidate + gamma1 );
355 if ( iota > a360 - gamma1 )
359 labelY += -labelHeight + labelHeight * iota / ( 2 * gamma1 );
363 else if ( angleToCandidate < a90 - gamma2 )
365 labelX += distanceToLabel * cos( angleToCandidate );
366 labelY += distanceToLabel * sin( angleToCandidate );
369 else if ( angleToCandidate < a90 + gamma2 )
372 labelX += -labelWidth * ( angleToCandidate - a90 + gamma2 ) / ( 2 * gamma2 );
373 labelY += distanceToLabel;
376 else if ( angleToCandidate < a180 - gamma1 )
378 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
379 labelY += distanceToLabel * sin( angleToCandidate );
382 else if ( angleToCandidate < a180 + gamma1 )
384 labelX += -distanceToLabel - labelWidth;
386 labelY += - ( angleToCandidate - a180 + gamma1 ) * labelHeight / ( 2 * gamma1 );
389 else if ( angleToCandidate < a270 - gamma2 )
391 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
392 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
395 else if ( angleToCandidate < a270 + gamma2 )
397 labelY += -distanceToLabel - labelHeight;
399 labelX += -labelWidth + ( angleToCandidate - a270 + gamma2 ) * labelWidth / ( 2 * gamma2 );
402 else if ( angleToCandidate < a360 )
404 labelX += distanceToLabel * cos( angleToCandidate );
405 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
411 if ( numberCandidates == 1 )
414 cost = 0.0001 + 0.0020 * double( icost ) / double( numberCandidates - 1 );
425 candidates <<
new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost,
this,
false, quadrant );
429 if ( icost == numberCandidates )
431 icost = numberCandidates - 1;
434 else if ( icost > numberCandidates )
436 icost = numberCandidates - 2;
444 for (
int i = 0; i < candidates.
count(); ++i )
446 lPos << candidates.
at( i );
450 return candidates.
count();
457 std::cout <<
"SetPosition (line) : " <<
layer->
name <<
"/" << uid << std::endl;
469 double bx, by, ex, ey;
486 std::cout <<
"New line of " << line->
nbPoints <<
" points with label " << xrm <<
"x" << yrm << std::endl;
493 d =
new double[nbPoints-1];
497 for ( i = 0; i < line->
nbPoints - 1; i++ )
502 ad[i] = ad[i-1] + d[i-1];
504 d[i] =
dist_euc2d( x[i], y[i], x[i+1], y[i+1] );
511 nbls = ( int )( ll / xrm );
514 std::cout <<
"line length :" << ll << std::endl;
515 std::cout <<
"nblp :" << nbls << std::endl;
526 dist = qMin( yrm, xrm );
530 l = - ( xrm - ll ) / 2.0;
540 std::cout << l <<
" / " << ll - xrm << std::endl;
542 while ( l < ll - xrm )
551 birdfly = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
552 + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
554 birdfly = sqrt(( ex - bx ) * ( ex - bx ) + ( ey - by ) * ( ey - by ) );
556 cost = birdfly / xrm;
560 cost = ( 1 - cost ) / 100;
563 double costCenter = qAbs( ll / 2 - ( l + xrm / 2 ) ) / ll;
564 cost += costCenter / 1000;
568 std::cout <<
"b: " << bx <<
";" << by << std::endl;
569 std::cout <<
"e: " << ex <<
";" << ey << std::endl;
573 alpha = atan2( ey - by, ex - bx );
575 beta = alpha +
M_PI / 2;
578 std::cout <<
" Create new label" << std::endl;
583 bool isRightToLeft = ( alpha >
M_PI / 2 || alpha <= -
M_PI / 2 );
593 positions.
append(
new LabelPosition( i, bx + cos( beta ) *distlabel, by + sin( beta ) *distlabel, xrm, yrm, alpha, cost,
this, isRightToLeft ) );
598 positions.
append(
new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ), by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost,
this, isRightToLeft ) );
603 positions.
append(
new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost,
this, isRightToLeft ) );
608 positions.
append(
new LabelPosition( i, bx - xrm / 2, by - yrm / 2, xrm, yrm, 0, cost,
this ) );
628 int nbp = positions.
size();
629 while ( positions.
size() > 0 )
641 while ( distance < 0 && index > 1 )
644 distance += path_distances[
index];
647 if ( index <= 1 && distance < 0 )
653 while ( index < path_positions->
nbPoints && distance > path_distances[index] )
655 distance -= path_distances[
index];
658 if ( index >= path_positions->
nbPoints )
666 int initial_index =
index;
667 double initial_distance = distance;
670 double old_x = path_positions->
x[index-1];
671 double old_y = path_positions->
y[index-1];
673 double new_x = path_positions->
x[
index];
674 double new_y = path_positions->
y[
index];
676 double dx = new_x - old_x;
677 double dy = new_y - old_y;
679 double segment_length = path_distances[
index];
680 if ( segment_length == 0 )
689 double angle = atan2( -dy, dx );
691 bool orientation_forced = ( orientation != 0 );
692 if ( !orientation_forced )
693 orientation = ( angle > 0.55 *
M_PI || angle < -0.45 *
M_PI ? -1 : 1 );
695 int upside_down_char_count = 0;
697 for (
int i = 0; i < li->
char_num; i++ )
699 double last_character_angle =
angle;
705 if ( segment_length == 0 )
712 double start_x = old_x + dx * distance / segment_length;
713 double start_y = old_y + dy * distance / segment_length;
719 if ( segment_length - distance >= ci.
width )
722 distance += ci.
width;
723 end_x = old_x + dx * distance / segment_length;
724 end_y = old_y + dy * distance / segment_length;
735 if ( index >= path_positions->
nbPoints )
740 new_x = path_positions->
x[
index];
741 new_y = path_positions->
y[
index];
744 segment_length = path_distances[
index];
749 while ( sqrt( pow( start_x - new_x, 2 ) + pow( start_y - new_y, 2 ) ) < ci.
width );
755 distance = sqrt( pow( old_x - end_x, 2 ) + pow( old_y - end_y, 2 ) );
759 angle = atan2( start_y - end_y, end_x - start_x );
765 double angle_delta = last_character_angle -
angle;
767 while ( angle_delta >
M_PI ) angle_delta -= 2 *
M_PI;
768 while ( angle_delta < -
M_PI ) angle_delta += 2 *
M_PI;
772 && angle_delta < li->max_char_angle_outside*(
M_PI / 180 ) ) )
778 double render_angle =
angle;
780 double render_x = start_x;
781 double render_y = start_y;
787 if ( orientation < 0 )
790 render_x += ci.
width * cos( render_angle );
791 render_y -= ci.
width * sin( render_angle );
792 render_angle +=
M_PI;
808 while ( render_angle >= 2*
M_PI ) render_angle -= 2 *
M_PI;
809 while ( render_angle < 0 ) render_angle += 2 *
M_PI;
811 if ( render_angle >
M_PI / 2 && render_angle < 1.5*
M_PI )
812 upside_down_char_count++;
817 if ( upside_down_char_count >= li->
char_num / 2.0 )
820 if ( !orientation_forced )
822 orientation = -orientation;
849 if ( li == NULL || li->
char_num == 0 )
853 double* path_distances =
new double[mapShape->
nbPoints];
854 double total_distance = 0;
855 double old_x = -1.0, old_y = -1.0;
856 for (
int i = 0; i < mapShape->
nbPoints; i++ )
859 path_distances[i] = 0;
861 path_distances[i] = sqrt( pow( old_x - mapShape->
x[i], 2 ) + pow( old_y - mapShape->
y[i], 2 ) );
862 old_x = mapShape->
x[i];
863 old_y = mapShape->
y[i];
865 total_distance += path_distances[i];
868 if ( total_distance == 0 )
870 delete[] path_distances;
876 double bx = mapShape->
x[0];
877 double by = mapShape->
y[0];
878 double ex = mapShape->
x[ mapShape->
nbPoints - 1 ];
879 double ey = mapShape->
y[ mapShape->
nbPoints - 1 ];
885 lineAngle = atan2( ey - by, ex - bx );
888 bool isRightToLeft = ( lineAngle >
M_PI / 2 || lineAngle <= -
M_PI / 2 );
891 double delta = qMax( li->
label_height, total_distance / 10.0 );
901 for (
int i = 0; i*delta < total_distance; i++ )
908 double angle_diff = 0.0, angle_last = 0.0, diff;
910 double sin_avg = 0, cos_avg = 0;
915 diff = fabs( tmp->
getAlpha() - angle_last );
916 if ( diff > 2*
M_PI ) diff -= 2 *
M_PI;
917 diff = qMin( diff, 2 *
M_PI - diff );
927 double angle_diff_avg = li->
char_num > 1 ? ( angle_diff / ( li->
char_num - 1 ) ) : 0;
928 double cost = angle_diff_avg / 100;
929 if ( cost < 0.0001 ) cost = 0.0001;
933 double costCenter = qAbs( total_distance / 2 - labelCenter ) / total_distance;
934 cost += costCenter / 1000;
945 if (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) )
954 int nbp = positions.
size();
955 for (
int i = 0; i < nbp; i++ )
960 delete[] path_distances;
984 std::cout <<
"SetPosition (polygon) : " <<
layer->
name <<
"/" << uid << std::endl;
1000 shapes_toProcess.
append( mapShape );
1006 if ( shapes_final.
size() > 0 )
1018 double diago = sqrt( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 );
1024 while ( shapes_final.
size() > 0 )
1036 dx = labelWidth / 2.0;
1037 dy = labelHeight / 2.0;
1048 for ( bbid = 0; bbid < j; bbid++ )
1054 std::cout <<
"Very Large BBOX (should never occur : bug-report please)" << std::endl;
1055 std::cout <<
" Box size: " << box->
length <<
"/" << box->
width << std::endl;
1056 std::cout <<
" Alpha: " << alpha <<
" " << alpha * 180 /
M_PI << std::endl;
1057 std::cout <<
" Dx;Dy: " << dx <<
" " << dy << std::endl;
1058 std::cout <<
" LabelSizerm: " << labelWidth <<
" " << labelHeight << std::endl;
1066 if ( box->
length < labelWidth || box->
width < labelHeight )
1074 std::cout <<
"New BBox : " << bbid << std::endl;
1075 for ( i = 0; i < 4; i++ )
1077 std::cout << box->
x[i] <<
"\t" << box->
y[i] << std::endl;
1081 bool enoughPlace =
false;
1085 px = ( box->
x[0] + box->
x[2] ) / 2 - labelWidth;
1086 py = ( box->
y[0] + box->
y[2] ) / 2 - labelHeight;
1092 for ( rx = px, i = 0; i < 2; rx = rx + 2 * labelWidth, i++ )
1094 for ( ry = py, j = 0; j < 2; ry = ry + 2 * labelHeight, j++ )
1098 enoughPlace =
false;
1114 else if ( box->
length > 1.5*labelWidth && box->
width > 1.5*labelWidth )
1134 beta = atan2( labelHeight, labelWidth ) + alpha;
1140 dlx = cos( beta ) * diago;
1141 dly = sin( beta ) * diago;
1145 px0 = box->
width / 2.0;
1148 px0 -= ceil( px0 / dx ) * dx;
1149 py0 -= ceil( py0 / dy ) * dy;
1151 for ( px = px0; px <= box->
width; px += dx )
1153 for ( py = py0; py <= box->
length; py += dy )
1165 if ( candidateAcceptable )
1168 positions.
append(
new LabelPosition(
id++, rx - dlx, ry - dly, labelWidth, labelHeight, alpha, 0.0001,
this ) );
1174 nbp = positions.
size();
1182 while ( nbp == 0 && numTry < maxTry );
1184 nbp = positions.
size();
1186 for ( i = 0; i < nbp; i++ )
1191 for ( bbid = 0; bbid < j; bbid++ )
1204 std::cout <<
"NbLabelPosition: " << nbp << std::endl;
1210 void FeaturePart::print()
1213 std::cout <<
"Geometry id : " << f->uid << std::endl;
1214 std::cout <<
"Type: " <<
type << std::endl;
1218 std::cout <<
x[i] <<
", " <<
y[i] << std::endl;
1219 std::cout <<
"Obstacle: " << nbHoles << std::endl;
1220 for ( i = 0; i < nbHoles; i++ )
1222 std::cout <<
" obs " << i << std::endl;
1223 for ( j = 0; j < holes[i]->nbPoints; j++ )
1225 std::cout << holes[i]->x[j] <<
";" << holes[i]->y[j] << std::endl;
1230 std::cout << std::endl;
1235 double bbox_min[2],
double bbox_max[2],
1240 bbox[0] = bbox_min[0];
1241 bbox[1] = bbox_min[1];
1242 bbox[2] = bbox_max[0];
1243 bbox[3] = bbox_max[1];
1261 case GEOS_LINESTRING:
1296 bool outside =
false;
1313 return lPos.
count();
1322 int geomType = GEOSGeomTypeId_r( ctxt,
mGeos );
1324 double sizeCost = 0;
1325 if ( geomType == GEOS_LINESTRING )
1330 if ( GEOSLength_r( ctxt,
mGeos, &length ) != 1 )
1333 catch ( GEOSException &e )
1338 double bbox_length = qMax( bbx[2] - bbx[0], bby[2] - bby[0] );
1339 if ( length >= bbox_length / 4 )
1342 sizeCost = 1 - ( length / ( bbox_length / 4 ) );
1344 else if ( geomType == GEOS_POLYGON )
1349 if ( GEOSArea_r( ctxt,
mGeos, &area ) != 1 )
1352 catch ( GEOSException &e )
1357 double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] );
1358 if ( area >= bbox_area / 16 )
1361 sizeCost = 1 - ( area / ( bbox_area / 16 ) );
1369 for (
int i = 0; i < nbp; i++ )
1371 lPos.
at( i )->setCost( lPos.
at( i )->cost() + sizeCost / 100 );
1384 catch ( GEOSException &e )
1395 if ( !other->
mGeos )
1401 GEOSGeometry* g1 = GEOSGeom_clone_r( ctxt,
mGeos );
1402 GEOSGeometry* g2 = GEOSGeom_clone_r( ctxt, other->
mGeos );
1403 GEOSGeometry* geoms[2] = { g1, g2 };
1404 GEOSGeometry* g = GEOSGeom_createCollection_r( ctxt, GEOS_MULTILINESTRING, geoms, 2 );
1405 GEOSGeometry* gTmp = GEOSLineMerge_r( ctxt, g );
1406 GEOSGeom_destroy_r( ctxt, g );
1408 if ( GEOSGeomTypeId_r( ctxt, gTmp ) != GEOS_LINESTRING )
1411 GEOSGeom_destroy_r( ctxt, gTmp );
1426 catch ( GEOSException &e )
pal::Layer * layer() const
Get PAL layer of the label feature. Should be only used internally in PAL.
int reorderPolygon(int nbPoints, double *x, double *y)
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
arranges candidates around a point (centroid for polygon)
bool alwaysShow() const
Whether label should be always shown (sets very high label priority)
FeaturePart(QgsLabelFeature *lf, const GEOSGeometry *geom)
Creates a new generic feature.
void getCentroid(double &px, double &py, bool forceInside=false) const
double getLabelHeight() const
Arrangement arrangement() const
Returns the layer's arrangement policy.
double calculatePriority() const
Calculates the priority for the feature.
void setCost(double newCost)
Sets the candidate label position's geographical cost.
A layer of spacial entites.
const T & at(int i) const
void offsetPosition(double xOffset, double yOffset)
Shift the label by specified offset.
friend class LabelPosition
int setPositionForPolygon(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate candidates for polygon features.
static LabelPosition * _createCurvedCandidate(LabelPosition *lp, double angle, double dist)
QPointF quadOffset() const
Applies to "offset from point" placement strategy and "around point" (in case hasFixedQuadrant() retu...
double getLabelWidth() const
QgsFeatureId featureId() const
Returns the unique ID of the feature.
double priority() const
Returns the layer's priority, between 0 and 1.
CHullBox * compute_chull_bbox()
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.
Only for polygon, arranges candidates with respect of polygon orientation.
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
void createGeosGeom() const
double x() const
Get the x value of the point.
CharacterInfo * char_info
pal::LabelInfo * curvedLabelInfo() const
Get additional infor required for curved label placement. Returns null if not set.
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
int setPositionForLine(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate candidates for line feature.
bool isIntersect(double *bbox)
Is the labelposition intersect the bounding-box ?
int count(const T &value) const
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.
int setPosition(QList< LabelPosition * > &lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree< LabelPosition *, double, 2, double > *candidates)
Generic method to generate candidates.
void addSizePenalty(int nbp, QList< LabelPosition * > &lPos, double bbx[4], double bby[4])
virtual ~FeaturePart()
Delete the feature.
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged)...
double getAlpha() const
get alpha
double getLabelDistance() const
Layer * layer()
Returns the layer that feature belongs to.
QgsPoint fixedPosition() const
Coordinates of the fixed position (relevant only if hasFixedPosition() returns true) ...
bool hasFixedQuadrant() const
Returns whether the quadrant for the label is fixed.
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)
double dist_euc2d(double x1, double y1, double x2, double y2)
bool isConnected(FeaturePart *p2)
Check whether this part is connected with some other part.
LabelPosition * getNextPart() const
GEOSContextHandle_t geosContext()
Get GEOS context handle to be used in all GEOS library calls with reentrant API.
void insertIntoIndex(RTree< LabelPosition *, double, 2, double > *index)
Main class to handle feature.
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
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)
void extractCoords(const GEOSGeometry *geom)
read coordinates from a GEOS geom
LabelPosition * curvedPlacementAtOffset(PointSet *path_positions, double *path_distances, int orientation, int index, double distance)
Only for lines, labels along the line.
bool getShowPartial()
Get flag show partial label.
void setNextPart(LabelPosition *next)
int setPositionForLineCurved(QList< LabelPosition * > &lPos, PointSet *mapShape)
Generate curved candidates for line features.
QgsPoint positionOffset() const
Applies only to "offset from point" placement strategy.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
int setPositionForPoint(double x, double y, QList< LabelPosition * > &lPos, double angle, PointSet *mapShape=0)
Generate candidates for point feature, located around a specified point.
int setPositionOverPoint(double x, double y, QList< LabelPosition * > &lPos, double angle, PointSet *mapShape=0)
Generate one candidate over or offset the specified point.
double max_char_angle_inside
double distLabel() const
Applies to "around point" placement strategy or linestring features.
void findLineCircleIntersection(double cx, double cy, double radius, double x1, double y1, double x2, double y2, double &xRes, double &yRes)
LabelPosition is a candidate feature label position.
QString name() const
Returns the layer's name.
LineArrangementFlags arrangementFlags() const
Returns the layer's arrangement flags.
double y() const
Get the y value of the point.
Quadrant
Position of label candidate relative to feature.
bool hasFixedAngle() const
Whether the label should use a fixed angle instead of using angle from automatic placement.
const GEOSPreparedGeometry * preparedGeom() const
double length() const
Returns length of line geometry.
void getPointByDistance(double *d, double *ad, double dl, double *px, double *py)
Get a point a set distance along a line geometry.
double fixedAngle() const
Angle in degrees of the fixed angle (relevant only if hasFixedAngle() returns true) ...
arranges candidates over a point (centroid for polygon)
static void splitPolygons(QLinkedList< PointSet * > &shapes_toProcess, QLinkedList< PointSet * > &shapes_final, double xrm, double yrm, const QgsFeatureId &uid)
Split a concave shape into several convex shapes.
void append(const T &value)
bool isInside(double *bbox)
Is the labelposition inside the bounding-box ?
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)