DYT/Tool/OpenSceneGraph-3.6.5/include/geos/geom/Geometry.h
2024-12-25 07:49:36 +08:00

1052 lines
35 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2009 2011 Sandro Santilli <strk@kbt.io>
* Copyright (C) 2005 2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************
*
* Last port: geom/Geometry.java rev. 1.112
*
**********************************************************************/
#pragma once
#ifndef USE_UNSTABLE_GEOS_CPP_API
#ifndef _MSC_VER
# warning "The GEOS C++ API is unstable, please use the C API instead"
# warning "HINT: #include geos_c.h"
#else
#pragma message("The GEOS C++ API is unstable, please use the C API instead")
#pragma message("HINT: #include geos_c.h")
#endif
#endif
#include <geos/export.h>
#include <geos/geom/Envelope.h>
#include <geos/geom/Dimension.h> // for Dimension::DimensionType
#include <geos/geom/GeometryComponentFilter.h> // for inheritance
#include <geos/geom/CoordinateSequence.h> // to materialize CoordinateSequence
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <memory>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
#endif
// Forward declarations
namespace geos {
namespace geom {
class Coordinate;
class CoordinateFilter;
class CoordinateSequence;
class CoordinateSequenceFilter;
class GeometryComponentFilter;
class GeometryFactory;
class GeometryFilter;
class PrecisionModel;
class Point;
class IntersectionMatrix;
}
namespace io { // geos.io
class Unload;
} // namespace geos.io
}
namespace geos { // geos
namespace geom { // geos::geom
/// Geometry types
enum GeometryTypeId : int {
/// a point
GEOS_POINT,
/// a linestring
GEOS_LINESTRING,
/// a linear ring (linestring with 1st point == last point)
GEOS_LINEARRING,
/// a polygon
GEOS_POLYGON,
/// a collection of points
GEOS_MULTIPOINT,
/// a collection of linestrings
GEOS_MULTILINESTRING,
/// a collection of polygons
GEOS_MULTIPOLYGON,
/// a collection of heterogeneus geometries
GEOS_GEOMETRYCOLLECTION,
GEOS_CIRCULARSTRING,
GEOS_COMPOUNDCURVE,
GEOS_CURVEPOLYGON,
GEOS_MULTICURVE,
GEOS_MULTISURFACE,
};
enum GeometrySortIndex {
SORTINDEX_POINT = 0,
SORTINDEX_MULTIPOINT = 1,
SORTINDEX_LINESTRING = 2,
SORTINDEX_LINEARRING = 3,
SORTINDEX_MULTILINESTRING = 4,
SORTINDEX_POLYGON = 5,
SORTINDEX_MULTIPOLYGON = 6,
SORTINDEX_GEOMETRYCOLLECTION = 7,
SORTINDEX_CIRCULARSTRING = 8,
SORTINDEX_COMPOUNDCURVE = 9,
SORTINDEX_CURVEPOLYGON = 10,
SORTINDEX_MULTICURVE = 11,
SORTINDEX_MULTISURFACE = 12,
};
/**
* \class Geometry geom.h geos.h
*
* \brief Basic implementation of Geometry, constructed and
* destructed by GeometryFactory.
*
* <code>clone</code> returns a deep copy of the object.
* Use GeometryFactory to construct.
*
* <H3>Binary Predicates</H3>
* Because it is not clear at this time
* what semantics for spatial
* analysis methods involving <code>GeometryCollection</code>s would be useful,
* <code>GeometryCollection</code>s are not supported as arguments to binary
* predicates (other than <code>convexHull</code>) or the <code>relate</code>
* method.
*
* <H3>Set-Theoretic Methods</H3>
*
* The spatial analysis methods will
* return the most specific class possible to represent the result. If the
* result is homogeneous, a <code>Point</code>, <code>LineString</code>, or
* <code>Polygon</code> will be returned if the result contains a single
* element; otherwise, a <code>MultiPoint</code>, <code>MultiLineString</code>,
* or <code>MultiPolygon</code> will be returned. If the result is
* heterogeneous a <code>GeometryCollection</code> will be returned. <P>
*
* Because it is not clear at this time what semantics for set-theoretic
* methods involving <code>GeometryCollection</code>s would be useful,
* <code>GeometryCollections</code>
* are not supported as arguments to the set-theoretic methods.
*
* <H4>Representation of Computed Geometries </H4>
*
* The SFS states that the result
* of a set-theoretic method is the "point-set" result of the usual
* set-theoretic definition of the operation (SFS 3.2.21.1). However, there are
* sometimes many ways of representing a point set as a <code>Geometry</code>.
* <P>
*
* The SFS does not specify an unambiguous representation of a given point set
* returned from a spatial analysis method. One goal of JTS is to make this
* specification precise and unambiguous. JTS will use a canonical form for
* <code>Geometry</code>s returned from spatial analysis methods. The canonical
* form is a <code>Geometry</code> which is simple and noded:
* <UL>
* <LI> Simple means that the Geometry returned will be simple according to
* the JTS definition of <code>isSimple</code>.
* <LI> Noded applies only to overlays involving <code>LineString</code>s. It
* means that all intersection points on <code>LineString</code>s will be
* present as endpoints of <code>LineString</code>s in the result.
* </UL>
* This definition implies that non-simple geometries which are arguments to
* spatial analysis methods must be subjected to a line-dissolve process to
* ensure that the results are simple.
*
* <H4> Constructed Points And The Precision Model </H4>
*
* The results computed by the set-theoretic methods may
* contain constructed points which are not present in the input Geometry.
* These new points arise from intersections between line segments in the
* edges of the input Geometry. In the general case it is not
* possible to represent constructed points exactly. This is due to the fact
* that the coordinates of an intersection point may contain twice as many bits
* of precision as the coordinates of the input line segments. In order to
* represent these constructed points explicitly, JTS must truncate them to fit
* the PrecisionModel.
*
* Unfortunately, truncating coordinates moves them slightly. Line segments
* which would not be coincident in the exact result may become coincident in
* the truncated representation. This in turn leads to "topology collapses" --
* situations where a computed element has a lower dimension than it would in
* the exact result.
*
* When JTS detects topology collapses during the computation of spatial
* analysis methods, it will throw an exception. If possible the exception will
* report the location of the collapse.
*
* equals(Object) and hashCode are not overridden, so that when two
* topologically equal Geometries are added to HashMaps and HashSets, they
* remain distinct. This behaviour is desired in many cases.
*
*/
class GEOS_DLL Geometry {
public:
friend class GeometryFactory;
/// A vector of const Geometry pointers
using ConstVect = std::vector<const Geometry*>;
/// A vector of non-const Geometry pointers
using NonConstVect = std::vector<Geometry*>;
/// An unique_ptr of Geometry
using Ptr = std::unique_ptr<Geometry> ;
/// Make a deep-copy of this Geometry
std::unique_ptr<Geometry> clone() const { return std::unique_ptr<Geometry>(cloneImpl()); }
/// Destroy Geometry and all components
virtual ~Geometry();
/**
* \brief
* Gets the factory which contains the context in which this
* geometry was created.
*
* @return the factory for this geometry
*/
const GeometryFactory*
getFactory() const
{
return _factory;
}
/**
* \brief
* A simple scheme for applications to add their own custom data to
* a Geometry.
* An example use might be to add an object representing a
* Coordinate Reference System.
*
* Note that user data objects are not present in geometries created
* by construction methods.
*
* @param newUserData an object, the semantics for which are
* defined by the application using this Geometry
*/
void
setUserData(void* newUserData)
{
_userData = newUserData;
}
/**
* \brief
* Gets the user data object for this geometry, if any.
*
* @return the user data object, or <code>null</code> if none set
*/
void*
getUserData() const
{
return _userData;
}
/** \brief
* Returns the ID of the Spatial Reference System used by the Geometry.
*
* GEOS supports Spatial Reference System information in the simple way
* defined in the SFS. A Spatial Reference System ID (SRID) is present
* in each Geometry object. Geometry provides basic accessor operations
* for this field, but no others. The SRID is represented as an integer.
*
* @return the ID of the coordinate space in which the Geometry is defined.
*/
virtual int
getSRID() const
{
return SRID;
}
/** \brief
* Sets the ID of the Spatial Reference System used by the Geometry.
*/
virtual void
setSRID(int newSRID)
{
SRID = newSRID;
}
/**
* \brief
* Get the PrecisionModel used to create this Geometry.
*/
const PrecisionModel* getPrecisionModel() const;
/// Returns a vertex of this Geometry, or NULL if this is the empty geometry.
virtual const CoordinateXY* getCoordinate() const = 0; //Abstract
/**
* \brief
* Returns this Geometry vertices.
* Caller takes ownership of the returned object.
*/
virtual std::unique_ptr<CoordinateSequence> getCoordinates() const = 0; //Abstract
/// Returns the count of this Geometrys vertices.
virtual std::size_t getNumPoints() const = 0; //Abstract
/// Returns false if the Geometry not simple.
virtual bool isSimple() const;
/// Return a string representation of this Geometry type
virtual std::string getGeometryType() const = 0; //Abstract
/// Returns whether the Geometry contains curved components
virtual bool hasCurvedComponents() const;
/// Return an integer representation of this Geometry type
virtual GeometryTypeId getGeometryTypeId() const = 0; //Abstract
/**
* \brief Returns the number of geometries in this collection,
* or 1 if this is not a collection.
*
* Empty collection or multi-geometry types return 0,
* and empty simple geometry types return 1.
*/
virtual std::size_t
getNumGeometries() const
{
return 1;
}
/// \brief Returns a pointer to the nth Geometry in this collection
/// (or self if this is not a collection)
virtual const Geometry*
getGeometryN(std::size_t /*n*/) const
{
return this;
}
/**
* \brief Tests the validity of this <code>Geometry</code>.
*
* Subclasses provide their own definition of "valid".
*
* @return <code>true</code> if this <code>Geometry</code> is valid
*
* @see IsValidOp
*/
virtual bool isValid() const;
/// Returns whether or not the set of points in this Geometry is empty.
virtual bool isEmpty() const = 0; //Abstract
/// Polygon overrides to check for actual rectangle
virtual bool
isRectangle() const
{
return false;
}
/// Returns the dimension of this Geometry (0=point, 1=line, 2=surface)
virtual Dimension::DimensionType getDimension() const = 0; //Abstract
/// Checks whether any component of this geometry has dimension d
virtual bool hasDimension(Dimension::DimensionType d) const {
return getDimension() == d;
}
/// Checks whether this Geometry consists only of components having dimension d.
virtual bool isDimensionStrict(Dimension::DimensionType d) const {
return d == getDimension();
}
bool isPuntal() const {
return isDimensionStrict(Dimension::P);
}
bool isLineal() const {
return isDimensionStrict(Dimension::L);
}
bool isPolygonal() const {
return isDimensionStrict(Dimension::A);
}
bool isMixedDimension() const;
bool isMixedDimension(Dimension::DimensionType* baseDim) const;
bool isCollection() const {
int t = getGeometryTypeId();
return t == GEOS_GEOMETRYCOLLECTION ||
t == GEOS_MULTIPOINT ||
t == GEOS_MULTILINESTRING ||
t == GEOS_MULTIPOLYGON;
}
static GeometryTypeId multiTypeId(GeometryTypeId typeId) {
switch (typeId) {
case GEOS_POINT: return GEOS_MULTIPOINT;
case GEOS_LINESTRING: return GEOS_MULTILINESTRING;
case GEOS_POLYGON: return GEOS_MULTIPOLYGON;
default: return typeId;
}
}
/// Returns the coordinate dimension of this Geometry (2=XY, 3=XYZ or XYM, 4=XYZM).
virtual uint8_t getCoordinateDimension() const = 0; //Abstract
virtual bool hasZ() const = 0;
virtual bool hasM() const = 0;
/**
* \brief
* Returns the boundary, or an empty geometry of appropriate
* dimension if this <code>Geometry</code> is empty.
*
* (In the case of zero-dimensional geometries,
* an empty GeometryCollection is returned.)
* For a discussion of this function, see the OpenGIS Simple
* Features Specification. As stated in SFS Section 2.1.13.1,
* "the boundary of a Geometry is a set of Geometries of the
* next lower dimension."
*
* @return the closure of the combinatorial boundary
* of this <code>Geometry</code>.
* Ownershipof the returned object transferred to caller.
*/
virtual std::unique_ptr<Geometry> getBoundary() const = 0; //Abstract
/// Returns the dimension of this Geometrys inherent boundary.
virtual int getBoundaryDimension() const = 0; //Abstract
/// Returns this Geometrys bounding box.
virtual std::unique_ptr<Geometry> getEnvelope() const;
/** \brief
* Returns the minimum and maximum x and y values in this Geometry,
* or a null Envelope if this Geometry is empty.
*/
virtual const Envelope* getEnvelopeInternal() const = 0;
/**
* Tests whether this geometry is disjoint from the specified geometry.
*
* The <code>disjoint</code> predicate has the following equivalent
* definitions:
* - The two geometries have no point in common
* - The DE-9IM Intersection Matrix for the two geometries matches
* <code>[FF*FF****]</code>
* - <code>! g.intersects(this)</code>
* (<code>disjoint</code> is the inverse of <code>intersects</code>)
*
* @param other the Geometry with which to compare this Geometry
* @return true if the two <code>Geometry</code>s are disjoint
*
* @see Geometry::intersects
*/
virtual bool disjoint(const Geometry* other) const;
/** \brief
* Returns true if the DE-9IM intersection matrix for the two
* Geometrys is FT*******, F**T***** or F***T****.
*/
virtual bool touches(const Geometry* other) const;
/// Returns true if disjoint returns false.
virtual bool intersects(const Geometry* g) const;
/**
* Tests whether this geometry crosses the specified geometry.
*
* The <code>crosses</code> predicate has the following equivalent
* definitions:
* - The geometries have some but not all interior points in common.
* - The DE-9IM Intersection Matrix for the two geometries matches
* - <code>[T*T******]</code> (for P/L, P/A, and L/A situations)
* - <code>[T*****T**]</code> (for L/P, A/P, and A/L situations)
* - <code>[0********]</code> (for L/L situations)
* For any other combination of dimensions this predicate returns
* <code>false</code>.
*
* The SFS defined this predicate only for P/L, P/A, L/L, and L/A
* situations.
* JTS extends the definition to apply to L/P, A/P and A/L situations
* as well, in order to make the relation symmetric.
*
* @param g the <code>Geometry</code> with which to compare this
* <code>Geometry</code>
*@return <code>true</code> if the two <code>Geometry</code>s cross.
*/
virtual bool crosses(const Geometry* g) const;
/** \brief
* Returns true if the DE-9IM intersection matrix for the two
* Geometrys is T*F**F***.
*/
virtual bool within(const Geometry* g) const;
/// Returns true if other.within(this) returns true.
virtual bool contains(const Geometry* g) const;
/** \brief
* Returns true if the DE-9IM intersection matrix for the two
* Geometrys is T*T***T** (for two points or two surfaces)
* 1*T***T** (for two curves).
*/
virtual bool overlaps(const Geometry* g) const;
/**
* \brief
* Returns true if the elements in the DE-9IM intersection matrix
* for the two Geometrys match the elements in intersectionPattern.
*
* IntersectionPattern elements may be: 0 1 2 T ( = 0, 1 or 2)
* F ( = -1) * ( = -1, 0, 1 or 2).
*
* For more information on the DE-9IM, see the OpenGIS Simple
* Features Specification.
*
* @throws util::IllegalArgumentException if either arg is a collection
*
*/
bool relate(const Geometry* g,
const std::string& intersectionPattern) const;
bool
relate(const Geometry& g, const std::string& intersectionPattern) const
{
return relate(&g, intersectionPattern);
}
/// Returns the DE-9IM intersection matrix for the two Geometrys.
std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const;
std::unique_ptr<IntersectionMatrix> relate(const Geometry& g) const;
/**
* \brief
* Returns true if the DE-9IM intersection matrix for the two
* Geometrys is T*F**FFF*.
*/
virtual bool equals(const Geometry* g) const;
/** \brief
* Returns <code>true</code> if this geometry covers the
* specified geometry.
*
* The <code>covers</code> predicate has the following
* equivalent definitions:
*
* - Every point of the other geometry is a point of this geometry.
* - The DE-9IM Intersection Matrix for the two geometries is
* <code>T*****FF*</code>
* or <code>*T****FF*</code>
* or <code>***T**FF*</code>
* or <code>****T*FF*</code>
* - <code>g.coveredBy(this)</code>
* (<code>covers</code> is the inverse of <code>coveredBy</code>)
*
* If either geometry is empty, the value of this predicate
* is <tt>false</tt>.
*
* This predicate is similar to {@link #contains},
* but is more inclusive (i.e. returns <tt>true</tt> for more cases).
* In particular, unlike <code>contains</code> it does not distinguish
* between points in the boundary and in the interior of geometries.
* For most situations, <code>covers</code> should be used in
* preference to <code>contains</code>.
* As an added benefit, <code>covers</code> is more amenable to
* optimization, and hence should be more performant.
*
* @param g
* the <code>Geometry</code> with which to compare this
* <code>Geometry</code>
*
* @return <code>true</code> if this <code>Geometry</code>
* covers <code>g</code>
*
* @see Geometry::contains
* @see Geometry::coveredBy
*/
bool covers(const Geometry* g) const;
/** \brief
* Tests whether this geometry is covered by the
* specified geometry.
*
* The <code>coveredBy</code> predicate has the following
* equivalent definitions:
*
* - Every point of this geometry is a point of the other geometry.
* - The DE-9IM Intersection Matrix for the two geometries matches
* <code>[T*F**F***]</code>
* or <code>[*TF**F***]</code>
* or <code>[**FT*F***]</code>
* or <code>[**F*TF***]</code>
* - <code>g.covers(this)</code>
* (<code>coveredBy</code> is the converse of <code>covers</code>)
*
* If either geometry is empty, the value of this predicate
* is <tt>false</tt>.
*
* This predicate is similar to {@link #within},
* but is more inclusive (i.e. returns <tt>true</tt> for more cases).
*
* @param g the <code>Geometry</code> with which to compare
* this <code>Geometry</code>
* @return <code>true</code> if this <code>Geometry</code>
* is covered by <code>g</code>
*
* @see Geometry#within
* @see Geometry#covers
*/
bool coveredBy(const Geometry* g) const;
/// Returns the Well-known Text representation of this Geometry.
virtual std::string toString() const;
virtual std::string toText() const;
/// Returns a buffer region around this Geometry having the given width.
///
/// @throws util::TopologyException if a robustness error occurs
///
std::unique_ptr<Geometry> buffer(double distance) const;
/// \brief
/// Returns a buffer region around this Geometry having the
/// given width and with a specified number of segments used
/// to approximate curves.
///
/// @throws util::TopologyException if a robustness error occurs
///
std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments) const;
/** \brief
* Computes a buffer area around this geometry having the given
* width and with a specified accuracy of approximation for circular
* arcs, and using a specified end cap style.
*
* Buffer area boundaries can contain circular arcs.
* To represent these arcs using linear geometry they must be
* approximated with line segments.
*
* The <code>quadrantSegments</code> argument allows controlling the
* accuracy of the approximation by specifying the number of line
* segments used to represent a quadrant of a circle
*
* The end cap style specifies the buffer geometry that will be
* created at the ends of linestrings. The styles provided are:
*
* - BufferOp::CAP_ROUND - (default) a semi-circle
* - BufferOp::CAP_BUTT - a straight line perpendicular to the
* end segment
* - BufferOp::CAP_SQUARE - a half-square
*
*
* @param distance the width of the buffer
* (may be positive, negative or 0)
*
* @param quadrantSegments the number of line segments used
* to represent a quadrant of a circle
*
* @param endCapStyle the end cap style to use
*
* @return an area geometry representing the buffer region
*
* @throws util::TopologyException if a robustness error occurs
*
* @see BufferOp
*/
std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments,
int endCapStyle) const;
/// \brief
/// Returns the smallest convex Polygon that contains
/// all the points in the Geometry.
virtual std::unique_ptr<Geometry> convexHull() const;
/** \brief
* Computes a new geometry which has all component coordinate sequences
* in reverse order (opposite orientation) to this one.
*
* @return a reversed geometry
*/
std::unique_ptr<Geometry> reverse() const { return std::unique_ptr<Geometry>(reverseImpl()); }
/** \brief
* Returns a Geometry representing the points shared by
* this Geometry and other.
*
* @throws util::TopologyException if a robustness error occurs
* @throws util::IllegalArgumentException if either input is a
* non-empty GeometryCollection
*
*/
std::unique_ptr<Geometry> intersection(const Geometry* other) const;
/** \brief
* Returns a Geometry representing all the points in this Geometry
* and other.
*
* @throws util::TopologyException if a robustness error occurs
* @throws util::IllegalArgumentException if either input is a
* non-empty GeometryCollection
*
*/
std::unique_ptr<Geometry> Union(const Geometry* other) const;
// throw(IllegalArgumentException *, TopologyException *);
/** \brief
* Computes the union of all the elements of this geometry. Heterogeneous
* [GeometryCollections](@ref GeometryCollection) are fully supported.
*
* The result obeys the following contract:
*
* - Unioning a set of [LineStrings](@ref LineString) has the effect of fully noding
* and dissolving the linework.
* - Unioning a set of [Polygons](@ref Polygon) will always
* return a polygonal geometry (unlike Geometry::Union(const Geometry* other) const),
* which may return geometrys of lower dimension if a topology collapse
* occurred.
*
* @return the union geometry
*
* @see UnaryUnionOp
*/
Ptr Union() const;
// throw(IllegalArgumentException *, TopologyException *);
/**
* \brief
* Returns a Geometry representing the points making up this
* Geometry that do not make up other.
*
* @throws util::TopologyException if a robustness error occurs
* @throws util::IllegalArgumentException if either input is a
* non-empty GeometryCollection
*
*/
std::unique_ptr<Geometry> difference(const Geometry* other) const;
/** \brief
* Returns a set combining the points in this Geometry not in other,
* and the points in other not in this Geometry.
*
* @throws util::TopologyException if a robustness error occurs
* @throws util::IllegalArgumentException if either input is a
* non-empty GeometryCollection
*
*/
std::unique_ptr<Geometry> symDifference(const Geometry* other) const;
/** \brief
* Returns true iff the two Geometrys are of the same type and their
* vertices corresponding by index are equal up to a specified distance
* tolerance. Geometries are not required to have the same dimemsion;
* any Z/M values are ignored.
*/
virtual bool equalsExact(const Geometry* other, double tolerance = 0)
const = 0; // Abstract
/** \brief
* Returns true if the two geometries are of the same type and their
* vertices corresponding by index are equal in all dimensions.
*/
virtual bool equalsIdentical(const Geometry* other) const = 0;
virtual void apply_rw(const CoordinateFilter* filter) = 0; //Abstract
virtual void apply_ro(CoordinateFilter* filter) const = 0; //Abstract
virtual void apply_rw(GeometryFilter* filter);
virtual void apply_ro(GeometryFilter* filter) const;
virtual void apply_rw(GeometryComponentFilter* filter);
virtual void apply_ro(GeometryComponentFilter* filter) const;
/**
* Performs an operation on the coordinates in this Geometry's
* CoordinateSequences.
* If the filter reports that a coordinate value has been changed,
* {@link #geometryChanged} will be called automatically.
*
* @param filter the filter to apply
*/
virtual void apply_rw(CoordinateSequenceFilter& filter) = 0;
/**
* Performs a read-only operation on the coordinates in this
* Geometry's CoordinateSequences.
*
* @param filter the filter to apply
*/
virtual void apply_ro(CoordinateSequenceFilter& filter) const = 0;
/** \brief
* Apply a filter to each component of this geometry.
* The filter is expected to provide a .filter(const Geometry*)
* method.
*
* I intend similar templated methods to replace
* all the virtual apply_rw and apply_ro functions...
* --strk(2005-02-06);
*/
template <class T>
void
applyComponentFilter(T& f) const
{
for(std::size_t i = 0, n = getNumGeometries(); i < n; ++i) {
f.filter(getGeometryN(i));
}
}
/**
* Reorganizes this Geometry into normal form (or canonical form).
* Starting point of rings is lower left, collections are ordered
* by geometry type, etc.
*/
virtual void normalize() = 0; //Abstract
/// Comparator for sorting geometry
virtual int compareTo(const Geometry* geom) const;
/// Returns the area of this Geometry.
virtual double getArea() const;
/// Returns the length of this Geometry.
virtual double getLength() const;
/** Returns the minimum distance between this Geometry and the Geometry g
*
* @param g the Geometry to calculate distance to
* @return the distance in cartesian units
*/
virtual double distance(const Geometry* g) const;
/** \brief
* Tests whether the distance from this Geometry to another
* is less than or equal to a specified value.
*
* @param geom the Geometry to check the distance to
* @param cDistance the distance value to compare
* @return <code>true</code> if the geometries are less than
* <code>distance</code> apart.
*
* @todo doesn't seem to need being virtual, make it concrete
*/
virtual bool isWithinDistance(const Geometry* geom,
double cDistance) const;
/** \brief
* Computes the centroid of this <code>Geometry</code>.
*
* The centroid is equal to the centroid of the set of component
* Geometries of highest dimension (since the lower-dimension geometries
* contribute zero "weight" to the centroid)
*
* @return a {@link Point} which is the centroid of this Geometry
*/
virtual std::unique_ptr<Point> getCentroid() const;
/// Computes the centroid of this Geometry as a Coordinate
//
/// Returns false if centroid cannot be computed (EMPTY geometry)
///
virtual bool getCentroid(CoordinateXY& ret) const;
/** \brief
* Computes an interior point of this <code>Geometry</code>.
*
* An interior point is guaranteed to lie in the interior of the Geometry,
* if it possible to calculate such a point exactly. Otherwise,
* the point may lie on the boundary of the geometry.
*
* @return a Point which is in the interior of this Geometry, or
* null if the geometry doesn't have an interior (empty)
*/
std::unique_ptr<Point> getInteriorPoint() const;
/**
* \brief
* Notifies this Geometry that its Coordinates have been changed
* by an external party (using a CoordinateFilter, for example).
*/
virtual void geometryChanged();
/**
* \brief
* Notifies this Geometry that its Coordinates have been changed
* by an external party.
*/
virtual void geometryChangedAction() = 0;
protected:
/// Make a deep-copy of this Geometry
virtual Geometry* cloneImpl() const = 0;
/// Make a geometry with coordinates in reverse order
virtual Geometry* reverseImpl() const = 0;
/// Returns true if the array contains any non-empty Geometrys.
template<typename T>
static bool hasNonEmptyElements(const std::vector<T>* geometries) {
return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return !g->isEmpty(); });
}
/// Returns true if the CoordinateSequence contains any null elements.
static bool hasNullElements(const CoordinateSequence* list);
/// Returns true if the vector contains any null elements.
template<typename T>
static bool hasNullElements(const std::vector<T>* geometries) {
return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return g == nullptr; });
}
// static void reversePointOrder(CoordinateSequence* coordinates);
// static Coordinate& minCoordinate(CoordinateSequence* coordinates);
// static void scroll(CoordinateSequence* coordinates,Coordinate* firstCoordinate);
// static int indexOf(Coordinate* coordinate,CoordinateSequence* coordinates);
//
/** \brief
* Returns whether the two Geometrys are equal, from the point
* of view of the equalsExact method.
*/
virtual bool isEquivalentClass(const Geometry* other) const;
static void checkNotGeometryCollection(const Geometry* g);
virtual int compareToSameClass(const Geometry* geom) const = 0; //Abstract
template<typename T>
static int compare(const T& a, const T& b)
{
std::size_t i = 0;
std::size_t j = 0;
while(i < a.size() && j < b.size()) {
const auto& aGeom = *a[i];
const auto& bGeom = *b[j];
int comparison = aGeom.compareTo(&bGeom);
if(comparison != 0) {
return comparison;
}
i++;
j++;
}
if(i < a.size()) {
return 1;
}
if(j < b.size()) {
return -1;
}
return 0;
}
bool equal(const CoordinateXY& a, const CoordinateXY& b,
double tolerance) const;
int SRID;
Geometry(const Geometry& geom);
/** \brief
* Construct a geometry with the given GeometryFactory.
*
* Will keep a reference to the factory, so don't
* delete it until al Geometry objects referring to
* it are deleted.
*
* @param factory
*/
Geometry(const GeometryFactory* factory);
template<typename T>
static std::vector<std::unique_ptr<Geometry>> toGeometryArray(std::vector<std::unique_ptr<T>> && v) {
static_assert(std::is_base_of<Geometry, T>::value, "");
std::vector<std::unique_ptr<Geometry>> gv(v.size());
for (std::size_t i = 0; i < v.size(); i++) {
gv[i] = std::move(v[i]);
}
return gv;
}
static std::vector<std::unique_ptr<Geometry>> toGeometryArray(std::vector<std::unique_ptr<Geometry>> && v) {
return std::move(v);
}
protected:
virtual int getSortIndex() const = 0;
private:
class GEOS_DLL GeometryChangedFilter : public GeometryComponentFilter {
public:
void filter_rw(Geometry* geom) override;
};
static GeometryChangedFilter geometryChangedFilter;
/// The GeometryFactory used to create this Geometry
///
/// Externally owned
///
const GeometryFactory* _factory;
void* _userData;
};
/// \brief
/// Write the Well-known Binary representation of this Geometry
/// as an HEX string to the given output stream
///
GEOS_DLL std::ostream& operator<< (std::ostream& os, const Geometry& geom);
struct GEOS_DLL GeometryGreaterThen {
bool operator()(const Geometry* first, const Geometry* second);
};
/// Return current GEOS version
GEOS_DLL std::string geosversion();
/**
* \brief
* Return the version of JTS this GEOS
* release has been ported from.
*/
GEOS_DLL std::string jtsport();
// We use this instead of std::pair<unique_ptr<Geometry>> because C++11
// forbids that construct:
// http://lwg.github.com/issues/lwg-closed.html#2068
struct GeomPtrPair {
typedef std::unique_ptr<Geometry> GeomPtr;
GeomPtr first;
GeomPtr second;
};
} // namespace geos::geom
} // namespace geos
#ifdef _MSC_VER
#pragma warning(pop)
#endif