43 #include <QLinkedList> 48 #define M_PI 3.14159265358979323846 57 mGeos =
const_cast<GEOSGeometry*
>( geom );
63 for (
int i = 0; i <
mHoles.count(); i++ )
65 mHoles.at( i )->holeOf =
this;
77 mHoles.last()->holeOf =
this;
91 const GEOSCoordSequence *coordSeq;
94 type = GEOSGeomTypeId_r( geosctxt, geom );
96 if (
type == GEOS_POLYGON )
98 if ( GEOSGetNumInteriorRings_r( geosctxt, geom ) > 0 )
100 int numHoles = GEOSGetNumInteriorRings_r( geosctxt, geom );
102 for (
int i = 0; i < numHoles; ++i )
104 const GEOSGeometry* interior = GEOSGetInteriorRingN_r( geosctxt, geom, i );
116 geom = GEOSGetExteriorRing_r( geosctxt, geom );
125 nbPoints = GEOSGetNumCoordinates_r( geosctxt, geom );
126 coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, geom );
137 for (
int i = 0; i <
nbPoints; ++i )
139 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &
x[i] );
140 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &
y[i] );
182 qreal quadOffsetX = quadOffset.
x(), quadOffsetY = quadOffset.
y();
184 if ( quadOffsetX < 0 )
186 if ( quadOffsetY < 0 )
190 else if ( quadOffsetY > 0 )
199 else if ( quadOffsetX > 0 )
201 if ( quadOffsetY < 0 )
205 else if ( quadOffsetY > 0 )
216 if ( quadOffsetY < 0 )
220 else if ( quadOffsetY > 0 )
239 double cost = 0.0001;
242 double xdiff = -labelW / 2.0;
243 double ydiff = -labelH / 2.0;
258 double xd = xdiff * cos( angle ) - ydiff * sin( angle );
259 double yd = xdiff * sin( angle ) + ydiff * cos( angle );
295 double lx = x + xdiff;
296 double ly = y + ydiff;
306 lPos <<
new LabelPosition(
id, lx, ly, labelW, labelH, angle, cost,
this,
false, quadrantFromOffset() );
321 double cost = 0.0001;
334 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
335 deltaY = -visualMargin.
bottom + symbolHeightOffset;
341 deltaX = -labelWidth / 4.0 - visualMargin.
left;
342 deltaY = -visualMargin.
bottom + symbolHeightOffset;
348 deltaX = -labelWidth / 2.0;
349 deltaY = -visualMargin.
bottom + symbolHeightOffset;
355 deltaX = -labelWidth * 3.0 / 4.0 + visualMargin.
right;
356 deltaY = -visualMargin.
bottom + symbolHeightOffset;
362 deltaX = - visualMargin.
left + symbolWidthOffset;
363 deltaY = -visualMargin.
bottom + symbolHeightOffset;
369 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
370 deltaY = -labelHeight / 2.0;
376 deltaX = -visualMargin.
left + symbolWidthOffset;
377 deltaY = -labelHeight / 2.0;
383 deltaX = -labelWidth + visualMargin.
right - symbolWidthOffset;
384 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
390 deltaX = -labelWidth / 4.0 - visualMargin.
left;
391 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
397 deltaX = -labelWidth / 2.0;
398 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
404 deltaX = -labelWidth * 3.0 / 4.0 + visualMargin.
right;
405 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
411 deltaX = -visualMargin.
left + symbolWidthOffset;
412 deltaY = -labelHeight + visualMargin.
top - symbolHeightOffset;
417 double referenceX = cos( alpha ) * distanceToLabel +
x;
418 double referenceY = sin( alpha ) * distanceToLabel +
y;
420 double labelX = referenceX + deltaX;
421 double labelY = referenceY + deltaY;
425 lPos <<
new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost,
this,
false, quadrant );
447 double candidateAngleIncrement = 2 *
M_PI / numberCandidates;
450 double a90 =
M_PI / 2;
452 double a270 = a180 + a90;
453 double a360 = 2 *
M_PI;
455 double gamma1, gamma2;
457 if ( distanceToLabel > 0 )
459 gamma1 = atan2( labelHeight / 2, distanceToLabel + labelWidth / 2 );
460 gamma2 = atan2( labelWidth / 2, distanceToLabel + labelHeight / 2 );
464 gamma1 = gamma2 = a90 / 3.0;
467 if ( gamma1 > a90 / 3.0 )
470 if ( gamma2 > a90 / 3.0 )
476 double angleToCandidate;
477 for ( i = 0, angleToCandidate =
M_PI / 4; i < numberCandidates; i++, angleToCandidate += candidateAngleIncrement )
482 if ( angleToCandidate > a360 )
483 angleToCandidate -= a360;
487 if ( angleToCandidate < gamma1 || angleToCandidate > a360 - gamma1 )
489 labelX += distanceToLabel;
490 double iota = ( angleToCandidate + gamma1 );
491 if ( iota > a360 - gamma1 )
495 labelY += -labelHeight + labelHeight * iota / ( 2 * gamma1 );
499 else if ( angleToCandidate < a90 - gamma2 )
501 labelX += distanceToLabel * cos( angleToCandidate );
502 labelY += distanceToLabel * sin( angleToCandidate );
505 else if ( angleToCandidate < a90 + gamma2 )
508 labelX += -labelWidth * ( angleToCandidate - a90 + gamma2 ) / ( 2 * gamma2 );
509 labelY += distanceToLabel;
512 else if ( angleToCandidate < a180 - gamma1 )
514 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
515 labelY += distanceToLabel * sin( angleToCandidate );
518 else if ( angleToCandidate < a180 + gamma1 )
520 labelX += -distanceToLabel - labelWidth;
522 labelY += - ( angleToCandidate - a180 + gamma1 ) * labelHeight / ( 2 * gamma1 );
525 else if ( angleToCandidate < a270 - gamma2 )
527 labelX += distanceToLabel * cos( angleToCandidate ) - labelWidth;
528 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
531 else if ( angleToCandidate < a270 + gamma2 )
533 labelY += -distanceToLabel - labelHeight;
535 labelX += -labelWidth + ( angleToCandidate - a270 + gamma2 ) * labelWidth / ( 2 * gamma2 );
538 else if ( angleToCandidate < a360 )
540 labelX += distanceToLabel * cos( angleToCandidate );
541 labelY += distanceToLabel * sin( angleToCandidate ) - labelHeight;
547 if ( numberCandidates == 1 )
550 cost = 0.0001 + 0.0020 * double( icost ) / double( numberCandidates - 1 );
561 candidates <<
new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost,
this,
false, quadrant );
565 if ( icost == numberCandidates )
567 icost = numberCandidates - 1;
570 else if ( icost > numberCandidates )
572 icost = numberCandidates - 2;
580 for (
int i = 0; i < candidates.
count(); ++i )
582 lPos << candidates.
at( i );
586 return candidates.
count();
594 if ( candidates < mLF->
layer()->
pal->line_p )
620 for (
int i = 1; i <= numberNodes - ( closedLine ? 1 : 2 ); ++i )
624 double x3 = x[ i == numberNodes - 1 ? 1 : i+1];
627 double y3 = y[ i == numberNodes - 1 ? 1 : i+1];
632 double vertexAngle =
M_PI - ( atan2( y3 - y2, x3 - x2 ) - atan2( y2 - y1, x2 - x1 ) );
636 if ( vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle >
M_PI * 225.0 / 180.0 )
637 extremeAngleNodes << i;
639 extremeAngleNodes << numberNodes - 1;
641 if ( extremeAngleNodes.
isEmpty() )
648 double* segmentLengths =
new double[ numberNodes-1 ];
649 double* distanceToSegment =
new double[ numberNodes ];
650 double totalLineLength = 0.0;
653 straightSegmentLengths.
reserve( extremeAngleNodes.
size() + 1 );
654 straightSegmentAngles.
reserve( extremeAngleNodes.
size() + 1 );
655 double currentStraightSegmentLength = 0;
656 double longestSegmentLength = 0;
657 int segmentIndex = 0;
658 double segmentStartX = x[0];
659 double segmentStartY = y[0];
660 for (
int i = 0; i < numberNodes - 1; i++ )
663 distanceToSegment[i] = 0;
665 distanceToSegment[i] = distanceToSegment[i-1] + segmentLengths[i-1];
668 totalLineLength += segmentLengths[i];
669 if ( extremeAngleNodes.
contains( i ) )
672 straightSegmentLengths << currentStraightSegmentLength;
674 longestSegmentLength = qMax( longestSegmentLength, currentStraightSegmentLength );
676 currentStraightSegmentLength = 0;
677 segmentStartX = x[i];
678 segmentStartY = y[i];
680 currentStraightSegmentLength += segmentLengths[i];
682 distanceToSegment[line->
nbPoints-1] = totalLineLength;
683 straightSegmentLengths << currentStraightSegmentLength;
685 longestSegmentLength = qMax( longestSegmentLength, currentStraightSegmentLength );
686 double middleOfLine = totalLineLength / 2.0;
688 if ( totalLineLength < labelWidth )
690 delete[] segmentLengths;
691 delete[] distanceToSegment;
695 double lineStepDistance = ( totalLineLength - labelWidth );
696 lineStepDistance = qMin( qMin( labelHeight, labelWidth ), lineStepDistance /
mLF->
layer()->
pal->line_p );
698 double distanceToEndOfSegment = 0.0;
699 int lastNodeInSegment = 0;
701 for (
int i = 0; i < straightSegmentLengths.
count(); ++i )
703 currentStraightSegmentLength = straightSegmentLengths.
at( i );
704 double currentSegmentAngle = straightSegmentAngles.
at( i );
705 lastNodeInSegment = extremeAngleNodes.
at( i );
706 double distanceToStartOfSegment = distanceToEndOfSegment;
707 distanceToEndOfSegment = distanceToSegment[ lastNodeInSegment ];
708 double distanceToCenterOfSegment = 0.5 * ( distanceToEndOfSegment + distanceToStartOfSegment );
710 if ( currentStraightSegmentLength < labelWidth )
714 double currentDistanceAlongLine = distanceToStartOfSegment;
715 double candidateStartX, candidateStartY, candidateEndX, candidateEndY;
716 double candidateLength = 0.0;
722 double segmentCost = 1.0 - ( distanceToEndOfSegment - distanceToStartOfSegment ) / longestSegmentLength;
723 double segmentAngleCost = 1 - qAbs( fmod( currentSegmentAngle,
M_PI ) -
M_PI_2 ) /
M_PI_2;
725 while ( currentDistanceAlongLine + labelWidth < distanceToEndOfSegment )
728 line->
getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine, &candidateStartX, &candidateStartY );
729 line->
getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine + labelWidth, &candidateEndX, &candidateEndY );
731 candidateLength = sqrt(( candidateEndX - candidateStartX ) * ( candidateEndX - candidateStartX ) + ( candidateEndY - candidateStartY ) * ( candidateEndY - candidateStartY ) );
737 cost = candidateLength / labelWidth;
743 cost = ( 1 - cost ) / 100;
747 double labelCenter = currentDistanceAlongLine + labelWidth / 2.0;
748 double costCenter = 2 * qAbs( labelCenter - distanceToCenterOfSegment ) / ( distanceToEndOfSegment - distanceToStartOfSegment );
749 cost += costCenter * 0.0005;
756 double costLineCenter = 2 * qAbs( labelCenter - middleOfLine ) / totalLineLength;
757 cost += costLineCenter * 0.0005;
760 cost += segmentCost * 0.0005;
761 cost += segmentAngleCost * 0.0001;
768 angle = atan2( candidateEndY - candidateStartY, candidateEndX - candidateStartX );
770 beta = angle +
M_PI / 2;
775 bool isRightToLeft = ( angle >
M_PI / 2 || angle <= -
M_PI / 2 );
781 double placementCost = 0.0;
786 lPos.
append(
new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost + placementCost,
this, isRightToLeft ) );
787 placementCost += 0.001;
794 lPos.
append(
new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost + placementCost,
this, isRightToLeft ) );
795 placementCost += 0.001;
801 lPos.
append(
new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost + placementCost,
this, isRightToLeft ) );
806 lPos.
append(
new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost,
this ) );
813 currentDistanceAlongLine += lineStepDistance;
817 delete[] segmentLengths;
818 delete[] distanceToSegment;
843 double* segmentLengths =
new double[nbPoints-1];
844 double* distanceToSegment =
new double[
nbPoints];
846 double totalLineLength = 0.0;
847 for (
int i = 0; i < line->
nbPoints - 1; i++ )
850 distanceToSegment[i] = 0;
852 distanceToSegment[i] = distanceToSegment[i-1] + segmentLengths[i-1];
855 totalLineLength += segmentLengths[i];
857 distanceToSegment[line->
nbPoints-1] = totalLineLength;
859 double lineStepDistance = ( totalLineLength - labelWidth );
860 double currentDistanceAlongLine = 0;
862 if ( totalLineLength > labelWidth )
864 lineStepDistance = qMin( qMin( labelHeight, labelWidth ), lineStepDistance /
mLF->
layer()->
pal->line_p );
868 currentDistanceAlongLine = - ( labelWidth - totalLineLength ) / 2.0;
869 lineStepDistance = -1;
870 totalLineLength = labelWidth;
873 double candidateLength;
875 double candidateStartX, candidateStartY, candidateEndX, candidateEndY;
877 while ( currentDistanceAlongLine < totalLineLength - labelWidth )
880 line->
getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine, &candidateStartX, &candidateStartY );
881 line->
getPointByDistance( segmentLengths, distanceToSegment, currentDistanceAlongLine + labelWidth, &candidateEndX, &candidateEndY );
883 if ( currentDistanceAlongLine < 0 )
886 candidateLength = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
887 + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
891 candidateLength = sqrt(( candidateEndX - candidateStartX ) * ( candidateEndX - candidateStartX ) + ( candidateEndY - candidateStartY ) * ( candidateEndY - candidateStartY ) );
894 cost = candidateLength / labelWidth;
900 cost = ( 1 - cost ) / 100;
904 double costCenter = qAbs( totalLineLength / 2 - ( currentDistanceAlongLine + labelWidth / 2 ) ) / totalLineLength;
905 cost += costCenter / 1000;
913 angle = atan2( candidateEndY - candidateStartY, candidateEndX - candidateStartX );
915 beta = angle +
M_PI / 2;
920 bool isRightToLeft = ( angle >
M_PI / 2 || angle <= -
M_PI / 2 );
929 positions.
append(
new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost,
this, isRightToLeft ) );
934 positions.
append(
new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost,
this, isRightToLeft ) );
939 positions.
append(
new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost,
this, isRightToLeft ) );
944 positions.
append(
new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost,
this ) );
951 currentDistanceAlongLine += lineStepDistance;
955 if ( lineStepDistance < 0 )
961 delete[] segmentLengths;
962 delete[] distanceToSegment;
972 while ( distance < 0 && index > 1 )
975 distance += path_distances[
index];
978 if ( index <= 1 && distance < 0 )
984 while ( index < path_positions->
nbPoints && distance > path_distances[index] )
986 distance -= path_distances[
index];
989 if ( index >= path_positions->
nbPoints )
998 double segment_length = path_distances[
index];
1005 if ( orientation == 0 )
1009 double _distance = distance;
1010 int endindex =
index;
1012 for (
int i = 0; i < li->
char_num; i++ )
1015 double start_x, start_y, end_x, end_y;
1016 if (
nextCharPosition( ci.
width, path_distances[index], path_positions, endindex, _distance, start_x, start_y, end_x, end_y ) ==
false )
1023 double dx = path_positions->
x[endindex] - path_positions->
x[
index];
1024 double dy = path_positions->
y[endindex] - path_positions->
y[
index];
1025 double line_angle = atan2( -dy, dx );
1027 bool isRightToLeft = ( line_angle > 0.55 *
M_PI || line_angle < -0.45 *
M_PI );
1028 reversed = isRightToLeft;
1029 orientation = isRightToLeft ? -1 : 1;
1034 if ( orientation < 0 )
1037 reversed = !reversed;
1045 double old_x = path_positions->
x[index-1];
1046 double old_y = path_positions->
y[index-1];
1048 double new_x = path_positions->
x[
index];
1049 double new_y = path_positions->
y[
index];
1051 double dx = new_x - old_x;
1052 double dy = new_y - old_y;
1054 double angle = atan2( -dy, dx );
1056 for (
int i = 0; i < li->
char_num; i++ )
1058 double last_character_angle =
angle;
1062 double start_x, start_y, end_x, end_y;
1063 if (
nextCharPosition( ci.
width, path_distances[index], path_positions, index, distance, start_x, start_y, end_x, end_y ) == false )
1070 angle = atan2( start_y - end_y, end_x - start_x );
1075 double angle_delta = last_character_angle -
angle;
1077 while ( angle_delta >
M_PI ) angle_delta -= 2 *
M_PI;
1078 while ( angle_delta < -
M_PI ) angle_delta += 2 *
M_PI;
1082 && angle_delta < li->max_char_angle_outside*(
M_PI / 180 ) ) )
1091 if ( orientation < 0 )
1096 start_x += dist * cos( angle +
M_PI_2 );
1097 start_y -= dist * sin( angle +
M_PI_2 );
1099 double render_angle =
angle;
1101 double render_x = start_x;
1102 double render_y = start_y;
1108 if ( orientation < 0 )
1111 render_x += ci.
width * cos( render_angle );
1112 render_y -= ci.
width * sin( render_angle );
1113 render_angle +=
M_PI;
1125 while ( render_angle >= 2 *
M_PI ) render_angle -= 2 *
M_PI;
1126 while ( render_angle < 0 ) render_angle += 2 *
M_PI;
1128 if ( render_angle >
M_PI / 2 && render_angle < 1.5 *
M_PI )
1152 double* path_distances =
new double[mapShape->
nbPoints];
1153 double total_distance = 0;
1154 double old_x = -1.0, old_y = -1.0;
1155 for (
int i = 0; i < mapShape->
nbPoints; i++ )
1158 path_distances[i] = 0;
1160 path_distances[i] = sqrt( pow( old_x - mapShape->
x[i], 2 ) + pow( old_y - mapShape->
y[i], 2 ) );
1161 old_x = mapShape->
x[i];
1162 old_y = mapShape->
y[i];
1164 total_distance += path_distances[i];
1169 delete[] path_distances;
1181 for (
double i = 0; i < total_distance; i += delta )
1185 bool reversed =
false;
1188 int orientation = 0;
1197 if ( slp ==
nullptr )
1207 orientation = -orientation;
1211 if ( slp ==
nullptr )
1215 double angle_diff = 0.0, angle_last = 0.0, diff;
1217 double sin_avg = 0, cos_avg = 0;
1222 diff = fabs( tmp->
getAlpha() - angle_last );
1223 if ( diff > 2*
M_PI ) diff -= 2 *
M_PI;
1224 diff = qMin( diff, 2 *
M_PI - diff );
1234 double angle_diff_avg = li->
char_num > 1 ? ( angle_diff / ( li->
char_num - 1 ) ) : 0;
1235 double cost = angle_diff_avg / 100;
1236 if ( cost < 0.0001 ) cost = 0.0001;
1240 double costCenter = qAbs( total_distance / 2 - labelCenter ) / total_distance;
1241 cost += costCenter / 1000;
1245 double angle_avg = atan2( sin_avg / li->
char_num, cos_avg / li->
char_num );
1246 bool localreversed = flip ? !reversed : reversed;
1248 for (
int i = 0; i <= 2; ++i )
1258 if ( i == 2 && (( !localreversed && ( flags & FLAG_BELOW_LINE ) ) || ( localreversed && ( flags & FLAG_ABOVE_LINE ) ) ) )
1268 while ( within && currentPos )
1288 int nbp = positions.
size();
1289 for (
int i = 0; i < nbp; i++ )
1294 delete[] path_distances;
1322 mapShape->
parent =
nullptr;
1324 shapes_toProcess.
append( mapShape );
1326 splitPolygons( shapes_toProcess, shapes_final, labelWidth, labelHeight );
1330 if ( !shapes_final.
isEmpty() )
1342 double diago = sqrt( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 );
1348 while ( !shapes_final.
isEmpty() )
1360 dx = labelWidth / 2.0;
1361 dy = labelHeight / 2.0;
1371 for ( bbid = 0; bbid < j; bbid++ )
1392 bool enoughPlace =
false;
1396 px = ( box->
x[0] + box->
x[2] ) / 2 - labelWidth;
1397 py = ( box->
y[0] + box->
y[2] ) / 2 - labelHeight;
1403 for ( rx = px, i = 0; i < 2; rx = rx + 2 * labelWidth, i++ )
1405 for ( ry = py, j = 0; j < 2; ry = ry + 2 * labelHeight, j++ )
1409 enoughPlace =
false;
1425 else if ( box->
length > 1.5*labelWidth && box->
width > 1.5*labelWidth )
1445 beta = atan2( labelHeight, labelWidth ) + alpha;
1451 dlx = cos( beta ) * diago;
1452 dly = sin( beta ) * diago;
1456 px0 = box->
width / 2.0;
1459 px0 -= ceil( px0 / dx ) * dx;
1460 py0 -= ceil( py0 / dy ) * dy;
1462 for ( px = px0; px <= box->
width; px += dx )
1464 for ( py = py0; py <= box->
length; py += dy )
1476 if ( candidateAcceptable )
1479 positions.
append(
new LabelPosition(
id++, rx - dlx, ry - dly, labelWidth, labelHeight, alpha, 0.0001,
this ) );
1485 nbp = positions.
size();
1493 while ( nbp == 0 && numTry < maxTry );
1495 nbp = positions.
size();
1497 for ( i = 0; i < nbp; i++ )
1502 for ( bbid = 0; bbid < j; bbid++ )
1518 double bboxMin[2],
double bboxMax[2],
1519 PointSet *mapShape, RTree<LabelPosition*, double, 2, double>* candidates )
1523 bbox[0] = bboxMin[0];
1524 bbox[1] = bboxMin[1];
1525 bbox[2] = bboxMax[0];
1526 bbox[3] = bboxMax[1];
1546 case GEOS_LINESTRING:
1584 bool outside =
false;
1601 return lPos.
count();
1610 int geomType = GEOSGeomTypeId_r( ctxt,
mGeos );
1612 double sizeCost = 0;
1613 if ( geomType == GEOS_LINESTRING )
1618 if ( GEOSLength_r( ctxt,
mGeos, &length ) != 1 )
1621 catch ( GEOSException &e )
1626 double bbox_length = qMax( bbx[2] - bbx[0], bby[2] - bby[0] );
1627 if ( length >= bbox_length / 4 )
1630 sizeCost = 1 - ( length / ( bbox_length / 4 ) );
1632 else if ( geomType == GEOS_POLYGON )
1637 if ( GEOSArea_r( ctxt,
mGeos, &area ) != 1 )
1640 catch ( GEOSException &e )
1645 double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] );
1646 if ( area >= bbox_area / 16 )
1649 sizeCost = 1 - ( area / ( bbox_area / 16 ) );
1655 for (
int i = 0; i < nbp; i++ )
1657 lPos.
at( i )->setCost( lPos.
at( i )->cost() + sizeCost / 100 );
1670 catch ( GEOSException &e )
1681 if ( !other->
mGeos )
1687 GEOSGeometry* g1 = GEOSGeom_clone_r( ctxt,
mGeos );
1688 GEOSGeometry* g2 = GEOSGeom_clone_r( ctxt, other->
mGeos );
1689 GEOSGeometry* geoms[2] = { g1, g2 };
1690 GEOSGeometry* g = GEOSGeom_createCollection_r( ctxt, GEOS_MULTILINESTRING, geoms, 2 );
1691 GEOSGeometry* gTmp = GEOSLineMerge_r( ctxt, g );
1692 GEOSGeom_destroy_r( ctxt, g );
1694 if ( GEOSGeomTypeId_r( ctxt, gTmp ) != GEOS_LINESTRING )
1697 GEOSGeom_destroy_r( ctxt, gTmp );
1712 catch ( GEOSException &e )
1734 bool uprightLabel =
false;
1739 uprightLabel =
true;
1745 uprightLabel =
true;
1751 uprightLabel =
true;
1753 return uprightLabel;
1757 double& start_x,
double& start_y,
double& end_x,
double& end_y )
const 1766 double old_x = path_positions->
x[index-1];
1767 double old_y = path_positions->
y[index-1];
1769 double new_x = path_positions->
x[
index];
1770 double new_y = path_positions->
y[
index];
1772 double dx = new_x - old_x;
1773 double dy = new_y - old_y;
1775 start_x = old_x + dx * distance / segment_length;
1776 start_y = old_y + dy * distance / segment_length;
1782 if ( segment_length - distance >= charWidth )
1785 distance += charWidth;
1786 end_x = old_x + dx * distance / segment_length;
1787 end_y = old_y + dy * distance / segment_length;
1798 if ( index >= path_positions->
nbPoints )
1802 new_x = path_positions->
x[
index];
1803 new_y = path_positions->
y[
index];
1807 while ( sqrt( pow( start_x - new_x, 2 ) + pow( start_y - new_y, 2 ) ) < charWidth );
1813 distance = sqrt( pow( old_x - end_x, 2 ) + pow( old_y - end_y, 2 ) );
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.
Label below point, slightly right of center.
bool centroidInside() const
Returns whether labels placed at the centroid of features within the layer are forced to be placed in...
Label on bottom-left of point.
virtual ~FeaturePart()
Delete the feature.
int createCandidatesForPolygon(QList< LabelPosition *> &lPos, PointSet *mapShape)
Generate candidates for polygon features.
double distLabel() const
Applies to "around point" placement strategy or linestring features.
bool isIntersect(double *bbox)
Is the labelposition intersect the bounding-box ?
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
double fixedAngle() const
Returns the fixed angle for the feature's label.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)
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
double priority() const
Returns the feature's labeling priority.
bool alwaysShow() const
Whether label should be always shown (sets very high label priority)
Label on top-left of point.
void setCost(double newCost)
Sets the candidate label position's geographical cost.
int incrementUpsideDownCharCount()
Increases the count of upside down characters for this label position.
bool hasFixedRotation() const
Returns true if the feature's label has a fixed rotation.
double getY(int i=0) const
get the down-left y coordinate
QgsPoint positionOffset() const
Applies only to "offset from point" placement strategy.
A set of features which influence the labelling process.
PredefinedPointPosition
Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode...
void offsetPosition(double xOffset, double yOffset)
Shift the label by specified offset.
const T & at(int i) const
int createCandidatesAlongLineNearStraightSegments(QList< LabelPosition *> &lPos, PointSet *mapShape)
Generate candidates for line feature, by trying to place candidates towards the middle of the longest...
void createGeosGeom() const
Candidates are placed in predefined positions around a point.
friend class LabelPosition
const GEOSPreparedGeometry * permissibleZonePrepared() const
Returns a GEOS prepared geometry representing the label's permissibleZone().
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.
const QSizeF & symbolSize() const
Returns the size of the rendered symbol associated with this feature, if applicable.
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged)...
UpsideDownLabels upsidedownLabels() const
Returns how upside down labels are handled within the layer.
bool isConnected(FeaturePart *p2)
Check whether this part is connected with some other part.
QgsPoint fixedPosition() const
Coordinates of the fixed position (relevant only if hasFixedPosition() returns true) ...
double getLabelDistance() const
int createCandidatesAtOrderedPositionsOverPoint(double x, double y, QList< LabelPosition *> &lPos, double angle)
Generates candidates following a prioritised list of predefined positions around a point...
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
double y() const
Get the y value of the point.
Arranges candidates following the curvature of a line feature.
CharacterInfo * char_info
bool isInside(double *bbox)
Is the labelposition inside the bounding-box ?
int createCandidatesAroundPoint(double x, double y, QList< LabelPosition *> &lPos, double angle)
Generate candidates for point feature, located around a specified point.
double priority() const
Returns the layer's priority, between 0 and 1.
LabelPosition * curvedPlacementAtOffset(PointSet *path_positions, double *path_distances, int &orientation, int index, double distance, bool &reversed, bool &flip)
Returns the label position for a curved label at a specific offset along a path.
double cost() const
Returns the candidate label position's geographical cost.
int count(const T &value) const
pal::LabelInfo * curvedLabelInfo() const
Get additional infor required for curved label placement. Returns null if not set.
bool contains(const T &value) const
void append(const T &value)
bool hasFixedQuadrant() const
Returns whether the quadrant for the label is fixed.
static bool containsCandidate(const GEOSPreparedGeometry *geom, double x, double y, double width, double height, double alpha)
Returns true if a GEOS prepared geometry totally contains a label candidate.
QgsGeometry permissibleZone() const
Returns the label's permissible zone geometry.
bool nextCharPosition(double charWidth, double segment_length, PointSet *path_positions, int &index, double &distance, double &start_x, double &start_y, double &end_x, double &end_y) const
Returns true if the next char position is found. The referenced parameters are updated.
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.
void addSizePenalty(int nbp, QList< LabelPosition *> &lPos, double bbx[4], double bby[4])
double width() const
Width of the rectangle.
static LabelPosition * _createCurvedCandidate(LabelPosition *lp, double angle, double dist)
Arranges candidates in a circle around a point (or centroid of a polygon).
LabelPosition * getNextPart() const
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 calculatePriority() const
Calculates the priority for the feature.
QgsPalLayerSettings::Placement arrangement() const
Returns the layer's arrangement policy.
bool hasFixedAngle() const
Whether the label should use a fixed angle instead of using angle from automatic placement.
void insertIntoIndex(RTree< LabelPosition *, double, 2, double > *index)
static double dist_euc2d(double x1, double y1, double x2, double y2)
pal::Layer * layer() const
Get PAL layer of the label feature. Should be only used internally in PAL.
int createCandidatesAlongLine(QList< LabelPosition *> &lPos, PointSet *mapShape)
Generate candidates for line feature.
GEOSContextHandle_t geosContext()
Get GEOS context handle to be used in all GEOS library calls with reentrant API.
double fixedAngle() const
Angle in degrees of the fixed angle (relevant only if hasFixedAngle() returns true) ...
double getLabelHeight() const
Stores visual margins for labels (left, right, top and bottom)
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
Main class to handle feature.
int upsideDownCharCount() const
Returns the number of upside down characters for this label position.
Offset distance applies from rendered symbol bounds.
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 hasFixedPosition() const
Returns true if the feature's label has a fixed position.
int createCandidatesOverPoint(double x, double y, QList< LabelPosition *> &lPos, double angle)
Generate one candidate over or offset the specified point.
QPointF quadOffset() const
Applies to "offset from point" placement strategy and "around point" (in case hasFixedQuadrant() retu...
const VisualMargin & visualMargin() const
Returns the visual margin for the label feature.
void setNextPart(LabelPosition *next)
CHullBox * compute_chull_bbox()
const T & at(int i) const
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point...
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...
bool hasSameLabelFeatureAs(FeaturePart *part) const
Tests whether this feature part belongs to the same QgsLabelFeature as another feature part...
double getAlpha() const
get alpha
double length() const
Returns length of line geometry.
QgsPalLayerSettings::OffsetType offsetType() const
Returns the offset type, which determines how offsets and distance to label behaves.
double getX(int i=0) const
get the down-left x coordinate
double max_char_angle_inside
double right
Right margin.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
int createCandidatesAlongLineNearMidpoint(QList< LabelPosition *> &lPos, PointSet *mapShape, double initialCost=0.0)
Generate candidates for line feature, by trying to place candidates as close as possible to the line'...
Label below point, slightly left of center.
void extractCoords(const GEOSGeometry *geom)
read coordinates from a GEOS geom
int count(const T &value) const
QString name() const
Returns the layer's name.
double getLabelWidth() const
LabelPosition is a candidate feature label position.
Label on top of point, slightly left of center.
Quadrant
Position of label candidate relative to feature.
const GEOSPreparedGeometry * preparedGeom() const
LineArrangementFlags arrangementFlags() const
Returns the layer's arrangement flags.
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...
FeaturePart(QgsLabelFeature *lf, const GEOSGeometry *geom)
Creates a new generic feature.
QVector< QgsPalLayerSettings::PredefinedPointPosition > predefinedPositionOrder() const
Returns the priority ordered list of predefined positions for label candidates.
void getCentroid(double &px, double &py, bool forceInside=false) const
static void splitPolygons(QLinkedList< PointSet *> &shapes_toProcess, QLinkedList< PointSet *> &shapes_final, double xrm, double yrm)
Split a concave shape into several convex shapes.
bool isCurved() const
Returns true if the layer has curved labels.
bool showUprightLabels() const
Returns true if feature's label must be displayed upright.
double x() const
Get the x value of the point.
void append(const T &value)
double height() const
Height of the rectangle.
int connectedFeatureId(QgsFeatureId featureId) const
Returns the connected feature ID for a label feature ID, which is unique for all features which have ...
int createCurvedCandidatesAlongLine(QList< LabelPosition *> &lPos, PointSet *mapShape)
Generate curved candidates for line features.
Arranges candidates scattered throughout a polygon feature.