[mapguide-commits] r9491 - in sandbox/jng/tiling_v2: Common/MapGuideCommon/Services Server/src/Services/Rendering Server/src/Services/Tile

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Apr 15 04:39:50 PDT 2019


Author: jng
Date: 2019-04-15 04:39:50 -0700 (Mon, 15 Apr 2019)
New Revision: 9491

Modified:
   sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
   sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h
   sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/RenderingService.h
   sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/TileDefs.h
   sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTile.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTileXYZ.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.h
   sandbox/jng/tiling_v2/Server/src/Services/Tile/ServerTileService.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.h
   sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.cpp
   sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.h
Log:
Add new overloads of RenderTile and RenderTileXYZ to take tile extent offset as a parameter

Modified: sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
===================================================================
--- sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -139,6 +139,40 @@
     return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
 }
 
+MgByteReader* MgProxyRenderingService::RenderTile(
+    MgMap* map,
+    CREFSTRING baseMapLayerGroupName,
+    INT32 tileColumn,
+    INT32 tileRow,
+    INT32 tileWidth,
+    INT32 tileHeight,
+    INT32 tileDpi,
+    CREFSTRING tileImageFormat,
+    double tileExtentOffset)
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                      // Connection
+        MgCommand::knObject,                            // Return type expected
+        MgRenderingServiceOpId::RenderTile2,            // Command Code
+        9,                                              // 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, tileColumn,                 // Argument#3
+        MgCommand::knInt32, tileRow,                    // Argument#4
+        MgCommand::knInt32, tileWidth,                  // Argument#5
+        MgCommand::knInt32, tileHeight,                 // Argument#6
+        MgCommand::knInt32, tileDpi,                    // Argument#7
+        MgCommand::knString, &tileImageFormat,          // Argument#8
+        MgCommand::knDouble, tileExtentOffset,          // Argument#9
+        MgCommand::knNone);                             // End of arguments
+
+    SetWarning(cmd.GetWarningObject());
+
+    return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
+}
+
 MgByteReader* MgProxyRenderingService::RenderTileXYZ(MgMap* map,
                                                      CREFSTRING baseMapLayerGroupName,
                                                      INT32 x,
@@ -193,6 +227,37 @@
     return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
 }
 
