[mapserver-commits] r7547 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Wed Apr 30 16:26:57 EDT 2008


Author: pramsey
Date: 2008-04-30 16:26:56 -0400 (Wed, 30 Apr 2008)
New Revision: 7547

Added:
   trunk/mapserver/maptile.c
   trunk/mapserver/maptile.h
Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/Makefile.in
   trunk/mapserver/mapserv.c
   trunk/mapserver/mapserv.h
   trunk/mapserver/maptemplate.h
Log:
Tiling API (RFC 43) mode=tile, tilemode=spheremerc, tile=x y zoom (#2581)


Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2008-04-30 14:27:38 UTC (rev 7546)
+++ trunk/mapserver/HISTORY.TXT	2008-04-30 20:26:56 UTC (rev 7547)
@@ -13,6 +13,8 @@
 Current Version (5.1-dev, SVN trunk):
 -------------------------------------
 
+- Tiling API (RFC 43) mode=tile, tilemode=spheremerc, tile=x y zoom (#2581)
+
 - Remove C++-style comments and most other warnings thrown by -pedantic (#2598)
 
 - Fix PostGIS transaction behavior in fcgi situations (#2497)

Modified: trunk/mapserver/Makefile.in
===================================================================
--- trunk/mapserver/Makefile.in	2008-04-30 14:27:38 UTC (rev 7546)
+++ trunk/mapserver/Makefile.in	2008-04-30 20:26:56 UTC (rev 7547)
@@ -329,8 +329,8 @@
 scalebar: $(LIBMAP_STATIC)  scalebar.o mapserver.h
 	$(LD) $(CFLAGS) scalebar.o $(EXE_LDFLAGS) -o scalebar
 
-mapserv: mapserv.h $(LIBMAP_STATIC)  mapserv.o cgiutil.o mapserver.h
-	$(LD) $(CFLAGS) mapserv.o cgiutil.o $(EXE_LDFLAGS) -o mapserv
+mapserv: mapserv.h maptile.h $(LIBMAP_STATIC)  mapserv.o cgiutil.o maptile.o mapserver.h
+	$(LD) $(CFLAGS) mapserv.o cgiutil.o maptile.o $(EXE_LDFLAGS) -o mapserv
 
 shpindex: $(LIBMAP_STATIC) shpindex.o mapserver.h
 	$(LD) $(CFLAGS) shpindex.o $(EXE_LDFLAGS) -o shpindex

Modified: trunk/mapserver/mapserv.c
===================================================================
--- trunk/mapserver/mapserv.c	2008-04-30 14:27:38 UTC (rev 7546)
+++ trunk/mapserver/mapserv.c	2008-04-30 20:26:56 UTC (rev 7547)
@@ -843,6 +843,40 @@
       continue;
     }
 
+    /* -------------------------------------------------------------------- 
+     *   The following code is used to support mode=tile                    
+     * -------------------------------------------------------------------- */ 
+
+    if(strcasecmp(msObj->request->ParamNames[i], "tilemode") == 0) { 
+      /* currently, only valid tilemode is "spheremerc" */
+      if( strcasecmp(msObj->request->ParamValues[i], "spheremerc") != 0) {
+        msSetError(MS_WEBERR, "Invalid tilemode. Use one of: spheremerc", "loadForm()");
+        writeError();
+      }
+      msObj->TileMode = SPHEREMERC;
+      continue;
+    }
+
+    if(strcasecmp(msObj->request->ParamNames[i],"tile") == 0) { 
+
+      int num_coords = 0;
+      char **coords = NULL;
+      int l = 0;
+      
+      msObj->CoordSource = FROMTILE;
+      coords = msStringSplit(msObj->request->ParamValues[i], ' ', &(num_coords));
+      if( num_coords != 3 ) {
+        msSetError(MS_WEBERR, "Invalid number of tile coordinates (should be three).", "loadForm()");
+        writeError();
+      }
+
+      msObj->TileCoords = (long *) malloc(sizeof(long) * 3);
+      for(l = 0; l < num_coords; l++) {
+        *(msObj->TileCoords + l) = strtol(coords[l], NULL, 10);
+      }
+      continue;
+    }
+
     /* -------------------------------------------------------------------- */
     /*      The following code is used to support the rosa applet (for      */
     /*      more information on Rosa, please consult :                      */
@@ -1258,6 +1292,16 @@
     if(msObj->CoordSource == FROMREFPNT) /* force browse mode if the reference coords are set */
       msObj->Mode = BROWSE;
 
+    /*
+    ** Tile mode:
+    ** Set the projection up and test the parameters for legality.
+    */
+    if(msObj->Mode == TILE) {
+      if( msTileSetup(msObj) != MS_SUCCESS ) {
+        writeError();
+      }
+    }
+
     if(msObj->Mode == BROWSE) {
 
       if(!msObj->Map->web.template) {
@@ -1297,10 +1341,19 @@
         }
       }
 
-    } else if(msObj->Mode == MAP || msObj->Mode == SCALEBAR || msObj->Mode == REFERENCE) { /* "image" only modes */
+    } else if(msObj->Mode == MAP || msObj->Mode == SCALEBAR || msObj->Mode == REFERENCE || msObj->Mode == TILE) { /* "image" only modes */
+
       setExtent(msObj);
       checkWebScale(msObj);
       
+      /*
+      ** We set tile extents here instead of setExtent so that all the 
+      ** non-CGI utilities don't require maptile.o in their build.
+      */
+      if( msObj->Mode == TILE ) {
+        msTileSetExtent(msObj);
+      }
+            
       switch(msObj->Mode) {
       case MAP:
         if(QueryFile) {
@@ -1317,12 +1370,25 @@
       case SCALEBAR:
         img = msDrawScalebar(msObj->Map);
         break;
+      case TILE:
+        /* TODO: we may need an msDrawTile for doing "draw large then clip" tricks */
+        img = msDrawMap(msObj->Map, MS_FALSE);
+        break;
       }
       
       if(!img) writeError();
       
+      /*
+      ** Set the Cache control headers if the option is set. 
+      */
+      if( msLookupHashTable(&(msObj->Map->web.metadata), "http_max_age") ) {
+        msIO_printf("Cache-Control: max-age=%s%c", msLookupHashTable(&(msObj->Map->web.metadata), "http_max_age"), 10);
+      }
+
       msIO_printf("Content-type: %s%c%c",MS_IMAGE_MIME_TYPE(msObj->Map->outputformat), 10,10);
-      if( msObj->Mode == MAP )
+      
+      
+      if( msObj->Mode == MAP || msObj->Mode == TILE )
         status = msSaveImage(msObj->Map,img, NULL);
       else
         status = msSaveImage(NULL,img, NULL);
@@ -1699,7 +1765,7 @@
     if(QueryLayer) free(QueryLayer);
     if(SelectLayer) free(SelectLayer);
     if(QueryFile) free(QueryFile);
-   
+
     msFreeMapServObj(msObj);
 
 #ifdef USE_FASTCGI

Modified: trunk/mapserver/mapserv.h
===================================================================
--- trunk/mapserver/mapserv.h	2008-04-30 14:27:38 UTC (rev 7546)
+++ trunk/mapserver/mapserv.h	2008-04-30 20:26:56 UTC (rev 7547)
@@ -38,6 +38,7 @@
 #include <time.h>
 
 #include "maptemplate.h"
+#include "maptile.h"
 
 #include "cgiutil.h"
 /*
@@ -56,13 +57,13 @@
 /*
 ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h).
 */
-int numModes = 27;
-static char *modeStrings[27] = {"BROWSE","ZOOMIN","ZOOMOUT","MAP","LEGEND","LEGENDICON","REFERENCE","SCALEBAR","COORDINATE",
+int numModes = 28;
+static char *modeStrings[28] = {"BROWSE","ZOOMIN","ZOOMOUT","MAP","LEGEND","LEGENDICON","REFERENCE","SCALEBAR","COORDINATE",
                                 "QUERY","QUERYMAP","NQUERY","NQUERYMAP",
 			        "ITEMQUERY","ITEMQUERYMAP","ITEMNQUERY","ITEMNQUERYMAP",
 				"FEATUREQUERY","FEATUREQUERYMAP","FEATURENQUERY","FEATURENQUERYMAP",
 				"ITEMFEATUREQUERY","ITEMFEATUREQUERYMAP","ITEMFEATURENQUERY","ITEMFEATURENQUERYMAP",
-				"INDEXQUERY","INDEXQUERYMAP"};
+				"INDEXQUERY","INDEXQUERYMAP","TILE"};
 
 /*
 ** Global variables

Modified: trunk/mapserver/maptemplate.h
===================================================================
--- trunk/mapserver/maptemplate.h	2008-04-30 14:27:38 UTC (rev 7546)
+++ trunk/mapserver/maptemplate.h	2008-04-30 20:26:56 UTC (rev 7547)
@@ -38,15 +38,16 @@
 #define MAXZOOM 25
 #define MINZOOM -25
 
-enum coordSources {NONE, FROMIMGPNT, FROMIMGBOX, FROMIMGSHAPE, FROMREFPNT, FROMUSERPNT, FROMUSERBOX, FROMUSERSHAPE, FROMBUF, FROMSCALE};
+enum coordSources {NONE, FROMIMGPNT, FROMIMGBOX, FROMIMGSHAPE, FROMREFPNT, FROMUSERPNT, FROMUSERBOX, FROMUSERSHAPE, FROMBUF, FROMSCALE, FROMTILE};
 
 enum modes {BROWSE, ZOOMIN, ZOOMOUT, MAP, LEGEND, LEGENDICON, REFERENCE, SCALEBAR, COORDINATE, 
             QUERY, QUERYMAP, NQUERY, NQUERYMAP, 
             ITEMQUERY, ITEMQUERYMAP, ITEMNQUERY, ITEMNQUERYMAP, 
             FEATUREQUERY, FEATUREQUERYMAP, FEATURENQUERY, FEATURENQUERYMAP, 
-            ITEMFEATUREQUERY, ITEMFEATUREQUERYMAP,ITEMFEATURENQUERY,ITEMFEATURENQUERYMAP,
-            INDEXQUERY,INDEXQUERYMAP};
+            ITEMFEATUREQUERY, ITEMFEATUREQUERYMAP, ITEMFEATURENQUERY, ITEMFEATURENQUERYMAP,
+            INDEXQUERY, INDEXQUERYMAP, TILE};
 
+
 /*! \srtuct mapservObj
  *  \brief Global structur used by template and mapserv
  * 
@@ -93,6 +94,11 @@
    /* can be BROWSE, QUERY, etc. */
    int Mode; 
    
+   /* can be SPHEREMERC */
+   int TileMode;
+   /* three integral coordinates, X, Y, Zoom */
+   long *TileCoords;
+   
    /* big enough for time + pid */
    char Id[IDSIZE]; 
    

Added: trunk/mapserver/maptile.c
===================================================================
--- trunk/mapserver/maptile.c	                        (rev 0)
+++ trunk/mapserver/maptile.c	2008-04-30 20:26:56 UTC (rev 7547)
@@ -0,0 +1,213 @@
+/******************************************************************************
+ * $Id$ 
+ *
+ * Project:  MapServer
+ * Purpose:  MapServer Tile Access API
+ * Author:   Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ ******************************************************************************
+ * Copyright (c) 2008, Paul Ramsey
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
+ * all copies of this Software or works derived from this Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "maptile.h"
+#include "mapproject.h"
+
+/************************************************************************
+ *                            msTileSetup                               *
+ *                                                                      * 
+ *  Called from mapserv.c, this is where the fun begins                 *
+ *  Set up projections and test the parameters for legality.            *
+ ************************************************************************/
+int msTileSetup(mapservObj* msObj) {
+#ifdef USE_TILE_API 
+
+  char *outProjStr = NULL;
+
+  /* 
+  ** Ensure all the LAYERs have a projection. 
+  **/  
+  if( msTileSetProjections(msObj->Map) != 0 ) {
+    return(MS_FAILURE);
+  }
+
+  /* 
+  ** Set the projection string for this mode. 
+  **/
+  if( msObj->TileMode == SPHEREMERC ) {
+    outProjStr = SPHEREMERC_PROJ4;
+  } else {
+    return(MS_FAILURE); /* Huh? No mode? */
+  }
+  if( msLoadProjectionString(&(msObj->Map->projection), outProjStr) != 0 ) {
+    msSetError(MS_CGIERR, "Unable to load projection string.", "msTileSetExtent()");
+    return(MS_FAILURE);
+  }
+  
+  /*
+  ** Set up the output extents for this tilemode and tile coordinates 
+  **/
+  if( msObj->TileMode == SPHEREMERC ) {
+    
+    int x = msObj->TileCoords[0];
+    int y = msObj->TileCoords[1];
+    int zoom = msObj->TileCoords[2];
+    double zoomfactor = pow(2.0, (double)zoom);
+    
+    /*
+    ** Check the input request for sanity.
+    **/
+    if( x >= zoomfactor || y >= zoomfactor ) {
+      msSetError(MS_CGIERR, "Tile coordinates are too large for supplied zoom.", "msTileSetExtent()");
+      return(MS_FAILURE);
+    }
+    if( x < 0 || y < 0 ) {
+      msSetError(MS_CGIERR, "Tile coordinates should not be less than zero.", "msTileSetExtent()");
+      return(MS_FAILURE);
+    }
+
+    /* 
+    ** Set the output tile size.
+    **/
+    msObj->ImgCols = SPHEREMERC_IMAGE_SIZE;
+    msObj->ImgRows = SPHEREMERC_IMAGE_SIZE;
+    msObj->Map->width = SPHEREMERC_IMAGE_SIZE;
+    msObj->Map->height = SPHEREMERC_IMAGE_SIZE;
+
+  }
+  else {
+    return(MS_FAILURE); /* Huh? Should have a mode. */
+  }
+  
+  return MS_SUCCESS;
+#else
+  msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetExtent()");
+  return(MS_FAILURE);
+#endif
+}
+
+/************************************************************************
+ *                            msTileSetExtent                           *
+ *                                                                      * 
+ *  Called from setExtent() in maptemplate.c.                           *
+ ************************************************************************/
+int msTileSetExtent(mapservObj* msObj) {
+#ifdef USE_TILE_API 
+  
+  mapObj *map = msObj->Map;
+
+  if( msObj->TileMode == SPHEREMERC ) {
+    
+    int x = msObj->TileCoords[0];
+    int y = msObj->TileCoords[1];
+    int zoom = msObj->TileCoords[2];
+    double zoomfactor = pow(2.0, (double)zoom);
+    
+    /*
+     * Calculate the ground extents of the tile request.
+     */
+//    printf("X: %i  Y: %i  Z: %i\n",x,y,zoom);
+    double tilesize = SPHEREMERC_GROUND_SIZE / zoomfactor;
+    double xmin = (x * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0);
+    double xmax = ((x + 1) * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0);
+    double ymin = (SPHEREMERC_GROUND_SIZE / 2.0) - ((y + 1) * tilesize);
+    double ymax = (SPHEREMERC_GROUND_SIZE / 2.0) - (y * tilesize);
+    
+    map->extent.minx = xmin;
+    map->extent.maxx = xmax;
+    map->extent.miny = ymin;
+    map->extent.maxy = ymax;
+
+    /* 
+     * Set the output tile size.
+     */
+    msObj->ImgCols = SPHEREMERC_IMAGE_SIZE;
+    msObj->ImgRows = SPHEREMERC_IMAGE_SIZE;
+    map->width = SPHEREMERC_IMAGE_SIZE;
+    map->height = SPHEREMERC_IMAGE_SIZE;
+
+    /* 
+     * Adjust the extents inwards by 1/2 pixel so they are from
+     * center-of-pixel to center-of-pixel, instead of edge-to-edge.
+     * This is the way mapserver does it.
+     */
+    double	dx, dy;
+    dx = (map->extent.maxx - map->extent.minx) / map->width;
+    map->extent.minx += dx*0.5;
+    map->extent.maxx -= dx*0.5;
+    dy = (map->extent.maxy - map->extent.miny) / map->height;
+    map->extent.miny += dy*0.5;
+    map->extent.maxy -= dy*0.5;
+    
+  }
+  else {
+    return(MS_FAILURE); /* Huh? Should have a mode. */
+  }
+  
+  return MS_SUCCESS;
+#else
+  msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetExtent()");
+  return(MS_FAILURE);
+#endif
+}
+
+/************************************************************************
+ *                            msTileSetProjections                      *
+ *                                                                      * 
+ *   Ensure that all the layers in the map file have a projection       *
+ *   by copying the map-level projection to all layers than have no     *
+ *   projection.                                                        *
+ ************************************************************************/
+
+int msTileSetProjections(mapObj* map) {
+
+  char *mapProjStr = NULL;
+  
+  if (map->projection.numargs <= 0) {
+    msSetError(MS_WMSERR, "Cannot set new SRS on a map that doesn't "
+                          "have any projection set. Please make sure your mapfile "
+                          "has a PROJECTION defined at the top level.", 
+                          "msTileSetExtent()");
+    return(MS_FAILURE);
+  }
+  int i;
+  for(i=0; i<map->numlayers; i++) {
+    /* This layer is turned on and needs a projection? */
+    if (GET_LAYER(map, i)->projection.numargs <= 0 &&
+        GET_LAYER(map, i)->status != MS_OFF &&
+        GET_LAYER(map, i)->transform == MS_TRUE) {
+   
+      /* Fetch main map projection string only now that we need it */
+      if (mapProjStr == NULL)
+        mapProjStr = msGetProjectionString(&(map->projection));
+      
+      /* Set the projection to the map file projection */  
+      if (msLoadProjectionString(&(GET_LAYER(map, i)->projection), mapProjStr) != 0) {
+        msSetError(MS_CGIERR, "Unable to set projection on layer.", "msTileSetExtent()");
+        return(MS_FAILURE);
+      }
+      GET_LAYER(map, i)->project = MS_TRUE;
+    }
+  }
+  msFree(mapProjStr);
+  return(MS_SUCCESS);
+}
+
+

Added: trunk/mapserver/maptile.h
===================================================================
--- trunk/mapserver/maptile.h	                        (rev 0)
+++ trunk/mapserver/maptile.h	2008-04-30 20:26:56 UTC (rev 7547)
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * $Id$ 
+ *
+ * Project:  MapServer
+ * Purpose:  MapServer Tile Access API
+ * Author:   Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ ******************************************************************************
+ * Copyright (c) 2008, Paul Ramsey
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
+ * all copies of this Software or works derived from this Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+ 
+#include "mapserver.h"
+#include "maptemplate.h"
+
+/* TODO: add this to build environment */
+#define USE_TILE_API 1
+
+#define SPHEREMERC_PROJ4 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +units=m +k=1.0 +nadgrids=@null"
+#define SPHEREMERC_GROUND_SIZE (20037508.34*2)
+#define SPHEREMERC_IMAGE_SIZE 256
+
+enum tileModes {SPHEREMERC};
+ 
+MS_DLL_EXPORT int msTileSetup(mapservObj *msObj); 
+MS_DLL_EXPORT int msTileSetExtent(mapservObj *msObj); 
+MS_DLL_EXPORT int msTileSetProjections(mapObj *map);
+
+



More information about the mapserver-commits mailing list