Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
pgl::Triangulation< TriangleType_, SegmentType_ > Struct Template Reference

Triangulation whose connectivity may change and whose vertex set may grow. More...

#include <triangulation.hpp>

Public Types

using TriangleType = TriangleType_
using SegmentType = SegmentType_
using PointType = typename TriangleType::PointType
using NumberType = typename PointType::NumberType
using SegmentLabel = typename SegmentType::LabelType
using TriangleLabel = detail::optional_label_t<TriangleType>
using VertexId = detail::Handle<VertexTag>
 Handle of a vertex of this triangulation specialization.
using TriId = detail::Handle<TriTag>
 Handle of a triangle of this triangulation specialization.

Public Member Functions

 Triangulation ()=default
 Creates an empty triangulation.
template<class TriangleRange>
requires TriangleConcept<typename TriangleRange::value_type>
 Triangulation (const TriangleRange &tris)
 Builds a triangulation from a set of triangles.
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const SegmentRange &segs)
 Builds a triangulation from its set of edges.
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
 Triangulation (const PointRange &pts)
 Builds the Delaunay triangulation of a set of points.
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const PointRange &pts, const SegmentRange &segments)
 Builds the conforming constrained Delaunay triangulation of a point set with constraint segments.
 Triangulation (const Polygon< PointType > &poly)
 Builds the constrained Delaunay triangulation of a simple polygon, optionally with extra interior points and constraint segments.
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
 Triangulation (const Polygon< PointType > &poly, const PointRange &points)
 Adds the interior points as extra triangulation vertices.
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const Polygon< PointType > &poly, const SegmentRange &segments)
 Adds the interior segments as constrained edges and vertices.
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const Polygon< PointType > &poly, const PointRange &points, const SegmentRange &segments)
 Adds both interior points and constraint segments.
 Triangulation (const PolygonWithHoles< PointType > &region)
 Builds the constrained Delaunay triangulation of a region with holes, optionally with extra interior points and constraint segments.
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
 Triangulation (const PolygonWithHoles< PointType > &region, const PointRange &points)
 Adds the interior points as extra triangulation vertices.
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const PolygonWithHoles< PointType > &region, const SegmentRange &segments)
 Adds the interior segments as constrained edges and vertices.
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const PolygonWithHoles< PointType > &region, const PointRange &points, const SegmentRange &segments)
 Adds both interior points and constraint segments.
 Triangulation (const PolygonSet< PointType > &set)
 Builds the constrained Delaunay triangulation of a set of regions, optionally with extra interior points and constraint segments.
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
 Triangulation (const PolygonSet< PointType > &set, const PointRange &points)
 Adds the interior points as extra triangulation vertices.
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const PolygonSet< PointType > &set, const SegmentRange &segments)
 Adds the interior segments as constrained edges and vertices.
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
 Triangulation (const PolygonSet< PointType > &set, const PointRange &points, const SegmentRange &segments)
 Adds both interior points and constraint segments.
template<class ResultNumber = division_result_t<NumberType>>
Arrangement< Point< ResultNumber >, PointTypevoronoiDiagram () const
 Returns the Voronoi diagram dual to this Delaunay triangulation.
std::size_t numVertices () const
 Number of real vertices (excludes the ghost vertex).
std::size_t numTriangles () const
 Number of triangles (excludes ghost and out-of-domain fill triangles).
std::size_t numEdges () const
 Number of undirected edges incident to the visible triangulation.
bool empty () const
 True if the triangulation stores no in-domain triangles.
bool has (const TriangleType &t) const
 True if t is one of the triangles of this triangulation.
bool has (const SegmentType &s) const
 True if s is an edge incident to the visible triangulation.
std::optional< TriangleTypeotherTriangle (const TriangleType &t, const SegmentType &shared) const
 The triangle on the other side of shared from t.
std::vector< TriangleTypeedgeAdjacentTriangles (const TriangleType &t) const
 The (up to three) triangles sharing an edge with t.
std::vector< TriangleTypevertexAdjacentTriangles (const TriangleType &t) const
 The triangles sharing at least one vertex with t (excluding t).
std::vector< TriangleTypeincidentTriangles (const SegmentType &s) const
 The (up to two) triangles incident to edge s.
std::vector< TriangleTypeincidentTriangles (const PointType &p) const
 The triangles incident to vertex p — its full fan.
template<class Fn>
bool visitTriangles (Fn fn) const
 Calls fn(Triangle) — or fn(TriId) — on every triangle.
template<class Fn>
bool visitEdges (Fn fn) const
 Calls fn(Segment) on every edge, with its stored label.
std::vector< TriangleTypetriangles () const
 Returns all triangles, sorted.
std::vector< SegmentTypeedges () const
 Returns all edges, sorted, each with its stored label.
Graph< PointTypeasGraph () const
 Returns the mesh's vertices and edges as a Graph.
Arrangement< PointType, TriIdasArrangement () const
 Returns the visible mesh as an arrangement, labeling each triangle face by its ID.
void buildPointLocation ()
 Builds the point-location index: a Kirkpatrick hierarchy over this mesh.
void clearPointLocation () noexcept
 Releases the point-location index.
bool hasPointLocation () const noexcept
 True if locate and locateId currently use the point-location index.
bool hasCurrentPointLocation () const noexcept
 True if the index is in place and was drawn against the mesh as it now stands.
std::vector< TriIdtriangleIds () const
 The handles of every triangle, in storage order.
std::vector< VertexIdvertexIds () const
 The handles of every vertex, in storage order.
std::size_t triangleIndexBound () const
 One past the largest index a TriId of this triangulation can carry.
std::size_t vertexIndexBound () const
 One past the largest index a VertexId of this triangulation can carry.
TriId locateId (const PointType &p) const
 Finds the triangle containing the query point, as a handle.
template<PointConcept QueryPoint>
TriId locateId (const QueryPoint &p) const
TriangleType getShape (TriId t) const
 The triangle a handle refers to, with its stored label.
const PointTypegetShape (VertexId v) const
 The position of the vertex a handle refers to.
TriangleType operator[] (TriId t) const
 Same as getShape(TriId) const.
const PointTypeoperator[] (VertexId v) const
 Same as getShape(VertexId) const.
TriId getId (const TriangleType &t) const
 The handle of a triangle of this triangulation.
VertexId getId (const PointType &p) const
 The handle of a vertex of this triangulation.
bool has (TriId t) const
 True if t is a handle of one of the triangles of this triangulation.
bool has (VertexId v) const
 True if v is a handle of one of the vertices of this triangulation.
std::array< VertexId, 3 > vertices (TriId t) const
 The three vertices of a triangle, counterclockwise.
std::optional< TriIdotherTriangle (TriId t, int side) const
 The triangle on the other side of side side of t.
bool isConstrained (TriId t, int side) const
 True if side side of t is a constrained edge.
void setConstrained (TriId t, int side, bool value=true)
 Constrains (or unconstrains) side side of t.
std::optional< TriIdotherTriangle (TriId t, VertexId a, VertexId b) const
 The triangle on the other side of edge a b from t.
std::vector< TriIdedgeAdjacentTriangles (TriId t) const
 The (up to three) triangles sharing an edge with t.
std::vector< TriIdvertexAdjacentTriangles (TriId t) const
 The triangles sharing at least one vertex with t (excluding t).
std::vector< TriIdincidentTriangles (VertexId v) const
 The triangles incident to vertex v — its full fan.
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
L & label (TriId t)
 Returns a reference to the label stored for the triangle t.
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
const L & label (TriId t) const
Graph< PointTypevisibilityGraph () const
 Returns the visibility graph of the mesh vertices.
Graph< PointTypeclearVisibilityGraph () const
 Returns the clear visibility graph of the mesh vertices.
Graph< PointTypereducedVisibilityGraph () const
 Returns the reduced visibility graph of the mesh vertices.
std::vector< PointTypevisibleVertices (const PointType &query) const
 The mesh vertices visible from query.
std::vector< PointTypeclearlyVisibleVertices (const PointType &query) const
 The mesh vertices clearly visible from query.
template<class ResultNumber = division_result_t<NumberType>>
Polygon< Point< ResultNumber > > regularizedVisiblePolygon (const PointType &query) const
 The region of the domain visible from query, regularized.
std::vector< Convex< PointType > > convexPartition () const
 The domain cut into convex pieces with pairwise disjoint interiors.
std::vector< Convex< PointType > > convexCovering () const
 Covers the domain with a greedily selected set of convex polygons.
template<detail::DirectedTraversal OS, class Fn>
bool visitTrianglesIntersecting (const OS &s, Fn f) const
 Visits every triangle met by the directed query s, in order.
template<detail::TriangulationQuery OS>
std::vector< TriangleTypetrianglesIntersecting (const OS &s) const
 Returns the triangles met by s (a segment, (oriented) line, ray, or chain, in order, or a region query shape, in an unspecified order).