+MgByteReader* MgProxyRenderingService::RenderTileXYZ(MgMap* map,
+    CREFSTRING baseMapLayerGroupName,
+    INT32 x,
+    INT32 y,
+    INT32 z,
+    INT32 dpi,
+    CREFSTRING tileImageFormat,
+    double tileExtentOffset)
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                      // Connection
+        MgCommand::knObject,                            // Return type expected
+        MgRenderingServiceOpId::RenderTileXYZ2,         // Command Code
+        8,                                              // 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::knString, &tileImageFormat,          // Argument#7
+        MgCommand::knDouble, tileExtentOffset,          // Argument#8
+        MgCommand::knNone);                             // End of arguments
+
+    SetWarning(cmd.GetWarningObject());
+
+    return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
+}
+
 MgByteReader * MgProxyRenderingService::RenderTileUTFGrid(MgMap * map, CREFSTRING baseMapLayerGroupName, INT32 x, INT32 y, INT32 z, INT32 dpi)
 {
     MgCommand cmd;

Modified: sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h
===================================================================
--- sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -107,6 +107,60 @@
 
     /////////////////////////////////////////////////////////////////
     /// \brief
+    /// Returns the specified base map tile for the given map.
+    ///
+    /// \remarks
+    /// This method only renders the given tile. No tile caching is performed
+    /// by this method. To render and cache the tile, use the 
+    /// \link MgTileService::GetTile GetTile \endlink method instead. However,
+    /// using that method will use default tile width/height/dpi/format specified
+    /// in your MapGuide Server configuration
+    ///
+    /// \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 tileColumn
+    /// Input
+    /// Specifies the column index of the tile to return.
+    /// \param tileRow
+    /// Input
+    /// Specifies the row index of the tile to return.
+    /// \param tileWidth
+    /// Input
+    /// Specifies the width of the tile to return.
+    /// \param tileHeight
+    /// Input
+    /// Specifies the height of the tile to return.
+    /// \param tileDpi
+    /// Input
+    /// Specifies the dpi the tile to return.
+    /// \param tileImageFormat
+    /// Input
+    /// Specifies the image format of the tile. See \link MgImageFormats \endlink
+    /// \param tileExtentOffset
+    /// Specifies the ratio by which the tile to be rendered should be "buffered out". The tile will be rendered at the specified width
+    /// multiplied by the given ration, which will be cropped back to the original requested size after rendering. This is to improve
+    /// label placement on rendered tiles by giving extra "breathing space" to label placement algorithms.
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* RenderTile(
+        MgMap* map,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 tileColumn,
+        INT32 tileRow,
+        INT32 tileWidth,
+        INT32 tileHeight,
+        INT32 tileDpi,
+        CREFSTRING tileImageFormat,
+        double tileExtentOffset);
+
+    /////////////////////////////////////////////////////////////////
+    /// \brief
     /// Returns the specified map tile for the given map. Tile structure is
     /// based on the XYZ tiling scheme used by Google Maps, OpenStreetMap, and
     /// others
@@ -179,6 +233,51 @@
 
     /////////////////////////////////////////////////////////////////
     /// \brief
+    /// Returns the specified map 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.
+    /// \param tileExtentOffset
+    /// Specifies the ratio by which the tile to be rendered should be "buffered out". The tile will be rendered at the specified width
+    /// multiplied by the given ration, which will be cropped back to the original requested size after rendering. This is to improve
+    /// label placement on rendered tiles by giving extra "breathing space" to label placement algorithms.
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* RenderTileXYZ(
+        MgMap* map,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 x,
+        INT32 y,
+        INT32 z,
+        INT32 dpi,
+        CREFSTRING tileImageFormat,
+        double tileExtentOffset);
+
+    /////////////////////////////////////////////////////////////////
+    /// \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

Modified: sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/RenderingService.h
===================================================================
--- sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/RenderingService.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/RenderingService.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -121,6 +121,60 @@
 
     /////////////////////////////////////////////////////////////////
     /// \brief
+    /// Returns the specified base map tile for the given map.
+    ///
+    /// \remarks
+    /// This method only renders the given tile. No tile caching is performed
+    /// by this method. To render and cache the tile, use the 
+    /// \link MgTileService::GetTile GetTile \endlink method instead. However,
+    /// using that method will use default tile width/height/dpi/format specified
+    /// in your MapGuide Server configuration
+    ///
+    /// \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 tileColumn
+    /// Input
+    /// Specifies the column index of the tile to return.
+    /// \param tileRow
+    /// Input
+    /// Specifies the row index of the tile to return.
+    /// \param tileWidth
+    /// Input
+    /// Specifies the width of the tile to return.
+    /// \param tileHeight
+    /// Input
+    /// Specifies the height of the tile to return.
+    /// \param tileDpi
+    /// Input
+    /// Specifies the dpi the tile to return.
+    /// \param tileImageFormat
+    /// Input
+    /// Specifies the image format of the tile. See \link MgImageFormats \endlink
+    /// \param tileExtentOffset
+    /// Specifies the ratio by which the tile to be rendered should be "buffered out". The tile will be rendered at the specified width
+    /// multiplied by the given ration, which will be cropped back to the original requested size after rendering. This is to improve
+    /// label placement on rendered tiles by giving extra "breathing space" to label placement algorithms.
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* RenderTile(
+        MgMap* map,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 tileColumn,
+        INT32 tileRow,
+        INT32 tileWidth,
+        INT32 tileHeight,
+        INT32 tileDpi,
+        CREFSTRING tileImageFormat,
+        double tileExtentOffset) = 0;
+
+    /////////////////////////////////////////////////////////////////
+    /// \brief
     /// Returns the specified map tile for the given map. Tile structure is
     /// based on the XYZ tiling scheme used by Google Maps, OpenStreetMap, and
     /// others
@@ -194,6 +248,51 @@
 
     /////////////////////////////////////////////////////////////////
     /// \brief
+    /// Returns the specified map 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.
+    /// \param tileExtentOffset
+    /// Specifies the ratio by which the tile to be rendered should be "buffered out". The tile will be rendered at the specified width
+    /// multiplied by the given ration, which will be cropped back to the original requested size after rendering. This is to improve
+    /// label placement on rendered tiles by giving extra "breathing space" to label placement algorithms.
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* RenderTileXYZ(
+        MgMap* map,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 x,
+        INT32 y,
+        INT32 z,
+        INT32 dpi,
+        CREFSTRING tileImageFormat,
+        double tileExtentOffset) = 0;
+
+    /////////////////////////////////////////////////////////////////
+    /// \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

Modified: sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/TileDefs.h
===================================================================
--- sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/TileDefs.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Common/MapGuideCommon/Services/TileDefs.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -66,5 +66,6 @@
 #define MG_TILE_PROVIDER_COMMON_PARAM_RENDERONLY       L"RenderOnly"
 #define MG_TILE_PROVIDER_COMMON_PARAM_COORDINATESYSTEM L"CoordinateSystem"
 #define MG_TILE_PROVIDER_COMMON_PARAM_FINITESCALELIST  L"FiniteScaleList"
+#define MG_TILE_PROVIDER_COMMON_PARAM_TILEEXTENTOFFSET L"TileExtentOffset"
 
 #endif

Modified: sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTile.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTile.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTile.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -148,6 +148,65 @@
 
         EndExecution(byteReader);
     }
