[mapserver-commits] r13169 - sandbox/tb-labels

svn at osgeo.org svn at osgeo.org
Thu Feb 23 14:03:13 EST 2012


Author: tbonfort
Date: 2012-02-23 11:03:13 -0800 (Thu, 23 Feb 2012)
New Revision: 13169

Modified:
   sandbox/tb-labels/mapdraw.c
   sandbox/tb-labels/mapfile.c
   sandbox/tb-labels/maplabel.c
   sandbox/tb-labels/mapprimitive.c
   sandbox/tb-labels/mapprimitive.h
   sandbox/tb-labels/mapserver.h
Log:
modify msTestLabelCacheCollisions to not modify cachePtr->status.
add offseted labels with leader lines



Modified: sandbox/tb-labels/mapdraw.c
===================================================================
--- sandbox/tb-labels/mapdraw.c	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/mapdraw.c	2012-02-23 19:03:13 UTC (rev 13169)
@@ -2343,44 +2343,216 @@
   return MS_SUCCESS;
 }
 
+/* private shortcut function to try a leader offsetted label */
+void offsetAndTest(imageObj*image, mapObj *map, labelCacheMemberObj *cachePtr, double ox, double oy,
+      int priority, int label_idx, shapeObj *unoffsetedpoly) {
+   /* offset cachePtr->poly and cachePtr->point */
+   int i,j;
+   for(i=cachePtr->poly->numlines-1;i>=0;i--) {
+      for(j=cachePtr->poly->line[i].numpoints-1;j>=0;j--) {
+         cachePtr->poly->line[i].point[j].x = unoffsetedpoly->line[i].point[j].x + ox;
+         cachePtr->poly->line[i].point[j].y = unoffsetedpoly->line[i].point[j].y + oy;
+      }
+   }
+   cachePtr->poly->bounds.minx = unoffsetedpoly->bounds.minx + ox;
+   cachePtr->poly->bounds.miny = unoffsetedpoly->bounds.miny + oy;
+   cachePtr->poly->bounds.maxx = unoffsetedpoly->bounds.maxx + ox;
+   cachePtr->poly->bounds.maxy = unoffsetedpoly->bounds.maxy + oy;
 
+   cachePtr->point.x = cachePtr->leaderline->point[0].x + ox;
+   cachePtr->point.y = cachePtr->leaderline->point[0].y + oy;
+   
+   /* set the second point of the leader line */
+   cachePtr->leaderline->point[1].x = cachePtr->point.x;
+   cachePtr->leaderline->point[1].y = cachePtr->point.y;
+
+   /* compute leader line bbox */
+   if(ox>0) {
+      cachePtr->leaderbbox->minx = cachePtr->leaderline->point[0].x;
+      cachePtr->leaderbbox->maxx = cachePtr->point.x;
+   } else {
+      cachePtr->leaderbbox->maxx = cachePtr->leaderline->point[0].x;
+      cachePtr->leaderbbox->minx = cachePtr->point.x;
+   }
+   if(oy>0) {
+      cachePtr->leaderbbox->miny = cachePtr->leaderline->point[0].y;
+      cachePtr->leaderbbox->maxy = cachePtr->point.y;
+   } else {
+      cachePtr->leaderbbox->maxy = cachePtr->leaderline->point[0].y;
+      cachePtr->leaderbbox->miny = cachePtr->point.y;
+   }
+   cachePtr->status = msTestLabelCacheCollisions(&(map->labelcache), &(cachePtr->labels[0]), image->width, image->height, 0 /* todo map_edge_buffer */,
+         cachePtr, priority, -label_idx, 0, 0);
+   if(cachePtr->status) {
+      int ll;
+      for(ll=0;ll<cachePtr->numlabels;ll++) {
+         cachePtr->labels[ll].annopoint.x += ox;
+         cachePtr->labels[ll].annopoint.y += oy;
+      }
+   }
+}
+
 int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) {
    assert(MS_RENDERER_PLUGIN(image->format));
    int retval = MS_SUCCESS;
-   int l;
+   int l,map_edge_buffer;
    labelCacheSlotObj *cacheslot;
    labelCacheMemberObj *cachePtr;
    cacheslot = &(map->labelcache.slots[priority]);
+   char *value;
+   if((value = msLookupHashTable(&(map->web.metadata), "labelcache_map_edge_buffer")) != NULL) {
+      map_edge_buffer = atoi(value);
+   }
    for(l=cacheslot->numlabels-1; l>=0; l--) {
       cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */
-      if(cachePtr->status == MS_FALSE) { /* only test labels that haven't been rendered */
+      if(cachePtr->status == MS_FALSE && !cachePtr->labelpath) {
+         /* only test regular labels that haven't been rendered */
          classObj *classPtr = (GET_CLASS(map,cachePtr->layerindex,cachePtr->classindex));
+         layerObj *layerPtr = (GET_LAYER(map,cachePtr->layerindex));
          if(classPtr->leader.maxdistance) { /* only test labels that can be offsetted */
-            
-            /* if the entry has a single label and it has position != CC, 
+            if(cachePtr->point.x <= -map_edge_buffer ||
+                  cachePtr->point.y <= -map_edge_buffer ||
+                  cachePtr->point.x >= image->width + map_edge_buffer ||
+                  cachePtr->point.y >= image->height + map_edge_buffer) {
+               /* don't look for leaders if point is in edge buffer as the leader line would end up chopped off */
+               continue;
+            }
+
+            /* TODO: if the entry has a single label and it has position != CC, 
              * recompute the cachePtr->poly and labelPtr->annopoint using POSITION CC */
             shapeObj origPoly;
             msInitShape(&origPoly);
             msCopyShape(cachePtr->poly,&origPoly);
+            
+            cachePtr->leaderline = msSmallMalloc(sizeof(lineObj));
+            cachePtr->leaderline->numpoints = 2;
+            cachePtr->leaderline->point = msSmallMalloc(2*sizeof(pointObj));
+            cachePtr->leaderline->point[0] = cachePtr->point;
+            cachePtr->leaderbbox = msSmallMalloc(sizeof(rectObj));
 
+            int steps = classPtr->leader.maxdistance / classPtr->leader.gridstep;
+            int i;
 
+#define x0 (cachePtr->leaderline->point[0].x)
+#define y0 (cachePtr->leaderline->point[0].y)
+#define gridstepsc (classPtr->leader.gridstep)
+
+#define otest(ox,oy) offsetAndTest(image,map,cachePtr,(ox),(oy),priority,l,&origPoly); \
+               if(cachePtr->status) break;
+
             /* loop through possible offsetted positions */
-            {
-               /* offset cachePtr->poly and cachePtr->point*/
+            for(i=1;i<=steps;i++) {
 
-               /* test for collision of offsetted label ( and leader line ) */
                
-               /* if no collision */
-               {
-                 /* mark label as rendered */
-                 /* add leader line to cachePtr */
-                 /* render label group and leader line */
-                 /* continue to next label is slot */
+                 /* test the 4 cardinal points on the ring */
+
+                 /* (points marked "0" are the ones being tested)
+                 
+                    XXX0XXX
+                    XXXXXXX
+                    XXXXXXX
+                    0XX.XX0
+                    XXXXXXX
+                    XXXXXXX
+                    XXX0XXX
+ 
+                  * (x0+i*gridtep,y0), pos cr
+
+                  * (x0-i*gridstep,y0), pos cl
+                  * (x0,y0-i*gridstep), pos uc
+                  * (x0,y0+i*gridstep), pos lc
+                  */ 
+               otest(i*gridstepsc,0);
+               otest(-i*gridstepsc,0);
+               otest(0,-i*gridstepsc);
+               otest(0,i*gridstepsc);
+               otest(i*gridstepsc,i*gridstepsc);
+               otest(-i*gridstepsc,-i*gridstepsc);
+               otest(i*gridstepsc,-i*gridstepsc);
+               otest(-i*gridstepsc,i*gridstepsc);
+
+                 
+               /* test the intermediate points on the ring */
+                 
+                 /* (points marked "0" are the ones being tested)
+                 
+                    X00X00X
+                    0XXXXX0
+                    0XXXXX0
+                    XXX.XXX
+                    0XXXXX0
+                    0XXXXX0
+                    X00X00X
+
+                 */
+                 
+                 /* test the extreme diagonal points */
+                 
+                 /* (points marked "0" are the ones being tested)
+                 
+                    0XXXXX0
+                    XXXXXXX
+                    XXXXXXX
+                    XXX.XXX
+                    XXXXXXX
+                    XXXXXXX
+                    0XXXXX0
+
+                    (x0+i*gridstep, y0+i*gridstep), pos lr
+                    (x0-i*gridstep, y0-i*gridstep), pos ul
+                    (x0+i*gridstep, y0-i*gridstep), pos ur
+                    (x0-i*gridstep, y0+i*gridstep), pos ll
+
+                 */
+            }
+            if(cachePtr->status) {
+               shapeObj labelLeader; /* label polygon (bounding box, possibly rotated) */
+               labelLeader.line = cachePtr->leaderline; /* setup the label polygon structure */
+               labelLeader.numlines = 1;
+
+               int ll;
+               for(ll=0;ll<classPtr->leader.numstyles;ll++) {
+                  msDrawLineSymbol(&map->symbolset, image,&labelLeader , classPtr->leader.styles[ll], layerPtr->scalefactor);
                }
-               /* else */
-               {
-                 /* reset cachePtr->poly and cachePtr->point */
+               for(ll=0; ll<cachePtr->numlabels; ll++) {
+                  labelObj *labelPtr = &(cachePtr->labels[ll]);
+
+                  /* here's where we draw the label styles */
+                  if(labelPtr->numstyles > 0) {
+                     for(i=0; i<labelPtr->numstyles; i++) {
+                        if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT)
+                           msDrawMarkerSymbol(&map->symbolset, image, &(cachePtr->point), labelPtr->styles[i], layerPtr->scalefactor);
+                        else if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
+                           msDrawShadeSymbol(&map->symbolset, image, labelPtr->annopoly, labelPtr->styles[i], layerPtr->scalefactor);
+                        } else {
+                           /* TODO: need error msg about unsupported geomtransform */
+                           return MS_FAILURE;
+                        }
+                     }
+                  }
+                  msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */
                }
+
+               /*
+               styleObj tstyle;
+               static int foo =0;
+               if(!foo) {
+                  srand(time(NULL));
+                  foo = 1;
+                  initStyle(&tstyle);
+                  tstyle.width = 1;
+                  tstyle.color.alpha = 255;
+               }
+               tstyle.color.red = random()%255;
+               tstyle.color.green = random()%255;
+               tstyle.color.blue =random()%255;
+               msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor);
+               */
+            } else {
+               msFree(cachePtr->leaderline->point);
+               msFree(cachePtr->leaderline);
+               msFree(cachePtr->leaderbbox);
+               cachePtr->leaderline = NULL;
             }
             msFreeShape(&origPoly);
          }
@@ -2486,9 +2658,9 @@
             /* compare against image bounds, rendered labels and markers (sets cachePtr->status), if FORCE=TRUE then skip it */
             cachePtr->status = MS_TRUE;
             if(!labelPtr->force)
-              msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));             
+              cachePtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));             
 
