Version 3 (modified by 7 years ago) ( diff ) | ,
---|
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 | 14 Jun 2017 |
Author | Jackie Ng |
RFC Status | draft |
Implementation Status | |
Proposed Milestone | 3.3 |
Assigned PSC guide(s) | (when determined) |
Voting History | (vote date) |
+1 | |
+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 |
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
|
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
|
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.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 | 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.
MgGeometry enhancements
In addition to mapagent enhancements, this RFC enhances the MgGeometry
class with support for "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.
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.
Benchmark repeated evaluation of spatial operations using MgGeometry
vs MgPreparedGeometry
. Verify that using MgPreparedGeometry
provides noticeable performance over using MgGeometry
Funding / Resources
Community