+    else if (9 == m_packet.m_NumArguments)
+    {
+        Ptr<MgMap> map = (MgMap*)m_stream->GetObject();
+        Ptr<MgResourceIdentifier> resource = map->GetResourceId();
+        map->SetDelayedLoadResourceService(m_resourceService);
+
+        STRING baseMapLayerGroupName;
+        m_stream->GetString(baseMapLayerGroupName);
+
+        INT32 tileCol = 0;
+        m_stream->GetInt32(tileCol);
+
+        INT32 tileRow = 0;
+        m_stream->GetInt32(tileRow);
+
+        INT32 tileWidth = 0;
+        m_stream->GetInt32(tileWidth);
+
+        INT32 tileHeight = 0;
+        m_stream->GetInt32(tileHeight);
+
+        INT32 tileDpi = 0;
+        m_stream->GetInt32(tileDpi);
+
+        STRING tileImageFormat;
+        m_stream->GetString(tileImageFormat);
+
+        double tileExtentOffset = 0.0;
+        m_stream->GetDouble(tileExtentOffset);
+
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? L"MgResourceIdentifier" : resource->ToString().c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(baseMapLayerGroupName.c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileCol);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileRow);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileWidth);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileHeight);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileDpi);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(tileImageFormat.c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_DOUBLE(tileExtentOffset);
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+
+        Validate();
+
+        Ptr<MgByteReader> byteReader =
+            m_service->RenderTile(map, baseMapLayerGroupName, tileCol, tileRow, tileWidth, tileHeight, tileDpi, tileImageFormat, tileExtentOffset);
+
+        EndExecution(byteReader);
+    }
     else
     {
         MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();

Modified: sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTileXYZ.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTileXYZ.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Rendering/OpRenderTileXYZ.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -146,6 +146,59 @@
 
         EndExecution(byteReader);
     }
