[mapserver-commits] r9121 - sandbox/aboudreault

svn at osgeo.org svn at osgeo.org
Thu Jun 25 15:51:31 EDT 2009


Author: aboudreault
Date: 2009-06-25 15:51:30 -0400 (Thu, 25 Jun 2009)
New Revision: 9121

Modified:
   sandbox/aboudreault/mapprimitive.c
Log:
applied the modified labels placement algorithm to labelpaths placement, in aboudreault sandbox

Modified: sandbox/aboudreault/mapprimitive.c
===================================================================
--- sandbox/aboudreault/mapprimitive.c	2009-06-25 18:52:24 UTC (rev 9120)
+++ sandbox/aboudreault/mapprimitive.c	2009-06-25 19:51:30 UTC (rev 9121)
@@ -1496,7 +1496,7 @@
       
       point_position = left_point_position;
       n++;
-    } while (n<2); // we place 2 labels at time
+    } while (n<2); // we place the right point then the left point.
 
     right_point_position -= point_distance;
     left_point_position += point_distance;
@@ -1564,10 +1564,10 @@
 {
   double distance_along_segment;
   double segment_length, fwd_line_length, rev_line_length, text_length, text_start_length, label_buffer, text_end_length;
-
+  double right_label_position, left_label_position, center_label_position;
   int numchars;
   
-  int i,j,k,l, inc, final_j, label_repeat;
+  int i,j,k,l,n, inc, final_j, label_repeat;
   double direction;
   rectObj bbox;
   lineObj bounds;
@@ -1647,283 +1647,311 @@
 
   // We compute the number of labels we can repeat in the line
   text_end_length = 0;
+  left_label_position = right_label_position = center_label_position = (line_length - text_length) / 2.0;
   label_repeat = (line_length / (text_length + label->repeatdistance));
   label_buffer = (line_length / label_repeat); // buffer allowed per label 
-  if (label->repeatdistance > 0 && label_repeat > 1)
-    text_start_length = (label_buffer / 2) - (text_length / 2);
+  if (label->repeatdistance > 0 && label_repeat > 1) {
+    if (label_repeat % 2 == 0) {
+        label_repeat -= 1;
+        label_buffer = (line_length / label_repeat);  
+    }
+//    text_start_length = (label_buffer / 2) - (text_length / 2);
+
+    // initial point position
+    left_label_position -= ((label_repeat-1)/2 * label_buffer);
+    right_label_position += ((label_repeat-1)/2 * label_buffer);
+    
+    label_repeat = (label_repeat-1)/2+1;
+  }
   else
   {
     label_repeat = 1;
-    text_start_length = (line_length - text_length) / 2.0;
+    center_label_position = (line_length - text_length) / 2.0;
   }
-  
+
   for (l=0; l < label_repeat; l++)
   {
-    /* allocate the labelpath */
-    labelpath = (labelPathObj *) malloc(sizeof(labelPathObj));
-    labelpath->path.numpoints = numchars;
-    labelpath->path.point = (pointObj *) calloc(labelpath->path.numpoints, sizeof(pointObj));
-    labelpath->angles = (double *) malloc(sizeof(double) * (labelpath->path.numpoints));
-    msInitShape(&(labelpath->bounds));
+    if (l == label_repeat-1) { // last label to place is always the center label
+      text_start_length = center_label_position;
+      n = 1;
+    } 
+    else {
+      text_start_length = right_label_position;
+      n = 0;
+    }
+
+    do {
+        /* allocate the labelpath */
+        labelpath = (labelPathObj *) malloc(sizeof(labelPathObj));
+        labelpath->path.numpoints = numchars;
+        labelpath->path.point = (pointObj *) calloc(labelpath->path.numpoints, sizeof(pointObj));
+        labelpath->angles = (double *) malloc(sizeof(double) * (labelpath->path.numpoints));
+        msInitShape(&(labelpath->bounds));
     
 
-    /*     
-    ** The bounds will have two points for each character plus an endpoint:
-    ** the UL corners of each bbox will be tied together and the LL corners
-    ** will be tied together.
-    */
-    bounds.numpoints = 2*numchars + 1;
-    bounds.point = (pointObj *) malloc(sizeof(pointObj) * bounds.numpoints);
+        /*     
+        ** The bounds will have two points for each character plus an endpoint:
+        ** the UL corners of each bbox will be tied together and the LL corners
+        ** will be tied together.
+        */
+        bounds.numpoints = 2*numchars + 1;
+        bounds.point = (pointObj *) malloc(sizeof(pointObj) * bounds.numpoints);
 
-    /* the points start at (line_length - text_length) / 2 in order to be centred */
-//  text_start_length = (line_length - text_length) / 2.0;
+        /* the points start at (line_length - text_length) / 2 in order to be centred */
+        //  text_start_length = (line_length - text_length) / 2.0;
 
-    /* the text is longer than the line: extrapolate the first and last segments */
-    if(text_start_length < 0.0) {    
-      j = 0;
-      final_j = p->line[i].numpoints - 1;
-      fwd_line_length = rev_line_length = 0;
-    } else {
-      /* proceed until we've traversed text_start_length in distance */
-      fwd_line_length = 0;
-      j = 0;
-      while ( fwd_line_length < text_start_length )
-        fwd_line_length += segment_lengths[i][j++];
+        /* the text is longer than the line: extrapolate the first and last segments */
+        if(text_start_length < 0.0) {    
+            j = 0;
+            final_j = p->line[i].numpoints - 1;
+            fwd_line_length = rev_line_length = 0;
+        } else {
+            /* proceed until we've traversed text_start_length in distance */
+            fwd_line_length = 0;
+            j = 0;
+            while ( fwd_line_length < text_start_length )
+                fwd_line_length += segment_lengths[i][j++];
 
-      j--;
+            j--;
 
-      /* determine the last segment */ 
-      rev_line_length = 0;
-      final_j = p->line[i].numpoints - 1;
+            /* determine the last segment */ 
+            rev_line_length = 0;
+            final_j = p->line[i].numpoints - 1;
 
-      text_end_length = line_length - (text_start_length + text_length);
-      while(rev_line_length < text_end_length) {
-        rev_line_length += segment_lengths[i][final_j - 1];
-        final_j--;
-      }
-      final_j++;
-    }
+            text_end_length = line_length - (text_start_length + text_length);
+            while(rev_line_length < text_end_length) {
+                rev_line_length += segment_lengths[i][final_j - 1];
+                final_j--;
+            }
+            final_j++;
+        }
 
-    if(final_j == 0)
-      final_j = 1;
+        if(final_j == 0)
+            final_j = 1;
   
-    /* determine if the line is mostly left to right or right to left, 
-       see bug 1620 discussion by Steve Woodbridge */
-    direction = 0;
-    k = j;
-    while (k < final_j) {
-      direction += p->line[i].point[k+1].x - p->line[i].point[k].x;
-      k++;
-    }
+        /* determine if the line is mostly left to right or right to left, 
+           see bug 1620 discussion by Steve Woodbridge */
+        direction = 0;
+        k = j;
+        while (k < final_j) {
+            direction += p->line[i].point[k+1].x - p->line[i].point[k].x;
+            k++;
+        }
 
-    if(direction > 0) {    
-      inc = 1; /* j is already correct */
+        if(direction > 0) {    
+            inc = 1; /* j is already correct */
 
-      /* length of the segment containing the starting point */
-      segment_length = segment_lengths[i][j];
+            /* length of the segment containing the starting point */
+            segment_length = segment_lengths[i][j];
 
-      /* determine how far along the segment we need to go */
-      t = 1 - (fwd_line_length - text_start_length) / segment_length;
-    } else {
-      j = final_j;
-      inc = -1;
+            /* determine how far along the segment we need to go */
+            t = 1 - (fwd_line_length - text_start_length) / segment_length;
+        } else {
+            j = final_j;
+            inc = -1;
       
-      /* length of the segment containing the starting point */
-      segment_length = segment_lengths[i][j-1];
-      t = 1 - (rev_line_length - text_end_length) / segment_length;    
-    }
+            /* length of the segment containing the starting point */
+            segment_length = segment_lengths[i][j-1];
+            t = 1 - (rev_line_length - text_end_length) / segment_length;    
+        }
     
-    distance_along_segment = t * segment_length; /* starting point */
+        distance_along_segment = t * segment_length; /* starting point */
   
-    theta = 0;
-    k = 0;
-    w = 0;
-    while ( k < labelpath->path.numpoints ) {
-      int m;
-      double x,y;
+        theta = 0;
+        k = 0;
+        w = 0;
+        while ( k < labelpath->path.numpoints ) {
+            int m;
+            double x,y;
       
-      x = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x;
-      y = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y;
+            x = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x;
+            y = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y;
 
-      /* 
-      ** This used to be a series of if-then-else's, but that fails for short (length < 4)
-      ** labels. There may be small speed-ups possible here. (bug 1921)
-      **
-      ** average this label point with its neighbors according to the smoothing kernel
-      */
-      if ( k == 0) {
-        labelpath->path.point[k].x += (kernel[0] + kernel[1]) * x;
-        labelpath->path.point[k].y += (kernel[0] + kernel[1]) * y;
-      } 
-      if ( k == 1) {
-        labelpath->path.point[k].x += kernel[0] * x;
-        labelpath->path.point[k].y += kernel[0] * y;
-      } 
-      if ( k == labelpath->path.numpoints - 2) {
-        labelpath->path.point[k].x += kernel[4] * x;
-        labelpath->path.point[k].y += kernel[4] * y;      
-      } 
-      if ( k == labelpath->path.numpoints - 1) {
-        labelpath->path.point[k].x += (kernel[3] + kernel[4]) * x;
-        labelpath->path.point[k].y += (kernel[3] + kernel[4]) * y;
-      }
+            /* 
+            ** This used to be a series of if-then-else's, but that fails for short (length < 4)
+            ** labels. There may be small speed-ups possible here. (bug 1921)
+            **
+            ** average this label point with its neighbors according to the smoothing kernel
+            */
+            if ( k == 0) {
+                labelpath->path.point[k].x += (kernel[0] + kernel[1]) * x;
+                labelpath->path.point[k].y += (kernel[0] + kernel[1]) * y;
+            } 
+            if ( k == 1) {
+                labelpath->path.point[k].x += kernel[0] * x;
+                labelpath->path.point[k].y += kernel[0] * y;
+            } 
+            if ( k == labelpath->path.numpoints - 2) {
+                labelpath->path.point[k].x += kernel[4] * x;
+                labelpath->path.point[k].y += kernel[4] * y;      
+            } 
+            if ( k == labelpath->path.numpoints - 1) {
+                labelpath->path.point[k].x += (kernel[3] + kernel[4]) * x;
+                labelpath->path.point[k].y += (kernel[3] + kernel[4]) * y;
+            }
       
-      for(m = 0; m < kernel_size; m++) {
-        if(m + k - 2 < 0 || m + k - 2 > labelpath->path.numpoints - 1)
-          continue;
-        labelpath->path.point[k+m-2].x += kernel[m]*x;
-        labelpath->path.point[k+m-2].y += kernel[m]*y;
-      }
+            for(m = 0; m < kernel_size; m++) {
+                if(m + k - 2 < 0 || m + k - 2 > labelpath->path.numpoints - 1)
+                    continue;
+                labelpath->path.point[k+m-2].x += kernel[m]*x;
+                labelpath->path.point[k+m-2].y += kernel[m]*y;
+            }
     
-      w = letterspacing*offsets[k];
+            w = letterspacing*offsets[k];
     
-      /* add the character's width to the distance along the line */
-      distance_along_segment += w;
+            /* add the character's width to the distance along the line */
+            distance_along_segment += w;
 
-      /* if we still have segments left and we've past the current segment, move to the next one */    
-      if(inc == 1 && j < p->line[i].numpoints - 2) {      
+            /* if we still have segments left and we've past the current segment, move to the next one */    
+            if(inc == 1 && j < p->line[i].numpoints - 2) {      
 
-        while ( j < p->line[i].numpoints - 2 && distance_along_segment > segment_lengths[i][j] ) {
-          distance_along_segment -= segment_lengths[i][j];                
-          j += inc; /* move to next segment */
-        }
+                while ( j < p->line[i].numpoints - 2 && distance_along_segment > segment_lengths[i][j] ) {
+                    distance_along_segment -= segment_lengths[i][j];                
+                    j += inc; /* move to next segment */
+                }
 
-        segment_length = segment_lengths[i][j];
+                segment_length = segment_lengths[i][j];
             
-      } else if( inc == -1 && j > 1 ) {
+            } else if( inc == -1 && j > 1 ) {
 
-        while ( j > 1 && distance_along_segment > segment_lengths[i][j-1] ) {
-          distance_along_segment -= segment_lengths[i][j-1];
-          j += inc; /* move to next segment */
-        }
+                while ( j > 1 && distance_along_segment > segment_lengths[i][j-1] ) {
+                    distance_along_segment -= segment_lengths[i][j-1];
+                    j += inc; /* move to next segment */
+                }
       
-        segment_length = segment_lengths[i][j-1];
-      }
+                segment_length = segment_lengths[i][j-1];
+            }
     
-      /* Recalculate interpolation parameter */
-      t = distance_along_segment / segment_length;
+            /* Recalculate interpolation parameter */
+            t = distance_along_segment / segment_length;
     
-      k++;
-    }
+            k++;
+        }
   
-    /* pre-calc the character's centre y value.  Used for rotation adjustment. */
-    cy = -size / 2.0;
+        /* pre-calc the character's centre y value.  Used for rotation adjustment. */
+        cy = -size / 2.0;
 
-    labelpath->path.point[0].x /= kernel_normal;
-    labelpath->path.point[0].y /= kernel_normal;
+        labelpath->path.point[0].x /= kernel_normal;
+        labelpath->path.point[0].y /= kernel_normal;
   
-    /* Average the points and calculate each angle */
-    for (k = 1; k <= labelpath->path.numpoints; k++) {
+        /* Average the points and calculate each angle */
+        for (k = 1; k <= labelpath->path.numpoints; k++) {
 
-      if ( k < labelpath->path.numpoints ) {  
-        labelpath->path.point[k].x /= kernel_normal;
-        labelpath->path.point[k].y /= kernel_normal;
-        dx = labelpath->path.point[k].x - labelpath->path.point[k-1].x;
-        dy = labelpath->path.point[k].y - labelpath->path.point[k-1].y;
-      } else {
-        /* Handle the last character */
-        dx = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x - labelpath->path.point[k-1].x;
-        dy = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y - labelpath->path.point[k-1].y;
-      }
+            if ( k < labelpath->path.numpoints ) {  
+                labelpath->path.point[k].x /= kernel_normal;
+                labelpath->path.point[k].y /= kernel_normal;
+                dx = labelpath->path.point[k].x - labelpath->path.point[k-1].x;
+                dy = labelpath->path.point[k].y - labelpath->path.point[k-1].y;
+            } else {
+                /* Handle the last character */
+                dx = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x - labelpath->path.point[k-1].x;
+                dy = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y - labelpath->path.point[k-1].y;
+            }
 
-      theta = -atan2(dy,dx);
+            theta = -atan2(dy,dx);
 
-      /* If the difference between subsequent angles is > 80% of 180deg
-         bail because the line likely overlaps itself. */
+            /* If the difference between subsequent angles is > 80% of 180deg
+               bail because the line likely overlaps itself. */
    
-      if ( k > 2 && abs(theta - labelpath->angles[k-2]) > 0.4 * MS_PI ) {
-         goto LABEL_FAILURE;
-      }
+            if ( k > 2 && abs(theta - labelpath->angles[k-2]) > 0.4 * MS_PI ) {
+                goto LABEL_FAILURE;
+            }
       
-      /* msDebug("s: %c (x,y): (%0.2f,%0.2f) t: %0.2f\n", string[k-1], labelpath->path.point[k-1].x, labelpath->path.point[k-1].y, theta); */
+            /* msDebug("s: %c (x,y): (%0.2f,%0.2f) t: %0.2f\n", string[k-1], labelpath->path.point[k-1].x, labelpath->path.point[k-1].y, theta); */
 
-      labelpath->angles[k-1] = theta;
+            labelpath->angles[k-1] = theta;
   
-      /* Move the previous point so that when the character is rotated and
-         placed it is centred on the line */
-      cos_t = cos(theta);
-      sin_t = sin(theta);
+            /* Move the previous point so that when the character is rotated and
+               placed it is centred on the line */
+            cos_t = cos(theta);
+            sin_t = sin(theta);
   
-      w = letterspacing*offsets[k-1];
+            w = letterspacing*offsets[k-1];
 
-      cx = 0; /* Center the character vertically only */
+            cx = 0; /* Center the character vertically only */
 
-      dx = - (cx * cos_t + cy * sin_t);
-      dy = - (cy * cos_t - cx * sin_t);
+            dx = - (cx * cos_t + cy * sin_t);
+            dy = - (cy * cos_t - cx * sin_t);
   
-      labelpath->path.point[k-1].x += dx;
-      labelpath->path.point[k-1].y += dy;
+            labelpath->path.point[k-1].x += dx;
+            labelpath->path.point[k-1].y += dy;
 
-      /* Calculate the bounds */
-      bbox.minx = 0;
-      bbox.maxx = w;
-      bbox.maxy = 0;
-      bbox.miny = -size;
+            /* Calculate the bounds */
+            bbox.minx = 0;
+            bbox.maxx = w;
+            bbox.maxy = 0;
+            bbox.miny = -size;
 
-      /* Add the label buffer to the bounds */
-      bbox.maxx += label->buffer;
-      bbox.maxy += label->buffer;
-      bbox.minx -= label->buffer;
-      bbox.miny -= label->buffer;
+            /* Add the label buffer to the bounds */
+            bbox.maxx += label->buffer;
+            bbox.maxy += label->buffer;
+            bbox.minx -= label->buffer;
+            bbox.miny -= label->buffer;
   
-      if ( k < labelpath->path.numpoints ) {
-        /* Transform the bbox too.  We take the UL and LL corners and rotate
-           then translate them. */
-        bounds.point[k-1].x = (bbox.minx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x;
-        bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y;
+            if ( k < labelpath->path.numpoints ) {
+                /* Transform the bbox too.  We take the UL and LL corners and rotate
+                   then translate them. */
+                bounds.point[k-1].x = (bbox.minx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x;
+                bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y;
 
-        /* Start at end and work towards the half way point */
-        bounds.point[bounds.numpoints - k - 1].x = (bbox.minx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x;
-        bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y;
+                /* Start at end and work towards the half way point */
+                bounds.point[bounds.numpoints - k - 1].x = (bbox.minx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x;
+                bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y;
 
-      } else {
+            } else {
     
-        /* This is the last character in the string so we take the UR and LR
-           corners of the bbox */
-        bounds.point[k-1].x = (bbox.maxx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x;
-        bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y;
+                /* This is the last character in the string so we take the UR and LR
+                   corners of the bbox */
+                bounds.point[k-1].x = (bbox.maxx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x;
+                bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y;
   
-        bounds.point[bounds.numpoints - k - 1].x = (bbox.maxx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x;
-        bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y;
-      }
+                bounds.point[bounds.numpoints - k - 1].x = (bbox.maxx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x;
+                bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y;
+            }
 
-    }
+        }
 
-    /* Close the bounds */
-    bounds.point[bounds.numpoints - 1].x = bounds.point[0].x;
-    bounds.point[bounds.numpoints - 1].y = bounds.point[0].y;
+        /* Close the bounds */
+        bounds.point[bounds.numpoints - 1].x = bounds.point[0].x;
+        bounds.point[bounds.numpoints - 1].y = bounds.point[0].y;
   
-    /* Convert the bounds to a shape and store them in the labelpath */
-    if ( msAddLineDirectly(&(labelpath->bounds), &bounds) == MS_FAILURE ) {
-      goto LABEL_FAILURE;
-    }
+        /* Convert the bounds to a shape and store them in the labelpath */
+        if ( msAddLineDirectly(&(labelpath->bounds), &bounds) == MS_FAILURE ) {
+            goto LABEL_FAILURE;
+        }
 
-    msComputeBounds(&(labelpath->bounds));
+        msComputeBounds(&(labelpath->bounds));
       
-    goto LABEL_END;
+        goto LABEL_END;
     
-  LABEL_FAILURE:
+    LABEL_FAILURE:
 
-    if (bounds.point)
-      free(bounds.point);
-    bounds.point = NULL;
-    bounds.numpoints = 0;
+        if (bounds.point)
+            free(bounds.point);
+        bounds.point = NULL;
+        bounds.numpoints = 0;
 
-    if ( labelpath ) {
-      msFreeLabelPathObj(labelpath);
-      labelpath = NULL;
-    }
+        if ( labelpath ) {
+            msFreeLabelPathObj(labelpath);
+            labelpath = NULL;
+        }
     
-  LABEL_END:
-    if (labelpath) {
-      if (*labelpaths_index == *labelpaths_size) {
-        *labelpaths_size *= 2;
-        (*labelpaths) = (labelPathObj **) realloc(*labelpaths,sizeof(labelPathObj *) * (*labelpaths_size));
-      }
-      (*labelpaths)[(*labelpaths_index)++] = labelpath;
-    }
+    LABEL_END:
+        if (labelpath) {
+            if (*labelpaths_index == *labelpaths_size) {
+                *labelpaths_size *= 2;
+                (*labelpaths) = (labelPathObj **) realloc(*labelpaths,sizeof(labelPathObj *) * (*labelpaths_size));
+            }
+            (*labelpaths)[(*labelpaths_index)++] = labelpath;
+        }
     
-    text_start_length += label_buffer;
+        text_start_length = left_label_position;
+        n++;
+    } while (n<2);
+    
+    right_label_position -= label_buffer;
+    left_label_position += label_buffer;
+
   }
 
   goto END; // normal exit



More information about the mapserver-commits mailing list