[mapserver-commits] r12291 - trunk/mapserver/mapcache/src

svn at osgeo.org svn at osgeo.org
Fri Aug 26 07:14:19 EDT 2011


Author: tbonfort
Date: 2011-08-26 04:14:19 -0700 (Fri, 26 Aug 2011)
New Revision: 12291

Added:
   trunk/mapserver/mapcache/src/service_kml.c
Modified:
   trunk/mapserver/mapcache/src/configuration.c
Log:
add initial support for "full" WMS requests.
fixes issue 9.
thomas.bonfort | 2011-02-03 16:06:19 +0100 (Thu, 03 Feb 2011)

Modified: trunk/mapserver/mapcache/src/configuration.c
===================================================================
--- trunk/mapserver/mapcache/src/configuration.c	2011-08-26 11:14:14 UTC (rev 12290)
+++ trunk/mapserver/mapcache/src/configuration.c	2011-08-26 11:14:19 UTC (rev 12291)
@@ -786,18 +786,21 @@
          config->services[GEOCACHE_SERVICE_WMTS] = geocache_service_wmts_create(ctx);
       }
    }
-   /*
-   if ((node = ezxml_child(root,"kml")) != NULL) {
+   if ((node = ezxml_child(root,"tms")) != NULL) {
       if(!node->txt || !*node->txt || strcmp(node->txt, "false")) {
-         config->services[GEOCACHE_SERVICE_KML] = geocache_service_kml_create(ctx);
+         config->services[GEOCACHE_SERVICE_TMS] = geocache_service_tms_create(ctx);
       }
    }
-   */
-   if ((node = ezxml_child(root,"tms")) != NULL) {
+   if ((node = ezxml_child(root,"kml")) != NULL) {
       if(!node->txt || !*node->txt || strcmp(node->txt, "false")) {
-         config->services[GEOCACHE_SERVICE_TMS] = geocache_service_tms_create(ctx);
+         if(!config->services[GEOCACHE_SERVICE_TMS]) {
+            ctx->set_error(ctx,400,"kml service requires the tms service to be active");
+            return;
+         }
+         config->services[GEOCACHE_SERVICE_KML] = geocache_service_kml_create(ctx);
       }
    }
+
    if ((node = ezxml_child(root,"gmaps")) != NULL) {
       if(!node->txt || !*node->txt || strcmp(node->txt, "false")) {
          config->services[GEOCACHE_SERVICE_GMAPS] = geocache_service_gmaps_create(ctx);
@@ -826,6 +829,12 @@
    if (doc == NULL) {
       ctx->set_error(ctx,400, "failed to parse file %s. Is it valid XML?", filename);
       goto cleanup;
+   } else {
+      const char *err = ezxml_error(doc);
+      if(err && *err) {
+         ctx->set_error(ctx,400, "failed to parse file %s: %s", filename, err);
+         goto cleanup;
+      }
    }
 
    if(strcmp(doc->name,"geocache")) {

Added: trunk/mapserver/mapcache/src/service_kml.c
===================================================================
--- trunk/mapserver/mapcache/src/service_kml.c	                        (rev 0)
+++ trunk/mapserver/mapcache/src/service_kml.c	2011-08-26 11:14:19 UTC (rev 12291)
@@ -0,0 +1,236 @@
+/*
+ *  Copyright 2010 Thomas Bonfort
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "geocache.h"
+#include <apr_strings.h>
+#include <math.h>
+
+/** \addtogroup services */
+/** @{ */
+
+
+void _create_capabilities_kml(geocache_context *ctx, geocache_request_get_capabilities *req, char *url, char *path_info, geocache_cfg *cfg) {
+   geocache_request_get_capabilities_kml *request = (geocache_request_get_capabilities_kml*)req;
+   char *caps;
+   const char *onlineresource = apr_table_get(cfg->metadata,"url");
+   double bbox[4];  
+   if(!onlineresource) {
+      onlineresource = url;
+   }
+   request->request.mime_type = apr_pstrdup(ctx->pool,"application/vnd.google-earth.kml+xml");
+
+   geocache_tileset_tile_bbox(request->tile,bbox);
+
+
+   caps = apr_psprintf(ctx->pool,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+         "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n"
+         "  <Document>\n"
+         "    <Region>\n"
+         "      <Lod>\n"
+         "        <minLodPixels>128</minLodPixels><maxLodPixels>%d</maxLodPixels>\n"
+         "      </Lod>\n"
+         "      <LatLonAltBox>\n"
+         "        <north>%f</north><south>%f</south>\n"
+         "        <east>%f</east><west>%f</west>\n"
+         "      </LatLonAltBox>\n"
+         "    </Region>\n"
+         "    <GroundOverlay>\n"
+         "      <drawOrder>0</drawOrder>\n"
+         "      <Icon>\n"
+         "        <href>%s/tms/1.0.0/%s@%s/%d/%d/%d.%s</href>\n"
+         "      </Icon>\n"
+         "      <LatLonBox>\n"
+         "        <north>%f</north><south>%f</south>\n"
+         "        <east>%f</east><west>%f</west>\n"
+         "      </LatLonBox>\n"
+         "    </GroundOverlay>\n",
+      (request->tile->z == request->tile->grid_link->grid->nlevels-1)?-1:512,
+      bbox[3],bbox[1],bbox[2],bbox[0],
+      onlineresource,request->tile->tileset->name,request->tile->grid_link->grid->name,
+      request->tile->z, request->tile->x,request->tile->y,
+      (request->tile->tileset->format)?request->tile->tileset->format->extension:"png",
+      bbox[3],bbox[1],bbox[2],bbox[0]);
+
+   if(request->tile->z < request->tile->grid_link->grid->nlevels-1) {
+      int i,j;
+      for(i=0;i<=1;i++) {
+         for(j=0;j<=1;j++) {
+            geocache_tile *t = geocache_tileset_tile_create(ctx->pool,request->tile->tileset, request->tile->grid_link);
+            double bb[4];
+            t->x = (request->tile->x << 1) +i;
+            t->y = (request->tile->y << 1) +j;
+            t->z = request->tile->z + 1;
+            geocache_tileset_tile_bbox(t,bb);
+
+            caps = apr_psprintf(ctx->pool,"%s"
+                  "    <NetworkLink>\n"
+                  "      <name>%d%d%d</name>\n"
+                  "      <Region>\n"
+                  "        <Lod>\n"
+                  "          <minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>\n"
+                  "        </Lod>\n"
+                  "        <LatLonAltBox>\n"
+                  "          <north>%f</north><south>%f</south>\n"
+                  "          <east>%f</east><west>%f</west>\n"
+                  "        </LatLonAltBox>\n"
+                  "      </Region>\n"
+                  "      <Link>\n"
+                  "        <href>%s/kml/%s@%s/%d/%d/%d.kml</href>\n"
+                  "        <viewRefreshMode>onRegion</viewRefreshMode>\n"
+                  "      </Link>\n"
+                  "    </NetworkLink>\n",
+                  caps,t->x,t->y,t->z,
+                  bb[3],bb[1],bb[2],bb[0],
+                  onlineresource,request->tile->tileset->name,request->tile->grid_link->grid->name,
+                  t->z, t->x,t->y);
+         }
+      }
+   }
+
+   caps = apr_pstrcat(ctx->pool,caps,"  </Document>\n</kml>\n",NULL);
+   request->request.capabilities = caps;
+
+
+}
+
+/**
+ * \brief parse a KML request
+ * \private \memberof geocache_service_kml
+ * \sa geocache_service::parse_request()
+ */
+void _geocache_service_kml_parse_request(geocache_context *ctx, geocache_service *this, geocache_request **request,
+      const char *cpathinfo, apr_table_t *params, geocache_cfg *config) {
+   int index = 0;
+   char *last, *key, *endptr;
+   geocache_tileset *tileset = NULL;
+   geocache_grid_link *grid_link = NULL;
+   char *pathinfo;
+   int x=-1,y=-1,z=-1;
+  
+   if(cpathinfo) {
+      pathinfo = apr_pstrdup(ctx->pool,cpathinfo);
+      /* parse a path_info like /layer at grid/0/0/0.kml */
+      for (key = apr_strtok(pathinfo, "/", &last); key != NULL;
+            key = apr_strtok(NULL, "/", &last)) {
+         if(!*key) continue; /* skip an empty string, could happen if the url contains // */
+         switch(++index) {
+         case 1: /* layer name */
+            tileset = geocache_configuration_get_tileset(config,key);
+            if(!tileset) {
+               /*tileset not found directly, test if it was given as "name at grid" notation*/
+               char *tname = apr_pstrdup(ctx->pool,key);
+               char *gname = tname;
+               int i;
+               while(*gname) {
+                  if(*gname == '@') {
+                     *gname = '\0';
+                     gname++;
+                     break;
+                  }
+                  gname++;
+               }
+               if(!gname) {
+                  ctx->set_error(ctx,404, "received kml request with invalid layer %s", key);
+                  return;
+               }
+               tileset = geocache_configuration_get_tileset(config,tname);
+               if(!tileset) {
+                  ctx->set_error(ctx,404, "received kml request with invalid layer %s", tname);
+                  return;
+               }
+               for(i=0;i<tileset->grid_links->nelts;i++) {
+                  geocache_grid_link *sgrid = APR_ARRAY_IDX(tileset->grid_links,i,geocache_grid_link*);
+                  if(!strcmp(sgrid->grid->name,gname)) {
+                     grid_link = sgrid;
+                     break;
+                  }
+               }
+               if(!grid_link) {
+                  ctx->set_error(ctx,404, "received kml request with invalid grid %s", gname);
+                  return;
+               }
+
+            } else {
+               grid_link = APR_ARRAY_IDX(tileset->grid_links,0,geocache_grid_link*);
+            }
+            break;
+         case 2:
+            z = (int)strtol(key,&endptr,10);
+            if(*endptr != 0) {
+               ctx->set_error(ctx,404, "received kml request %s with invalid z %s", pathinfo, key);
+               return;
+            }
+            break;
+         case 3:
+            x = (int)strtol(key,&endptr,10);
+            if(*endptr != 0) {
+               ctx->set_error(ctx,404, "received kml request %s with invalid x %s", pathinfo, key);
+               return;
+            }
+            break;
+         case 4:
+            y = (int)strtol(key,&endptr,10);
+            if(*endptr != '.') {
+               ctx->set_error(ctx,404, "received kml request %s with invalid y %s", pathinfo, key);
+               return;
+            }
+            endptr++;
+            if(strcmp(endptr,"kml")) {
+               ctx->set_error(ctx,404, "received kml request with invalid extension %s", pathinfo, endptr);
+               return;
+            }
+            break;
+         default:
+            ctx->set_error(ctx,404, "received kml request %s with invalid parameter %s", pathinfo, key);
+            return;
+         }
+      }
+   }
+   if(index == 4) {
+      geocache_request_get_capabilities_kml *req = (geocache_request_get_capabilities_kml*)apr_pcalloc(
+            ctx->pool,sizeof(geocache_request_get_capabilities_kml));
+      req->request.request.type = GEOCACHE_REQUEST_GET_CAPABILITIES;
+      req->tile = geocache_tileset_tile_create(ctx->pool, tileset, grid_link);
+      req->tile->x = x;
+      req->tile->y = y;
+      req->tile->z = z;
+      geocache_tileset_tile_validate(ctx,req->tile);
+      GC_CHECK_ERROR(ctx);
+      *request = (geocache_request*)req;
+      return;
+   }
+   else {
+      ctx->set_error(ctx,404, "received kml request %s with wrong number of arguments", pathinfo);
+      return;
+   }
+}
+
+geocache_service* geocache_service_kml_create(geocache_context *ctx) {
+   geocache_service_kml* service = (geocache_service_kml*)apr_pcalloc(ctx->pool, sizeof(geocache_service_kml));
+   if(!service) {
+      ctx->set_error(ctx, 500, "failed to allocate kml service");
+      return NULL;
+   }
+   service->service.url_prefix = apr_pstrdup(ctx->pool,"kml");
+   service->service.type = GEOCACHE_SERVICE_KML;
+   service->service.parse_request = _geocache_service_kml_parse_request;
+   service->service.create_capabilities_response = _create_capabilities_kml;
+   return (geocache_service*)service;
+}
+
+/** @} */
+/* vim: ai ts=3 sts=3 et sw=3
+*/



More information about the mapserver-commits mailing list