TrueType line symbol rotation

Jim Klassen Jim.Klassen at CI.STPAUL.MN.US
Tue Jul 10 12:11:20 EDT 2007


I am working on a project to display a sewer system with CGI Mapserver.
One of the goals of the project is to display the direction of sewer
flow based on the map. This information is encoded in the by the
ordering of the endpoints of the lines which represent the sewer system.
We are doing this by using a TrueType symbol (right now the '^') to
point in the direction of the flow overlaid on the line.

The problem I am having is sometimes the '^' point the correct direction
and sometimes they are 180 degrees off. I have checked the data and the
ordering of the endpoints is correct in the dataset and up to and
including in the shape pointer that is passed to
msImageTruetypePolyline() in maplabel.c. It appears that theta is not
being calculated in msImageTruetypePolyline() in the way I would expect.
I don't fully understand what the existing code is doing, in particular,
I don't understand the implications of changing the position variable.

I have commented out the block I don't understand and replaced it with
the three lines labeled ADDED and the code now functions as I would
expect, but again I don't know the implications of not messing with the
position variable. I have also added a bunch of fprintf's to see what
was going on.

Is there a better approach to showing the direction associated with the
lines?
Are there more places in the code that I should change to get the
desired (by me) behavior?

Mapserver 4.10.0, 4.10.2 and SVN r6263 (from July 5th) all behave the
same way.

=== mapfile fragment

SYMBOL
  NAME "carret"
  TYPE truetype
  FONT 'arial-bold'
  CHARACTER ">"
      GAP 50
END
LAYER
    DATA 'sewer_lines'
    STATUS DEFAULT
    TYPE LINE
    CLASS
      STYLE
        SIZE 15
        SYMBOL "carret"
        COLOR 60 60 60
      END
    END
END

==== maplabel.c fragment from SVN as modified

  
  if(msGetLabelSize(symbol->character, &label, &label_rect,
symbolset->fontset, scalefactor, MS_FALSE) == -1)
    return(-1);

  label_width = (int) label_rect.maxx - (int) label_rect.minx;

fprintf(stderr, "Line: ");
  for(i=0; i<p->numlines; i++) {
    current_length = gap+label_width/2.0; /* initial padding for each
line */
fprintf(stderr, " S%d ", i);
    for(j=1;j<p->line[i].numpoints;j++) {
fprintf(stderr, " %f,%f-%f,%f ", p->line[i].point[j-1].x,
p->line[i].point[j-1].y,p->line[i].point[j].x, p->line[i].point[j].y);
      length = sqrt((pow((p->line[i].point[j].x -
p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y -
p->line[i].point[j-1].y),2)));
      if(length==0)continue;
      rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length;
      ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length;
      position = symbol->position;
      theta = asin(ry);
/*      if(rx < 0) {
        if(rot){
          theta += MS_PI;
                if((position == MS_UR)||(position == MS_UL)) position =
MS_LC;
          if((position == MS_LR)||(position == MS_LL)) position = MS_UC;
        }else{
          if(position == MS_UC) position = MS_LC;
          else if(position == MS_LC) position = MS_UC;
        }
      }
      else theta = -theta; */
      if( rx < 0 && ry > 0) theta = MS_PI - theta; /* Quadrant II
transform */
      else if(rx < 0 && ry < 0) theta = -MS_PI - theta; /* Quandant III
transform */
      theta = -theta; /* image space y coords are the reverse of graph
space */    
fprintf(stderr, " rx: %f ry: %f length: %f theta: %f ", rx, ry, length,
theta * MS_RAD_TO_DEG);

      if((position == MS_UR)||(position == MS_UL)) position = MS_UC;
 
=== Before output

Line:  S0  450.000000,640.000000-448.000000,286.000000  rx: -0.005650
ry: -0.999984 length: 354.005650 theta: -89.676298 
Line:  S0  895.000000,280.000000-448.000000,286.000000  rx: -0.999910
ry: 0.013422 length: 447.040267 theta: 0.769025 
Line:  S0  -1.000000,288.000000-448.000000,286.000000  rx: 0.999990 ry:
-0.004454 length: 449.004454 theta: 0.255213 
Line:  S0  448.000000,286.000000-448.000000,205.000000  rx: 0.000000 ry:
-1.000000 length: 81.000000 theta: 90.000000 

=== After output (as expected)

Line:  S0  450.000000,640.000000-448.000000,286.000000  rx: -0.005650
ry: -0.999984 length: 354.005650 theta: 90.323702 
Line:  S0  895.000000,280.000000-448.000000,286.000000  rx: -0.999910
ry: 0.013422 length: 447.040267 theta: -179.230975 
Line:  S0  -1.000000,288.000000-448.000000,286.000000  rx: 0.999990 ry:
-0.004454 length: 449.004454 theta: 0.255213 
Line:  S0  448.000000,286.000000-448.000000,205.000000  rx: 0.000000 ry:
-1.000000 length: 81.000000 theta: 90.000000 




Jim Klassen
City of Saint Paul
Office of Technology and Communications/Public Works
(651) 266-6098



More information about the mapserver-dev mailing list