+    else if (8 == m_packet.m_NumArguments)
+    {
+        Ptr<MgMap> map = (MgMap*)m_stream->GetObject();
+        Ptr<MgResourceIdentifier> resource = map->GetResourceId();
+        map->SetDelayedLoadResourceService(m_resourceService);
+
+        STRING baseMapLayerGroupName;
+        m_stream->GetString(baseMapLayerGroupName);
+
+        INT32 x = 0;
+        m_stream->GetInt32(x);
+
+        INT32 y = 0;
+        m_stream->GetInt32(y);
+
+        INT32 z = 0;
+        m_stream->GetInt32(z);
+
+        INT32 tileDpi = 0;
+        m_stream->GetInt32(tileDpi);
+
+        STRING tileImageFormat;
+        m_stream->GetString(tileImageFormat);
+
+        double tileExtentOffset = 0.0;
+        m_stream->GetDouble(tileExtentOffset);
+
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? L"MgResourceIdentifier" : resource->ToString().c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(baseMapLayerGroupName.c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(x);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(y);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(z);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_INT32(tileDpi);
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(tileImageFormat.c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_DOUBLE(tileExtentOffset);
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+
+        Validate();
+
+        Ptr<MgByteReader> byteReader = m_service->RenderTileXYZ(map, baseMapLayerGroupName, x, y, z, tileDpi, tileImageFormat, tileExtentOffset);
+
+        EndExecution(byteReader);
+    }
     else
     {
         MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();

Modified: sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -179,65 +179,20 @@
 {
     Ptr<MgByteReader> ret;
 
+    // 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;
+
     MG_TRY()
 
-    CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTile");
-    CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTile");
+    ret = RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow, tileWidth, tileHeight, tileDpi, tileImageFormat, tileExtentOffset);
 
-    // find the finite display scale closest to the requested map scale
-    double scale = map->GetViewScale();
-    INT32 scaleIndex = map->FindNearestFiniteDisplayScaleIndex(scale);
-
-    // if we don't find a nearest scale then something is wrong with the map
-    if (scaleIndex < 0)
-        throw new MgInvalidMapDefinitionException(L"MgServerRenderingService.RenderTile", __LINE__, __WFILE__, NULL, L"", NULL);
-
-    // 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.RenderTile",
-            __LINE__, __WFILE__, &arguments, L"MgMapLayerGroupNameNotFound", NULL);
-    }
-
-    // get the scale at which to render the tile
-    scale = map->GetFiniteDisplayScaleAt(scaleIndex);
-
-    // ensure the tile DPI is set on the map
-    map->SetDisplayDpi(tileDpi);
-
-    // ------------------------------------------------------
-    // the upper left corner of tile (0,0) corresponds to the
-    // upper left corner of the map extent
-    // ------------------------------------------------------
-
-    Ptr<MgEnvelope> mapExtent = map->GetMapExtent();
-    Ptr<MgCoordinate> pt00 = mapExtent->GetLowerLeftCoordinate();
-    Ptr<MgCoordinate> pt11 = mapExtent->GetUpperRightCoordinate();
-    double mapMinX = rs_min(pt00->GetX(), pt11->GetX());
-    double mapMaxX = rs_max(pt00->GetX(), pt11->GetX());
-    double mapMinY = rs_min(pt00->GetY(), pt11->GetY());
-    double mapMaxY = rs_max(pt00->GetY(), pt11->GetY());
-
-    double metersPerUnit  = map->GetMetersPerUnit();
-    double metersPerPixel = METERS_PER_INCH / tileDpi;
-    double tileWidthMCS   = (double)tileWidth  * metersPerPixel * scale / metersPerUnit;
-    double tileHeightMCS  = (double)tileHeight * metersPerPixel * scale / metersPerUnit;
-
-    double tileMinX = mapMinX + (double)(tileColumn  ) * tileWidthMCS;  // left edge
-    double tileMaxX = mapMinX + (double)(tileColumn+1) * tileWidthMCS;  // right edge
-    double tileMinY = mapMaxY - (double)(tileRow   +1) * tileHeightMCS; // bottom edge
-    double tileMaxY = mapMaxY - (double)(tileRow     ) * tileHeightMCS; // top edge
-
-    // make the call to render the tile
-    ret = RenderTile(map, baseGroup, scaleIndex, tileWidth, tileHeight, scale,
-                     tileMinX, tileMaxX, tileMinY, tileMaxY, tileImageFormat);
-
     MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTile")
 
     return ret.Detach();
@@ -312,123 +267,20 @@
 {
     Ptr<MgByteReader> ret;
 
-    MG_TRY()
-
-    CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTileXYZ");
-    CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTileXYZ");
-    
-    // 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.RenderTileXYZ",
-            __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
-    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);
+        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;
+    MG_TRY()
 
-    if (mapAR >= screenAR)
-    {
-        scale = extent.width() * map->GetMetersPerUnit() / METERS_PER_INCH * (double)dpi / (double)width;
+    ret = RenderTileXYZ(map, baseMapLayerGroupName, x, y, z, dpi, tileImageFormat, tileExtentOffset);
 
-        // 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);
-
-    // initialize the renderer (set clipping to false so that we label
-    // the unclipped geometry)
-    auto_ptr<SE_Renderer> dr(CreateRenderer(drawWidth, drawHeight, bgColor, false, true, tileExtentOffset));
-
-    // 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);
-
-    // call the internal helper API to do all the stylization overhead work
-    ret = RenderMapInternal(map, NULL, roLayers, dr.get(), drawWidth, drawHeight, width, height, tileImageFormat, scale, extent, true, true, false, NULL);
-
-    // restore the base group's visibility
-    baseGroup->SetVisible(groupVisible);
-
     MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTileXYZ")
 
     return ret.Detach();
@@ -626,17 +478,18 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 /// render a map using all layers from the baseGroup
-MgByteReader* MgServerRenderingService::RenderTile(MgMap* map,
-                                                   MgLayerGroup* baseGroup,
-                                                   INT32 scaleIndex,
-                                                   INT32 width,
-                                                   INT32 height,
-                                                   double scale,
-                                                   double mcsMinX,
-                                                   double mcsMaxX,
-                                                   double mcsMinY,
-                                                   double mcsMaxY,
-                                                   CREFSTRING format)
+MgByteReader* MgServerRenderingService::RenderTileInternal(MgMap* map,
+                                                           MgLayerGroup* baseGroup,
+                                                           INT32 scaleIndex,
+                                                           INT32 width,
+                                                           INT32 height,
+                                                           double scale,
+                                                           double mcsMinX,
+                                                           double mcsMaxX,
+                                                           double mcsMinY,
+                                                           double mcsMaxY,
+                                                           CREFSTRING format,
+                                                           double tileExtentOffset)
 {
     Ptr<MgByteReader> ret;
 
@@ -652,16 +505,6 @@
     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;
-
     // initialize the renderer (set clipping to false so that we label
     // the unclipped geometry)
     auto_ptr<SE_Renderer> dr(CreateRenderer(width, height, bgColor, false, true, tileExtentOffset));
@@ -2552,3 +2395,203 @@
 
     return bs->GetReader();
 }
+
+MgByteReader* MgServerRenderingService::RenderTile(MgMap* map,
+                                                   CREFSTRING baseMapLayerGroupName,
+                                                   INT32 tileColumn,
+                                                   INT32 tileRow,
+                                                   INT32 tileWidth,
+                                                   INT32 tileHeight,
+                                                   INT32 tileDpi,
+                                                   CREFSTRING tileImageFormat,
+                                                   double tileExtentOffset)
+{
+    Ptr<MgByteReader> ret;
+
+    MG_TRY()
+
+    CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTile");
+    CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTile");
+
+    // find the finite display scale closest to the requested map scale
+    double scale = map->GetViewScale();
+    INT32 scaleIndex = map->FindNearestFiniteDisplayScaleIndex(scale);
+
+    // if we don't find a nearest scale then something is wrong with the map
+    if (scaleIndex < 0)
+        throw new MgInvalidMapDefinitionException(L"MgServerRenderingService.RenderTile", __LINE__, __WFILE__, NULL, L"", NULL);
+
+    // 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.RenderTile",
+            __LINE__, __WFILE__, &arguments, L"MgMapLayerGroupNameNotFound", NULL);
+    }
+
+    // get the scale at which to render the tile
+    scale = map->GetFiniteDisplayScaleAt(scaleIndex);
+
+    // ensure the tile DPI is set on the map
+    map->SetDisplayDpi(tileDpi);
+
+    // ------------------------------------------------------
+    // the upper left corner of tile (0,0) corresponds to the
+    // upper left corner of the map extent
+    // ------------------------------------------------------
+
+    Ptr<MgEnvelope> mapExtent = map->GetMapExtent();
+    Ptr<MgCoordinate> pt00 = mapExtent->GetLowerLeftCoordinate();
+    Ptr<MgCoordinate> pt11 = mapExtent->GetUpperRightCoordinate();
+    double mapMinX = rs_min(pt00->GetX(), pt11->GetX());
+    double mapMaxX = rs_max(pt00->GetX(), pt11->GetX());
+    double mapMinY = rs_min(pt00->GetY(), pt11->GetY());
+    double mapMaxY = rs_max(pt00->GetY(), pt11->GetY());
+
+    double metersPerUnit  = map->GetMetersPerUnit();
+    double metersPerPixel = METERS_PER_INCH / tileDpi;
+    double tileWidthMCS   = (double)tileWidth  * metersPerPixel * scale / metersPerUnit;
+    double tileHeightMCS  = (double)tileHeight * metersPerPixel * scale / metersPerUnit;
+
+    double tileMinX = mapMinX + (double)(tileColumn  ) * tileWidthMCS;  // left edge
+    double tileMaxX = mapMinX + (double)(tileColumn+1) * tileWidthMCS;  // right edge
+    double tileMinY = mapMaxY - (double)(tileRow   +1) * tileHeightMCS; // bottom edge
+    double tileMaxY = mapMaxY - (double)(tileRow     ) * tileHeightMCS; // top edge
+
+    // make the call to render the tile
+    ret = RenderTileInternal(map, baseGroup, scaleIndex, tileWidth, tileHeight, scale,
+                             tileMinX, tileMaxX, tileMinY, tileMaxY, tileImageFormat,
+                             tileExtentOffset);
+
+    MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTile")
+
+    return ret.Detach();
+}
+
+MgByteReader* MgServerRenderingService::RenderTileXYZ(MgMap* map,
+                                                      CREFSTRING baseMapLayerGroupName,
+                                                      INT32 x,
+                                                      INT32 y,
+                                                      INT32 z,
+                                                      INT32 dpi,
+                                                      CREFSTRING tileImageFormat,
+                                                      double tileExtentOffset)
+{
+    Ptr<MgByteReader> ret;
+
+    MG_TRY()
+
+    CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTileXYZ");
+    CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTileXYZ");
+    
+    // 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.RenderTileXYZ",
+            __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
+    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;
+    
+    // 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);
+
+    // initialize the renderer (set clipping to false so that we label
+    // the unclipped geometry)
+    auto_ptr<SE_Renderer> dr(CreateRenderer(drawWidth, drawHeight, bgColor, false, true, tileExtentOffset));
+
+    // 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);
+
+    // call the internal helper API to do all the stylization overhead work
+    ret = RenderMapInternal(map, NULL, roLayers, dr.get(), drawWidth, drawHeight, width, height, tileImageFormat, scale, extent, true, true, false, NULL);
+
+    // restore the base group's visibility
+    baseGroup->SetVisible(groupVisible);
+
+    MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTileXYZ")
+
+    return ret.Detach();
+}
\ No newline at end of file

