[mapserver-commits] r10781 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Tue Dec 7 10:05:26 EST 2010


Author: tbonfort
Date: 2010-12-07 07:05:26 -0800 (Tue, 07 Dec 2010)
New Revision: 10781

Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/mapagg.cpp
   trunk/mapserver/mapcairo.c
   trunk/mapserver/mapdraw.c
   trunk/mapserver/mapdummyrenderer.c
   trunk/mapserver/mapgd.c
   trunk/mapserver/mapgraticule.c
   trunk/mapserver/mapkml.cpp
   trunk/mapserver/mapogl.cpp
   trunk/mapserver/mapprimitive.c
   trunk/mapserver/mapserver.h
   trunk/mapserver/maptemplate.c
Log:
Add support for per layer tuning of the shape to pixel conversion (SIMPLIFY, ROUND, SNAPTOGRID, FULLRESOLUTION)



Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/HISTORY.TXT	2010-12-07 15:05:26 UTC (rev 10781)
@@ -13,6 +13,8 @@
 
 Current Version (SVN trunk):
 ----------------------------
+- Add support for per layer tuning of the shape to pixel conversion (SIMPLIFY, ROUND,
+  SNAPTOGRID, FULLRESOLUTION)
 
 - Fixed: Memory allocation results should always be checked (#3559)
 

Modified: trunk/mapserver/mapagg.cpp
===================================================================
--- trunk/mapserver/mapagg.cpp	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapagg.cpp	2010-12-07 15:05:26 UTC (rev 10781)
@@ -789,6 +789,7 @@
    renderer->supports_pixel_buffer = 1;
    renderer->use_imagecache = 0;
    renderer->supports_clipping = 0;
+   renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY;
    
    agg2InitCache(&(MS_RENDERER_CACHE(renderer)));
    renderer->cleanup = agg2Cleanup;
@@ -825,7 +826,6 @@
    renderer->startLayer = &agg2StartNewLayer;
    renderer->endLayer = &agg2CloseNewLayer;
 
-   renderer->transformShape = &msTransformShapeToPixel;
    renderer->freeImage = &agg2FreeImage;
    renderer->freeSymbol = &agg2FreeSymbol;
    renderer->cleanup = agg2Cleanup;

Modified: trunk/mapserver/mapcairo.c
===================================================================
--- trunk/mapserver/mapcairo.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapcairo.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -790,6 +790,7 @@
 #ifdef USE_CAIRO
     renderer->supports_pixel_buffer=1;
     renderer->supports_transparent_layers = 0;
+    renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY;
     initializeCache(&MS_RENDERER_CACHE(renderer));
     renderer->startLayer = startLayerRasterCairo;
     renderer->endLayer = closeLayerRasterCairo;
@@ -798,8 +799,6 @@
     renderer->saveImage=&saveImageCairo;
     renderer->getRasterBufferHandle=&getRasterBufferHandleCairo;
     renderer->getRasterBufferCopy=&getRasterBufferCopyCairo;
-        
-    renderer->transformShape=&msTransformShapeToPixel;
     renderer->renderPolygon=&renderPolygonCairo;
     renderer->renderGlyphs=&renderGlyphsCairo;
     renderer->freeImage=&freeImageCairo;
@@ -827,6 +826,7 @@
     renderer->use_imagecache=0;
     renderer->supports_pixel_buffer=0;
     renderer->supports_transparent_layers = 1;
+    renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY;
     initializeCache(&MS_RENDERER_CACHE(renderer));
     renderer->startLayer = startLayerVectorCairo;
     renderer->endLayer = closeLayerVectorCairo;
@@ -834,7 +834,6 @@
     renderer->createImage=&createImageCairo;
     renderer->saveImage=&saveImageCairo;
     renderer->getRasterBufferHandle=&getRasterBufferHandleCairo;
-    renderer->transformShape=&msTransformShapeToPixel;
     renderer->renderPolygon=&renderPolygonCairo;
     renderer->renderGlyphs=&renderGlyphsCairo;
     renderer->freeImage=&freeImageCairo;

Modified: trunk/mapserver/mapdraw.c
===================================================================
--- trunk/mapserver/mapdraw.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapdraw.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -1470,7 +1470,7 @@
 
         msInitShape(&annoshape);
         msCopyShape(shape, &annoshape);
-        msTransformShape(&annoshape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(&annoshape, map->extent, map->cellsize, image);
 
         if(layer->class[c]->label.anglemode == MS_FOLLOW ) {
           annopaths = msPolylineLabelPath(map,image,&annoshape, minfeaturesize, &(map->fontset), shape->text, &(layer->class[c]->label), layer->scalefactor, &numpaths, &regularLines, &numRegularLines);
@@ -1484,7 +1484,7 @@
       if(layer->transform == MS_TRUE) {
         msClipPolylineRect(shape, cliprect);
         if(shape->numlines == 0) return(MS_SUCCESS);
-        msTransformShape(shape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(shape, map->extent, map->cellsize, image);
       } else
         msOffsetShapeRelativeTo(shape, layer);
 
@@ -1653,7 +1653,7 @@
       if(layer->transform == MS_TRUE) {
         msClipPolygonRect(shape, cliprect);
         if(shape->numlines == 0) return(MS_SUCCESS);
-        msTransformShape(shape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(shape, map->extent, map->cellsize, image);
       } else
 	msOffsetShapeRelativeTo(shape, layer);
 
@@ -1795,7 +1795,7 @@
 
       msInitShape(&annoshape);
       msCopyShape(shape, &annoshape);
-      msTransformShape(&annoshape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+      msTransformShape(&annoshape, map->extent, map->cellsize, image);
 
       if(layer->class[c]->label.anglemode == MS_FOLLOW) {
         annopaths = msPolylineLabelPath(map,image,&annoshape, minfeaturesize, &(map->fontset), shape->text, &(layer->class[c]->label), layer->scalefactor, &numpaths, &regularLines, &numRegularLines);
@@ -1827,9 +1827,9 @@
           msFreeShape(&nonClippedShape);   
         return(MS_SUCCESS);
       }
-      msTransformShape(shape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+      msTransformShape(shape, map->extent, map->cellsize, image);
       if(hasGeomTransform)
-        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image);
     } else {
       msOffsetShapeRelativeTo(shape, layer);
     }
@@ -2045,13 +2045,13 @@
           msFreeShape(&nonClippedShape);   
         return(MS_SUCCESS);
       }
-      msTransformShape(shape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+      msTransformShape(shape, map->extent, map->cellsize, image);
       if(hasGeomTransform)
-        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image);
     } else {
       msOffsetShapeRelativeTo(shape, layer);
       if(hasGeomTransform)
-        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image, MS_SIMPLIFY_DEFAULT);
+        msTransformShape(&nonClippedShape, map->extent, map->cellsize, image);
     }
  
     for(s=0; s<layer->class[c]->numstyles; s++) {
@@ -2613,7 +2613,23 @@
     if (image)
     {
         if( MS_RENDERER_PLUGIN(image->format) ) {
-            MS_IMAGE_RENDERER(image)->startLayer(image, map, layer);
+           char *approximation_scale = msLayerGetProcessingKey( layer, "APPROXIMATION_SCALE" );
+           if(approximation_scale) {
+              if(!strncasecmp(approximation_scale,"ROUND",5)) {
+                 MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_ROUND;
+              } else if(!strncasecmp(approximation_scale,"FULL",4)) {
+                 MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_FULLRESOLUTION;
+              } else if(!strncasecmp(approximation_scale,"SIMPLIFY",8)) {
+                 MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SIMPLIFY;
+              } else {
+                 MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SNAPTOGRID;
+                 MS_IMAGE_RENDERER(image)->approximation_scale = atof(approximation_scale);
+              }
+           } else {
+              MS_IMAGE_RENDERER(image)->transform_mode = MS_IMAGE_RENDERER(image)->default_transform_mode;
+              MS_IMAGE_RENDERER(image)->approximation_scale = MS_IMAGE_RENDERER(image)->default_approximation_scale;
+           }
+           MS_IMAGE_RENDERER(image)->startLayer(image, map, layer);
         }
         else if( MS_RENDERER_IMAGEMAP(image->format) )
             msImageStartLayerIM(map, layer, image);

Modified: trunk/mapserver/mapdummyrenderer.c
===================================================================
--- trunk/mapserver/mapdummyrenderer.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapdummyrenderer.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -200,11 +200,6 @@
 	return MS_FAILURE;
 }
 
-int transformShapeDummy(shapeObj *shape, rectObj extend, double cellsize, enum MS_SIMPLIFY_MODE simplify) {
-	msSetError(MS_RENDERERERR,"transformShape not implemented","transformShape()");
-	return MS_FAILURE;
-}
-
 int freeImageDummy(imageObj *image) {
 	msSetError(MS_RENDERERERR,"freeImage not implemented","freeImage()");
 	return MS_FAILURE;
@@ -232,6 +227,7 @@
 	renderer->supports_clipping = 0;
 	renderer->supports_bitmap_fonts = 0;
 	renderer->renderer_data = NULL;
+	renderer->transform_mode = MS_TRANSFORM_SIMPLIFY;
 	renderer->startLayer = &startLayerDummy;
 	renderer->endLayer = &endLayerDummy;
 	renderer->renderLine=&renderLineDummy;
@@ -240,7 +236,6 @@
 	renderer->getRasterBufferHandle=&getRasterBufferHandleDummy;
 	renderer->getRasterBufferCopy=getRasterBufferCopyDummy;
 	renderer->initializeRasterBuffer=initializeRasterBufferDummy;
-	renderer->transformShape=&msTransformShapeToPixel;
 	renderer->renderPolygon=&renderPolygonDummy;
 	renderer->renderGlyphs=&renderGlyphsDummy;
 	renderer->renderBitmapGlyphs = &renderGlyphsDummy;

Modified: trunk/mapserver/mapgd.c
===================================================================
--- trunk/mapserver/mapgd.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapgd.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -910,6 +910,7 @@
   renderer->supports_pixel_buffer=1;
   renderer->supports_transparent_layers = 0;
   renderer->supports_bitmap_fonts = 1;
+  renderer->default_transform_mode = MS_TRANSFORM_ROUND;
   
   for(i=0;i<5;i++) {
      gdFontPtr f = msGetBitmapFont(i);
@@ -928,8 +929,6 @@
   renderer->getRasterBufferCopy = &getRasterBufferCopyGD;
   renderer->initializeRasterBuffer = initializeRasterBufferGD;
   renderer->loadImageFromFile = msLoadGDRasterBufferFromFile;
-    
-  renderer->transformShape = &msTransformShapeToPixel;
   renderer->renderPolygon = &renderPolygonGD;
   renderer->renderGlyphs = &renderGlyphsGD;
   renderer->renderBitmapGlyphs = &renderBitmapGlyphsGD;

Modified: trunk/mapserver/mapgraticule.c
===================================================================
--- trunk/mapserver/mapgraticule.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapgraticule.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -698,12 +698,7 @@
       msClipPolylineRect(&shapegrid, cliprect);
      
 
-      if(MS_RENDERER_PLUGIN(map->outputformat)) {
-    	  rendererVTableObj *renderer = MS_MAP_RENDERER(map);
-    	  renderer->transformShape(&shapegrid, map->extent, map->cellsize, MS_SIMPLIFY_DEFAULT);
-      } else {
-    	  msTransformShapeToPixel(&shapegrid, map->extent, map->cellsize, MS_SIMPLIFY_DEFAULT);
-      }
+      msTransformShapeToPixelRound(&shapegrid, map->extent, map->cellsize);
 
      
  
@@ -1100,11 +1095,7 @@
 #endif
 
   if(pLayer->transform) {
-	if(MS_RENDERER_PLUGIN(pLayer->map->outputformat)) {
-		MS_MAP_RENDERER(pLayer->map)->transformShape(pShape, pLayer->map->extent, pLayer->map->cellsize, MS_SIMPLIFY_DEFAULT);
-	} else {
-		msTransformShapeToPixel(pShape, pLayer->map->extent, pLayer->map->cellsize, MS_SIMPLIFY_DEFAULT);
-	}
+     msTransformShapeToPixelRound(pShape, pLayer->map->extent, pLayer->map->cellsize);
   }
 
   if(msGetLabelSize(pLayer->map, &pLayer->class[0]->label,pShape->text, size,&rectLabel,NULL) != MS_SUCCESS)

Modified: trunk/mapserver/mapkml.cpp
===================================================================
--- trunk/mapserver/mapkml.cpp	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapkml.cpp	2010-12-07 15:05:26 UTC (rev 10781)
@@ -165,11 +165,6 @@
 	return renderer->closeNewLayer(img, layer);
 }
 
-int msTransformShapeKml(shapeObj *shape, rectObj extend, double cellsize, enum MS_SIMPLIFY_MODE simplifyMode)
-{
-   return MS_SUCCESS;
-}
-
 int msFreeImageKml(imageObj *image)
 {
 	KmlRenderer* renderer = getKmlRenderer(image);
@@ -223,14 +218,13 @@
    renderer->supports_bitmap_fonts = 0;
    renderer->supports_clipping = 0;
    renderer->use_imagecache = 0;
-   
+   renderer->default_transform_mode = MS_TRANSFORM_NONE;
 
    renderer->startLayer = msStartNewLayerKml;
    renderer->endLayer = msCloseNewLayerKml;
    renderer->renderLine=&msRenderLineKml;
    renderer->createImage=&msCreateImageKml;
    renderer->saveImage=&msSaveImageKml;
-   renderer->transformShape=&msTransformShapeKml;
    renderer->renderPolygon=&msRenderPolygonKml;
    renderer->renderGlyphs=&msRenderGlyphsKml;
    renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml;

Modified: trunk/mapserver/mapogl.cpp
===================================================================
--- trunk/mapserver/mapogl.cpp	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapogl.cpp	2010-12-07 15:05:26 UTC (rev 10781)
@@ -201,7 +201,7 @@
 		renderer->supports_clipping = 0;
 		renderer->use_imagecache = 0;
 		renderer->supports_bitmap_fonts = 0;
-
+		renderer->transform_mode = MS_TRANSFORM_SIMPLIFY;
     	renderer->startLayer = msStartLayerOgl;
     	renderer->endLayer = msEndLayerOgl;        
         
@@ -221,7 +221,6 @@
         renderer->renderPolygonTiled = &msDrawPolygonTiledOgl;
         renderer->renderLineTiled = &msDrawLineTiledOgl;
         
-		renderer->transformShape=&msTransformShapeToPixel;
 		renderer->getTruetypeTextBBox = &msGetTruetypeTextBBoxOgl;
         
 		renderer->getRasterBufferHandle = msGetRasterBufferHandleOgl;

Modified: trunk/mapserver/mapprimitive.c
===================================================================
--- trunk/mapserver/mapprimitive.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapprimitive.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -816,89 +816,13 @@
   return;
 }
 
-/**
- * Generic function to transorm the shape coordinates to output coordinates
- */
-void  msTransformShape(shapeObj *shape, rectObj extent, double cellsize, 
-                       imageObj *image, enum MS_SIMPLIFY_MODE simplify_mode)   
+void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize)
 {
-	if (image != NULL && MS_RENDERER_PLUGIN(image->format)) {
-		image->format->vtable->transformShape(shape, extent, cellsize, simplify_mode);
-
-		return;
-	}
-#ifdef USE_MING_FLASH
-    if (image != NULL && MS_RENDERER_SWF(image->format) )
-    {
-        if (strcasecmp(msGetOutputFormatOption(image->format, "FULL_RESOLUTION",""), 
-                       "FALSE") == 0)
-          msTransformShapeToPixel(shape, extent, cellsize, simplify_mode);
-        else
-          msTransformShapeSWF(shape, extent, cellsize);
-          
-
-        return;
-    }
-#endif
-    msTransformShapeToPixel(shape, extent, cellsize, simplify_mode);
-}
-
-int msTransformShapeToPixel(shapeObj *shape, rectObj extent, double cellsize, enum MS_SIMPLIFY_MODE simplifyMode)
-{
-	if(shape->numlines == 0) return;
-	switch(simplifyMode) {
-	case MS_SIMPLIFY_ROUND:
-		return msTransformShapeToPixelIntegerPrecision(shape,extent,cellsize);
-		break;
-	case MS_SIMPLIFY_NAIVE:
-	case MS_SIMPLIFY_NONE:
-	case MS_SIMPLIFY_DEFAULT:
-	default:
-		return msTransformShapeToPixelDoublePrecision(shape,extent,cellsize);
-	}
-
-}
-
-/*
-** converts from map coordinates to image coordinates
-*/
-int msTransformShapeToPixelIntegerPrecision(shapeObj *shape, rectObj extent, double cellsize)
-{
-  int i,j,k; /* loop counters */
-  double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
-
-  if(shape->numlines == 0) return; /* nothing to transform */
-
-  if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
-    for(i=0; i<shape->numlines; i++) { /* for each part */
-      shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);
-      shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
-      for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
-        shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
-        shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
-        if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
-          k++;
-      }
-      shape->line[i].numpoints = k; /* save actual number kept */
-    }
-  } else { /* points or untyped shapes */
-    for(i=0; i<shape->numlines; i++) { /* for each part */
-      for(j=1; j < shape->line[i].numpoints; j++ ) {
-        shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
-        shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
-      }
-    }
-  }
-}
-
-int msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize)
-{
     int i,j,k,beforelast; /* loop counters */
     double dx,dy;
     double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
+    if(shape->numlines == 0) return; /* nothing to transform */
     pointObj *point;
-    if(shape->numlines == 0) return; /* nothing to transform */
-
     if(shape->type == MS_SHAPE_LINE) {
         /*
          * loop through the shape's lines, and do naive simplification
@@ -937,7 +861,7 @@
             }
             //skip degenerate line once more
             if(shape->line[i].numpoints<2)
-            	shape->line[i].numpoints=0;
+               shape->line[i].numpoints=0;
         }
     }
     else if(shape->type == MS_SHAPE_POLYGON) {
@@ -986,8 +910,158 @@
     }
 }
 
+/**
+ * Generic function to transorm the shape coordinates to output coordinates
+ */
+void  msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image)
+{
+	if (image != NULL && MS_RENDERER_PLUGIN(image->format)) {
+	   rendererVTableObj *renderer = MS_IMAGE_RENDERER(image);
+	   if(renderer->transform_mode == MS_TRANSFORM_SNAPTOGRID) {
+	      msTransformShapeToPixelSnapToGrid(shape, extent, cellsize, renderer->approximation_scale);
+	   } else if(renderer->transform_mode == MS_TRANSFORM_SIMPLIFY) {
+         msTransformShapeSimplify(shape, extent, cellsize);
+      } else if(renderer->transform_mode == MS_TRANSFORM_ROUND) {
+	      msTransformShapeToPixelRound(shape, extent, cellsize);
+      } else if(renderer->transform_mode == MS_TRANSFORM_FULLRESOLUTION) {
+	      msTransformShapeToPixelDoublePrecision(shape,extent,cellsize);
+	   } else if(renderer->transform_mode == MS_TRANSFORM_NONE) {
+         /* nothing to do */
+         return;
+      } 
+	   /* unknown, do nothing */
+		return;
+	}
+#ifdef USE_MING_FLASH
+    if (image != NULL && MS_RENDERER_SWF(image->format) )
+    {
+        if (strcasecmp(msGetOutputFormatOption(image->format, "FULL_RESOLUTION",""), 
+                       "FALSE") == 0)
+          msTransformShapeToPixelRound(shape, extent, cellsize);
+        else
+          msTransformShapeSWF(shape, extent, cellsize);
+          
 
+        return;
+    }
+#endif
+    msTransformShapeToPixelRound(shape, extent, cellsize);
+}
 
+void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution)
+{
+   int i,j,k; /* loop counters */
+   double inv_cs;
+   if(shape->numlines == 0) return;
+   inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
+   
+   
+   if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
+      for(i=0; i<shape->numlines; i++) { /* for each part */
+         int snap = 1;
+         double x0,y0,x1,y1,x2,y2;
+         /*do a quick heuristic: will we risk having a degenerate shape*/
+         if(shape->type == MS_SHAPE_LINE) {
+            /*a line is degenerate if it has a single pixel. we check that the first and last pixel are different*/
+            x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
+            y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
+            x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs, grid_resolution);
+            y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs, grid_resolution);
+            if(x0 == x1 && y0 == y1) {
+               snap = 0;
+            }
+         } else if(shape->type == MS_SHAPE_POLYGON) {
+            x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
+            y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
+            x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].x, extent.minx, inv_cs, grid_resolution);
+            y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].y, extent.maxy, inv_cs, grid_resolution);
+            x2 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].x, extent.minx, inv_cs, grid_resolution);
+            y2 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].y, extent.maxy, inv_cs, grid_resolution);
+            if((x0 == x1 && y0 == y1) ||
+                  (x0 == x2 && y0 == y2) ||
+                  (x1 == x2 && y1 == y2)) {
+               snap = 0;
+            }
+         }
+         if(snap) {
+               shape->line[i].point[0].x = x0;
+               shape->line[i].point[0].y = y0;
+               for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
+                  shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[j].x, extent.minx, inv_cs, grid_resolution);
+                  shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[j].y, extent.maxy, inv_cs, grid_resolution);
+                  if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
+                     k++;
+               }
+               shape->line[i].numpoints=k;
+         } else {
+            if(shape->type == MS_SHAPE_LINE) {
+               shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[0].x, extent.minx, inv_cs);
+               shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[0].y, extent.maxy, inv_cs);
+               shape->line[i].point[1].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs);
+               shape->line[i].point[1].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs);      
+               shape->line[i].numpoints = 2;
+            } else {
+               for(j=0; j < shape->line[i].numpoints; j++ ) {
+                  shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
+                  shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
+               }
+            }
+         }
+      }
+   } else { /* points or untyped shapes */
+      for(i=0; i<shape->numlines; i++) { /* for each part */
+         for(j=1; j < shape->line[i].numpoints; j++ ) {
+            shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
+            shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
+         }
+      }
+   }
+
+}
+
+void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize)
+{
+   int i,j,k; /* loop counters */
+   double inv_cs;
+   if(shape->numlines == 0) return;
+   inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
+   if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
+      for(i=0; i<shape->numlines; i++) { /* for each part */
+         shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);;
+         shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
+         for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
+            shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
+            shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
+            if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
+               k++;
+         }
+         shape->line[i].numpoints=k;
+      }
+   } else { /* points or untyped shapes */
+      for(i=0; i<shape->numlines; i++) { /* for each part */
+         for(j=1; j < shape->line[i].numpoints; j++ ) {
+            shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
+            shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
+         }
+      }
+   }
+
+}
+
+void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize)
+{
+   int i,j; /* loop counters */
+   double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
+   for(i=0; i<shape->numlines; i++) {
+      for(j=0;j<shape->line[i].numpoints;j++) {
+         shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
+         shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
+      }
+   }
+}
+
+
+
 /*
 ** Converts from map coordinates to image coordinates
 */

Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/mapserver.h	2010-12-07 15:05:26 UTC (rev 10781)
@@ -395,12 +395,15 @@
 #define MS_IMAGE2MAP_X(x,minx,cx) (minx + cx*x)
 #define MS_IMAGE2MAP_Y(y,maxy,cy) (maxy - cy*y)
 