template<detail::TriangulationQuery OS, class Fn>
bool visitTrianglesInteriorIntersecting (const OS &s, Fn f) const
 Visits the triangles whose interior s actually enters.
template<detail::TriangulationQuery OS>
std::vector< TriangleTypetrianglesInteriorIntersecting (const OS &s) const
 Returns the triangles whose interior s enters.
template<detail::TriangulationQuery OS, class Fn>
bool visitEdgesIntersecting (const OS &s, Fn f) const
 Visits every triangulation edge met by s.
template<detail::TriangulationQuery OS, class Fn>
bool visitEdgesInteriorIntersecting (const OS &s, Fn f) const
 Visits the triangulation edges whose interior s crosses.
template<detail::TriangulationQuery OS>
std::vector< SegmentTypeedgesIntersecting (const OS &s) const
 Returns the triangulation edges met by s.
template<detail::TriangulationQuery OS>
std::vector< SegmentTypeedgesInteriorIntersecting (const OS &s) const
 Returns the triangulation edges whose interior s crosses.
template<detail::TriangulationRegionQuery Q, class Fn>
bool visitTrianglesIntersecting (const Q &shape, Fn f) const
 Visits every in-domain triangle that intersects shape.
template<detail::ChainTraversal C, class Fn>
bool visitTrianglesIntersecting (const C &c, Fn f) const
 Visits every in-domain triangle that intersects the chain c, in the order the chain first meets them.
template<PointConcept QueryPoint>
std::optional< TriangleTypelocate (const QueryPoint &p) const
 Finds the triangle containing the query point by walking the mesh.
template<PointConcept QueryPoint>
bool contains (const QueryPoint &shape) const
 True if the triangulated domain contains shape (A ⊇ B).
template<detail::SegmentOrOriented S>
bool contains (const S &shape) const
template<detail::ChainTraversal C>
bool contains (const C &shape) const
template<detail::PolygonalRegion Q>
bool contains (const Q &shape) const
template<PolygonWithHolesConcept Q>
bool contains (const Q &shape) const
template<PolygonSetConcept Q>
bool contains (const Q &shape) const
template<HalfplaneIntersectionConcept Q>
bool contains (const Q &shape) const
template<DiskConcept D>
bool contains (const D &shape) const
template<class U>
requires detail::LineOrOriented<U> || RayConcept<U> || HalfplaneConcept<U>
bool contains (const U &) const
template<EmptyShapeConcept E>
bool contains (const E &) const
bool contains (const Shape< PointType > &shape) const
template<detail::TriangulationQuery Q>
bool intersects (const Q &shape) const
 True if the triangulated domain meets shape (A ∩ B ≠ ∅).
template<PolygonConcept Q>
bool intersects (const Q &shape) const
template<PolygonWithHolesConcept Q>
bool intersects (const Q &shape) const
template<PolygonSetConcept Q>
bool intersects (const Q &shape) const
template<HalfplaneIntersectionConcept Q>
bool intersects (const Q &shape) const
template<EmptyShapeConcept E>
bool intersects (const E &) const
bool intersects (const Shape< PointType > &shape) const
template<detail::TriangulationQuery Q>
bool interiorContains (const Q &shape) const
 True if the domain's interior contains shape (A∖∂A ⊇ B).
template<PolygonConcept Q>
bool interiorContains (const Q &shape) const
template<PolygonWithHolesConcept Q>
bool interiorContains (const Q &shape) const
template<PolygonSetConcept Q>
bool interiorContains (const Q &shape) const
template<HalfplaneIntersectionConcept Q>
bool interiorContains (const Q &shape) const
template<EmptyShapeConcept E>
bool interiorContains (const E &) const
bool interiorContains (const Shape< PointType > &shape) const
template<PointConcept QueryPoint>
bool interiorsIntersect (const QueryPoint &shape) const
 True if the domain's interior meets shape's interior (A∖∂A ∩ B∖∂B ≠ ∅).
template<detail::TriangulationQuery Q>
requires (!PointConcept<Q>)
bool interiorsIntersect (const Q &shape) const
template<PolygonConcept Q>
bool interiorsIntersect (const Q &shape) const
template<PolygonWithHolesConcept Q>
bool interiorsIntersect (const Q &shape) const
template<PolygonSetConcept Q>
bool interiorsIntersect (const Q &shape) const
template<HalfplaneIntersectionConcept Q>
bool interiorsIntersect (const Q &shape) const
template<EmptyShapeConcept E>
bool interiorsIntersect (const E &) const
bool interiorsIntersect (const Shape< PointType > &shape) const
bool isConstrained (const SegmentType &s) const
 True if edge s is flagged as constrained.
void setConstrained (const SegmentType &s, bool value=true)
 Flags (or clears) edge s as constrained on both incident sides.
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
L & label (const TriangleType &t)
 Returns a reference to the label stored for triangle t.
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
const L & label (const TriangleType &t) const
template<class L = SegmentLabel>
requires (detail::has_label_v<L>)
L & label (const SegmentType &s)
 Returns a reference to the label stored for edge s.
template<class L = SegmentLabel>
requires (detail::has_label_v<L>)
const L & label (const SegmentType &s) const
bool flippable (const SegmentType &s) const
 True if edge s can be flipped (unconstrained, interior, convex quad).
std::optional< SegmentTypeflip (const SegmentType &s)
 Flips edge s, replacing it by the opposite diagonal.
template<class EdgeRange>
requires SegmentConcept<typename EdgeRange::value_type>
bool flippable (const EdgeRange &edges) const
 True if every edge in edges can be flipped simultaneously.
template<class EdgeRange>
requires SegmentConcept<typename EdgeRange::value_type>
std::optional< std::vector< SegmentType > > flip (const EdgeRange &edges)
 Flips every edge in edges at once, if the whole set allows it.
bool insert (const PointType &p)
 Inserts p as a new vertex.
bool insertDelaunay (const PointType &p)
 Inserts p as a new vertex and restores the constrained Delaunay property around it.
bool checkInvariants () const
 Checks the structural invariants (orientation + neighbor symmetry). Intended for debug assertions.
template<class ResultNumber>
Arrangement< Point< ResultNumber >, typename Triangulation< TriangleType, SegmentType >::PointTypevoronoiDiagram () const

Friends

Canvasoperator<< (Canvas &canvas, const Triangulation &triangulation)
 Draws every triangle to a canvas.

Detailed Description

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
struct pgl::Triangulation< TriangleType_, SegmentType_ >

Triangulation whose connectivity may change and whose vertex set may grow.

Template Parameters
TriangleType_The triangle type stored, e.g. pgl::Triangle<Point>. The point type — and hence any vertex labels — is taken from it.
SegmentType_The edge type stored, defaulting to the triangle's own edge-segment type. When built from a container of labeled segments it is deduced as that labeled type, so segment labels are kept.

Any label carried by the input triangles (TriangleType::LabelType) and segments (SegmentType::LabelType) is stored and surfaced again by the accessors, and can be read or edited in place through label. A flip resets the labels of the edges and triangles it touches to default-constructed values. Labels are stored via [[no_unique_address]], so they cost nothing when absent (NoLabel).

Member Typedef Documentation

◆ NumberType

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::NumberType = typename PointType::NumberType

◆ PointType

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::PointType = typename TriangleType::PointType

◆ SegmentLabel

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::SegmentLabel = typename SegmentType::LabelType

◆ SegmentType

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::SegmentType = SegmentType_

◆ TriangleLabel

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::TriangleLabel = detail::optional_label_t<TriangleType>

◆ TriangleType

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::TriangleType = TriangleType_

◆ TriId

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::TriId = detail::Handle<TriTag>

Handle of a triangle of this triangulation specialization.

◆ VertexId

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
using pgl::Triangulation< TriangleType_, SegmentType_ >::VertexId = detail::Handle<VertexTag>

Handle of a vertex of this triangulation specialization.

Constructor & Destructor Documentation

