void parseGrid(mapcache_context *ctx, ezxml_t node, mapcache_cfg *config) { char *name; mapcache_extent extent = {0,0,0,0}; mapcache_grid *grid; ezxml_t cur_node; char *value; name = (char*)ezxml_attr(node,"name"); if(!name || !strlen(name)) { ctx->set_error(ctx, 400, "mandatory attribute \"name\" not found in <grid>"); return; } else { name = apr_pstrdup(ctx->pool, name); /* check we don't already have a grid defined with this name */ if(mapcache_configuration_get_grid(config, name)) { ctx->set_error(ctx, 400, "duplicate grid with name \"%s\"",name); return; } } grid = mapcache_grid_create(ctx->pool); grid->name = name; if ((cur_node = ezxml_child(node,"extent")) != NULL) { double *values; int nvalues; value = apr_pstrdup(ctx->pool,cur_node->txt); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, value, NULL, &values, &nvalues) || nvalues != 4) { ctx->set_error(ctx, 400, "failed to parse extent array %s." "(expecting 4 space separated numbers, got %d (%f %f %f %f)" "eg <extent>-180 -90 180 90</extent>", value,nvalues,values[0],values[1],values[2],values[3]); return; } extent.minx = values[0]; extent.miny = values[1]; extent.maxx = values[2]; extent.maxy = values[3]; } if ((cur_node = ezxml_child(node,"metadata")) != NULL) { parseMetadata(ctx, cur_node, grid->metadata); GC_CHECK_ERROR(ctx); } if ((cur_node = ezxml_child(node,"units")) != NULL) { if(!strcasecmp(cur_node->txt,"dd")) { grid->unit = MAPCACHE_UNIT_DEGREES; } else if(!strcasecmp(cur_node->txt,"m")) { grid->unit = MAPCACHE_UNIT_METERS; } else if(!strcasecmp(cur_node->txt,"ft")) { grid->unit = MAPCACHE_UNIT_FEET; } else { ctx->set_error(ctx, 400, "unknown unit %s for grid %s (valid values are \"dd\", \"m\", and \"ft\"", cur_node->txt, grid->name); return; } } if ((cur_node = ezxml_child(node,"srs")) != NULL) { grid->srs = apr_pstrdup(ctx->pool,cur_node->txt); } for(cur_node = ezxml_child(node,"srsalias"); cur_node; cur_node = cur_node->next) { value = apr_pstrdup(ctx->pool,cur_node->txt); APR_ARRAY_PUSH(grid->srs_aliases,char*) = value; } if ((cur_node = ezxml_child(node,"origin")) != NULL) { if(!strcasecmp(cur_node->txt,"top-left")) { grid->origin = MAPCACHE_GRID_ORIGIN_TOP_LEFT; } else if(!strcasecmp(cur_node->txt,"bottom-left")) { grid->origin = MAPCACHE_GRID_ORIGIN_BOTTOM_LEFT; } else if(!strcasecmp(cur_node->txt,"top-right")) { grid->origin = MAPCACHE_GRID_ORIGIN_TOP_RIGHT; } else if(!strcasecmp(cur_node->txt,"bottom-right")) { grid->origin = MAPCACHE_GRID_ORIGIN_BOTTOM_RIGHT; } else { ctx->set_error(ctx, 400, "unknown origin %s for grid %s (valid values are \"top-left\", \"bottom-left\", \"top-right\" and \"bottom-right\"", cur_node->txt, grid->name); return; } if(grid->origin == MAPCACHE_GRID_ORIGIN_BOTTOM_RIGHT || grid->origin == MAPCACHE_GRID_ORIGIN_TOP_RIGHT) { ctx->set_error(ctx,500,"grid origin %s not implemented",cur_node->txt); return; } } if ((cur_node = ezxml_child(node,"size")) != NULL) { int *sizes, nsizes; value = apr_pstrdup(ctx->pool,cur_node->txt); if(MAPCACHE_SUCCESS != mapcache_util_extract_int_list(ctx, value, NULL, &sizes, &nsizes) || nsizes != 2) { ctx->set_error(ctx, 400, "failed to parse size array %s in grid %s" "(expecting two space separated integers, eg <size>256 256</size>", value, grid->name); return; } grid->tile_sx = sizes[0]; grid->tile_sy = sizes[1]; } if ((cur_node = ezxml_child(node,"resolutions")) != NULL) { int nvalues; double *values; value = apr_pstrdup(ctx->pool,cur_node->txt); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, value, NULL, &values, &nvalues) || !nvalues) { ctx->set_error(ctx, 400, "failed to parse resolutions array %s." "(expecting space separated numbers, " "eg <resolutions>1 2 4 8 16 32</resolutions>", value); return; } grid->nlevels = nvalues; grid->levels = (mapcache_grid_level**)apr_pcalloc(ctx->pool, grid->nlevels*sizeof(mapcache_grid_level)); while(nvalues--) { double unitheight; double unitwidth; mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(ctx->pool,sizeof(mapcache_grid_level)); level->resolution = values[nvalues]; unitheight = grid->tile_sy * level->resolution; unitwidth = grid->tile_sx * level->resolution; level->maxy = ceil((extent.maxy-extent.miny - 0.01* unitheight)/unitheight); level->maxx = ceil((extent.maxx-extent.minx - 0.01* unitwidth)/unitwidth); grid->levels[nvalues] = level; } } if(grid->srs == NULL) { ctx->set_error(ctx, 400, "grid \"%s\" has no srs configured." " You must add a <srs> tag.", grid->name); return; } if(extent.minx >= extent.maxx || extent.miny >= extent.maxy) { ctx->set_error(ctx, 400, "grid \"%s\" has no (or invalid) extent configured" " You must add/correct a <extent> tag.", grid->name); return; } else { grid->extent = extent; } if(grid->tile_sx <= 0 || grid->tile_sy <= 0) { ctx->set_error(ctx, 400, "grid \"%s\" has no (or invalid) tile size configured" " You must add/correct a <size> tag.", grid->name); return; } if(!grid->nlevels) { ctx->set_error(ctx, 400, "grid \"%s\" has no resolutions configured." " You must add a <resolutions> tag.", grid->name); return; } mapcache_configuration_add_grid(config,grid,name); }
mapcache_cfg* mapcache_configuration_create(apr_pool_t *pool) { mapcache_grid *grid; int i; double wgs84_resolutions[18]= { 0.703125000000000, 0.351562500000000, 0.175781250000000, 8.78906250000000e-2, 4.39453125000000e-2, 2.19726562500000e-2, 1.09863281250000e-2, 5.49316406250000e-3, 2.74658203125000e-3, 1.37329101562500e-3, 6.86645507812500e-4, 3.43322753906250e-4, 1.71661376953125e-4, 8.58306884765625e-5, 4.29153442382812e-5, 2.14576721191406e-5, 1.07288360595703e-5, 5.36441802978516e-6 }; double google_resolutions[19] = { 156543.0339280410, 78271.51696402048, 39135.75848201023, 19567.87924100512, 9783.939620502561, 4891.969810251280, 2445.984905125640, 1222.992452562820, 611.4962262814100, 305.7481131407048, 152.8740565703525, 76.43702828517624, 38.21851414258813, 19.10925707129406, 9.554628535647032, 4.777314267823516, 2.388657133911758, 1.194328566955879, 0.5971642834779395 }; mapcache_extent wgs84_extent= {-180,-90,180,90}; mapcache_extent google_extent= {-20037508.3427892480,-20037508.3427892480,20037508.3427892480,20037508.3427892480}; double unitwidth,unitheight; mapcache_cfg *cfg = (mapcache_cfg*)apr_pcalloc(pool, sizeof(mapcache_cfg)); cfg->caches = apr_hash_make(pool); cfg->sources = apr_hash_make(pool); cfg->tilesets = apr_hash_make(pool); cfg->grids = apr_hash_make(pool); cfg->image_formats = apr_hash_make(pool); cfg->metadata = apr_table_make(pool,3); mapcache_configuration_add_image_format(cfg, mapcache_imageio_create_png_format(pool,"PNG",MAPCACHE_COMPRESSION_FAST), "PNG"); mapcache_configuration_add_image_format(cfg, mapcache_imageio_create_png_q_format(pool,"PNG8",MAPCACHE_COMPRESSION_FAST,256), "PNG8"); mapcache_configuration_add_image_format(cfg, mapcache_imageio_create_jpeg_format(pool,"JPEG",90,MAPCACHE_PHOTOMETRIC_YCBCR,MAPCACHE_OPTIMIZE_YES), "JPEG"); mapcache_configuration_add_image_format(cfg, mapcache_imageio_create_mixed_format(pool,"mixed", mapcache_configuration_get_image_format(cfg,"PNG"), mapcache_configuration_get_image_format(cfg,"JPEG"), 255), "mixed"); cfg->default_image_format = mapcache_configuration_get_image_format(cfg,"mixed"); cfg->reporting = MAPCACHE_REPORT_MSG; grid = mapcache_grid_create(pool); grid->name = apr_pstrdup(pool,"WGS84"); apr_table_add(grid->metadata,"title","GoogleCRS84Quad"); apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleCRS84Quad"); apr_table_add(grid->metadata,"profile","global-geodetic"); grid->srs = apr_pstrdup(pool,"EPSG:4326"); grid->unit = MAPCACHE_UNIT_DEGREES; grid->tile_sx = grid->tile_sy = 256; grid->nlevels = 18; grid->extent = wgs84_extent; grid->levels = (mapcache_grid_level**)apr_pcalloc(pool, grid->nlevels*sizeof(mapcache_grid_level*)); for(i=0; i<grid->nlevels; i++) { mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level)); level->resolution = wgs84_resolutions[i]; unitheight = grid->tile_sy * level->resolution; unitwidth = grid->tile_sx * level->resolution; level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight); level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth); grid->levels[i] = level; } mapcache_configuration_add_grid(cfg,grid,"WGS84"); grid = mapcache_grid_create(pool); grid->name = apr_pstrdup(pool,"GoogleMapsCompatible"); grid->srs = apr_pstrdup(pool,"EPSG:3857"); APR_ARRAY_PUSH(grid->srs_aliases,char*) = apr_pstrdup(pool,"EPSG:900913"); apr_table_add(grid->metadata,"title","GoogleMapsCompatible"); apr_table_add(grid->metadata,"profile","global-mercator"); apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible"); grid->tile_sx = grid->tile_sy = 256; grid->nlevels = 19; grid->unit = MAPCACHE_UNIT_METERS; grid->extent = google_extent; grid->levels = (mapcache_grid_level**)apr_pcalloc(pool, grid->nlevels*sizeof(mapcache_grid_level*)); for(i=0; i<grid->nlevels; i++) { mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level)); level->resolution = google_resolutions[i]; unitheight = grid->tile_sy * level->resolution; unitwidth = grid->tile_sx * level->resolution; level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight); level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth); grid->levels[i] = level; } mapcache_configuration_add_grid(cfg,grid,"GoogleMapsCompatible"); grid = mapcache_grid_create(pool); grid->name = apr_pstrdup(pool,"g"); grid->srs = apr_pstrdup(pool,"EPSG:900913"); APR_ARRAY_PUSH(grid->srs_aliases,char*) = apr_pstrdup(pool,"EPSG:3857"); apr_table_add(grid->metadata,"title","GoogleMapsCompatible"); apr_table_add(grid->metadata,"profile","global-mercator"); apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible"); grid->tile_sx = grid->tile_sy = 256; grid->nlevels = 19; grid->unit = MAPCACHE_UNIT_METERS; grid->extent = google_extent; grid->levels = (mapcache_grid_level**)apr_pcalloc(pool, grid->nlevels*sizeof(mapcache_grid_level*)); for(i=0; i<grid->nlevels; i++) { mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level)); level->resolution = google_resolutions[i]; unitheight = grid->tile_sy * level->resolution; unitwidth = grid->tile_sx * level->resolution; level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight); level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth); grid->levels[i] = level; } mapcache_configuration_add_grid(cfg,grid,"g"); cfg->loglevel = MAPCACHE_WARN; cfg->autoreload = 0; return cfg; }