[mapserver-commits] r9729 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Thu Jan 21 21:21:52 EST 2010


Author: assefa
Date: 2010-01-21 21:21:52 -0500 (Thu, 21 Jan 2010)
New Revision: 9729

Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/maptemplate.c
Log:
Add shplabel tag support in templates (#3241)

Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2010-01-21 23:30:12 UTC (rev 9728)
+++ trunk/mapserver/HISTORY.TXT	2010-01-22 02:21:52 UTC (rev 9729)
@@ -14,6 +14,8 @@
 Current Version (SVN trunk):
 ----------------------------
 
+- Add shplabel tag support in templates (#3241)
+
 - Bumped GEOS requirement to version 3.0+ (#3215)
 
 - Fixed memory leak related to templates (#2996)

Modified: trunk/mapserver/maptemplate.c
===================================================================
--- trunk/mapserver/maptemplate.c	2010-01-21 23:30:12 UTC (rev 9728)
+++ trunk/mapserver/maptemplate.c	2010-01-22 02:21:52 UTC (rev 9729)
@@ -871,6 +871,13 @@
     status = msLayerResultsGetShape(layer, &(mapserv->resultshape), layer->resultcache->results[i].tileindex, layer->resultcache->results[i].shapeindex);
     if(status != MS_SUCCESS) return status;
 
+    mapserv->resultshape.classindex = msShapeGetClass(layer, &mapserv->resultshape, 
+                                                      layer->map->scaledenom, NULL, -1);
+    if ( mapserv->resultshape.classindex>=0 &&
+         (layer->class[mapserv->resultshape.classindex]->text.string || layer->labelitem) && 
+         layer->class[mapserv->resultshape.classindex]->label.size != -1)
+      mapserv->resultshape.text = msShapeGetAnnotation(layer, & mapserv->resultshape);
+
     /* prepare any necessary JOINs here (one-to-one only) */
     if(layer->numjoins > 0) {
       for(j=0; j<layer->numjoins; j++) {
@@ -1430,6 +1437,339 @@
   return(MS_SUCCESS);
 }
 
+
+static int processShplabelTag(layerObj *layer, char **line, shapeObj *shape) 
+{
+    char *tag, *tagStart, *tagEnd;
+    char *tagValue=NULL;
+    hashTableObj *tagArgs=NULL;
+    int tagOffset, tagLength;
+    char *format;
+    char *argValue=NULL;
+    char *projectionString=NULL;
+    shapeObj tShape;
+    int precision=0;
+    int clip_to_map=MS_TRUE;
+    int use_label_settings=MS_FALSE;
+    double cellsize=0;
+    int labelposvalid = MS_FALSE;
+    pointObj labelPos;
+    int i,status;
+    char number[64]; /* holds a single number in the extent */
+    char numberFormat[16];
+
+    if(!*line) {
+    msSetError(MS_WEBERR, "Invalid line pointer.", "processShplabelTag()");
+    return(MS_FAILURE);
+    }
+    if( msCheckParentPointer(layer->map,"map")==MS_FAILURE )
+      return MS_FAILURE;
+  
+    tagStart = findTag(*line, "shplabel");
+
+    /* It is OK to have no shplabel tags, just return. */
+    if( !tagStart )
+      return MS_SUCCESS;
+
+    if(!shape || shape->numlines <= 0) { /* I suppose we need to make sure the part has vertices (need shape checker?) */
+      msSetError(MS_WEBERR, "Null or empty shape.", "processShplabelTag()");
+      return(MS_FAILURE);
+    }
+
+    while (tagStart) 
+    {
+        projectionString = NULL;
+        format = "$x,$y";
+        tagOffset = tagStart - *line;
+
+        if(getTagArgs("shplabel", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE);
+        if(tagArgs) 
+        {
+            argValue = msLookupHashTable(tagArgs, "format");
+            if(argValue) format = argValue;
+
+            argValue = msLookupHashTable(tagArgs, "precision");
+            if(argValue) precision = atoi(argValue);
+
+            argValue = msLookupHashTable(tagArgs, "proj");
+            if(argValue) projectionString = argValue;
+
+            argValue = msLookupHashTable(tagArgs, "clip_to_map");
+            if(argValue) 
+              if(strcasecmp(argValue,"false") == 0) clip_to_map = MS_FALSE;
+
+            argValue = msLookupHashTable(tagArgs, "use_label_settings");
+            if(argValue) 
+              if(strcasecmp(argValue,"true") == 0) use_label_settings = MS_TRUE;
+        }
+
+        msInitShape(&tShape);
+
+        tShape.type = MS_SHAPE_LINE;
+        tShape.line = (lineObj *) malloc(sizeof(lineObj));
+        tShape.numlines = 1;
+        tShape.line[0].point = NULL; /* initialize the line */
+        tShape.line[0].numpoints = 0;
+
+        if (layer->map->cellsize <= 0)
+        cellsize = MS_MAX(MS_CELLSIZE(layer->map->extent.minx, layer->map->extent.maxx, layer->map->width), 
+                          MS_CELLSIZE(layer->map->extent.miny, layer->map->extent.maxy, layer->map->height));
+        else
+          cellsize = layer->map->cellsize ;
+
+        if (shape->type == MS_SHAPE_POINT)
+        {
+            labelposvalid = MS_FALSE;
+            if (shape->numlines > 0 && shape->line[0].numpoints > 0)
+            {
+                labelposvalid = MS_TRUE;
+                labelPos = shape->line[0].point[0];
+                if(layer->transform == MS_TRUE) 
+                {
+                    if (layer->project && 
+                        msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+                      msProjectShape(&layer->projection, &layer->map->projection, shape);
+              
+                    labelPos = shape->line[0].point[0];
+                    labelPos.x = MS_MAP2IMAGE_X(labelPos.x, layer->map->extent.minx, cellsize);
+                    labelPos.y = MS_MAP2IMAGE_Y(labelPos.y, layer->map->extent.maxy, cellsize);
+                }
+            }
+          
+        }
+        else if (shape->type == MS_SHAPE_LINE)
+        {
+            pointObj     **annopoints = NULL;
+            double** angles = NULL, **lengths = NULL;
+            int numpoints = 1;
+
+            labelposvalid = MS_FALSE;
+            if(layer->transform == MS_TRUE) {
+                if (layer->project && 
+                    msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+                  msProjectShape(&layer->projection, &layer->map->projection, shape);
+                if (clip_to_map)
+                  msClipPolylineRect(shape, layer->map->extent);
+         
+
+                msTransformShapeToPixel(shape, layer->map->extent, cellsize);
+            }
+            else
+              msOffsetShapeRelativeTo(shape, layer);
+
+            if (shape->numlines > 0)
+            {
+                annopoints = msPolylineLabelPoint(shape, -1, 0, &angles, &lengths, &numpoints, MS_FALSE);
+                if (numpoints > 0)
+                {
+                    /*convert to geo*/
+                    labelPos.x = annopoints[0]->x;
+                    labelPos.y = annopoints[0]->y;
+                
+                    labelposvalid = MS_TRUE;
+                    for (i=0; i<numpoints; i++)
+                    {
+                        if (annopoints[i])
+                          msFree(annopoints[i]);
+                        if (angles[i])
+                          msFree(angles[i]);
+                        if (lengths[i])
+                          msFree(lengths[i]);
+                    }
+                    msFree(angles);
+                    msFree(annopoints);
+                    msFree(lengths);
+                }      
+            }
+        
+        }
+        else if (shape->type == MS_SHAPE_POLYGON)
+        {
+            labelposvalid = MS_FALSE;
+            if(layer->transform == MS_TRUE) 
+            {
+                if (layer->project && 
+                    msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+                  msProjectShape(&layer->projection, &layer->map->projection, shape);
+          
+                if (clip_to_map)
+                  msClipPolygonRect(shape, layer->map->extent);
+
+                msTransformShapeToPixel(shape, layer->map->extent, cellsize);
+            }
+            else
+              msOffsetShapeRelativeTo(shape, layer);
+
+            if (shape->numlines > 0)
+            {
+                labelposvalid = MS_TRUE;
+                msPolygonLabelPoint(shape, &labelPos, -1);
+            }
+        }
+        if (labelposvalid == MS_TRUE)
+        {
+            pointObj p1;
+            pointObj p2;
+            int label_offset_x, label_offset_y;
+            labelObj *label=NULL;
+            rectObj r;
+            shapeObj poly;
+            double tmp;
+
+            msInitShape(&poly);
+
+            p1.x =labelPos.x;
+            p1.y =labelPos.y; 
+
+            p2.x =labelPos.x;
+            p2.y =labelPos.y;  
+            if (use_label_settings == MS_TRUE)
+            {
+                if (shape->text && shape->classindex >=0)
+                {
+                    label = &layer->class[shape->classindex]->label;
+                    if(msGetLabelSize(NULL, shape->text, label, 
+                                      &r, &(layer->map->fontset), layer->scalefactor, MS_FALSE,NULL) != -1)
+                    {
+                        label_offset_x = (int)(label->offsetx*layer->scalefactor);
+                        label_offset_y = (int)(label->offsety*layer->scalefactor);
+
+                        p1 = get_metrics(&labelPos, label->position, r, label_offset_x, label_offset_y, 
+                                              label->angle, 0, &poly);
+                        /*should we use the point returned from  get_metrics?. From few test done, It seems
+                         to return the UL corner of the text. For now use the bounds.minx/miny*/
+
+                        p1.x = poly.bounds.minx;
+                        p1.y = poly.bounds.miny;
+                        p2.x = poly.bounds.maxx;
+                        p2.y = poly.bounds.maxy;
+                        
+                    }
+                }
+            }
+            /* y's are flipped because it is in image coordinate systems */
+            p1.x = MS_IMAGE2MAP_X(p1.x, layer->map->extent.minx, cellsize);
+            tmp = p1.y;
+            p1.y = MS_IMAGE2MAP_Y(p2.y, layer->map->extent.maxy, cellsize);
+            p2.x = MS_IMAGE2MAP_X(p2.x, layer->map->extent.minx, cellsize);
+            p2.y = MS_IMAGE2MAP_Y(tmp, layer->map->extent.maxy, cellsize);
+            if(layer->transform == MS_TRUE) {
+                if (layer->project && 
+                    msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+                {
+                    msProjectPoint(&layer->map->projection, &layer->projection, &p1);
+                    msProjectPoint(&layer->map->projection, &layer->projection, &p2);
+                }
+            }
+            msAddPointToLine(&(tShape.line[0]), &p1);
+            msAddPointToLine(&(tShape.line[0]), &p2);
+        }
+        else
+          tShape.numlines = 0;
+
+         if(projectionString && strcasecmp(projectionString,"image") == 0) {
+             precision = 0;
+
+             /* if necessary, project the shape to match the map */
+             if(msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+               msProjectShape(&layer->projection, &layer->map->projection, &tShape);
+      
+              msClipPolylineRect(&tShape, layer->map->extent);
+
+              msTransformShapeToPixel(&tShape, layer->map->extent, layer->map->cellsize);
+
+         } else if(projectionString) {
+             projectionObj projection;
+             msInitProjection(&projection);
+
+             status = msLoadProjectionString(&projection, projectionString);
+             if(status != MS_SUCCESS) return MS_FAILURE;
+
+             if(msProjectionsDiffer(&(layer->projection), &projection)) 
+               msProjectShape(&layer->projection, &projection, &tShape);
+         }
+         
+          
+
+          /* find the end of the tag */
+          tagEnd = findTagEnd(tagStart);
+          tagEnd++;
+
+          /* build the complete tag so we can do substitution */
+          tagLength = tagEnd - tagStart;
+          tag = (char *) malloc(tagLength + 1);
+          strncpy(tag, tagStart, tagLength);
+          tag[tagLength] = '\0';
+
+          /* do the replacement */
+          tagValue = strdup(format);
+          if(precision > 0)
+            snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision);
+          else
+            snprintf(numberFormat, sizeof(numberFormat), "%%f");
+
+          if (tShape.numlines > 0)
+          {
+              if(msCaseFindSubstring(tagValue, "$x") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x);
+                  tagValue = msReplaceSubstring(tagValue, "$x", number);
+              }
+              if(msCaseFindSubstring(tagValue, "$y") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y);
+                  tagValue = msReplaceSubstring(tagValue, "$y", number);
+              }
+          
+              if(msCaseFindSubstring(tagValue, "$minx") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x);
+                  tagValue = msReplaceSubstring(tagValue, "$minx", number);
+              }
+              if(msCaseFindSubstring(tagValue, "$miny") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y);
+                  tagValue = msReplaceSubstring(tagValue, "$miny", number);
+              }
+              if(msCaseFindSubstring(tagValue, "$maxx") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].x);
+                  tagValue = msReplaceSubstring(tagValue, "$maxx", number);
+              }
+              if(msCaseFindSubstring(tagValue, "$maxy") != 0)
+              {
+                  snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].y);
+                  tagValue = msReplaceSubstring(tagValue, "$maxy", number);
+              }
+          }
+           /* find the end of the tag */
+          tagEnd = findTagEnd(tagStart);
+          tagEnd++;
+
+          /* build the complete tag so we can do substitution */
+          tagLength = tagEnd - tagStart;
+          tag = (char *) malloc(tagLength + 1);
+          strncpy(tag, tagStart, tagLength);
+          tag[tagLength] = '\0';
+
+          *line = msReplaceSubstring(*line, tag, tagValue);
+
+          /* clean up */
+          msFreeShape(&tShape);
+          free(tag); tag = NULL;
+          msFreeHashTable(tagArgs); tagArgs=NULL;
+          msFree(tagValue); tagValue=NULL;
+             
+
+         if((*line)[tagOffset] != '\0')
+          tagStart = findTag(*line+tagOffset+1, "shplabel");
+         else
+           tagStart = NULL; 
+    }
+
+    return(MS_SUCCESS);
+}
+
 /*
 ** Function to process a [shpxy ...] tag: line contains the tag, shape holds the coordinates. 
 **
@@ -1474,6 +1814,7 @@
   shapeObj tShape;
   char *coords=NULL, point[128];  
   
+
   if(!*line) {
     msSetError(MS_WEBERR, "Invalid line pointer.", "processShpxyTag()");
     return(MS_FAILURE);
@@ -1548,6 +1889,7 @@
       if(argValue) 
         if(strcasecmp(argValue,"true") == 0) centroid = MS_TRUE;
 
+
       argValue = msLookupHashTable(tagArgs, "proj");
       if(argValue) projectionString = argValue;
     }
@@ -1575,6 +1917,7 @@
 
       msAddPointToLine(&(tShape.line[0]), &p);      
     } 
+    
 #ifdef USE_GEOS
     else if(buffer != 0 && bufferUnits != MS_PIXELS) {
       shapeObj *bufferShape=NULL;
@@ -3362,6 +3705,9 @@
     if(processShpxyTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS)
       return(NULL);
 
+     if(processShplabelTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS)
+      return(NULL);
+
     sprintf(repstr, "%f", mapserv->resultshape.bounds.minx);
     outstr = msReplaceSubstring(outstr, "[shpminx]", repstr);
     sprintf(repstr, "%f", mapserv->resultshape.bounds.miny);



More information about the mapserver-commits mailing list