[mapguide-commits] r9611 - in sandbox/jng/mvt_alt: . Common/CoordinateSystem Common/Geometry Common/Geometry/Spatial Common/Renderers Common/Stylization Server/src/Services/Mapping

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sat Sep 21 13:28:06 PDT 2019


Author: jng
Date: 2019-09-21 13:28:06 -0700 (Sat, 21 Sep 2019)
New Revision: 9611

Added:
   sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilities.h
Removed:
   sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.h
Modified:
   sandbox/jng/mvt_alt/
   sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysGrids.cpp
   sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysMgrsZone.cpp
   sandbox/jng/mvt_alt/Common/Geometry/ArcSegment.cpp
   sandbox/jng/mvt_alt/Common/Geometry/GeosUtil.cpp
   sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.cpp
   sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp
   sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp
   sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.h
   sandbox/jng/mvt_alt/Common/Stylization/DefaultStylizer.cpp
   sandbox/jng/mvt_alt/Common/Stylization/RS_FeatureReader.h
   sandbox/jng/mvt_alt/Common/Stylization/Renderer.h
   sandbox/jng/mvt_alt/Common/Stylization/RendererStyles.h
   sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.cpp
   sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.h
   sandbox/jng/mvt_alt/Common/Stylization/StylizationEngine.cpp
   sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.cpp
   sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.h
   sandbox/jng/mvt_alt/Server/src/Services/Mapping/ServerMappingService.vcxproj
Log:
Merged revision(s) 9546-9547 from sandbox/jng/mvt:
Rename SpatialUtility.h to SpatialUtilities.h to avoid collision with FDO's spatial utility header of the same name (and same relative path!)

Fix all affected usages.
........
As I had suspected and feared, ring orientation is important when rendering mapbox vector tiles, so we have to entertain the real possibility that incorrectly oriented polygons could be fed to our MVTRenderer.

Fortunately, FDO has some code in FdoSpatialUtility to help us correct polygons to the right orientation, but this requires some interface changes in the rendering/stylization engine first:

 - Add a new RS_DesiredPolygonOrientation enum that a renderer implementation returns to specify the desired orientation of polygons passed to it. By default it returns RS_DesiredPolygonOrientation::NotApplicable, but for the MVTRenderer, it returns RS_DesiredPolygonOrientation::Clockwise
 - Modify RS_FeatureReader::GetGeometry to also take in this new enum
 - Ensure the DefaultStylizer and StylizationEngine read the enum value from the renderer and pass it down to the GetGeometry() calls
 - In the RSMgFeatureReader implementation, use this passed enum to determine if geometries are polygon and require re-orientation. If so, load the AGF of the re-oriented polygon into the LineBuffer to be returned.

There will be perf overhead having to re-orient polygons when rendering, but it is overhead that only the MVT renderer has to wear.
........


Index: sandbox/jng/mvt_alt
===================================================================
--- sandbox/jng/mvt_alt	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt	2019-09-21 20:28:06 UTC (rev 9611)

Property changes on: sandbox/jng/mvt_alt
___________________________________________________________________
Modified: svn:mergeinfo
## -19,7 +19,7 ##
 /sandbox/jng/fusion_entrypoint_refactor:9400-9406
 /sandbox/jng/geoprocessing:9205-9229
 /sandbox/jng/geos34x:8256-8259
-/sandbox/jng/mvt:9527-9528,9535,9537
+/sandbox/jng/mvt:9527-9528,9535,9537,9546-9547
 /sandbox/jng/ogc:9240-9255
 /sandbox/jng/php56x:8975-8985
 /sandbox/jng/querymapfeatures_selectionkey:9590-9591
Modified: sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysGrids.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysGrids.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysGrids.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Geometry/ArcSegment.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/ArcSegment.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Geometry/ArcSegment.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -16,7 +16,7 @@
 //
 
 #include "GeometryCommon.h"
-#include "Spatial/SpatialUtility.h"
+#include "Spatial/SpatialUtilities.h"
 
 //////////////////////////////////////////////////////////////////
 // Construct a MgArcSegment object

Modified: sandbox/jng/mvt_alt/Common/Geometry/GeosUtil.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/GeosUtil.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Geometry/GeosUtil.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilities.h (from rev 9547, sandbox/jng/mvt/Common/Geometry/Spatial/SpatialUtilities.h)
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilities.h	                        (rev 0)
+++ sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilities.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtility.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Geometry/Spatial/SpatialUtilityCircularArc.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -16,7 +16,7 @@
 //
 
 #include "GeometryCommon.h"
-#include "SpatialUtility.h"
+#include "SpatialUtilities.h"
 #include "SpatialUtilityCircularArc.h"
 #include "MathUtility.h"
 

Modified: sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -833,4 +833,9 @@
 void MVTRenderer::ReleaseMVTContent(unsigned char* buf)
 {
     m_impl->ReleaseMVTContent(buf);
+}
+
+RS_DesiredPolygonOrientation MVTRenderer::GetDesiredPolygonOrientation()
+{
+    return RS_DesiredPolygonOrientation::Clockwise;
 }
\ No newline at end of file

Modified: sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -70,6 +70,7 @@
     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

Modified: sandbox/jng/mvt_alt/Common/Stylization/DefaultStylizer.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/DefaultStylizer.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/DefaultStylizer.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Stylization/RS_FeatureReader.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/RS_FeatureReader.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/RS_FeatureReader.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Stylization/Renderer.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/Renderer.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/Renderer.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Stylization/RendererStyles.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/RendererStyles.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/RendererStyles.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -23,7 +23,14 @@
 
 typedef std::wstring RS_String;
 
+enum RS_DesiredPolygonOrientation
+{
+    Clockwise,
+    CounterClockwise,
+    NotApplicable
+};
 
+
 //////////////////////////////////////////////////////////////////////////////
 enum RS_HAlignment
 {

Modified: sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -722,3 +722,8 @@
 {
     return true;
 }
+
+RS_DesiredPolygonOrientation SE_Renderer::GetDesiredPolygonOrientation()
+{
+    return RS_DesiredPolygonOrientation::NotApplicable;
+}
\ No newline at end of file


Property changes on: sandbox/jng/mvt_alt/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/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
Modified: sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.h
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/SE_Renderer.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Common/Stylization/StylizationEngine.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Stylization/StylizationEngine.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Common/Stylization/StylizationEngine.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.cpp
===================================================================
--- sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.cpp	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.cpp	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.h
===================================================================
--- sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.h	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Server/src/Services/Mapping/RSMgFeatureReader.h	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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: sandbox/jng/mvt_alt/Server/src/Services/Mapping/ServerMappingService.vcxproj
===================================================================
--- sandbox/jng/mvt_alt/Server/src/Services/Mapping/ServerMappingService.vcxproj	2019-09-21 20:18:15 UTC (rev 9610)
+++ sandbox/jng/mvt_alt/Server/src/Services/Mapping/ServerMappingService.vcxproj	2019-09-21 20:28:06 UTC (rev 9611)
@@ -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>



More information about the mapguide-commits mailing list