Modified: sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Rendering/ServerRenderingService.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -56,6 +56,16 @@
                                      INT32 tileDpi,
                                      CREFSTRING tileImageFormat);
 
+    virtual MgByteReader* RenderTile(MgMap* map,
+                                     CREFSTRING baseMapLayerGroupName,
+                                     INT32 tileColumn,
+                                     INT32 tileRow,
+                                     INT32 tileWidth,
+                                     INT32 tileHeight,
+                                     INT32 tileDpi,
+                                     CREFSTRING tileImageFormat,
+                                     double tileExtentOffset);
+
     virtual MgByteReader* RenderTileXYZ(MgMap* map,
                                         CREFSTRING baseMapLayerGroupName,
                                         INT32 x,
@@ -70,6 +80,15 @@
                                         INT32 dpi,
                                         CREFSTRING tileImageFormat);
 
+    virtual MgByteReader* RenderTileXYZ(MgMap* map,
+                                        CREFSTRING baseMapLayerGroupName,
+                                        INT32 x,
+                                        INT32 y,
+                                        INT32 z,
+                                        INT32 dpi,
+                                        CREFSTRING tileImageFormat,
+                                        double tileExtentOffset);
+
     virtual MgByteReader* RenderTileUTFGrid(MgMap* map,
                                             CREFSTRING baseMapLayerGroupName,
                                             INT32 x,
@@ -246,17 +265,18 @@
 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,
-                             INT32 scaleIndex,
-                             INT32 width,
-                             INT32 height,
-                             double scale,
-                             double mcsMinX,
-                             double mcsMaxX,
-                             double mcsMinY,
-                             double mcsMaxY,
-                             CREFSTRING format);
+    MgByteReader* RenderTileInternal(MgMap* map,
+                                     MgLayerGroup* baseGroup,
+                                     INT32 scaleIndex,
+                                     INT32 width,
+                                     INT32 height,
+                                     double scale,
+                                     double mcsMinX,
+                                     double mcsMaxX,
+                                     double mcsMinY,
+                                     double mcsMaxY,
+                                     CREFSTRING format,
+                                     double tileExtentOffset);
 
     // helper used by other methods
     MgByteReader* RenderMapInternal(MgMap* map,

Modified: sandbox/jng/tiling_v2/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Tile/ServerTileService.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Tile/ServerTileService.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -313,6 +313,22 @@
         xml.append("<DefaultValue></DefaultValue>\n");
         xml.append("</ConnectionProperty>\n");
 
+        //Property: TileExtentOffset
+        xml.append("<ConnectionProperty Enumerable=\"false\" Protected=\"false\" Required=\"true\">\n");
+        xml.append("<Name>");
+        std::string mbTileExtentOffset;
+        MgUtil::WideCharToMultiByte(MG_TILE_PROVIDER_COMMON_PARAM_TILEEXTENTOFFSET, mbTileExtentOffset);
+        xml.append(mbTileExtentOffset);
+        xml.append("</Name>\n");
+        xml.append("<LocalizedName>");
+        std::string mbLocTileExtentOffset;
+        STRING wLocTileExtentOffset = MgUtil::GetResourceMessage(MgResources::TileService, L"MgTileProvider_Common_Property_TileExtentOffset_LocalizedName");
+        MgUtil::WideCharToMultiByte(wLocTileExtentOffset, mbLocTileExtentOffset);
+        xml.append(mbLocTileExtentOffset);
+        xml.append("</LocalizedName>\n");
+        xml.append("<DefaultValue></DefaultValue>\n");
+        xml.append("</ConnectionProperty>\n");
+
         xml.append("</ConnectionProperties>\n");
         xml.append("</TileProvider>\n");
     }
