150 lines
4.8 KiB
C++
150 lines
4.8 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://libgeos.org
|
|
*
|
|
* Copyright (c) 2021 Martin Davis
|
|
* Copyright (C) 2022 Paul Ramsey <pramsey@cleverlephant.ca>
|
|
*
|
|
* 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/export.h>
|
|
|
|
|
|
// Forward declarations
|
|
namespace geos {
|
|
namespace geom {
|
|
class CoordinateXY;
|
|
}
|
|
}
|
|
|
|
using geos::geom::CoordinateXY;
|
|
|
|
|
|
namespace geos {
|
|
namespace algorithm { // geos::algorithm
|
|
|
|
/**
|
|
* Functions to compute topological information
|
|
* about nodes (ring intersections) in polygonal geometry.
|
|
*
|
|
* @author mdavis
|
|
*
|
|
*/
|
|
class GEOS_DLL PolygonNodeTopology {
|
|
|
|
public:
|
|
|
|
/*
|
|
* Check if the segments at a node between two rings (or one ring) cross.
|
|
* The node is topologically valid if the rings do not cross.
|
|
* This function assumes that the segments are not collinear.
|
|
*
|
|
* @param nodePt the node location
|
|
* @param a0 the previous segment endpoint in a ring
|
|
* @param a1 the next segment endpoint in a ring
|
|
* @param b0 the previous segment endpoint in the other ring
|
|
* @param b1 the next segment endpoint in the other ring
|
|
* @return true if the rings cross at the node
|
|
*/
|
|
static bool
|
|
isCrossing(const CoordinateXY* nodePt,
|
|
const CoordinateXY* a0, const CoordinateXY* a1,
|
|
const CoordinateXY* b0, const CoordinateXY* b1);
|
|
|
|
|
|
/**
|
|
* Tests whether an segment node-b lies in the interior or exterior
|
|
* of a corner of a ring formed by the two segments a0-node-a1.
|
|
* The ring interior is assumed to be on the right of the corner
|
|
* (i.e. a CW shell or CCW hole).
|
|
* The test segment must not be collinear with the corner segments.
|
|
*
|
|
* @param nodePt the node location
|
|
* @param a0 the first vertex of the corner
|
|
* @param a1 the second vertex of the corner
|
|
* @param b the other vertex of the test segment
|
|
* @return true if the segment is interior to the ring corner
|
|
*/
|
|
static bool isInteriorSegment(const CoordinateXY* nodePt,
|
|
const CoordinateXY* a0, const CoordinateXY* a1, const CoordinateXY* b);
|
|
|
|
/**
|
|
* Compares the angles of two vectors
|
|
* relative to the positive X-axis at their origin.
|
|
* Angles increase CCW from the X-axis.
|
|
*
|
|
* @param origin the origin of the vectors
|
|
* @param p the endpoint of the vector P
|
|
* @param q the endpoint of the vector Q
|
|
* @return a negative integer, zero, or a positive integer as this vector P has angle less than, equal to, or greater than vector Q
|
|
*/
|
|
static int compareAngle(
|
|
const CoordinateXY* origin,
|
|
const CoordinateXY* p,
|
|
const CoordinateXY* q);
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
* Tests if an edge p is between edges e0 and e1,
|
|
* where the edges all originate at a common origin.
|
|
* The "inside" of e0 and e1 is the arc which does not include the origin.
|
|
* The edges are assumed to be distinct (non-collinear).
|
|
*
|
|
* @param origin the origin
|
|
* @param p the destination point of edge p
|
|
* @param e0 the destination point of edge e0
|
|
* @param e1 the destination point of edge e1
|
|
* @return true if p is between e0 and e1
|
|
*/
|
|
static bool isBetween(const CoordinateXY* origin,
|
|
const CoordinateXY* p,
|
|
const CoordinateXY* e0, const CoordinateXY* e1);
|
|
|
|
/**
|
|
* Compares whether an edge p is between or outside the edges e0 and e1,
|
|
* where the edges all originate at a common origin.
|
|
* The "inside" of e0 and e1 is the arc which does not include
|
|
* the positive X-axis at the origin.
|
|
* If p is collinear with an edge 0 is returned.
|
|
*
|
|
* @param origin the origin
|
|
* @param p the destination point of edge p
|
|
* @param e0 the destination point of edge e0
|
|
* @param e1 the destination point of edge e1
|
|
* @return a negative integer, zero or positive integer as the vector P lies outside, collinear with, or inside the vectors E0 and E1
|
|
*/
|
|
static int compareBetween(const CoordinateXY* origin, const CoordinateXY* p,
|
|
const CoordinateXY* e0, const CoordinateXY* e1);
|
|
|
|
|
|
/**
|
|
* Tests if the angle with the origin of a vector P is greater than that of the
|
|
* vector Q.
|
|
*
|
|
* @param origin the origin of the vectors
|
|
* @param p the endpoint of the vector P
|
|
* @param q the endpoint of the vector Q
|
|
* @return true if vector P has angle greater than Q
|
|
*/
|
|
static bool isAngleGreater(const CoordinateXY* origin, const CoordinateXY* p, const CoordinateXY* q);
|
|
|
|
static int quadrant(const CoordinateXY* origin, const CoordinateXY* p);
|
|
|
|
|
|
};
|
|
|
|
|
|
} // namespace geos::algorithm
|
|
} // namespace geos
|
|
|