MapGuide RFC 161 - Geo-Processing Services
This page contains a change request (RFC) for the MapGuide Open Source project. More MapGuide RFCs can be found on the RFCs page.
Status
RFC Template Version | (1.0) |
Submission Date | 14 Jun 2017 |
Last Modified | 12 July 2017 |
Author | Jackie Ng |
RFC Status | Implemented |
Implementation Status | completed |
Proposed Milestone | 4.0 |
Assigned PSC guide(s) | (when determined) |
Voting History | (vote date) |
+1 | Jackie,Gordon,Crispin |
+0 | |
-0 | |
-1 | |
no vote |
Overview
This RFC proposes to add geo-processing capabilities to the mapagent and enhance MgGeometry with additional capabilities offered by the underlying GEOS library we're wrapping.
Motivation
The mapagent in its current form offers no services for geo-processing. Such capabilities require custom code using MgGeometry from the MapGuide Web API.
For basic geo-processing such as geometry manipulation (union/buffer/etc) or testing of common spatial predicates (contains/intersects/etc), we should be able to tap into such functionality in the mapagent.
Proposed Solution
This RFC enhances the mapagent with support for the following operations:
Buffer
Performs a buffer of the given input geometry in with the specified distance.
This is the mapagent equivalent of MgGeometry::Buffer()
Name | Value | Required | Description |
OPERATION | GEO.BUFFER | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the geometry to buffer |
DISTANCE | number | Yes | The buffer distance in the specific units |
UNITS | mi/km/ft/m | Yes | miles/kilometers/feet/meters |
FORMAT | WKT/GEOJSON | Yes | Output the buffer result as WKT or GeoJSON |
COORDINATESYSTEM | string | Yes | The coordinate system (CS-Map code) of the input geometry |
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the buffer geometry into. If not specified, the buffer geometry will be in the input coordinate system |
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
Simplify
Returns a simplified form of the given input geometry.
This is the mapagent equivalent of MgGeometrySimplifier::Simplify()
Name | Value | Required | Description |
OPERATION | GEO.SIMPLIFY | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the geometry to simplify |
TOLERANCE | number | Yes | The simplification tolerance |
ALGORITHM | 0/1 | Yes | 0=Douglas-Peucker, 1=Topology Preserving |
FORMAT | WKT/GEOJSON | Yes | Output the simplification result as WKT or GeoJSON |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) of the input geometry. Only required in combination with TRANSFORMTO if you intend to transform the simplified geometry
|
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the simplified geometry into. Only required in combination with COORDINATESYSTEM if you intend to transform the simplified geometry
|
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
Binary Operation
Performs the given binary operation against the 2 input geometries specified (in WKT) as WKT or GeoJSON with optional transformation.
The following binary operations are supported:
- Union
- Difference
- Intersection
- SymmetricDifference
Name | Value | Required | Description |
OPERATION | GEO.BINARYOPERATION | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRYA | string | Yes | The Well-Known Text of the first input geometry |
GEOMETRYB | string | Yes | The Well-Known Text of the second input geometry |
OPERATOR | UNION/DIFFERENCE/INTERSECTION/SYMMETRICDIFFERENCE | Yes | The desired operator for this operation |
FORMAT | WKT/GEOJSON | Yes | Output the operation result as WKT or GeoJSON |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) of the input geometries. Only required in combination with TRANSFORMTO if you intend to transform the geometry result
|
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the simplified geometry into. Only required in combination with COORDINATESYSTEM if you intend to transform the geometry result
|
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
All operators are invoked in the form of GEOMETRYA OPERATOR GEOMETRYB
. Where ordering of input geometries matters (the operator is not commutative), refer to this rule.
Spatial Predicate
Tests and returns whether the 2 input geometries specified (in WKT) passes the given spatial predicate.
The following spatial predicates are supported:
- Contains
- Crosses
- Disjoint
- Equals
- Intersects
- Overlaps
- Touches
- Within
Name | Value | Required | Description | |
OPERATION | GEO.SPATIALPREDICATE | Yes | Operation to execute | |
VERSION | 3.3.0 | Yes | Operation version | |
CLIENTAGENT | text | Optional | Descriptive text for client | |
GEOMETRYA | string | Yes | The Well-Known Text of the first input geometry | |
GEOMETRYB | string | Yes | The Well-Known Text of the second input geometry | |
OPERATOR | CONTAINS/CROSSES/DISJOINT/EQUALS/INTERSECTS/OVERLAPS/TOUCHES/WITHIN | Yes | The desired operator for this spatial predicate test | result |
All operators are invoked in the form of GEOMETRYA OPERATOR GEOMETRYB
. Where ordering of input geometries matters (the operator is not commutative), refer to this rule.
Convex Hull
Returns the smallest convex Polygon that contains all the points in the given Geometry
Name | Value | Required | Description |
OPERATION | GEO.CONVEXHULL | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the input geometry |
FORMAT | WKT/GEOJSON | Yes | Output the operation result as WKT or GeoJSON |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) of the input geometries. Only required in combination with TRANSFORMTO if you intend to transform the geometry result
|
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the simplified geometry into. Only required in combination with COORDINATESYSTEM if you intend to transform the geometry result
|
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
Boundary
Returns the geometry that represents the input geometry's boundary
Name | Value | Required | Description |
OPERATION | GEO.BOUNDARY | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the input geometry |
FORMAT | WKT/GEOJSON | Yes | Output the operation result as WKT or GeoJSON |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) of the input geometries. Only required in combination with TRANSFORMTO if you intend to transform the geometry result
|
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the simplified geometry into. Only required in combination with COORDINATESYSTEM if you intend to transform the geometry result
|
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
Tessellate
Returns the geometry that is a tessellated form of the input geometry. This operation is provided for approximating curve-based geometries to non-curve equivalents and has no effect if the input geometry is not curve-based (the operation will return the input geometry)
Name | Value | Required | Description |
OPERATION | GEO.TESSELLATE | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the input geometry |
FORMAT | WKT/GEOJSON | Yes | Output the operation result as WKT or GeoJSON |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) of the input geometries. Only required in combination with TRANSFORMTO if you intend to transform the geometry result
|
TRANSFORMTO | string | Optional | The coordinate system (CS-Map code) to transform the simplified geometry into. Only required in combination with COORDINATESYSTEM if you intend to transform the geometry result
|
PRECISION | number | Optional | The decimal precision to use when outputting as GeoJSON. If not specified, coordinates will be output as-is if output format is GeoJSON |
Distance
Returns the shortest distance between this geometry and another
Name | Value | Required | Description |
OPERATION | GEO.DISTANCE | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the input geometry |
OTHERGEOMETRY | string | Yes | The Well-Known Text of the other geometry (to compute distance to) |
COORDINATESYSTEM | string | Optional | The coordinate system (CS-Map code) to use for measuring distance. If provided, the distance result with be returned in meters. If not provided, a linear distance measurement is used and the result will be returned in unknown units. |
FORMAT | string | Yes | text/xml for XML, application/json for JSON
|
CLEAN | 1/0 | Optional | If requested format is application/json , returns a clean JSON structure per MapGuideRfc158
|
The result adheres to the new UnitOfMeasure-3.3.0.xsd
XML schema
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="UnitOfMeasure"> <xs:annotation> <xs:documentation>Unit of measure</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="Value" type="xs:double" /> <xs:element name="Unit" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Geometry Info
Returns information about the input geometry
Name | Value | Required | Description |
OPERATION | GEO.GEOMETRYINFO | Yes | Operation to execute |
VERSION | 3.3.0 | Yes | Operation version |
CLIENTAGENT | text | Optional | Descriptive text for client |
GEOMETRY | string | Yes | The Well-Known Text of the input geometry |
FORMAT | string | Yes | text/xml for XML, application/json for JSON
|
CLEAN | 1/0 | Optional | If requested format is application/json , returns a clean JSON structure per MapGuideRfc158
|
The result adheres to the new GeometryInfo-3.3.0.xsd
XML schema
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="GeometryInfo"> <xs:annotation> <xs:documentation>Geometry Information</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="Area" type="xs:double" /> <xs:element name="Dimension" type="xs:int" /> <xs:element name="Length" type="xs:double" /> <xs:element name="IsClosed" type="xs:boolean" /> <xs:element name="IsEmpty" type="xs:boolean" /> <xs:element name="IsSimple" type="xs:boolean" /> <xs:element name="IsValid" type="xs:boolean" /> <xs:element name="Envelope" type="Envelope" /> <xs:element name="Centroid" type="Coordinate" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="Coordinate"> <xs:annotation> <xs:documentation>Represents a bounding box</xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="X" type="xs:double"> <xs:annotation> <xs:documentation>x-coordinate</xs:documentation> </xs:annotation> </xs:element> <xs:element name="Y" type="xs:double"> <xs:annotation> <xs:documentation>y-coordinate</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="Envelope"> <xs:annotation> <xs:documentation>Represents a bounding box defined in terms of a lower left coordinate and an upper right coordinate</xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="LowerLeft" type="Coordinate"> <xs:annotation> <xs:documentation>Lower-left coordinate</xs:documentation> </xs:annotation> </xs:element> <xs:element name="UpperRight" type="Coordinate"> <xs:annotation> <xs:documentation>Upper-right coordinate</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> </xs:schema>
GeoJSON improvements
As GeoJSON is a key output format for a majority of these new operations, this RFC includes some improvements to the GeoJSON support introduced in MapGuideRfc158
Configurable coordinate precision
As implied by some of the new mapagent operations, the GeoJSON output support introduced in MapGuideRfc158 has been enhanced with support for configurable coordinate precision.
Before this RFC, GeoJSON coordinates were output verbatim from their source geometry counterparts. Generally speaking, coordinates beyond 7 decimal places in most coordinate systems are superfluous and adds unnecessary bloat to GeoJSON content when converting feature geometry.
As a result, the MgGeoJsonWriter
class has been extended to allow a custom decimal precision to be specified. Coordinate precision is opt-in so it requires manual activation.
class MG_PLATFORMBASE_API MgGeoJsonWriter : public MgGuardDisposable { PUBLISHED_API: ... ////////////////////////////////////////////////////////////////// /// \brief /// Sets the decimal precision to use when writing out coordinates. If you do not call this method, the default precision used is 7 decimal places. /// Precision must be enabled in order for this setting to have any effect /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// void SetPrecision(int precision); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// void SetPrecision(int precision); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// void SetPrecision(int precision); /// \htmlinclude SyntaxBottom.html /// /// \param precision (int) /// The decimal precision to write out coordinates /// /// void SetPrecision(INT32 precision); ////////////////////////////////////////////////////////////////// /// \brief /// Gets the decimal precision to use when writing out coordinates /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// int GetPrecision(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// int GetPrecision(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// int GetPrecision(); /// \htmlinclude SyntaxBottom.html /// /// \return /// Returns the current precision /// INT32 GetPrecision(); ////////////////////////////////////////////////////////////////// /// \brief /// Sets whether to apply coordinate precision when writing out GeoJSON coordinates /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// void SetPrecisionEnabled(bool enabled); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// void SetPrecisionEnabled(boolean enabled); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// void SetPrecisionEnabled(bool enabled); /// \htmlinclude SyntaxBottom.html /// /// \param enabled (bool) /// If true, enables coordinate precision. Otherwise disables it /// /// \return /// Returns the GeoJSON output as a string. /// void SetPrecisionEnabled(bool enabled); ////////////////////////////////////////////////////////////////// /// \brief /// Gets whether coordinate precision is enabled /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// bool IsPrecisionEnabled(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// boolean IsPrecisionEnabled(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// bool IsPrecisionEnabled(); /// \htmlinclude SyntaxBottom.html /// /// \return /// True if coordinate precision is enabled. False otherwise /// bool IsPrecisionEnabled(); };
By default, MgGeoJsonWriter
will output coordinates as-is.
If not specified, 7 decimal places will be default when converting feature data to GeoJSON using MgGeoJsonWriter
if coordinate precision is enabled, but no call to SetPrecision
is made.
Auto-tessellation of curves
The GeoJSON spec does not define curve geometries, as a result if one was converting a feature with curve-based geometry to GeoJSON, the geometry
component is currently always going to be null
For this RFC, curve geometries are automatically tessellated to their non-curve equivalents.
MgGeometry enhancements
In addition to mapagent enhancements, this RFC enhances the MgGeometry
API with extra capabilities.
Tessellation
The GeoJSON support has demonstrated the need to provide some means for any curve-based MgGeometry
to return a tessellated version of itself so it can be used in cases where curve-based geometries are not supported (such as converting to GeoJSON).
To support such cases, we'll introduce a new API to MgGeometry
to support tessellation
class MG_GEOMETRY_API MgGeometry : public MgGeometricEntity { PUBLISHED_API: ... /////////////////////////////////////////////////////////////////////// /// \brief /// Returns a tessellated version of this geometry. A tessellated version of this /// geometry will have all arc/curve geometry components approximated with line /// strings. Thus, this method is only applicable for curve geometries and has /// no effect on non-curve geometries. /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// /// \since 3.3 /// /// \return /// A tesellated version of this geometry. If this geometry is not curve-based, the operation does nothing and this method returns itself. /// MgGeometry* Tessellate(); };
Implementation-wise, this method merely delegates to the existing MgSpatialUtility::TessellateCurve(MgGeometry*)
method already in the MgGeometry project.
Prepared geometries
Prepared geometries is a performance optimization that improves the performance of operations between a single target geometry and a batch of test geometries. By preparing the target geometry, various internal data structures of the prepared geometry can be pre-computed, which then allows subsequent geometric operations to be evaluated with maximum efficiency.
The RFC introduces a new MgPreparedGeometry
class to the MapGuide API
//////////////////////////////////////////////////////////////// /// \brief /// MgPreparedGeometry is an prepared form of MgGeometry optimized for the case of /// repeated evaluation of spatial predicates against it and any other geometry /// class MG_GEOMETRY_API MgPreparedGeometry : public MgGuardDisposable { PUBLISHED_API: //////////////////////////////////////////////////////////////////////////////////////////////////////// /// \brief /// This is a convenience method. Given 2 geometries a and b, /// a.Contains(b) is true if and only if b.MgGeometry::Within(a) /// is true. /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Contains(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Contains(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Contains(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this one. /// /// \return /// True if the other geometry is within this geometry, false /// otherwise. /// virtual bool Contains(MgGeometry* other); ////////////////////////////////////////////////////////////////////// /// \brief /// Given 2 geometries a and b, a.Crosses(b) is true if and only /// if the dimension of the intersection of the interior of a and /// the interior of b is less than the greater of the dimension /// of the interior of a and the dimension of the interior of b /// and the intersection of a and b is neither a nor b. /// /// \remarks /// A Point cannot cross another geometry because the /// intersection of the Point with the other geometry is the /// Point. /// \n /// Two MultiPoint geometries cannot cross one another because /// the dimension of the intersection of their interiors, namely /// the 0-dimension, is not less than the greater of the /// dimensions of their interiors, namely the 0-dimension. /// \n /// [\link OGC99049 OGC99-049 \endlink] implicitly excludes a Crosses /// relationship between 2 polygons. According to the definition, /// the possibility of such a relationship would require that the /// intersection of the interior of one polygon with that of /// another be a Point or Line. /// <h2>Illustration</h2> /// d, e and f are MultiPoint geometries. /// \n /// \image html crosses.png /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Crosses(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Crosses(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Crosses(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this /// one. /// /// \return /// True if this geometry spatially crosses the other geometry, /// false otherwise. /// virtual bool Crosses(MgGeometry* other); ///////////////////////////////////////////////////////////////////////// /// \brief /// Given 2 geometries a and b, a.Disjoint(b)is true if and only /// if the intersection of a and b is empty. /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Disjoint(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Disjoint(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Disjoint(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this one. /// /// \return /// True if this geometry is spatially disjoint from the other /// geometry, false otherwise. /// virtual bool Disjoint(MgGeometry* other); ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// \brief /// This is a convenience method. Given 2 geometries a and b, /// a.Intersects(b) is true if and only if a.\link MgGeometry::Disjoint Disjoint \endlink(b) /// is false. /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Intersects(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Intersects(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Intersects(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this one. /// /// \return /// True if this geometry is not disjoint with respect to the /// other geometry, false otherwise. /// virtual bool Intersects(MgGeometry* other); ///////////////////////////////////////////////////////////////////////// /// \brief /// Given 2 geometries a and b, a.Overlaps(b) is true if and only /// if the dimension of the interior of a equals the dimension of /// the interior of b equals the dimension of the intersection of /// the interior of a and the interior of b and the intersection /// of a and b is neither a nor b. /// /// \remarks /// A Point cannot overlap a Point, and a MultiPoint cannot /// overlap a Point but a MultiPoint can overlap a MultiPoint. /// <h2>Illustration</h2> /// c and d are MultiPoint geometries. /// \image html overlaps.png /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Overlaps(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Overlaps(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Overlaps(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this one. /// /// \return /// True if this geometry spatially overlaps the other geometry, /// false otherwise. /// virtual bool Overlaps(MgGeometry* other); ////////////////////////////////////////////////////////////////////// /// \brief /// Given 2 geometries a and b, a.Touches(b) is true if and only /// if the intersection of the interior of a and the interior of /// b is empty and the intersection of a and b is not empty. /// /// \remarks /// A Point cannot touch a Point because a Point has no boundary /// and so the intersection of the interiors of the two /// geometries is not empty. /// \n /// A Point can touch a non-closed Line at one of the end points /// of the Line. /// \n /// A Point cannot touch a closed Line because all of the points /// in the Line are interior to it. /// <h2>Illustration</h2> /// e are MultiPoint geometries and f is a LineString. /// \image html touches.png /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Touches(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Touches(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Touches(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this /// one. /// /// \return /// True if this geometry spatially touches the other geometry, /// false otherwise. /// virtual bool Touches(MgGeometry* other); ////////////////////////////////////////////////////////////////////// /// \brief /// Given 2 geometries a and b, a.Within(b) is true if and only /// if the intersection of a and b is a and the intersection of /// the interior of a and the interior of b is not empty. /// /// \remarks /// If the entire point-set of a geometry intersects the boundary /// of another geometry, the former is not within the latter. /// <h2>Illustration</h2> /// The end point of d and the end point of e intersect. a, b, i, /// j, k, and m are MultiPoints. The concentric circles represent /// intersecting points. The polygon n1n2n3n4 is within the /// polygon p1p2p3p4 and vice versa. The LineString q1q2 is /// within the LineString r1r2 and vice versa. The MultiPoint j /// is within the MultiPoint k and vice versa. The Point f is /// within the point g and vice versa. /// \n /// \image html within.png /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual bool Within(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual boolean Within(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual bool Within(MgGeometry other); /// \htmlinclude SyntaxBottom.html /// /// \param other (MgGeometry) /// The MgGeometry to test against this /// one. /// /// \return /// True if this geometry is spatially within the other geometry, /// false otherwise. /// virtual bool Within(MgGeometry* other); };
MgPreparedGeometry
instances are obtained by calling a new Prepare
method on a MgGeometry
instance
class MG_GEOMETRY_API MgGeometry : public MgGeometricEntity { PUBLISHED_API: ... /////////////////////////////////////////////////////////////////////// /// \brief /// Returns a prepared version of this geometry that is optimized for /// repeated evaluation of spatial predicate operations /// /// <!-- Syntax in .Net, Java, and PHP --> /// \htmlinclude DotNetSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude JavaSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// \htmlinclude PHPSyntaxTop.html /// virtual MgGeometry Prepare(); /// \htmlinclude SyntaxBottom.html /// /// \return /// An MgPreparedGeometry representing the prepared version of this geometry /// MgPreparedGeometry* Prepare(); };
It is important to note that the use-case of MgPreparedGeometry
is primarily for fast/repeated evaluation of spatial predicates. As such, MgPreparedGeometry
does not follow the geometry class hierarchy like its MgGeometry
counterpart. If one wants to know the actual geometric information about the MgPreparedGeometry
, they should retain a reference to the original MgGeometry
that they Prepare()
'd from.
Also, this is not a substitute for equivalent spatial filtering criteria on a Feature Source if its provider capabilities allow for it. Data-store level evaluation of these spatial predicates will generally always be faster than doing it at the application level through this new API.
Implementation-wise, MgPreparedGeometry
wraps the underlying PreparedGeometry
class provided by GEOS. We use the pimpl pattern to avoid leaking out the PreparedGeometry
dependency (and consequently any geos headers) in the public header of MgPreparedGeometry
.
Implications
These are new API additions.
Test Plan
Test new mapagent geo-processing operations and verify that their output is the same as the results provided by using MgGeometry
APIs directly.
Add tests for double to string conversion with specific decimal precision.
Benchmark repeated evaluation of spatial operations using MgGeometry
vs MgPreparedGeometry
. Verify that using MgPreparedGeometry
provides noticeable performance over using MgGeometry
Funding / Resources
Community
Addendum
Made coordinate precision behavior opt-in