-	    if(!cachePtr->status)
+            if(!cachePtr->status)
               continue;
 
             msDrawTextLine(image, labelPtr->annotext, labelPtr, cachePtr->labelpath, &(map->fontset), layerPtr->scalefactor); /* Draw the curved label */
@@ -2496,7 +2668,7 @@
           } else { /* point-based label */
             int drawLabelText=MS_TRUE; // unused
             shapeObj *poly=NULL; /* hold label polygon for one label, cachePtr->poly holds label polygon for the whole group */
-
+            shapeObj *tmppoly;
             poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj));
             msInitShape(poly);
 
@@ -2528,14 +2700,16 @@
             /* 
 	    ** all other cases *could* have multiple labels defined 
             */
-            cachePtr->status = MS_FALSE; /* assume this cache element *can't* be placed */
-
+            cachePtr->status = MS_OFF; /* assume this cache element *can't* be placed */
             for(ll=0; ll<cachePtr->numlabels; ll++) { /* RFC 77 TODO: Still may want to step through backwards... */
               msFreeShape(poly);
               labelPtr = &(cachePtr->labels[ll]);
+              labelPtr->status = MS_OFF;
 
-              if(!labelPtr->annotext || strlen(labelPtr->annotext) == 0) continue; /* skip this label (RFC 77 TODO: ok to bail here?) */
-
+              if(!labelPtr->annotext || strlen(labelPtr->annotext) == 0) {
+                 labelPtr->status = MS_ON; /* TODO TBT, check for marker only */
+                 continue; /* skip this label (RFC 77 TODO: ok to bail here?) */
+              }
               /* compute label size */
               if(labelPtr->type == MS_TRUETYPE) {
                 size = labelPtr->size * layerPtr->scalefactor;
@@ -2585,7 +2759,7 @@
                       return MS_FAILURE;
                     break; 
                   }
-		}
+                }
                 
                 for(i=0; i<labelPtr->numstyles; i++) { 
                   if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
@@ -2597,7 +2771,7 @@
                     labelPtr->annopoly->line->point =  (pointObj *) malloc(5*sizeof(pointObj));
                     labelPtr->annopoly->line->numpoints = 5;
                     break;
-		  }
+                  }
                 }
 
                 label_marker_offset_x = MS_NINT(label_marker_width/2.0); 
