[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