◆ Triangulation() [1/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( )
default

Creates an empty triangulation.

◆ Triangulation() [2/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class TriangleRange>
requires TriangleConcept<typename TriangleRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const TriangleRange & tris)
inlineexplicit

Builds a triangulation from a set of triangles.

The vertex set is the union of the triangles' vertices (extendable later via insert). Adjacencies, the ghost triangles over the boundary, and the segment-to-edge map are all computed automatically.

Template Parameters
TriangleRangeRange whose elements are TriangleType.
Parameters
trisTriangles forming the triangulation.
Precondition
No triangle is degenerate; the triangles tile a region without overlaps (i.e. they form a valid triangulation).

◆ Triangulation() [3/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const SegmentRange & segs)
inlineexplicit

Builds a triangulation from its set of edges.

The triangular faces are recovered from the edge set by sorting each vertex's incident edges counterclockwise and tracing the bounded faces (an exact rotation-system / DCEL face walk). The vertex set is the union of the segments' endpoints (extendable later via insert).

Template Parameters
SegmentRangeRange whose elements are pgl::Segment.
Parameters
segsEdges of the triangulation.
Precondition
The segments are the edges of a valid triangulation (every bounded face is a triangle); no segment is degenerate.

◆ Triangulation() [4/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PointRange & pts)
inlineexplicit

Builds the Delaunay triangulation of a set of points.

The vertex set is the points (deduplicated; extendable later via insert) and the connectivity is their Delaunay triangulation, computed exactly. Points that are collinear with all others, or duplicated, simply carry no incident triangle.

Template Parameters
PointRangeRange whose elements are pgl::Point.
Parameters
ptsPoints to triangulate.

◆ Triangulation() [5/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PointRange & pts,
const SegmentRange & segments )
inline

Builds the conforming constrained Delaunay triangulation of a point set with constraint segments.

The vertex set is the union of the points and the segments' endpoints (deduplicated; extendable later via insert) and every input segment is present as a constrained edge — never flipped, kept by insertDelaunay, fencing hull growth like a polygon boundary when it lies on the hull. Unlike the polygon constructors nothing is carved away: the domain is the whole convex hull. Segment labels are kept on the constrained edges.

Template Parameters
PointRangeRange whose elements are pgl::Point.
SegmentRangeRange whose elements are segments.
Parameters
ptsPoints to triangulate.
segmentsConstraint segments.
Precondition
The segments are non-degenerate and pairwise non-crossing (sharing endpoints is fine), and no vertex — point or other endpoint — lies in a segment's relative interior. Not checked.

◆ Triangulation() [6/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const Polygon< PointType > & poly)
inlineexplicit

Builds the constrained Delaunay triangulation of a simple polygon, optionally with extra interior points and constraint segments.

The convex hull of all input vertices is Delaunay-triangulated, the polygon's boundary edges and every constraint segment are inserted as constraints, and the triangles lying outside the polygon (between it and its convex hull) are marked out-of-domain. The public view — triangles, numTriangles, locate, ... — then sees exactly the polygon's interior; locate therefore works for non-convex polygons.

The vertex set is the union of the polygon's vertices, the points in points, and the endpoints of the segments in segments; each segment additionally becomes a constrained edge. Either points or segments (or both) may be omitted.

Parameters
polySimple polygon (convex or not) to triangulate.
Precondition
poly is simple (non-self-intersecting) and non-degenerate, and any extra points and segments lie inside it (the latter is not checked).

◆ Triangulation() [7/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const Polygon< PointType > & poly,
const PointRange & points )
inline

Adds the interior points as extra triangulation vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie inside poly.

◆ Triangulation() [8/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const Polygon< PointType > & poly,
const SegmentRange & segments )
inline

Adds the interior segments as constrained edges and vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
segmentsConstraint edges (and their endpoint vertices); assumed to lie inside poly.

◆ Triangulation() [9/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const Polygon< PointType > & poly,
const PointRange & points,
const SegmentRange & segments )
inline

Adds both interior points and constraint segments.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie inside poly.
segmentsConstraint edges (and their endpoint vertices); assumed to lie inside poly.

◆ Triangulation() [10/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonWithHoles< PointType > & region)
inlineexplicit

Builds the constrained Delaunay triangulation of a region with holes, optionally with extra interior points and constraint segments.

Every ring — the outer boundary and each hole — goes in as constrained edges, and the out-of-domain flood is seeded both from outside the convex hull and from inside each hole. The domain is then exactly the part of the region that has area: triangles, numTriangles and locate see the material between the rings and nothing else.

A region may hold pieces with no area at all — a hole sharing an edge with another ring leaves a slit, and the region contains it without any neighbourhood of it being in the region. Slits carry no triangle, so the triangulated domain is the closure of the region's interior rather than the region itself. Areas are unaffected, a slit having none.

Parameters
regionRegion to triangulate.
Precondition
region satisfies PolygonWithHoles::isValid, and any extra points and segments lie in it (neither is checked).

◆ Triangulation() [11/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonWithHoles< PointType > & region,
const PointRange & points )
inline

Adds the interior points as extra triangulation vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie in region.

◆ Triangulation() [12/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonWithHoles< PointType > & region,
const SegmentRange & segments )
inline

Adds the interior segments as constrained edges and vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
segmentsConstraint edges (and their endpoint vertices); assumed to lie in region.

◆ Triangulation() [13/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonWithHoles< PointType > & region,
const PointRange & points,
const SegmentRange & segments )
inline

Adds both interior points and constraint segments.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie in region.
segmentsConstraint edges (and their endpoint vertices); assumed to lie in region.

◆ Triangulation() [14/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonSet< PointType > & set)
inlineexplicit

Builds the constrained Delaunay triangulation of a set of regions, optionally with extra interior points and constraint segments.

Every ring of every component goes in as constrained edges, and the out-of-domain flood is seeded both from outside the convex hull and from inside each component's holes. The domain is then exactly the part of the set that has area — the gap between two components is reached by the same flood that carves away the exterior, and a component stranded inside another's hole is fenced out of that hole's flood by its own outer ring.

As with a single region, a slit carries no triangle, so the triangulated domain is closure(A°) rather than A itself.

Parameters
setSet of regions to triangulate.
Precondition
set satisfies PolygonSet::isValid, and any extra points and segments lie in it (neither is checked).

◆ Triangulation() [15/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange>
requires PointConcept<typename PointRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonSet< PointType > & set,
const PointRange & points )
inline

Adds the interior points as extra triangulation vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie in set.

◆ Triangulation() [16/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class SegmentRange>
requires SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonSet< PointType > & set,
const SegmentRange & segments )
inline

Adds the interior segments as constrained edges and vertices.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
segmentsConstraint edges (and their endpoint vertices); assumed to lie in set.

◆ Triangulation() [17/17]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class PointRange, class SegmentRange>
requires PointConcept<typename PointRange::value_type> && SegmentConcept<typename SegmentRange::value_type>
pgl::Triangulation< TriangleType_, SegmentType_ >::Triangulation ( const PolygonSet< PointType > & set,
const PointRange & points,
const SegmentRange & segments )
inline

Adds both interior points and constraint segments.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
pointsExtra vertices to insert; assumed to lie in set.
segmentsConstraint edges (and their endpoint vertices); assumed to lie in set.

Member Function Documentation

◆ asArrangement()

template<TriangleConcept TriangleType, SegmentConcept SegmentType>
Arrangement< typename Triangulation< TriangleType, SegmentType >::PointType, typename Triangulation< TriangleType, SegmentType >::TriId > pgl::Triangulation< TriangleType, SegmentType >::asArrangement ( ) const
nodiscard

Returns the visible mesh as an arrangement, labeling each triangle face by its ID.

The arrangement contains exactly the geometric edges returned by edges. Its bounded faces that are triangles of this triangulation are labeled with their TriId; every other face, including the exterior and holes in a constrained domain, has an invalid label. Arrangement edge labels are likewise invalid: the arrangement's label type is reserved for face IDs.

Returns
An arrangement of the visible mesh edges, with triangle faces labeled by their handles.

◆ asGraph()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
Graph< PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::asGraph ( ) const
inlinenodiscard

Returns the mesh's vertices and edges as a Graph.

The graph is the 1-skeleton of the triangulation: its vertices are the numVertices stored points and its edges are the numEdges edges of the visible mesh, so a vertex left without any incident in-domain edge — one duplicated or collinear with every other point, which carries no triangle — comes back as an isolated graph vertex rather than not at all. The ghost vertex closing the mesh at infinity is internal and is not one of them.

The points are the graph's vertices, since a point identifies a vertex of a triangulation, unlike Arrangement::asGraph where the vertex at infinity forces the use of handles. Edge labels have no place in a graph and are dropped; label recovers the label of an edge from its endpoints.

Complexity: O(V + E).

◆ buildPointLocation()

template<TriangleConcept TriangleType, SegmentConcept SegmentType>
void pgl::Triangulation< TriangleType, SegmentType >::buildPointLocation ( )

Builds the point-location index: a Kirkpatrick hierarchy over this mesh.

The mesh is enclosed in a box and the ring between the box and the convex hull is triangulated, so that every vertex but the four box corners is interior. An independent set of low-degree vertices is then removed and the hole each star leaves is retriangulated, and again over the result, until only the box is left: some thirty levels for a mesh of 100,000 vertices, each holding about seven tenths of the triangles below it. Every triangle records the ones it covers, so a query placed in the box descends one triangle per level and arrives at the mesh triangle holding it.

Until it is called, locate and locateId walk the mesh from the last query's answer, which is fast for queries that follow one another and linear for queries that do not. Afterwards a query whose coordinates convert losslessly to this triangulation's PointType descends the hierarchy instead. What a query may return does not change: a point strictly inside a triangle gets that triangle indexed or not, and one on an edge or a vertex gets an incident triangle, which of them being as unspecified as it is for the bare walk.

The index outlives every edit. A hierarchy built before an insert or a flip stays usable across it: what it lands on is a triangle of this mesh whatever has happened to the mesh since, and the walk resumes from there rather than answering outright. What an edit costs is that resumption — the hierarchy does not know the vertices added since it was drawn, so the walk out of its answer lengthens as the mesh grows away from it. Rebuilding is therefore the owner's call and never the triangulation's — call this again to redraw the hierarchy against the mesh as it now stands (it does nothing if nothing has changed since), or clearPointLocation to give it up and go back to walking from the previous query's answer.

@complexity Expected O(V) time and space, both a small multiple of what the mesh itself takes; O(log V) per query.

◆ checkInvariants()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::checkInvariants ( ) const
inlinenodiscard

Checks the structural invariants (orientation + neighbor symmetry). Intended for debug assertions.

◆ clearlyVisibleVertices()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
std::vector< typename Triangulation< TriangleType_, SegmentType_ >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::clearlyVisibleVertices ( const PointType & query) const
nodiscard

The mesh vertices clearly visible from query.

The strict counterpart of visibleVertices, matching clearVisibilityGraph: the open segment queryv must lie in the interior of the domain, cross no wall, and hold no other vertex. Neither grazing nor passing through a vertex counts, and a vertex reached only along the boundary — including the far end of a boundary edge query sits on — is left out. Always a subset of visibleVertices.

Parameters
queryPoint to look from; outside the domain nothing is visible.
Returns
The clearly visible vertices, ordered as in visibleVertices.

◆ clearPointLocation()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
void pgl::Triangulation< TriangleType_, SegmentType_ >::clearPointLocation ( )
inlinenoexcept

Releases the point-location index.

The only thing that does: no edit releases it. locate and locateId go back to walking from the previous query's answer.

◆ clearVisibilityGraph()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
Graph< typename Triangulation< TriangleType_, SegmentType_ >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::clearVisibilityGraph ( ) const
nodiscard

Returns the clear visibility graph of the mesh vertices.

Two vertices are adjacent exactly when the open segment joining them lies in the interior of the domain, crosses no wall, and contains no other vertex. This is the strict reading of visibility: a segment that grazes the boundary, runs along a wall or passes through a third vertex is excluded, and so is every boundary edge of the domain itself, whose relative interior lies on the boundary rather than inside it. The clear visibility graph of a simple polygon is therefore exactly its set of legal triangulation diagonals, and it is always a subgraph of visibilityGraph.

Computed by the same triangular expansion as visibilityGraph, with the cone kept open, and without the collinear closure.

Complexity: O(V·T + E), as for visibilityGraph.

Returns
An undirected graph over this triangulation's vertices.

◆ contains() [1/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::ChainTraversal C>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const C & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [2/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<DiskConcept D>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const D & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [3/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<EmptyShapeConcept E>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const E & ) const
inlinenodiscard

◆ contains() [4/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<HalfplaneIntersectionConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [5/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonSetConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [6/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonWithHolesConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [7/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::PolygonalRegion Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [8/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PointConcept QueryPoint>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const QueryPoint & shape) const
inlinenodiscard

True if the triangulated domain contains shape (A ⊇ B).

The domain is the closed region the triangulation covers — the polygon for the polygon constructors, the convex hull otherwise — so this, and its companions interiorContains, intersects and interiorsIntersect, answer exactly what the shape predicates of the same name would answer for that region as a Polygon, boundary and all: a shape running along a polygon edge, or ending on one, is contained. The work is done on the mesh, though, so the cost is proportional to the triangles shape meets rather than to the size of the domain's boundary.

Every shape type is accepted. An unbounded one — a line, oriented line, ray, or half-plane — is never contained in the bounded domain; the empty shape always is.

Parameters
shapeQuery shape; it may use a different point type.
Note
Distinct from has, which asks whether a triangle or segment is a cell of the mesh, not whether the domain covers it geometrically.

◆ contains() [9/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::SegmentOrOriented S>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const S & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [10/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const Shape< PointType > & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ contains() [11/11]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class U>
requires detail::LineOrOriented<U> || RayConcept<U> || HalfplaneConcept<U>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::contains ( const U & ) const
inlinenodiscard

◆ convexCovering()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< Convex< PointType > > pgl::Triangulation< TriangleType_, SegmentType_ >::convexCovering ( ) const
inlinenodiscard

Covers the domain with a greedily selected set of convex polygons.

A convex candidate is grown independently from every in-domain triangle, always against the original triangulation. Growth crosses an unconstrained boundary edge when adjoining its triangle keeps the candidate convex; a failed edge is reconsidered if a later merge changes either endpoint angle. Each candidate is stored together with the exact set of triangles fused to make it.

Those triangle sets form a set-cover instance whose universe is the in-domain triangles. The greedy phase repeatedly takes the candidate that covers the most triangles not covered yet. A final reverse pass removes a selected candidate whenever all its triangles are still covered by the other selected candidates. Thus the result is irredundant, though neither the greedy cover nor the independently grown candidates are guaranteed minimum. Unlike convexPartition, returned polygons may overlap.

Constrained edges are never crossed. The pieces are unlabeled for the same reason as those returned by convexPartition: one piece may contain several triangles with different labels.

Complexity: O(n^2) time and space for n real triangles. There are at most n candidates, each grown and stored in O(n) time and space; the incidence-based greedy cover and redundancy pass are quadratic as well.

Returns
The irredundant greedy convex covering, in canonical order.

◆ convexPartition()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< Convex< PointType > > pgl::Triangulation< TriangleType_, SegmentType_ >::convexPartition ( ) const
inlinenodiscard

The domain cut into convex pieces with pairwise disjoint interiors.

Hertel–Mehlhorn: start from the triangles and delete every diagonal whose deletion leaves a convex piece, in one pass. Deleting a diagonal can only change the interior angle at its two endpoints — everywhere else the merged boundary is a stretch of one of the two pieces, unchanged — so each merge is decided by two orientation tests and nothing has to be re-examined. The classical guarantee is that the result has at most four times the minimum number of convex pieces, whatever order the diagonals are visited in, which is why no search is worth doing here. On a random simple polygon it halves the piece count against the triangulation.

What it partitions is the domain: closure(interior), exactly the part the triangles cover. A region's holes are where there is no piece, and a slit — a stretch of boundary two rings cover between them — has no area and so appears in no piece. Callers that need to sweep a slit have to add it themselves; pgl::detail::minkowskiConvexPieces is the one that does.

A constrained edge is never deleted. It is in the triangulation because something asked for it, and a partition that cuts along it is the one the caller described; for a polygon or a region built without extra constraints only the rings are constrained, so nothing is given up.

The pieces come back unlabeled: a piece is a merge of several triangles and there is no one triangle's label to carry.

Complexity: O(n^2) worst-case time and O(n) auxiliary space for n real triangles. The merge tests and ring construction are linear apart from the shared-edge guard below: it walks the boundary of a current piece, and repeated walks over a growing piece can take quadratic time altogether. Reading the surviving rings is linear; putting the p result pieces in canonical order additionally takes O(p log p) polygon comparisons.

Returns
The convex pieces, in canonical order, whose union is the domain.

◆ edgeAdjacentTriangles() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::edgeAdjacentTriangles ( const TriangleType & t) const
inlinenodiscard

The (up to three) triangles sharing an edge with t.

◆ edgeAdjacentTriangles() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::edgeAdjacentTriangles ( TriId t) const
inlinenodiscard

The (up to three) triangles sharing an edge with t.

◆ edges()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< SegmentType > pgl::Triangulation< TriangleType_, SegmentType_ >::edges ( ) const
inlinenodiscard

Returns all edges, sorted, each with its stored label.

◆ edgesInteriorIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS>
std::vector< SegmentType > pgl::Triangulation< TriangleType_, SegmentType_ >::edgesInteriorIntersecting ( const OS & s) const
inlinenodiscard

Returns the triangulation edges whose interior s crosses.

A materialized form of visitEdgesInteriorIntersecting: the in-domain edges e with s.interiorsIntersect(e), each with its stored label — in the order they are encountered along a segment or chain s, or an unspecified order for a region query shape.

Parameters
sA directed query — segment, oriented segment, line, oriented line, or ray — or a chain (polyline, monotone chain), both traced in order; or a region query shape (reported in an unspecified order). It may use a different point type.

◆ edgesIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS>
std::vector< SegmentType > pgl::Triangulation< TriangleType_, SegmentType_ >::edgesIntersecting ( const OS & s) const
inlinenodiscard

Returns the triangulation edges met by s.

A materialized form of visitEdgesIntersecting: the in-domain edges e with s.intersects(e), each with its stored label — in the order they are encountered along a segment or chain s, or an unspecified order for a region query shape.

Parameters
sA directed query — segment, oriented segment, line, oriented line, or ray — or a chain (polyline, monotone chain), both traced in order; or a region query shape (reported in an unspecified order). It may use a different point type.

◆ empty()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::empty ( ) const
inlinenodiscard

True if the triangulation stores no in-domain triangles.

◆ flip() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class EdgeRange>
requires SegmentConcept<typename EdgeRange::value_type>
std::optional< std::vector< SegmentType > > pgl::Triangulation< TriangleType_, SegmentType_ >::flip ( const EdgeRange & edges)
inline

Flips every edge in edges at once, if the whole set allows it.

All-or-nothing: if flippable(edges) holds, each edge is replaced by the opposite diagonal and the new diagonals are returned in the order of edges; otherwise the triangulation is left unchanged and std::nullopt is returned. Because the quadrilaterals are disjoint, the individual flips are independent — one never disturbs another's quad — so order does not matter.

Parameters
edgesA range of edge segments (edges.value_type is a segment).
Returns
The new diagonal segments, or std::nullopt if edges is not flippable as a set.

◆ flip() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::optional< SegmentType > pgl::Triangulation< TriangleType_, SegmentType_ >::flip ( const SegmentType & s)
inline

Flips edge s, replacing it by the opposite diagonal.

The two triangles sharing s are retriangulated across the other diagonal; the segment-to-edge map is updated accordingly.

Parameters
sEdge to flip.
Returns
The new diagonal segment, or std::nullopt if s is not flippable.

◆ flippable() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class EdgeRange>
requires SegmentConcept<typename EdgeRange::value_type>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::flippable ( const EdgeRange & edges) const
inlinenodiscard

True if every edge in edges can be flipped simultaneously.

A parallel flip is valid only when each edge is individually flippable (unconstrained, interior, convex quad) and the quadrilaterals are pairwise disjoint — i.e. no triangle is shared by two of the edges' quads. A shared triangle would be rewritten by the first flip, invalidating the other, so such a set is rejected (a repeated edge fails for the same reason). An empty range is trivially flippable.

Parameters
edgesA range of edge segments (edges.value_type is a segment).

◆ flippable() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::flippable ( const SegmentType & s) const
inlinenodiscard

True if edge s can be flipped (unconstrained, interior, convex quad).

◆ getId() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
VertexId pgl::Triangulation< TriangleType_, SegmentType_ >::getId ( const PointType & p) const
inlinenodiscard

The handle of a vertex of this triangulation.

Found by a point-location walk, so no hash lookup is involved.

Parameters
pA point.
Returns
Its handle, or the invalid handle when p is not a vertex of the triangulation (or lies outside the triangulated region).

◆ getId() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
TriId pgl::Triangulation< TriangleType_, SegmentType_ >::getId ( const TriangleType & t) const
inlinenodiscard

The handle of a triangle of this triangulation.

This is the bridge from the value world into the handle world: it is the one query that pays for a hash lookup, after which the handle-taking navigation methods walk the connectivity without touching a hash table.

Parameters
tA triangle.
Returns
Its handle, or the invalid handle when t is not one of the triangulation's triangles.

◆ getShape() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
TriangleType pgl::Triangulation< TriangleType_, SegmentType_ >::getShape ( TriId t) const
inlinenodiscard

The triangle a handle refers to, with its stored label.

Parameters
tHandle of a triangle of this triangulation.
Precondition
has(t).

◆ getShape() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
const PointType & pgl::Triangulation< TriangleType_, SegmentType_ >::getShape ( VertexId v) const
inlinenodiscard

The position of the vertex a handle refers to.

Parameters
vHandle of a vertex of this triangulation.
Precondition
has(v).

◆ has() [1/4]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::has ( const SegmentType & s) const
inlinenodiscard

True if s is an edge incident to the visible triangulation.

◆ has() [2/4]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::has ( const TriangleType & t) const
inlinenodiscard

True if t is one of the triangles of this triangulation.

◆ has() [3/4]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::has ( TriId t) const
inlinenodiscard

True if t is a handle of one of the triangles of this triangulation.

◆ has() [4/4]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::has ( VertexId v) const
inlinenodiscard

True if v is a handle of one of the vertices of this triangulation.

◆ hasCurrentPointLocation()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::hasCurrentPointLocation ( ) const
inlinenodiscardnoexcept

True if the index is in place and was drawn against the mesh as it now stands.

False once an edit has moved the mesh on from the index, which costs a query the index's answer — the walk resumes from it instead — and nothing else. See buildPointLocation, which this is the test of whether calling would do any work.

◆ hasPointLocation()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::hasPointLocation ( ) const
inlinenodiscardnoexcept

True if locate and locateId currently use the point-location index.

◆ incidentTriangles() [1/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::incidentTriangles ( const PointType & p) const
inlinenodiscard

The triangles incident to vertex p — its full fan.

Parameters
pA vertex of the triangulation.
Returns
Every in-domain triangle having p as one of its vertices, in rotational order around p. Empty if p is not a vertex of the triangulation (or lies outside the triangulated region).

◆ incidentTriangles() [2/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::incidentTriangles ( const SegmentType & s) const
inlinenodiscard

The (up to two) triangles incident to edge s.

◆ incidentTriangles() [3/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::incidentTriangles ( VertexId v) const
inlinenodiscard

The triangles incident to vertex v — its full fan.

Parameters
vHandle of a vertex of the triangulation.
Returns
Every in-domain triangle having v as one of its vertices, in rotational order around v. Empty when v carries no triangle (a vertex duplicated or collinear with every other one) or when the handle is not a vertex of the triangulation.

◆ insert()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::insert ( const PointType & p)
inline

Inserts p as a new vertex.

If p lies strictly inside a triangle, that triangle is replaced by the three-triangle fan from its edges to p. If p lies in the interior of an edge, the edge splits into two collinear halves — which inherit its constrained flag and its label — and each incident triangle (two for an interior edge, one on the convex-hull boundary) splits in two. If p lies strictly outside the convex hull, the hull grows: p is joined to every hull edge it strictly sees, one new triangle per edge (the only triangulation of the pocket between the hull and the point); a constrained hull edge stays constrained and simply becomes interior. All other edges keep their labels; the replacement triangles get default-constructed labels, as with flip.

The change is purely local — no other connectivity changes — so a Delaunay triangulation does not generally stay Delaunay; use insertDelaunay for that.

Parameters
pThe vertex to insert.
Precondition
For a triangulation built from a polygon, p lies in the closed polygon. Inserting a point outside it — in the carved-away region between polygon and hull, or beyond the hull — is undefined behavior, like the polygon constructors' extra points (not checked).
Returns
true if the vertex was inserted; false — with the triangulation unchanged — if p is already a vertex or the triangulation is empty.

◆ insertDelaunay()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::insertDelaunay ( const PointType & p)
inline

Inserts p as a new vertex and restores the constrained Delaunay property around it.

Performs insert, then legalizes outward from p by Lawson flips, never flipping a constrained edge: if the triangulation satisfied the constrained Delaunay property before the call (as built by the point-set and polygon constructors), it satisfies it after. Edges and triangles touched by the legalizing flips have their labels reset, as with flip; the halves of a split edge inherit its constrained flag and label, as with insert.

Parameters
pThe vertex to insert.
Precondition
As for insert: for a triangulation built from a polygon, p lies in the closed polygon (not checked).
Returns
true if the vertex was inserted; false — with the triangulation unchanged — under the same conditions as insert.

◆ interiorContains() [1/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<EmptyShapeConcept E>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const E & ) const
inlinenodiscard

◆ interiorContains() [2/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<HalfplaneIntersectionConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorContains() [3/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonSetConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorContains() [4/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonWithHolesConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorContains() [5/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorContains() [6/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Q & shape) const
inlinenodiscard

True if the domain's interior contains shape (A∖∂A ⊇ B).

The domain minus its boundary: shape must lie inside it without touching the polygon's edges (or, for a hull domain, the hull's). So it is contains plus "meets no boundary edge of the domain" — an edge with a ghost or a hull-fill triangle on its far side. A shape lying along a polygon edge is contained but not interior-contained.

Parameters
shapeQuery shape; it may use a different point type.

◆ interiorContains() [7/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorContains ( const Shape< PointType > & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [1/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<EmptyShapeConcept E>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const E & ) const
inlinenodiscard

◆ interiorsIntersect() [2/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<HalfplaneIntersectionConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [3/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonSetConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [4/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonWithHolesConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [5/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [6/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery Q>
requires (!PointConcept<Q>)
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ interiorsIntersect() [7/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PointConcept QueryPoint>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const QueryPoint & shape) const
inlinenodiscard

True if the domain's interior meets shape's interior (A∖∂A ∩ B∖∂B ≠ ∅).

Contact along the boundary of either does not count: a segment lying on a polygon edge, or a triangle of the mesh sharing only an edge with shape, do not interior-intersect the domain.

Parameters
shapeQuery shape; it may use a different point type.

◆ interiorsIntersect() [8/8]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::interiorsIntersect ( const Shape< PointType > & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ intersects() [1/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<EmptyShapeConcept E>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const E & ) const
inlinenodiscard

◆ intersects() [2/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<HalfplaneIntersectionConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ intersects() [3/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonSetConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ intersects() [4/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonWithHolesConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ intersects() [5/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PolygonConcept Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Q & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ intersects() [6/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery Q>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Q & shape) const
inlinenodiscard

True if the triangulated domain meets shape (A ∩ B ≠ ∅).

Closed intersection, as for contains: a shape touching the domain only along its boundary meets it. This is precisely "some triangle of the mesh meets @p shape", which is what the traversals report, so it is the cheapest of the four predicates — the walk stops at the first triangle found.

Parameters
shapeQuery shape; it may use a different point type.

◆ intersects() [7/7]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::intersects ( const Shape< PointType > & shape) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ isConstrained() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::isConstrained ( const SegmentType & s) const
inlinenodiscard

True if edge s is flagged as constrained.

◆ isConstrained() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::isConstrained ( TriId t,
int side ) const
inlinenodiscard

True if side side of t is a constrained edge.

Handle counterpart of isConstrained(const SegmentType&) const, with the edge named by the triangle it belongs to and its index there (see otherTriangle(TriId, int) const for the side convention). Constraints are what the polygon and region constructors mark their boundary with, so this is also how a walk recognizes the boundary of the shape it came from without keeping a set of its edges.

Parameters
tHandle of a triangle of the triangulation.
sideWhich of its three edges to test, in [0, 3).
Precondition
has(t).

◆ label() [1/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = SegmentLabel>
requires (detail::has_label_v<L>)
L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( const SegmentType & s)
inlinenodiscard

Returns a reference to the label stored for edge s.

The reference is into the triangulation's own storage, so assigning through it (tri.label(s) = ...) changes the label every later accessor reports for that edge. Only available when the segment type carries a label.

Parameters
sAn edge of this triangulation.
Returns
Reference to its stored label.
Precondition
has(s)s is one of the triangulation's edges.

◆ label() [2/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = SegmentLabel>
requires (detail::has_label_v<L>)
const L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( const SegmentType & s) const
inlinenodiscard

◆ label() [3/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( const TriangleType & t)
inlinenodiscard

Returns a reference to the label stored for triangle t.

The reference is into the triangulation's own storage, so assigning through it (tri.label(t) = ...) changes the label every later accessor reports for that triangle. Only available when the triangle type carries a label.

Parameters
tA triangle of this triangulation.
Returns
Reference to its stored label.
Precondition
has(t)t is one of the triangulation's triangles.

◆ label() [4/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
const L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( const TriangleType & t) const
inlinenodiscard

◆ label() [5/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( TriId t)
inlinenodiscard

Returns a reference to the label stored for the triangle t.

Handle counterpart of label(const TriangleType&), reaching the same storage without the hash lookup that resolving a triangle value needs.

Parameters
tHandle of a triangle of this triangulation.
Precondition
has(t).

◆ label() [6/6]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class L = TriangleLabel>
requires (detail::has_label_v<L>)
const L & pgl::Triangulation< TriangleType_, SegmentType_ >::label ( TriId t) const
inlinenodiscard

◆ locate()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PointConcept QueryPoint>
std::optional< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::locate ( const QueryPoint & p) const
inlinenodiscard

Finds the triangle containing the query point by walking the mesh.

Uses a stochastic (randomized) visibility walk, which terminates with probability one on any valid triangulation, not just Delaunay ones; a generous step cap remains only as a defensive bound. After buildPointLocation a query descends the point-location hierarchy instead, for the same answer in logarithmic time.

Parameters
pQuery point; may use a different point type than the triangulation.
Returns
The containing triangle, or std::nullopt if p lies outside the triangulated region (or the triangulation is empty).

◆ locateId() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
TriId pgl::Triangulation< TriangleType_, SegmentType_ >::locateId ( const PointType & p) const
inlinenodiscard

Finds the triangle containing the query point, as a handle.

Handle counterpart of locate: the same stochastic visibility walk, answering with the triangle's handle instead of its value. This is the hash-free way into the handle world for a point that is not a vertex — getId(*locate(p)) would locate the triangle and then look it up again.

buildPointLocation replaces the walk by a descent of the point-location hierarchy, which is what a query pays for; it does not change what a query may return.

Parameters
pQuery point; may use a different point type than the triangulation.
Returns
The handle of the containing triangle, or the invalid handle if p lies outside the triangulated region (or the triangulation is empty).

◆ locateId() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<PointConcept QueryPoint>
TriId pgl::Triangulation< TriangleType_, SegmentType_ >::locateId ( const QueryPoint & p) const
inlinenodiscard

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. Queries with matching coordinate types take their walk's start from the index whenever their points can be converted too. Other coordinate types walk from the usual hint, avoiding a potentially lossy conversion into the index's own point type.

◆ numEdges()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::size_t pgl::Triangulation< TriangleType_, SegmentType_ >::numEdges ( ) const
inlinenodiscard

Number of undirected edges incident to the visible triangulation.

◆ numTriangles()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::size_t pgl::Triangulation< TriangleType_, SegmentType_ >::numTriangles ( ) const
inlinenodiscard

Number of triangles (excludes ghost and out-of-domain fill triangles).

◆ numVertices()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::size_t pgl::Triangulation< TriangleType_, SegmentType_ >::numVertices ( ) const
inlinenodiscard

Number of real vertices (excludes the ghost vertex).

◆ operator[]() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
TriangleType pgl::Triangulation< TriangleType_, SegmentType_ >::operator[] ( TriId t) const
inlinenodiscard

◆ operator[]() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
const PointType & pgl::Triangulation< TriangleType_, SegmentType_ >::operator[] ( VertexId v) const
inlinenodiscard

◆ otherTriangle() [1/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::optional< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::otherTriangle ( const TriangleType & t,
const SegmentType & shared ) const
inlinenodiscard

The triangle on the other side of shared from t.

Parameters
tA triangle of the triangulation.
sharedAn edge of t.
Returns
The adjacent triangle across shared, or std::nullopt if that edge is on the boundary or the arguments are not part of the mesh.

◆ otherTriangle() [2/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::optional< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::otherTriangle ( TriId t,
int side ) const
inlinenodiscard

The triangle on the other side of side side of t.

Side i of a triangle is the edge from vertices(t)[i] to vertices(t)[(i + 1) % 3], which is getShape(t).edges()[i]. Crossing it is one array read, so a walk over the mesh never has to name an edge by its segment.

Parameters
tHandle of a triangle of the triangulation.
sideWhich of its three edges to cross, in [0, 3).
Returns
The adjacent triangle across that edge, or std::nullopt when the edge is on the boundary of the domain.
Precondition
has(t).

◆ otherTriangle() [3/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::optional< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::otherTriangle ( TriId t,
VertexId a,
VertexId b ) const
inlinenodiscard

The triangle on the other side of edge a b from t.

Handle counterpart of otherTriangle(const TriangleType&, const SegmentType&) const, with the shared edge given by its two endpoints instead of as a segment.

Parameters
tHandle of a triangle of the triangulation.
aOne endpoint of an edge of t.
bThe other endpoint of that edge.
Returns
The adjacent triangle across that edge, or std::nullopt if the edge is on the boundary of the domain or is not an edge of t.

◆ reducedVisibilityGraph()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
Graph< typename Triangulation< TriangleType_, SegmentType_ >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::reducedVisibilityGraph ( ) const
nodiscard

Returns the reduced visibility graph of the mesh vertices.

The subgraph of visibilityGraph holding the edges a shortest path can bend along: those tangent to the obstacles at both ends. An edge uv is tangent at u when the walls incident to u all lie in one closed half-plane of the line uv, which is what lets a taut path bend there. A vertex with no incident wall — a free point inside the domain — bends no path and comes back isolated.

The surviving edges are the walls themselves and the bitangents between reflex corners, so this is much sparser than visibilityGraph.

This graph alone does not answer shortest-path queries. What it guarantees is the interior of a geodesic: an edge lying strictly inside some shortest path has that path bending at both its ends, is therefore tangent at both, and survives. A path does not bend at its own endpoints, though — it merely starts and ends there — so its first and last hop need no tangency and may well have been pruned. To route between two points, vertices or not, add each of them joined to everything it sees:

auto graph = mesh.reducedVisibilityGraph();
for (const auto& w : mesh.visibilityGraph().neighbors(source)) {
graph.addEdge(source, w); // and the same for the target
}

Using it unaided returns a path that exists but is too long: a convex corner keeps only its two boundary edges, so a route starting there is forced along the wall.

Complexity: visibilityGraph plus O(E·w) for w walls per vertex, which is two along a polygon boundary.

Returns
An undirected graph over this triangulation's vertices.

◆ regularizedVisiblePolygon()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
template<class ResultNumber>
Polygon< Point< ResultNumber > > pgl::Triangulation< TriangleType_, SegmentType_ >::regularizedVisiblePolygon ( const PointType & query) const
nodiscard

The region of the domain visible from query, regularized.

The visibility polygon: every point reachable from query by a segment that stays in the domain and crosses no wall. Being star-shaped about query it is simply connected, so the result is one Polygon however many holes or walls the domain has.

Regularized means the closure of the interior, which drops the lower-dimensional slivers grazing sight would otherwise add: a sightline running along a wall, or straight through a vertex into a region beyond that has no area, contributes a one-dimensional spike to the visible set and none to this. What comes back always bounds area.

Its vertices are the domain's own vertices together with the window ends where a sightline past a reflex corner lands on a farther edge. Those are ray-edge intersections and need division, so the result type is requested explicitly, as everywhere in the library.

query on the boundary is a vertex of the result. Should the domain pinch so that the visible region reaches query along more than one lobe, the ring passes through query once per lobe and is then only weakly simple.

Template Parameters
ResultNumberCoordinate type of the result (default: division_result_t of the mesh's own).
Parameters
queryPoint to look from.
Returns
The visible region, counterclockwise; empty when query lies outside the domain.

◆ setConstrained() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
void pgl::Triangulation< TriangleType_, SegmentType_ >::setConstrained ( const SegmentType & s,
bool value = true )
inline

Flags (or clears) edge s as constrained on both incident sides.

◆ setConstrained() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
void pgl::Triangulation< TriangleType_, SegmentType_ >::setConstrained ( TriId t,
int side,
bool value = true )
inline

Constrains (or unconstrains) side side of t.

Handle counterpart of setConstrained(const SegmentType&, bool). The flag belongs to the edge, so it is set on both incident triangles and a later isConstrained sees it from either side.

Parameters
tHandle of a triangle of the triangulation.
sideWhich of its three edges to mark, in [0, 3).
valuetrue to constrain the edge, false to release it.
Precondition
has(t).

◆ triangleIds()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::triangleIds ( ) const
inlinenodiscard

The handles of every triangle, in storage order.

The order is the triangulation's own, which is neither the sorted order of triangles nor a stable one across edits, but is the order that reads the connectivity arrays front to back.

◆ triangleIndexBound()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::size_t pgl::Triangulation< TriangleType_, SegmentType_ >::triangleIndexBound ( ) const
inlinenodiscard

One past the largest index a TriId of this triangulation can carry.

id.index() is therefore a slot of a side table of this size — a plain std::vector rather than a map — for every handle the triangulation hands out. The indices are dense over [0, triangleIndexBound()), but the range also covers the triangles a polygon or region domain carved away, which has rejects and no query returns: it is a bound on the storage, not a triangle count, and exceeds numTriangles by exactly those.

◆ triangles()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::triangles ( ) const
inlinenodiscard

Returns all triangles, sorted.

◆ trianglesInteriorIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::trianglesInteriorIntersecting ( const OS & s) const
inlinenodiscard

Returns the triangles whose interior s enters.

A materialized form of visitTrianglesInteriorIntersecting: the in-domain triangles t with t.interiorsIntersect(s) — in the order they are encountered along a segment or chain s, or an unspecified order for a region query shape.

Parameters
sA directed query — segment, oriented segment, line, oriented line, or ray — or a chain (polyline, monotone chain), both traced in order; or a region query shape (reported in an unspecified order). It may use a different point type.

◆ trianglesIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::trianglesIntersecting ( const OS & s) const
inlinenodiscard

Returns the triangles met by s (a segment, (oriented) line, ray, or chain, in order, or a region query shape, in an unspecified order).

A materialized form of visitTrianglesIntersecting: the in-domain triangles t with s.intersects(t), in the order they are encountered along s. The order is preserved (not sorted), since it is the point of the traversal.

Parameters
sA directed query — segment, oriented segment, line, oriented line, or ray — or a chain (polyline, monotone chain), both traced in order; or a region query shape (reported in an unspecified order). It may use a different point type.

◆ vertexAdjacentTriangles() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriangleType > pgl::Triangulation< TriangleType_, SegmentType_ >::vertexAdjacentTriangles ( const TriangleType & t) const
inlinenodiscard

The triangles sharing at least one vertex with t (excluding t).

The union of the vertex fans of t's three vertices: every triangle touching t at a vertex or across an edge, each listed once. A superset of edgeAdjacentTriangles.

Parameters
tA triangle of the triangulation.
Returns
The triangles sharing a vertex with t; empty if t is not part of the mesh.

◆ vertexAdjacentTriangles() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< TriId > pgl::Triangulation< TriangleType_, SegmentType_ >::vertexAdjacentTriangles ( TriId t) const
inlinenodiscard

The triangles sharing at least one vertex with t (excluding t).

Handle counterpart of vertexAdjacentTriangles(const TriangleType&) const.

◆ vertexIds()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::vector< VertexId > pgl::Triangulation< TriangleType_, SegmentType_ >::vertexIds ( ) const
inlinenodiscard

The handles of every vertex, in storage order.

Every stored vertex is listed, including one that carries no triangle (duplicated, or collinear with every other point), exactly as numVertices counts them. The internal ghost vertex is not one of them.

◆ vertexIndexBound()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::size_t pgl::Triangulation< TriangleType_, SegmentType_ >::vertexIndexBound ( ) const
inlinenodiscard

One past the largest index a VertexId of this triangulation can carry.

As with triangleIndexBound, id.index() is a slot of a side table of this size. Vertex indices are dense over [1, vertexIndexBound()): slot 0 belongs to the internal ghost vertex that closes the mesh at infinity and is never handed out, so a table indexed by id.index() - 1 is the tight one of numVertices entries.

◆ vertices()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
std::array< VertexId, 3 > pgl::Triangulation< TriangleType_, SegmentType_ >::vertices ( TriId t) const
inlinenodiscard

The three vertices of a triangle, counterclockwise.

Handle counterpart of getShape(t).vertices(): the order is the same one TriangleType normalizes to, the lexicographically smallest vertex first, so vertices(t)[i] is the vertex at getShape(t)[i].

Parameters
tHandle of a triangle of this triangulation.
Precondition
has(t).

◆ visibilityGraph()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
Graph< typename Triangulation< TriangleType_, SegmentType_ >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::visibilityGraph ( ) const
nodiscard

Returns the visibility graph of the mesh vertices.

Sight is stopped by the boundary of the domain and by every constrained edge, which therefore act as opaque walls: poly.triangulation(walls) answers visibility inside poly among the obstacles walls. An unconstrained interior edge is transparent, so the visibility graph of a plain point-set triangulation is the complete graph over its convex hull.

Two vertices are adjacent exactly when the closed segment joining them stays in the closed domain and never crosses a wall. Grazing counts: a segment that runs along a wall, touches a boundary vertex, or passes straight through another vertex without leaving the domain is a visibility edge. See clearVisibilityGraph for the convention that forbids it.

The mesh's own edges are always present, and a vertex with no in-domain triangle comes back isolated rather than absent.

Computed by triangular expansion: one cone-clipped traversal of the mesh per vertex, whose cost is proportional to the part of the domain that vertex actually sees, followed by a walk along each collinear chain. Every test is an orientation predicate on stored vertices, so an exact coordinate type stays exact and nothing is ever constructed.

Complexity: O(V·T + E) for V vertices, E visibility edges and T triangles seen per vertex; T is O(1) in a corridor-like domain and O(V) at worst.

Returns
An undirected graph over this triangulation's vertices.

◆ visibleVertices()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_>
std::vector< typename Triangulation< TriangleType_, SegmentType_ >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::visibleVertices ( const PointType & query) const
nodiscard

The mesh vertices visible from query.

Same convention as visibilityGraph, for a point that need not be a vertex: a vertex v is reported when the closed segment queryv stays in the closed domain and crosses no wall, grazing included. Together with reducedVisibilityGraph this is what routes a shortest path between arbitrary points — that graph alone holds only the edges a path can bend along, so each endpoint needs joining to everything it sees:

auto graph = mesh.reducedVisibilityGraph();
for (const auto& w : mesh.visibleVertices(source)) {
graph.addEdge(source, w); // and the same for the target
}

Costs one cone-clipped traversal of the mesh, proportional to the part of the domain query actually sees — never the whole visibility graph.

Parameters
queryPoint to look from; outside the domain nothing is visible.
Returns
The visible vertices, counterclockwise around query starting from the lexicographically smallest, as sortAround orders them. Empty when query lies outside the domain.

◆ visitEdges()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitEdges ( Fn fn) const
inline

Calls fn(Segment) on every edge, with its stored label.

If fn returns a value convertible to bool, the visit stops early as soon as it returns true; a void-returning fn visits every edge.

Returns
true if the visit was stopped early, false otherwise.

◆ visitEdgesInteriorIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitEdgesInteriorIntersecting ( const OS & s,
Fn f ) const
inline

Visits the triangulation edges whose interior s crosses.

Like visitEdgesIntersecting but reports only the edges e with s.interiorsIntersect(e) — dropping those merely touched at a shared endpoint (e.g. where a segment s passes through a mesh vertex, or an endpoint of s lands on an edge). s may be a directed query, a chain, or a region query shape.

f follows the visitor convention (return true to stop early, void to visit all); returns whether the walk stopped early. s may use a different point type than the triangulation.

◆ visitEdgesIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitEdgesIntersecting ( const OS & s,
Fn f ) const
inline

Visits every triangulation edge met by s.

Reports each in-domain edge e with s.intersects(e) exactly once, with its stored label (for a segment or chain s, roughly in the order it meets them, ties broken arbitrarily; for a region query shape, in an unspecified order). Built on visitTrianglesIntersecting: as each met triangle is visited, its edges that s meets are reported (deduplicated across the two triangles sharing an edge). Edges of ghost or out-of-domain triangles are never reported, matching edges.

f follows the visitor convention (return true to stop early, void to visit all); returns whether the walk stopped early. s may use a different point type than the triangulation.

◆ visitTriangles()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitTriangles ( Fn fn) const
inline

Calls fn(Triangle) — or fn(TriId) — on every triangle.

A fn that accepts a TriangleType is given triangle values; one that accepts only a TriId is given handles instead, so a global pass can work in the handle world without materializing a triangle per step. A generic callable ([](auto t)) accepts both and is given values.

If fn returns a value convertible to bool, the visit stops early as soon as it returns true; a void-returning fn visits every triangle.

Returns
true if the visit was stopped early, false otherwise.

◆ visitTrianglesInteriorIntersecting()

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationQuery OS, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitTrianglesInteriorIntersecting ( const OS & s,
Fn f ) const
inline

Visits the triangles whose interior s actually enters.

Like visitTrianglesIntersecting but reports only the triangles t with t.interiorsIntersect(s) — dropping those merely touched along an edge or at a vertex. The traversal still passes through every met triangle for navigation; the filtered ones simply are not reported. s may be a directed query or a chain (reported in order) or a region query shape (unspecified order).

f follows the visitor convention (return true to stop early, void to visit all); returns whether the walk stopped early. s may use a different point type than the triangulation.

◆ visitTrianglesIntersecting() [1/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::ChainTraversal C, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitTrianglesIntersecting ( const C & c,
Fn f ) const
inline

Visits every in-domain triangle that intersects the chain c, in the order the chain first meets them.

Generalizes visitTrianglesIntersecting(const OS&, Fn) const from a single segment to a polygonal chain — a Polyline or a MonotoneChain. The chain is traced edge by edge with the directed segment walk, from vertex c[0] towards c[c.size() - 1], and each triangle is reported the first time it is met: the set passed to f is exactly { t : t.intersects(c) } over the in-domain triangles, so a triangle met again by a later edge (a chain that turns back into it, or self-intersects) is not reported twice. A chain that leaves the triangulated region and comes back is handled — unlike the region flood fill, the per-edge walks re-enter it — and a chain with a single vertex is the point query.

The cost is that of the individual segment walks: proportional to the triangles met, plus one point location per edge.

f follows the visitor convention: returning true stops the walk early, a void return visits every such triangle. Returns whether it stopped early. c may use a different point type.

◆ visitTrianglesIntersecting() [2/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::DirectedTraversal OS, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitTrianglesIntersecting ( const OS & s,
Fn f ) const
inline

Visits every triangle met by the directed query s, in order.

s may be a segment, oriented segment, line, oriented line, or ray. For a segment, it locates s.source(), visits the triangles touching it (if any), then traces s to s.target(). A line or oriented line has no finite endpoints: it enters the hull at the ghost where the directed line s[0]->s[1] crosses in (found by a directional descent of the ghost ring) and traces forward until it leaves the hull again. A ray keeps s.source() (located, or entered at that directional ghost when the source is outside the hull) but, like a line, runs forward until it leaves the hull rather than stopping at a target. Either way each triangle crossed is visited — including the fan where s passes through a vertex — and the set passed to f is exactly { t : s.intersects(t) } over the in-domain triangles, in the order they are met along s[0]->s[1] (a plain line's order follows its arbitrary defining-point direction). Ghost triangles and (for a polygon) out-of-domain hull-fill triangles are traversed for navigation but never reported, so a query leaving and re-entering the polygon through a reflex pocket simply shows a gap.

f follows the visitor convention: returning true stops the walk early, a void return visits all. Returns whether it stopped early. As in visitTriangles, an f that accepts only a TriId is given handles instead of triangle values. s may use a different point type than the triangulation.

◆ visitTrianglesIntersecting() [3/3]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<detail::TriangulationRegionQuery Q, class Fn>
bool pgl::Triangulation< TriangleType_, SegmentType_ >::visitTrianglesIntersecting ( const Q & shape,
Fn f ) const
inline

Visits every in-domain triangle that intersects shape.

Generalizes visitTrianglesIntersecting(const OS&, Fn) const from a segment to a connected convex query shape — a point, triangle, rectangle, convex polygon, or an unbounded line, oriented line, ray, or half-plane. The set of triangles t passed to f is exactly { t : t.intersects(shape) } over the in-domain triangles, in an unspecified order.

The work is local. A seed triangle meeting shape is found by navigation — tracing shape's boundary edges with the segment walk (for a bounded shape), or scanning the convex-hull boundary for an edge it crosses (for an unbounded one) — and the reported set is then grown by a flood fill through edge/vertex adjacency that never strays past the triangles meeting shape and their immediate neighbours. The cost is therefore proportional to the number of triangles met, not to the size of the triangulation; the lone exception is the unbounded-shape seed search, which scans the hull and is O(hull).

f follows the visitor convention: returning true stops the walk early, a void return visits every such triangle. Returns whether it stopped early. shape may use a different point type.

◆ voronoiDiagram() [1/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class ResultNumber>
Arrangement< Point< ResultNumber >, typename Triangulation< TriangleType, SegmentType >::PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::voronoiDiagram ( ) const

◆ voronoiDiagram() [2/2]

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
template<class ResultNumber = division_result_t<NumberType>>
Arrangement< Point< ResultNumber >, PointType > pgl::Triangulation< TriangleType_, SegmentType_ >::voronoiDiagram ( ) const
nodiscard

Returns the Voronoi diagram dual to this Delaunay triangulation.

The result is an unbounded Arrangement whose faces are labeled by their generating vertices: after locating a query in a face f, diagram.label(f) is the nearest vertex. On a Voronoi edge or vertex, Arrangement::locateFace applies its usual infinitesimal perturbation and therefore selects one of the tied sites; use Arrangement::locateCell and inspect the incident faces to recover every tied site.

The dual is built from the current triangle connectivity. An interior Delaunay edge becomes a segment between the two incident circumcenters, and a convex-hull edge becomes an outward ray. Cocircular triangles may have the same circumcenter; their zero-length dual edge is omitted.

The arrangement's edge labels are default-constructed and have no meaning; its face labels are the stored PointType values.

Template Parameters
ResultNumberCoordinate type of the arrangement vertices. The default is exact and overflow-free for integral input.
Precondition
The triangulation is not empty.
Its current real triangles form a Delaunay triangulation of all its stored vertices (equivalently, they triangulate their convex hull and every edge is locally Delaunay). This precondition is not checked.
Returns
The unbounded Voronoi arrangement, with one site-labeled face per stored vertex.

◆ operator<<

template<TriangleConcept TriangleType_, SegmentConcept SegmentType_ = typename TriangleType_::template BoundaryType<false>>
Canvas & operator<< ( Canvas & canvas,
const Triangulation< TriangleType_, SegmentType_ > & triangulation )
friend

Draws every triangle to a canvas.

Parameters
canvasDestination canvas.
triangulationTriangulation whose triangles are drawn.
Returns
The canvas.