@@ -2607,8 +2781,8 @@
                 label_marker_rect.miny = MS_NINT(cachePtr->point.y - .5 * label_marker_height) - labelPtr->buffer; 
                 label_marker_rect.maxx = MS_NINT(cachePtr->point.x + .5 * label_marker_width) + labelPtr->buffer; // marker_rect.minx + (marker_width-1) + labelPtr->buffer; 
                 label_marker_rect.maxy = MS_NINT(cachePtr->point.y + .5 * label_marker_height) + labelPtr->buffer; // marker_rect.miny + (marker_height-1) + labelPtr->buffer; 
-	      }
-
+              }
+              
               if(drawLabelText && labelPtr->position == MS_AUTO) {
                 int positions[MS_POSITIONS_LENGTH], npositions=0;
    
@@ -2634,40 +2808,44 @@
                   // RFC 77 TODO: take label_marker_offset_x/y into account
                   labelPtr->annopoint = get_metrics(&(cachePtr->point), positions[i], r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, label_buffer, poly);
 
-                  if(labelPtr->force != MS_LABEL_FORCE_GROUP) {
-                     /* check for collisions inside the label group unless the label is FORCE GROUP */
+                  if(labelPtr->force == MS_OFF) {
+                     /* check for collisions inside the label group */
 
                      /* if cachePtr->status we're still working on the first valid label with a valid status value */
                      /* was: if((ll != 0) && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) */
-                     if(cachePtr->status != MS_FALSE && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {                  
+                     if(ll && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {                  
+                        /* there was a self intersection, remove the label bbox added by get_metrics ? */
                         msShapeDeleteLine(poly, poly->numlines-1);
-                        cachePtr->status = MS_FALSE;
-                        continue; /* next position */
+                        msComputeBounds(poly);
+                        continue; /* next position, labelPtr->status is left to MS_OFF */
                      }
                   }
 
-                  msCopyShape(poly, cachePtr->poly); // RFC 77 - HMMM, this isn't right (need to save existing cache->poly value in case there's a collision)...
-                  msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));
+                  tmppoly = cachePtr->poly;
+                  cachePtr->poly = poly;
+                  labelPtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));
+                  cachePtr->poly = tmppoly;
 
                   /* found a suitable place for this label */
-                  if(cachePtr->status) {
+                  if(labelPtr->status) {
                     if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), positions[i], r, (marker_offset_x + label_offset_x), (marker_offset_y + label_offset_y), labelPtr->angle, 1, labelPtr->annopoly->line);
                     break; /* ...out of position loop */
-                  } else { 
-                    /* reset some things */ 
-                    msShapeDeleteLine(cachePtr->poly, cachePtr->poly->numlines-1);
-                    if(poly->numlines == 2) msShapeDeleteLine(cachePtr->poly, cachePtr->poly->numlines-1); /* marker too */
+                  } else {
+                    /* reset some things */
+                    /* TB->SDL: this block seemed wrong, shouldn't the marker be deleted only once *all* auto positions have been tested? */
+
+                    /* there was a collision with a previous label, remove current label bbox before trying another position */
                     msShapeDeleteLine(poly, poly->numlines-1);
+                    msComputeBounds(poly);
                   }
                 } /* next position */
 