@@ -397,6 +413,23 @@
         xml.append("<DefaultValue>false</DefaultValue>\n");
         xml.append("</ConnectionProperty>\n");
 
+        //Property: TileExtentOffset
+        xml.append("<ConnectionProperty Enumerable=\"false\" Protected=\"false\" Required=\"true\">\n");
+        xml.append("<Name>");
+        std::string mbTileExtentOffset;
+        MgUtil::WideCharToMultiByte(MG_TILE_PROVIDER_COMMON_PARAM_TILEEXTENTOFFSET, mbTileExtentOffset);
+        xml.append(mbTileExtentOffset);
+        xml.append("</Name>\n");
+        xml.append("<LocalizedName>");
+        std::string mbLocTileExtentOffset;
+        STRING wLocTileExtentOffset = MgUtil::GetResourceMessage(MgResources::TileService, L"MgTileProvider_Common_Property_TileExtentOffset_LocalizedName");
+        MgUtil::WideCharToMultiByte(wLocTileExtentOffset, mbLocTileExtentOffset);
+        xml.append(mbLocTileExtentOffset);
+        xml.append("</LocalizedName>\n");
+        xml.append("<DefaultValue></DefaultValue>\n");
+        xml.append("</ConnectionProperty>\n");
+
+
         xml.append("</ConnectionProperties>\n");
         xml.append("</TileProvider>\n");
     }
