[mapguide-commits] r9185 - in sandbox/jng/utfgrid: Common/MapGuideCommon/Services Common/Renderers Server/src/Services/Rendering Server/src/UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Mon May 1 16:56:15 PDT 2017
Author: jng
Date: 2017-05-01 16:56:15 -0700 (Mon, 01 May 2017)
New Revision: 9185
Modified:
sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.h
sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingDefs.h
sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingService.h
sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h
sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h
sandbox/jng/utfgrid/Server/src/Services/Rendering/RenderingOperationFactory.cpp
sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.cpp
sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.h
sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj
sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters
sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp
sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.cpp
sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.h
Log:
- Add RenderTileUTFGrid API to MgRenderingService
- Extract out XYZ tile extent computation to a common method in MgServerFeatureService
- Fix access violation in agg_utfgrid_context, we don't use the stride value as copypasta'd from agg_context!
- Use plain unsigned int instead of the typedef'd utfgrid_band_type in our various new headers to avoid AGG headers leaking out to ServerRenderingService project
- Add unit test for rendering out UTFGrid tiles, re-using XYZ tile test data and giving us a nice baseline visual comparsion.
Modified: sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -19,6 +19,7 @@
#include "Command.h"
#include "RenderingDefs.h"
+#include "ProxyRenderingService.h"
static const int Rendering_Service = (int)MgPacketParser::msiRendering;
@@ -192,6 +193,28 @@
return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
}
+MgByteReader * MgProxyRenderingService::RenderTileUTFGrid(MgMap * map, CREFSTRING baseMapLayerGroupName, INT32 x, INT32 y, INT32 z, INT32 dpi)
+{
+ MgCommand cmd;
+ cmd.ExecuteCommand(m_connProp, // Connection
+ MgCommand::knObject, // Return type expected
+ MgRenderingServiceOpId::RenderTileUTFGrid, // Command Code
+ 7, // No of arguments
+ Rendering_Service, // Service Id
+ BUILD_VERSION(3, 3, 0), // Operation version
+ MgCommand::knObject, map, // Argument#1
+ MgCommand::knString, &baseMapLayerGroupName, // Argument#2
+ MgCommand::knInt32, x, // Argument#3
+ MgCommand::knInt32, y, // Argument#4
+ MgCommand::knInt32, z, // Argument#5
+ MgCommand::knInt32, dpi, // Argument#6
+ MgCommand::knNone); // End of arguments
+
+ SetWarning(cmd.GetWarningObject());
+
+ return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
+}
+
/////////////////////////////////////////////////////////////////
/// <summary>
/// Renders all dynamic layers in the specified MgMap to a dynamic overlay image
Modified: sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.h
===================================================================
--- sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/MapGuideCommon/Services/ProxyRenderingService.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -179,6 +179,45 @@
/////////////////////////////////////////////////////////////////
/// \brief
+ /// Returns the specified UTFGrid tile for the given map. Tile structure is
+ /// based on the XYZ tiling scheme used by Google Maps, OpenStreetMap, and
+ /// others
+ ///
+ /// \param map
+ /// Input
+ /// map object containing current state of map.
+ /// \param baseMapLayerGroupName
+ /// Input
+ /// Specifies the name of the baseMapLayerGroup for which to render the tile.
+ /// \param x
+ /// Input
+ /// Specifies the row index of the tile to return.
+ /// \param y
+ /// Input
+ /// Specifies the column index of the tile to return.
+ /// \param z
+ /// Input
+ /// Specifies the zoom level of the tile to return.
+ /// \param dpi
+ /// Input
+ /// Specifies the dpi of the tile to return.
+ /// \param tileImageFormat
+ /// Input
+ /// Specifies the image format of the tile to return.
+ ///
+ /// \return
+ /// A byte reader containing the rendered tile image.
+ ///
+ virtual MgByteReader* RenderTileUTFGrid(
+ MgMap* map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi);
+
+ /////////////////////////////////////////////////////////////////
+ /// \brief
/// Renders all dynamic layers in the specified MgMap to a dynamic overlay image
/// with a transparent background. The center, scale, size, and layers to be
/// rendered are defined by the specified map instance. The format parameter
Modified: sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingDefs.h
===================================================================
--- sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingDefs.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingDefs.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -45,6 +45,7 @@
static const int RenderTileXYZ2 = 0x1111E911;
static const int RenderMap6 = 0x1111E912;
static const int RenderMap7 = 0x1111E913;
+ static const int RenderTileUTFGrid = 0x1111E914;
};
/// \endcond
Modified: sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingService.h
===================================================================
--- sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingService.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/MapGuideCommon/Services/RenderingService.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -194,6 +194,45 @@
/////////////////////////////////////////////////////////////////
/// \brief
+ /// Returns the specified UTFGrid tile for the given map. Tile structure is
+ /// based on the XYZ tiling scheme used by Google Maps, OpenStreetMap, and
+ /// others
+ ///
+ /// \param map
+ /// Input
+ /// map object containing current state of map.
+ /// \param baseMapLayerGroupName
+ /// Input
+ /// Specifies the name of the baseMapLayerGroup for which to render the tile.
+ /// \param x
+ /// Input
+ /// Specifies the row index of the tile to return.
+ /// \param y
+ /// Input
+ /// Specifies the column index of the tile to return.
+ /// \param z
+ /// Input
+ /// Specifies the zoom level of the tile to return.
+ /// \param dpi
+ /// Input
+ /// Specifies the dpi of the tile to return.
+ /// \param tileImageFormat
+ /// Input
+ /// Specifies the image format of the tile to return.
+ ///
+ /// \return
+ /// A byte reader containing the rendered tile image.
+ ///
+ virtual MgByteReader* RenderTileUTFGrid(
+ MgMap* map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi) = 0;
+
+ /////////////////////////////////////////////////////////////////
+ /// \brief
/// Renders all dynamic layers in the specified MgMap to a dynamic overlay image
/// with a transparent background. The center, scale, size, and layers to be
/// rendered are defined by the specified map instance. The format parameter
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -1,4 +1,5 @@
#include "UTFGridContent.h"
+#include "UnicodeString.h"
#include "agg_utfgrid_context.h"
UTFGridContent::UTFGridContent()
@@ -11,7 +12,10 @@
std::string UTFGridContent::GetString()
{
- return m_content.str();
+ std::string mbContent;
+ std::wstring content = m_content.str();
+ UnicodeString::WideCharToMultiByte(content.c_str(), mbContent);
+ return mbContent;
}
void UTFGridContent::AddFeature(unsigned int color, RS_FeatureReader* feature)
@@ -24,7 +28,7 @@
}
-void UTFGridContent::AppendRowPixel(utfgrid_band_type pixel)
+void UTFGridContent::AppendRowPixel(unsigned int pixel)
{
m_content.sputc(EncodeChar(pixel));
}
@@ -34,12 +38,12 @@
m_content.sputc('\n');
}
-utfgrid_band_type UTFGridContent::EncodeChar(utfgrid_band_type toEncode)
+unsigned int UTFGridContent::EncodeChar(unsigned int toEncode)
{
// Encoding IDs: https://github.com/mapbox/utfgrid-spec/blob/master/1.3/utfgrid.md#encoding-ids
// Add 32
- utfgrid_band_type encoded = toEncode + 32;
+ unsigned int encoded = toEncode + 32;
// If result is >= 34, add 1
if (encoded >= 34)
{
@@ -53,12 +57,12 @@
return encoded;
}
-utfgrid_band_type UTFGridContent::DecodeChar(utfgrid_band_type toDecode)
+unsigned int UTFGridContent::DecodeChar(unsigned int toDecode)
{
// Decoding IDs: https://github.com/mapbox/utfgrid-spec/blob/master/1.3/utfgrid.md#encoding-ids
// If codepoint is >= 93, subtract 1
- utfgrid_band_type decoded = toDecode;
+ unsigned int decoded = toDecode;
if (decoded >= 93)
{
decoded -= 1;
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -20,7 +20,6 @@
#include "Renderers.h"
#include "RS_FeatureReader.h"
-#include "agg_utfgrid_context.h"
#include <sstream>
typedef std::map<unsigned int, std::string> FeaturePixelMap;
@@ -36,14 +35,14 @@
void AddFeature(unsigned int color, RS_FeatureReader* feature);
void StartGridRow();
- void AppendRowPixel(utfgrid_band_type pixel);
+ void AppendRowPixel(unsigned int pixel);
void EndGridRow();
private:
- static utfgrid_band_type EncodeChar(utfgrid_band_type toEncode);
- static utfgrid_band_type DecodeChar(utfgrid_band_type toDecode);
+ static unsigned int EncodeChar(unsigned int toEncode);
+ static unsigned int DecodeChar(unsigned int toDecode);
- std::stringbuf m_content;
+ std::wstringbuf m_content;
FeaturePixelMap m_features;
};
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -48,7 +48,14 @@
UTFGridRenderer::UTFGridRenderer(UTFGridContent* utfGrid)
: m_currentColor(0),
- m_content(utfGrid)
+ m_content(utfGrid),
+ m_dpi(0),
+ m_drawingScale(0.0),
+ m_metersPerUnit(0.0),
+ m_mapScale(0.0),
+ m_mapInfo(NULL),
+ m_layerInfo(NULL),
+ m_fcInfo(NULL)
{
// allocate back buffer
int len = UTF_GRID_WIDTH * UTF_GRID_HEIGHT;
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -100,7 +100,7 @@
agg_utfgrid_context* m_context;
//screen buffer
- utfgrid_band_type* m_rows;
+ unsigned int* m_rows;
//Not used, just passed around to satisfy required func signatures
SE_LineStroke m_lineStroke;
Modified: sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -61,7 +61,7 @@
m_rows = rows;
}
- int stride = width * sizeof(utfgrid_band_type);
+ int stride = width; // *sizeof(utfgrid_band_type);
rendering_buffer.attach(m_rows, width, height, stride);
pixel_format.attach(rendering_buffer);
renderer_base.attach(pixel_format);
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/RenderingOperationFactory.cpp
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/RenderingOperationFactory.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/RenderingOperationFactory.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -108,6 +108,17 @@
L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
}
break;
+ case MgRenderingServiceOpId::RenderTileUTFGrid:
+ switch (VERSION_NO_PHASE(operationVersion))
+ {
+ case VERSION_SUPPORTED(3, 3):
+ handler.reset(new MgOpRenderTileUTFGrid());
+ break;
+ default:
+ throw new MgInvalidOperationVersionException(
+ L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+ break;
case MgRenderingServiceOpId::RenderDynamicOverlay:
switch (VERSION_NO_PHASE(operationVersion))
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -20,6 +20,7 @@
#include "DefaultStylizer.h"
#include "GDRenderer.h"
#include "AGGRenderer.h"
+#include "UTFGridRenderer.h"
#include "RSMgSymbolManager.h"
#include "RSMgFeatureReader.h"
#include "FeatureInfoRenderer.h"
@@ -259,6 +260,48 @@
return ret.Detach();
}
+void MgServerRenderingService::ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
+{
+ //XYZ to lat/lon math. From this we can convert to the bounds in the map's CS
+ //
+ //Source: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+ double nMin = M_PI - 2.0 * M_PI * y / pow(2.0, (int)z);
+ double nMax = M_PI - 2.0 * M_PI * (y + 1) / pow(2.0, (int)z);
+ double lonMin = x / pow(2.0, (int)z) * 360.0 - 180;
+ double latMin = 180.0 / M_PI * atan(0.5 * (exp(nMin) - exp(-nMin)));
+ double lonMax = (x + 1) / pow(2.0, (int)z) * 360.0 - 180;
+ double latMax = 180.0 / M_PI * atan(0.5 * (exp(nMax) - exp(-nMax)));
+
+ double mcsMinX = std::min(lonMin, lonMax);
+ double mcsMinY = std::min(latMin, latMax);
+ double mcsMaxX = std::max(lonMin, lonMax);
+ double mcsMaxY = std::max(latMin, latMax);
+
+ STRING mapCsWkt = map->GetMapSRS();
+ Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
+ Ptr<MgCoordinateSystem> mapCs = csFactory->Create(mapCsWkt);
+ if (mapCs->GetCsCode() != L"LL84")
+ {
+ //Set up LL to map transform and transform the bounds into map space
+ Ptr<MgCoordinateSystem> llCs = csFactory->CreateFromCode(L"LL84");
+ Ptr<MgCoordinateSystemTransform> trans = csFactory->GetTransform(llCs, mapCs);
+
+ Ptr<MgCoordinate> ul = trans->Transform(lonMin, latMin);
+ Ptr<MgCoordinate> lr = trans->Transform(lonMax, latMax);
+
+ mcsMinX = std::min(lr->GetX(), ul->GetX());
+ mcsMinY = std::min(lr->GetY(), ul->GetY());
+ mcsMaxX = std::max(lr->GetX(), ul->GetX());
+ mcsMaxY = std::max(lr->GetY(), ul->GetY());
+ }
+
+ // get map extent that corresponds to tile extent
+ extent.minx = mcsMinX;
+ extent.miny = mcsMinY;
+ extent.maxx = mcsMaxX;
+ extent.maxy = mcsMaxY;
+}
+
MgByteReader* MgServerRenderingService::RenderTileXYZ(MgMap* map,
CREFSTRING baseMapLayerGroupName,
INT32 x,
@@ -293,45 +336,11 @@
int width = XYZ_TILE_WIDTH;
int height = XYZ_TILE_HEIGHT;
- //XYZ to lat/lon math. From this we can convert to the bounds in the map's CS
- //
- //Source: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
- double nMin = M_PI - 2.0 * M_PI * y / pow(2.0, (int)z);
- double nMax = M_PI - 2.0 * M_PI * (y + 1) / pow(2.0, (int)z);
- double lonMin = x / pow(2.0, (int)z) * 360.0 - 180;
- double latMin = 180.0 / M_PI * atan(0.5 * (exp(nMin) - exp(-nMin)));
- double lonMax = (x + 1) / pow(2.0, (int)z) * 360.0 - 180;
- double latMax = 180.0 / M_PI * atan(0.5 * (exp(nMax) - exp(-nMax)));
-
- double mcsMinX = std::min(lonMin, lonMax);
- double mcsMinY = std::min(latMin, latMax);
- double mcsMaxX = std::max(lonMin, lonMax);
- double mcsMaxY = std::max(latMin, latMax);
-
- STRING mapCsWkt = map->GetMapSRS();
- Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
- Ptr<MgCoordinateSystem> mapCs = csFactory->Create(mapCsWkt);
- if (mapCs->GetCsCode() != L"LL84")
- {
- //Set up LL to map transform and transform the bounds into map space
- Ptr<MgCoordinateSystem> llCs = csFactory->CreateFromCode(L"LL84");
- Ptr<MgCoordinateSystemTransform> trans = csFactory->GetTransform(llCs, mapCs);
-
- Ptr<MgCoordinate> ul = trans->Transform(lonMin, latMin);
- Ptr<MgCoordinate> lr = trans->Transform(lonMax, latMax);
-
- mcsMinX = std::min(lr->GetX(), ul->GetX());
- mcsMinY = std::min(lr->GetY(), ul->GetY());
- mcsMaxX = std::max(lr->GetX(), ul->GetX());
- mcsMaxY = std::max(lr->GetY(), ul->GetY());
- }
-
// Inlining same logic from RenderTile() overload below as we want the same logic, but we want to pass scale
// instead of scale index
+ RS_Bounds extent;
+ ComputeXYZTileExtents(map, x, y, z, extent);
- // get map extent that corresponds to tile extent
- RS_Bounds extent(mcsMinX, mcsMinY, mcsMaxX, mcsMaxY);
-
// use the map's background color, but always make it fully transparent
RS_Color bgColor;
StylizationUtil::ParseColor(map->GetBackgroundColor(), bgColor);
@@ -425,6 +434,197 @@
return ret.Detach();
}
+MgByteReader* MgServerRenderingService::RenderTileUTFGrid(MgMap * map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi)
+{
+ Ptr<MgByteReader> ret;
+
+ MG_TRY()
+
+ CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTileUTFGrid");
+ CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTileUTFGrid");
+
+ // get the layer group associated with the name
+ Ptr<MgLayerGroupCollection> layerGroups = map->GetLayerGroups();
+ Ptr<MgLayerGroup> baseGroup = layerGroups->GetItem(baseMapLayerGroupName);
+ if (baseGroup == NULL)
+ {
+ MgStringCollection arguments;
+ arguments.Add(L"2");
+ arguments.Add(baseMapLayerGroupName);
+
+ throw new MgInvalidArgumentException(L"MgServerRenderingService.RenderTileUTFGrid",
+ __LINE__, __WFILE__, &arguments, L"MgMapLayerGroupNameNotFound", NULL);
+ }
+
+ //Set the dpi
+ map->SetDisplayDpi(dpi);
+
+ int width = XYZ_TILE_WIDTH;
+ int height = XYZ_TILE_HEIGHT;
+
+ // Inlining same logic from RenderTile() overload below as we want the same logic, but we want to pass scale
+ // instead of scale index
+
+ // get map extent that corresponds to tile extent
+ RS_Bounds extent;
+ ComputeXYZTileExtents(map, x, y, z, extent);
+
+ // use the map's background color, but always make it fully transparent
+ RS_Color bgColor;
+ StylizationUtil::ParseColor(map->GetBackgroundColor(), bgColor);
+ bgColor.alpha() = 0;
+
+ // the label renderer needs to know the tile extent offset parameter
+ double tileExtentOffset = 0.0;
+ MgConfiguration* pConf = MgConfiguration::GetInstance();
+ pConf->GetDoubleValue(MgConfigProperties::RenderingServicePropertiesSection,
+ MgConfigProperties::RenderingServicePropertyTileExtentOffset,
+ tileExtentOffset,
+ MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset);
+ if (tileExtentOffset < 0.0)
+ tileExtentOffset = MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset;
+
+ // Image scaling logic ripped verbatim from RenderMap() overload that takes MgEnvelope
+ //
+ // If we need to scale the image (because of request for non-square
+ // pixels) we will need to draw at one image size and then save at
+ // another scaled size. Here we will compute the correct map scale
+ // and render size for a requested extent and image size.
+ double screenAR = (double)width / (double)height;
+ double mapAR = extent.width() / extent.height();
+
+ int drawWidth = width;
+ int drawHeight = height;
+ double scale = 0.0;
+
+ if (mapAR >= screenAR)
+ {
+ scale = extent.width() * map->GetMetersPerUnit() / METERS_PER_INCH * (double)dpi / (double)width;
+
+ // we based map scale on the image width, so adjust rendering
+ // height to match the map aspect ratio
+ drawHeight = (int)(width / mapAR);
+
+ // ignore small perturbations in order to avoid rescaling the
+ // end image in cases where the rescaling of width is less than
+ // a pixel or so
+ if (abs(drawHeight - height) <= 1)
+ drawHeight = height;
+ }
+ else
+ {
+ scale = extent.height() * map->GetMetersPerUnit() / METERS_PER_INCH * (double)dpi / (double)height;
+
+ // we based map scale on the image height, so adjust rendering
+ // height to match the map aspect ratio
+ drawWidth = (int)(height * mapAR);
+
+ // ignore small perturbations, in order to avoid rescaling the
+ // end image in cases where the rescaling of width is less than
+ // a pixel or so
+ if (abs(drawWidth - width) <= 1)
+ drawWidth = width;
+ }
+
+ //printf("XYZ(%d, %d, %d) -> [%f, %f] [%f, %f] at %f -- (w: %d, h: %d, mpu: %f)\n", x, y, z, mcsMinX, mcsMinY, mcsMaxX, mcsMaxY, scale, width, height, map->GetMetersPerUnit());
+
+ // sanity check - number of image pixels cannot exceed MAX_PIXELS
+ if (drawWidth * drawHeight > MAX_PIXELS)
+ throw new MgOutOfRangeException(L"MgServerRenderingService.RenderMap", __LINE__, __WFILE__, NULL, L"MgInvalidImageSizeTooBig", NULL);
+
+ // create a temporary collection containing all the layers for the base group
+ Ptr<MgLayerCollection> layers = map->GetLayers();
+ Ptr<MgReadOnlyLayerCollection> roLayers = new MgReadOnlyLayerCollection();
+ for (int i = 0; i<layers->GetCount(); i++)
+ {
+ Ptr<MgLayerBase> layer = layers->GetItem(i);
+ Ptr<MgLayerGroup> parentGroup = layer->GetGroup();
+ if (parentGroup == baseGroup)
+ roLayers->Add(layer);
+ }
+
+ // of course the group has to also be visible
+ bool groupVisible = baseGroup->GetVisible();
+ baseGroup->SetVisible(true);
+
+ // We'd like to re-use RenderMapInternal, but its design is biased towards image-based SE_Renderers (that expect to
+ // save to some RS_ByteData that an MgByteReader is returned from.
+ //
+ // Our UTFGridRenderer is not such a renderer, so we have to inline the pertinent bits here
+
+ // set the map scale to the requested scale
+ map->SetViewScale(scale);
+
+ // convert the map coordinate system from srs wkt to a mentor cs structure
+ STRING srs = map->GetMapSRS();
+ Ptr<MgCoordinateSystem> dstCs;
+ if (!srs.empty())
+ {
+ // let's not fail here if coord sys conversion fails for the map's
+ // coordinate system. Instead we will fail per layer at a later stage
+ try
+ {
+ dstCs = m_pCSFactory->Create(srs);
+ }
+ catch (MgInvalidCoordinateSystemException* e)
+ {
+ e->Release();
+ }
+ }
+
+ RS_String units = dstCs.p ? dstCs->GetUnits() : L"";
+
+ // get the session ID
+ STRING sessionId;
+ Ptr<MgUserInformation> userInfo = MgUserInformation::GetCurrentUserInfo();
+ if (userInfo != NULL)
+ sessionId = userInfo->GetMgSessionId();
+
+ UTFGridContent content;
+ std::auto_ptr<UTFGridRenderer> dr(new UTFGridRenderer(&content));
+
+ RSMgSymbolManager mgr(m_svcResource);
+ dr->SetSymbolManager(&mgr);
+
+ SEMgSymbolManager semgr(m_svcResource);
+ DefaultStylizer ds(&semgr);
+
+ RS_Color bgcolor(0, 0, 0, 255); //Not used by UTFGridRenderer
+
+ Ptr<MgPoint> ptCenter = map->GetViewCenter();
+ Ptr<MgCoordinate> coord = ptCenter->GetCoordinate();
+ RS_MapUIInfo mapInfo(sessionId, map->GetName(), map->GetObjectId(), srs, units, bgcolor, coord->GetX(), coord->GetY(), scale);
+
+ // begin map stylization
+ dr->StartMap(&mapInfo, extent, scale, map->GetDisplayDpi(), map->GetMetersPerUnit(), NULL);
+
+ // We can't use RenderMapInternal, but we can use RenderLayers, which is all we really need
+ RenderLayers(map, roLayers, &ds, dr.get(), dstCs, true, scale, L"UTFGRID", NULL);
+
+ dr->EndMap(); //This will trigger the UTFGrid tile encoding process
+
+ // restore the base group's visibility
+ baseGroup->SetVisible(groupVisible);
+
+ // Now extract the encoded utfgrid tile and pack it into a MgByteReader
+ std::string utfgrid = content.GetString();
+ Ptr<MgByteSource> bs = new MgByteSource((BYTE_ARRAY_IN)utfgrid.c_str(), (INT32)utfgrid.length());
+
+ // TODO: Convert to MgMimeType::Json when encoding is fully implemented
+ bs->SetMimeType(MgMimeType::Text);
+
+ ret = bs->GetReader();
+
+ MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTileUTFGrid")
+
+ return ret.Detach();
+}
+
///////////////////////////////////////////////////////////////////////////////
/// render a map using all layers from the baseGroup
MgByteReader* MgServerRenderingService::RenderTile(MgMap* map,
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -70,6 +70,13 @@
INT32 dpi,
CREFSTRING tileImageFormat);
+ virtual MgByteReader* RenderTileUTFGrid(MgMap* map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi);
+
virtual MgByteReader* RenderDynamicOverlay(MgMap* map,
MgSelection* selection,
CREFSTRING format);
@@ -226,6 +233,7 @@
bool bIncludeFeatureBBOX);
private:
+ static void ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
// used for tile generation
MgByteReader* RenderTile(MgMap* map,
MgLayerGroup* baseGroup,
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj 2017-05-01 23:56:15 UTC (rev 9185)
@@ -240,6 +240,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="OpRenderTileUTFGrid.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="RenderingOperation.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -292,6 +298,7 @@
<ClInclude Include="OpRenderMapLegend.h" />
<ClInclude Include="OpRenderTile.h" />
<ClInclude Include="OpRenderTileXYZ.h" />
+ <ClInclude Include="OpRenderTileUTFGrid.h" />
<ClInclude Include="RenderingOperation.h" />
<ClInclude Include="RenderingOperationFactory.h" />
<ClInclude Include="FeatureInfoRenderer.h" />
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters 2017-05-01 23:56:15 UTC (rev 9185)
@@ -39,6 +39,9 @@
<ClCompile Include="OpRenderTileXYZ.cpp">
<Filter>Ops</Filter>
</ClCompile>
+ <ClCompile Include="OpRenderTileUTFGrid.cpp">
+ <Filter>Ops</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="OpQueryFeatureProperties.h">
@@ -74,6 +77,9 @@
<ClInclude Include="OpRenderTileXYZ.h">
<Filter>Ops</Filter>
</ClInclude>
+ <ClInclude Include="OpRenderTileUTFGrid.h">
+ <Filter>Ops</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ServerRenderingService.rc" />
Modified: sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp
===================================================================
--- sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -25,6 +25,7 @@
#include "OpRenderMapLegend.cpp"
#include "OpRenderTile.cpp"
#include "OpRenderTileXYZ.cpp"
+#include "OpRenderTileUTFGrid.cpp"
#include "OpQueryFeatures.cpp"
#include "OpQueryFeatureProperties.cpp"
#include "RenderingOperation.cpp"
Modified: sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.cpp
===================================================================
--- sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.cpp 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.cpp 2017-05-01 23:56:15 UTC (rev 9185)
@@ -1761,6 +1761,29 @@
}
}
+void TestRenderingService::TestCase_RenderTileUTFGrid()
+{
+ try
+ {
+ Ptr<MgMap> map = CreateTestTiledMap();
+ Ptr<MgByteReader> tileTL = m_svcRendering->RenderTileUTFGrid(map, L"BaseLayers", 2099, 2985, 13, 96);
+ Ptr<MgByteReader> tileTR = m_svcRendering->RenderTileUTFGrid(map, L"BaseLayers", 2100, 2985, 13, 96);
+ Ptr<MgByteReader> tileBL = m_svcRendering->RenderTileUTFGrid(map, L"BaseLayers", 2099, 2986, 13, 96);
+ Ptr<MgByteReader> tileBR = m_svcRendering->RenderTileUTFGrid(map, L"BaseLayers", 2100, 2986, 13, 96);
+
+ tileTL->ToFile(L"../UnitTestFiles/RenderTileUTFGrid_TopLeft.utfgrid");
+ tileTR->ToFile(L"../UnitTestFiles/RenderTileUTFGrid_TopRight.utfgrid");
+ tileBL->ToFile(L"../UnitTestFiles/RenderTileUTFGrid_BottomLeft.utfgrid");
+ tileBR->ToFile(L"../UnitTestFiles/RenderTileUTFGrid_BottomRight.utfgrid");
+ }
+ catch (MgException* e)
+ {
+ STRING message = e->GetDetails(TEST_LOCALE);
+ SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+}
+
STRING TestRenderingService::GetPath(CREFSTRING basePath, CREFSTRING imageFormat, CREFSTRING extension)
{
STRING ret;
Modified: sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.h
===================================================================
--- sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.h 2017-05-01 16:24:06 UTC (rev 9184)
+++ sandbox/jng/utfgrid/Server/src/UnitTesting/TestRenderingService.h 2017-05-01 23:56:15 UTC (rev 9185)
@@ -55,6 +55,7 @@
CPPUNIT_TEST(TestCase_LayerWatermarkPNG);
CPPUNIT_TEST(TestCase_RenderTilePNG);
CPPUNIT_TEST(TestCase_RenderTileXYZ_PNG);
+ CPPUNIT_TEST(TestCase_RenderTileUTFGrid);
CPPUNIT_TEST(TestCase_StylizationFunctionsPNG8);
@@ -219,6 +220,7 @@
void TestCase_LayerWatermarkPNG() { TestCase_LayerWatermark(L"PNG", L"png"); }
void TestCase_RenderTilePNG() { TestCase_RenderTile(L"PNG", L"png"); }
void TestCase_RenderTileXYZ_PNG() { TestCase_RenderTileXYZ(L"PNG", L"png"); }
+ void TestCase_RenderTileUTFGrid();
//PNG8 output tests
void TestCase_RenderDynamicOverlayPNG8() { TestCase_RenderDynamicOverlay(L"PNG8", L"png"); }
More information about the mapguide-commits
mailing list