-                if(!cachePtr->status && labelPtr->force == MS_TRUE) {                 
+                if(!labelPtr->status && labelPtr->force == MS_TRUE) {                 
                   if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), positions[npositions-1], r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, 1, labelPtr->annopoly->line);
-                  cachePtr->status = MS_TRUE; /* draw in spite of collisions based on last position, need a *best* position */
+                  labelPtr->status = MS_TRUE; /* draw in spite of collisions based on last position, need a *best* position */
                 }
 
               } else { /* explicit position */
-                msFreeShape(poly);
 
                 if(labelPtr->position == MS_CC) { /* don't need the marker_offset */
                   labelPtr->annopoint = get_metrics(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, label_buffer, poly);
@@ -2682,30 +2860,47 @@
 
                 if(labelPtr->force == MS_TRUE) {
                   msCopyShape(poly, cachePtr->poly);
-                  cachePtr->status = MS_TRUE;
+                  labelPtr->status = MS_TRUE;
                 } else {
-                   if(labelPtr->force != MS_LABEL_FORCE_GROUP) {
-                     /* check for collisions inside the label group unless the label is FORCE GROUP */
+                  if(labelPtr->force == MS_OFF) {
+                    /* check for collisions inside the label group unless the label is FORCE GROUP */
 
-                      /* if cachePtr->status we're still working on the first valid label with a valid status value */
-                      if(cachePtr->status != MS_FALSE && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {
-                         cachePtr->status = MS_FALSE;
-                         break; /* collision within the group, done... */
-                      }
-                   }
-                  msCopyShape(poly, cachePtr->poly);
-                  msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));                  
+                    /* if cachePtr->status we're still working on the first valid label with a valid status value */
+                    if(ll && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {
+                      break; /* collision within the group */
+                    }
+                  }
+                  tmppoly = cachePtr->poly;
+                  cachePtr->poly = poly;
+                  /* TODO: in case we have leader lines and multiple labels, there's no use in testing for labelcache collisions
+                   * once a first collision has been found. we only need to know that the label group has collided, and the 
+                   * poly of the whole label group: if(label_group) testLabelCacheCollisions */
+                  labelPtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));
+                  cachePtr->poly = tmppoly;
                 }
