You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
7.6 KiB
C++
250 lines
7.6 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://geos.osgeo.org
|
|
*
|
|
* Copyright (C) 2010 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: operation/valid/IsValidOp.java r335 (JTS-1.12)
|
|
*
|
|
**********************************************************************/
|
|
|
|
#ifndef GEOS_OP_ISVALIDOP_H
|
|
#define GEOS_OP_ISVALIDOP_H
|
|
|
|
#include <geos/export.h>
|
|
|
|
#include <geos/operation/valid/TopologyValidationError.h> // for inlined destructor
|
|
|
|
// Forward declarations
|
|
namespace geos {
|
|
namespace util {
|
|
class TopologyValidationError;
|
|
}
|
|
namespace geom {
|
|
class CoordinateSequence;
|
|
class GeometryFactory;
|
|
class Geometry;
|
|
class Point;
|
|
class LinearRing;
|
|
class LineString;
|
|
class Polygon;
|
|
class GeometryCollection;
|
|
class MultiPolygon;
|
|
class MultiLineString;
|
|
}
|
|
namespace geomgraph {
|
|
class DirectedEdge;
|
|
class EdgeIntersectionList;
|
|
class PlanarGraph;
|
|
class GeometryGraph;
|
|
}
|
|
}
|
|
|
|
namespace geos {
|
|
namespace operation { // geos::operation
|
|
namespace valid { // geos::operation::valid
|
|
|
|
/** \brief
|
|
* Implements the algorithsm required to compute the <code>isValid()</code>
|
|
* method for [Geometrys](@ref geom::Geometry).
|
|
*/
|
|
class GEOS_DLL IsValidOp {
|
|
friend class Unload;
|
|
private:
|
|
/// the base Geometry to be validated
|
|
const geom::Geometry* parentGeometry;
|
|
|
|
bool isChecked;
|
|
|
|
// CHECKME: should this really be a pointer ?
|
|
TopologyValidationError* validErr;
|
|
|
|
// This is the version using 'isChecked' flag
|
|
void checkValid();
|
|
|
|
void checkValid(const geom::Geometry* g);
|
|
void checkValid(const geom::Point* g);
|
|
void checkValid(const geom::LinearRing* g);
|
|
void checkValid(const geom::LineString* g);
|
|
void checkValid(const geom::Polygon* g);
|
|
void checkValid(const geom::MultiPolygon* g);
|
|
void checkValid(const geom::GeometryCollection* gc);
|
|
void checkConsistentArea(geomgraph::GeometryGraph* graph);
|
|
|
|
|
|
/**
|
|
* Check that there is no ring which self-intersects
|
|
* (except of course at its endpoints).
|
|
* This is required by OGC topology rules (but not by other models
|
|
* such as ESRI SDE, which allow inverted shells and exverted holes).
|
|
*
|
|
* @param graph the topology graph of the geometry
|
|
*/
|
|
void checkNoSelfIntersectingRings(geomgraph::GeometryGraph* graph);
|
|
|
|
/**
|
|
* check that a ring does not self-intersect, except at its endpoints.
|
|
* Algorithm is to count the number of times each node along edge
|
|
* occurs.
|
|
* If any occur more than once, that must be a self-intersection.
|
|
*/
|
|
void checkNoSelfIntersectingRing(
|
|
geomgraph::EdgeIntersectionList& eiList);
|
|
|
|
void checkTooFewPoints(geomgraph::GeometryGraph* graph);
|
|
|
|
/**
|
|
* Test that each hole is inside the polygon shell.
|
|
* This routine assumes that the holes have previously been tested
|
|
* to ensure that all vertices lie on the shell or inside it.
|
|
* A simple test of a single point in the hole can be used,
|
|
* provide the point is chosen such that it does not lie on the
|
|
* boundary of the shell.
|
|
*
|
|
* @param p the polygon to be tested for hole inclusion
|
|
* @param graph a geomgraph::GeometryGraph incorporating the polygon
|
|
*/
|
|
void checkHolesInShell(const geom::Polygon* p,
|
|
geomgraph::GeometryGraph* graph);
|
|
|
|
/**
|
|
* Tests that no hole is nested inside another hole.
|
|
* This routine assumes that the holes are disjoint.
|
|
* To ensure this, holes have previously been tested
|
|
* to ensure that:
|
|
*
|
|
* - they do not partially overlap
|
|
* (checked by <code>checkRelateConsistency</code>)
|
|
* - they are not identical
|
|
* (checked by <code>checkRelateConsistency</code>)
|
|
*
|
|
*/
|
|
void checkHolesNotNested(const geom::Polygon* p,
|
|
geomgraph::GeometryGraph* graph);
|
|
|
|
/**
|
|
* Tests that no element polygon is wholly in the interior of another
|
|
* element polygon.
|
|
*
|
|
* Preconditions:
|
|
*
|
|
* - shells do not partially overlap
|
|
* - shells do not touch along an edge
|
|
* - no duplicate rings exist
|
|
*
|
|
* This routine relies on the fact that while polygon shells
|
|
* may touch at one or more vertices, they cannot touch at
|
|
* ALL vertices.
|
|
*/
|
|
void checkShellsNotNested(const geom::MultiPolygon* mp,
|
|
geomgraph::GeometryGraph* graph);
|
|
|
|
|
|
void checkConnectedInteriors(geomgraph::GeometryGraph& graph);
|
|
|
|
void checkInvalidCoordinates(const geom::CoordinateSequence* cs);
|
|
|
|
void checkInvalidCoordinates(const geom::Polygon* poly);
|
|
|
|
void checkClosedRings(const geom::Polygon* poly);
|
|
|
|
void checkClosedRing(const geom::LinearRing* ring);
|
|
|
|
bool isSelfTouchingRingFormingHoleValid;
|
|
|
|
public:
|
|
/** \brief
|
|
* Find a point from the list of testCoords
|
|
* that is NOT a node in the edge for the list of searchCoords
|
|
*
|
|
* @return the point found, or NULL if none found
|
|
*/
|
|
static const geom::Coordinate* findPtNotNode(
|
|
const geom::CoordinateSequence* testCoords,
|
|
const geom::LinearRing* searchRing,
|
|
const geomgraph::GeometryGraph* graph);
|
|
|
|
/** \brief
|
|
* Checks whether a coordinate is valid for processing.
|
|
* Coordinates are valid iff their x and y coordinates are in the
|
|
* range of the floating point representation.
|
|
*
|
|
* @param coord the coordinate to validate
|
|
* @return `true` if the coordinate is valid
|
|
*/
|
|
static bool isValid(const geom::Coordinate& coord);
|
|
|
|
/** \brief
|
|
* Tests whether a geom::Geometry is valid.
|
|
*
|
|
* @param geom the Geometry to test
|
|
* @return `true` if the geometry is valid
|
|
*/
|
|
static bool isValid(const geom::Geometry& geom);
|
|
|
|
IsValidOp(const geom::Geometry* geom)
|
|
:
|
|
parentGeometry(geom),
|
|
isChecked(false),
|
|
validErr(nullptr),
|
|
isSelfTouchingRingFormingHoleValid(false)
|
|
{}
|
|
|
|
/// TODO: validErr can't be a pointer!
|
|
virtual
|
|
~IsValidOp()
|
|
{
|
|
delete validErr;
|
|
}
|
|
|
|
bool isValid();
|
|
|
|
TopologyValidationError* getValidationError();
|
|
|
|
/** \brief
|
|
* Sets whether polygons using **Self-Touching Rings** to form
|
|
* holes are reported as valid.
|
|
*
|
|
* If this flag is set, the following Self-Touching conditions
|
|
* are treated as being valid:
|
|
*
|
|
* - the shell ring self-touches to create a hole touching the shell
|
|
* - a hole ring self-touches to create two holes touching at a point
|
|
*
|
|
* The default (following the OGC SFS standard)
|
|
* is that this condition is **not** valid (`false`).
|
|
*
|
|
* This does not affect whether Self-Touching Rings
|
|
* disconnecting the polygon interior are considered valid
|
|
* (these are considered to be **invalid** under the SFS,
|
|
* and many other spatial models as well).
|
|
* This includes "bow-tie" shells, which self-touch at a single point
|
|
* causing the interior to be disconnected, and "C-shaped" holes which
|
|
* self-touch at a single point causing an island to be formed.
|
|
*
|
|
* @param p_isValid states whether geometry with this condition is valid
|
|
*/
|
|
void
|
|
setSelfTouchingRingFormingHoleValid(bool p_isValid)
|
|
{
|
|
isSelfTouchingRingFormingHoleValid = p_isValid;
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace geos.operation.valid
|
|
} // namespace geos.operation
|
|
} // namespace geos
|
|
|
|
#endif // GEOS_OP_ISVALIDOP_H
|