-/* this version of MS_MAP2IMAGE takes 1/cellsize and is much faster */
+/* these versions of MS_MAP2IMAGE takes 1/cellsize and is much faster */
 #define MS_MAP2IMAGE_X_IC(x,minx,icx) (MS_NINT((x - minx)*icx))
 #define MS_MAP2IMAGE_Y_IC(y,maxy,icy) (MS_NINT((maxy - y)*icy))
 
 #define MS_MAP2IMAGE_X_IC_DBL(x,minx,icx) ((x - minx)*icx)
 #define MS_MAP2IMAGE_Y_IC_DBL(y,maxy,icy) ((maxy - y)*icy)
+    
+#define MS_MAP2IMAGE_X_IC_SNAP(x,minx,icx,res) ((MS_NINT((x - minx)*icx*res))/(res))
+#define MS_MAP2IMAGE_Y_IC_SNAP(y,maxy,icy,res) ((MS_NINT((maxy - y)*icy*res))/(res))
 
 /* For CARTO symbols */
 #define MS_PI    3.14159265358979323846
@@ -451,11 +454,12 @@
 #define MS_FILE_DEFAULT MS_FILE_MAP   
 
 /* coordinate to pixel simplification modes, used in msTransformShape */
-enum MS_SIMPLIFY_MODE {
-	MS_SIMPLIFY_DEFAULT, /* use renderer default */ 
-	MS_SIMPLIFY_NONE, /* precise conversion */
-	MS_SIMPLIFY_ROUND, /* round to closest pixel, removing identical points */
-	MS_SIMPLIFY_NAIVE /* find better name */
+enum MS_TRANSFORM_MODE {
+   MS_TRANSFORM_NONE, /* no geographic to pixel transformation */
+   MS_TRANSFORM_ROUND, /* round to integer, might create degenerate geometries (used for GD)*/
+   MS_TRANSFORM_SNAPTOGRID, /* snap to a grid, should be user configurable in the future*/
+   MS_TRANSFORM_FULLRESOLUTION, /* keep full resolution */
+   MS_TRANSFORM_SIMPLIFY /* keep full resolution */
 };
 
 #ifndef SWIG
@@ -1921,16 +1925,17 @@
 MS_DLL_EXPORT void msRectToPolygon(rectObj rect, shapeObj *poly);
 MS_DLL_EXPORT void msClipPolylineRect(shapeObj *shape, rectObj rect);
 MS_DLL_EXPORT void msClipPolygonRect(shapeObj *shape, rectObj rect);
-MS_DLL_EXPORT void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image, enum MS_SIMPLIFY_MODE simplifyMode);
+MS_DLL_EXPORT void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image);
 
 
 MS_DLL_EXPORT void msTransformPoint(pointObj *point, rectObj *extent, double cellsize, imageObj *image);
 
 MS_DLL_EXPORT void msOffsetPointRelativeTo(pointObj *point, layerObj *layer);
 MS_DLL_EXPORT void msOffsetShapeRelativeTo(shapeObj *shape, layerObj *layer);