-              } /* end else */
+              } /* end POSITION AUTO vs Fixed POSITION */
 
-              if(!cachePtr->status && classPtr->leader.maxdistance == 0) {
+              if(!labelPtr->status && classPtr->leader.maxdistance == 0) {
                 break; /* no point looking at more labels, unless their is a leader defined, in which
-                case we want to compute the full cachePt->poly to be used for offset tests */
+                case we still want to compute the full cachePtr->poly to be used for offset tests */
+              } else {
+                msCopyShape(poly, cachePtr->poly);
               }
             } /* next label in the group */
-   
-            if(!cachePtr->status)
-              continue; /* next label */
+            
+            /*
+             * with multiple labels and leader lines, cachePtr->status can be set back to ON if the last label
+             * didn't collide. we set it back to OFF in that case so it can become a candidate for leader offsetting
+             */
+            cachePtr->status = MS_ON;
+            for(ll=0;ll<cachePtr->numlabels; ll++) {
+               if(cachePtr->labels[ll].status == MS_OFF) {
+                  cachePtr->status = MS_OFF;
+                  break;
+               }
+            }
+            if(cachePtr->status == MS_OFF)
+               continue; /* next label, as we had a collision */
 
             if(layerPtr->type == MS_LAYER_ANNOTATION && cachePtr->numstyles > 0) { /* need to draw a marker */
               for(i=0; i<cachePtr->numstyles; i++)
@@ -2731,25 +2926,28 @@
    
               msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */
             }
