444 lines
11 KiB
C++
444 lines
11 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://geos.osgeo.org
|
|
*
|
|
* Copyright (C) 2012 Excensus LLC.
|
|
* Copyright (C) 2019 Daniel Baston
|
|
*
|
|
* This is free software; you can redistribute and/or modify it under
|
|
* the terms of the GNU Lesser General Licence as published
|
|
* by the Free Software Foundation.
|
|
* See the COPYING file for more information.
|
|
*
|
|
**********************************************************************
|
|
*
|
|
* Last port: triangulate/quadedge/QuadEdge.java r524
|
|
*
|
|
**********************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
|
|
#include <geos/triangulate/quadedge/Vertex.h>
|
|
#include <geos/geom/LineSegment.h>
|
|
|
|
namespace geos {
|
|
namespace triangulate { //geos.triangulate
|
|
namespace quadedge { //geos.triangulate.quadedge
|
|
|
|
|
|
class GEOS_DLL QuadEdgeQuartet;
|
|
|
|
/** \brief
|
|
* A class that represents the edge data structure which implements the quadedge algebra.
|
|
*
|
|
* The quadedge algebra was described in a well-known paper by Guibas and Stolfi,
|
|
* "Primitives for the manipulation of general subdivisions and the computation of Voronoi diagrams",
|
|
* *ACM Transactions on Graphics*, 4(2), 1985, 75-123.
|
|
*
|
|
* Each edge object is part of a QuadEdgeQuartet of 4 edges, linked via relative memory addresses.
|
|
* Quadedges in a subdivision are linked together via their `next` references.
|
|
* The linkage between the quadedge quartets determines the topology
|
|
* of the subdivision.
|
|
*
|
|
* The edge class does not contain separate information for vertice or faces; a vertex is implicitly
|
|
* defined as a ring of edges (created using the `next` field).
|
|
*
|
|
* @author JTS: David Skea
|
|
* @author JTS: Martin Davis
|
|
* @author Benjamin Campbell
|
|
* */
|
|
class GEOS_DLL QuadEdge {
|
|
friend class QuadEdgeQuartet;
|
|
public:
|
|
/** \brief
|
|
* Creates a new QuadEdge quartet from {@link Vertex} o to {@link Vertex} d.
|
|
*
|
|
* @param o the origin Vertex
|
|
* @param d the destination Vertex
|
|
* @param edges a container in which to store the newly created quartet
|
|
* @return the new QuadEdge*,
|
|
*/
|
|
static QuadEdge* makeEdge(const Vertex& o, const Vertex & d, std::deque<QuadEdgeQuartet> & edges);
|
|
|
|
/** \brief
|
|
* Creates a new QuadEdge connecting the destination of a to the origin of
|
|
* b, in such a way that all three have the same left face after the
|
|
* connection is complete.
|
|
*
|
|
* Additionally, the data pointers of the new edge are set.
|
|
*
|
|
* @return the new QuadEdge*
|
|
*/
|
|
static QuadEdge* connect(QuadEdge& a, QuadEdge& b, std::deque<QuadEdgeQuartet> & edges);
|
|
|
|
/** \brief
|
|
* Splices two edges together or apart.
|
|
*
|
|
* Splice affects the two edge rings around the origins of a and b, and, independently, the two
|
|
* edge rings around the left faces of `a` and `b`.
|
|
* In each case, (i) if the two rings are distinct,
|
|
* Splice will combine them into one, or (ii) if the two are the same ring, Splice will break it
|
|
* into two separate pieces. Thus, Splice can be used both to attach the two edges together, and
|
|
* to break them apart.
|
|
*
|
|
* @param a an edge to splice
|
|
* @param b an edge to splice
|
|
*
|
|
*/
|
|
static void splice(QuadEdge& a, QuadEdge& b);
|
|
|
|
/** \brief
|
|
* Turns an edge counterclockwise inside its enclosing quadrilateral.
|
|
*
|
|
* @param e the quadedge to turn
|
|
*/
|
|
static void swap(QuadEdge& e);
|
|
|
|
private:
|
|
//// the dual of this edge, directed from right to left
|
|
Vertex vertex; // The vertex that this edge represents
|
|
QuadEdge* next; // A reference to a connected edge
|
|
|
|
int8_t num; // the position of the QuadEdge in the quartet (0-3)
|
|
|
|
bool isAlive;
|
|
bool visited;
|
|
|
|
/**
|
|
* Quadedges must be made using {@link QuadEdgeQuartet::makeEdge},
|
|
* to ensure proper construction.
|
|
*/
|
|
explicit QuadEdge(int8_t _num) :
|
|
next(nullptr),
|
|
num(_num),
|
|
isAlive(true),
|
|
visited(false) {
|
|
}
|
|
|
|
public:
|
|
/** \brief
|
|
* Gets the primary edge of this quadedge and its `sym`.
|
|
*
|
|
* The primary edge is the one for which the origin
|
|
* and destination coordinates are ordered
|
|
* according to the standard geom::Coordinate ordering
|
|
*
|
|
* @return the primary quadedge
|
|
*/
|
|
const QuadEdge& getPrimary();
|
|
|
|
/** \brief
|
|
* Marks this quadedge as being deleted.
|
|
*
|
|
* This does not free the memory used by
|
|
* this quadedge quartet, but indicates
|
|
* that this quadedge quartet no longer participates
|
|
* in a subdivision.
|
|
*
|
|
* @note called "delete" in JTS
|
|
*
|
|
*/
|
|
void remove();
|
|
|
|
/** \brief
|
|
* Tests whether this edge has been deleted.
|
|
*
|
|
* @return `true` if this edge has not been deleted.
|
|
*/
|
|
inline bool
|
|
isLive() const
|
|
{
|
|
return isAlive;
|
|
}
|
|
|
|
inline bool
|
|
isVisited() const
|
|
{
|
|
return visited;
|
|
}
|
|
|
|
inline void
|
|
setVisited(bool v) {
|
|
visited = v;
|
|
}
|
|
|
|
/** \brief
|
|
* Sets the connected edge
|
|
*
|
|
* @param p_next edge
|
|
*/
|
|
inline void
|
|
setNext(QuadEdge* p_next)
|
|
{
|
|
this->next = p_next;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* QuadEdge Algebra
|
|
***************************************************************************
|
|
*/
|
|
|
|
/** \brief
|
|
* Gets the dual of this edge, directed from its right to its left.
|
|
*
|
|
* @return the rotated edge
|
|
*/
|
|
inline const QuadEdge&
|
|
rot() const
|
|
{
|
|
return (num < 3) ? *(this + 1) : *(this - 3);
|
|
}
|
|
|
|
inline QuadEdge&
|
|
rot()
|
|
{
|
|
return (num < 3) ? *(this + 1) : *(this - 3);
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the dual of this edge, directed from its left to its right.
|
|
*
|
|
* @return the inverse rotated edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
invRot() const
|
|
{
|
|
return (num > 0) ? *(this - 1) : *(this + 3);
|
|
}
|
|
|
|
inline QuadEdge&
|
|
invRot()
|
|
{
|
|
return (num > 0) ? *(this - 1) : *(this + 3);
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the edge from the destination to the origin of this edge.
|
|
*
|
|
* @return the sym of the edge
|
|
*/
|
|
inline const QuadEdge&
|
|
sym() const
|
|
{
|
|
return (num < 2) ? *(this + 2) : *(this - 2);
|
|
}
|
|
|
|
inline QuadEdge&
|
|
sym()
|
|
{
|
|
return (num < 2) ? *(this + 2) : *(this - 2);
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the next CCW edge around the origin of this edge.
|
|
*
|
|
* @return the next linked edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
oNext() const
|
|
{
|
|
return *next;
|
|
}
|
|
|
|
inline QuadEdge&
|
|
oNext()
|
|
{
|
|
return *next;
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the next CW edge around (from) the origin of this edge.
|
|
*
|
|
* @return the previous edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
oPrev() const
|
|
{
|
|
return rot().oNext().rot();
|
|
}
|
|
|
|
inline QuadEdge&
|
|
oPrev()
|
|
{
|
|
return rot().oNext().rot();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the next CCW edge around (into) the destination of this edge.
|
|
*
|
|
* @return the next destination edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
dNext() const
|
|
{
|
|
return sym().oNext().sym();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the next CW edge around (into) the destination of this edge.
|
|
*
|
|
* @return the previous destination edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
dPrev() const
|
|
{
|
|
return invRot().oNext().invRot();
|
|
}
|
|
|
|
inline QuadEdge&
|
|
dPrev()
|
|
{
|
|
return invRot().oNext().invRot();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the CCW edge around the left face following this edge.
|
|
*
|
|
* @return the next left face edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
lNext() const
|
|
{
|
|
return invRot().oNext().rot();
|
|
}
|
|
|
|
inline QuadEdge&
|
|
lNext()
|
|
{
|
|
return invRot().oNext().rot();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the CCW edge around the left face before this edge.
|
|
*
|
|
* @return the previous left face edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
lPrev() const
|
|
{
|
|
return oNext().sym();
|
|
}
|
|
|
|
inline QuadEdge&
|
|
lPrev()
|
|
{
|
|
return oNext().sym();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the edge around the right face ccw following this edge.
|
|
*
|
|
* @return the next right face edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
rNext() const
|
|
{
|
|
return rot().oNext().invRot();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the edge around the right face ccw before this edge.
|
|
*
|
|
* @return the previous right face edge.
|
|
*/
|
|
inline const QuadEdge&
|
|
rPrev() const
|
|
{
|
|
return sym().oNext();
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* Data Access
|
|
**********************************************************************************************/
|
|
/** \brief
|
|
* Sets the vertex for this edge's origin
|
|
*
|
|
* @param o the origin vertex
|
|
*/
|
|
inline void
|
|
setOrig(const Vertex& o)
|
|
{
|
|
vertex = o;
|
|
}
|
|
|
|
/** \brief
|
|
* Sets the vertex for this edge's destination
|
|
*
|
|
* @param d the destination vertex
|
|
*/
|
|
inline void
|
|
setDest(const Vertex& d)
|
|
{
|
|
sym().setOrig(d);
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the vertex for the edge's origin
|
|
*
|
|
* @return the origin vertex
|
|
*/
|
|
const Vertex&
|
|
orig() const
|
|
{
|
|
return vertex;
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the vertex for the edge's destination
|
|
*
|
|
* @return the destination vertex
|
|
*/
|
|
const Vertex&
|
|
dest() const
|
|
{
|
|
return sym().orig();
|
|
}
|
|
|
|
/** \brief
|
|
* Gets the length of the geometry of this quadedge.
|
|
*
|
|
* @return the length of the quadedge
|
|
*/
|
|
inline double
|
|
getLength() const
|
|
{
|
|
return orig().getCoordinate().distance(dest().getCoordinate());
|
|
}
|
|
|
|
/** \brief
|
|
* Tests if this quadedge and another have the same line segment geometry,
|
|
* regardless of orientation.
|
|
*
|
|
* @param qe a quadege
|
|
* @return `true` if the quadedges are based on the same line segment regardless of orientation
|
|
*/
|
|
bool equalsNonOriented(const QuadEdge& qe) const;
|
|
|
|
/** \brief
|
|
* Tests if this quadedge and another have the same line segment geometry
|
|
* with the same orientation.
|
|
*
|
|
* @param qe a quadege
|
|
* @return `true` if the quadedges are based on the same line segment
|
|
*/
|
|
bool equalsOriented(const QuadEdge& qe) const;
|
|
|
|
/** \brief
|
|
* Creates a {@link geom::LineSegment} representing the
|
|
* geometry of this edge.
|
|
*
|
|
* @return a LineSegment
|
|
*/
|
|
std::unique_ptr<geom::LineSegment> toLineSegment() const;
|
|
};
|
|
|
|
GEOS_DLL std::ostream& operator<< (std::ostream& os, const QuadEdge* e);
|
|
|
|
} //namespace geos.triangulate.quadedge
|
|
} //namespace geos.triangulate
|
|
} //namespace geos
|
|
|