DYT/Tool/OpenSceneGraph-3.6.5/include/geos/operation/buffer/BufferCurveSetBuilder.h

297 lines
9.9 KiB
C
Raw Normal View History

2024-12-24 23:49:36 +00:00
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
* Copyright (C) 2006 Refractions Research 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/buffer/BufferCurveSetBuilder.java 4c343e79f (JTS-1.19)
*
**********************************************************************/
#pragma once
#include <geos/export.h>
#include <geos/geom/Location.h>
#include <geos/operation/buffer/OffsetCurveBuilder.h>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
#endif
// Forward declarations
namespace geos {
namespace geom {
class Geometry;
class CoordinateSequence;
class PrecisionModel;
class GeometryCollection;
class Point;
class LineString;
class LinearRing;
class Polygon;
}
namespace geomgraph {
class Label;
}
namespace noding {
class SegmentString;
}
namespace operation {
namespace buffer {
class BufferParameters;
}
}
}
namespace geos {
namespace operation { // geos.operation
namespace buffer { // geos.operation.buffer
/**
* \class BufferCurveSetBuilder
*
* \brief
* Creates all the raw offset curves for a buffer of a Geometry.
*
* Raw curves need to be noded together and polygonized to form the
* final buffer area.
*
*/
class GEOS_DLL BufferCurveSetBuilder {
private:
static constexpr int MAX_INVERTED_RING_SIZE = 9;
static constexpr int INVERTED_CURVE_VERTEX_FACTOR = 4;
static constexpr double NEARNESS_FACTOR = 0.99;
// To keep track of newly-created Labels.
// Labels will be released by object dtor
std::vector<geomgraph::Label*> newLabels;
const geom::Geometry& inputGeom;
double distance;
OffsetCurveBuilder curveBuilder;
/// The raw offset curves computed.
/// This class holds ownership of std::vector elements.
///
std::vector<noding::SegmentString*> curveList;
bool isInvertOrientation = false;
/**
* Creates a noding::SegmentString for a coordinate list which is a raw
* offset curve, and adds it to the list of buffer curves.
* The noding::SegmentString is tagged with a geomgraph::Label
* giving the topology of the curve.
* The curve may be oriented in either direction.
* If the curve is oriented CW, the locations will be:
* - Left: Location.EXTERIOR
* - Right: Location.INTERIOR
*
* @param coord is raw offset curve, ownership transferred here
*/
void addCurve(geom::CoordinateSequence* coord, geom::Location leftLoc,
geom::Location rightLoc);
void add(const geom::Geometry& g);
void addCollection(const geom::GeometryCollection* gc);
/**
* Add a Point to the graph.
*/
void addPoint(const geom::Point* p);
void addLineString(const geom::LineString* line);
void addPolygon(const geom::Polygon* p);
void addRingBothSides(const geom::CoordinateSequence* coord, double p_distance);
/**
* Add an offset curve for a polygon ring.
* The side and left and right topological location arguments
* assume that the ring is oriented CW.
* If the ring is in the opposite orientation,
* the left and right locations must be interchanged and the side
* flipped.
*
* @param coord the coordinates of the ring (must not contain
* repeated points)
* @param offsetDistance the distance at which to create the buffer
* @param side the side of the ring on which to construct the buffer
* line
* @param cwLeftLoc the location on the L side of the ring
* (if it is CW)
* @param cwRightLoc the location on the R side of the ring
* (if it is CW)
*/
void addRingSide(const geom::CoordinateSequence* coord,
double offsetDistance, int side, geom::Location cwLeftLoc,
geom::Location cwRightLoc);
/**
* Tests whether the offset curve for a ring is fully inverted.
* An inverted ("inside-out") curve occurs in some specific situations
* involving a buffer distance which should result in a fully-eroded (empty) buffer.
* It can happen that the sides of a small, convex polygon
* produce offset segments which all cross one another to form
* a curve with inverted orientation.
* This happens at buffer distances slightly greater than the distance at
* which the buffer should disappear.
* The inverted curve will produce an incorrect non-empty buffer (for a shell)
* or an incorrect hole (for a hole).
* It must be discarded from the set of offset curves used in the buffer.
* Heuristics are used to reduce the number of cases which area checked,
* for efficiency and correctness.
* <p>
* See https://github.com/locationtech/jts/issues/472
*
* @param inputPts the input ring
* @param distance the buffer distance
* @param curvePts the generated offset curve
* @return true if the offset curve is inverted
*/
static bool isRingCurveInverted(
const geom::CoordinateSequence* inputPts, double dist,
const geom::CoordinateSequence* curvePts);
/**
* Tests if there are points on the raw offset curve which may
* lie on the final buffer curve
* (i.e. they are (approximately) at the buffer distance from the input ring).
* For efficiency this only tests a limited set of points on the curve.
*
* @param inputRing
* @param distance
* @param curveRing
* @return true if the curve contains points lying at the required buffer distance
*/
static bool hasPointOnBuffer(
const CoordinateSequence* inputRing, double dist,
const CoordinateSequence* curveRing);
/**
* The ringCoord is assumed to contain no repeated points.
* It may be degenerate (i.e. contain only 1, 2, or 3 points).
* In this case it has no area, and hence has a minimum diameter of 0.
*
* @param ringCoord
* @param bufferDistance
* @return
*/
bool isErodedCompletely(const geom::LinearRing* ringCoord,
double bufferDistance);
/**
* Tests whether a triangular ring would be eroded completely by
* the given buffer distance.
* This is a precise test. It uses the fact that the inner buffer
* of a triangle converges on the inCentre of the triangle (the
* point equidistant from all sides). If the buffer distance is
* greater than the distance of the inCentre from a side, the
* triangle will be eroded completely.
*
* This test is important, since it removes a problematic case where
* the buffer distance is slightly larger than the inCentre distance.
* In this case the triangle buffer curve "inverts" with incorrect
* topology, producing an incorrect hole in the buffer.
*
* @param triCoord
* @param bufferDistance
* @return
*/
bool isTriangleErodedCompletely(const geom::CoordinateSequence* triCoords,
double bufferDistance);
// Declare type as noncopyable
BufferCurveSetBuilder(const BufferCurveSetBuilder& other) = delete;
BufferCurveSetBuilder& operator=(const BufferCurveSetBuilder& rhs) = delete;
/**
* Computes orientation of a ring using a signed-area orientation test.
* For invalid (self-crossing) rings this ensures the largest enclosed area
* is taken to be the interior of the ring.
* This produces a more sensible result when
* used for repairing polygonal geometry via buffer-by-zero.
* For buffer, using the lower robustness of orientation-by-area
* doesn't matter, since narrow or flat rings
* produce an acceptable offset curve for either orientation.
*
* @param coord the ring coordinates
* @return true if the ring is CCW
*/
bool isRingCCW(const geom::CoordinateSequence* coords) const;
public:
/// Constructor
BufferCurveSetBuilder(
const geom::Geometry& newInputGeom,
double newDistance,
const geom::PrecisionModel* newPm,
const BufferParameters& newBufParams)
: inputGeom(newInputGeom)
, distance(newDistance)
, curveBuilder(newPm, newBufParams)
, curveList()
, isInvertOrientation(false)
{};
/// Destructor
~BufferCurveSetBuilder();
/** \brief
* Computes the set of raw offset curves for the buffer.
*
* Each offset curve has an attached {@link geomgraph::Label} indicating
* its left and right location.
*
* @return a Collection of SegmentStrings representing the raw buffer curves
*/
std::vector<noding::SegmentString*>& getCurves();
/// \brief Add raw curves for a set of CoordinateSequences.
///
/// @param lineList is a list of CoordinateSequence, ownership
/// of which is transferred here
/// @param leftLoc left location
/// @param rightLoc right location
///
void addCurves(const std::vector<geom::CoordinateSequence*>& lineList,
geom::Location leftLoc, geom::Location rightLoc);
/**
* Sets whether the offset curve is generated
* using the inverted orientation of input rings.
* This allows generating a buffer(0) polygon from the smaller lobes
* of self-crossing rings.
*
* @param p_isInvertOrientation true if input ring orientation should be inverted
*/
void setInvertOrientation(bool p_isInvertOrientation) {
isInvertOrientation = p_isInvertOrientation;
}
};
} // namespace geos::operation::buffer
} // namespace geos::operation
} // namespace geos
#ifdef _MSC_VER
#pragma warning(pop)
#endif