+
+            /*
             styleObj tstyle;
-            initStyle(&tstyle);
             static int foo =0;
             if(!foo) {
-            srand(time(NULL));
-            foo = 1;
+               srand(time(NULL));
+               foo = 1;
+               initStyle(&tstyle);
+               tstyle.width = 1;
+               tstyle.color.alpha = 255;
             }
-            tstyle.width = 1;
             tstyle.color.red = random()%255;
             tstyle.color.green = random()%255;
             tstyle.color.blue =random()%255;
-            tstyle.color.alpha = 255;
             msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor);
+            */
 
             msFreeShape(poly); /* clean up label polygon */
             msFree(poly);
           } /* end else */
         } /* next label(group) from cacheslot */
-        //msDrawOffsettedLabels(image, map, priority);
+        msDrawOffsettedLabels(image, map, priority);
       } /* next priority */
 
       return MS_SUCCESS; /* necessary? */

Modified: sandbox/tb-labels/mapfile.c
===================================================================
--- sandbox/tb-labels/mapfile.c	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/mapfile.c	2012-02-23 19:03:13 UTC (rev 13169)
@@ -1675,6 +1675,14 @@
   return;
 }
 
+static int freeLabelLeader(labelLeaderObj *leader) {
+   int i;
+   for(i=0;i<leader->numstyles;i++) {
+      msFree(leader->styles[i]);
+   }
+
+   return MS_SUCCESS;
+}
 static int freeLabel(labelObj *label)
 {
   int i;
@@ -1704,6 +1712,8 @@
     msFree(label->annopoly);
   }
 
+  freeLabelLeader(&(label->leader));
+
   return MS_SUCCESS;
 }
 
@@ -3048,6 +3058,7 @@
   msFree(class->labels);
 
   msFree(class->keyimage);
+  freeLabelLeader(&(class->leader));
 
   return MS_SUCCESS;
 }

Modified: sandbox/tb-labels/maplabel.c
===================================================================
--- sandbox/tb-labels/maplabel.c	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/maplabel.c	2012-02-23 19:03:13 UTC (rev 13169)
@@ -365,6 +365,8 @@
   cachePtr->point.x = MS_NINT(cachePtr->point.x);
   cachePtr->point.y = MS_NINT(cachePtr->point.y);
   cachePtr->labelpath = NULL;
+  cachePtr->leaderline = NULL;
+  cachePtr->leaderbbox = NULL;
 
   // cachePtr->text = msStrdup(string); /* the actual text */
 
@@ -527,6 +529,8 @@
 
   cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */
   cachePtr->classindex = classindex;