@@ -503,6 +536,7 @@
         MdfModel::NameStringPairCollection* parameters = tilesetParams->GetParameters();
         INT32 width = 300;
         INT32 height = 300;
+        double tileExtentOffset = MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset;
         STRING format = L"PNG";
         STRING path;
         bool bRenderOnly = false;
@@ -529,6 +563,14 @@
             {
                 bRenderOnly = MgUtil::StringToBoolean(pair->GetValue());
             }
+            else if (pair->GetName() == MG_TILE_PROVIDER_COMMON_PARAM_TILEEXTENTOFFSET)
+            {
+                tileExtentOffset = MgUtil::StringToDouble(pair->GetValue());
+                if (tileExtentOffset < 0.0)
+                {
+                    tileExtentOffset = MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset;
+                }
+            }
         }
 
         //If we find the cache path substitution tag, replace it with the default path from the configuration
@@ -537,12 +579,13 @@
             path = MgTileParameters::tileCachePath;
         }
 
-        cache = new MgTileCacheDefaultProvider(tileSetId, path, width, height, format, bRenderOnly);
+        cache = new MgTileCacheDefaultProvider(tileSetId, path, width, height, format, bRenderOnly, tileExtentOffset);
     }
     else if (provider == MG_TILE_PROVIDER_XYZ)
     {
         MdfModel::NameStringPairCollection* parameters = tilesetParams->GetParameters();
         STRING format = L"PNG";
+        double tileExtentOffset = MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset;
         STRING path;
         bool bRenderOnly = false;
         for (INT32 i = 0; i < parameters->GetCount(); i++)
@@ -560,6 +603,14 @@
             {
                 bRenderOnly = MgUtil::StringToBoolean(pair->GetValue());
             }
+            else if (pair->GetName() == MG_TILE_PROVIDER_COMMON_PARAM_TILEEXTENTOFFSET)
+            {
+                tileExtentOffset = MgUtil::StringToDouble(pair->GetValue());
+                if (tileExtentOffset < 0.0)
+                {
+                    tileExtentOffset = MgConfigProperties::DefaultRenderingServicePropertyTileExtentOffset;
+                }
+            }
         }
 
         //If we find the cache path substitution tag, replace it with the default path from the configuration
@@ -568,7 +619,7 @@
             path = MgTileParameters::tileCachePath;
         }
 
