@@ -237,7 +237,7 @@ namespace pal
237
237
}
238
238
}
239
239
240
- int FeaturePart::setPositionOverPoint ( double x, double y, LabelPosition ***lPos, double angle )
240
+ int FeaturePart::setPositionOverPoint ( double x, double y, LabelPosition ***lPos, double angle, PointSet *mapShape )
241
241
{
242
242
int nbp = 1 ;
243
243
*lPos = new LabelPosition *[nbp];
@@ -308,20 +308,30 @@ namespace pal
308
308
double lx = x + xdiff;
309
309
double ly = y + ydiff;
310
310
311
+ if ( mapShape && type == GEOS_POLYGON && mFeature ->layer ->fitInPolygonOnly () )
312
+ {
313
+ if ( !mapShape->containsLabelCandidate ( lx, ly, labelW, labelH, angle ) )
314
+ {
315
+ delete[] *lPos;
316
+ *lPos = 0 ;
317
+ return 0 ;
318
+ }
319
+ }
320
+
311
321
( *lPos )[0 ] = new LabelPosition ( id, lx, ly, labelW, labelH, angle, cost, this , false , quadrantFromOffset () );
312
322
return nbp;
313
323
}
314
324
315
- int FeaturePart::setPositionForPoint ( double x, double y, LabelPosition ***lPos, double angle )
325
+ int FeaturePart::setPositionForPoint ( double x, double y, LabelPosition ***lPos, double angle, PointSet *mapShape )
316
326
{
317
327
318
328
#ifdef _DEBUG_
319
329
std::cout << " SetPosition (point) : " << layer->name << " /" << uid << std::endl;
320
330
#endif
321
331
322
- double xrm = mFeature ->label_x ;
323
- double yrm = mFeature ->label_y ;
324
- double distlabel = mFeature ->distlabel ;
332
+ double labelWidth = mFeature ->label_x ;
333
+ double labelHeight = mFeature ->label_y ;
334
+ double distanceToLabel = mFeature ->distlabel ;
325
335
326
336
int numberCandidates = mFeature ->layer ->pal ->point_p ;
327
337
@@ -339,10 +349,10 @@ namespace pal
339
349
340
350
double gamma1, gamma2;
341
351
342
- if ( distlabel > 0 )
352
+ if ( distanceToLabel > 0 )
343
353
{
344
- gamma1 = atan2 ( yrm / 2 , distlabel + xrm / 2 );
345
- gamma2 = atan2 ( xrm / 2 , distlabel + yrm / 2 );
354
+ gamma1 = atan2 ( labelHeight / 2 , distanceToLabel + labelWidth / 2 );
355
+ gamma2 = atan2 ( labelWidth / 2 , distanceToLabel + labelHeight / 2 );
346
356
}
347
357
else
348
358
{
@@ -361,7 +371,7 @@ namespace pal
361
371
std::cout << " Oups... label size error..." << std::endl;
362
372
}
363
373
364
- *lPos = new LabelPosition *[numberCandidates] ;
374
+ QList< LabelPosition* > candidates ;
365
375
366
376
int i;
367
377
double angleToCandidate;
@@ -377,59 +387,59 @@ namespace pal
377
387
378
388
if ( angleToCandidate < gamma1 || angleToCandidate > a360 - gamma1 ) // on the right
379
389
{
380
- labelX += distlabel ;
390
+ labelX += distanceToLabel ;
381
391
double iota = ( angleToCandidate + gamma1 );
382
392
if ( iota > a360 - gamma1 )
383
393
iota -= a360;
384
394
385
395
// ly += -yrm/2.0 + tan(alpha)*(distlabel + xrm/2);
386
- labelY += -yrm + yrm * iota / ( 2 * gamma1 );
396
+ labelY += -labelHeight + labelHeight * iota / ( 2 * gamma1 );
387
397
388
398
quadrant = LabelPosition::QuadrantRight;
389
399
}
390
400
else if ( angleToCandidate < a90 - gamma2 ) // top-right
391
401
{
392
- labelX += distlabel * cos ( angleToCandidate );
393
- labelY += distlabel * sin ( angleToCandidate );
402
+ labelX += distanceToLabel * cos ( angleToCandidate );
403
+ labelY += distanceToLabel * sin ( angleToCandidate );
394
404
quadrant = LabelPosition::QuadrantAboveRight;
395
405
}
396
406
else if ( angleToCandidate < a90 + gamma2 ) // top
397
407
{
398
408
// lx += -xrm/2.0 - tan(alpha+a90)*(distlabel + yrm/2);
399
- labelX += -xrm * ( angleToCandidate - a90 + gamma2 ) / ( 2 * gamma2 );
400
- labelY += distlabel ;
409
+ labelX += -labelWidth * ( angleToCandidate - a90 + gamma2 ) / ( 2 * gamma2 );
410
+ labelY += distanceToLabel ;
401
411
quadrant = LabelPosition::QuadrantAbove;
402
412
}
403
413
else if ( angleToCandidate < a180 - gamma1 ) // top left
404
414
{
405
- labelX += distlabel * cos ( angleToCandidate ) - xrm ;
406
- labelY += distlabel * sin ( angleToCandidate );
415
+ labelX += distanceToLabel * cos ( angleToCandidate ) - labelWidth ;
416
+ labelY += distanceToLabel * sin ( angleToCandidate );
407
417
quadrant = LabelPosition::QuadrantAboveLeft;
408
418
}
409
419
else if ( angleToCandidate < a180 + gamma1 ) // left
410
420
{
411
- labelX += -distlabel - xrm ;
421
+ labelX += -distanceToLabel - labelWidth ;
412
422
// ly += -yrm/2.0 - tan(alpha)*(distlabel + xrm/2);
413
- labelY += - ( angleToCandidate - a180 + gamma1 ) * yrm / ( 2 * gamma1 );
423
+ labelY += - ( angleToCandidate - a180 + gamma1 ) * labelHeight / ( 2 * gamma1 );
414
424
quadrant = LabelPosition::QuadrantLeft;
415
425
}
416
426
else if ( angleToCandidate < a270 - gamma2 ) // down - left
417
427
{
418
- labelX += distlabel * cos ( angleToCandidate ) - xrm ;
419
- labelY += distlabel * sin ( angleToCandidate ) - yrm ;
428
+ labelX += distanceToLabel * cos ( angleToCandidate ) - labelWidth ;
429
+ labelY += distanceToLabel * sin ( angleToCandidate ) - labelHeight ;
420
430
quadrant = LabelPosition::QuadrantBelowLeft;
421
431
}
422
432
else if ( angleToCandidate < a270 + gamma2 ) // down
423
433
{
424
- labelY += -distlabel - yrm ;
434
+ labelY += -distanceToLabel - labelHeight ;
425
435
// lx += -xrm/2.0 + tan(alpha+a90)*(distlabel + yrm/2);
426
- labelX += -xrm + ( angleToCandidate - a270 + gamma2 ) * xrm / ( 2 * gamma2 );
436
+ labelX += -labelWidth + ( angleToCandidate - a270 + gamma2 ) * labelWidth / ( 2 * gamma2 );
427
437
quadrant = LabelPosition::QuadrantBelow;
428
438
}
429
439
else if ( angleToCandidate < a360 ) // down - right
430
440
{
431
- labelX += distlabel * cos ( angleToCandidate );
432
- labelY += distlabel * sin ( angleToCandidate ) - yrm ;
441
+ labelX += distanceToLabel * cos ( angleToCandidate );
442
+ labelY += distanceToLabel * sin ( angleToCandidate ) - labelHeight ;
433
443
quadrant = LabelPosition::QuadrantBelowRight;
434
444
}
435
445
@@ -440,7 +450,16 @@ namespace pal
440
450
else
441
451
cost = 0.0001 + 0.0020 * double ( icost ) / double ( numberCandidates - 1 );
442
452
443
- ( *lPos )[i] = new LabelPosition ( i, labelX, labelY, xrm, yrm, angle, cost, this , false , quadrant );
453
+
454
+ if ( mapShape && type == GEOS_POLYGON && mFeature ->layer ->fitInPolygonOnly () )
455
+ {
456
+ if ( !mapShape->containsLabelCandidate ( labelX, labelY, labelWidth, labelHeight, angle ) )
457
+ {
458
+ continue ;
459
+ }
460
+ }
461
+
462
+ candidates << new LabelPosition ( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this , false , quadrant );
444
463
445
464
icost += inc;
446
465
@@ -457,10 +476,19 @@ namespace pal
457
476
458
477
}
459
478
460
- return numberCandidates;
479
+ if ( !candidates.isEmpty () )
480
+ {
481
+ *lPos = new LabelPosition *[candidates.count ()];
482
+ for ( int i = 0 ; i < candidates.count (); ++i )
483
+ {
484
+ ( *lPos )[i] = candidates.at ( i );
485
+ }
486
+ }
487
+
488
+ return candidates.count ();
461
489
}
462
490
463
- // TODO work with squared distance by remonving call to sqrt or dist_euc2d
491
+ // TODO work with squared distance by removing call to sqrt or dist_euc2d
464
492
int FeaturePart::setPositionForLine ( LabelPosition ***lPos, PointSet *mapShape )
465
493
{
466
494
#ifdef _DEBUG_
@@ -969,8 +997,8 @@ namespace pal
969
997
int i;
970
998
int j;
971
999
972
- double xrm = mFeature ->label_x ;
973
- double yrm = mFeature ->label_y ;
1000
+ double labelWidth = mFeature ->label_x ;
1001
+ double labelHeight = mFeature ->label_y ;
974
1002
975
1003
// print();
976
1004
@@ -981,7 +1009,7 @@ namespace pal
981
1009
982
1010
shapes_toProcess.append ( mapShape );
983
1011
984
- splitPolygons ( shapes_toProcess, shapes_final, xrm, yrm , mFeature ->uid );
1012
+ splitPolygons ( shapes_toProcess, shapes_final, labelWidth, labelHeight , mFeature ->uid );
985
1013
986
1014
int nbp;
987
1015
@@ -997,7 +1025,7 @@ namespace pal
997
1025
double dy;
998
1026
int bbid;
999
1027
double beta;
1000
- double diago = sqrt ( xrm * xrm / 4.0 + yrm * yrm / 4 );
1028
+ double diago = sqrt ( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 );
1001
1029
double rx, ry;
1002
1030
CHullBox **boxes = new CHullBox*[shapes_final.size ()];
1003
1031
j = 0 ;
@@ -1015,12 +1043,16 @@ namespace pal
1015
1043
}
1016
1044
1017
1045
// dx = dy = min( yrm, xrm ) / 2;
1018
- dx = xrm / 2.0 ;
1019
- dy = yrm / 2.0 ;
1046
+ dx = labelWidth / 2.0 ;
1047
+ dy = labelHeight / 2.0 ;
1048
+
1020
1049
1050
+ int numTry = 0 ;
1051
+
1052
+ // fit in polygon only mode slows down calculation a lot, so if it's enabled
1053
+ // then use a smaller limit for number of iterations
1054
+ int maxTry = mFeature ->layer ->fitInPolygonOnly () ? 7 : 10 ;
1021
1055
1022
- int num_try = 0 ;
1023
- int max_try = 10 ;
1024
1056
do
1025
1057
{
1026
1058
for ( bbid = 0 ; bbid < j; bbid++ )
@@ -1033,11 +1065,21 @@ namespace pal
1033
1065
std::cout << " Box size: " << box->length << " /" << box->width << std::endl;
1034
1066
std::cout << " Alpha: " << alpha << " " << alpha * 180 / M_PI << std::endl;
1035
1067
std::cout << " Dx;Dy: " << dx << " " << dy << std::endl;
1036
- std::cout << " LabelSizerm: " << xrm << " " << yrm << std::endl;
1068
+ std::cout << " LabelSizerm: " << labelWidth << " " << labelHeight << std::endl;
1037
1069
std::cout << " LabelSizeUn: " << mFeature ->label_x << " " << mFeature ->label_y << std::endl;
1038
1070
continue ;
1039
1071
}
1040
1072
1073
+ if ( mFeature ->layer ->arrangement () == P_HORIZ && mFeature ->layer ->fitInPolygonOnly () )
1074
+ {
1075
+ // check width/height of bbox is sufficient for label
1076
+ if ( box->length < labelWidth || box->width < labelHeight )
1077
+ {
1078
+ // no way label can fit in this box, skip it
1079
+ continue ;
1080
+ }
1081
+ }
1082
+
1041
1083
#ifdef _DEBUG_FULL_
1042
1084
std::cout << " New BBox : " << bbid << std::endl;
1043
1085
for ( i = 0 ; i < 4 ; i++ )
@@ -1050,16 +1092,16 @@ namespace pal
1050
1092
if ( mFeature ->layer ->arrangement () == P_FREE )
1051
1093
{
1052
1094
enoughPlace = true ;
1053
- px = ( box->x [0 ] + box->x [2 ] ) / 2 - xrm ;
1054
- py = ( box->y [0 ] + box->y [2 ] ) / 2 - yrm ;
1095
+ px = ( box->x [0 ] + box->x [2 ] ) / 2 - labelWidth ;
1096
+ py = ( box->y [0 ] + box->y [2 ] ) / 2 - labelHeight ;
1055
1097
int i, j;
1056
1098
1057
1099
// Virtual label: center on bbox center, label size = 2x original size
1058
1100
// alpha = 0.
1059
1101
// If all corner are in bbox then place candidates horizontaly
1060
- for ( rx = px, i = 0 ; i < 2 ; rx = rx + 2 * xrm , i++ )
1102
+ for ( rx = px, i = 0 ; i < 2 ; rx = rx + 2 * labelWidth , i++ )
1061
1103
{
1062
- for ( ry = py, j = 0 ; j < 2 ; ry = ry + 2 * yrm , j++ )
1104
+ for ( ry = py, j = 0 ; j < 2 ; ry = ry + 2 * labelHeight , j++ )
1063
1105
{
1064
1106
if ( !mapShape->containsPoint ( rx, ry ) )
1065
1107
{
@@ -1079,7 +1121,7 @@ namespace pal
1079
1121
{
1080
1122
alpha = 0.0 ; // HORIZ
1081
1123
}
1082
- else if ( box->length > 1.5 *xrm && box->width > 1.5 *xrm )
1124
+ else if ( box->length > 1.5 *labelWidth && box->width > 1.5 *labelWidth )
1083
1125
{
1084
1126
if ( box->alpha <= M_PI / 4 )
1085
1127
{
@@ -1099,7 +1141,7 @@ namespace pal
1099
1141
alpha = box->alpha ;
1100
1142
}
1101
1143
1102
- beta = atan2 ( yrm, xrm ) + alpha;
1144
+ beta = atan2 ( labelHeight, labelWidth ) + alpha;
1103
1145
1104
1146
1105
1147
// alpha = box->alpha;
@@ -1108,7 +1150,6 @@ namespace pal
1108
1150
dlx = cos ( beta ) * diago;
1109
1151
dly = sin ( beta ) * diago;
1110
1152
1111
-
1112
1153
double px0, py0;
1113
1154
1114
1155
px0 = box->width / 2.0 ;
@@ -1128,11 +1169,13 @@ namespace pal
1128
1169
rx += box->x [0 ];
1129
1170
ry += box->y [0 ];
1130
1171
1131
- // Only accept candidate that center is in the polygon
1132
- if ( mapShape->containsPoint ( rx, ry ) )
1172
+ bool candidateAcceptable = ( mFeature ->layer ->fitInPolygonOnly ()
1173
+ ? mapShape->containsLabelCandidate ( rx - dlx, ry - dly, labelWidth, labelHeight, alpha )
1174
+ : mapShape->containsPoint ( rx, ry ) );
1175
+ if ( candidateAcceptable )
1133
1176
{
1134
1177
// cost is set to minimal value, evaluated later
1135
- positions.append ( new LabelPosition ( id++, rx - dlx, ry - dly, xrm, yrm , alpha, 0.0001 , this ) ); // Polygon
1178
+ positions.append ( new LabelPosition ( id++, rx - dlx, ry - dly, labelWidth, labelHeight , alpha, 0.0001 , this ) ); // Polygon
1136
1179
}
1137
1180
}
1138
1181
}
@@ -1143,10 +1186,10 @@ namespace pal
1143
1186
{
1144
1187
dx /= 2 ;
1145
1188
dy /= 2 ;
1146
- num_try ++;
1189
+ numTry ++;
1147
1190
}
1148
1191
}
1149
- while ( nbp == 0 && num_try < max_try );
1192
+ while ( nbp == 0 && numTry < maxTry );
1150
1193
1151
1194
nbp = positions.size ();
1152
1195
@@ -1245,9 +1288,9 @@ namespace pal
1245
1288
double cx, cy;
1246
1289
mapShape->getCentroid ( cx, cy, mFeature ->layer ->centroidInside () );
1247
1290
if ( mFeature ->layer ->arrangement () == P_POINT_OVER )
1248
- nbp = setPositionOverPoint ( cx, cy, lPos, angle );
1291
+ nbp = setPositionOverPoint ( cx, cy, lPos, angle, mapShape );
1249
1292
else
1250
- nbp = setPositionForPoint ( cx, cy, lPos, angle );
1293
+ nbp = setPositionForPoint ( cx, cy, lPos, angle, mapShape );
1251
1294
break ;
1252
1295
case P_LINE:
1253
1296
nbp = setPositionForLine ( lPos, mapShape );
0 commit comments