+  cachePtr->leaderline = NULL;
+  cachePtr->leaderbbox = NULL;
 
   if(shape) {
     cachePtr->tileindex = shape->tileindex;
@@ -658,7 +662,7 @@
 **
 ** This function is used by the various msDrawLabelCacheXX() implementations.
 */
-void msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, 
+int msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, 
                                 int mapwidth, int mapheight, int buffer,
                                 labelCacheMemberObj *cachePtr, int current_priority, 
                                 int current_label, int mindistance, double label_size)
@@ -666,15 +670,12 @@
   int i, p;
   labelCacheMemberObj *curCachePtr=NULL; 
 
-  cachePtr->status = MS_TRUE; /* by default */
-
   /* Check against image bounds first 
   ** Pass mapwidth=-1 to skip this test
    */
   if(!labelPtr->partials && mapwidth > 0 && mapheight > 0) {
     if(labelInImage(mapwidth, mapheight, cachePtr->poly, buffer) == MS_FALSE) {
-      cachePtr->status = MS_FALSE;
-      return;
+      return MS_FALSE;
     }
   }
 
@@ -688,8 +689,7 @@
     for ( i = 0; i < markerslot->nummarkers; i++ ) {
       if ( !(p == current_priority && (current_label == markerslot->markers[i].id || -current_label == markerslot->markers[i].id) ) ) {  /* labels can overlap their own marker */
         if ( intersectLabelPolygons(markerslot->markers[i].poly, cachePtr->poly ) == MS_TRUE ) {
-          cachePtr->status = MS_FALSE;  /* polys intersect */
-          return;
+          return MS_FALSE;
         }
       }
     }
@@ -727,19 +727,33 @@
           (cachePtr->classindex == curCachePtr->classindex) && 
           (strcmp(cachePtr->labels[0].annotext, curCachePtr->labels[0].annotext) == 0) &&
           (msDistancePointToPoint(&(cachePtr->point), &(curCachePtr->point)) <= (mindistance + label_size))) { /* label is a duplicate */
-          cachePtr->status = MS_FALSE;
-          return;
+          return MS_FALSE;
         }
 
         if(intersectLabelPolygons(curCachePtr->poly, cachePtr->poly) == MS_TRUE) { /* polys intersect */
-          cachePtr->status = MS_FALSE;
-          return;
+          return MS_FALSE;
         }
+        if(curCachePtr->leaderline) {
+           /* our poly against rendered leader lines */
+           /* first do a bbox check */
+           if(msRectOverlap(curCachePtr->leaderbbox, &(cachePtr->poly->bounds))) {
+              return MS_FALSE;
+           }
+
+        }
+        if(cachePtr->leaderline) {
+           /* does our leader intersect current label */
+           /* first do a bbox check */
+           if(msRectOverlap(cachePtr->leaderbbox, &(curCachePtr->poly->bounds))) {
+              return MS_FALSE;
+           }
+        }
       }
     } /* i */
 
     i = 0; /* Start over with 1st label of next slot */
   } /* p */
+  return MS_TRUE;
 }
 
 /* msGetLabelCacheMember()
@@ -1235,7 +1249,6 @@
   /* STEP 0: check bounding boxes */
   if(!msRectOverlap(&p1->bounds, &p2->bounds)) /* from alans at wunderground.com */
   {
-     msDebug("reject 1 %d %d\n",p1,p2);
     return(MS_FALSE);
   }
 
@@ -1246,7 +1259,6 @@
 	for(v2=1; v2<p2->line[c2].numpoints; v2++)
 	  if(msIntersectSegments(&(p1->line[c1].point[v1-1]), &(p1->line[c1].point[v1]), &(p2->line[c2].point[v2-1]), &(p2->line[c2].point[v2])) ==  MS_TRUE)
      {
-     msDebug("reject 2 %d %d/n",p1,p2);
         return(MS_TRUE);
      }
 