-MS_DLL_EXPORT int msTransformShapeToPixel(shapeObj *shape, rectObj extent, double cellsize, enum MS_SIMPLIFY_MODE simplify_mode);
-MS_DLL_EXPORT int msTransformShapeToPixelIntegerPrecision(shapeObj *shape, rectObj extent, double cellsize);
-MS_DLL_EXPORT int msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize);
+MS_DLL_EXPORT void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize);
+MS_DLL_EXPORT void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution);
+MS_DLL_EXPORT void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize);
+MS_DLL_EXPORT void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize);
 
 MS_DLL_EXPORT void msTransformPixelToShape(shapeObj *shape, rectObj extent, double cellsize);
 MS_DLL_EXPORT void msImageCartographicPolyline(gdImagePtr im, shapeObj *p, styleObj *style, symbolObj *symbol, int c, double size, double scalefactor);
@@ -2563,6 +2568,10 @@
 	int supports_clipping;
 	int supports_bitmap_fonts;
 	int use_imagecache;
+	enum MS_TRANSFORM_MODE default_transform_mode;
+	enum MS_TRANSFORM_MODE transform_mode;
+	double default_approximation_scale;
+	double approximation_scale;
 	
 	void *renderer_data;
 
@@ -2632,7 +2641,6 @@
 	int (*setClip)(imageObj *img, rectObj clipRect);
 	int (*resetClip)(imageObj *img);
 
