[mapserver-commits] r10234 - sandbox/mapserver6

svn at osgeo.org svn at osgeo.org
Fri Jun 18 04:31:06 EDT 2010


Author: tbonfort
Date: 2010-06-18 08:31:06 +0000 (Fri, 18 Jun 2010)
New Revision: 10234

Modified:
   sandbox/mapserver6/mapgd2.c
Log:
vector symbols


Modified: sandbox/mapserver6/mapgd2.c
===================================================================
--- sandbox/mapserver6/mapgd2.c	2010-06-18 07:01:11 UTC (rev 10233)
+++ sandbox/mapserver6/mapgd2.c	2010-06-18 08:31:06 UTC (rev 10234)
@@ -445,8 +445,163 @@
    return MS_SUCCESS;
 }
 
+static void get_bbox(pointObj *poiList, int numpoints, double *minx, double *miny, double *maxx, double *maxy) {
+  int j;
+
+  *minx = *maxx = poiList[0].x;
+  *miny = *maxy = poiList[0].y;
+  for(j=1; j<numpoints; j++) {
+    if ((poiList[j].x==-99.0) || (poiList[j].y==-99.0)) continue;
+    *minx = MS_MIN(*minx, poiList[j].x);
+    *maxx = MS_MAX(*maxx, poiList[j].x);
+    *miny = MS_MIN(*miny, poiList[j].y);
+    *maxy = MS_MAX(*maxy, poiList[j].y);
+  }
+
+  return;
+}
+
+symbolObj* rotateVectorSymbolPoints(symbolObj *symbol, double angle_rad) {
+   double dp_x, dp_y, xcor, ycor;
+   double sin_a, cos_a;
+   double minx,miny,maxx,maxy;
+   symbolObj *newSymbol;
+   double TOL=0.00000000001;
+   int i;
+   
+   angle_rad = -angle_rad;
+   
+   newSymbol = (symbolObj *) malloc(sizeof(symbolObj));
+   msCopySymbol(newSymbol, symbol, NULL);
+   
+   sin_a = sin(angle_rad);
+   cos_a = cos(angle_rad);
+
+   dp_x = symbol->sizex * .5; /* get the shift vector at 0,0 */
+   dp_y = symbol->sizey * .5;
+
+   /* center at 0,0 and rotate; then move back */
+   for( i=0;i < symbol->numpoints;i++) {
+      /* don't rotate PENUP commands (TODO: should use a constant here) */
+      if ((symbol->points[i].x == -99.0) && (symbol->points[i].x == -99.0) ) {
+         newSymbol->points[i].x = -99.0;
+         newSymbol->points[i].y = -99.0;
+         continue;
+      }
+
+      newSymbol->points[i].x = dp_x + ((symbol->points[i].x-dp_x)*cos_a - (symbol->points[i].y-dp_y)*sin_a);
+      newSymbol->points[i].y = dp_y + ((symbol->points[i].x-dp_x)*sin_a + (symbol->points[i].y-dp_y)*cos_a);
+   }
+
+   /* get the new bbox of the symbol, because we need it to get the new dimensions of the new symbol */
+   get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy);
+   if ( (fabs(minx)>TOL) || (fabs(miny)>TOL) ) {
+      xcor = minx*-1.0; /* symbols always start at 0,0 so get the shift vector */
+      ycor = miny*-1.0;
+      for( i=0;i < newSymbol->numpoints;i++) {
+         if ((newSymbol->points[i].x == -99.0) && (newSymbol->points[i].x == -99.0))
+            continue;
+         newSymbol->points[i].x = newSymbol->points[i].x + xcor;
+         newSymbol->points[i].y = newSymbol->points[i].y + ycor;
+      }
+
+      /* update the bbox to get the final dimension values for the symbol */
+      get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy);
+   }
+   newSymbol->sizex = maxx;
+   newSymbol->sizey = maxy;
+   return newSymbol;
+}
+
 int renderVectorSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) {
-  return MS_SUCCESS;
+   int bRotated = MS_FALSE;
+   int j,k;
+   gdImagePtr ip;
+   gdPoint mPoints[MS_MAXVECTORPOINTS];
+   gdPoint oldpnt,newpnt;
+   int fc,oc;
+   if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE;
+   
+   
+   if(style->color.pen == MS_PEN_UNSET) setPen(ip, &(style->color));
+   if(style->outlinecolor.pen == MS_PEN_UNSET) setPen(ip, &(style->outlinecolor));
+   fc =style->color.pen;
+   oc = style->outlinecolor.pen;
+   
+   if(oc==-1 && fc ==-1) {
+      return MS_SUCCESS;
+   }
+   
+   if (style->rotation != 0.0) {      
+      bRotated = MS_TRUE;
+      symbol = rotateVectorSymbolPoints(symbol, style->rotation);
+      if(!symbol) {
+         return MS_FAILURE;
+      }
+   }
+
+   /* We avoid MS_NINT in this context because the potentially variable
+          handling of 0.5 rounding is often a problem for symbols which are
+          often an odd size (ie. 7pixels) and so if "p" is integral the 
+          value is always on a 0.5 boundary - bug 1716 */
+   x -= style->scale*.5*symbol->sizex;
+   y -= style->scale*.5*symbol->sizey;
+
+   if(symbol->filled) { /* if filled */
+
+      k = 0; /* point counter */
+      for(j=0;j < symbol->numpoints;j++) {
+         if((symbol->points[j].x == -99) && (symbol->points[j].x == -99)) { /* new polygon (PENUP) */
+            if(k>2) {
+               if(fc >= 0)
+                  gdImageFilledPolygon(ip, mPoints, k, fc);
+               if(oc >= 0)
+                  gdImagePolygon(ip, mPoints, k, oc);
+            }
+            k = 0; /* reset point counter */
+         } else {
+            mPoints[k].x = MS_NINT(style->scale*symbol->points[j].x + x);
+            mPoints[k].y = MS_NINT(style->scale*symbol->points[j].y + y); 
+            k++;
+         }
+      }
+
+      if(fc >= 0)
+         gdImageFilledPolygon(ip, mPoints, k, fc);
+      if(oc >= 0)
+         gdImagePolygon(ip, mPoints, k, oc);
+
+   } else  { /* NOT filled */     
+
+      if(oc >= 0) fc = oc; /* try the outline color (reference maps sometimes do this when combining a box and a custom vector marker */
+      
+      oldpnt.x = MS_NINT(style->scale*symbol->points[0].x + x); /* convert first point in marker */
+      oldpnt.y = MS_NINT(style->scale*symbol->points[0].y + y);
+
+      gdImageSetThickness(ip, style->outlinewidth);
+
+      for(j=1;j < symbol->numpoints;j++) { /* step through the marker */
+         if((symbol->points[j].x != -99) || (symbol->points[j].x != -99)) {
+            if((symbol->points[j-1].x == -99) && (symbol->points[j-1].y == -99)) { /* Last point was PENUP, now a new beginning */
+               oldpnt.x = MS_NINT(style->scale*symbol->points[j].x + x);
+               oldpnt.y = MS_NINT(style->scale*symbol->points[j].y + y);
+            } else {
+               newpnt.x = MS_NINT(style->scale*symbol->points[j].x + x);
+               newpnt.y = MS_NINT(style->scale*symbol->points[j].y + y);
+               gdImageLine(ip, oldpnt.x, oldpnt.y, newpnt.x, newpnt.y, fc);
+               oldpnt = newpnt;
+            }
+         }
+      } /* end for loop */   
+
+      gdImageSetThickness(ip, 1); /* restore thinkness */
+   } /* end if-then-else */
+
+   if(bRotated) {
+      msFreeSymbol(symbol); /* clean up */
+      msFree(symbol);
+   }
+   return MS_SUCCESS;
 }
 
 int renderTruetypeSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *s) {



More information about the mapserver-commits mailing list