Modified: sandbox/tb-labels/mapprimitive.c
===================================================================
--- sandbox/tb-labels/mapprimitive.c	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/mapprimitive.c	2012-02-23 19:03:13 UTC (rev 13169)
@@ -115,19 +115,27 @@
 }
 
 int msCopyShape(shapeObj *from, shapeObj *to) {
-  int i;
+  int i,copybounds=0;
 
   if(!from || !to) return(-1);
 
+  if(to->numlines <= 0) copybounds=1;
   for(i=0; i<from->numlines; i++)
     msAddLine(to, &(from->line[i])); /* copy each line */
 
   to->type = from->type;
 
-  to->bounds.minx = MS_MIN(to->bounds.minx,from->bounds.minx);
-  to->bounds.miny = MS_MIN(to->bounds.miny,from->bounds.miny);
-  to->bounds.maxx = MS_MAX(to->bounds.maxx,from->bounds.maxx);
-  to->bounds.maxy = MS_MAX(to->bounds.maxy,from->bounds.maxy);
+  if(copybounds) {
+     to->bounds.minx = from->bounds.minx;
+     to->bounds.miny = from->bounds.miny;
+     to->bounds.maxx = from->bounds.maxx;
+     to->bounds.maxy = from->bounds.maxy;
+  } else {
+     to->bounds.minx = MS_MIN(to->bounds.minx,from->bounds.minx);
+     to->bounds.miny = MS_MIN(to->bounds.miny,from->bounds.miny);
+     to->bounds.maxx = MS_MAX(to->bounds.maxx,from->bounds.maxx);
+     to->bounds.maxy = MS_MAX(to->bounds.maxy,from->bounds.maxy);
+  }
 
   if(from->text) to->text = msStrdup(from->text);
 

Modified: sandbox/tb-labels/mapprimitive.h
===================================================================
--- sandbox/tb-labels/mapprimitive.h	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/mapprimitive.h	2012-02-23 19:03:13 UTC (rev 13169)
@@ -86,6 +86,7 @@
   long index;
   int tileindex;
   int classindex;
+  char **texts;
   char *text;
   
   int scratch;

Modified: sandbox/tb-labels/mapserver.h
===================================================================
--- sandbox/tb-labels/mapserver.h	2012-02-23 13:58:25 UTC (rev 13168)
+++ sandbox/tb-labels/mapserver.h	2012-02-23 19:03:13 UTC (rev 13169)
@@ -1107,7 +1107,7 @@
   int shapetype; /* source geometry type */
 
   pointObj point; /* label point */
-  shapeObj *poly; /* label bounding box */
+  shapeObj *poly; /* label bounding box, accumulation of individual label's bounding boxes */
 
   int status; /* has this label been drawn or not */
 
@@ -1116,6 +1116,8 @@
 #endif /* SWIG */
 
   int markerid; /* corresponding marker (POINT layers only) */
+  lineObj *leaderline;
+  rectObj *leaderbbox;
 } labelCacheMemberObj;
 
 /************************************************************************/
@@ -2034,7 +2036,7 @@
 
 MS_DLL_EXPORT int msAddLabel(mapObj *map, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, double featuresize);
 MS_DLL_EXPORT int msAddLabelGroup(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize);
-MS_DLL_EXPORT void msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, int mapwidth, int mapheight, int buffer, labelCacheMemberObj *cachePtr, int current_priority, int current_label, int mindistance, double label_size);
+MS_DLL_EXPORT int __attribute__((warn_unused_result)) msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, int mapwidth, int mapheight, int buffer, labelCacheMemberObj *cachePtr, int current_priority, int current_label, int mindistance, double label_size);
 MS_DLL_EXPORT labelCacheMemberObj *msGetLabelCacheMember(labelCacheObj *labelcache, int i);
 
 MS_DLL_EXPORT gdFontPtr msGetBitmapFont(int size);



More information about the mapserver-commits mailing list