-        cache = new MgTileCacheXYZProvider(tileSetId, path, format, bRenderOnly);
+        cache = new MgTileCacheXYZProvider(tileSetId, path, format, bRenderOnly, tileExtentOffset);
     }
     else 
     {

Modified: sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -18,7 +18,7 @@
 #include "MapGuideCommon.h"
 #include "TileCacheDefaultProvider.h"
 
-MgTileCacheDefaultProvider::MgTileCacheDefaultProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, INT32 tileWidth, INT32 tileHeight, CREFSTRING format, bool bRenderOnly)
+MgTileCacheDefaultProvider::MgTileCacheDefaultProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, INT32 tileWidth, INT32 tileHeight, CREFSTRING format, bool bRenderOnly, double tileExtentOffset)
 {
     m_tilesetId = SAFE_ADDREF(tileSetId);
     m_path = path;
@@ -26,6 +26,7 @@
     m_tileHeight = tileHeight;
     m_format = format;
     m_renderOnly = bRenderOnly;
+    m_tileExtentOffset = tileExtentOffset;
 }
 
 MgTileCacheDefaultProvider::~MgTileCacheDefaultProvider()
@@ -64,7 +65,7 @@
     if (svcRendering != NULL)
     {
         // generate the tile
-        img = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow, GetDefaultTileSizeX(), GetDefaultTileSizeY(), map->GetDisplayDpi(), GetTileFormat());
+        img = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow, GetDefaultTileSizeX(), GetDefaultTileSizeY(), map->GetDisplayDpi(), GetTileFormat(), m_tileExtentOffset);
 
         // cache the tile
         if (!m_renderOnly)

Modified: sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.h
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheDefaultProvider.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -22,7 +22,7 @@
 class MG_SERVER_TILE_API MgTileCacheDefaultProvider : public MgTileCacheDefault
 {
 public:
-    MgTileCacheDefaultProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, INT32 tileWidth, INT32 tileHeight, CREFSTRING format, bool bRenderOnly);
+    MgTileCacheDefaultProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, INT32 tileWidth, INT32 tileHeight, CREFSTRING format, bool bRenderOnly, double tileExtentOffset);
     virtual ~MgTileCacheDefaultProvider();
 
     virtual MgByteReader* GetTile(CREFSTRING baseMapLayerGroupName,
@@ -53,6 +53,7 @@
     INT32 m_tileHeight;
     STRING m_format;
     bool m_renderOnly;
+    double m_tileExtentOffset;
 };
 
 #endif
\ No newline at end of file

Modified: sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.cpp
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.cpp	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.cpp	2019-04-15 11:39:50 UTC (rev 9491)
@@ -18,12 +18,13 @@
 #include "MapGuideCommon.h"
 #include "TileCacheXYZProvider.h"
 
-MgTileCacheXYZProvider::MgTileCacheXYZProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, CREFSTRING format, bool bRenderOnly)
+MgTileCacheXYZProvider::MgTileCacheXYZProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, CREFSTRING format, bool bRenderOnly, double tileExtentOffset)
 {
     m_tilesetId = SAFE_ADDREF(tileSetId);
     m_path = path;
     m_format = format;
     m_renderOnly = bRenderOnly;
+    m_tileExtentOffset = tileExtentOffset;
 }
 
 MgTileCacheXYZProvider::~MgTileCacheXYZProvider()
@@ -70,7 +71,7 @@
         else //Assume it must be image-based at this point
         {
             // generate the tile
-            img = svcRendering->RenderTileXYZ(map, baseMapLayerGroupName, tileRow, tileColumn, scaleIndex, map->GetDisplayDpi(), m_format);
+            img = svcRendering->RenderTileXYZ(map, baseMapLayerGroupName, tileRow, tileColumn, scaleIndex, map->GetDisplayDpi(), m_format, m_tileExtentOffset);
         }
         // cache the tile
         if (!m_renderOnly)

Modified: sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.h
===================================================================
--- sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.h	2019-03-29 10:18:34 UTC (rev 9490)
+++ sandbox/jng/tiling_v2/Server/src/Services/Tile/TileCacheXYZProvider.h	2019-04-15 11:39:50 UTC (rev 9491)
@@ -22,7 +22,7 @@
 class MG_SERVER_TILE_API MgTileCacheXYZProvider : public MgTileCacheDefault
 {
 public:
-    MgTileCacheXYZProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, CREFSTRING format, bool bRenderOnly);
+    MgTileCacheXYZProvider(MgResourceIdentifier* tileSetId, CREFSTRING path, CREFSTRING format, bool bRenderOnly, double tileExtentOffset);
     virtual ~MgTileCacheXYZProvider();
 
     virtual MgByteReader* GetTile(CREFSTRING baseMapLayerGroupName,
@@ -57,6 +57,7 @@
     STRING m_path;
     STRING m_format;
     bool m_renderOnly;
+    double m_tileExtentOffset;
 };
 
 #endif
\ No newline at end of file



More information about the mapguide-commits mailing list