[mapserver-commits] r9167 - sandbox/davidK
svn at osgeo.org
svn at osgeo.org
Sat Jul 11 16:51:03 EDT 2009
Author: davidK
Date: 2009-07-11 16:51:02 -0400 (Sat, 11 Jul 2009)
New Revision: 9167
Added:
sandbox/davidK/mapkml.cpp
sandbox/davidK/mapkml.h
sandbox/davidK/mapkmlrenderer.cpp
sandbox/davidK/mapkmlrenderer.h
Log:
Added KML renderer files mapkml.c and mapkmlrenderer.cpp
Added: sandbox/davidK/mapkml.cpp
===================================================================
--- sandbox/davidK/mapkml.cpp (rev 0)
+++ sandbox/davidK/mapkml.cpp 2009-07-11 20:51:02 UTC (rev 9167)
@@ -0,0 +1,211 @@
+#include "mapserver.h"
+#include "mapkmlrenderer.h"
+
+#include "mapkml.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+KmlRenderer* getKmlRenderer(imageObj* img)
+{
+ return (KmlRenderer*) img->img.plugin;
+}
+
+imageObj* msCreateImageKml(int width, int height, outputFormatObj *format, colorObj* bg)
+{
+ imageObj *image = NULL;
+
+ image = (imageObj*)malloc(sizeof(imageObj));
+ memset(image, 0, sizeof(imageObj));
+
+ KmlRenderer *ren = new KmlRenderer(width, height, bg);
+ image->img.plugin = (void *) ren;
+
+ return image;
+}
+
+int msSaveImageKml(imageObj *img, FILE *fp, outputFormatObj *format)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ return renderer->saveImage(img, fp, format);
+}
+
+void msRenderLineKml(imageObj *img, shapeObj *p, strokeStyleObj *style)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->renderLine(img, p, style);
+}
+
+void msRenderPolygonKml(imageObj *img, shapeObj *p, colorObj *color)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->renderPolygon(img, p, color);
+}
+
+void msRenderPolygonTiledKml(imageObj *img, shapeObj *p, imageObj *tile)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+}
+
+void msRenderLineTiledKml(imageObj *img, shapeObj *p, imageObj *tile)
+{
+}
+
+void msRenderGlyphsKml(imageObj *img, double x, double y,
+ labelStyleObj *style, char *text)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->renderGlyphs(img, x, y, style, text);
+}
+
+void msRenderGlyphsLineKml(imageObj *img,labelPathObj *labelpath,
+ labelStyleObj *style, char *text)
+{
+}
+
+void msRenderVectorSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+}
+
+void* msCreateVectorSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+ return NULL;
+}
+
+void msRenderPixmapSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->renderPixmapSymbol(img, x, y, symbol, style);
+}
+
+void* msCreatePixmapSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+ return NULL;
+}
+
+void msRenderEllipseSymbolKml(imageObj *image, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+}
+
+void* msCreateEllipseSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+ return NULL;
+}
+
+void msRenderTruetypeSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+}
+
+void* msCreateTruetypeSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style)
+{
+ return NULL;
+}
+
+void msRenderTileKml(imageObj *img, imageObj *tile, double x, double y)
+{
+}
+
+void msGetRasterBufferKml(imageObj *img,rasterBufferObj *rb)
+{
+}
+
+void msMergeRasterBufferKml(imageObj *dest, rasterBufferObj *overlay, double opacity, int dstX, int dstY)
+{
+}
+
+int msGetTruetypeTextBBoxKml(imageObj *img,char *font, double size, char *string,
+ rectObj *rect, double **advances)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ return renderer->getTruetypeTextBBox(img, font, size, string, rect, advances);
+}
+
+void msStartNewLayerKml(imageObj *img, layerObj *layer)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->startNewLayer(img, layer);
+}
+
+void msCloseNewLayerKml(imageObj *img, layerObj *layer)
+{
+ KmlRenderer* renderer = getKmlRenderer(img);
+ renderer->closeNewLayer(img, layer);
+}
+
+void msTransformShapeKml(shapeObj *shape, rectObj extend, double cellsize)
+{
+}
+
+void msFreeImageKml(imageObj *image)
+{
+ KmlRenderer* renderer = getKmlRenderer(image);
+ if (renderer)
+ {
+ delete renderer;
+ }
+ image->img.plugin=NULL;
+}
+
+void msFreeTileKml(imageObj *tile)
+{
+}
+
+void msFreeSymbolKml(symbolObj *symbol)
+{
+}
+
+int msPopulateRendererVTableKML( rendererVTableObj *renderer )
+{
+#ifdef USE_KML
+
+ renderer->supports_transparent_layers = 1;
+ renderer->supports_pixel_buffer = 0;
+ renderer->supports_imagecache = 0;
+
+ renderer->startNewLayer = msStartNewLayerKml;
+ renderer->closeNewLayer = msCloseNewLayerKml;
+ renderer->renderLine=&msRenderLineKml;
+ renderer->createImage=&msCreateImageKml;
+ renderer->saveImage=&msSaveImageKml;
+ renderer->transformShape=&msTransformShapeKml;
+ renderer->renderPolygon=&msRenderPolygonKml;
+ renderer->renderGlyphs=&msRenderGlyphsKml;
+ renderer->renderGlyphsLine = &msRenderGlyphsLineKml;
+ renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml;
+ renderer->renderVectorSymbol = &msRenderVectorSymbolKml;
+ renderer->renderPixmapSymbol = &msRenderPixmapSymbolKml;
+ renderer->renderTruetypeSymbol = &msRenderTruetypeSymbolKml;
+ renderer->getRasterBuffer = &msGetRasterBufferKml;
+ renderer->mergeRasterBuffer = &msMergeRasterBufferKml;
+ renderer->getTruetypeTextBBox = &msGetTruetypeTextBBoxKml;
+ renderer->createPixmapSymbolTile = &msCreatePixmapSymbolTileKml;
+ renderer->createVectorSymbolTile = &msCreateVectorSymbolTileKml;
+ renderer->createEllipseSymbolTile = &msCreateEllipseSymbolTileKml;
+ renderer->createTruetypeSymbolTile = &msCreateTruetypeSymbolTileKml;
+ renderer->renderTile = &msRenderTileKml;
+ renderer->renderPolygonTiled = &msRenderPolygonTiledKml;
+ renderer->renderLineTiled = &msRenderLineTiledKml;
+ renderer->freeTile = &msFreeTileKml;
+ renderer->freeSymbol = &msFreeSymbolKml;
+ renderer->freeImage=&msFreeImageKml;
+
+ return MS_SUCCESS;
+#else
+ msSetError(MS_MISCERR, "KML Driver requested but is not built in",
+ "msPopulateRendererVTableKML()");
+ return MS_FAILURE;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
Added: sandbox/davidK/mapkml.h
===================================================================
--- sandbox/davidK/mapkml.h (rev 0)
+++ sandbox/davidK/mapkml.h 2009-07-11 20:51:02 UTC (rev 9167)
@@ -0,0 +1,64 @@
+#ifndef MAPKML_H
+#define MAPKML_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mapserver.h"
+
+imageObj* msCreateImageKml(int width, int height, outputFormatObj *format, colorObj* bg);
+int msSaveImageKml(imageObj *img, FILE *fp, outputFormatObj *format);
+void msRenderLineKml(imageObj *img, shapeObj *p, strokeStyleObj *style);
+void msRenderPolygonKml(imageObj *img, shapeObj *p, colorObj *color);
+void msRenderPolygonTiledKml(imageObj *img, shapeObj *p, imageObj *tile);
+void msRenderLineTiledKml(imageObj *img, shapeObj *p, imageObj *tile);
+void msRenderGlyphsKml(imageObj *img, double x, double y,
+ labelStyleObj *style, char *text);
+
+void msRenderGlyphsLineKml(imageObj *img,labelPathObj *labelpath,
+ labelStyleObj *style, char *text);
+
+void msRenderVectorSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void* msCreateVectorSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void msRenderPixmapSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void* msCreatePixmapSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void msRenderEllipseSymbolKml(imageObj *image, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void* msCreateEllipseSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void msRenderTruetypeSymbolKml(imageObj *img, double x, double y,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void* msCreateTruetypeSymbolTileKml(int width, int height,
+ symbolObj *symbol, symbolStyleObj *style);
+
+void msRenderTileKml(imageObj *img, imageObj *tile, double x, double y);
+void msGetRasterBufferKml(imageObj *img,rasterBufferObj *rb);
+
+void msMergeRasterBufferKml(imageObj *dest, rasterBufferObj *overlay, double opacity, int dstX, int dstY);
+int msGetTruetypeTextBBoxKml(imageObj *img,char *font, double size, char *string,
+ rectObj *rect, double **advances);
+
+void msStartNewLayerKml(imageObj *img, layerObj *layer);
+void msCloseNewLayerKml(imageObj *img, layerObj *layer);
+void msTransformShapeKml(shapeObj *shape, rectObj extend, double cellsize);
+void msFreeImageKml(imageObj *image);
+void msFreeTileKml(imageObj *tile);
+void msFreeSymbolKml(symbolObj *symbol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAPKML_H */
\ No newline at end of file
Added: sandbox/davidK/mapkmlrenderer.cpp
===================================================================
--- sandbox/davidK/mapkmlrenderer.cpp (rev 0)
+++ sandbox/davidK/mapkmlrenderer.cpp 2009-07-11 20:51:02 UTC (rev 9167)
@@ -0,0 +1,733 @@
+#ifdef USE_KML
+
+#include "mapserver.h"
+#include "maperror.h"
+#include "mapkmlrenderer.h"
+#include "mapio.h"
+
+#define LAYER_FOLDER_STYLE "LayerFolder"
+#define LAYER_FOLDER_STYLE_URL "#LayerFolder"
+
+KmlRenderer::KmlRenderer(int width, int height, colorObj* color/*=NULL*/)
+ : XmlDoc(NULL), LayerNode(NULL), Width(width), Height(height),
+ FirstLayer(true), RasterizerOutputFormat(NULL),
+ VectorMode(true), RasterMode(false), MapCellsize(1.0)
+{
+ // Create document.
+ XmlDoc = xmlNewDoc(BAD_CAST "1.0");
+
+ xmlNodePtr rootNode = xmlNewNode(NULL, BAD_CAST "kml");
+
+ // Name spaces
+ xmlSetNs(rootNode, xmlNewNs(rootNode, BAD_CAST "http://www.opengis.net/kml/2.2", NULL));
+
+ xmlDocSetRootElement(XmlDoc, rootNode);
+
+ DocNode = xmlNewChild(rootNode, NULL, BAD_CAST "Document", NULL);
+
+ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL);
+ xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST LAYER_FOLDER_STYLE);
+ xmlNodePtr listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL);
+ xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "checkHideChildren");
+
+ StyleHashTable = msCreateHashTable();
+}
+
+KmlRenderer::~KmlRenderer()
+{
+ if (XmlDoc)
+ xmlFreeDoc(XmlDoc);
+
+ if (StyleHashTable)
+ msFreeHashTable(StyleHashTable);
+
+ xmlCleanupParser();
+
+ if (RasterizerOutputFormat)
+ msFreeOutputFormat(RasterizerOutputFormat);
+}
+
+imageObj* KmlRenderer::createInternalImage()
+{
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ imageObj *img = r->createImage(Width, Height, RasterizerOutputFormat, NULL);
+
+ return img;
+}
+
+imageObj* KmlRenderer::createImage(int width, int height, outputFormatObj *format, colorObj* bg)
+{
+ return NULL;
+}
+
+int KmlRenderer::saveImage(imageObj *img, FILE *fp, outputFormatObj *format)
+{
+ //
+ if (InternalImg)
+ {
+ char fileName[512];
+
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+
+ //FILE *stream = fopen(msBuildPath(szPath, map->mappath, filename), "wb");
+
+ sprintf(fileName, "kml_ground_overlay_%ld%d.%s", (long)time(NULL), (int)getpid(), MS_IMAGE_EXTENSION(RasterizerOutputFormat)); // __TODO__ add WEB IMAGEURL path;
+ FILE *stream = fopen(fileName, "wb");
+
+ if(r->supports_pixel_buffer)
+ {
+ rasterBufferObj data;
+ r->getRasterBuffer(InternalImg,&data);
+ msSaveRasterBuffer(&data, stream, RasterizerOutputFormat );
+ }
+ else
+ {
+ r->saveImage(InternalImg, stream, RasterizerOutputFormat);
+ }
+ fclose(stream);
+
+ createGroundOverlayNode(fileName);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Write out the document. */
+ /* -------------------------------------------------------------------- */
+
+ int bufSize = 0;
+ xmlChar *buf = NULL;
+ msIOContext *context = NULL;
+
+ if( msIO_needBinaryStdout() == MS_FAILURE )
+ return MS_FAILURE;
+
+ xmlDocDumpFormatMemoryEnc(XmlDoc, &buf, &bufSize, "ISO-8859-1", 1);
+
+ context = msIO_getHandler(fp);
+ if (context)
+ msIO_printf("Content-type: %s%c%c",format->mimetype,10,10);
+
+
+ int chunkSize = 4096;
+ for (int i=0; i<bufSize; i+=chunkSize)
+ {
+ int size = chunkSize;
+ if (i + size > bufSize)
+ size = bufSize - i;
+
+ if (context)
+ msIO_contextWrite(context, buf+i, size);
+ else
+ msIO_fwrite(buf+i, 1, size, fp);
+ }
+
+ //msIO_fprintf(fp, "%s", buffer);
+
+ xmlFree(buf);
+
+ return(MS_SUCCESS);
+}
+
+void KmlRenderer::freeImage(imageObj *image)
+{
+}
+
+void KmlRenderer::setupRenderingParams(hashTableObj *layerMetadata)
+{
+ AltitudeMode = 0;
+ Extrude = 0;
+ Tessellate = 0;
+
+ char *altitudeModeVal = msLookupHashTable(layerMetadata, "kml_altitudeMode");
+ if (altitudeModeVal)
+ {
+ if(strcasecmp(altitudeModeVal, "absolute") == 0)
+ AltitudeMode = absolute;
+ else if(strcasecmp(altitudeModeVal, "relativeToGround") == 0)
+ AltitudeMode = relativeToGround;
+ else if(strcasecmp(altitudeModeVal, "clampToGround") == 0)
+ AltitudeMode = clampToGround;
+ }
+
+ char *extrudeVal = msLookupHashTable(layerMetadata, "kml_extrude");
+ if (altitudeModeVal)
+ {
+ Extrude = atoi(extrudeVal);
+ }
+
+ char *tessellateVal = msLookupHashTable(layerMetadata, "kml_tessellate");
+ if (tessellateVal)
+ {
+ Tessellate = atoi(tessellateVal);
+ }
+}
+
+int KmlRenderer::checkProjection(projectionObj *projection)
+{
+#ifdef USE_PROJ
+ if (projection && projection->numargs > 0 && pj_is_latlong(projection->proj))
+ {
+ char *projStr = msGetProjectionString(projection);
+
+ /* is ellipsoid WGS84 or projection code epsg:4326 */
+ if (strcasestr(projStr, "WGS84") || strcasestr(projStr,"epsg:4326"))
+ {
+ return MS_SUCCESS;
+ }
+ }
+
+ msSetError(MS_PROJERR, "Mapfile projection not defined, KML output driver requires projection WGS84 (epsg:4326)", "KmlRenderer::checkProjection()" );
+ return MS_FAILURE;
+
+#else
+ msSetError(MS_MISCERR, "Projection support not enabled", "KmlRenderer::checkProjection" );
+ return MS_FAILURE;
+#endif
+}
+
+void KmlRenderer::startNewLayer(imageObj *img, layerObj *layer)
+{
+ LayerNode = xmlNewChild(DocNode, NULL, BAD_CAST "Folder", NULL);
+
+ xmlNewChild(LayerNode, NULL, BAD_CAST "name", BAD_CAST layer->name);
+
+ char *layerVisibility = layer->status != MS_OFF ? "1" : "0";
+ xmlNewChild(LayerNode, NULL, BAD_CAST "visibility", BAD_CAST layerVisibility);
+
+ xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST LAYER_FOLDER_STYLE_URL);
+
+ setupRenderingParams(&layer->metadata);
+
+ if (FirstLayer)
+ {
+ FirstLayer = false;
+
+ // map rect for ground overlay
+ MapExtent = layer->map->extent;
+ MapCellsize = layer->map->cellsize;
+
+ if (layer->map->name)
+ xmlNewChild(DocNode, NULL, BAD_CAST "name", BAD_CAST layer->map->name);
+
+ // First rendered layer - check mapfile projection
+ checkProjection(&layer->map->projection);
+
+ for (int i=0; i<layer->map->numoutputformats; i++)
+ {
+ outputFormatObj *iFormat = layer->map->outputformatlist[i];
+ if(!strcasecmp(iFormat->driver,"cairo/png"))
+ {
+ RasterizerOutputFormat = msCloneOutputFormat(iFormat);
+ InternalImg = createInternalImage();
+ }
+ }
+ }
+}
+
+void KmlRenderer::closeNewLayer(imageObj *img, layerObj *layer)
+{
+
+}
+
+xmlNodePtr KmlRenderer::createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl)
+{
+ xmlNodePtr placemarkNode = xmlNewChild(parentNode, NULL, BAD_CAST "Placemark", NULL);
+
+ if (styleUrl)
+ xmlNewChild(placemarkNode, NULL, BAD_CAST "styleUrl", BAD_CAST styleUrl);
+
+ return placemarkNode;
+}
+
+void KmlRenderer::renderLineVector(imageObj *img, shapeObj *p, strokeStyleObj *style)
+{
+ xmlNodePtr placemarkNode = createPlacemarkNode(LayerNode, lookupLineStyle(style));
+
+ if (p->numlines == 1)
+ {
+ xmlNodePtr geomNode = xmlNewChild(placemarkNode, NULL, BAD_CAST "LineString", NULL);
+ addAddRenderingSpecifications(geomNode);
+ addCoordsNode(geomNode, p->line[0].point, p->line[0].numpoints);
+ }
+ else
+ {
+ xmlNodePtr multiGeomNode = xmlNewChild(placemarkNode, NULL, BAD_CAST "MultiGeometry", NULL);
+ for (int i=0; i<p->numlines; i++)
+ {
+ xmlNodePtr lineStringNode = xmlNewChild(multiGeomNode, NULL, BAD_CAST "LineString", NULL);
+ addAddRenderingSpecifications(lineStringNode);
+ addCoordsNode(lineStringNode, p->line[i].point, p->line[i].numpoints);
+ }
+ }
+}
+
+void KmlRenderer::renderLine(imageObj *img, shapeObj *p, strokeStyleObj *style)
+{
+ if (VectorMode)
+ renderLineVector(img, p, style);
+
+ if (RasterMode)
+ {
+ shapeObj rasShape;
+
+ // internal renderer used for rasterizing
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+
+ msInitShape(&rasShape);
+ msCopyShape(p,&rasShape);
+
+ r->transformShape(&rasShape, MapExtent, MapCellsize);
+
+ r->renderLine(InternalImg, &rasShape, style);
+ msFreeShape(&rasShape);
+ }
+}
+
+void KmlRenderer::renderPolygonVector(imageObj *img, shapeObj *p, colorObj *color)
+{
+ xmlNodePtr placemarkNode = createPlacemarkNode(LayerNode, lookupPolyStyle(color));
+ xmlNodePtr polygonNode = xmlNewChild(placemarkNode, NULL, BAD_CAST "Polygon", NULL);
+
+ for (int i=0; i<p->numlines; i++)
+ {
+ xmlNodePtr bdryNode = NULL;
+
+ if (i==0) // __TODO__ check ring order
+ bdryNode = xmlNewChild(polygonNode, NULL, BAD_CAST "outerBoundaryIs", NULL);
+ else
+ bdryNode = xmlNewChild(polygonNode, NULL, BAD_CAST "innerBoundaryIs", NULL);
+
+ xmlNodePtr ringNode = xmlNewChild(bdryNode, NULL, BAD_CAST "LinearRing", NULL);
+ addAddRenderingSpecifications(ringNode);
+ addCoordsNode(ringNode, p->line[i].point, p->line[i].numpoints);
+ }
+}
+
+void KmlRenderer::renderPolygon(imageObj *img, shapeObj *p, colorObj *color)
+{
+ if (VectorMode)
+ renderPolygonVector(img, p, color);
+
+ if (RasterMode)
+ {
+ shapeObj rasShape;
+
+ // internal renderer used for rasterizing
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+
+ msInitShape(&rasShape);
+ msCopyShape(p,&rasShape);
+
+ r->transformShape(&rasShape, MapExtent, MapCellsize);
+
+ r->renderPolygon(InternalImg, &rasShape, color);
+ msFreeShape(&rasShape);
+ }
+}
+
+void KmlRenderer::addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts)
+{
+ char lineBuf[128];
+
+ xmlNodePtr coordsNode = xmlNewChild(parentNode, NULL, BAD_CAST "coordinates", NULL);
+ xmlNodeAddContent(coordsNode, BAD_CAST "\n");
+
+ for (int i=0; i<numPts; i++)
+ {
+ if (AltitudeMode == relativeToGround || AltitudeMode == absolute)
+ {
+#ifdef USE_POINT_Z_M
+ sprintf(lineBuf, "\t%.8f,%.8f,%.8f\n", pts[i].x, pts[i].y, pts[i].z);
+#else
+ msSetError(MS_MISCERR, "Z coordinates support not available (mapserver not compiled with USE_POINT_Z_M option)", "KmlRenderer::addCoordsNode()");
+#endif
+ }
+ else
+ sprintf(lineBuf, "\t%.8f,%.8f\n", pts[i].x, pts[i].y);
+
+ xmlNodeAddContent(coordsNode, BAD_CAST lineBuf);
+ }
+ xmlNodeAddContent(coordsNode, BAD_CAST "\t");
+}
+
+char* KmlRenderer::lookupLineStyle(strokeStyleObj *strokeStyle)
+{
+ /*
+ <LineStyle id="ID">
+ <!-- inherited from ColorStyle -->
+ <color>ffffffff</color> <!-- kml:color -->
+ <colorMode>normal</colorMode> <!-- colorModeEnum: normal or random -->
+
+ <!-- specific to LineStyle -->
+ <width>1</width> <!-- float -->
+ </LineStyle>
+ */
+
+ char hexColor[16];
+ sprintf(hexColor,"%02x%02x%02x%02x", strokeStyle->color.alpha, strokeStyle->color.blue,
+ strokeStyle->color.green, strokeStyle->color.red);
+
+ char styleName[32];
+ sprintf(styleName, "lineStyle%s_w%.1f", hexColor, strokeStyle->width);
+
+ char *styleUrl = msLookupHashTable(StyleHashTable, styleName);
+ if (!styleUrl)
+ {
+ char styleValue[32];
+ sprintf(styleValue, "#%s", styleName);
+
+ hashObj *hash = msInsertHashTable(StyleHashTable, styleName, styleValue);
+ styleUrl = hash->data;
+
+ // Insert new PolyStyle node into Document node
+ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL);
+ xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST styleName);
+
+ xmlNodePtr lineStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "LineStyle", NULL);
+ xmlNewChild(lineStyleNode, NULL, BAD_CAST "color", BAD_CAST hexColor);
+
+ char width[16];
+ sprintf(width, "%.1f", strokeStyle->width);
+ xmlNewChild(lineStyleNode, NULL, BAD_CAST "width", BAD_CAST width);
+ }
+
+ return styleUrl;
+}
+
+char* KmlRenderer::lookupPolyStyle(colorObj *color)
+{
+ /*
+ <PolyStyle id="ID">
+ <!-- inherited from ColorStyle -->
+ <color>ffffffff</color> <!-- kml:color -->
+ <colorMode>normal</colorMode> <!-- kml:colorModeEnum: normal or random -->
+
+ <!-- specific to PolyStyle -->
+ <fill>1</fill> <!-- boolean -->
+ <outline>1</outline> <!-- boolean -->
+ </PolyStyle>
+ */
+
+ char hexColor[16];
+ sprintf(hexColor,"%02x%02x%02x%02x", color->alpha, color->blue, color->green, color->red);
+
+ char styleName[32];
+ sprintf(styleName, "polyStyle%s", hexColor);
+
+ char *styleUrl = msLookupHashTable(StyleHashTable, styleName);
+ if (!styleUrl)
+ {
+ char styleValue[32];
+ sprintf(styleValue, "#%s", styleName);
+
+ hashObj *hash = msInsertHashTable(StyleHashTable, styleName, styleValue);
+ styleUrl = hash->data;
+
+ // Insert new PolyStyle node into Document node
+ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL);
+ xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST styleName);
+
+ xmlNodePtr polyStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "PolyStyle", NULL);
+ xmlNewChild(polyStyleNode, NULL, BAD_CAST "color", BAD_CAST hexColor);
+ }
+
+ return styleUrl;
+}
+
+char* KmlRenderer::lookupPointStyle(colorObj *color)
+{
+ return NULL;
+}
+
+void KmlRenderer::renderGlyphsVector(imageObj *img, double x, double y, labelStyleObj *style, char *text)
+{
+ xmlNodePtr placemarkNode = createPlacemarkNode(LayerNode, lookupPointStyle(&style->color));
+ xmlNewChild(placemarkNode, NULL, BAD_CAST "name", BAD_CAST text);
+ xmlNodePtr pointNode = xmlNewChild(placemarkNode, NULL, BAD_CAST "Point", NULL);
+
+ addAddRenderingSpecifications(pointNode);
+
+ pointObj pt;
+ pt.x = x; pt.y = y;
+ addCoordsNode(pointNode, &pt, 1);
+}
+
+void KmlRenderer::renderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text)
+{
+ if (VectorMode)
+ renderGlyphsVector(img, x, y, style, text);
+
+ if (RasterMode)
+ {
+ // internal renderer used for rasterizing
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->renderGlyphs(InternalImg, x, y, style, text);
+ }
+}
+
+int KmlRenderer::getTruetypeTextBBox(imageObj *img,char *font, double size, char *string,
+ rectObj *rect, double **advances)
+{
+ if (VectorMode)
+ {
+ // TODO
+ rect->minx=0.0;
+ rect->maxx=0.0;
+ rect->miny=0.0;
+ rect->maxy=0.0;
+ }
+
+ if (RasterMode)
+ {
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->getTruetypeTextBBox(InternalImg, font, size, string, rect, advances);
+ }
+
+ return true;
+}
+
+void KmlRenderer::addAddRenderingSpecifications(xmlNodePtr node)
+{
+ /*
+ <extrude>0</extrude> <!-- boolean -->
+ <tessellate>0</tessellate> <!-- boolean -->
+ <altitudeMode>clampToGround</altitudeMode>
+ */
+
+ if (Extrude)
+ xmlNewChild(node, NULL, BAD_CAST "extrude", BAD_CAST "1");
+
+ if (Tessellate)
+ xmlNewChild(node, NULL, BAD_CAST "tessellate", BAD_CAST "1");
+
+ if (AltitudeMode == absolute)
+ xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "absolute");
+ else if (AltitudeMode == relativeToGround)
+ xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "relativeToGround");
+ else if (AltitudeMode == clampToGround)
+ xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "clampToGround");
+}
+
+char* KmlRenderer::lookupSymbolStyle(symbolObj *symbol, symbolStyleObj *style)
+{
+ /*
+ <Style id="randomColorIcon">
+ <IconStyle>
+ <color>ff00ff00</color>
+ <colorMode>random</colorMode>
+ <scale>1.1</scale>
+ <Icon>
+ <href>http://maps.google.com/mapfiles/kml/pal3/icon21.png</href>
+ </Icon>
+ </IconStyle>
+ </Style>
+ */
+
+ char styleName[128];
+ sprintf(styleName, "symbol_%s_%.1f", symbol->name, style->scale);
+
+ char *styleUrl = msLookupHashTable(StyleHashTable, styleName);
+ if (!styleUrl)
+ {
+ char styleValue[32];
+ sprintf(styleValue, "#%s", styleName);
+
+ hashObj *hash = msInsertHashTable(StyleHashTable, styleName, styleValue);
+ styleUrl = hash->data;
+
+ // Insert new IconStyle node into Document node
+ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL);
+ xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST styleName);
+
+ xmlNodePtr iconStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "IconStyle", NULL);
+ char scale[16];
+ sprintf(scale, "%.1f", style->scale);
+ xmlNewChild(iconStyleNode, NULL, BAD_CAST "scale", BAD_CAST scale);
+
+ char iconFileName[512];
+ sprintf(iconFileName, "symbol_%s_%.1f.%s", symbol->name, style->scale, MS_IMAGE_EXTENSION(RasterizerOutputFormat)); // __TODO__ add WEB IMAGEURL path
+ if (createIconImage(iconFileName, symbol, style) != MS_SUCCESS)
+ {
+ char errMsg[512];
+ sprintf(errMsg, "Error creating icon file '%s'", iconFileName);
+ msSetError(MS_IOERR, errMsg, "KmlRenderer::lookupSymbolStyle()" );
+ return NULL;
+ }
+
+ xmlNodePtr iconNode = xmlNewChild(iconStyleNode, NULL, BAD_CAST "Icon", NULL);
+ xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST iconFileName);
+ }
+
+ return styleUrl;
+}
+
+int KmlRenderer::createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *style)
+{
+ // internal renderer used for rasterizing
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+
+ RasterizerOutputFormat->imagemode = MS_IMAGEMODE_RGBA;
+ imageObj *tmpImg = r->createImage(symbol->sizex, symbol->sizey, RasterizerOutputFormat, NULL);
+
+ double scale = style->scale; // save symbol scale
+ style->scale = 1.0; // render symbol in default size
+
+ double cx = symbol->sizex / 2;
+ double cy = symbol->sizey / 2;
+
+ switch(symbol->type)
+ {
+ case (MS_SYMBOL_TRUETYPE):
+ r->renderTruetypeSymbol(tmpImg, cx, cy, symbol, style);
+ break;
+ case (MS_SYMBOL_PIXMAP):
+ r->renderPixmapSymbol(tmpImg, cx, cy, symbol, style);
+ break;
+ case (MS_SYMBOL_ELLIPSE):
+ r->renderEllipseSymbol(tmpImg, cx, cy, symbol, style);
+ break;
+ case (MS_SYMBOL_VECTOR):
+ r->renderVectorSymbol(tmpImg, cx, cy, symbol, style);
+ break;
+ default:
+ break;
+ }
+
+ style->scale = scale; // restore symbol scale
+
+ FILE *fOut = fopen(fileName, "wb");
+ if (!fOut)
+ return MS_FAILURE;
+
+ tmpImg->format = RasterizerOutputFormat;
+
+ int status = MS_FAILURE;
+ if(r->supports_pixel_buffer)
+ {
+ rasterBufferObj data;
+ r->getRasterBuffer(tmpImg,&data);
+ status = msSaveRasterBuffer(&data, fOut, RasterizerOutputFormat );
+ }
+ else
+ {
+ status = r->saveImage(tmpImg, fOut, RasterizerOutputFormat);
+ }
+
+ fclose(fOut);
+
+ return status;
+}
+
+void KmlRenderer::createSymbolPlacemark(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
+{
+ char *symbolUrl = lookupSymbolStyle(symbol, style);
+
+ xmlNodePtr placemarkNode = createPlacemarkNode(LayerNode, symbolUrl);
+ xmlNewChild(placemarkNode, NULL, BAD_CAST "name", NULL);
+ xmlNodePtr pointNode = xmlNewChild(placemarkNode, NULL, BAD_CAST "Point", NULL);
+
+ addAddRenderingSpecifications(pointNode);
+
+ pointObj pt;
+ pt.x = x; pt.y = y;
+ addCoordsNode(pointNode, &pt, 1);
+}
+
+void KmlRenderer::renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
+{
+ if (VectorMode)
+ createSymbolPlacemark(img, x, y, symbol, style);
+
+ if (RasterMode)
+ {
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->renderPixmapSymbol(InternalImg, x, y, symbol, style);
+ }
+}
+
+void KmlRenderer::renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
+{
+ if (VectorMode)
+ createSymbolPlacemark(img, x, y, symbol, style);
+
+ if (RasterMode)
+ {
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->renderVectorSymbol(InternalImg, x, y, symbol, style);
+ }
+}
+
+void KmlRenderer::renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
+{
+ if (VectorMode)
+ createSymbolPlacemark(img, x, y, symbol, style);
+
+ if (RasterMode)
+ {
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->renderEllipseSymbol(InternalImg, x, y, symbol, style);
+ }
+}
+
+void KmlRenderer::renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
+{
+ if (VectorMode)
+ createSymbolPlacemark(img, x, y, symbol, style);
+
+ if (RasterMode)
+ {
+ rendererVTableObj *r = RasterizerOutputFormat->vtable;
+ r->renderTruetypeSymbol(InternalImg, x, y, symbol, style);
+ }
+}
+
+void KmlRenderer::createGroundOverlayNode(char *imageHref)
+{
+ /*
+ <?xml version="1.0" encoding="UTF-8"?>
+ <kml xmlns="http://www.opengis.net/kml/2.2">
+ <GroundOverlay>
+ <name>GroundOverlay.kml</name>
+ <color>7fffffff</color>
+ <drawOrder>1</drawOrder>
+ <Icon>
+ <href>http://www.google.com/intl/en/images/logo.gif</href>
+ <refreshMode>onInterval</refreshMode>
+ <refreshInterval>86400</refreshInterval>
+ <viewBoundScale>0.75</viewBoundScale>
+ </Icon>
+ <LatLonBox>
+ <north>37.83234</north>
+ <south>37.832122</south>
+ <east>-122.373033</east>
+ <west>-122.373724</west>
+ <rotation>45</rotation>
+ </LatLonBox>
+ </GroundOverlay>
+ </kml>
+ */
+
+ xmlNodePtr groundOverlayNode = xmlNewChild(DocNode, NULL, BAD_CAST "GroundOverlay", NULL);
+ xmlNewChild(groundOverlayNode, NULL, BAD_CAST "color", BAD_CAST "ffffffff");
+ xmlNewChild(groundOverlayNode, NULL, BAD_CAST "drawOrder", BAD_CAST "1");
+
+ xmlNodePtr iconNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "Icon", NULL);
+ xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST imageHref);
+
+ char crdStr[64];
+ xmlNodePtr latLonBoxNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "LatLonBox", NULL);
+ sprintf(crdStr, "%.8f", MapExtent.maxy);
+ xmlNewChild(latLonBoxNode, NULL, BAD_CAST "north", BAD_CAST crdStr);
+
+ sprintf(crdStr, "%.8f", MapExtent.miny);
+ xmlNewChild(latLonBoxNode, NULL, BAD_CAST "south", BAD_CAST crdStr);
+
+ sprintf(crdStr, "%.8f", MapExtent.minx);
+ xmlNewChild(latLonBoxNode, NULL, BAD_CAST "west", BAD_CAST crdStr);
+
+ sprintf(crdStr, "%.8f", MapExtent.maxx);
+ xmlNewChild(latLonBoxNode, NULL, BAD_CAST "east", BAD_CAST crdStr);
+
+ xmlNewChild(latLonBoxNode, NULL, BAD_CAST "rotation", BAD_CAST "0.0");
+}
+
+#endif
\ No newline at end of file
Added: sandbox/davidK/mapkmlrenderer.h
===================================================================
--- sandbox/davidK/mapkmlrenderer.h (rev 0)
+++ sandbox/davidK/mapkmlrenderer.h 2009-07-11 20:51:02 UTC (rev 9167)
@@ -0,0 +1,99 @@
+#ifndef MAPKMLRENDERER_H
+#define MAPKMLRENDERER_H
+
+#if defined(USE_KML) && defined (USE_LIBXML2)
+
+#include "mapserver.h"
+#include "maplibxml2.h"
+
+
+class KmlRenderer
+{
+protected:
+
+ xmlDocPtr XmlDoc; /* document pointer */
+ xmlNodePtr DocNode;
+ xmlNodePtr LayerNode;
+
+ int Width, Height;
+
+ hashTableObj *StyleHashTable;
+
+ int AltitudeMode;
+ int Tessellate;
+ int Extrude;
+
+ int FirstLayer;
+
+ // internal output format containing cairo renderer used for rasterizing and rendering symbols
+ outputFormatObj *RasterizerOutputFormat;
+ imageObj *InternalImg;
+
+ rectObj MapExtent;
+ double MapCellsize;
+
+ // if true - features are rasterized
+ int VectorMode;
+
+ // if true - features are written directly in kml
+ int RasterMode;
+
+ enum altitudeModeEnum { undefined, clampToGround, relativeToGround, absolute };
+
+protected:
+
+ imageObj* createInternalImage();
+ xmlNodePtr createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl);
+ void createGroundOverlayNode(char *imageHref);
+
+ char* lookupPointStyle(colorObj *color);
+ char* lookupLineStyle(strokeStyleObj *strokeStyle);
+ char* lookupPolyStyle(colorObj *color);
+
+ char* lookupSymbolStyle(symbolObj *symbol, symbolStyleObj *style);
+
+ void addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts);
+
+ void setupRenderingParams(hashTableObj *layerMetadata);
+ void addAddRenderingSpecifications(xmlNodePtr node);
+
+ int checkProjection(projectionObj *projection);
+
+ int createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *style);
+
+ void createSymbolPlacemark(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ void renderLineVector(imageObj *img, shapeObj *p, strokeStyleObj *style);
+ void renderPolygonVector(imageObj *img, shapeObj *p, colorObj *color);
+ void renderGlyphsVector(imageObj *img, double x, double y, labelStyleObj *style, char *text);
+
+public:
+
+ KmlRenderer(int width, int height, colorObj* color = NULL);
+ virtual ~KmlRenderer();
+
+ imageObj* createImage(int width, int height, outputFormatObj *format, colorObj* bg);
+ int saveImage(imageObj *img, FILE *fp, outputFormatObj *format);
+ void freeImage(imageObj *image);
+
+ void startNewLayer(imageObj *img, layerObj *layer);
+ void closeNewLayer(imageObj *img, layerObj *layer);
+
+ void renderLine(imageObj *img, shapeObj *p, strokeStyleObj *style);
+ void renderPolygon(imageObj *img, shapeObj *p, colorObj *color);
+
+ void renderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text);
+
+ // Symbols
+ void renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
+ void renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
+ void renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
+ void renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
+
+ int getTruetypeTextBBox(imageObj *img,char *font, double size, char *string, rectObj *rect, double **advances);
+};
+
+#endif /* USE_KML && USE_LIBXML2*/
+#endif
\ No newline at end of file
More information about the mapserver-commits
mailing list