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

263 lines
7.3 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* 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.
*
**********************************************************************/
#pragma once
#include <geos/noding/SegmentIntersector.h> // for inheritance
#include <geos/geom/Coordinate.h> // for composition
#include <geos/noding/SegmentString.h>
#include <vector>
// Forward declarations
namespace geos {
namespace algorithm {
class LineIntersector;
}
namespace noding {
class SegmentString;
}
}
namespace geos {
namespace noding { // geos.noding
/**
* \brief Finds non-noded intersections in a set of {@link SegmentString}s, if any exist.
*
* Non-noded intersections include:
*
* - intersections which lie in the interior of a segment
* - intersections at a vertex in the interior of a SegmentString
* (e.g. with a segment string endpoint or other interior vertex)
*
* @version 1.7
*/
class NodingIntersectionFinder: public SegmentIntersector {
public:
/** \brief
* Creates an intersection finder which finds an interior intersection
* if one exists
*
* @param newLi the LineIntersector to use
*/
NodingIntersectionFinder(algorithm::LineIntersector& newLi)
:
li(newLi),
interiorIntersection(geom::Coordinate::getNull()),
intersectionCount(0),
isCheckEndSegmentsOnly(false),
findAllIntersections(false)
{
}
/** \brief
* Tests whether an intersection was found.
*
* @return true if an intersection was found
*/
bool
hasIntersection() const
{
return !interiorIntersection.isNull();
}
/** \brief
* Gets the computed location of the intersection.
* Due to round-off, the location may not be exact.
*
* @return the coordinate for the intersection location
*/
const geom::Coordinate&
getInteriorIntersection() const
{
return interiorIntersection;
}
/** \brief
* Gets the count of intersections found.
*
* @return the intersection count
*/
size_t
count() const
{
return intersectionCount;
}
/** \brief
* Sets whether only end segments should be tested for interior intersection.
*
* This is a performance optimization that may be used if the segments
* have been previously noded by an appropriate algorithm.
* It may be known that any potential noding failures will occur only in
* end segments.
*
* @param isCESO whether to test only end segments
*/
void
setCheckEndSegmentsOnly(bool isCESO)
{
isCheckEndSegmentsOnly = isCESO;
}
/** \brief
* Sets whether all intersections should be computed.
*
* When this is `false` (the default value) the value of
* #isDone() is `true` after the first intersection is found.
*
* Default is `false`.
*
* @param fAI whether all intersections should be computed
*/
void
setFindAllIntersections(bool fAI)
{
findAllIntersections = fAI;
}
/** \brief
* Gets the endpoints of the intersecting segments.
*
* @return an array of the segment endpoints (p00, p01, p10, p11)
*/
const std::vector<geom::Coordinate>&
getIntersectionSegments() const
{
return intSegments;
}
/** \brief
* This method is called by clients of the SegmentIntersector class to process
* intersections for two segments of the [SegmentStrings](@ref SegmentString)
* being intersected.
*
* @note Some clients (such as `MonotoneChains`) may optimize away
* this call for segment pairs which they have determined do not intersect
* (e.g. by an disjoint envelope test).
*/
void processIntersections(
SegmentString* e0, std::size_t segIndex0,
SegmentString* e1, std::size_t segIndex1) override;
bool
isDone() const override
{
return !interiorIntersection.isNull();
}
private:
algorithm::LineIntersector& li;
geom::Coordinate interiorIntersection;
std::size_t intersectionCount;
bool isCheckEndSegmentsOnly;
bool findAllIntersections;
std::vector<geom::Coordinate> intSegments;
// Declare type as noncopyable
NodingIntersectionFinder(const NodingIntersectionFinder& other) = delete;
NodingIntersectionFinder& operator=(const NodingIntersectionFinder& rhs) = delete;
/** \brief
* Tests if two vertices with at least one in a segmentString interior
* are equal.
*
* @param p0 a segment vertex
* @param p1 a segment vertex
* @param isEnd0 true if vertex is a segmentString endpoint
* @param isEnd1 true if vertex is a segmentString endpoint
* @return true if an intersection is found
*/
static bool isInteriorVertexIntersection(
const geom::Coordinate& p0, const geom::Coordinate& p1,
bool isEnd0, bool isEnd1)
{
// Intersections between endpoints are valid nodes, so not reported
if (isEnd0 && isEnd1) {
return false;
}
if (p0.equals2D(p1)) {
return true;
}
return false;
};
/** \brief
* Tests if an intersection occurs between a SegmentString interior vertex and another vertex.
*
* @note intersections between two endpoint vertices are valid noding,
* and are not flagged.
*
* @param p00 a segment vertex
* @param p01 a segment vertex
* @param p10 a segment vertex
* @param p11 a segment vertex
* @param isEnd00 true if vertex is a segmentString endpoint
* @param isEnd01 true if vertex is a segmentString endpoint
* @param isEnd10 true if vertex is a segmentString endpoint
* @param isEnd11 true if vertex is a segmentString endpoint
* @return true if an intersection is found
*/
static bool isInteriorVertexIntersection(
const geom::Coordinate& p00, const geom::Coordinate& p01,
const geom::Coordinate& p10, const geom::Coordinate& p11,
bool isEnd00, bool isEnd01, bool isEnd10, bool isEnd11)
{
if (isInteriorVertexIntersection(p00, p10, isEnd00, isEnd10)) {
return true;
}
if (isInteriorVertexIntersection(p00, p11, isEnd00, isEnd11)) {
return true;
}
if (isInteriorVertexIntersection(p01, p10, isEnd01, isEnd10)) {
return true;
}
if (isInteriorVertexIntersection(p01, p11, isEnd01, isEnd11)) {
return true;
}
return false;
};
/** \brief
* Tests whether a segment in a SegmentString is an end segment.
* (either the first or last).
*
* @param segStr a segment string
* @param index the index of a segment in the segment string
* @return true if the segment is an end segment
*/
static bool isEndSegment(const SegmentString* segStr, std::size_t index)
{
if (index == 0) {
return true;
}
if (index >= segStr->size() - 2) {
return true;
}
return false;
};
};
} // namespace geos.noding
} // namespace geos