[mapguide-commits] r9630 - in trunk/MgDev: . Common/CoordinateSystem Common/Foundation/Data Common/Geometry Common/Geometry/Spatial Common/MapGuideCommon/Services Common/Renderers Common/Stylization Doc/samples Doc/samples/ol2samples Doc/samples/ol2samples/wms Doc/samples/ol2samples/xyz Server/src/Services/Mapping Server/src/Services/Rendering Server/src/Services/Tile Server/src/UnitTesting UnitTest/TestData/Samples/Sheboygan UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Sun Oct 6 05:18:03 PDT 2019
Author: jng
Date: 2019-10-06 05:18:03 -0700 (Sun, 06 Oct 2019)
New Revision: 9630
Added:
trunk/MgDev/Common/Geometry/Spatial/SpatialUtilities.h
trunk/MgDev/Common/Renderers/MVTRenderer.cpp
trunk/MgDev/Common/Renderers/MVTRenderer.h
trunk/MgDev/Common/Renderers/mvt/
trunk/MgDev/Doc/samples/ol2samples/mvt/
trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.cpp
trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.h
trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml
trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml
Removed:
trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
Modified:
trunk/MgDev/
trunk/MgDev/CMakeLists.txt
trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
trunk/MgDev/Common/Foundation/Data/ByteSink.cpp
trunk/MgDev/Common/Foundation/Data/MimeType.cpp
trunk/MgDev/Common/Foundation/Data/MimeType.h
trunk/MgDev/Common/Geometry/ArcSegment.cpp
trunk/MgDev/Common/Geometry/GeosUtil.cpp
trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
trunk/MgDev/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp
trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.h
trunk/MgDev/Common/MapGuideCommon/Services/RenderingDefs.h
trunk/MgDev/Common/MapGuideCommon/Services/RenderingService.h
trunk/MgDev/Common/Renderers/CMakeLists.txt
trunk/MgDev/Common/Renderers/Renderers.vcxproj
trunk/MgDev/Common/Renderers/Renderers.vcxproj.filters
trunk/MgDev/Common/Stylization/DefaultStylizer.cpp
trunk/MgDev/Common/Stylization/LineBuffer.cpp
trunk/MgDev/Common/Stylization/RS_FeatureReader.h
trunk/MgDev/Common/Stylization/Renderer.h
trunk/MgDev/Common/Stylization/RendererStyles.h
trunk/MgDev/Common/Stylization/SE_Renderer.cpp
trunk/MgDev/Common/Stylization/SE_Renderer.h
trunk/MgDev/Common/Stylization/StylizationEngine.cpp
trunk/MgDev/Doc/samples/ol2samples/wms/index.html
trunk/MgDev/Doc/samples/ol2samples/xyz/index_ol.html
trunk/MgDev/Doc/samples/samples.php
trunk/MgDev/License.txt
trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.cpp
trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.h
trunk/MgDev/Server/src/Services/Mapping/ServerMappingService.vcxproj
trunk/MgDev/Server/src/Services/Rendering/RenderingOperationFactory.cpp
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.h
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp
trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
trunk/MgDev/Server/src/Services/Tile/TileCacheXYZProvider.cpp
trunk/MgDev/Server/src/UnitTesting/CMakeLists.txt
trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp
trunk/MgDev/Server/src/UnitTesting/TestMisc.h
trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp
trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h
trunk/MgDev/Server/src/UnitTesting/UnitTesting.vcxproj
trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml
trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/MgResourcePackageManifest.xml
Log:
Implement MapGuide RFC 177
Merged revision(s) 9604-9629 from sandbox/jng/mvt_alt:
Index: trunk/MgDev
===================================================================
--- trunk/MgDev 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev 2019-10-06 12:18:03 UTC (rev 9630)
Property changes on: trunk/MgDev
___________________________________________________________________
Modified: svn:mergeinfo
## -19,6 +19,8 ##
/sandbox/jng/fusion_entrypoint_refactor:9400-9406
/sandbox/jng/geoprocessing:9205-9229
/sandbox/jng/geos34x:8256-8259
+/sandbox/jng/mvt:9527-9528,9535,9537,9546-9547
+/sandbox/jng/mvt_alt:9604-9629
/sandbox/jng/ogc:9240-9255
/sandbox/jng/php56x:8975-8985
/sandbox/jng/querymapfeatures_selectionkey:9590-9591
## -32,5 +34,4 ##
/sandbox/jng/v30:8212-8227
/sandbox/jng/v4:9511-9519
/sandbox/jng/wfs_hits:9569-9577
-/sandbox/rfc94:5099-5163
-/trunk/MgDev:9397-9399
\ No newline at end of property
+/sandbox/rfc94:5099-5163
\ No newline at end of property
Modified: trunk/MgDev/CMakeLists.txt
===================================================================
--- trunk/MgDev/CMakeLists.txt 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/CMakeLists.txt 2019-10-06 12:18:03 UTC (rev 9630)
@@ -62,13 +62,13 @@
if (NOT MG_VERSION_MAJOR)
set(MG_VERSION_MAJOR 4)
-endif (MG_VERSION_MAJOR)
+endif (NOT MG_VERSION_MAJOR)
if (NOT MG_VERSION_MINOR)
set(MG_VERSION_MINOR 0)
-endif (MG_VERSION_MINOR)
+endif (NOT MG_VERSION_MINOR)
if (NOT MG_VERSION_RELEASE)
set(MG_VERSION_RELEASE 0)
-endif (MG_VERSION_RELEASE)
+endif (NOT MG_VERSION_RELEASE)
if (NOT MG_VERSION_REV)
set(MG_VERSION_REV 0)
endif (NOT MG_VERSION_REV)
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -20,7 +20,7 @@
#include "CoordSysUtil.h"
#include "CriticalSection.h"
#include "Spatial/MathUtility.h"
-#include "Spatial/SpatialUtility.h"
+#include "Spatial/SpatialUtilities.h"
#include "CoordSys.h"
#include "CoordSysGrids.h"
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -21,7 +21,7 @@
#include "CriticalSection.h" //for SmartCriticalClass
#include "Spatial/MathUtility.h"
-#include "Spatial/SpatialUtility.h"
+#include "Spatial/SpatialUtilities.h"
#include "CoordSysGrids.h"
#include "CoordSysOneGrid.h"
#include "CoordSysMgrsZone.h"
Modified: trunk/MgDev/Common/Foundation/Data/ByteSink.cpp
===================================================================
--- trunk/MgDev/Common/Foundation/Data/ByteSink.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Foundation/Data/ByteSink.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -80,6 +80,7 @@
if (!mimeType.empty()
&& mimeType.find(L"text") == STRING::npos
+ && MgMimeType::Mvt != mimeType
&& MgMimeType::Binary != mimeType)
{
// Note that the mime type of resource data is determined by the
Modified: trunk/MgDev/Common/Foundation/Data/MimeType.cpp
===================================================================
--- trunk/MgDev/Common/Foundation/Data/MimeType.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Foundation/Data/MimeType.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -37,3 +37,4 @@
const STRING MgMimeType::Kml = L"application/vnd.google-earth.kml+xml";
const STRING MgMimeType::Kmz = L"application/vnd.google-earth.kmz";
const STRING MgMimeType::Meta = L"application/metatile";
+const STRING MgMimeType::Mvt = L"application/vnd.mapbox-vector-tile";
\ No newline at end of file
Modified: trunk/MgDev/Common/Foundation/Data/MimeType.h
===================================================================
--- trunk/MgDev/Common/Foundation/Data/MimeType.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Foundation/Data/MimeType.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -87,6 +87,10 @@
/// \brief
/// application/metatile
static const STRING Meta; ///\if INTERNAL value("application/metatile") \endif
+
+ /// \brief
+ /// application/vnd.mapbox-vector-tile
+ static const STRING Mvt; ///\if INTERNAL value("application/vnd.mapbox-vector-tile") \endif
};
/// \}
Modified: trunk/MgDev/Common/Geometry/ArcSegment.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/ArcSegment.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Geometry/ArcSegment.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -16,7 +16,7 @@
//
#include "GeometryCommon.h"
-#include "Spatial/SpatialUtility.h"
+#include "Spatial/SpatialUtilities.h"
//////////////////////////////////////////////////////////////////
// Construct a MgArcSegment object
Modified: trunk/MgDev/Common/Geometry/GeosUtil.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/GeosUtil.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Geometry/GeosUtil.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -25,7 +25,7 @@
#include "Buffer/buffer.h"
#include "GeosUtil.h"
#include "GeometryExceptionDef.h"
-#include "Spatial/SpatialUtility.h"
+#include "Spatial/SpatialUtilities.h"
#include "GeometricEntityType.h"
using namespace geos;
Copied: trunk/MgDev/Common/Geometry/Spatial/SpatialUtilities.h (from rev 9629, sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilities.h)
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtilities.h (rev 0)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtilities.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,380 @@
+//
+// Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef MgSpatialUtilities_H
+#define MgSpatialUtilities_H
+
+// NOTE: This header has been renamed to avoid collison with FDO's spatial utility header
+// of the same name and relative path!
+
+/// \cond INTERNAL
+
+/// \brief
+/// Spatial utility class.
+class MgSpatialUtility
+{
+public:
+
+ /// Converts arcs to linestrings
+ static MgGeometry* TesselateCurve(MgGeometry* curve);
+ /// Converts arcs to linestrings
+ static MgGeometryComponent* TesselateGeometryComponent(MgGeometryComponent* curve);
+
+ /// \brief
+ /// Approximates a geometry, which may contain parametric curve components,
+ /// with a geometry that only contains straight, linear components.
+ ///
+ /// \remarks
+ /// If the given geometry does not require approximation, this method returns
+ /// the input geometry, and thus avoids unnecessary object creation.
+ /// Tolerances are in same units as the geometry's ordinates.
+ /// If the given tolerances are both zero, a tesselated geometry is produced,
+ /// wherein arcs are represented using only their three defining positions.
+ /// Math performed is all in implicit Cartesian (rectilinear) coordinate system.
+ /// Measurement ("M") ordinates of interpolated positions undergo linear
+ /// interpolation from an arc's start position to end position (possibly disregarding
+ /// an "M" ordinate in the arc's mid position).
+ /// Unless the arc is too short for any interpolation, the "mid" point parameter
+ /// used to define arcs is not guaranteed to appear among interpolated points.
+ ///
+ /// \param geometry
+ /// Input Geometry to approximate
+ /// \param maxSpacing
+ /// Input Maximum length of each line segment used to approximate parametric curves. Ignored if zero.
+ /// \param maxOffset
+ /// Input Maximum distance that a line segment may be from the curve that it approximates (error tolerance). Ignored if zero.
+ /// \param geometryFactory
+ /// Input Geometry factory for the creation of the approximated geometry.
+ ///
+ /// \return
+ /// Returns An approximation of the given geometry.
+ ///
+ static MgGeometry * ApproximateGeometryWithLineStrings(
+ MgGeometry * geometry,
+ double maxSpacing,
+ double maxOffset,
+ MgGeometryFactory* geometryFactory);
+
+ static bool ArePositionsEqualXYZ(
+ MgCoordinate * p1,
+ MgCoordinate * p2);
+
+ static bool ArePositionsEqualXY(
+ MgCoordinate * p1,
+ MgCoordinate * p2);
+
+ static double DistanceBetweenPositionsXYZ(
+ MgCoordinate * p1,
+ MgCoordinate * p2);
+
+ static double DistanceBetweenPositionsXY(
+ MgCoordinate * p1,
+ MgCoordinate * p2);
+
+ /// Unit normal from plane defined by vectors p1p2 to p2p3 using right-hand rule.
+ /// This will return (0,0,0) for parallel vectors (collinear points) or zero-length
+ /// vectors.
+ static MgCoordinate * UnitNormalVector(
+ MgCoordinate * p1,
+ MgCoordinate * p2,
+ MgCoordinate * p3);
+
+ static void AppendPositionToDistinctCollection(
+ MgCoordinateCollection * distinctPositions,
+ MgCoordinate * positionToAppend);
+
+ /// Return a new point with the location of the given point after rotation
+ /// about the given axis and center.
+ /// This method assumes that the involved data has XYZ dimensionality.
+ /// <p><b>Note:</b> "axisVector" must be a unit normal to the plane of rotation.
+ static MgCoordinate * RotatePosition(
+ MgCoordinate * position,
+ double angle,
+ MgCoordinate * axisVector,
+ MgCoordinate * center,
+ bool includeM,
+ double m);
+
+ static MgLinearRing* CurveRingToLinearRing(MgCurveRing* curveRing, double maxSpacing, double maxOffset);
+ static MgLinearSegment* ArcSegmentToLinearSegment(MgArcSegment* segment, double maxSpacing, double maxOffset);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Extracts the greatest magnitude of the all the coordinates in a
+ /// coordinate collection. Return value is always positive.
+ /// </summary>
+ /// <param name="coordinteIterator">
+ /// An iterator dervied from the target coordinate collection.
+ /// </param>
+ /// <returns>
+ /// Returns a positive value which is the largest magnitude of all
+ /// ordinates in the collection.
+ /// </returns>
+ /// <remarks>
+ /// Intended to be used to determine a suitable tolerance value for such
+ /// things as coordinate comparisons.
+ /// </remarks>
+ static double GreatestMagnitude (MgCoordinateIterator* coordinateIterator);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Computes the intersection of two 2D line segments. Intersection point,
+ /// if any, is returned in the provided result coordinate which (of course)
+ /// must already exist. All point arguments are expected (not required)
+ /// to be MgCoordinateXY objects.
+ /// </summary>
+ /// <param name="result">
+ /// The calculated intersection point is returned in this variable which,
+ /// of course, must exist. Coordinates of <c>result</c> remain unaltered
+ /// if an intersection does not exist. Only X and Y are returned.
+ /// </param>
+ /// <param name="seg1From">
+ /// The initial point of the first line segment.
+ /// </param>
+ /// <param name="seg1To">
+ /// The end point of the first line segment.
+ /// </param>
+ /// <param name="seg2From">
+ /// The initial point of the second line segment.
+ /// </param>
+ /// <param name="seg2To">
+ /// The end point of the second line segment.
+ /// </param>
+ /// <param name="magnitude">
+ /// A value which represents the greatest coordinate value in the dataset
+ /// being processed. Used to calculate an appropriate "fuzzy" value for
+ /// coordinate comparisions, etc.
+ /// </param>
+ /// <returns>
+ /// Return status of the intersection of the two segments as a bit map of
+ /// values as defined in <c>SpatialUtilityStatus.h</c>
+ /// </returns>
+ /// <remarks>
+ /// In determining if the intersection point resides on a line, an intersection
+ /// point identical to the 'to' point is considered on the line, but an
+ /// intersection point identical to the 'from' point is _NOT_ considered to be
+ /// on the line. Such a convention is necessary to avoid the appearance
+ /// of two intersections when indeed there is only one when processing a
+ /// a line string, for example.
+ /// </remarks>
+ /// <exception cref="MgNullReferenceException">
+ /// Thrown if any argument is null
+ /// </exception>
+ static INT32 SegmentIntersection (MgCoordinate* result,MgCoordinate* seg1From,
+ MgCoordinate* seg1To,
+ MgCoordinate* seg2From,
+ MgCoordinate* seg2To,
+ double magnitude = 1.0E+10);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Returns a collection of coordinates with all of the intersection points of
+ /// the provided segment with the polygon provided by the first argument.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring to which the provided segment is
+ /// intersected.
+ /// </param>
+ /// <param name="segFrom">
+ /// The initial point of the line segment to be intersected with the provided
+ /// closed ring.
+ /// </param>
+ /// <param name="segTo">
+ /// The ending point of the line segment to be intersected with the provided
+ /// closed ring.
+ /// </param>
+ /// <returns>
+ /// A new collection of <c>MgCoordinateXYM</c> points, one such point for each
+ /// intersection is returned. This collection can be, and often is, an empty
+ /// collection. A null pointer is never returned.<para>
+ /// The X and Y ordinates of each point in the returned collection represent
+ /// the actual location of the intersection. The M ordinate will carry, as
+ /// a double, the status of the intersection as returned by the
+ /// <c>SegmentIntersection</c> function.
+ /// </returns>
+ static MgCoordinateCollection* PolySegIntersection (MgCoordinateIterator* polyItr,
+ MgCoordinate* segFrom,
+ MgCoordinate* segTo);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Adds a coordinate to a coordinate collection such that the resulting
+ /// collection represents a collection of points in sequence from the
+ /// provided base point.
+ /// </summary>
+ /// <param name="collection">
+ /// The coordinate collection to which the <c>newPoint</c> is to be added.
+ /// </param>
+ /// <param name="newPoint">
+ /// The point to be added to the provided collection.
+ /// </param>
+ /// <param name="basePoint">
+ /// The base point which is used to order the collection.
+ /// </param>
+ /// <returns>
+ /// the index at which the insertion occurred.
+ /// </returns>
+ /// <remarks>
+ /// The purpose of this function is serve as a helper for the PolySegIntersection
+ /// function. It enables PolySegIntersection to return a point collection such
+ /// that the points in the collection present an orderly sequence of points from
+ /// the provided base point. Thus, if the original line segment provided to
+ /// PolySegIntersection proceeded in the south to north direction, the point
+ /// collection returned would also be returned in that order; regardless of the
+ /// shape of the polygon or the direction in which it proceeds.<para>
+ /// The determination as to the insertion point of <c>newPoint</c> is based solely
+ /// on the X and Y ordinates of <c>newPoint</c> and the points which already
+ /// exist in the provided collection. The type of <c>newPoint</c> and the points
+ /// in the collection is immaterial.
+ /// </remarks>
+ static INT32 AddToCoordinateCollection (MgCoordinateCollection* collection,MgCoordinate* newPoint,
+ MgCoordinate* basePoint);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Determines if the provided point is inside (or actually on) the closed
+ /// ring provided by the <c>polyItr</c> argument.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring which is the subject polygon.
+ /// </param>
+ /// <param name="queryPoint">
+ /// The 2D point whose status is to be determined.
+ /// </param>
+ /// <returns>
+ /// Returns zero if the query point is outside the closed ring, +1 if the
+ /// query point is precisely on the closed ring (per MgMathUtility::DblCmp),
+ /// or +2 if the query point is inside the closed ring.
+ /// </returns>
+ /// <remarks>
+ /// Currently, this function calculates the envelope of the provided closed
+ /// ring in order to determine a point which is known to be outside of the
+ /// closed ring. An overloaded function which accepts a point known to be
+ /// outside the closed ring which is a lot faster is also available.
+ /// </remarks>
+ static INT32 PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* queryPoint);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Determines a point guaranteed to be ouside the provided polygon.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring which is the subject polygon.
+ /// </param>
+ /// <returns>
+ /// Returns an <c>MgCoordinateXY</c> point which is guaranteed to be ooutside
+ /// the provided polygon.
+ /// </returns>
+ static MgCoordinate* PointOutsidePolygon (MgCoordinateIterator* polyItr);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Determines if the provided point is inside (or actually on) the closed
+ /// ring provided by the <c>polyItr</c> argument.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring which is the subject polygon.
+ /// </param>
+ /// <param name="outsidePoint">
+ /// A 2D point which is known to be outside of the provided polygon. Can
+ /// be obtained from <c>PointOutsidePolygon</c>.
+ /// <param name="queryPoint">
+ /// The 2D point whose status is to be determined.
+ /// </param>
+ /// <returns>
+ /// Returns zero if the query point is outside the closed ring, +1 if the
+ /// query point is precisely on the closed ring (per MgMathUtility::DblCmp),
+ /// or +2 if the query point is inside the closed ring.
+ /// </returns>
+ /// <remarks>
+ /// This function requires that the calling module supply a point known to
+ /// be outside the polygon. Thus, higher performance can be obtained when
+ /// multiple queries against the same polygon are required.
+ /// </remarks>
+ static INT32 PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* outsidePoint,
+ MgCoordinate* queryPoint);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Clips a line string to an arbitrary polygon returning a collection of line
+ /// strings which represent the portions of the provided line string which are
+ /// inside the provided closed ring.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator to the closed ring to which the provided line string is to be
+ /// clipped.
+ /// </param>
+ /// <param name="lineItr">
+ /// An iterator for the line string which is to be clipped.
+ /// </param>
+ /// <param name="includeCollinear">
+ /// A true value indicates that segments, and/or portions of segments,
+ /// of the line string to be clipped which are collinear with the clipping
+ /// boundary are to be considered to be inside the clipping boundary. A
+ /// false value causes collinear segments (or portions thereof) to be
+ /// outside the clipping boundary and thus excluded from the returned
+ /// line string collection.
+ /// </param>
+ /// <returns>
+ /// A collection of line string objects which represents the portions of the
+ /// provided line string which are inside of the provided closed ring. This
+ /// collection may be empty; a null pointer is never returned.
+ /// </returns>
+ static MgLineStringCollection* ClipStringToPolygon (MgCoordinateIterator* polyItr,
+ MgCoordinateIterator* lineItr,
+ bool includeCollinear = false);
+protected:
+
+ MgSpatialUtility() {};
+ ~MgSpatialUtility() {};
+
+ static void AppendLinearizedCurveSegmentsToDistinctCollection(
+ MgCoordinateCollection * distinctPositions,
+ MgCurveSegmentCollection * curveSegments,
+ double maxSpacing,
+ double maxOffset);
+
+ static void AppendPositionsToDistinctCollection(
+ MgCoordinateCollection * distinctPositions,
+ MgCoordinateCollection * positionsToAppend);
+
+ // Values which are stored in the M member of the internally used point
+ // collection; i.e. the status of each point relative to the clip ploygon.
+ static const INT32 StringPointNotDetermined = 0;
+ static const INT32 StringPointIsOutside = 1;
+ static const INT32 StringPointIsOnBoundary = 2;
+ static const INT32 StringPointIsInside = 3;
+
+ // Values which are stored in the Z member of the internally used point
+ // collection; i.e. the status of each segment relative to the clip
+ // ploygon. The value stored refers to the segment which starts at
+ // the point in which the segment status is stored.
+ static const INT32 StringSegNotDetermined = 0;
+ static const INT32 StringSegIsOutside = 1;
+ static const INT32 StringSegIsCollinear = 2;
+ static const INT32 StringSegIsInside = 3;
+
+ static MgCoordinateCollection* StringClipPhaseOne (MgCoordinateIterator* lineString,
+ MgCoordinateIterator* itrPolygon);
+ static void StringClipPhaseTwo (MgCoordinateIterator* lineString,MgCoordinateIterator* itrPolygon);
+ static void StringClipPhaseThree (MgCoordinateIterator* lineString,MgCoordinateIterator* itrPolygon);
+ static MgLineStringCollection* StringClipPhaseFour (MgCoordinateIterator* lineString,bool collinear = false,
+ bool outside = false);
+};
+/// \endcond
+
+#endif
Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -19,7 +19,7 @@
#include "GeometryCommon.h"
#include "MathUtility.h"
#include "SpatialUtilityCircularArc.h"
-#include "SpatialUtility.h"
+#include "SpatialUtilities.h"
#include "SpatialUtilityStatus.h"
#define EPSILON 1e-10
Deleted: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -1,377 +0,0 @@
-//
-// Copyright (C) 2004-2011 by Autodesk, Inc.
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of version 2.1 of the GNU Lesser
-// General Public License as published by the Free Software Foundation.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#ifndef MgSpatialUtility_H
-#define MgSpatialUtility_H
-
-/// \cond INTERNAL
-
-/// \brief
-/// Spatial utility class.
-class MgSpatialUtility
-{
-public:
-
- /// Converts arcs to linestrings
- static MgGeometry* TesselateCurve(MgGeometry* curve);
- /// Converts arcs to linestrings
- static MgGeometryComponent* TesselateGeometryComponent(MgGeometryComponent* curve);
-
- /// \brief
- /// Approximates a geometry, which may contain parametric curve components,
- /// with a geometry that only contains straight, linear components.
- ///
- /// \remarks
- /// If the given geometry does not require approximation, this method returns
- /// the input geometry, and thus avoids unnecessary object creation.
- /// Tolerances are in same units as the geometry's ordinates.
- /// If the given tolerances are both zero, a tesselated geometry is produced,
- /// wherein arcs are represented using only their three defining positions.
- /// Math performed is all in implicit Cartesian (rectilinear) coordinate system.
- /// Measurement ("M") ordinates of interpolated positions undergo linear
- /// interpolation from an arc's start position to end position (possibly disregarding
- /// an "M" ordinate in the arc's mid position).
- /// Unless the arc is too short for any interpolation, the "mid" point parameter
- /// used to define arcs is not guaranteed to appear among interpolated points.
- ///
- /// \param geometry
- /// Input Geometry to approximate
- /// \param maxSpacing
- /// Input Maximum length of each line segment used to approximate parametric curves. Ignored if zero.
- /// \param maxOffset
- /// Input Maximum distance that a line segment may be from the curve that it approximates (error tolerance). Ignored if zero.
- /// \param geometryFactory
- /// Input Geometry factory for the creation of the approximated geometry.
- ///
- /// \return
- /// Returns An approximation of the given geometry.
- ///
- static MgGeometry * ApproximateGeometryWithLineStrings(
- MgGeometry * geometry,
- double maxSpacing,
- double maxOffset,
- MgGeometryFactory* geometryFactory);
-
- static bool ArePositionsEqualXYZ(
- MgCoordinate * p1,
- MgCoordinate * p2);
-
- static bool ArePositionsEqualXY(
- MgCoordinate * p1,
- MgCoordinate * p2);
-
- static double DistanceBetweenPositionsXYZ(
- MgCoordinate * p1,
- MgCoordinate * p2);
-
- static double DistanceBetweenPositionsXY(
- MgCoordinate * p1,
- MgCoordinate * p2);
-
- /// Unit normal from plane defined by vectors p1p2 to p2p3 using right-hand rule.
- /// This will return (0,0,0) for parallel vectors (collinear points) or zero-length
- /// vectors.
- static MgCoordinate * UnitNormalVector(
- MgCoordinate * p1,
- MgCoordinate * p2,
- MgCoordinate * p3);
-
- static void AppendPositionToDistinctCollection(
- MgCoordinateCollection * distinctPositions,
- MgCoordinate * positionToAppend);
-
- /// Return a new point with the location of the given point after rotation
- /// about the given axis and center.
- /// This method assumes that the involved data has XYZ dimensionality.
- /// <p><b>Note:</b> "axisVector" must be a unit normal to the plane of rotation.
- static MgCoordinate * RotatePosition(
- MgCoordinate * position,
- double angle,
- MgCoordinate * axisVector,
- MgCoordinate * center,
- bool includeM,
- double m);
-
- static MgLinearRing* CurveRingToLinearRing(MgCurveRing* curveRing, double maxSpacing, double maxOffset);
- static MgLinearSegment* ArcSegmentToLinearSegment(MgArcSegment* segment, double maxSpacing, double maxOffset);
-
- ///////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Extracts the greatest magnitude of the all the coordinates in a
- /// coordinate collection. Return value is always positive.
- /// </summary>
- /// <param name="coordinteIterator">
- /// An iterator dervied from the target coordinate collection.
- /// </param>
- /// <returns>
- /// Returns a positive value which is the largest magnitude of all
- /// ordinates in the collection.
- /// </returns>
- /// <remarks>
- /// Intended to be used to determine a suitable tolerance value for such
- /// things as coordinate comparisons.
- /// </remarks>
- static double GreatestMagnitude (MgCoordinateIterator* coordinateIterator);
-
- ///////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Computes the intersection of two 2D line segments. Intersection point,
- /// if any, is returned in the provided result coordinate which (of course)
- /// must already exist. All point arguments are expected (not required)
- /// to be MgCoordinateXY objects.
- /// </summary>
- /// <param name="result">
- /// The calculated intersection point is returned in this variable which,
- /// of course, must exist. Coordinates of <c>result</c> remain unaltered
- /// if an intersection does not exist. Only X and Y are returned.
- /// </param>
- /// <param name="seg1From">
- /// The initial point of the first line segment.
- /// </param>
- /// <param name="seg1To">
- /// The end point of the first line segment.
- /// </param>
- /// <param name="seg2From">
- /// The initial point of the second line segment.
- /// </param>
- /// <param name="seg2To">
- /// The end point of the second line segment.
- /// </param>
- /// <param name="magnitude">
- /// A value which represents the greatest coordinate value in the dataset
- /// being processed. Used to calculate an appropriate "fuzzy" value for
- /// coordinate comparisions, etc.
- /// </param>
- /// <returns>
- /// Return status of the intersection of the two segments as a bit map of
- /// values as defined in <c>SpatialUtilityStatus.h</c>
- /// </returns>
- /// <remarks>
- /// In determining if the intersection point resides on a line, an intersection
- /// point identical to the 'to' point is considered on the line, but an
- /// intersection point identical to the 'from' point is _NOT_ considered to be
- /// on the line. Such a convention is necessary to avoid the appearance
- /// of two intersections when indeed there is only one when processing a
- /// a line string, for example.
- /// </remarks>
- /// <exception cref="MgNullReferenceException">
- /// Thrown if any argument is null
- /// </exception>
- static INT32 SegmentIntersection (MgCoordinate* result,MgCoordinate* seg1From,
- MgCoordinate* seg1To,
- MgCoordinate* seg2From,
- MgCoordinate* seg2To,
- double magnitude = 1.0E+10);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Returns a collection of coordinates with all of the intersection points of
- /// the provided segment with the polygon provided by the first argument.
- /// </summary>
- /// <param name="polyItr">
- /// An iterator of the closed ring to which the provided segment is
- /// intersected.
- /// </param>
- /// <param name="segFrom">
- /// The initial point of the line segment to be intersected with the provided
- /// closed ring.
- /// </param>
- /// <param name="segTo">
- /// The ending point of the line segment to be intersected with the provided
- /// closed ring.
- /// </param>
- /// <returns>
- /// A new collection of <c>MgCoordinateXYM</c> points, one such point for each
- /// intersection is returned. This collection can be, and often is, an empty
- /// collection. A null pointer is never returned.<para>
- /// The X and Y ordinates of each point in the returned collection represent
- /// the actual location of the intersection. The M ordinate will carry, as
- /// a double, the status of the intersection as returned by the
- /// <c>SegmentIntersection</c> function.
- /// </returns>
- static MgCoordinateCollection* PolySegIntersection (MgCoordinateIterator* polyItr,
- MgCoordinate* segFrom,
- MgCoordinate* segTo);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Adds a coordinate to a coordinate collection such that the resulting
- /// collection represents a collection of points in sequence from the
- /// provided base point.
- /// </summary>
- /// <param name="collection">
- /// The coordinate collection to which the <c>newPoint</c> is to be added.
- /// </param>
- /// <param name="newPoint">
- /// The point to be added to the provided collection.
- /// </param>
- /// <param name="basePoint">
- /// The base point which is used to order the collection.
- /// </param>
- /// <returns>
- /// the index at which the insertion occurred.
- /// </returns>
- /// <remarks>
- /// The purpose of this function is serve as a helper for the PolySegIntersection
- /// function. It enables PolySegIntersection to return a point collection such
- /// that the points in the collection present an orderly sequence of points from
- /// the provided base point. Thus, if the original line segment provided to
- /// PolySegIntersection proceeded in the south to north direction, the point
- /// collection returned would also be returned in that order; regardless of the
- /// shape of the polygon or the direction in which it proceeds.<para>
- /// The determination as to the insertion point of <c>newPoint</c> is based solely
- /// on the X and Y ordinates of <c>newPoint</c> and the points which already
- /// exist in the provided collection. The type of <c>newPoint</c> and the points
- /// in the collection is immaterial.
- /// </remarks>
- static INT32 AddToCoordinateCollection (MgCoordinateCollection* collection,MgCoordinate* newPoint,
- MgCoordinate* basePoint);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Determines if the provided point is inside (or actually on) the closed
- /// ring provided by the <c>polyItr</c> argument.
- /// </summary>
- /// <param name="polyItr">
- /// An iterator of the closed ring which is the subject polygon.
- /// </param>
- /// <param name="queryPoint">
- /// The 2D point whose status is to be determined.
- /// </param>
- /// <returns>
- /// Returns zero if the query point is outside the closed ring, +1 if the
- /// query point is precisely on the closed ring (per MgMathUtility::DblCmp),
- /// or +2 if the query point is inside the closed ring.
- /// </returns>
- /// <remarks>
- /// Currently, this function calculates the envelope of the provided closed
- /// ring in order to determine a point which is known to be outside of the
- /// closed ring. An overloaded function which accepts a point known to be
- /// outside the closed ring which is a lot faster is also available.
- /// </remarks>
- static INT32 PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* queryPoint);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Determines a point guaranteed to be ouside the provided polygon.
- /// </summary>
- /// <param name="polyItr">
- /// An iterator of the closed ring which is the subject polygon.
- /// </param>
- /// <returns>
- /// Returns an <c>MgCoordinateXY</c> point which is guaranteed to be ooutside
- /// the provided polygon.
- /// </returns>
- static MgCoordinate* PointOutsidePolygon (MgCoordinateIterator* polyItr);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Determines if the provided point is inside (or actually on) the closed
- /// ring provided by the <c>polyItr</c> argument.
- /// </summary>
- /// <param name="polyItr">
- /// An iterator of the closed ring which is the subject polygon.
- /// </param>
- /// <param name="outsidePoint">
- /// A 2D point which is known to be outside of the provided polygon. Can
- /// be obtained from <c>PointOutsidePolygon</c>.
- /// <param name="queryPoint">
- /// The 2D point whose status is to be determined.
- /// </param>
- /// <returns>
- /// Returns zero if the query point is outside the closed ring, +1 if the
- /// query point is precisely on the closed ring (per MgMathUtility::DblCmp),
- /// or +2 if the query point is inside the closed ring.
- /// </returns>
- /// <remarks>
- /// This function requires that the calling module supply a point known to
- /// be outside the polygon. Thus, higher performance can be obtained when
- /// multiple queries against the same polygon are required.
- /// </remarks>
- static INT32 PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* outsidePoint,
- MgCoordinate* queryPoint);
-
- ///////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Clips a line string to an arbitrary polygon returning a collection of line
- /// strings which represent the portions of the provided line string which are
- /// inside the provided closed ring.
- /// </summary>
- /// <param name="polyItr">
- /// An iterator to the closed ring to which the provided line string is to be
- /// clipped.
- /// </param>
- /// <param name="lineItr">
- /// An iterator for the line string which is to be clipped.
- /// </param>
- /// <param name="includeCollinear">
- /// A true value indicates that segments, and/or portions of segments,
- /// of the line string to be clipped which are collinear with the clipping
- /// boundary are to be considered to be inside the clipping boundary. A
- /// false value causes collinear segments (or portions thereof) to be
- /// outside the clipping boundary and thus excluded from the returned
- /// line string collection.
- /// </param>
- /// <returns>
- /// A collection of line string objects which represents the portions of the
- /// provided line string which are inside of the provided closed ring. This
- /// collection may be empty; a null pointer is never returned.
- /// </returns>
- static MgLineStringCollection* ClipStringToPolygon (MgCoordinateIterator* polyItr,
- MgCoordinateIterator* lineItr,
- bool includeCollinear = false);
-protected:
-
- MgSpatialUtility() {};
- ~MgSpatialUtility() {};
-
- static void AppendLinearizedCurveSegmentsToDistinctCollection(
- MgCoordinateCollection * distinctPositions,
- MgCurveSegmentCollection * curveSegments,
- double maxSpacing,
- double maxOffset);
-
- static void AppendPositionsToDistinctCollection(
- MgCoordinateCollection * distinctPositions,
- MgCoordinateCollection * positionsToAppend);
-
- // Values which are stored in the M member of the internally used point
- // collection; i.e. the status of each point relative to the clip ploygon.
- static const INT32 StringPointNotDetermined = 0;
- static const INT32 StringPointIsOutside = 1;
- static const INT32 StringPointIsOnBoundary = 2;
- static const INT32 StringPointIsInside = 3;
-
- // Values which are stored in the Z member of the internally used point
- // collection; i.e. the status of each segment relative to the clip
- // ploygon. The value stored refers to the segment which starts at
- // the point in which the segment status is stored.
- static const INT32 StringSegNotDetermined = 0;
- static const INT32 StringSegIsOutside = 1;
- static const INT32 StringSegIsCollinear = 2;
- static const INT32 StringSegIsInside = 3;
-
- static MgCoordinateCollection* StringClipPhaseOne (MgCoordinateIterator* lineString,
- MgCoordinateIterator* itrPolygon);
- static void StringClipPhaseTwo (MgCoordinateIterator* lineString,MgCoordinateIterator* itrPolygon);
- static void StringClipPhaseThree (MgCoordinateIterator* lineString,MgCoordinateIterator* itrPolygon);
- static MgLineStringCollection* StringClipPhaseFour (MgCoordinateIterator* lineString,bool collinear = false,
- bool outside = false);
-};
-/// \endcond
-
-#endif
Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -16,7 +16,7 @@
//
#include "GeometryCommon.h"
-#include "SpatialUtility.h"
+#include "SpatialUtilities.h"
#include "SpatialUtilityCircularArc.h"
#include "MathUtility.h"
Modified: trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -282,6 +282,28 @@
return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
}
+MgByteReader * MgProxyRenderingService::RenderTileMVT(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::RenderTileMVT, // Command Code
+ 7, // No of arguments
+ Rendering_Service, // Service Id
+ BUILD_VERSION(4,0,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: trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyRenderingService.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -322,6 +322,46 @@
/////////////////////////////////////////////////////////////////
/// \brief
+ /// Returns the specified MVT (Mapbox Vector 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.
+ ///
+ /// \since 4.0
+ virtual MgByteReader* RenderTileMVT(
+ 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: trunk/MgDev/Common/MapGuideCommon/Services/RenderingDefs.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/RenderingDefs.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/MapGuideCommon/Services/RenderingDefs.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -50,6 +50,7 @@
static const int RenderMetatile = 0x1111E916;
static const int RenderTileFromMetaTile = 0x1111E917;
static const int RenderMetatileXYZ = 0x1111E918;
+ static const int RenderTileMVT = 0x1111E919;
};
/// \endcond
Modified: trunk/MgDev/Common/MapGuideCommon/Services/RenderingService.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/RenderingService.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/MapGuideCommon/Services/RenderingService.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -338,6 +338,46 @@
/////////////////////////////////////////////////////////////////
/// \brief
+ /// Returns the specified MVT (Mapbox Vector 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.
+ ///
+ /// \since 4.0
+ virtual MgByteReader* RenderTileMVT(
+ 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: trunk/MgDev/Common/Renderers/CMakeLists.txt
===================================================================
--- trunk/MgDev/Common/Renderers/CMakeLists.txt 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Renderers/CMakeLists.txt 2019-10-06 12:18:03 UTC (rev 9630)
@@ -40,6 +40,8 @@
KmlIconStyle.cpp
KmlRenderer.cpp
MapQuantization.cpp
+ mvt/mvt_tile.cpp
+ MVTRenderer.cpp
ObservationMesh.cpp
RenderUtil.cpp
RS_ByteData.cpp
Copied: trunk/MgDev/Common/Renderers/MVTRenderer.cpp (from rev 9629, sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp)
===================================================================
--- trunk/MgDev/Common/Renderers/MVTRenderer.cpp (rev 0)
+++ trunk/MgDev/Common/Renderers/MVTRenderer.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,871 @@
+//
+// Copyright (C) 2004-2019 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#include "MVTRenderer.h"
+#include "RS_FeatureReader.h"
+#include "UnicodeString.h"
+#include <cmath>
+#include "mvt/gpb.h"
+#include "mvt/mvt_tile.h"
+
+// =========================== MVTRenderer overview =============================== //
+//
+// MVTRenderer is really just an adapter to connect our Stylizer to MVTTile
+//
+// So the responsibility of MVTRenderer is simply to:
+//
+// - Create a new MVTTileLayer instance on every StartLayer()
+// - Stash the RS_FeatureReader pointer on every StartFeature() call (we need this for writing properties)
+// - For every ProcessXXX() call
+// - Create a MVTTileLayerFeature instance
+// - Write the active property map
+// - Encode the geometry coordinates
+// - Add the MVTTileLayerFeature if encoding succeeds
+//
+// ================================================================================ //
+
+// WebMercator related constants
+constexpr double kmSPHERICAL_RADIUS = 6378137.0;
+constexpr double kmMAX_GM = kmSPHERICAL_RADIUS * M_PI; // 20037508.342789244
+
+static unsigned GetCmdCountCombined(unsigned int nCmdId,
+ unsigned int nCmdCount)
+{
+ return (nCmdId | (nCmdCount << 3));
+}
+
+
+struct MVTRenderer::MVTImpl {
+ MVTImpl(MVTRenderer* parent, int x, int y, int z)
+ : m_activeLayer(nullptr)
+ , m_nExtent(knDEFAULT_EXTENT)
+ , m_tileX(x)
+ , m_tileY(y)
+ , m_tileZ(z)
+ //InitWebMercatorTilingScheme
+ , m_dfTopX(-kmMAX_GM)
+ , m_dfTopY(kmMAX_GM)
+ , m_dfTileDim0(2 * kmMAX_GM)
+ , m_parent(parent)
+ { }
+
+ ~MVTImpl()
+ {
+
+ }
+
+ void SetActiveLayerBuilder(const std::string& name)
+ {
+ m_activeLayer = std::make_shared<MVTTileLayer>();
+ m_activeLayer->setName(name);
+ m_tile.addLayer(m_activeLayer);
+ }
+
+ void ClearActiveLayerBuilder()
+ {
+ m_activeLayer.reset();
+ }
+
+ void ConvertToTileCoords(double dfX,
+ double dfY,
+ int& nX,
+ int& nY,
+ double dfTopX,
+ double dfTopY,
+ double dfTileDim) const
+ {
+ nX = static_cast<int>(std::round((dfX - dfTopX) * m_nExtent / dfTileDim));
+ nY = static_cast<int>(std::round((dfTopY - dfY) * m_nExtent / dfTileDim));
+ }
+
+ static void AddActiveFeatureProperties(RS_FeatureReader* activeFeature, MVTTileLayer* layer, MVTTileLayerFeature* feature)
+ {
+ TrySetFeatureId(feature, activeFeature);
+
+ int count;
+ auto propNames = activeFeature->GetPropNames(count);
+ for (int i = 0; i < count; i++)
+ {
+ auto name = propNames[i];
+ if (activeFeature->IsNull(name))
+ {
+ continue;
+ }
+
+ MVTTileLayerValue tv;
+
+ std::string mbName;
+ UnicodeString::WideCharToMultiByte(name, mbName);
+ auto propType = activeFeature->GetPropertyType(name);
+ switch (propType)
+ {
+ case FdoDataType_Boolean:
+ tv.setBoolValue(activeFeature->GetBoolean(name));
+ break;
+ case FdoDataType_Byte:
+ tv.setIntValue(activeFeature->GetByte(name));
+ break;
+ case FdoDataType_DateTime:
+ {
+ auto dt = activeFeature->GetAsString(name);
+ std::string sDt;
+ UnicodeString::WideCharToMultiByte(dt, sDt);
+ tv.setStringValue(sDt);
+ break;
+ }
+ case FdoDataType_Decimal:
+ case FdoDataType_Double:
+ tv.setDoubleValue(activeFeature->GetDouble(name));
+ break;
+ case FdoDataType_Int16:
+ tv.setIntValue(activeFeature->GetInt16(name));
+ break;
+ case FdoDataType_Int32:
+ tv.setIntValue(activeFeature->GetInt32(name));
+ break;
+ case FdoDataType_Int64:
+ tv.setIntValue(activeFeature->GetInt64(name));
+ break;
+ case FdoDataType_Single:
+ tv.setFloatValue(activeFeature->GetSingle(name));
+ break;
+ case FdoDataType_String:
+ {
+ auto s = activeFeature->GetString(name);
+ std::string sVal;
+ UnicodeString::WideCharToMultiByte(s, sVal);
+ tv.setStringValue(sVal);
+ break;
+ }
+ case FdoDataType_BLOB: //Not handled
+ case FdoDataType_CLOB:
+ break;
+ }
+
+ auto nKey = layer->addKey(mbName);
+ auto nVal = layer->addValue(tv);
+ feature->addTag(nKey);
+ feature->addTag(nVal);
+ }
+ }
+
+ static void TrySetFeatureId(MVTTileLayerFeature* feature, RS_FeatureReader* activeFeature)
+ {
+ int count = 0;
+ auto idPropNames = activeFeature->GetIdentPropNames(count);
+ if (count == 1)
+ {
+ auto idName = idPropNames[0];
+ auto ptype = activeFeature->GetPropertyType(idName);
+ switch (ptype)
+ {
+ case FdoDataType_Byte:
+ feature->setId(activeFeature->GetByte(idName));
+ break;
+ case FdoDataType_Int16:
+ feature->setId(activeFeature->GetInt16(idName));
+ break;
+ case FdoDataType_Int32:
+ feature->setId(activeFeature->GetInt32(idName));
+ break;
+ case FdoDataType_Int64:
+ feature->setId(activeFeature->GetInt64(idName));
+ break;
+ }
+ }
+ }
+
+ bool EncodePolygonGeometry(MVTTileLayerFeature* poGPBFeature,
+ LineBuffer* lb,
+ int cStart, int cEnd,
+ double dfTopX,
+ double dfTopY,
+ double dfTileDim,
+ bool bCanRecurse,
+ int& nLastX,
+ int& nLastY) const
+ {
+ for (int i = cStart; i <= cEnd; i++)
+ {
+ const bool bWriteLastPoint = false;
+ const bool bReverseOrder = (i > 0);
+ const GUInt32 nMinLineTo = 2;
+ const GUInt32 nInitialSize = poGPBFeature->getGeometryCount();
+ const int nLastXOri = nLastX;
+ const int nLastYOri = nLastY;
+
+ bool bSuccess =
+ EncodeLineStringGeometry(poGPBFeature, lb, i,
+ bWriteLastPoint, bReverseOrder,
+ nMinLineTo,
+ dfTopX, dfTopY, dfTileDim, nLastX, nLastY);
+
+ if (!bSuccess)
+ {
+ if (i == 0)
+ return false;
+ continue;
+ }
+ poGPBFeature->addGeometry(GetCmdCountCombined(knCMD_CLOSEPATH, 1));
+ }
+ return true;
+ }
+
+ bool EncodePolygon(MVTTileLayerFeature* feature, LineBuffer* lb)
+ {
+ double dfTileDim = m_dfTileDim0 / (1 << m_tileZ);
+ double dfTopX = m_dfTopX + m_tileX * dfTileDim;
+ double dfTopY = m_dfTopY - m_tileY * dfTileDim;
+ int nLastX = 0;
+ int nLastY = 0;
+ bool bGeomOK = false;
+
+ int cStart = 0;
+ int geom_count = lb->geom_count();
+ for (int i = 0; i < geom_count; i++)
+ {
+ int cSize = lb->geom_size(i);
+
+ bGeomOK |= EncodePolygonGeometry(feature, lb,
+ cStart, cSize - 1,
+ dfTopX, dfTopY, dfTileDim,
+ true,
+ nLastX, nLastY);
+
+ cStart += cSize;
+ }
+
+ return bGeomOK;
+ }
+
+ void ProcessPolygon(RS_FeatureReader* activeFeature, LineBuffer * lb)
+ {
+ auto feature = std::make_shared<MVTTileLayerFeature>();
+ feature->setType(MVTTileLayerFeature::GeomType::POLYGON);
+ AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+ if (EncodePolygon(feature.get(), lb))
+ m_activeLayer->addFeature(feature);
+ }
+
+ bool EncodeLineStringGeometry(MVTTileLayerFeature* poGPBFeature,
+ LineBuffer* lb,
+ int lineStrIdx,
+ bool bWriteLastPoint,
+ bool bReverseOrder,
+ GUInt32 nMinLineTo,
+ double dfTopX,
+ double dfTopY,
+ double dfTileDim,
+ int& nLastX,
+ int& nLastY) const
+ {
+ const GUInt32 nInitialSize = poGPBFeature->getGeometryCount();
+ const int nLastXOri = nLastX;
+ const int nLastYOri = nLastY;
+ GUInt32 nLineToCount = 0;
+ const int nPoints = lb->cntr_size(lineStrIdx) - (bWriteLastPoint ? 0 : 1);
+ int nFirstX = 0;
+ int nFirstY = 0;
+ int nLastXValid = nLastX;
+ int nLastYValid = nLastY;
+ auto pointOffset = lb->contour_start_point(lineStrIdx);
+ for (int i = 0; i < nPoints; i++)
+ {
+ int nX, nY;
+ int nSrcIdx = bReverseOrder ? lb->cntr_size(lineStrIdx) - 1 - i : i;
+ double dfX = lb->x_coord(nSrcIdx + pointOffset);
+ double dfY = lb->y_coord(nSrcIdx + pointOffset);
+
+ ConvertToTileCoords(dfX, dfY, nX, nY,
+ dfTopX, dfTopY, dfTileDim);
+ int nDiffX = nX - nLastX;
+ int nDiffY = nY - nLastY;
+ if (i == 0 || nDiffX != 0 || nDiffY != 0)
+ {
+ if (i > 0)
+ {
+ nLineToCount++;
+ if (nLineToCount == 1)
+ {
+ poGPBFeature->addGeometry(
+ GetCmdCountCombined(knCMD_MOVETO, 1));
+ const int nLastDiffX = nLastX - nLastXOri;
+ const int nLastDiffY = nLastY - nLastYOri;
+ poGPBFeature->addGeometry(EncodeSInt(nLastDiffX));
+ poGPBFeature->addGeometry(EncodeSInt(nLastDiffY));
+
+ // To be modified later
+ poGPBFeature->addGeometry(
+ GetCmdCountCombined(knCMD_LINETO, 0));
+ }
+
+ poGPBFeature->addGeometry(EncodeSInt(nDiffX));
+ poGPBFeature->addGeometry(EncodeSInt(nDiffY));
+ }
+ else
+ {
+ nFirstX = nX;
+ nFirstY = nY;
+ }
+ nLastXValid = nLastX;
+ nLastYValid = nLastY;
+ nLastX = nX;
+ nLastY = nY;
+ }
+ }
+
+ // If last point of ring is identical to first one, discard it
+ if (nMinLineTo == 2 && nLineToCount > 0 &&
+ nFirstX == nLastX && nFirstY == nLastY)
+ {
+ poGPBFeature->resizeGeometryArray(
+ poGPBFeature->getGeometryCount() - 2);
+ nLineToCount--;
+ nLastX = nLastXValid;
+ nLastY = nLastYValid;
+ }
+
+ if (nLineToCount >= nMinLineTo)
+ {
+ // Patch actual number of points in LINETO command
+ poGPBFeature->setGeometry(nInitialSize + 3,
+ GetCmdCountCombined(knCMD_LINETO, nLineToCount));
+ return true;
+ }
+ else
+ {
+ poGPBFeature->resizeGeometryArray(nInitialSize);
+ nLastX = nLastXOri;
+ nLastY = nLastYOri;
+ return false;
+ }
+ }
+
+ bool EncodePolyine(MVTTileLayerFeature* feature, LineBuffer* lb)
+ {
+ double dfTileDim = m_dfTileDim0 / (1 << m_tileZ);
+ double dfTopX = m_dfTopX + m_tileX * dfTileDim;
+ double dfTopY = m_dfTopY - m_tileY * dfTileDim;
+ bool bGeomOK = false;
+ const bool bWriteLastPoint = true;
+ const bool bReverseOrder = false;
+ const GUInt32 nMinLineTo = 1;
+ int nLastX = 0;
+ int nLastY = 0;
+ //TODO: Can probably fold everything into the MultiLineString code path here
+ if (lb->cntr_count() == 1)
+ {
+ bGeomOK = EncodeLineStringGeometry(feature, lb, 0,
+ bWriteLastPoint, bReverseOrder,
+ nMinLineTo,
+ dfTopX, dfTopY, dfTileDim,
+ nLastX, nLastY);
+ }
+ else //MultiLineString
+ {
+ for (auto i = 0; i < lb->cntr_count(); i++)
+ {
+ bool bSubGeomOK = EncodeLineStringGeometry(
+ feature, lb, i,
+ bWriteLastPoint, bReverseOrder,
+ nMinLineTo,
+ dfTopX, dfTopY, dfTileDim,
+ nLastX, nLastY);
+ bGeomOK |= bSubGeomOK;
+ }
+ }
+ return bGeomOK;
+ }
+
+ void ProcessPolyline(RS_FeatureReader* activeFeature, LineBuffer * lb)
+ {
+ auto feature = std::make_shared<MVTTileLayerFeature>();
+ feature->setType(MVTTileLayerFeature::GeomType::LINESTRING);
+ AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+ if (EncodePolyine(feature.get(), lb))
+ m_activeLayer->addFeature(feature);
+ }
+
+ bool EncodePoint(MVTTileLayerFeature* feature, LineBuffer* lb)
+ {
+ double dfTileDim = m_dfTileDim0 / (1 << m_tileZ);
+ double dfTopX = m_dfTopX + m_tileX * dfTileDim;
+ double dfTopY = m_dfTopY - m_tileY * dfTileDim;
+
+ bool bGeomOK = false;
+ if (lb->point_count() == 1)
+ {
+ int nX, nY;
+ auto dfX = lb->x_coord(0);
+ auto dfY = lb->y_coord(0);
+ bGeomOK = true;
+ ConvertToTileCoords(dfX, dfY, nX, nY, dfTopX, dfTopY, dfTileDim);
+
+ feature->addGeometry(GetCmdCountCombined(knCMD_MOVETO, 1));
+ feature->addGeometry(EncodeSInt(nX));
+ feature->addGeometry(EncodeSInt(nY));
+ }
+ else //MultiPoint
+ {
+ std::set<std::pair<int, int>> oSetUniqueCoords;
+ feature->addGeometry(GetCmdCountCombined(knCMD_MOVETO, 0)); // To be modified later
+ int nLastX = 0;
+ int nLastY = 0;
+ for (auto i = 0; i < lb->point_count(); i++)
+ {
+ int nX, nY;
+ auto dfX = lb->x_coord(i);
+ auto dfY = lb->y_coord(i);
+ ConvertToTileCoords(dfX, dfY, nX, nY, dfTopX, dfTopY, dfTileDim);
+ if (oSetUniqueCoords.find(std::pair<int, int>(nX, nY)) ==
+ oSetUniqueCoords.end())
+ {
+ oSetUniqueCoords.insert(std::pair<int, int>(nX, nY));
+
+ int nDiffX = nX - nLastX;
+ int nDiffY = nY - nLastY;
+ feature->addGeometry(EncodeSInt(nDiffX));
+ feature->addGeometry(EncodeSInt(nDiffY));
+ nLastX = nX;
+ nLastY = nY;
+ }
+ }
+ GUInt32 nPoints = static_cast<GUInt32>(oSetUniqueCoords.size());
+ bGeomOK = nPoints > 0;
+ feature->setGeometry(0, GetCmdCountCombined(knCMD_MOVETO, nPoints));
+ }
+ return bGeomOK;
+ }
+
+ void ProcessMarker(RS_FeatureReader* activeFeature, LineBuffer * lb)
+ {
+ auto feature = std::make_shared<MVTTileLayerFeature>();
+ feature->setType(MVTTileLayerFeature::GeomType::POINT);
+ AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+ if (EncodePoint(feature.get(), lb))
+ m_activeLayer->addFeature(feature);
+ }
+
+ unsigned char* GetMVTContent(size_t& size)
+ {
+ size = m_tile.getSize();
+ GByte* pabyBuffer = new GByte[size];
+ m_tile.write(pabyBuffer);
+ return pabyBuffer;
+ }
+
+ void ReleaseMVTContent(unsigned char* buf)
+ {
+ delete[] buf;
+ }
+
+ void SetTileCoords(const int x, const int y, const int z)
+ {
+ m_tileX = x;
+ m_tileY = y;
+ m_tileZ = z;
+ }
+
+private:
+ MVTTile m_tile;
+ std::shared_ptr<MVTTileLayer> m_activeLayer;
+ MVTRenderer* m_parent;
+
+ int m_tileX;
+ int m_tileY;
+ int m_tileZ;
+
+ double m_dfTopX;
+ double m_dfTopY;
+ double m_dfTileDim0;
+
+ unsigned int m_nExtent;
+};
+
+MVTRenderer::MVTRenderer(int x, int y, int z)
+ : m_impl(new MVTRenderer::MVTImpl(this, x, y, z)) //MVTImpl only stashes this pointer in its ctor, nothing is called on it yet
+ , m_mapInfo(nullptr)
+ , m_layerInfo(nullptr)
+ , m_fcInfo(nullptr)
+{
+
+}
+
+MVTRenderer::~MVTRenderer()
+{ }
+
+//Called by the stylizer when rendering is about to begin on the map
+void MVTRenderer::StartMap(RS_MapUIInfo * /*mapInfo*/, RS_Bounds & extents, double mapScale, double dpi, double metersPerUnit, CSysTransformer * /*xformToLL*/)
+{
+ m_mapScale = mapScale;
+ m_dpi = dpi;
+ m_metersPerUnit = metersPerUnit;
+ m_extents = extents;
+
+ // find scale used to convert to pixel coordinates
+ // need to take aspect ratios into account
+ /*
+ double arDisplay = (double)m_width / (double)m_height;
+ double arMap = m_extents.width() / m_extents.height();
+
+ double scale;
+ if (arDisplay > arMap)
+ scale = (double)m_height / m_extents.height();
+ else
+ */
+ double wScale = (double)m_width / m_extents.width();
+ double hScale = (double)m_height / m_extents.height();
+
+ m_xform.x0 = wScale;
+ m_xform.x1 = 0.0;
+ m_xform.x2 = -wScale * m_extents.minx;
+ m_xform.y0 = 0.0;
+ m_xform.y1 = hScale;
+ m_xform.y2 = -hScale * m_extents.miny;
+
+ m_ixform.x0 = 1.0 / wScale;
+ m_ixform.x1 = 0.0;
+ m_ixform.x2 = m_extents.minx;
+ m_ixform.y0 = 0.0;
+ m_ixform.y1 = m_ixform.x0;
+ m_ixform.y2 = m_extents.miny;
+
+ double metersPerPixel = METERS_PER_INCH / m_dpi;
+
+ // compute drawing scale
+ // drawing scale is map scale converted to [mapping units] / [pixels]
+ m_drawingScale = m_mapScale * metersPerPixel / m_metersPerUnit;
+}
+
+//Called by the stylizer when rendering is about to begin on the map
+void MVTRenderer::EndMap()
+{
+ // clear the map info
+ m_mapInfo = nullptr;
+}
+
+//Called by the stylizer when rendering is about to begin on the map for the given layer
+void MVTRenderer::StartLayer(RS_LayerUIInfo * layerInfo, RS_FeatureClassInfo * classInfo)
+{
+ m_layerInfo = layerInfo;
+ m_fcInfo = classInfo;
+
+ std::string name;
+ UnicodeString::WideCharToMultiByte(m_layerInfo->name().c_str(), name);
+
+ m_impl->SetActiveLayerBuilder(name);
+}
+
+//Called by the stylizer when rendering is about to begin on the map for the layer indicated by StartLayer()
+void MVTRenderer::EndLayer()
+{
+ // clear the layer/feature info
+ m_layerInfo = nullptr;
+ m_fcInfo = nullptr;
+
+ m_impl->ClearActiveLayerBuilder();
+}
+
+//Called by the stylizer when rendering is about to begin on the map for the given feature
+void MVTRenderer::StartFeature(RS_FeatureReader * feature, bool /*initialPass*/, const RS_String * /*tooltip*/, const RS_String * /*url*/, const RS_String * /*theme*/, double /*zOffset*/, double /*zExtrusion*/, RS_ElevationType /*zOffsetType*/)
+{
+ m_activeFeature = feature;
+}
+
+//Entry point for polygon rendering. Perform any pre-rendering operations.
+void MVTRenderer::ProcessPolygon(LineBuffer * lb, RS_FillStyle & /*fill*/)
+{
+ //Optimize LB before sending to MVT tile writer
+ auto workbuffer = lb->Optimize(m_drawingScale, m_pPool);
+ std::unique_ptr<LineBuffer> spLB(workbuffer);
+
+ //Also clip the geometry to the extents if required as we do not want to encode
+ //"out of tile" coordinates
+ auto clipped = workbuffer->Clip(m_extents, LineBuffer::ctArea, m_pPool);
+ if (workbuffer != clipped)
+ {
+ if (spLB.get())
+ {
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+ }
+
+ workbuffer = clipped;
+ spLB.reset(workbuffer);
+ }
+
+ if (workbuffer)
+ m_impl->ProcessPolygon(m_activeFeature, workbuffer);
+
+ if (spLB.get())
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+}
+
+//Entry point for polyline rendering. Perform any pre-rendering operations.
+void MVTRenderer::ProcessPolyline(LineBuffer * lb, RS_LineStroke & /*lsym*/)
+{
+ //Optimize LB before sending to MVT tile writer
+ auto workbuffer = lb->Optimize(m_drawingScale, m_pPool);
+ std::unique_ptr<LineBuffer> spLB(workbuffer);
+
+ //Also clip the geometry to the extents if required as we do not want to encode
+ //"out of tile" coordinates
+ auto clipped = workbuffer->Clip(m_extents, LineBuffer::ctLine, m_pPool);
+ if (workbuffer != clipped)
+ {
+ if (spLB.get())
+ {
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+ }
+
+ workbuffer = clipped;
+ spLB.reset(workbuffer);
+ }
+
+ if (workbuffer)
+ m_impl->ProcessPolyline(m_activeFeature, workbuffer);
+
+ if (spLB.get())
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+}
+
+//Entry point for raster/image rendering. Perform any pre-rendering operations.
+void MVTRenderer::ProcessRaster(unsigned char * /*data*/, int /*length*/, RS_ImageFormat /*format*/, int /*width*/, int /*height*/, RS_Bounds & /*extents*/, TransformMesh * /*xformMesh*/)
+{
+ //This will generally result in a call to DrawScreenRaster() after processing.
+ //
+ //If your renderer only concerns vector data, this method can be left blank
+}
+
+//Entry point for marker rendering. Perform any pre-rendering operations.
+void MVTRenderer::ProcessMarker(LineBuffer * lb, RS_MarkerDef & /*mdef*/, bool /*allowOverpost*/, RS_Bounds * /*bounds*/)
+{
+ //vtzero is very finicky about redundant coordinates, so feed vtzero an optimized LineBuffer
+ //that should weed such coordinates out
+ auto workbuffer = lb->Optimize(m_drawingScale, m_pPool);
+ std::unique_ptr<LineBuffer> spLB(workbuffer);
+
+ //Also clip the geometry to the extents if required as we do not want to encode
+ //"out of tile" coordinates
+ auto clipped = workbuffer->Clip(m_extents, LineBuffer::ctPoint, m_pPool);
+ if (workbuffer != clipped)
+ {
+ if (spLB.get())
+ {
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+ }
+
+ workbuffer = clipped;
+ spLB.reset(workbuffer);
+ }
+
+ if (workbuffer)
+ m_impl->ProcessMarker(m_activeFeature, workbuffer);
+
+ if (spLB.get())
+ LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
+}
+
+//Entry point for label group rendering.
+void MVTRenderer::ProcessLabelGroup(RS_LabelInfo * /*labels*/, int /*nlabels*/, const RS_String & /*text*/, RS_OverpostType /*type*/, bool /*exclude*/, LineBuffer * /*path*/, double /*scaleLimit*/)
+{
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If your renderer does not render labels, this method can be left blank
+}
+
+// Inserts the contents of a given DWF input stream into the current
+// output W2D. The given coord sys transformation is applied and geometry
+// will be clipped to the RS_Bounds context of the DWFRenderer.
+void MVTRenderer::AddDWFContent(RS_InputStream * /*in*/, CSysTransformer * /*xformer*/, const RS_String & /*section*/, const RS_String & /*passwd*/, const RS_String & /*w2dfilter*/)
+{
+ // This is data from a DWF drawing layer. If your renderer is not intended to support DWF
+ // drawing layers/sources, this method can be left blank.
+}
+
+//Sets the legacy symbol manager which will be used when fetching (DWF) symbol data
+void MVTRenderer::SetSymbolManager(RS_SymbolManager * /*manager*/)
+{
+ //If your renderer does not render DWF-based image symbols, this method can be left blank
+}
+
+RS_MapUIInfo * MVTRenderer::GetMapInfo()
+{
+ return m_mapInfo;
+}
+
+RS_LayerUIInfo * MVTRenderer::GetLayerInfo()
+{
+ return m_layerInfo;
+}
+
+RS_FeatureClassInfo * MVTRenderer::GetFeatureClassInfo()
+{
+ return m_fcInfo;
+}
+
+double MVTRenderer::GetMapScale()
+{
+ return m_mapScale;
+}
+
+double MVTRenderer::GetDrawingScale()
+{
+ return m_drawingScale;
+}
+
+double MVTRenderer::GetMetersPerUnit()
+{
+ return m_metersPerUnit;
+}
+
+double MVTRenderer::GetDpi()
+{
+ return m_dpi;
+}
+
+RS_Bounds & MVTRenderer::GetBounds()
+{
+ return m_extents;
+}
+
+bool MVTRenderer::RequiresClipping()
+{
+ return false;
+}
+
+bool MVTRenderer::RequiresLabelClipping()
+{
+ return false;
+}
+
+//Return true if this renderer can handle 3D geometries
+bool MVTRenderer::SupportsZ()
+{
+ return false;
+}
+
+//Render out the given polyline using the provided fill style
+void MVTRenderer::DrawScreenPolyline(LineBuffer * /*polyline*/, const SE_Matrix * /*xform*/, const SE_LineStroke & /*lineStroke*/)
+{
+
+}
+
+//Render out the given polygon using the provided fill style
+void MVTRenderer::DrawScreenPolygon(LineBuffer * /*polygon*/, const SE_Matrix * /*xform*/, unsigned int /*fill*/)
+{
+
+}
+
+//Render out the given raster data.
+void MVTRenderer::DrawScreenRaster(unsigned char * /*data*/, int /*length*/, RS_ImageFormat /*format*/, int /*native_width*/, int /*native_height*/, double /*x*/, double /*y*/, double /*w*/, double /*h*/, double /*angleDeg*/)
+{
+ //If your renderer only concerns vector data, this method can be left blank
+}
+
+//Render out the given raster data.
+void MVTRenderer::DrawScreenRaster(unsigned char * /*data*/, int /*length*/, RS_ImageFormat /*format*/, int /*native_width*/, int /*native_height*/, double /*x*/, double /*y*/, double /*w*/, double /*h*/, double /*angleDeg*/, double /*alpha*/)
+{
+ //If your renderer only concerns vector data, this method can be left blank
+}
+
+//Render out the given text.
+void MVTRenderer::DrawScreenText(const RS_TextMetrics & /*tm*/, RS_TextDef & /*tdef*/, double /*insx*/, double /*insy*/, RS_F_Point * /*path*/, int /*npts*/, double /*param_position*/)
+{
+ //If your renderer does not render labels, this method can be left blank
+}
+
+bool MVTRenderer::YPointsUp()
+{
+ return false;
+}
+
+void MVTRenderer::GetWorldToScreenTransform(SE_Matrix & xform)
+{
+ xform = m_xform;
+}
+
+void MVTRenderer::WorldToScreenPoint(double & inx, double & iny, double & ox, double & oy)
+{
+ m_xform.transform(inx, iny, ox, oy);
+}
+
+void MVTRenderer::ScreenToWorldPoint(double & inx, double & iny, double & ox, double & oy)
+{
+ m_ixform.transform(inx, iny, ox, oy);
+}
+
+double MVTRenderer::GetScreenUnitsPerMillimeterDevice()
+{
+ return m_dpi / MILLIMETERS_PER_INCH;
+}
+
+double MVTRenderer::GetScreenUnitsPerMillimeterWorld()
+{
+ return m_dpi / MILLIMETERS_PER_INCH / m_mapScale;
+}
+
+double MVTRenderer::GetScreenUnitsPerPixel()
+{
+ return 1.0;
+}
+
+RS_FontEngine * MVTRenderer::GetRSFontEngine()
+{
+ return NULL;
+}
+
+//Entry point for label rendering.
+void MVTRenderer::ProcessSELabelGroup(SE_LabelInfo * /*labels*/, int /*nlabels*/, RS_OverpostType /*type*/, bool /*exclude*/, LineBuffer * /*path*/)
+{
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If this render does not render labels, this method can be left blank.
+}
+
+//If this renderer can render labels, add and track the given exclusion region.
+//An exclusion region is a region that should not factor into desired label/symbol placement.
+void MVTRenderer::AddExclusionRegion(RS_F_Point * /*fpts*/, int /*npts*/)
+{
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If this renderer does not render labels. This method can be left blank.
+}
+
+unsigned char* MVTRenderer::GetMVTContent(size_t& size)
+{
+ return m_impl->GetMVTContent(size);
+}
+
+void MVTRenderer::ReleaseMVTContent(unsigned char* buf)
+{
+ m_impl->ReleaseMVTContent(buf);
+}
+
+RS_DesiredPolygonOrientation MVTRenderer::GetDesiredPolygonOrientation()
+{
+ return RS_DesiredPolygonOrientation::Clockwise;
+}
+
+bool MVTRenderer::IsValidTile(unsigned char* buf, size_t size)
+{
+ MVTTile oTileDeserialized;
+ bool bRet = oTileDeserialized.read(buf, buf + size);
+ return bRet;
+}
\ No newline at end of file
Copied: trunk/MgDev/Common/Renderers/MVTRenderer.h (from rev 9629, sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.h)
===================================================================
--- trunk/MgDev/Common/Renderers/MVTRenderer.h (rev 0)
+++ trunk/MgDev/Common/Renderers/MVTRenderer.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,106 @@
+//
+// Copyright (C) 2004-2019 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef _MVTRENDERER_H_
+#define _MVTRENDERER_H_
+
+#include "Renderers.h"
+#include "SE_Renderer.h"
+#include <vector>
+
+// A renderer that produces Mapbox Vector Tiles (MVT). This renderer exclusively works
+// against an XYZ tile access scheme so it can only be used for rendering XYZ tiles and
+// no other type of rendering
+class MVTRenderer : public SE_Renderer
+{
+public:
+ RENDERERS_API MVTRenderer(int x, int y, int z);
+ RENDERERS_API virtual ~MVTRenderer();
+
+ // Inherited via SE_Renderer
+ RENDERERS_API virtual void StartMap(RS_MapUIInfo * mapInfo, RS_Bounds & extents, double mapScale, double dpi, double metersPerUnit, CSysTransformer * xformToLL);
+ RENDERERS_API virtual void EndMap();
+ RENDERERS_API virtual void StartLayer(RS_LayerUIInfo * layerInfo, RS_FeatureClassInfo * classInfo);
+ RENDERERS_API virtual void EndLayer();
+ RENDERERS_API virtual void StartFeature(RS_FeatureReader * feature, bool initialPass, const RS_String * tooltip = NULL, const RS_String * url = NULL, const RS_String * theme = NULL, double zOffset = 0.0, double zExtrusion = 0.0, RS_ElevationType zOffsetType = RS_ElevationType_RelativeToGround);
+ RENDERERS_API virtual void ProcessPolygon(LineBuffer * lb, RS_FillStyle & fill);
+ RENDERERS_API virtual void ProcessPolyline(LineBuffer * lb, RS_LineStroke & lsym);
+ RENDERERS_API virtual void ProcessRaster(unsigned char * data, int length, RS_ImageFormat format, int width, int height, RS_Bounds & extents, TransformMesh * xformMesh = NULL);
+ RENDERERS_API virtual void ProcessMarker(LineBuffer * lb, RS_MarkerDef & mdef, bool allowOverpost, RS_Bounds * bounds = NULL);
+ RENDERERS_API virtual void ProcessLabelGroup(RS_LabelInfo * labels, int nlabels, const RS_String & text, RS_OverpostType type, bool exclude, LineBuffer * path, double scaleLimit);
+ RENDERERS_API virtual void AddDWFContent(RS_InputStream * in, CSysTransformer * xformer, const RS_String & section, const RS_String & passwd, const RS_String & w2dfilter);
+ RENDERERS_API virtual void SetSymbolManager(RS_SymbolManager * manager);
+ RENDERERS_API virtual RS_MapUIInfo * GetMapInfo();
+ RENDERERS_API virtual RS_LayerUIInfo * GetLayerInfo();
+ RENDERERS_API virtual RS_FeatureClassInfo * GetFeatureClassInfo();
+ RENDERERS_API virtual double GetMapScale();
+ RENDERERS_API virtual double GetDrawingScale();
+ RENDERERS_API virtual double GetMetersPerUnit();
+ RENDERERS_API virtual double GetDpi();
+ RENDERERS_API virtual RS_Bounds & GetBounds();
+ RENDERERS_API virtual bool RequiresClipping();
+ RENDERERS_API virtual bool RequiresLabelClipping();
+ RENDERERS_API virtual bool SupportsZ();
+ RENDERERS_API virtual void DrawScreenPolyline(LineBuffer * polyline, const SE_Matrix * xform, const SE_LineStroke & lineStroke);
+ RENDERERS_API virtual void DrawScreenPolygon(LineBuffer * polygon, const SE_Matrix * xform, unsigned int fill);
+ RENDERERS_API virtual void DrawScreenRaster(unsigned char * data, int length, RS_ImageFormat format, int native_width, int native_height, double x, double y, double w, double h, double angleDeg);
+ RENDERERS_API virtual void DrawScreenRaster(unsigned char * data, int length, RS_ImageFormat format, int native_width, int native_height, double x, double y, double w, double h, double angleDeg, double alpha);
+ RENDERERS_API virtual void DrawScreenText(const RS_TextMetrics & tm, RS_TextDef & tdef, double insx, double insy, RS_F_Point * path, int npts, double param_position);
+ RENDERERS_API virtual bool YPointsUp();
+ RENDERERS_API virtual void GetWorldToScreenTransform(SE_Matrix & xform);
+ RENDERERS_API virtual void WorldToScreenPoint(double & inx, double & iny, double & ox, double & oy);
+ RENDERERS_API virtual void ScreenToWorldPoint(double & inx, double & iny, double & ox, double & oy);
+ RENDERERS_API virtual double GetScreenUnitsPerMillimeterDevice();
+ RENDERERS_API virtual double GetScreenUnitsPerMillimeterWorld();
+ RENDERERS_API virtual double GetScreenUnitsPerPixel();
+ RENDERERS_API virtual RS_FontEngine * GetRSFontEngine();
+ RENDERERS_API virtual void ProcessSELabelGroup(SE_LabelInfo * labels, int nlabels, RS_OverpostType type, bool exclude, LineBuffer * path = NULL);
+ RENDERERS_API virtual void AddExclusionRegion(RS_F_Point * fpts, int npts);
+ RENDERERS_API virtual RS_DesiredPolygonOrientation GetDesiredPolygonOrientation();
+
+ // MVT-specific. Caller responsible for calling ReleaseMVTContent() on the returned
+ // pointer once done
+ RENDERERS_API unsigned char* GetMVTContent(size_t& size);
+ RENDERERS_API void ReleaseMVTContent(unsigned char* buf);
+
+ // For unit testing purposes
+ RENDERERS_API static bool IsValidTile(unsigned char* buf, size_t size);
+
+private:
+ struct MVTImpl;
+ std::unique_ptr<MVTImpl> m_impl;
+
+ RS_FeatureReader* m_activeFeature;
+
+ // map/layer/feature info
+ RS_MapUIInfo* m_mapInfo;
+ RS_LayerUIInfo* m_layerInfo;
+ RS_FeatureClassInfo* m_fcInfo;
+
+ SE_Matrix m_xform;
+ SE_Matrix m_ixform;
+ int m_width;
+ int m_height;
+
+ RS_Bounds m_extents;
+ double m_drawingScale;
+ double m_metersPerUnit;
+ double m_dpi;
+ double m_mapScale;
+};
+
+#endif
\ No newline at end of file
Modified: trunk/MgDev/Common/Renderers/Renderers.vcxproj
===================================================================
--- trunk/MgDev/Common/Renderers/Renderers.vcxproj 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Renderers/Renderers.vcxproj 2019-10-06 12:18:03 UTC (rev 9630)
@@ -215,6 +215,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="MapQuantization.cpp" />
+ <ClCompile Include="MVTRenderer.cpp" />
+ <ClCompile Include="mvt\mvt_tile.cpp" />
<ClCompile Include="SymbolTrans.cpp" />
<ClCompile Include="DWFRenderer.cpp" />
<ClCompile Include="EPlotRenderer.cpp" />
@@ -259,6 +261,10 @@
<ClInclude Include="agg_utfgrid_context.h" />
<ClInclude Include="MapQuantization.h" />
<ClInclude Include="MapUTFGrid.h" />
+ <ClInclude Include="MVTRenderer.h" />
+ <ClInclude Include="mvt\gpb.h" />
+ <ClInclude Include="mvt\mvt_port.h" />
+ <ClInclude Include="mvt\mvt_tile.h" />
<ClInclude Include="SymbolTrans.h" />
<ClInclude Include="DWFRenderer.h" />
<ClInclude Include="DWFRSInputStream.h" />
Modified: trunk/MgDev/Common/Renderers/Renderers.vcxproj.filters
===================================================================
--- trunk/MgDev/Common/Renderers/Renderers.vcxproj.filters 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Renderers/Renderers.vcxproj.filters 2019-10-06 12:18:03 UTC (rev 9630)
@@ -25,6 +25,9 @@
<Filter Include="UTFGridRenderer">
<UniqueIdentifier>{139cab4d-e977-4ad2-8526-73e40cb9dde1}</UniqueIdentifier>
</Filter>
+ <Filter Include="MVTRenderer">
+ <UniqueIdentifier>{86e80f69-f211-4769-b8fe-549ba11f2bee}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SymbolTrans.cpp">
@@ -111,6 +114,12 @@
<ClCompile Include="UTFGridContent.cpp">
<Filter>UTFGridRenderer</Filter>
</ClCompile>
+ <ClCompile Include="mvt\mvt_tile.cpp">
+ <Filter>MVTRenderer</Filter>
+ </ClCompile>
+ <ClCompile Include="MVTRenderer.cpp">
+ <Filter>MVTRenderer</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SymbolTrans.h">
@@ -202,6 +211,18 @@
<ClInclude Include="MapUTFGrid.h">
<Filter>UTFGridRenderer</Filter>
</ClInclude>
+ <ClInclude Include="mvt\gpb.h">
+ <Filter>MVTRenderer</Filter>
+ </ClInclude>
+ <ClInclude Include="mvt\mvt_tile.h">
+ <Filter>MVTRenderer</Filter>
+ </ClInclude>
+ <ClInclude Include="mvt\mvt_port.h">
+ <Filter>MVTRenderer</Filter>
+ </ClInclude>
+ <ClInclude Include="MVTRenderer.h">
+ <Filter>MVTRenderer</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Renderers.rc" />
Modified: trunk/MgDev/Common/Stylization/DefaultStylizer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/DefaultStylizer.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/DefaultStylizer.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -343,7 +343,9 @@
try
{
if (!features->IsNull(gpName))
- features->GetGeometry(gpName, lb, xformer);
+ {
+ features->GetGeometry(gpName, lb, xformer, renderer->GetDesiredPolygonOrientation());
+ }
else
{
// just move on to the next feature
Modified: trunk/MgDev/Common/Stylization/LineBuffer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/LineBuffer.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/LineBuffer.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -901,6 +901,10 @@
for (int q=0; q<num_geoms; ++q)
{
+ // Mark the beginning of a new geometry
+ if (q > 0)
+ NewGeometry();
+
// skip past geometry type of subgeometry
// we know it is LineString or Polygon or Point respectively
if (is_multi)
Modified: trunk/MgDev/Common/Stylization/RS_FeatureReader.h
===================================================================
--- trunk/MgDev/Common/Stylization/RS_FeatureReader.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/RS_FeatureReader.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -41,7 +41,7 @@
virtual FdoInt32 GetInt32 (const wchar_t* propertyName) = 0;
virtual FdoInt64 GetInt64 (const wchar_t* propertyName) = 0;
virtual const wchar_t* GetString (const wchar_t* propertyName) = 0;
- virtual LineBuffer* GetGeometry (const wchar_t* propertyName, LineBuffer* lb, CSysTransformer* xformer) = 0;
+ virtual LineBuffer* GetGeometry (const wchar_t* propertyName, LineBuffer* lb, CSysTransformer* xformer, RS_DesiredPolygonOrientation polygonOrientation) = 0;
virtual RS_Raster* GetRaster (const wchar_t* propertyName) = 0;
virtual const wchar_t* GetAsString (const wchar_t* propertyName) = 0;
virtual RS_InputStream* GetBLOB (const wchar_t* propertyName) = 0;
Modified: trunk/MgDev/Common/Stylization/Renderer.h
===================================================================
--- trunk/MgDev/Common/Stylization/Renderer.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/Renderer.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -240,6 +240,9 @@
// line buffer pool access
virtual SE_BufferPool* GetBufferPool() = 0;
virtual void SetBufferPool(SE_BufferPool* pool) = 0;
+
+ // States the desired polygon orientation
+ virtual RS_DesiredPolygonOrientation GetDesiredPolygonOrientation() = 0;
};
#endif
Modified: trunk/MgDev/Common/Stylization/RendererStyles.h
===================================================================
--- trunk/MgDev/Common/Stylization/RendererStyles.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/RendererStyles.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -23,7 +23,14 @@
typedef std::wstring RS_String;
+enum RS_DesiredPolygonOrientation
+{
+ Clockwise,
+ CounterClockwise,
+ NotApplicable
+};
+
//////////////////////////////////////////////////////////////////////////////
enum RS_HAlignment
{
Modified: trunk/MgDev/Common/Stylization/SE_Renderer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_Renderer.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/SE_Renderer.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -722,3 +722,8 @@
{
return true;
}
+
+RS_DesiredPolygonOrientation SE_Renderer::GetDesiredPolygonOrientation()
+{
+ return RS_DesiredPolygonOrientation::NotApplicable;
+}
\ No newline at end of file
Property changes on: trunk/MgDev/Common/Stylization/SE_Renderer.cpp
___________________________________________________________________
Modified: svn:mergeinfo
## -2,6 +2,7 ##
/branches/2.6/MgDev/Common/Stylization/SE_Renderer.cpp:8340
/sandbox/adsk/2.4j/Common/Stylization/SE_Renderer.cpp:6327-6445
/sandbox/jng/createruntimemap/Common/Stylization/SE_Renderer.cpp:7486-7555
+/sandbox/jng/mvt/Common/Stylization/SE_Renderer.cpp:9546-9547
+/sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.cpp:9604-9629
/sandbox/jng/v4/Common/Stylization/SE_Renderer.cpp:9511-9519
-/sandbox/rfc94/Common/Stylization/SE_Renderer.cpp:5099-5163
-/trunk/MgDev/Common/Stylization/SE_Renderer.cpp:6250-6326
\ No newline at end of property
+/sandbox/rfc94/Common/Stylization/SE_Renderer.cpp:5099-5163
\ No newline at end of property
Modified: trunk/MgDev/Common/Stylization/SE_Renderer.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_Renderer.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/SE_Renderer.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -136,6 +136,11 @@
// overridden.
STYLIZATION_API virtual bool OptimizeGeometry();
+ // Indicate the desired polygon orientation for this renderer. Some renderers may demand
+ // that polygon data passed to it be of a particular orientation. It will be the responsibility
+ // of the Stylizer to make sure this requirement is met.
+ STYLIZATION_API virtual RS_DesiredPolygonOrientation GetDesiredPolygonOrientation();
+
private:
void ProcessLineOverlapWrap(LineBuffer* geometry, SE_RenderLineStyle* style);
void ProcessLineOverlapNone(LineBuffer* geometry, SE_RenderLineStyle* style);
Modified: trunk/MgDev/Common/Stylization/StylizationEngine.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/StylizationEngine.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Common/Stylization/StylizationEngine.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -145,7 +145,9 @@
try
{
if (!reader->IsNull(gpName))
- reader->GetGeometry(gpName, lb, xformer);
+ {
+ reader->GetGeometry(gpName, lb, xformer, se_renderer->GetDesiredPolygonOrientation());
+ }
else
{
// just move on to the next feature
Modified: trunk/MgDev/Doc/samples/ol2samples/wms/index.html
===================================================================
--- trunk/MgDev/Doc/samples/ol2samples/wms/index.html 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Doc/samples/ol2samples/wms/index.html 2019-10-06 12:18:03 UTC (rev 9630)
@@ -63,7 +63,7 @@
<div id="main">
<div class="container">
<div class="alert alert-info">
- <p>This example demonstrates a Map Definition being consumed as a <strong>XYZ layer</strong> via the MapGuide REST API with <a href="http://openlayers.org/">OpenLayers 3</a>.</p>
+ <p>This example demonstrates a Map Definition being consumed as a <strong>XYZ layer</strong> with <a href="http://openlayers.org/">OpenLayers 3</a>.</p>
<p>An OpenStreetMap layer is included as a backdrop for context</p>
<strong>For maximum visual fidelity, your Map Definition should be in WGS84.PseudoMercator</strong>
<p>Sample not loading? <a href="../data/load.php">Check that the required resources have been loaded</a></p>
Modified: trunk/MgDev/Doc/samples/ol2samples/xyz/index_ol.html
===================================================================
--- trunk/MgDev/Doc/samples/ol2samples/xyz/index_ol.html 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Doc/samples/ol2samples/xyz/index_ol.html 2019-10-06 12:18:03 UTC (rev 9630)
@@ -57,7 +57,7 @@
<div id="main">
<div class="container">
<div class="alert alert-info">
- <p>This example demonstrates a Map Definition being consumed as a <strong>XYZ layer</strong> via the MapGuide REST API with <a href="http://openlayers.org/">OpenLayers 3</a>.</p>
+ <p>This example demonstrates a Map Definition being consumed as a <strong>XYZ layer</strong> with <a href="http://openlayers.org/">OpenLayers 3</a>.</p>
<p>An OpenStreetMap layer is included as a backdrop for context</p>
<strong>For maximum visual fidelity, your Map Definition should be in WGS84.PseudoMercator</strong>
<p>Sample not loading? <a href="../data/load.php">Check that the required resources have been loaded</a></p>
Modified: trunk/MgDev/Doc/samples/samples.php
===================================================================
--- trunk/MgDev/Doc/samples/samples.php 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Doc/samples/samples.php 2019-10-06 12:18:03 UTC (rev 9630)
@@ -127,6 +127,7 @@
<li><a href="ol2samples/xyz/index_ol.html">Sheboygan map as XYZ layer</a></li>
<li><a href="ol2samples/utfgrid/index.html">Sheboygan map as XYZ layer with UTFGrid interaction tiles</a></li>
<li><a href="ol2samples/wms/index.html">Sheboygan map as WMS layers</a></li>
+ <li><a href="ol2samples/mvt/index.html">Sheboygan map as Mapbox Vector Tiles</a></li>
</ul>
<? } ?>
<? } ?>
Modified: trunk/MgDev/License.txt
===================================================================
--- trunk/MgDev/License.txt 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/License.txt 2019-10-06 12:18:03 UTC (rev 9630)
@@ -95,6 +95,69 @@
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+MVT tile encoder copied from MVT driver for GDAL/OGR and adapted
+for use in MapGuide
+
+Files:
+ Common/Renderers/mvt/gpb.h
+ Common/Renderers/mvt/mvt_port.h (copied from cpl_port.h)
+ Common/Renderers/mvt/mvt_tile.h
+ Common/Renderers/mvt/mvt_tile.cpp
+
+Copyright (c) 1998, 2005, Frank Warmerdam
+Copyright (c) 2018, Even Rouault
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+UTFGrid encoder and PNG8 map quantization copied from MapServer and adapted
+for use in MapGuide
+
+Files:
+ Common/Renderers/MapUTFGrid.h
+ Common/Renderers/MapQuantization.h
+ Common/Renderers/MapQuantization.cpp
+
+Copyright (c) 1996-2005 Regents of the University of Minnesota.
+Copyright (c) 1996-2007 Regents of the University of Minnesota.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies of this Software or works derived from this Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
Copyright and Licensing Information for ACE(TM)
ACE(TM), TAO(TM), CIAO(TM), and CoSMIC(TM) (henceforth referred to as "DOC
Modified: trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -22,6 +22,8 @@
#include "LineBuffer.h"
#include "ServerFeatureReader.h"
#include "ServerGwsFeatureReader.h"
+#include "FdoGeometry.h"
+#include "FdoSpatial.h"
//we want to catch the MgException and rethrow a FdoException which
//the Stylizer knows how to catch and release. It does not know about
@@ -297,7 +299,8 @@
LineBuffer* RSMgFeatureReader::GetGeometry(const wchar_t* propertyName,
LineBuffer* lb,
- CSysTransformer* xformer)
+ CSysTransformer* xformer,
+ RS_DesiredPolygonOrientation polygonOrientation)
{
RSFR_TRY()
@@ -311,8 +314,66 @@
throw FdoException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_60_NULL_POINTER)));
_ASSERT(lb);
- lb->LoadFromAgf(agf, sz, xformer);
+ //Peek at the raw AGF bytes to see if it's a polygon ahead of time.
+ int* ireader = (int*)agf;
+ // the geometry type
+ auto geomType = (FdoGeometryType)*ireader++;
+ bool isPolygon = geomType == FdoGeometryType_Polygon
+ || geomType == FdoGeometryType_MultiPolygon
+ || geomType == FdoGeometryType_CurvePolygon
+ || geomType == FdoGeometryType_MultiCurvePolygon;
+
+ if (isPolygon && polygonOrientation != RS_DesiredPolygonOrientation::NotApplicable)
+ {
+ FdoPtr<FdoFgfGeometryFactory> geomFactory = FdoFgfGeometryFactory::GetInstance();
+ FdoPtr<FdoIGeometry> geom = geomFactory->CreateGeometryFromFgf(agf, sz);
+ FdoPtr<FdoIGeometry> reoriented;
+
+ switch (polygonOrientation)
+ {
+ case RS_DesiredPolygonOrientation::Clockwise:
+ {
+ reoriented = FdoSpatialUtility::FixPolygonVertexOrder(geom, FdoPolygonVertexOrderRule_CW);
+ FdoPtr<FdoByteArray> reFgf;
+ if (NULL != reoriented.p)
+ {
+ reFgf = geomFactory->GetFgf(reoriented);
+ lb->LoadFromAgf(reFgf->GetData(), reFgf->GetCount(), xformer);
+ }
+ else //Load original
+ {
+ lb->LoadFromAgf(agf, sz, xformer);
+ }
+ break;
+ }
+ case RS_DesiredPolygonOrientation::CounterClockwise:
+ {
+ reoriented = FdoSpatialUtility::FixPolygonVertexOrder(geom, FdoPolygonVertexOrderRule_CCW);
+ FdoPtr<FdoByteArray> reFgf;
+ if (NULL != reoriented.p)
+ {
+ reFgf = geomFactory->GetFgf(reoriented);
+ lb->LoadFromAgf(reFgf->GetData(), reFgf->GetCount(), xformer);
+ }
+ else //Load original
+ {
+ lb->LoadFromAgf(agf, sz, xformer);
+ }
+ break;
+ }
+ default:
+ {
+ _ASSERT(false);
+ break;
+ }
+ }
+ }
+ else
+ {
+ lb->LoadFromAgf(agf, sz, xformer);
+ }
+
return lb;
RSFR_CATCH()
Modified: trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.h
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Mapping/RSMgFeatureReader.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -58,7 +58,7 @@
virtual FdoInt32 GetInt32 (const wchar_t* propertyName);
virtual FdoInt64 GetInt64 (const wchar_t* propertyName);
virtual const wchar_t* GetString (const wchar_t* propertyName);
- virtual LineBuffer* GetGeometry (const wchar_t* propertyName, LineBuffer* lb, CSysTransformer* xformer);
+ virtual LineBuffer* GetGeometry (const wchar_t* propertyName, LineBuffer* lb, CSysTransformer* xformer, RS_DesiredPolygonOrientation polygonOrientation);
virtual RS_Raster* GetRaster (const wchar_t* propertyName);
virtual const wchar_t* GetAsString (const wchar_t* propertyName);
virtual RS_InputStream* GetBLOB (const wchar_t* propertyName);
Modified: trunk/MgDev/Server/src/Services/Mapping/ServerMappingService.vcxproj
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/ServerMappingService.vcxproj 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Mapping/ServerMappingService.vcxproj 2019-10-06 12:18:03 UTC (rev 9630)
@@ -104,10 +104,10 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
- <AdditionalDependencies>ACEd.lib;xerces-c_3mgD.lib;FDO.lib;FDOCommon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>ACEd.lib;xerces-c_3mgD.lib;FDO.lib;FDOCommon.lib;FDOGeometry.lib;FDOSpatial.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)MgServerMappingServiced.dll</OutputFile>
<AdditionalLibraryDirectories>..\..\..\..\Oem\ACE\ACE_wrappers\lib\$(Configuration);..\..\..\..\Oem\dbxml\lib\$(Configuration);..\..\..\..\Oem\FDO\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <DelayLoadDLLs>FDO.dll;FDOCommon.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <DelayLoadDLLs>FDO.dll;FDOCommon.dll;FDOGeometry.dll;FDOSpatial.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)MgServerMappingServiced.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
@@ -131,10 +131,10 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
- <AdditionalDependencies>ACEd.lib;xerces-c_3mgD.lib;FDO.lib;FDOCommon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>ACEd.lib;xerces-c_3mgD.lib;FDO.lib;FDOCommon.lib;FDOGeometry.lib;FDOSpatial.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)MgServerMappingServiced.dll</OutputFile>
<AdditionalLibraryDirectories>..\..\..\..\Oem\ACE\ACE_wrappers\lib64\$(Configuration);..\..\..\..\Oem\dbxml\lib64\$(Configuration);..\..\..\..\Oem\FDO\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <DelayLoadDLLs>FDO.dll;FDOCommon.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <DelayLoadDLLs>FDO.dll;FDOCommon.dll;FDOGeometry.dll;FDOSpatial.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)MgServerMappingServiced.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
@@ -157,10 +157,10 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
- <AdditionalDependencies>ACE.lib;xerces-c_3mg.lib;FDO.lib;FDOCommon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>ACE.lib;xerces-c_3mg.lib;FDO.lib;FDOCommon.lib;FDOGeometry.lib;FDOSpatial.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)MgServerMappingService.dll</OutputFile>
<AdditionalLibraryDirectories>..\..\..\..\Oem\ACE\ACE_wrappers\lib\$(Configuration);..\..\..\..\Oem\dbxml\lib\$(Configuration);..\..\..\..\Oem\FDO\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <DelayLoadDLLs>FDO.dll;FDOCommon.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <DelayLoadDLLs>FDO.dll;FDOCommon.dll;FDOGeometry.dll;FDOSpatial.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)MgServerMappingService.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
@@ -185,10 +185,10 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
- <AdditionalDependencies>ACE.lib;xerces-c_3mg.lib;FDO.lib;FDOCommon.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>ACE.lib;xerces-c_3mg.lib;FDO.lib;FDOCommon.lib;FDOGeometry.lib;FDOSpatial.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)MgServerMappingService.dll</OutputFile>
<AdditionalLibraryDirectories>..\..\..\..\Oem\ACE\ACE_wrappers\lib64\$(Configuration);..\..\..\..\Oem\dbxml\lib64\$(Configuration);..\..\..\..\Oem\FDO\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <DelayLoadDLLs>FDO.dll;FDOCommon.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <DelayLoadDLLs>FDO.dll;FDOCommon.dll;FDOGeometry.dll;FDOSpatial.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)MgServerMappingService.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
Copied: trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.cpp (from rev 9629, sandbox/jng/mvt_alt/Server/src/Services/Rendering/OpRenderTileMVT.cpp)
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.cpp (rev 0)
+++ trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,111 @@
+//
+// Copyright (C) 2004-2019 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#include "OpRenderTileMVT.h"
+#include "LogManager.h"
+
+MgOpRenderTileMVT::MgOpRenderTileMVT()
+{
+}
+
+MgOpRenderTileMVT::~MgOpRenderTileMVT()
+{
+}
+
+void MgOpRenderTileMVT::Execute()
+{
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT(" (%t) MgOpRenderTileMVT::Execute()\n")));
+
+ MG_LOG_OPERATION_MESSAGE(L"MgOpRenderTileMVT");
+
+ MG_TRY()
+
+ MG_LOG_OPERATION_MESSAGE_INIT(m_packet.m_OperationVersion, m_packet.m_NumArguments);
+
+ ACE_ASSERT(m_stream != NULL);
+
+ if (6 == 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);
+
+ 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_PARAMETERS_END();
+
+ Validate();
+
+ Ptr<MgByteReader> byteReader = m_service->RenderTileMVT(map, baseMapLayerGroupName, x, y, z, tileDpi);
+
+ EndExecution(byteReader);
+ }
+ else
+ {
+ MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+ MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+ }
+
+ if (!m_argsRead)
+ {
+ throw new MgOperationProcessingException(L"MgOpRenderTileMVT.Execute",
+ __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Successful operation
+ MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Success.c_str());
+
+ MG_CATCH(L"MgOpRenderTileMVT.Execute")
+
+ if (mgException != NULL)
+ {
+ // Failed operation
+ MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Failure.c_str());
+ }
+
+ // Add access log entry for operation
+ MG_LOG_OPERATION_MESSAGE_ACCESS_ENTRY();
+
+ MG_THROW()
+}
Copied: trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.h (from rev 9629, sandbox/jng/mvt_alt/Server/src/Services/Rendering/OpRenderTileMVT.h)
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.h (rev 0)
+++ trunk/MgDev/Server/src/Services/Rendering/OpRenderTileMVT.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2004-2019 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef MG_OP_RENDER_TILE_MVT_H
+#define MG_OP_RENDER_TILE_MVT_H
+
+#include "RenderingOperation.h"
+
+class MgOpRenderTileMVT : public MgRenderingOperation
+{
+public:
+ MgOpRenderTileMVT();
+ virtual ~MgOpRenderTileMVT();
+
+public:
+ virtual void Execute();
+};
+
+#endif
\ No newline at end of file
Modified: trunk/MgDev/Server/src/Services/Rendering/RenderingOperationFactory.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/RenderingOperationFactory.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/RenderingOperationFactory.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -153,7 +153,17 @@
L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
}
break;
-
+ case MgRenderingServiceOpId::RenderTileMVT:
+ switch (VERSION_NO_PHASE(operationVersion))
+ {
+ case VERSION_SUPPORTED(4, 0):
+ handler.reset(new MgOpRenderTileMVT());
+ break;
+ default:
+ throw new MgInvalidOperationVersionException(
+ L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+ break;
case MgRenderingServiceOpId::RenderDynamicOverlay:
switch (VERSION_NO_PHASE(operationVersion))
{
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -20,6 +20,7 @@
#include "DefaultStylizer.h"
#include "AGGRenderer.h"
#include "UTFGridRenderer.h"
+#include "MVTRenderer.h"
#include "RSMgSymbolManager.h"
#include "RSMgFeatureReader.h"
#include "FeatureInfoRenderer.h"
@@ -38,6 +39,9 @@
#define XYZ_TILE_WIDTH 256
#define XYZ_TILE_HEIGHT 256
+#define MVT_TILE_WIDTH 4096
+#define MVT_TILE_HEIGHT 4096
+
// the maximum number of allowed pixels for rendered images
static const INT32 MAX_PIXELS = 16384*16384;
static const INT32 FILTER_VISIBLE = 1;
@@ -204,7 +208,7 @@
return ret.Detach();
}
-void MgServerRenderingService::ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
+void MgServerRenderingService::ComputeXYZTileExtents(MgCoordinateSystem* mapCs, 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
//
@@ -221,11 +225,9 @@
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")
{
+ Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
//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);
@@ -246,6 +248,14 @@
extent.maxy = mcsMaxY;
}
+void MgServerRenderingService::ComputeXYZTileExtents(STRING mapCsWkt, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
+{
+ Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
+ Ptr<MgCoordinateSystem> mapCs = csFactory->Create(mapCsWkt);
+
+ ComputeXYZTileExtents(mapCs, x, y, z, extent);
+}
+
MgByteReader* MgServerRenderingService::RenderTileXYZ(MgMap* map,
CREFSTRING baseMapLayerGroupName,
INT32 x,
@@ -313,7 +323,7 @@
// get map extent that corresponds to tile extent
RS_Bounds extent;
- ComputeXYZTileExtents(map, x, y, z, extent);
+ ComputeXYZTileExtents(map->GetMapSRS(), x, y, z, extent);
// use the map's background color, but always make it fully transparent
RS_Color bgColor;
@@ -339,7 +349,7 @@
// 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);
+ throw new MgOutOfRangeException(L"MgServerRenderingService.RenderTileUTFGrid", __LINE__, __WFILE__, NULL, L"MgInvalidImageSizeTooBig", NULL);
// create a temporary collection containing all the layers for the base group
Ptr<MgLayerCollection> layers = map->GetLayers();
@@ -428,6 +438,130 @@
return ret.Detach();
}
+MgByteReader* MgServerRenderingService::RenderTileMVT(MgMap * map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi)
+{
+ Ptr<MgByteReader> ret;
+
+ MG_TRY()
+
+ CHECKARGUMENTNULL(map, L"MgServerRenderingService.RenderTileMVT");
+ CHECKARGUMENTEMPTYSTRING(baseMapLayerGroupName, L"MgServerRenderingService.RenderTileMVT");
+
+ // 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.RenderTileMVT",
+ __LINE__, __WFILE__, &arguments, L"MgMapLayerGroupNameNotFound", NULL);
+ }
+
+ //Set the dpi
+ map->SetDisplayDpi(dpi);
+
+ int width = MVT_TILE_WIDTH;
+ int height = MVT_TILE_HEIGHT;
+
+ // MVT tiles are always written in web mercator
+ STRING srs = m_pCSFactory->ConvertCoordinateSystemCodeToWkt(L"WGS84.PseudoMercator");
+ Ptr<MgCoordinateSystem> dstCs = m_pCSFactory->Create(srs);
+ double metersPerUnit = dstCs->ConvertCoordinateSystemUnitsToMeters(1.0);
+
+ // 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(dstCs, x, y, z, extent);
+
+ INT32 drawWidth = width;
+ INT32 drawHeight = height;
+ double scale = 0.0;
+ ComputeScaledDimensions(extent, width, height, dpi, metersPerUnit, drawWidth, drawHeight, scale);
+
+ //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());
+
+ // 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 MVTRenderer 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);
+
+ 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();
+
+ MVTRenderer dr(x, y, z);
+
+ RSMgSymbolManager mgr(m_svcResource);
+ dr.SetSymbolManager(&mgr);
+
+ SEMgSymbolManager semgr(m_svcResource);
+ DefaultStylizer ds(&semgr);
+
+ RS_Color bgcolor(0, 0, 0, 255); //Not used by MVTRenderer
+
+ 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, dstCs, true, scale, L"MVT", NULL);
+
+ dr.EndMap();
+
+ // restore the base group's visibility
+ baseGroup->SetVisible(groupVisible);
+
+ // Now extract the encoded MVT tile and pack it into a MgByteReader
+ size_t size;
+ auto buf = dr.GetMVTContent(size);
+ Ptr<MgByte> mvtBytes = new MgByte(buf, size);
+ dr.ReleaseMVTContent(buf);
+ Ptr<MgByteSource> bs = new MgByteSource(mvtBytes);
+
+ bs->SetMimeType(MgMimeType::Mvt);
+
+ ret = bs->GetReader();
+
+ MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTileMVT")
+
+ return ret.Detach();
+}
+
///////////////////////////////////////////////////////////////////////////////
/// render a map using all layers from the baseGroup
MgByteReader* MgServerRenderingService::RenderTileInternal(MgMap* map,
@@ -2405,7 +2539,8 @@
// 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);
+ STRING mapSrs = map->GetMapSRS();
+ ComputeXYZTileExtents(mapSrs, x, y, z, extent);
// If meta-tiling, request bounds for:
// (x, y, z) -> (x + (tm - 1), y + (tm - 1), z)
@@ -2415,7 +2550,7 @@
RS_Bounds extent2;
INT32 endX = x + (metaTilingFactor - 1);
INT32 endY = y + (metaTilingFactor - 1);
- ComputeXYZTileExtents(map, endX, endY, z, extent2);
+ ComputeXYZTileExtents(mapSrs, endX, endY, z, extent2);
extent.add_bounds(extent2);
}
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -100,6 +100,13 @@
INT32 z,
INT32 dpi);
+ virtual MgByteReader* RenderTileMVT(MgMap* map,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 x,
+ INT32 y,
+ INT32 z,
+ INT32 dpi);
+
virtual MgByteReader* RenderDynamicOverlay(MgMap* map,
MgSelection* selection,
CREFSTRING format);
@@ -304,7 +311,8 @@
static void ComputeScaledDimensions(RS_Bounds& extent, INT32 width, INT32 height, INT32 dpi,
double metersPerUnit, INT32& drawWidth, INT32& drawHeight, double& scale);
- static void ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
+ static void ComputeXYZTileExtents(MgCoordinateSystem* mapCs, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
+ static void ComputeXYZTileExtents(STRING mapCsWkt, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
// used for tile generation
MgByteReader* RenderTileInternal(MgMap* map,
MgLayerGroup* baseGroup,
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj 2019-10-06 12:18:03 UTC (rev 9630)
@@ -252,6 +252,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="OpRenderTileMVT.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="OpRenderTileXYZ.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -318,6 +324,7 @@
<ClInclude Include="OpRenderMetatileXYZ.h" />
<ClInclude Include="OpRenderTile.h" />
<ClInclude Include="OpRenderTileFromMetatile.h" />
+ <ClInclude Include="OpRenderTileMVT.h" />
<ClInclude Include="OpRenderTileXYZ.h" />
<ClInclude Include="OpRenderTileUTFGrid.h" />
<ClInclude Include="RenderingOperation.h" />
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.vcxproj.filters 2019-10-06 12:18:03 UTC (rev 9630)
@@ -51,6 +51,9 @@
<ClCompile Include="OpRenderTileFromMetatile.cpp">
<Filter>Ops</Filter>
</ClCompile>
+ <ClCompile Include="OpRenderTileMVT.cpp">
+ <Filter>Ops</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="OpQueryFeatureProperties.h">
@@ -98,6 +101,9 @@
<ClInclude Include="OpRenderTileFromMetatile.h">
<Filter>Ops</Filter>
</ClInclude>
+ <ClInclude Include="OpRenderTileMVT.h">
+ <Filter>Ops</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ServerRenderingService.rc" />
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingServiceBuild.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -29,6 +29,7 @@
#include "OpRenderTile.cpp"
#include "OpRenderTileXYZ.cpp"
#include "OpRenderTileUTFGrid.cpp"
+#include "OpRenderTileMVT.cpp"
#include "OpQueryFeatures.cpp"
#include "OpQueryFeatureProperties.cpp"
#include "RenderingOperation.cpp"
Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -410,6 +410,7 @@
xml.append("<Value>JPG</Value>");
xml.append("<Value>GIF</Value>");
xml.append("<Value>UTFGRID</Value>");
+ xml.append("<Value>MVT</Value>");
xml.append("</ConnectionProperty>\n");
//Property: RetinaScale
Modified: trunk/MgDev/Server/src/Services/Tile/TileCacheXYZProvider.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileCacheXYZProvider.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/Services/Tile/TileCacheXYZProvider.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -46,7 +46,7 @@
bool MgTileCacheXYZProvider::IsTileImageFormat()
{
- return m_format == L"UTFGRID";
+ return m_format != L"UTFGRID" && m_format != L"MVT";
}
MgByteReader* MgTileCacheXYZProvider::GetTile(CREFSTRING baseMapLayerGroupName,
@@ -83,9 +83,14 @@
if (svcRendering != NULL)
{
// Test for non-image formats first
- if (m_format == L"UTFGRID")
+ if (m_format == L"MVT")
{
// generate the tile
+ img = svcRendering->RenderTileMVT(map, baseMapLayerGroupName, tileRow, tileColumn, scaleIndex, map->GetDisplayDpi());
+ }
+ else if (m_format == L"UTFGRID")
+ {
+ // generate the tile
img = svcRendering->RenderTileUTFGrid(map, baseMapLayerGroupName, tileRow, tileColumn, scaleIndex, map->GetDisplayDpi());
}
else //Assume it must be image-based at this point
@@ -111,11 +116,15 @@
INT32 MgTileCacheXYZProvider::GetDefaultTileSizeX()
{
+ if (m_format == L"MVT")
+ return 4096;
return 256 * m_retinaScale;
}
INT32 MgTileCacheXYZProvider::GetDefaultTileSizeY()
{
+ if (m_format == L"MVT")
+ return 4096;
return 256 * m_retinaScale;
}
@@ -143,6 +152,10 @@
{
return L"utfgrid";
}
+ else if (m_format == L"MVT")
+ {
+ return L"mvt";
+ }
else
{
return L"png";
Modified: trunk/MgDev/Server/src/UnitTesting/CMakeLists.txt
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/CMakeLists.txt 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/CMakeLists.txt 2019-10-06 12:18:03 UTC (rev 9630)
@@ -7,6 +7,7 @@
${MG_COMMON_DIR}/MapGuideCommon
${MG_COMMON_DIR}/MdfModel
${MG_COMMON_DIR}/MdfParser
+ ${MG_COMMON_DIR}/Renderers
${MG_COMMON_DIR}/Stylization
${MG_SERVER_COMMON_DIR}
${MG_SERVER_COMMON_DIR}/Manager
Modified: trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -23,6 +23,8 @@
#include "../UnitTesting/CppUnitExtensions.h"
#include "FoundationDefs.h"
#include "FdoConnectionManager.h"
+#include "LineBuffer.h"
+#include "RS_BufferOutputStream.h"
const STRING TEST_LOCALE = L"en";
static const INT32 MG_TEST_THREADS = 16;
@@ -794,7 +796,7 @@
GetConfigValueThreadData* threadData = (GetConfigValueThreadData*)param;
INT32 threadId = threadData->threadId;
#ifdef _DEBUG
- printf("> thread %d started, tile %d,%d\n", threadId, tileRow, tileCol);
+ printf("> thread %d started\n", threadId);
#endif
try
@@ -912,4 +914,519 @@
{
throw;
}
+}
+
+void TestMisc::TestCase_LineBuffer_Conversion()
+{
+ //This isn't really a test, it's more verification and internal documentation
+ //of how LineBuffers are meant to be represented for various geometry types
+ try
+ {
+ MgWktReaderWriter wktRw;
+ MgAgfReaderWriter agfRw;
+ Ptr<MgGeometry> gPoint = wktRw.Read(L"POINT (30 10)");
+ Ptr<MgGeometry> gMultiPoint = wktRw.Read(L"MULTIPOINT (10 40, 40 30, 20 20, 30 10)");
+ Ptr<MgGeometry> gLineStr = wktRw.Read(L"LINESTRING (30 10, 10 30, 40 40)");
+ Ptr<MgGeometry> gMultiLineString = wktRw.Read(L"MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))");
+ Ptr<MgGeometry> gPolygon1 = wktRw.Read(L"POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))");
+ Ptr<MgGeometry> gPolygon2 = wktRw.Read(L"POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))");
+ STRING mpWkt1 = L"MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))";
+ Ptr<MgGeometry> gMultiPolygon1 = wktRw.Read(mpWkt1);
+ STRING mpWkt2 = L"MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)))";
+ Ptr<MgGeometry> gMultiPolygon2 = wktRw.Read(mpWkt2);
+
+ //Point
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gPoint);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(1 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.point_count());
+ CPPUNIT_ASSERT(30 == lb.x_coord(0));
+ CPPUNIT_ASSERT(10 == lb.y_coord(0));
+ }
+
+ //MultiPoint
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gMultiPoint);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(4 == lb.geom_count());
+ CPPUNIT_ASSERT(4 == lb.point_count());
+ CPPUNIT_ASSERT(10 == lb.x_coord(0));
+ CPPUNIT_ASSERT(40 == lb.y_coord(0));
+ CPPUNIT_ASSERT(40 == lb.x_coord(1));
+ CPPUNIT_ASSERT(30 == lb.y_coord(1));
+ CPPUNIT_ASSERT(20 == lb.x_coord(2));
+ CPPUNIT_ASSERT(20 == lb.y_coord(2));
+ CPPUNIT_ASSERT(30 == lb.x_coord(3));
+ CPPUNIT_ASSERT(10 == lb.y_coord(3));
+ }
+
+ //LineString
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gLineStr);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ int lineIdx = 0;
+ CPPUNIT_ASSERT(1 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.cntr_count());
+ CPPUNIT_ASSERT(3 == lb.cntr_size(lineIdx));
+
+ auto ptOffset = lb.contour_start_point(lineIdx);
+ for (int i = 0; i < lb.cntr_size(lineIdx); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ }
+ }
+ }
+
+ //MultiLineString
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gMultiLineString);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(2 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.geom_size(0));
+ CPPUNIT_ASSERT(1 == lb.geom_size(1));
+ CPPUNIT_ASSERT(2 == lb.cntr_count());
+ CPPUNIT_ASSERT(3 == lb.cntr_size(0));
+ CPPUNIT_ASSERT(4 == lb.cntr_size(1));
+
+ //LineString 1
+ {
+ auto ptOffset = lb.contour_start_point(0);
+ for (int i = 0; i < lb.cntr_size(0); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ }
+ }
+ }
+
+ //LineString 2
+ {
+ auto ptOffset = lb.contour_start_point(1);
+ for (int i = 0; i < lb.cntr_size(1); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ }
+ }
+ }
+ }
+
+ //Polygon 1 (1 outer, 0 inner)
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gPolygon1);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(1 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.geom_size(0));
+ auto cc = lb.cntr_count();
+ CPPUNIT_ASSERT(1 == cc);
+
+ int lineIdx = 0;
+ CPPUNIT_ASSERT(5 == lb.cntr_size(lineIdx));
+
+ auto ptOffset = lb.contour_start_point(lineIdx);
+ for (int i = 0; i < lb.cntr_size(lineIdx); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 4:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ }
+ }
+ }
+
+ //Polygon 2 (1 outer, 1 inner)
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gPolygon2);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(1 == lb.geom_count());
+ CPPUNIT_ASSERT(2 == lb.geom_size(0));
+ auto cc = lb.cntr_count();
+ CPPUNIT_ASSERT(2 == cc);
+
+ //Outer Ring
+ {
+ CPPUNIT_ASSERT(5 == lb.cntr_size(0));
+ auto ptOffset = lb.contour_start_point(0);
+ for (int i = 0; i < lb.cntr_size(0); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(35 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(45 == x);
+ CPPUNIT_ASSERT(45 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(15 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 4:
+ CPPUNIT_ASSERT(35 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ }
+ }
+ }
+
+ //Inner Ring
+ {
+ CPPUNIT_ASSERT(4 == lb.cntr_size(1));
+ auto ptOffset = lb.contour_start_point(1);
+ for (int i = 0; i < lb.cntr_size(1); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(35 == x);
+ CPPUNIT_ASSERT(35 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ }
+ }
+ }
+ }
+
+ //MultiPolygon 1
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gMultiPolygon1);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(2 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.geom_size(0));
+ CPPUNIT_ASSERT(1 == lb.geom_size(1));
+ auto cc = lb.cntr_count();
+ CPPUNIT_ASSERT(2 == cc);
+ auto closed1 = lb.contour_closed(0);
+ auto closed2 = lb.contour_closed(1);
+
+ //Polygon 1
+ {
+ CPPUNIT_ASSERT(4 == lb.cntr_size(0));
+ auto ptOffset = lb.contour_start_point(0);
+ for (int i = 0; i < lb.cntr_size(0); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(45 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ }
+ }
+ }
+
+ //Polygon 2
+ {
+ CPPUNIT_ASSERT(5 == lb.cntr_size(1));
+ auto ptOffset = lb.contour_start_point(1);
+ for (int i = 0; i < lb.cntr_size(1); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(15 == x);
+ CPPUNIT_ASSERT(5 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(5 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 4:
+ CPPUNIT_ASSERT(15 == x);
+ CPPUNIT_ASSERT(5 == y);
+ break;
+ }
+ }
+ }
+
+ RS_BufferOutputStream ros(bytes->GetLength());
+ lb.ToAgf(&ros);
+
+ Ptr<MgByte> obs = new MgByte(ros.data(), ros.length());
+ Ptr<MgByteSource> bs = new MgByteSource(obs);
+ Ptr<MgByteReader> oagf = bs->GetReader();
+
+ Ptr<MgGeometry> g2 = agfRw.Read(oagf);
+ STRING owkt = wktRw.Write(g2);
+ CPPUNIT_ASSERT(owkt == mpWkt1);
+ }
+
+ //MultiPolygon 2
+ {
+ LineBuffer lb(8);
+ Ptr<MgByteReader> agf = agfRw.Write(gMultiPolygon2);
+ Ptr<MgByteSink> agfSink = new MgByteSink(agf);
+ Ptr<MgByte> bytes = agfSink->ToBuffer();
+ lb.LoadFromAgf(bytes->Bytes(), bytes->GetLength(), nullptr);
+
+ CPPUNIT_ASSERT(2 == lb.geom_count());
+ CPPUNIT_ASSERT(1 == lb.geom_size(0));
+ CPPUNIT_ASSERT(2 == lb.geom_size(1));
+ auto cc = lb.cntr_count();
+ CPPUNIT_ASSERT(3 == cc);
+ auto closed1 = lb.contour_closed(0);
+ auto closed2 = lb.contour_closed(1);
+ auto closed3 = lb.contour_closed(2);
+
+ //Polygon 1
+ {
+ CPPUNIT_ASSERT(4 == lb.cntr_size(0));
+ auto ptOffset = lb.contour_start_point(0);
+ for (int i = 0; i < lb.cntr_size(0); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(45 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(45 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(40 == x);
+ CPPUNIT_ASSERT(40 == y);
+ break;
+ }
+ }
+ }
+
+ //Polygon 2 (inner ring)
+ {
+ CPPUNIT_ASSERT(6 == lb.cntr_size(1));
+ auto ptOffset = lb.contour_start_point(1);
+ for (int i = 0; i < lb.cntr_size(1); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(35 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(30 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(10 == x);
+ CPPUNIT_ASSERT(10 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(5 == y);
+ break;
+ case 4:
+ CPPUNIT_ASSERT(45 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 5:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(35 == y);
+ break;
+ }
+ }
+ }
+
+ //Polygon 2 (outer ring)
+ {
+ CPPUNIT_ASSERT(4 == lb.cntr_size(2));
+ auto ptOffset = lb.contour_start_point(2);
+ for (int i = 0; i < lb.cntr_size(2); i++)
+ {
+ auto x = lb.x_coord(ptOffset + i);
+ auto y = lb.y_coord(ptOffset + i);
+ switch (i)
+ {
+ case 0:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ case 1:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(15 == y);
+ break;
+ case 2:
+ CPPUNIT_ASSERT(20 == x);
+ CPPUNIT_ASSERT(25 == y);
+ break;
+ case 3:
+ CPPUNIT_ASSERT(30 == x);
+ CPPUNIT_ASSERT(20 == y);
+ break;
+ }
+ }
+ }
+
+ RS_BufferOutputStream ros(bytes->GetLength());
+ lb.ToAgf(&ros);
+
+ Ptr<MgByte> obs = new MgByte(ros.data(), ros.length());
+ Ptr<MgByteSource> bs = new MgByteSource(obs);
+ Ptr<MgByteReader> oagf = bs->GetReader();
+
+ Ptr<MgGeometry> g2 = agfRw.Read(oagf);
+ STRING owkt = wktRw.Write(g2);
+ CPPUNIT_ASSERT(owkt == mpWkt2);
+ }
+ }
+ catch (MgException* e)
+ {
+ STRING message = e->GetDetails(TEST_LOCALE);
+ SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+ catch (...)
+ {
+ throw;
+ }
}
\ No newline at end of file
Modified: trunk/MgDev/Server/src/UnitTesting/TestMisc.h
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestMisc.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/TestMisc.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -35,6 +35,7 @@
CPPUNIT_TEST(TestCase_TryParseDouble);
CPPUNIT_TEST(TestCase_BadResourceIdentifier);
CPPUNIT_TEST(TestCase_ThreadSafeConfiguration);
+ CPPUNIT_TEST(TestCase_LineBuffer_Conversion);
CPPUNIT_TEST(TestEnd); // This must be the very last unit test
CPPUNIT_TEST_SUITE_END();
@@ -59,6 +60,7 @@
void TestCase_TryParseDouble();
void TestCase_BadResourceIdentifier();
void TestCase_ThreadSafeConfiguration();
+ void TestCase_LineBuffer_Conversion();
private:
Ptr<MgSiteConnection> m_siteConnection;
Modified: trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp 2019-10-06 12:18:03 UTC (rev 9630)
@@ -21,8 +21,7 @@
#include "ServerSiteService.h"
#include "StylizationDefs.h"
#include "../Common/Manager/FdoConnectionManager.h"
-//#include "GDRenderer.h"
-//#include "AGGRenderer.h"
+#include "MVTRenderer.h"
#include "FoundationDefs.h"
#include "SE_Renderer.h"
@@ -1904,6 +1903,72 @@
}
}
+void TestRenderingService::TestCase_RenderTileMVT()
+{
+ try
+ {
+ Ptr<MgMap> map = CreateTestXYZMap();
+
+ //For ease of visual verfication, render the XYZ image tiles as baseline
+ Ptr<MgByteReader> imgTL = m_svcRendering->RenderTileXYZ(map, L"BaseLayers", 16797, 23893, 16, 96, MgImageFormats::Png);
+ Ptr<MgByteReader> imgTR = m_svcRendering->RenderTileXYZ(map, L"BaseLayers", 16798, 23893, 16, 96, MgImageFormats::Png);
+ Ptr<MgByteReader> imgBL = m_svcRendering->RenderTileXYZ(map, L"BaseLayers", 16797, 23894, 16, 96, MgImageFormats::Png);
+ Ptr<MgByteReader> imgBR = m_svcRendering->RenderTileXYZ(map, L"BaseLayers", 16798, 23894, 16, 96, MgImageFormats::Png);
+
+ imgTL->ToFile(L"../UnitTestFiles/RenderTileMVT_TL_ImageBaseline.png");
+ imgTR->ToFile(L"../UnitTestFiles/RenderTileMVT_TR_ImageBaseline.png");
+ imgBL->ToFile(L"../UnitTestFiles/RenderTileMVT_BL_ImageBaseline.png");
+ imgBR->ToFile(L"../UnitTestFiles/RenderTileMVT_BR_ImageBaseline.png");
+
+ //Now render the MVT tiles at the same place
+ Ptr<MgByteReader> mvtTL = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16797, 23893, 16, 96);
+ Ptr<MgByteReader> mvtTR = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16798, 23893, 16, 96);
+ Ptr<MgByteReader> mvtBL = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16797, 23894, 16, 96);
+ Ptr<MgByteReader> mvtBR = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16798, 23894, 16, 96);
+
+ CPPUNIT_ASSERT(MgMimeType::Mvt == mvtTL->GetMimeType());
+ CPPUNIT_ASSERT(MgMimeType::Mvt == mvtTR->GetMimeType());
+ CPPUNIT_ASSERT(MgMimeType::Mvt == mvtBL->GetMimeType());
+ CPPUNIT_ASSERT(MgMimeType::Mvt == mvtBR->GetMimeType());
+
+ CPPUNIT_ASSERT(mvtTL->GetLength() > 0);
+ CPPUNIT_ASSERT(mvtTR->GetLength() > 0);
+ CPPUNIT_ASSERT(mvtBL->GetLength() > 0);
+ CPPUNIT_ASSERT(mvtBR->GetLength() > 0);
+
+ mvtTL->ToFile(L"../UnitTestFiles/RenderTileMVT_TL.mvt");
+ mvtTR->ToFile(L"../UnitTestFiles/RenderTileMVT_TR.mvt");
+ mvtBL->ToFile(L"../UnitTestFiles/RenderTileMVT_BL.mvt");
+ mvtBR->ToFile(L"../UnitTestFiles/RenderTileMVT_UR.mvt");
+
+ mvtTL->Rewind();
+ mvtTR->Rewind();
+ mvtBL->Rewind();
+ mvtBR->Rewind();
+
+ Ptr<MgByteSink> sinkTL = new MgByteSink(mvtTL);
+ Ptr<MgByteSink> sinkTR = new MgByteSink(mvtTR);
+ Ptr<MgByteSink> sinkBL = new MgByteSink(mvtBL);
+ Ptr<MgByteSink> sinkBR = new MgByteSink(mvtBR);
+
+ Ptr<MgByte> bytesTL = sinkTL->ToBuffer();
+ Ptr<MgByte> bytesTR = sinkTR->ToBuffer();
+ Ptr<MgByte> bytesBL = sinkBL->ToBuffer();
+ Ptr<MgByte> bytesBR = sinkBR->ToBuffer();
+
+ CPPUNIT_ASSERT(MVTRenderer::IsValidTile(bytesTL->Bytes(), bytesTL->GetLength()));
+ CPPUNIT_ASSERT(MVTRenderer::IsValidTile(bytesTR->Bytes(), bytesTR->GetLength()));
+ CPPUNIT_ASSERT(MVTRenderer::IsValidTile(bytesBL->Bytes(), bytesBL->GetLength()));
+ CPPUNIT_ASSERT(MVTRenderer::IsValidTile(bytesBR->Bytes(), bytesBR->GetLength()));
+ }
+ 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: trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h 2019-10-06 12:18:03 UTC (rev 9630)
@@ -74,6 +74,7 @@
CPPUNIT_TEST(TestCase_RenderTilePNG);
CPPUNIT_TEST(TestCase_RenderTileXYZ_PNG);
CPPUNIT_TEST(TestCase_RenderTileUTFGrid);
+ CPPUNIT_TEST(TestCase_RenderTileMVT);
CPPUNIT_TEST(TestCase_StylizationFunctionsPNG8);
@@ -178,6 +179,9 @@
void TestEnd();
void TestCase_QueryFeatures();
+ void TestCase_RenderTileUTFGrid();
+ void TestCase_RenderTileMVT();
+
void TestCase_RenderMetatile(CREFSTRING imageFormat, CREFSTRING extension);
void TestCase_RenderXYZMetatile(CREFSTRING imageFormat, CREFSTRING extension, INT32 retinaScale);
void TestCase_RenderTile(CREFSTRING imageFormat, CREFSTRING extension);
@@ -238,7 +242,6 @@
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"); }
Modified: trunk/MgDev/Server/src/UnitTesting/UnitTesting.vcxproj
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/UnitTesting.vcxproj 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/Server/src/UnitTesting/UnitTesting.vcxproj 2019-10-06 12:18:03 UTC (rev 9630)
@@ -94,7 +94,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Renderers;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Async</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -120,7 +120,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Renderers;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Async</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -146,7 +146,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
- <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Renderers;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Async</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -173,7 +173,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
- <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\Common;..\Common\Cache;..\Common\Manager;..\Services\Feature;..\Services\Kml;..\Services\Mapping;..\Services\Rendering;..\Services\Resource;..\Services\ServerAdmin;..\Services\Site;..\Services\Tile;..\..\..\Common\Foundation;..\..\..\Common\Geometry;..\..\..\Common\PlatformBase;..\..\..\Common\MapGuideCommon;..\..\..\Common\MdfModel;..\..\..\Common\MdfParser;..\..\..\Common\Renderers;..\..\..\Common\Stylization;..\..\..\Oem\ACE\ACE_wrappers;..\..\..\Oem\CppUnit-1.9.14\include;..\..\..\Oem\dbxml\xerces-c-src\src;..\..\..\Oem\FDO\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Async</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -274,6 +274,9 @@
<Project>{f7334b1b-0efa-47e3-8e66-df158e61b7e4}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
+ <ProjectReference Include="..\..\..\Common\Renderers\Renderers.vcxproj">
+ <Project>{38161685-88ed-415e-a545-ccc17be069ae}</Project>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Common\Security\Security.vcxproj">
<Project>{7c1c5695-c51c-4017-abef-bc3032cbaf3b}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
Copied: trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml (from rev 9629, sandbox/jng/mvt_alt/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml)
===================================================================
--- trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml (rev 0)
+++ trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TileSetDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="TileSetDefinition-3.0.0.xsd">
+ <TileStoreParameters>
+ <TileProvider>XYZ</TileProvider>
+ <Parameter>
+ <Name>TilePath</Name>
+ <Value>%MG_TILE_CACHE_PATH%</Value>
+ </Parameter>
+ <Parameter>
+ <Name>TileFormat</Name>
+ <Value>MVT</Value>
+ </Parameter>
+ <Parameter>
+ <Name>RenderOnly</Name>
+ <Value>false</Value>
+ </Parameter>
+ </TileStoreParameters>
+ <Extents>
+ <MinX>-87.797866013831964</MinX>
+ <MaxX>-87.664527771869246</MaxX>
+ <MinY>43.6868578621819</MinY>
+ <MaxY>43.8037962206133</MaxY>
+ </Extents>
+ <BaseMapLayerGroup>
+ <Name>Base Layer Group</Name>
+ <Visible>true</Visible>
+ <ShowInLegend>true</ShowInLegend>
+ <ExpandInLegend>true</ExpandInLegend>
+ <LegendLabel>Tiled Layers</LegendLabel>
+ <BaseMapLayer>
+ <Name>Roads</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Roads.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Roads</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>Districts</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Districts.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Districts</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>Buildings</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Buildings.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Buildings</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>Parcels</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Parcels.LayerDefinition</ResourceId>
+ <Selectable>true</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Parcels</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>Islands</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Islands.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Islands</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>Hydrography</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/Hydrography.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>Hydrography</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ <BaseMapLayer>
+ <Name>CityLimits</Name>
+ <ResourceId>Library://Samples/Sheboygan/Layers/CityLimits.LayerDefinition</ResourceId>
+ <Selectable>false</Selectable>
+ <ShowInLegend>true</ShowInLegend>
+ <LegendLabel>CityLimits</LegendLabel>
+ <ExpandInLegend>true</ExpandInLegend>
+ </BaseMapLayer>
+ </BaseMapLayerGroup>
+</TileSetDefinition>
\ No newline at end of file
Copied: trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml (from rev 9629, sandbox/jng/mvt_alt/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml)
===================================================================
--- trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml (rev 0)
+++ trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml 2019-10-06 12:18:03 UTC (rev 9630)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ResourceDocumentHeader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="ResourceDocumentHeader-1.0.0.xsd">
+ <Security>
+ <Inherited>true</Inherited>
+ </Security>
+</ResourceDocumentHeader>
\ No newline at end of file
Modified: trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml
===================================================================
--- trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml 2019-10-06 12:18:03 UTC (rev 9630)
@@ -12,7 +12,7 @@
</Parameter>
<Parameter>
<Name>RenderOnly</Name>
- <Value>true</Value>
+ <Value>false</Value>
</Parameter>
</TileStoreParameters>
<Extents>
Modified: trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/MgResourcePackageManifest.xml
===================================================================
--- trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/MgResourcePackageManifest.xml 2019-09-26 08:34:25 UTC (rev 9629)
+++ trunk/MgDev/UnitTest/TestData/Samples/Sheboygan/MgResourcePackageManifest.xml 2019-10-06 12:18:03 UTC (rev 9630)
@@ -2365,7 +2365,7 @@
<Parameters>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
@@ -2375,17 +2375,17 @@
<Parameters>
<Parameter>
<Name>CONTENT</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition_CONTENT.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>HEADER</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_HEADER.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition_HEADER.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
@@ -2395,7 +2395,7 @@
<Parameters>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
@@ -2405,17 +2405,17 @@
<Parameters>
<Parameter>
<Name>CONTENT</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition_CONTENT.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition_CONTENT.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>HEADER</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition_HEADER.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition_HEADER.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZ.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
@@ -2425,7 +2425,7 @@
<Parameters>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
@@ -2435,19 +2435,49 @@
<Parameters>
<Parameter>
<Name>CONTENT</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition_CONTENT.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_CONTENT.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>HEADER</Name>
- <Value>Library/Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition_HEADER.xml</Value>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition_HEADER.xml</Value>
<ContentType>text/xml</ContentType>
</Parameter>
<Parameter>
<Name>RESOURCEID</Name>
- <Value>Library://Samples/Sheboygan/TileSets/SheboyganXYZRetina.TileSetDefinition</Value>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganUTFGrid.TileSetDefinition</Value>
</Parameter>
</Parameters>
</Operation>
+ <Operation>
+ <Name>DELETERESOURCE</Name>
+ <Version>1.0.0</Version>
+ <Parameters>
+ <Parameter>
+ <Name>RESOURCEID</Name>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition</Value>
+ </Parameter>
+ </Parameters>
+ </Operation>
+ <Operation>
+ <Name>SETRESOURCE</Name>
+ <Version>1.0.0</Version>
+ <Parameters>
+ <Parameter>
+ <Name>CONTENT</Name>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_CONTENT.xml</Value>
+ <ContentType>text/xml</ContentType>
+ </Parameter>
+ <Parameter>
+ <Name>HEADER</Name>
+ <Value>Library/Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition_HEADER.xml</Value>
+ <ContentType>text/xml</ContentType>
+ </Parameter>
+ <Parameter>
+ <Name>RESOURCEID</Name>
+ <Value>Library://Samples/Sheboygan/TileSets/SheboyganMVT.TileSetDefinition</Value>
+ </Parameter>
+ </Parameters>
+ </Operation>
</Operations>
</ResourcePackageManifest>
\ No newline at end of file
More information about the mapguide-commits
mailing list