1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2009 2011 Sandro Santilli <strk@kbt.io>
7  * Copyright (C) 2005 2006 Refractions Research Inc.
8  * Copyright (C) 2001-2002 Vivid Solutions Inc.
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU Lesser General Public Licence as published
12  * by the Free Software Foundation.
13  * See the COPYING file for more information.
14  *
15  **********************************************************************
16  *
17  * Last port: geom/Geometry.java rev. 1.112
18  *
19  **********************************************************************/
20 
21 #ifndef GEOS_GEOM_GEOMETRY_H
22 #define GEOS_GEOM_GEOMETRY_H
23 
24 #ifndef USE_UNSTABLE_GEOS_CPP_API
25 #ifndef _MSC_VER
26 # warning "The GEOS C++ API is unstable, please use the C API instead"
27 # warning "HINT: #include geos_c.h"
28 #else
29 #pragma message("The GEOS C++ API is unstable, please use the C API instead")
30 #pragma message("HINT: #include geos_c.h")
31 #endif
32 #endif
33 
34 #include <geos/export.h>
35 #include <geos/inline.h>
36 #include <geos/geom/Envelope.h>
37 #include <geos/geom/Dimension.h> // for Dimension::DimensionType
38 #include <geos/geom/GeometryComponentFilter.h> // for inheritance
39 #include <geos/geom/IntersectionMatrix.h>
40 
41 #include <algorithm>
42 #include <string>
43 #include <iostream>
44 #include <vector>
45 #include <memory>
46 
47 #ifdef _MSC_VER
48 #pragma warning(push)
49 #pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
50 #pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
51 #endif
52 
53 // Forward declarations
54 namespace geos {
55 namespace geom {
56 class Coordinate;
57 class CoordinateFilter;
58 class CoordinateSequence;
59 class CoordinateSequenceFilter;
60 class GeometryComponentFilter;
61 class GeometryFactory;
62 class GeometryFilter;
63 class PrecisionModel;
64 class Point;
65 }
66 namespace io { // geos.io
67 class Unload;
68 } // namespace geos.io
69 }
70 
71 namespace geos {
72 namespace geom { // geos::geom
73 
74 /// Geometry types
75 enum GeometryTypeId {
76     /// a point
77     GEOS_POINT,
78     /// a linestring
79     GEOS_LINESTRING,
80     /// a linear ring (linestring with 1st point == last point)
81     GEOS_LINEARRING,
82     /// a polygon
83     GEOS_POLYGON,
84     /// a collection of points
85     GEOS_MULTIPOINT,
86     /// a collection of linestrings
87     GEOS_MULTILINESTRING,
88     /// a collection of polygons
89     GEOS_MULTIPOLYGON,
90     /// a collection of heterogeneus geometries
91     GEOS_GEOMETRYCOLLECTION
92 };
93 
94 enum GeometrySortIndex {
95     SORTINDEX_POINT = 0,
96     SORTINDEX_MULTIPOINT = 1,
97     SORTINDEX_LINESTRING = 2,
98     SORTINDEX_LINEARRING = 3,
99     SORTINDEX_MULTILINESTRING = 4,
100     SORTINDEX_POLYGON = 5,
101     SORTINDEX_MULTIPOLYGON = 6,
102     SORTINDEX_GEOMETRYCOLLECTION = 7
103 };
104 
105 /**
106  * \class Geometry geom.h geos.h
107  *
108  * \brief Basic implementation of Geometry, constructed and
109  * destructed by GeometryFactory.
110  *
111  *  <code>clone</code> returns a deep copy of the object.
112  *  Use GeometryFactory to construct.
113  *
114  *  <H3>Binary Predicates</H3>
115  * Because it is not clear at this time
116  * what semantics for spatial
117  *  analysis methods involving <code>GeometryCollection</code>s would be useful,
118  *  <code>GeometryCollection</code>s are not supported as arguments to binary
119  *  predicates (other than <code>convexHull</code>) or the <code>relate</code>
120  *  method.
121  *
122  *  <H3>Set-Theoretic Methods</H3>
123  *
124  *  The spatial analysis methods will
125  *  return the most specific class possible to represent the result. If the
126  *  result is homogeneous, a <code>Point</code>, <code>LineString</code>, or
127  *  <code>Polygon</code> will be returned if the result contains a single
128  *  element; otherwise, a <code>MultiPoint</code>, <code>MultiLineString</code>,
129  *  or <code>MultiPolygon</code> will be returned. If the result is
130  *  heterogeneous a <code>GeometryCollection</code> will be returned. <P>
131  *
132  *  Because it is not clear at this time what semantics for set-theoretic
133  *  methods involving <code>GeometryCollection</code>s would be useful,
134  * <code>GeometryCollections</code>
135  *  are not supported as arguments to the set-theoretic methods.
136  *
137  *  <H4>Representation of Computed Geometries </H4>
138  *
139  *  The SFS states that the result
140  *  of a set-theoretic method is the "point-set" result of the usual
141  *  set-theoretic definition of the operation (SFS 3.2.21.1). However, there are
142  *  sometimes many ways of representing a point set as a <code>Geometry</code>.
143  *  <P>
144  *
145  *  The SFS does not specify an unambiguous representation of a given point set
146  *  returned from a spatial analysis method. One goal of JTS is to make this
147  *  specification precise and unambiguous. JTS will use a canonical form for
148  *  <code>Geometry</code>s returned from spatial analysis methods. The canonical
149  *  form is a <code>Geometry</code> which is simple and noded:
150  *  <UL>
151  *    <LI> Simple means that the Geometry returned will be simple according to
152  *    the JTS definition of <code>isSimple</code>.
153  *    <LI> Noded applies only to overlays involving <code>LineString</code>s. It
154  *    means that all intersection points on <code>LineString</code>s will be
155  *    present as endpoints of <code>LineString</code>s in the result.
156  *  </UL>
157  *  This definition implies that non-simple geometries which are arguments to
158  *  spatial analysis methods must be subjected to a line-dissolve process to
159  *  ensure that the results are simple.
160  *
161  *  <H4> Constructed Points And The Precision Model </H4>
162  *
163  *  The results computed by the set-theoretic methods may
164  *  contain constructed points which are not present in the input Geometry.
165  *  These new points arise from intersections between line segments in the
166  *  edges of the input Geometry. In the general case it is not
167  *  possible to represent constructed points exactly. This is due to the fact
168  *  that the coordinates of an intersection point may contain twice as many bits
169  *  of precision as the coordinates of the input line segments. In order to
170  *  represent these constructed points explicitly, JTS must truncate them to fit
171  *  the PrecisionModel.
172  *
173  *  Unfortunately, truncating coordinates moves them slightly. Line segments
174  *  which would not be coincident in the exact result may become coincident in
175  *  the truncated representation. This in turn leads to "topology collapses" --
176  *  situations where a computed element has a lower dimension than it would in
177  *  the exact result.
178  *
179  *  When JTS detects topology collapses during the computation of spatial
180  *  analysis methods, it will throw an exception. If possible the exception will
181  *  report the location of the collapse.
182  *
183  *  equals(Object) and hashCode are not overridden, so that when two
184  *  topologically equal Geometries are added to HashMaps and HashSets, they
185  *  remain distinct. This behaviour is desired in many cases.
186  *
187  */
188 class GEOS_DLL Geometry {
189 
190 public:
191 
192     friend class GeometryFactory;
193 
194     /// A vector of const Geometry pointers
195     using ConstVect = std::vector<const Geometry*>;
196 
197     /// A vector of non-const Geometry pointers
198     using NonConstVect = std::vector<Geometry*>;
199 
200     /// An unique_ptr of Geometry
201     using Ptr = std::unique_ptr<Geometry> ;
202 
203     /// Make a deep-copy of this Geometry
204     virtual std::unique_ptr<Geometry> clone() const = 0;
205 
206     /// Destroy Geometry and all components
207     virtual ~Geometry();
208 
209 
210     /**
211      * \brief
212      * Gets the factory which contains the context in which this
213      * geometry was created.
214      *
215      * @return the factory for this geometry
216      */
217     const GeometryFactory*
getFactory()218     getFactory() const
219     {
220         return _factory;
221     }
222 
223     /**
224     * \brief
225     * A simple scheme for applications to add their own custom data to
226     * a Geometry.
227     * An example use might be to add an object representing a
228     * Coordinate Reference System.
229     *
230     * Note that user data objects are not present in geometries created
231     * by construction methods.
232     *
233     * @param newUserData an object, the semantics for which are
234     * defined by the application using this Geometry
235     */
236     void
setUserData(void * newUserData)237     setUserData(void* newUserData)
238     {
239         _userData = newUserData;
240     }
241 
242     /**
243     * \brief
244     * Gets the user data object for this geometry, if any.
245     *
246     * @return the user data object, or <code>null</code> if none set
247     */
248     void*
getUserData()249     getUserData() const
250     {
251         return _userData;
252     }
253 
254     /** \brief
255      * Returns the ID of the Spatial Reference System used by the Geometry.
256      *
257      * GEOS supports Spatial Reference System information in the simple way
258      * defined in the SFS. A Spatial Reference System ID (SRID) is present
259      * in each Geometry object. Geometry provides basic accessor operations
260      * for this field, but no others. The SRID is represented as an integer.
261      *
262      * @return the ID of the coordinate space in which the Geometry is defined.
263      */
264     virtual int
getSRID()265     getSRID() const
266     {
267         return SRID;
268     }
269 
270     /** \brief
271      * Sets the ID of the Spatial Reference System used by the Geometry.
272      */
273     virtual void
setSRID(int newSRID)274     setSRID(int newSRID)
275     {
276         SRID = newSRID;
277     }
278 
279     /**
280      * \brief
281      * Get the PrecisionModel used to create this Geometry.
282      */
283     const PrecisionModel* getPrecisionModel() const;
284 
285     /// Returns a vertex of this Geometry, or NULL if this is the empty geometry.
286     virtual const Coordinate* getCoordinate() const = 0; //Abstract
287 
288     /**
289      * \brief
290      * Returns this Geometry vertices.
291      * Caller takes ownership of the returned object.
292      */
293     virtual std::unique_ptr<CoordinateSequence> getCoordinates() const = 0; //Abstract
294 
295     /// Returns the count of this Geometrys vertices.
296     virtual std::size_t getNumPoints() const = 0; //Abstract
297 
298     /// Returns false if the Geometry not simple.
299     virtual bool isSimple() const;
300 
301     /// Return a string representation of this Geometry type
302     virtual std::string getGeometryType() const = 0; //Abstract
303 
304     /// Return an integer representation of this Geometry type
305     virtual GeometryTypeId getGeometryTypeId() const = 0; //Abstract
306 
307     /// Returns the number of geometries in this collection
308     /// (or 1 if this is not a collection)
309     virtual std::size_t
getNumGeometries()310     getNumGeometries() const
311     {
312         return 1;
313     }
314 
315     /// \brief Returns a pointer to the nth Geometry in this collection
316     /// (or self if this is not a collection)
317     virtual const Geometry*
getGeometryN(std::size_t)318     getGeometryN(std::size_t /*n*/) const
319     {
320         return this;
321     }
322 
323     /**
324      * \brief Tests the validity of this <code>Geometry</code>.
325      *
326      * Subclasses provide their own definition of "valid".
327      *
328      * @return <code>true</code> if this <code>Geometry</code> is valid
329      *
330      * @see IsValidOp
331      */
332     virtual bool isValid() const;
333 
334     /// Returns whether or not the set of points in this Geometry is empty.
335     virtual bool isEmpty() const = 0; //Abstract
336 
337     /// Polygon overrides to check for actual rectangle
338     virtual bool
isRectangle()339     isRectangle() const
340     {
341         return false;
342     }
343 
344     /// Returns the dimension of this Geometry (0=point, 1=line, 2=surface)
345     virtual Dimension::DimensionType getDimension() const = 0; //Abstract
346 
347     /// Checks whether this Geometry consists only of components having dimension d.
isDimensionStrict(Dimension::DimensionType d)348     virtual bool isDimensionStrict(Dimension::DimensionType d) const {
349         return d == getDimension();
350     }
351 
isPuntal()352     bool isPuntal() const {
353         return isDimensionStrict(Dimension::P);
354     }
355 
isLineal()356     bool isLineal() const {
357         return isDimensionStrict(Dimension::L);
358     }
359 
isPolygonal()360     bool isPolygonal() const {
361         return isDimensionStrict(Dimension::A);
362     }
363 
isCollection()364     bool isCollection() const {
365         int t = getGeometryTypeId();
366         return t == GEOS_GEOMETRYCOLLECTION ||
367                t == GEOS_MULTIPOINT ||
368                t == GEOS_MULTILINESTRING ||
369                t == GEOS_MULTIPOLYGON;
370     }
371 
372     /// Returns the coordinate dimension of this Geometry (2=XY, 3=XYZ, 4=XYZM in future).
373     virtual uint8_t getCoordinateDimension() const = 0; //Abstract
374 
375     /**
376      * \brief
377      * Returns the boundary, or an empty geometry of appropriate
378      * dimension if this <code>Geometry</code>  is empty.
379      *
380      * (In the case of zero-dimensional geometries,
381      * an empty GeometryCollection is returned.)
382      * For a discussion of this function, see the OpenGIS Simple
383      * Features Specification. As stated in SFS Section 2.1.13.1,
384      * "the boundary of a Geometry is a set of Geometries of the
385      * next lower dimension."
386      *
387      * @return  the closure of the combinatorial boundary
388      *          of this <code>Geometry</code>.
389      *          Ownershipof the returned object transferred to caller.
390      */
391     virtual std::unique_ptr<Geometry> getBoundary() const = 0; //Abstract
392 
393     /// Returns the dimension of this Geometrys inherent boundary.
394     virtual int getBoundaryDimension() const = 0; //Abstract
395 
396     /// Returns this Geometrys bounding box.
397     virtual std::unique_ptr<Geometry> getEnvelope() const;
398 
399     /** \brief
400      * Returns the minimum and maximum x and y values in this Geometry,
401      * or a null Envelope if this Geometry is empty.
402      */
403     virtual const Envelope* getEnvelopeInternal() const;
404 
405     /**
406      * Tests whether this geometry is disjoint from the specified geometry.
407      *
408      * The <code>disjoint</code> predicate has the following equivalent
409      * definitions:
410      *  - The two geometries have no point in common
411      *  - The DE-9IM Intersection Matrix for the two geometries matches
412      *    <code>[FF*FF****]</code>
413      *  - <code>! g.intersects(this)</code>
414      *    (<code>disjoint</code> is the inverse of <code>intersects</code>)
415      *
416      * @param  other  the Geometry with which to compare this Geometry
417      * @return true if the two <code>Geometry</code>s are disjoint
418      *
419      * @see Geometry::intersects
420      */
421     virtual bool disjoint(const Geometry* other) const;
422 
423     /** \brief
424      * Returns true if the DE-9IM intersection matrix for the two
425      * Geometrys is FT*******, F**T***** or F***T****.
426      */
427     virtual bool touches(const Geometry* other) const;
428 
429     /// Returns true if disjoint returns false.
430     virtual bool intersects(const Geometry* g) const;
431 
432     /**
433      * Tests whether this geometry crosses the specified geometry.
434      *
435      * The <code>crosses</code> predicate has the following equivalent
436      * definitions:
437      *  - The geometries have some but not all interior points in common.
438      *  - The DE-9IM Intersection Matrix for the two geometries matches
439      *    - <code>[T*T******]</code> (for P/L, P/A, and L/A situations)
440      *    - <code>[T*****T**]</code> (for L/P, A/P, and A/L situations)
441      *    - <code>[0********]</code> (for L/L situations)
442      * For any other combination of dimensions this predicate returns
443      * <code>false</code>.
444      *
445      * The SFS defined this predicate only for P/L, P/A, L/L, and L/A
446      * situations.
447      * JTS extends the definition to apply to L/P, A/P and A/L situations
448      * as well, in order to make the relation symmetric.
449      *
450      * @param  g  the <code>Geometry</code> with which to compare this
451      *            <code>Geometry</code>
452      *@return  <code>true</code> if the two <code>Geometry</code>s cross.
453      */
454     virtual bool crosses(const Geometry* g) const;
455 
456     /** \brief
457      * Returns true if the DE-9IM intersection matrix for the two
458      * Geometrys is T*F**F***.
459      */
460     virtual bool within(const Geometry* g) const;
461 
462     /// Returns true if other.within(this) returns true.
463     virtual bool contains(const Geometry* g) const;
464 
465     /** \brief
466      * Returns true if the DE-9IM intersection matrix for the two
467      * Geometrys is T*T***T** (for two points or two surfaces)
468      * 1*T***T** (for two curves).
469      */
470     virtual bool overlaps(const Geometry* g) const;
471 
472     /**
473      * \brief
474      * Returns true if the elements in the DE-9IM intersection matrix
475      * for the two Geometrys match the elements in intersectionPattern.
476      *
477      * IntersectionPattern elements may be: 0 1 2 T ( = 0, 1 or 2)
478      * F ( = -1) * ( = -1, 0, 1 or 2).
479      *
480      * For more information on the DE-9IM, see the OpenGIS Simple
481      * Features Specification.
482      *
483      * @throws util::IllegalArgumentException if either arg is a collection
484      *
485      */
486     bool relate(const Geometry* g,
487                         const std::string& intersectionPattern) const;
488 
489     bool
relate(const Geometry & g,const std::string & intersectionPattern)490     relate(const Geometry& g, const std::string& intersectionPattern) const
491     {
492         return relate(&g, intersectionPattern);
493     }
494 
495     /// Returns the DE-9IM intersection matrix for the two Geometrys.
496     std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const;
497 
relate(const Geometry & g)498     std::unique_ptr<IntersectionMatrix> relate(const Geometry& g) const
499     {
500         return relate(&g);
501     }
502 
503     /**
504      * \brief
505      * Returns true if the DE-9IM intersection matrix for the two
506      * Geometrys is T*F**FFF*.
507      */
508     virtual bool equals(const Geometry* g) const;
509 
510     /** \brief
511      * Returns <code>true</code> if this geometry covers the
512      * specified geometry.
513      *
514      * The <code>covers</code> predicate has the following
515      * equivalent definitions:
516      *
517      * - Every point of the other geometry is a point of this geometry.
518      * - The DE-9IM Intersection Matrix for the two geometries is
519      *    <code>T*****FF*</code>
520      *    or <code>*T****FF*</code>
521      *    or <code>***T**FF*</code>
522      *    or <code>****T*FF*</code>
523      * - <code>g.coveredBy(this)</code>
524      *   (<code>covers</code> is the inverse of <code>coveredBy</code>)
525      *
526      * If either geometry is empty, the value of this predicate
527      * is <tt>false</tt>.
528      *
529      * This predicate is similar to {@link #contains},
530      * but is more inclusive (i.e. returns <tt>true</tt> for more cases).
531      * In particular, unlike <code>contains</code> it does not distinguish
532      * between points in the boundary and in the interior of geometries.
533      * For most situations, <code>covers</code> should be used in
534      * preference to <code>contains</code>.
535      * As an added benefit, <code>covers</code> is more amenable to
536      * optimization, and hence should be more performant.
537      *
538      * @param  g
539      *         the <code>Geometry</code> with which to compare this
540      *         <code>Geometry</code>
541      *
542      * @return <code>true</code> if this <code>Geometry</code>
543      *                           covers <code>g</code>
544      *
545      * @see Geometry::contains
546      * @see Geometry::coveredBy
547      */
548     bool covers(const Geometry* g) const;
549 
550     /** \brief
551      * Tests whether this geometry is covered by the
552      * specified geometry.
553      *
554      * The <code>coveredBy</code> predicate has the following
555      * equivalent definitions:
556      *
557      *  - Every point of this geometry is a point of the other geometry.
558      *  - The DE-9IM Intersection Matrix for the two geometries matches
559      *       <code>[T*F**F***]</code>
560      *    or <code>[*TF**F***]</code>
561      *    or <code>[**FT*F***]</code>
562      *    or <code>[**F*TF***]</code>
563      *  - <code>g.covers(this)</code>
564      *    (<code>coveredBy</code> is the converse of <code>covers</code>)
565      *
566      * If either geometry is empty, the value of this predicate
567      * is <tt>false</tt>.
568      *
569      * This predicate is similar to {@link #within},
570      * but is more inclusive (i.e. returns <tt>true</tt> for more cases).
571      *
572      * @param  g  the <code>Geometry</code> with which to compare
573      *            this <code>Geometry</code>
574      * @return  <code>true</code> if this <code>Geometry</code>
575      *                            is covered by <code>g</code>
576      *
577      * @see Geometry#within
578      * @see Geometry#covers
579      */
580     bool
coveredBy(const Geometry * g)581     coveredBy(const Geometry* g) const
582     {
583         return g->covers(this);
584     }
585 
586 
587     /// Returns the Well-known Text representation of this Geometry.
588     virtual std::string toString() const;
589 
590     virtual std::string toText() const;
591 
592     /// Returns a buffer region around this Geometry having the given width.
593     ///
594     /// @throws util::TopologyException if a robustness error occurs
595     ///
596     std::unique_ptr<Geometry> buffer(double distance) const;
597 
598     /// \brief
599     /// Returns a buffer region around this Geometry having the
600     /// given width and with a specified number of segments used
601     /// to approximate curves.
602     ///
603     /// @throws util::TopologyException if a robustness error occurs
604     ///
605     std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments) const;
606 
607     /** \brief
608      * Computes a buffer area around this geometry having the given
609      * width and with a specified accuracy of approximation for circular
610      * arcs, and using a specified end cap style.
611      *
612      * Buffer area boundaries can contain circular arcs.
613      * To represent these arcs using linear geometry they must be
614      * approximated with line segments.
615      *
616      * The <code>quadrantSegments</code> argument allows controlling the
617      * accuracy of the approximation by specifying the number of line
618      * segments used to represent a quadrant of a circle
619      *
620      * The end cap style specifies the buffer geometry that will be
621      * created at the ends of linestrings.  The styles provided are:
622      *
623      * - BufferOp::CAP_ROUND - (default) a semi-circle
624      * - BufferOp::CAP_BUTT  - a straight line perpendicular to the
625      *                         end segment
626      * - BufferOp::CAP_SQUARE - a half-square
627      *
628      *
629      * @param distance the width of the buffer
630      *                 (may be positive, negative or 0)
631      *
632      * @param quadrantSegments the number of line segments used
633      *                         to represent a quadrant of a circle
634      *
635      * @param endCapStyle the end cap style to use
636      *
637      * @return an area geometry representing the buffer region
638      *
639      * @throws util::TopologyException if a robustness error occurs
640      *
641      * @see BufferOp
642      */
643     std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments,
644                              int endCapStyle) const;
645 
646     /// \brief
647     /// Returns the smallest convex Polygon that contains
648     /// all the points in the Geometry.
649     virtual std::unique_ptr<Geometry> convexHull() const;
650 
651     /** \brief
652      * Computes a new geometry which has all component coordinate sequences
653      * in reverse order (opposite orientation) to this one.
654      *
655      * @return a reversed geometry
656      */
657     virtual std::unique_ptr<Geometry> reverse() const = 0;
658 
659     /** \brief
660      * Returns a Geometry representing the points shared by
661      * this Geometry and other.
662      *
663      * @throws util::TopologyException if a robustness error occurs
664      * @throws util::IllegalArgumentException if either input is a
665      *         non-empty GeometryCollection
666      *
667      */
668     std::unique_ptr<Geometry> intersection(const Geometry* other) const;
669 
670     /** \brief
671      * Returns a Geometry representing all the points in this Geometry
672      * and other.
673      *
674      * @throws util::TopologyException if a robustness error occurs
675      * @throws util::IllegalArgumentException if either input is a
676      *         non-empty GeometryCollection
677      *
678      */
679     std::unique_ptr<Geometry> Union(const Geometry* other) const;
680     // throw(IllegalArgumentException *, TopologyException *);
681 
682     /** \brief
683      * Computes the union of all the elements of this geometry. Heterogeneous
684      * [GeometryCollections](@ref GeometryCollection) are fully supported.
685      *
686      * The result obeys the following contract:
687      *
688      * - Unioning a set of [LineStrings](@ref LineString) has the effect of fully noding
689      *   and dissolving the linework.
690      * - Unioning a set of [Polygons](@ref Polygon) will always
691      *   return a polygonal geometry (unlike Geometry::Union(const Geometry* other) const),
692      *   which may return geometrys of lower dimension if a topology collapse
693      *   occurred.
694      *
695      * @return the union geometry
696      *
697      * @see UnaryUnionOp
698      */
699     Ptr Union() const;
700     // throw(IllegalArgumentException *, TopologyException *);
701 
702     /**
703      * \brief
704      * Returns a Geometry representing the points making up this
705      * Geometry that do not make up other.
706      *
707      * @throws util::TopologyException if a robustness error occurs
708      * @throws util::IllegalArgumentException if either input is a
709      *         non-empty GeometryCollection
710      *
711      */
712     std::unique_ptr<Geometry> difference(const Geometry* other) const;
713 
714     /** \brief
715      * Returns a set combining the points in this Geometry not in other,
716      * and the points in other not in this Geometry.
717      *
718      * @throws util::TopologyException if a robustness error occurs
719      * @throws util::IllegalArgumentException if either input is a
720      *         non-empty GeometryCollection
721      *
722      */
723     std::unique_ptr<Geometry> symDifference(const Geometry* other) const;
724 
725     /** \brief
726      * Returns true iff the two Geometrys are of the same type and their
727      * vertices corresponding by index are equal up to a specified tolerance.
728      */
729     virtual bool equalsExact(const Geometry* other, double tolerance = 0)
730         const = 0; // Abstract
731 
732     virtual void apply_rw(const CoordinateFilter* filter) = 0; //Abstract
733     virtual void apply_ro(CoordinateFilter* filter) const = 0; //Abstract
734     virtual void apply_rw(GeometryFilter* filter);
735     virtual void apply_ro(GeometryFilter* filter) const;
736     virtual void apply_rw(GeometryComponentFilter* filter);
737     virtual void apply_ro(GeometryComponentFilter* filter) const;
738 
739     /**
740      *  Performs an operation on the coordinates in this Geometry's
741      *  CoordinateSequences.
742      *  If the filter reports that a coordinate value has been changed,
743      *  {@link #geometryChanged} will be called automatically.
744      *
745      * @param  filter  the filter to apply
746      */
747     virtual void apply_rw(CoordinateSequenceFilter& filter) = 0;
748 
749     /**
750      *  Performs a read-only operation on the coordinates in this
751      *  Geometry's CoordinateSequences.
752      *
753      * @param  filter  the filter to apply
754      */
755     virtual void apply_ro(CoordinateSequenceFilter& filter) const = 0;
756 
757     /** \brief
758      * Apply a filter to each component of this geometry.
759      * The filter is expected to provide a .filter(const Geometry*)
760      * method.
761      *
762      * I intend similar templated methods to replace
763      * all the virtual apply_rw and apply_ro functions...
764      *                --strk(2005-02-06);
765      */
766     template <class T>
767     void
applyComponentFilter(T & f)768     applyComponentFilter(T& f) const
769     {
770         for(std::size_t i = 0, n = getNumGeometries(); i < n; ++i) {
771             f.filter(getGeometryN(i));
772         }
773     }
774 
775     /**
776      * Reorganizes this Geometry into normal form (or canonical form).
777      * Starting point of rings is lower left, collections are ordered
778      * by geometry type, etc.
779      */
780     virtual void normalize() = 0; //Abstract
781 
782     /// Comparator for sorting geometry
783     virtual int compareTo(const Geometry* geom) const;
784 
785     /** \brief
786      * Returns the minimum distance between this Geometry
787      * and the Geometry g
788      */
789     virtual double distance(const Geometry* g) const;
790 
791     /// Returns the area of this Geometry.
792     virtual double getArea() const;
793 
794     /// Returns the length of this Geometry.
795     virtual double getLength() const;
796 
797     /** \brief
798      * Tests whether the distance from this Geometry  to another
799      * is less than or equal to a specified value.
800      *
801      * @param geom the Geometry to check the distance to
802      * @param cDistance the distance value to compare
803      * @return <code>true</code> if the geometries are less than
804      *  <code>distance</code> apart.
805      *
806      * @todo doesn't seem to need being virtual, make it concrete
807      */
808     virtual bool isWithinDistance(const Geometry* geom,
809                                   double cDistance) const;
810 
811     /** \brief
812      * Computes the centroid of this <code>Geometry</code>.
813      *
814      * The centroid is equal to the centroid of the set of component
815      * Geometries of highest dimension (since the lower-dimension geometries
816      * contribute zero "weight" to the centroid)
817      *
818      * @return a {@link Point} which is the centroid of this Geometry
819      */
820     virtual std::unique_ptr<Point> getCentroid() const;
821 
822     /// Computes the centroid of this Geometry as a Coordinate
823     //
824     /// Returns false if centroid cannot be computed (EMPTY geometry)
825     ///
826     virtual bool getCentroid(Coordinate& ret) const;
827 
828     /** \brief
829      * Computes an interior point of this <code>Geometry</code>.
830      *
831      * An interior point is guaranteed to lie in the interior of the Geometry,
832      * if it possible to calculate such a point exactly. Otherwise,
833      * the point may lie on the boundary of the geometry.
834      *
835      * @return a Point which is in the interior of this Geometry, or
836      *         null if the geometry doesn't have an interior (empty)
837      */
838     std::unique_ptr<Point> getInteriorPoint() const;
839 
840     /**
841      * \brief
842      * Notifies this Geometry that its Coordinates have been changed
843      * by an external party (using a CoordinateFilter, for example).
844      */
845     virtual void geometryChanged();
846 
847     /**
848      * \brief
849      * Notifies this Geometry that its Coordinates have been changed
850      * by an external party.
851      */
852     void geometryChangedAction();
853 
854 protected:
855 
856     /// The bounding box of this Geometry
857     mutable std::unique_ptr<Envelope> envelope;
858 
859     /// Returns true if the array contains any non-empty Geometrys.
860     template<typename T>
hasNonEmptyElements(const std::vector<T> * geometries)861     static bool hasNonEmptyElements(const std::vector<T>* geometries) {
862         return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return !g->isEmpty(); });
863     }
864 
865     /// Returns true if the CoordinateSequence contains any null elements.
866     static bool hasNullElements(const CoordinateSequence* list);
867 
868     /// Returns true if the vector contains any null elements.
869     template<typename T>
hasNullElements(const std::vector<T> * geometries)870     static bool hasNullElements(const std::vector<T>* geometries) {
871         return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return g == nullptr; });
872     }
873 
874 //	static void reversePointOrder(CoordinateSequence* coordinates);
875 //	static Coordinate& minCoordinate(CoordinateSequence* coordinates);
876 //	static void scroll(CoordinateSequence* coordinates,Coordinate* firstCoordinate);
877 //	static int indexOf(Coordinate* coordinate,CoordinateSequence* coordinates);
878 //
879     /** \brief
880      * Returns whether the two Geometrys are equal, from the point
881      * of view of the equalsExact method.
882      */
883     virtual bool isEquivalentClass(const Geometry* other) const;
884 
885     static void checkNotGeometryCollection(const Geometry* g);
886     // throw(IllegalArgumentException *);
887 
888     //virtual void checkEqualSRID(Geometry *other);
889 
890     //virtual void checkEqualPrecisionModel(Geometry *other);
891 
892     virtual Envelope::Ptr computeEnvelopeInternal() const = 0; //Abstract
893 
894     virtual int compareToSameClass(const Geometry* geom) const = 0; //Abstract
895 
896     int compare(std::vector<Coordinate> a, std::vector<Coordinate> b) const;
897 
898     int compare(std::vector<Geometry*> a, std::vector<Geometry*> b) const;
899 
900     int compare(const std::vector<std::unique_ptr<Geometry>> & a, const std::vector<std::unique_ptr<Geometry>> & b) const;
901 
902     bool equal(const Coordinate& a, const Coordinate& b,
903                double tolerance) const;
904     int SRID;
905 
906     Geometry(const Geometry& geom);
907 
908     /** \brief
909      * Construct a geometry with the given GeometryFactory.
910      *
911      * Will keep a reference to the factory, so don't
912      * delete it until al Geometry objects referring to
913      * it are deleted.
914      *
915      * @param factory
916      */
917     Geometry(const GeometryFactory* factory);
918 
919     template<typename T>
toGeometryArray(std::vector<std::unique_ptr<T>> && v)920     static std::vector<std::unique_ptr<Geometry>> toGeometryArray(std::vector<std::unique_ptr<T>> && v) {
921         static_assert(std::is_base_of<Geometry, T>::value, "");
922         std::vector<std::unique_ptr<Geometry>> gv(v.size());
923         for (size_t i = 0; i < v.size(); i++) {
924             gv[i] = std::move(v[i]);
925         }
926         return gv;
927     }
928 
929 protected:
930 
931     virtual int getSortIndex() const = 0;
932 
933 
934 private:
935 
936     class GEOS_DLL GeometryChangedFilter : public GeometryComponentFilter {
937     public:
938         void filter_rw(Geometry* geom) override;
939     };
940 
941     static GeometryChangedFilter geometryChangedFilter;
942 
943     /// The GeometryFactory used to create this Geometry
944     ///
945     /// Externally owned
946     ///
947     const GeometryFactory* _factory;
948 
949     void* _userData;
950 };
951 
952 /// \brief
953 /// Write the Well-known Binary representation of this Geometry
954 /// as an HEX string to the given output stream
955 ///
956 GEOS_DLL std::ostream& operator<< (std::ostream& os, const Geometry& geom);
957 
958 struct GEOS_DLL GeometryGreaterThen {
959     bool operator()(const Geometry* first, const Geometry* second);
960 };
961 
962 
963 /// Return current GEOS version
964 GEOS_DLL std::string geosversion();
965 
966 /**
967  * \brief
968  * Return the version of JTS this GEOS
969  * release has been ported from.
970  */
971 GEOS_DLL std::string jtsport();
972 
973 // We use this instead of std::pair<unique_ptr<Geometry>> because C++11
974 // forbids that construct:
975 // http://lwg.github.com/issues/lwg-closed.html#2068
976 struct GeomPtrPair {
977     typedef std::unique_ptr<Geometry> GeomPtr;
978     GeomPtr first;
979     GeomPtr second;
980 };
981 
982 } // namespace geos::geom
983 } // namespace geos
984 
985 #ifdef _MSC_VER
986 #pragma warning(pop)
987 #endif
988 
989 #endif // ndef GEOS_GEOM_GEOMETRY_H
990