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

391 lines
12 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
*
* 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/OffsetSegmentGenerator.java r378 (JTS-1.12)
*
**********************************************************************/
#pragma once
#include <geos/export.h>
#include <vector>
#include <geos/algorithm/LineIntersector.h> // for composition
#include <geos/geom/Coordinate.h> // for composition
#include <geos/geom/LineSegment.h> // for composition
#include <geos/operation/buffer/BufferParameters.h> // for composition
#include <geos/operation/buffer/OffsetSegmentString.h> // for composition
#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 CoordinateSequence;
class PrecisionModel;
}
}
namespace geos {
namespace operation { // geos.operation
namespace buffer { // geos.operation.buffer
/**
* Generates segments which form an offset curve.
* Supports all end cap and join options
* provided for buffering.
* Implements various heuristics to
* produce smoother, simpler curves which are
* still within a reasonable tolerance of the
* true curve.
*
* @author Martin Davis
*
*/
class GEOS_DLL OffsetSegmentGenerator {
public:
/*
* @param nBufParams buffer parameters, this object will
* keep a reference to the passed parameters
* so caller must make sure the object is
* kept alive for the whole lifetime of
* the buffer builder.
*/
OffsetSegmentGenerator(const geom::PrecisionModel* newPrecisionModel,
const BufferParameters& bufParams, double distance);
/**
* Tests whether the input has a narrow concave angle
* (relative to the offset distance).
* In this case the generated offset curve will contain self-intersections
* and heuristic closing segments.
* This is expected behaviour in the case of buffer curves.
* For pure offset curves,
* the output needs to be further treated
* before it can be used.
*
* @return true if the input has a narrow concave angle
*/
bool
hasNarrowConcaveAngle() const
{
return _hasNarrowConcaveAngle;
}
void initSideSegments(const geom::Coordinate& nS1,
const geom::Coordinate& nS2, int nSide);
/// Get coordinates by taking ownership of them
///
/// After this call, the coordinates reference in
/// this object are dropped. Calling twice will
/// segfault...
///
/// FIXME: refactor memory management of this
///
void
getCoordinates(std::vector<geom::CoordinateSequence*>& to)
{
to.push_back(segList.getCoordinates());
}
std::unique_ptr<geom::CoordinateSequence>
getCoordinates()
{
return std::unique_ptr<geom::CoordinateSequence>(segList.getCoordinates());
}
void
closeRing()
{
segList.closeRing();
}
/// Adds a CW circle around a point
void createCircle(const geom::Coordinate& p, double distance);
/// Adds a CW square around a point
void createSquare(const geom::Coordinate& p, double distance);
/// Add first offset point
void
addFirstSegment()
{
segList.addPt(offset1.p0);
}
/// Add last offset point
void
addLastSegment()
{
segList.addPt(offset1.p1);
}
void addNextSegment(const geom::Coordinate& p, bool addStartPoint);
/// \brief
/// Add an end cap around point p1, terminating a line segment
/// coming from p0
void addLineEndCap(const geom::Coordinate& p0,
const geom::Coordinate& p1);
void
addSegments(const geom::CoordinateSequence& pts, bool isForward)
{
segList.addPts(pts, isForward);
}
/** \brief
* Compute an offset segment for an input segment on a given
* side and at a given distance.
*
* The offset points are computed in full double precision,
* for accuracy.
*
* @param seg the segment to offset
* @param side the side of the segment the offset lies on
* @param distance the offset distance
* @param offset the points computed for the offset segment
*/
static void computeOffsetSegment(const geom::LineSegment& seg,
int side, double distance,
geom::LineSegment& offset);
private:
/**
* Factor which controls how close offset segments can be to
* skip adding a filler or mitre.
*/
static const double OFFSET_SEGMENT_SEPARATION_FACTOR; // 1.0E-3;
/**
* Factor which controls how close curve vertices on inside turns
* can be to be snapped
*/
static const double INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR; // 1.0E-3;
/**
* Factor which controls how close curve vertices can be to be snapped
*/
static const double CURVE_VERTEX_SNAP_DISTANCE_FACTOR; // 1.0E-6;
/**
* Factor which determines how short closing segs can be for round buffers
*/
static const int MAX_CLOSING_SEG_LEN_FACTOR = 80;
/** \brief
* the max error of approximation (distance) between a quad segment and
* the true fillet curve
*/
double maxCurveSegmentError; // 0.0
/** \brief
* The angle quantum with which to approximate a fillet curve
* (based on the input # of quadrant segments)
*/
double filletAngleQuantum;
/// The Closing Segment Factor controls how long "closing
/// segments" are. Closing segments are added at the middle of
/// inside corners to ensure a smoother boundary for the buffer
/// offset curve. In some cases (particularly for round joins
/// with default-or-better quantization) the closing segments
/// can be made quite short. This substantially improves
/// performance (due to fewer intersections being created).
///
/// A closingSegFactor of 0 results in lines to the corner vertex.
/// A closingSegFactor of 1 results in lines halfway
/// to the corner vertex.
/// A closingSegFactor of 80 results in lines 1/81 of the way
/// to the corner vertex (this option is reasonable for the very
/// common default situation of round joins and quadrantSegs >= 8).
///
/// The default is 1.
///
int closingSegLengthFactor; // 1;
/// Owned by this object, destroyed by dtor
///
/// This actually gets created multiple times
/// and each of the old versions is pushed
/// to the ptLists std::vector to ensure all
/// created CoordinateSequences are properly
/// destroyed.
///
OffsetSegmentString segList;
double distance;
const geom::PrecisionModel* precisionModel;
const BufferParameters& bufParams;
algorithm::LineIntersector li;
geom::Coordinate s0, s1, s2;
geom::LineSegment seg0;
geom::LineSegment seg1;
geom::LineSegment offset0;
geom::LineSegment offset1;
int side;
bool _hasNarrowConcaveAngle; // =false
void addCollinear(bool addStartPoint);
/// The mitre will be beveled if it exceeds the mitre ratio limit.
///
/// @param offset0 the first offset segment
/// @param offset1 the second offset segment
/// @param distance the offset distance
///
void addMitreJoin(const geom::Coordinate& cornerPt,
const geom::LineSegment& offset0,
const geom::LineSegment& offset1,
double distance);
/// Adds a limited mitre join connecting two convex offset segments.
/// A limited mitre join is beveled at the distance
/// determined by the mitre limit factor,
/// or as a standard bevel join, whichever is further.
///
/// @param offset0 the first offset segment
/// @param offset1 the second offset segment
/// @param distance the offset distance
/// @param mitreLimitDistance the mitre limit ratio
///
void addLimitedMitreJoin(
const geom::LineSegment& offset0,
const geom::LineSegment& offset1,
double distance,
double mitreLimitDistance);
/**
* Extends a line segment forwards or backwards a given distance.
*
* @param seg the base line segment
* @param dist the distance to extend by
* @return the extended segment
*/
static geom::LineSegment extend(const geom::LineSegment& seg, double dist);
/**
* Adds a bevel join connecting the two offset segments
* around a reflex corner.
* Projects a point to a given distance in a given direction angle.
*
* @param pt the point to project
* @param d the projection distance
* @param dir the direction angle (in radians)
* @return the projected point
*/
static geom::Coordinate project(const geom::Coordinate& pt, double d, double dir);
/// \brief
/// Adds a bevel join connecting the two offset segments
/// around a reflex corner.
///
/// @param offset0 the first offset segment
/// @param offset1 the second offset segment
///
void addBevelJoin(const geom::LineSegment& offset0,
const geom::LineSegment& offset1);
static const double PI; // 3.14159265358979
// Not in JTS, used for single-sided buffers
int endCapIndex;
void init(double newDistance);
/**
* Use a value which results in a potential distance error which is
* significantly less than the error due to
* the quadrant segment discretization.
* For QS = 8 a value of 100 is reasonable.
* This should produce a maximum of 1% distance error.
*/
static const double SIMPLIFY_FACTOR; // 100.0;
/// Adds the offset points for an outside (convex) turn
///
/// @param orientation
/// @param addStartPoint
///
void addOutsideTurn(int orientation, bool addStartPoint);
/// Adds the offset points for an inside (concave) turn
///
/// @param orientation
/// @param addStartPoint
///
void addInsideTurn(int orientation, bool addStartPoint);
/**
* Adds points for a circular fillet around a reflex corner.
*
* Adds the start and end points
*
* @param p base point of curve
* @param p0 start point of fillet curve
* @param p1 endpoint of fillet curve
* @param direction the orientation of the fillet
* @param radius the radius of the fillet
*/
void addDirectedFillet(const geom::Coordinate& p, const geom::Coordinate& p0,
const geom::Coordinate& p1,
int direction, double radius);
/**
* Adds points for a circular fillet arc between two specified angles.
*
* The start and end point for the fillet are not added -
* the caller must add them if required.
*
* @param direction is -1 for a CW angle, 1 for a CCW angle
* @param radius the radius of the fillet
*/
void addDirectedFillet(const geom::Coordinate& p, double startAngle,
double endAngle, int direction, double radius);
private:
// An OffsetSegmentGenerator cannot be copied because of member "const BufferParameters& bufParams"
// Not declaring these functions triggers MSVC warning C4512: "assignment operator could not be generated"
OffsetSegmentGenerator(const OffsetSegmentGenerator&);
void operator=(const OffsetSegmentGenerator&);
};
} // namespace geos::operation::buffer
} // namespace geos::operation
} // namespace geos
#ifdef _MSC_VER
#pragma warning(pop)
#endif