-	int (*transformShape)(shapeObj *shape, rectObj extend, double cellsize, enum MS_SIMPLIFY_MODE simplify);
 	int (*freeImage)(imageObj *image);
 	int (*freeSymbol)(symbolObj *symbol);
 	int (*cleanup)(void *renderer_data);

Modified: trunk/mapserver/maptemplate.c
===================================================================
--- trunk/mapserver/maptemplate.c	2010-12-07 03:53:20 UTC (rev 10780)
+++ trunk/mapserver/maptemplate.c	2010-12-07 15:05:26 UTC (rev 10781)
@@ -1610,7 +1610,7 @@
                   msClipPolylineRect(shape, layer->map->extent);
          
 
-                msTransformShapeToPixel(shape, layer->map->extent, cellsize, MS_SIMPLIFY_DEFAULT);
+                msTransformShapeToPixelRound(shape, layer->map->extent, cellsize);
             }
             else
               msOffsetShapeRelativeTo(shape, layer);
@@ -1653,7 +1653,7 @@
                 if (clip_to_map)
                   msClipPolygonRect(shape, layer->map->extent);
 
-                msTransformShapeToPixel(shape, layer->map->extent, cellsize, MS_SIMPLIFY_DEFAULT);
+                msTransformShapeToPixelRound(shape, layer->map->extent, cellsize);
             }
             else
               msOffsetShapeRelativeTo(shape, layer);
@@ -1738,7 +1738,7 @@
       
               msClipPolylineRect(&tShape, layer->map->extent);
 
-              msTransformShapeToPixel(&tShape, layer->map->extent, layer->map->cellsize, MS_SIMPLIFY_DEFAULT);
+              msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize);
 
          } else if(projectionString) {
              projectionObj projection;
@@ -2046,7 +2046,7 @@
         return(MS_FAILURE);
         break;
       }
-      msTransformShapeToPixel(&tShape, layer->map->extent, layer->map->cellsize, MS_SIMPLIFY_DEFAULT);
+      msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize);
 
 #ifdef USE_GEOS
       if(buffer != 0 && bufferUnits == MS_PIXELS) {



More information about the mapserver-commits mailing list