DelaunayTriangulation.AbstractParametricCurveType
abstract type AbstractParametricCurve <: Function end

Abstract type for representing a parametric curve parametrised over 0 ≤ t ≤ 1. The curves represented by this abstract type should not be self-intersecting, with the exception of allowing for closed curves.

The structs that subtype this abstract type must implement are:

Functions that are defined for all AbstractParametricCurve subtypes are:

Efficiently computing the total variation

The curves in this package evaluate the total variation not by evaluating the integral itself, but by taking care of the changes in orientation in the curve to efficiently compute it. This is done by using the orientation markers of the curves, obtained using orientation_markers, that stored in the field orientation_markers of these curves. The function marked_total_variation is then used to evaluate it. You may like to consider using these functions for any curve you wish to implement yourself, using e.g. the BezierCurve struct's implementation as a reference.

DelaunayTriangulation.AdjacentType
Adjacent{IntegerType, EdgeType}

Struct for storing adjacency relationships for a triangulation.

Fields

  • adjacent::Dict{EdgeType, IntegerType}

The map taking edges (u, v) to w such that (u, v, w) is a positively oriented triangle in the underlying triangulation.

Constructors

Adjacent{IntegerType, EdgeType}()
Adjacent(adjacent::Dict{EdgeType, IntegerType})
DelaunayTriangulation.Adjacent2VertexType
Adjacent2Vertex{IntegerType, EdgesType}

Struct for connectivity information about edges relative to vertices for a triangulation.

Fields

  • adjacent2vertex::Dict{IntegerType, EdgesType}

The map taking w to the set of all (u, v) such that (u, v, w) is a positively oriented triangle in the underlying triangle.

Constructors

Adjacent2Vertex{IntegerType, EdgesType}()
Adjacent2Vertex(adj2v::Dict{IntegerType, EdgesType})
DelaunayTriangulation.BSplineType
BSpline <: AbstractParametricCurve

Curve for representing a BSpline, parametrised over 0 ≤ t ≤ 1. This curve can be evaluated using b_spline(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

See also BezierCurve and CatmullRomSpline.

Our implementation of a BSpline is based on https://github.com/thibauts/b-spline.

Loops

This curve is only tested on loop-free curves (and closed curves that otherwise have no self-intersections). It is not guaranteed to work on curves with loops, especially for finding the nearest point on the curve to a given point.

Interpolation

Remember that B-spline curves are not interpolation curves. They only go through the first and last control points, but not the intermediate ones. For an interpolating spline, see CatmullRomSpline.

Fields

  • control_points::Vector{NTuple{2,Float64}}: The control points of the BSpline. The curve goes through the first and last control points, but not the intermediate ones.
  • knots::Vector{Int}: The knots of the BSpline. You should not modify or set this field directly (in particular, do not expect any support for non-uniform B-splines).
  • cache::Vector{NTuple{2,Float64}}: A cache of the points on the curve. This is used to speed up evaluation of the curve using de Boor's algorithm.
  • lookup_table::Vector{NTuple{2,Float64}}: A lookup table for the B-spline curve, used for finding the point on the curve closest to a given point. The ith entry of the lookup table corresponds to the t-value i / (length(lookup_table) - 1).
  • orientation_markers::Vector{Float64}: The orientation markers of the curve. These are defined so that the orientation of the curve is monotone between any two consecutive markers. The first and last markers are always 0 and 1, respectively. See orientation_markers.

Constructor

You can construct a BSpline using

BSpline(control_points::Vector{NTuple{2,Float64}}; degree=3, lookup_steps=5000, kwargs...)

The keyword argument lookup_steps is used to build the lookup table for the curve. Note that the default degree=3 corresponds to a cubic B-spline curve. The kwargs... are keyword arguments passed to orientation_markers.

DelaunayTriangulation.BalancedBSTType
mutable struct BalancedBST{K}

Struct representing a balanced binary search tree.

Fields

  • root::Union{Nothing,BalancedBSTNode{K}}: The root of the tree.
  • count::Int32: The number of nodes in the tree.
Duplicate keys

Nodes with duplicate keys are not supported. If a duplicate key is inserted, the tree will not be modified.

DelaunayTriangulation.BalancedBSTNodeType
mutable struct BalancedBSTNode{K}

Struct representing a node in a balanced binary search tree.

Fields

  • key::K: The key associated with the node.
  • height::Int8: The height of the node.
  • count::Int32: The number of nodes in the subtree rooted at this node, including this node.
  • parent::Union{Nothing,BalancedBSTNode{K}}: The parent of the node.
  • left::Union{Nothing,BalancedBSTNode{K}}: The left child of the node.
  • right::Union{Nothing,BalancedBSTNode{K}}: The right child of the node.

Constructor

BalancedBSTNode(key::K) where {K}

Constructs a new node with key key, height 1, and count 1. The parent, left child, and right child are set to nothing.

DelaunayTriangulation.BezierCurveType
BezierCurve <: AbstractParametricCurve

Curve for representing a Bezier curve, parametrised over 0 ≤ t ≤ 1. This curve can be evaluated using bezier_curve(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

A good reference on Bezier curves is this.

See also BSpline and CatmullRomSpline.

Loops

This curve is only tested on loop-free curves (and closed curves that otherwise have no self-intersections). It is not guaranteed to work on curves with loops, especially for finding the nearest point on the curve to a given point.

Interpolation

Remember that Bezier curves are not interpolation curves. They only go through the first and last control points, but not the intermediate ones. If you want an interpolation curve, use CatmullRomSpline.

Fields

  • control_points::Vector{NTuple{2,Float64}}: The control points of the Bezier curve. The curve goes through the first and last control points, but not the intermediate ones.
  • cache::Vector{NTuple{2,Float64}}: A cache of the points on the curve. This is used to speed up evaluation of the curve using de Casteljau's algorithm.
  • lookup_table::Vector{NTuple{2,Float64}}: A lookup table for the Bezier curve, used for finding the point on the curve closest to a given point. The ith entry of the lookup table corresponds to the t-value i / (length(lookup_table) - 1).
  • orientation_markers::Vector{Float64}: The orientation markers of the curve. These are defined so that the orientation of the curve is monotone between any two consecutive markers. The first and last markers are always 0 and 1, respectively. See orientation_markers.
Concurrency

The cache is not thread-safe, and so you should not evaluate this curve in parallel.

Constructor

You can construct a BezierCurve using

BezierCurve(control_points::Vector{NTuple{2,Float64}}; lookup_steps=5000, kwargs...)

The keyword argument lookup_steps=100 controls how many time points in [0, 1] are used for the lookup table. The kwargs... are keyword arguments passed to orientation_markers.

DelaunayTriangulation.BoundaryEnricherType
BoundaryEnricher{P,B,C,I,BM,S}

Struct used for performing boundary enrichment on a curve-bounded boundary.

See also enrich_boundary!.

Fields

  • points::P: The point set.
  • boundary_nodes::B: The boundary nodes.
  • segments::S: The segments.
  • boundary_curves::C: The boundary curves.
  • polygon_hierarchy::PolygonHierarchy{I}: The polygon hierarchy.
  • parent_map::Dict{NTuple{2,I},I}: A map from an edge, represented as a Tuple, to the index of the parent curve in boundary_curves.
  • curve_index_map::Dict{I,I}: A map from a curve index to the index of the curve in boundary_curves.
  • boundary_edge_map::B: A map from a boundary node to the index of the curve in boundary_curves that it belongs to. See construct_boundary_edge_map.
  • spatial_tree::BoundaryRTree{P}: The BoundaryRTree used for spatial indexing.
  • queue::Queue{I}: A queue used for processing vertices during enrichment.
  • small_angle_complexes::Dict{I,Vector{SmallAngleComplex{I}}}: A map from an apex vertex to a list of all curves that define a small angle complex associated with that apex vertex.

The first three fields should be those associated with convert_boundary_curves!.

Constructor

BoundaryEnricher(points, boundary_nodes; IntegerType=Int, n=4096, coarse_n=0)

This constructor will use convert_boundary_curves! to convert points and boundary_nodes into a set of boundary curves and modified boundary nodes suitable for enrichment. The boundary nodes field will no longer aliased with the input boundary_nodes, although points will be. The polygon hierarchy is computed using construct_polygon_hierarchy. The argument n is used in polygonise for filling out the boundary temporarily in order to construct the PolygonHierarchy. The argument coarse_n defines the initial coarse discretisation through coarse_discretisation!; the default n=0 means that the coarse discretisation will be performed until the maximum total variation of a subcurve is less than π/2.

DelaunayTriangulation.BoundaryRTreeType
BoundaryRTree{P}

Type for representing an R-tree of a boundary with an associated point set. The rectangular elements of the R-tree are the bounding box of the diametral circles of the boundary edges.

Fields

  • tree::RTree: The R-tree.
  • points::P: The point set.

Constructors

BoundaryRTree(points)
DelaunayTriangulation.BoundingBoxType
BoundingBox <: AbstractBoundingShape

Type for representing an axis-aligned bounding box, represented as a pair of interval I and J so that the bounding box is I × J.

Fields

  • x::BoundingInterval: The interval for the x-axis.
  • y::BoundingInterval: The interval for the y-axis.

Constructors

BoundingBox(x::BoundingInterval, y::BoundingInterval)
BoundingBox(a::Float64, b::Float64, c::Float64, d::Float64) = BoundingBox(BoundingInterval(a, b), BoundingInterval(c, d))
BoundingBox(p::NTuple{2,<:Number}) = BoundingBox(p[1], p[1], p[2], p[2])
DelaunayTriangulation.BoundingIntervalType
BoundingInterval <: AbstractBoundingShape

Type for representing a bounding interval [a, b].

Fields

  • a::Float64: The left endpoint.
  • b::Float64: The right endpoint.
DelaunayTriangulation.BranchType
mutable struct Branch <: AbstractNode

Type for representing a branch node in an R-tree.

Fields

  • parent::Union{Branch, Nothing}: The parent of the branch node.
  • bounding_box::BoundingBox: The bounding box of the branch node.
  • children::Union{Vector{Branch},Vector{Leaf{Branch}}}: The children of the branch node.
  • level::Int: The level of the branch node.

Constructor

Branch(parent::Union{Branch,Nothing}=nothing, ::Type{C}=Branch) where {C<:AbstractNode} = new(parent, InvalidBoundingBox, C[], 1)
DelaunayTriangulation.CatmullRomSplineType
CatmullRomSpline <: AbstractParametricCurve

Curve for representing a Catmull-Rom spline, parametrised over 0 ≤ t ≤ 1. This curve can be evaluated using catmull_rom_spline(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

For information on these splines, see e.g. this article and this article. Additionally, this article lists some nice properties of these splines.

Loops

This curve is only tested on loop-free curves (and closed curves that otherwise have no self-intersections). It is not guaranteed to work on curves with loops, especially for finding the nearest point on the curve to a given point.

Extension

Typically, Catmull-Rom splines are defined on segments of four control points, and drawn between the two interior control points. This creates an issue in that the first and last control points will not be joined to the spline. To overcome this, we extend the spline to the left and right during the evaluation of a spline, using the fields left and right defined below. The rules used for extending these points come from CatmullRom.jl, which extrapolates based on a Thiele-like cubic polynomial.

Fields

  • control_points::Vector{NTuple{2,Float64}}: The control points of the Catmull-Rom spline. The curve goes through each point.
  • knots::Vector{Float64}: The parameter values of the Catmull-Rom spline. The ith entry of this vector corresponds to the t-value associated with the ith control point. With an alpha parameter α, these values are given by knots[i+1] = knots[i] + dist(control_points[i], control_points[i+1])^α, where knots[1] = 0, and the vector is the normalised by dividing by knots[end].
  • lookup_table::Vector{NTuple{2,Float64}}: A lookup table for the Catmull-Rom spline, used for finding the point on the curve closest to a given point. The ith entry of the lookup table corresponds to the t-value i / (length(lookup_table) - 1).
  • alpha::Float64: The alpha parameter of the Catmull-Rom spline. This controls the type of the parametrisation, where alpha = 0 corresponds to uniform parametrisation, alpha = 1/2 corresponds to centripetal parametrisation, and alpha = 1 corresponds to chordal parametrisation. Must be in [0, 1]. For reasons similar to what we describe for tension below, we only support alpha = 1/2 for now. (If you do really want to change it, use the _alpha keyword argument in the constructor.)
  • tension::Float64: The tension parameter of the Catmull-Rom spline. This controls the tightness of the spline, with tension = 0 being the least tight, and tension = 1 leading to straight lines between the control points. Must be in [0, 1]. You can not currently set this to anything except 0.0 due to numerical issues with boundary refinement. (For example, equivariation splits are not possible if tension=1 since the curve is piecewise linear in that case, and for tension very close to 1, the equivariation split is not always between the provided times. If you really want to change it, then you can use the _tension keyword argument in the constructor - but be warned that this may lead to numerical issues and potentially infinite loops.)
  • left::NTuple{2,Float64}: The left extension of the spline. This is used to evaluate the spline on the first segment.
  • right::NTuple{2,Float64}: The right extension of the spline. This is used to evaluate the spline on the last segment.
  • lengths::Vector{Float64}: The lengths of the individual segments of the spline.
  • segments::Vector{CatmullRomSplineSegment}: The individual segments of the spline.
  • orientation_markers::Vector{Float64}: The orientation markers of the curve. These are defined so that the orientation of the curve is monotone between any two consecutive markers. The first and last markers are always 0 and 1, respectively. See orientation_markers.

Constructor

To construct a CatmullRomSpline, use

CatmullRomSpline(control_points::Vector{NTuple{2,Float64}}; lookup_steps=5000, kwargs...)

The keyword argument lookup_steps is used to build the lookup table for the curve, with lookup_steps giving the number of time points in [0, 1] used for the lookup table. The kwargs... are keyword arguments passed to orientation_markers.

DelaunayTriangulation.CatmullRomSplineSegmentType
CatmullRomSplineSegment <: AbstractParametricCurve

A single segment of a Camtull-Rom spline, representing by a cubic polynomial. Note that evaluating this curve will only draw within the two interior control points of the spline.

Based on this article.

Fields

  • a::NTuple{2,Float64}: The coefficient on .
  • b::NTuple{2,Float64}: The coefficient on .
  • c::NTuple{2,Float64}: The coefficient on t.
  • d::NTuple{2,Float64}: The constant in the polynomial.
  • p₁::NTuple{2,Float64}: The second control point of the segment.
  • p₂::NTuple{2,Float64}: The third control point of the segment.

With these fields, the segment is parametrised over 0 ≤ t ≤ 1 by q(t), where

q(t) = at³ + bt² + ct + d,

and q(0) = p₁ and q(1) = p₂, where the segment is defined by four control points p₀, p₁, p₂, and p₃.

This struct is callable, returning the interpolated point (x, y) at t as a NTuple{2,Float64}.

Constructor

To construct this segment, use

catmull_rom_spline_segment(p₀, p₁, p₂, p₃, α, τ)

Here, p₀, p₁, p₂, and p₃ are the four points of the segment (not a, b, c, and d), and α and τ are the parameters of the spline. The parameter α controls the type of the parametrisation, where

  • α = 0: Uniform parametrisation.
  • α = 1/2: Centripetal parametrisation.
  • α = 1: Chordal parametrisation.

The parameter τ is the tension, and controls the tightness of the segment. τ = 0 is the least tight, while τ = 1 leads to straight lines between the control points. Both α and τ must be in [0, 1].

DelaunayTriangulation.CellType
Cell{T}

A cell in a grid. The cell is a square with side length 2half_width. The cell is centered at (x, y). The cell is assumed to live in a polygon.

Fields

  • x::T

The x-coordinate of the center of the cell.

  • y::T

The y-coordinate of the center of the cell.

  • half_width::T

The half-width of the cell.

  • dist::T

The distance from the center of the cell to the polygon.

  • max_dist::T

The maximum distance from the center of the cell to the polygon. This is dist + half_width * sqrt(2).

Constructors

Cell(x::T, y::T, half_width::T, points, boundary_nodes)

Constructs a cell with center (x, y) and half-width half_width. The cell is assumed to live in the polygon defined by points and boundary_nodes.

DelaunayTriangulation.CellQueueType
CellQueue{T}

A struct representing the priority queue of Cells, used for sorting the cells in a grid according to their maximum distance.

Fields

  • queue::MaxPriorityQueue{Cell{T},T}: The priority queue of cells, sorting according to maximum distance.

Constructors

CellQueue{T}()

Constructs a new CellQueue with elements of type Cell{T}.

DelaunayTriangulation.CircularArcType
CircularArc <: AbstractParametricCurve

Curve for representing a circular arc, parametrised over 0 ≤ t ≤ 1. This curve can be evaluated using circular_arc(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

Fields

  • center::NTuple{2,Float64}: The center of the arc.
  • radius::Float64: The radius of the arc.
  • start_angle::Float64: The angle of the initial point of the arc, in radians.
  • sector_angle::Float64: The angle of the sector of the arc, in radians. This is given by end_angle - start_angle, where end_angle is the angle at last, and so might be negative for negatively oriented arcs.
  • first::NTuple{2,Float64}: The first point of the arc.
  • last::NTuple{2,Float64}: The last point of the arc.
  • pqr::NTuple{3, NTuple{2, Float64}}: Three points on the circle through the arc. This is needed for point_position_relative_to_curve.
Orientation

The angles start_angle and end_angle should be setup such that start_angle > end_angle implies a positively oriented arc, and start_angle < end_angle implies a negatively oriented arc. Moreover, they must be in [0°, 2π°).

Constructor

You can construct a CircularArc using

CircularArc(first, last, center; positive=true)

It is up to you to ensure that first and last are equidistant from center - the radius used will be the distance between center and first. The positive keyword argument is used to determine if the arc is positively oriented or negatively oriented.

DelaunayTriangulation.ConvexHullType
ConvexHull{PointsType, IntegerType}

Struct for representing a convex hull. See also convex_hull.

Fields

  • points::PointsType: The underlying point set.
  • vertices::Vector{IntegerType}: The vertices of the convex hull, in counter-clockwise order. Defined so that vertices[begin] == vertices[end].

Constructors

ConvexHull(points, vertices)
convex_hull(points; IntegerType=Int)
DelaunayTriangulation.DiametralBoundingBoxType
DiametralBoundingBox

Type for representing a bounding box generated from an edge's diametral circle.

Fields

  • bounding_box::BoundingBox: The bounding box.
  • edge::NTuple{2,Int}: The generator edge.
DelaunayTriangulation.EachGhostEdgeType
EachGhostEdge{E,T}

An iterator over all ghost edges in a triangulation.

Fields

  • edges::E: The iterator over all edges in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EachGhostTriangleType
EachGhostTriangle{V,T}

An iterator over all ghost triangles in a triangulation.

Fields

  • triangles::V: The iterator over all triangles in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EachGhostVertexType
EachGhostVertex{V,T}

An iterator over all ghost vertices in a triangulation.

Fields

  • vertices::V: The iterator over all vertices in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EachSolidEdgeType
EachSolidEdge{E,T}

An iterator over all solid edges in a triangulation.

Fields

  • edges::E: The iterator over all edges in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EachSolidTriangleType
EachSolidTriangle{V,T}

An iterator over all solid triangles in a triangulation.

Fields

  • triangles::V: The iterator over all triangles in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EachSolidVertexType
EachSolidVertex{V,T}

An iterator over all solid vertices in a triangulation.

Fields

  • vertices::V: The iterator over all vertices in the triangulation.
  • tri::T: The triangulation.
DelaunayTriangulation.EllipticalArcType
EllipticalArc <: AbstractParametricCurve

Curve for representing an elliptical arc, parametrised over 0 ≤ t ≤ 1. This curve can be evaluated using elliptical_arc(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

Fields

  • center::NTuple{2,Float64}: The center of the ellipse.
  • horz_radius::Float64: The horizontal radius of the ellipse.
  • vert_radius::Float64: The vertical radius of the ellipse.
  • rotation_scales::NTuple{2,Float64}: If θ is the angle of rotation of the ellipse, then this is (sin(θ), cos(θ)).
  • start_angle::Float64: The angle of the initial point of the arc measured from center, in radians. This angle is measured from the center prior to rotating the ellipse.
  • sector_angle::Float64: The angle of the sector of the arc, in radians. This is given by end_angle - start_angle, where end_angle is the angle at last, and so might be negative for negatively oriented arcs.
  • first::NTuple{2,Float64}: The first point of the arc.
  • last::NTuple{2,Float64}: The last point of the arc.

Constructor

You can construct an EllipticalArc using

EllipticalArc(first, last, center, major_radius, minor_radius, rotation; positive=true)

where rotation is the angle of rotation of the ellipse, in degrees. The positive keyword argument is used to determine if the arc is positively oriented or negatively oriented.

DelaunayTriangulation.EnlargementValuesType
EnlargementValues

Type for representing the values used in the minimisation of enlargement.

Fields

  • enlargement::Float64: The enlargement of the bounding box of the child being compared with.
  • idx::Int: The index of the child being compared with.
  • area::Float64: The area of the child being compared with.
  • bounding_box::BoundingBox: The bounding box being compared with for enlargement.

Constructor

EnlargementValues(enlargement, idx, area, bounding_box)
EnlargementValues(bounding_box)
DelaunayTriangulation.GraphType
Graph{IntegerType}

Struct for storing neighbourhood relationships between vertices in a triangulation. This is an undirected graph.

Fields

  • vertices::Set{IntegerType}

The set of vertices in the underlying triangulation.

  • edges::Set{NTuple{2, IntegerType}}

The set of edges in the underlying triangulation.

  • neighbours::Dict{IntegerType, Set{IntegerType}}

The map taking vertices u to the set of all v such that (u, v) is an edge in the underlying triangulation.

Constructors

Graph{IntegerType}()
Graph(vertices::Set{IntegerType}, edges::Set{NTuple{2, IntegerType}}, neighbours::Dict{IntegerType, Set{IntegerType}})
DelaunayTriangulation.IndividualTriangleStatisticsType
IndividualTriangleStatistics{T}

Struct storing statistics of a single triangle.

Fields

  • area::T: The area of the triangle.
  • lengths::NTuple{3,T}: The lengths of the edges of the triangle, given in sorted order.
  • circumcenter::NTuple{2,T}: The circumcenter of the triangle.
  • circumradius::T: The circumradius of the triangle.
  • angles::NTuple{3, T}: The angles of the triangle, given in sorted order.
  • radius_edge_ratio::T: The ratio of the circumradius to the shortest edge length.
  • edge_midpoints::NTuple{3,NTuple{2,T}}: The midpoints of the edges of the triangle.
  • aspect_ratio::T: The ratio of the inradius to the circumradius.
  • inradius::T: The inradius of the triangle.
  • perimeter::T: The perimeter of the triangle.
  • centroid::NTuple{2,T}: The centroid of the triangle.
  • offcenter::NTuple{2,T}: The offcenter of the triangle with radius-edge ratio cutoff β=1. See this paper.
  • sink::NTuple{2,T}: The sink of the triangle relative to the parent triangulation. See this paper.

Constructors

The constructor is

IndividualTriangleStatistics(p, q, r, sink = (NaN, NaN))

where p, q, and r are the coordinates of the triangle given in counter-clockwise order. sink is the triangle's sink. This must be provided separately since it is only computed relative to a triangulation, and so requires vertices rather than coordinates; see triangle_sink.

Extended help

The relevant functions used for computing these statistics are

DelaunayTriangulation.InsertionEventHistoryType
InsertionEventHistory{T,E}

A data structure for storing the changes to the triangulation during the insertion of a point.

Fields

  • added_triangles::Set{T}: The triangles that were added.
  • deleted_triangles::Set{T}: The triangles that were deleted.
  • added_segments::Set{E}: The interior segments that were added.
  • deleted_segments::Set{E}: The interior segments that were deleted.
  • added_boundary_segments::Set{E}: The boundary segments that were added.
  • deleted_boundary_segments::Set{E}: The boundary segments that were deleted.

Constructor

The default constructor is available, but we also provide

InsertionEventHistory(tri::Triangulation)

which will initialise this struct with empty, appropriately sizehint!ed, sets.

DelaunayTriangulation.LeafType
mutable struct Leaf <: AbstractNode

Type for representing a leaf node in an R-tree.

Type parametrisation

Technically, this type should be referred to by Leaf{Branch}. Due to a lack of support for mutually recursive types or forward declarations, we have a parametric type in this struct's definition since Branch is not yet defined. In particular, Leaf is not a concrete type, whereas Leaf{Branch} is.

Fields

  • parent::Union{Branch, Nothing}: The parent of the leaf node.
  • bounding_box::BoundingBox: The bounding box of the leaf node.
  • children::Vector{DiametralBoundingBox}: The children of the leaf node.

Constructor

Leaf(parent::Union{Branch,Nothing}=nothing) = Leaf{Branch}(parent, InvalidBoundingBox, DiametralBoundingBox[])
DelaunayTriangulation.LineSegmentType
LineSegment <: AbstractParametricCurve

Curve for representing a line segment, parametrised over 0 ≤ t ≤ 1. This curve can be using line_segment(t) and returns a tuple (x, y) of the coordinates of the point on the curve at t.

Fields

  • first::NTuple{2,Float64}: The first point of the line segment.
  • last::NTuple{2,Float64}: The last point of the line segment.
  • length::Float64: The length of the line segment.

Constructor

You can construct a LineSegment using

LineSegment(first, last)
DelaunayTriangulation.MaxPriorityQueueType
MaxPriorityQueue{K, V}

Struct for a max priority queue.

Fields

  • data::Vector{Pair{K, V}}: The data of the queue, stored in a vector of key-value pairs mapping elements to their priority.
  • map::Dict{K, Int}: A dictionary mapping elements to their index in the data vector.
DelaunayTriangulation.NodeCacheType
NodeCache{Node,Child}

Type for representing a cache of nodes whose children are of type Child. This is used for caching nodes that are detached from the R-tree, e.g. when a node is split.

Fields

  • cache::Vector{Node}: The cache of nodes.
  • size_limit::Int: The maximum number of nodes that can be cached.

Constructor

NodeCache{Node,Child}(size_limit::Int) where {Node,Child} = new{Node,Child}(Node[], size_limit)
DelaunayTriangulation.PiecewiseLinearType
PiecewiseLinear <: AbstractParametricCurve

Struct for representing a piecewise linear curve. This curve should not be interacted with or constructed directly. It only exists so that it can be an AbstractParametricCurve. Instead, triangulations use this curve to know that its boundary_nodes field should be used instead.

Existing methods

This struct does have fields, namely points and boundary_nodes (and boundarynodes should be a contiguous section). These are only used so that we can use this struct in [`anglebetween](@ref) easily. In particular, we need to allow for evaluating this curve att=0and att=1, and similarly for differentiating the curve att=0and att=1. For this, we have defined, lettingLbe aPiecewiseLinearcurve,L(0)to return the first point on the curve, and the last point otherwise (meaningL(h)is constant forh > 0`), and similarly for differentiation. Do NOT rely on the implementation of these methods.

DelaunayTriangulation.PointLocationHistoryType
PointLocationHistory{T,E,I}

History from using jump_and_march.

Fields

  • triangles::Vector{T}: The visited triangles.
  • collinear_segments::Vector{E}: Segments collinear with the original line pq using to jump.
  • collinear_point_indices::Vector{I}: This field contains indices to segments in collinear_segments that refer to points that were on the original segment, but there is no valid segment for them. We use manually fix this after the fact. For example, we could add an edge (1, 14), when really we mean something like (7, 14) which isn't a valid edge.
  • left_vertices::Vector{I}: Vertices from the visited triangles to the left of pq.
  • right_verices::Vector{I}: Vertices from the visited triangles to the right of pq.
DelaunayTriangulation.PolygonType
Polygon{T,V,P} <: AbstractVector{T}

A struct for representing a polygon. The vertices are to be a counter-clockwise list of integers, where the integers themselves refer to points in points.

Fields

  • vertices::V: A list of integers that refer to points in points. The last vertex shokuld not be the same as the first.
  • points::P: A list of points.
Aliasing

In the case where vertices[begin] ≠ vertices[end], the vertices field is exactly the same as the input vertices. Where vertices[begin] = vertices[end], the vertices field is a view of vertices that excludes the last element.

DelaunayTriangulation.PolygonHierarchyType
PolygonHierarchy{I}

Struct used to define a polygon hierarchy. The hierarchy is represented as a forest of PolygonTrees.

Overlapping polygons

The polygons must not intersect any other polygon's boundaries.

Fields

  • polygon_orientations::BitVector: A BitVector of length n where n is the number of polygons in the hierarchy. The ith entry is true if the ith polygon is positively oriented, and false otherwise.
  • bounding_boxes::Vector{BoundingBox}: A Vector of BoundingBoxs of length n where n is the number of polygons in the hierarchy. The ith entry is the BoundingBox of the ith polygon.
  • trees::Dict{I,PolygonTree{I}}: A Dict mapping the index of a polygon to its PolygonTree. The keys of trees are the roots of each individual tree, i.e. the outer-most polygons.
  • reorder_cache::Vector{PolygonTree{I}}: A Vector used for caching trees to be deleted in [reorder_subtree!`](@ref).
One-based indexing

Note that the vector definitions for poylgon_orientations and bounding_boxes are treating the curves with the assumption that they are enumerated in the order 1, 2, 3, ....

Constructor

PolygonHierarchy{I}() where {I}

Constructs a PolygonHierarchy with no polygons.

DelaunayTriangulation.PolygonTreeType
mutable struct PolygonTree{I}

A tree structure used to define a polygon hierarchy.

Fields

  • parent::Union{Nothing,PolygonTree{I}}: The parent of the tree. If nothing, then the tree is the root.
  • children::Set{PolygonTree{I}}: The children of the tree.
  • index::I: The index of the tree. This is the index associated with the polygon.
  • height::Int: The height of the tree. This is the number of polygons in the tree that index is inside of. The root has height 0.

Constructor

PolygonTree{I}(parent::Union{Nothing,PolygonTree{I}}, index, height) where {I}

Constructs a PolygonTree with parent, index, and height, and no children.

DelaunayTriangulation.QueueType
Queue{T}

Struct for a first-in first-out queue.

Performance

Under the hood, Queue simply uses a Vector. This may not be as optimised compared to other implementations, e.g. DataStructure.jl's block-based approach with a Dequeue.

DelaunayTriangulation.RTreeType
mutable struct RTree

Type for representing an R-tree with linear splitting.

Fields

  • root::Union{Branch,Leaf{Branch}}: The root of the R-tree.
  • num_elements::Int: The number of elements in the R-tree.
  • branch_cache::BranchCache: The cache of branch nodes.
  • twig_cache::TwigCache: The cache of twig nodes.
  • leaf_cache::LeafCache: The cache of leaf nodes.
  • fill_factor::Float64: The fill factor of the R-tree, i.e. the percentage of a node's capacity that should be filled after splitting.
  • free_cache::BitVector: A bit vector for keeping track of which indices in detached_cache are free.
  • detached_cache::Vector{Union{Branch,Leaf{Branch}}}: A cache of detached nodes, i.e. nodes that have been split from the R-tree. This is used for deleting nodes.
  • intersection_cache::NTuple{2,IntersectionCache}: Cache used for identifying intersections. Each element of the Tuple is its own cache, allowing for up to two intersection queries to be performed simultaneously. Note that this makes the R-tree non-thread-safe, and even non-safe when considering three or more intersection queries simultaneously.

Constructor

    RTree(; size_limit=100, fill_factor=0.7)

The size_limit is the node capacity. All node types have the same capacity.

DelaunayTriangulation.RTreeIntersectionCacheType
RTreeIntersectionCache

Type for representing a cache used for identifying intersections in an R-tree.

Fields

  • node_indices::Vector{Int}: A cache of indices used for identifying intersections.
  • need_tests::BitVector: A BitVector cache for keeping track of which indices in node_indices need to be tested for intersections.
DelaunayTriangulation.RTreeIntersectionIteratorType
RTreeIntersectionIterator

Type for representing an iterator over the elements in an R-tree that intersect with a bounding box.

Fields

  • tree::RTree: The R-tree.
  • bounding_box::BoundingBox: The bounding box to test for intersections with.
  • cache::RTreeIntersectionCache: The cache used for identifying intersections.
DelaunayTriangulation.RefinementArgumentsType
RefinementArguments{Q,C,H,I,E,T,R}

A struct for storing arguments for mesh refinement.

Fields

  • queue::Q: The RefinementQueue.
  • constraints::C: The RefinementConstraints.
  • events::H: The InsertionEventHistory.
  • min_steiner_vertex::I: The minimum vertex of a Steiner point. All vertices greater than or equal to this can be considered as Steiner vertices.
  • segment_list::Set{E}: The set of segments in the triangulation before refinement.
  • segment_vertices::Set{I}: Set of vertices that are vertices of segments in segment_list.
  • midpoint_split_list::Set{I}: Set of vertices that are centre-splits of encroached edges.
  • offcenter_split_list::Set{I}: Set of vertices that are off-centre splits of encroached edges.
  • use_circumcenter::Bool: Whether to use circumcenters for Steiner points, or the more general approach of Erten and Üngör (2009).
  • use_lens::Bool: Whether to use diametral lens (true) or diametral circles (false) for the defining encroachment.
  • steiner_scale::T: The factor by which to scale the Steiner points closer to the triangle's shortest edge.
  • locked_convex_hull::Bool: Whether the convex hull of the triangulation had to be locked for refinement.
  • had_ghosts::Bool: Whether the triangulation initially had ghost triangles or not.
  • rng::R: The random number generator.
  • concavity_protection::Bool: Whether to use concavity protection or not for jump_and_march. Most likely not needed, but may help in pathological cases.

Constructors

In addition to the default constructor, we provide

RefinementArguments(tri::Triangulation; kwargs...)

for constructing this struct. This constructor will lock the convex hull and add ghost triangles to tri if needed (refine! will undo these changes once the refinement is finished))

DelaunayTriangulation.RefinementArgumentsMethod
RefinementArguments(tri::Triangulation; kwargs...) -> RefinementArguments

Initialises the RefinementArguments for the given Triangulation, tri. The kwargs... match those from refine!.

Mutation

If tri has no ghost triangles, it will be mutated so that it has them. Similarly, if the triangulation has no constrained boundary, then the convex hull will be locked so that it is treated as a constrained boundary. These changes will be undone in refine! once the refinement is finished.

DelaunayTriangulation.RefinementConstraintsType
RefinementConstraints{F}

A struct for storing constraints for mesh refinement.

Fields

  • min_angle=0.0: The minimum angle of a triangle.
  • max_angle=180.0: The maximum angle of a triangle.
  • min_area=0.0: The minimum area of a triangle.
  • max_area=Inf: The maximum area of a triangle.
  • max_radius_edge_ratio=csd(min_angle) / 2: The maximum radius-edge ratio of a triangle. This is computed from min_angle - you cannot provide a value for it yourself.
  • max_points=typemax(Int): The maximum number of vertices allowed in the triangulation. Note that this refers to num_solid_vertices, not the amount returned by num_points.
  • seiditous_angle=20.0: The inter-segment angle used to define seditious edges in degrees. Should not be substantially smaller than 20.0° or any greater than 60.0°.
  • custom_constraint::F=(tri, triangle) -> false: A custom constraint function. This should take a Triangulation and a triangle as arguments, and return true if the triangle violates the constraints and false otherwise.
DelaunayTriangulation.RefinementQueueType
RefinementQueue{T,E,F}

Struct defining a pair of priority queues for encroached segments and poor-quality triangles.

Fields

  • segments::MaxPriorityQueue{E,F}: A priority queue of encroached segments, where the priorities are the squared edge lengths.
  • triangles::MaxPriorityQueue{T,F}: A priority queue of poor-quality triangles, where the priorities are the radius-edge ratios.

Constructor

The default constructor is available, but we also provide

RefinementQueue(tri::Triangulation)

which will initialise this struct with empty queues with the appropriate types.

DelaunayTriangulation.RepresentativeCoordinatesType
RepresentativeCoordinates{IntegerType, NumberType}

A mutable struct for representing the coordinates of a representative point of polygon or a set of points.

Fields

  • x::NumberType: The x-coordinate of the representative point.
  • y::NumberType: The y-coordinate of the representative point.
  • n::IntegerType: The number of points represented by the representative point.
DelaunayTriangulation.ShuffledPolygonLinkedListType
ShuffledPolygonLinkedList{I,T}

Data structure for representing a polygon as a doubly-linked list. In the descriptions below, π is used to denote the shuffled_indices vector.

Fields

  • next::Vector{I}: The next vertices, so that next[π[i]] is the vertex after S[π[i]].
  • prev::Vector{I}: The prev vertices, so that prev[π[i]] is the vertex before S[π[i]].
  • shuffled_indices::Vector{I}: The shuffled indices of the vertices, so that S[π[i]] is the ith vertex.
  • k::I: The number of vertices in the polygon.
  • S::T: The vertices of the polygon. This should not be a circular vector, i.e. S[begin] ≠ S[end], and must use one-based indexing. Additionally, the vertices must be provided in counter-clockwise order - this is NOT checked.

Constructor

To construct this, use

ShuffledPolygonLinkedList(S::Vector; rng::AbstractRNG=Random.default_rng())

The argument rng is used for shuffling the shuffled_indices vector.

DelaunayTriangulation.SmallAngleComplexType
SmallAngleComplex{I}

Struct for representing a small-angle complex.

Fields

  • apex::I: The apex vertex of the complex.
  • members::Vector{SmallAngleComplexMember{I}}: The members of the complex.

Extended help

A small-angle complex is a set of curves that form a contiguous set of small angles, i.e. the angle between each consecutive pair of curves is less than 60°. The apex of the complex is the vertex that is shared by all of the curves.

DelaunayTriangulation.SmallAngleComplexMemberType
SmallAngleComplexMember{I}

Struct for representing a member of a small-angle complex.

Fields

  • parent_curve::I: The index of the parent curve in the boundary curves assoicated with the member. If this is 0, then this is instead a member of a complex around an interior segment.
  • next_edge::I: The next vertex after the apex in the boundary nodes associated with the member.
DelaunayTriangulation.TriangulationType
Triangulation{P,T,BN,W,I,E,Es,BC,BCT,BEM,GVM,GVR,BPL,C,BE}

Struct representing a triangulation, as constructed by triangulate.

Fields

  • points::P

The point set of the triangulation. Please note that this may not necessarily correspond to each point in the triangulation, e.g. some points may have been deleted - see each_solid_vertex for an iterator over each vertex in the triangulation.

  • triangles::T

The triangles in the triangulation. Each triangle is oriented counter-clockwise. If your triangulation has ghost triangles, some of these triangles will contain ghost vertices (i.e., vertices negative indices). Solid triangles can be iterated over using each_solid_triangle.

  • boundary_nodes::BN

The boundary nodes of the triangulation, if the triangulation is constrained; the assumed form of these boundary nodes is outlined in the docs. If your triangulation is unconstrained, then boundary_nodes will be empty and the boundary should instead be inspected using the convex hull field, or alternatively you can see lock_convex_hull!.

  • interior_segments::Es

Constrained segments appearing in the triangulation. These will only be those segments appearing off of the boundary. If your triangulation is unconstrained, then segments will be empty.

  • all_segments::Es

This is similar to segments, except this includes both the interior segments and the boundary segments. If your triangulation is unconstrained, then all_segments will be empty.

  • weights::W

The weights of the triangulation. If you are not using a weighted triangulation, this will be given by ZeroWeight(). Otherwise, the weights must be such that get_weight(weights, i) is the weight for the ith vertex. The weights should be Float64.

  • adjacent::Adjacent{I,E}

The Adjacent map of the triangulation. This maps edges (u, v) to vertices w such that (u, v, w) is a positively oriented triangle in triangles (up to rotation).

  • adjacent2vertex::Adjacent2Vertex{I,Es}

The Adjacent2Vertex map of the triangulation. This maps vertices w to sets S such that (u, v, w) is a positively oriented triangle in triangles (up to rotation) for all (u, v) ∈ S.

  • graph::Graph{I}

The Graph of the triangulation, represented as an undirected graph that defines all the neighbourhood information for the triangulation.

  • boundary_curves::BC

Functions defining the boundary curves of the triangulation, incase you are triangulating a curve-bounded domain. By default, this will be an empty Tuple, indicating that the boundary is as specified in boundary_nodes - a piecewise linear curve. If you are triangulating a curve-bounded domain, then these will be the parametric curves (see AbstractParametricCurve) you provided as a Tuple, where the ith element of the Tuple is associated with the ghost vertex -i, i.e. the ith section as indicated by ghost_vertex_map. If the ith boundary was left was a sequence of edges, then the function will be a PiecewiseLinear().

  • boundary_edge_map::BEM

This is a Dict from construct_boundary_edge_map that maps boundary edges (u, v) to their corresponding position in boundary_nodes.

  • ghost_vertex_map::GVM

This is a Dict that maps ghost vertices to their corresponding section in boundary_nodes, constructed by construct_ghost_vertex_map.

  • ghost_vertex_ranges::GVR

This is a Dict that maps ghost vertices to a range of all other ghost vertices that appear on the curve corresponding to the given ghost vertex, constructed by construct_ghost_vertex_ranges.

  • convex_hull::ConvexHull{P,I}

The ConvexHull of the triangulation, which is the convex hull of the point set points.

  • representative_point_list::BPL

The Dict of points giving RepresentativeCoordinates for each boundary curve, or for the convex hull if boundary_nodes is empty. These representative points are used for interpreting ghost vertices.

  • polygon_hierarchy::PolygonHierarchy{I}

The PolygonHierarchy of the boundary, defining the hierarchy of the boundary curves, giving information about which curves are contained in which other curves.

  • boundary_enricher::BE

The BoundaryEnricher used for triangulating a curve-bounded domain. If the domain is not curve-bounded, this is nothing.

  • cache::C

A TriangulationCache used as a cache for add_segment! which requires a separate Triangulation structure for use. This will not contain any segments or boundary nodes. Also stores segments useful for lock_convex_hull! and unlock_convex_hull!.

DelaunayTriangulation.TriangulationMethod
Triangulation(points, triangles, boundary_nodes; kwargs...) -> Triangulation

Returns the Triangulation corresponding to the triangulation of points with triangles and boundary_nodes.

Arguments

  • points: The points that the triangulation is of.
  • triangles: The triangles of the triangulation. These should be given in counter-clockwise order, with vertices corresponding to points. These should not include any ghost triangles.
  • boundary_nodes: The boundary nodes of the triangulation. These should match the specification given in the documentation or in check_args.

Keyword Arguments

  • IntegerType=Int: The integer type to use for the triangulation. This is used for representing vertices.
  • EdgeType=isnothing(segments) ? NTuple{2,IntegerType} : (edge_type ∘ typeof)(segments): The edge type to use for the triangulation.
  • TriangleType=NTuple{3,IntegerType}: The triangle type to use for the triangulation.
  • EdgesType=isnothing(segments) ? Set{EdgeType} : typeof(segments): The type to use for storing the edges of the triangulation.
  • TrianglesType=Set{TriangleType}: The type to use for storing the triangles of the triangulation.
  • weights=ZeroWeight(): The weights associated with the triangulation.
  • delete_ghosts=false: Whether to delete the ghost triangles after the triangulation is computed. This is done using delete_ghost_triangles!.

Output

DelaunayTriangulation.TriangulationCacheType
TriangulationCache{T,M,I,S}

A cache to be used as a field in Triangulation.

Fields

  • triangulation::T: The cached triangulation. This will only refer to an unconstrained triangulation, meaning it cannot have any segments or boundary nodes. It will contain the weights. This is used for constrained triangulations.
  • triangulation_2::T: An extra cached triangulation. This is needed for retriangulating fans for constrained triangulations.
  • marked_vertices::M: Marked vertices cache for use in constrained triangulations.
  • interior_segments_on_hull::I: Interior segments in the triangulation that also appear on the convex hull of tri. This is needed for lock_convex_hull! in case the convex hull also contains interior segments.
  • surrounding_polygon::S: The polygon surrounding the triangulation. This is needed for delete_point!.
  • fan_triangles::F: Triangles in a fan. This is needed for sorting fans for constrained triangulations.
Caches of caches

The triangulation cache itself does not have a cache. Instead, it stores a TriangulationCache(nothing).

Aliasing

The points of the cache's triangulation will be aliased to the points of the parent triangulation.

DelaunayTriangulation.TriangulationStatisticsType
TriangulationStatistics{T,V,I}

A struct containing statistics about a triangulation.

Fields

  • num_vertices::I: The number of vertices in the triangulation.
  • num_solid_vertices::I: The number of solid vertices in the triangulation.
  • num_ghost_vertices::I: The number of ghost vertices in the triangulation.
  • num_edges::I: The number of edges in the triangulation.
  • num_solid_edges::I: The number of solid edges in the triangulation.
  • num_ghost_edges::I: The number of ghost edges in the triangulation.
  • num_triangles::I: The number of triangles in the triangulation.
  • num_solid_triangles::I: The number of solid triangles in the triangulation.
  • num_ghost_triangles::I: The number of ghost triangles in the triangulation.
  • num_boundary_segments::I: The number of boundary segments in the triangulation.
  • num_interior_segments::I: The number of interior segments in the triangulation.
  • num_segments::I: The number of segments in the triangulation.
  • num_convex_hull_vertices::I: The number of vertices on the convex hull of the triangulation.
  • smallest_angle::V: The smallest angle in the triangulation.
  • largest_angle::V: The largest angle in the triangulation.
  • smallest_area::V: The smallest area of a triangle in the triangulation.
  • largest_area::V: The largest area of a triangle in the triangulation.
  • smallest_radius_edge_ratio::V: The smallest radius-edge ratio of a triangle in the triangulation.
  • largest_radius_edge_ratio::V: The largest radius-edge ratio of a triangle in the triangulation.
  • area::V: The total area of the triangulation.
  • individual_statistics::Dict{T,IndividualTriangleStatistics{V}}: A map from triangles in the triangulation to their individual statistics. See IndividualTriangleStatistics.

Constructors

To construct these statistics, use statistics, which you call as statistics(tri::Triangulation).

DelaunayTriangulation.VoronoiTessellationType
VoronoiTessellation{Tr<:Triangulation,P,I,T,S,E}

Struct for representing a Voronoi tessellation.

See also voronoi.

Fields

  • triangulation::Tr: The underlying triangulation. The tessellation is dual to this triangulation, although if the underlying triangulation is constrained then this is no longer the case (but it is still used).
  • generators::Dict{I,P}: A Dict that maps vertices of generators to coordinates. These are simply the points present in the triangulation. A Dict is needed in case the triangulation is missing some points.
  • polygon_points::Vector{P}: The points defining the coordinates of the polygons. The points are not guaranteed to be unique if a circumcenter appears on the boundary or you are considering a clipped tessellation. (See also get_polygon_coordinates.)
  • polygons::Dict{I,Vector{I}}: A Dict mapping polygon indices (which is the same as a generator vertex) to the vertices of a polygon. The polygons are given in counter-clockwise order and the first and last vertices are equal.
  • circumcenter_to_triangle::Dict{I,T}: A Dict mapping a circumcenter index to the triangle that contains it. The triangles are sorted such that the minimum vertex is last.
  • triangle_to_circumcenter::Dict{T,I}: A Dict mapping a triangle to its circumcenter index. The triangles are sorted such that the minimum vertex is last.
  • unbounded_polygons::Set{I}: A Set of indices of the unbounded polygons.
  • cocircular_circumcenters::S: A Set of indices of circumcenters that come from triangles that are cocircular with another triangle's vertices, and adjoin said triangles.
  • adjacent::Adjacent{I,E}: The adjacent map. This maps an oriented edge to the polygon that it belongs to.
  • boundary_polygons::Set{I}: A Set of indices of the polygons that are on the boundary of the tessellation. Only relevant for clipped tessellations, otherwise see unbounded_polygons.
Base.:∩Method
intersect(r1::BoundingBox, r2::BoundingBox) -> BoundingBox
r1::BoundingBox ∩ r2::BoundingBox -> BoundingBox

Returns the intersection of r1 and r2. If the intersection is empty, returns InvalidBoundingBox.

Base.:∩Method
intersect(I::BoundingInterval, J::BoundingInterval) -> BoundingInterval
I::BoundingInterval ∩ J::BoundingInterval -> BoundingInterval

Returns the intersection of I and J. If the intersection is empty, returns InvalidBoundingInterval.

Base.:∪Method
union(r1::BoundingBox, r2::BoundingBox) -> BoundingBox
r1::BoundingBox ∪ r2::BoundingBox -> BoundingBox

Returns the union of r1 and r2, i.e. the smallest bounding box that contains both r1 and r2.

Base.:∪Method
union(I::BoundingInterval, J::BoundingInterval) -> BoundingInterval
I::BoundingInterval ∪ J::BoundingInterval -> BoundingInterval

Returns the union of I and J, combining their bounds; i.e. the smallest interval that contains both I and J.

Base.append!Method
append!(complex::SmallAngleComplex, new_complex::SmallAngleComplex)

Appends the members of new_complex onto the members of complex.

Base.append!Method
append!(node::AbstractNode, child)

Appends child to node's children. Also updates node's bounding box.

Base.delete!Method
delete!(tree::BalancedBST{K}, key::K) -> BalancedBST{K}

Deletes the node in tree with key key if it exists. Returns tree.

Base.delete!Method
delete!(tree::BoundaryRTree, i, j)

Deletes the bounding box of the diametral circle of the edge between i and j in tree.

Base.delete!Method
delete!(tree::RTree, id_bounding_box::DiametralBoundingBox)

Deletes id_bounding_box from tree.

Base.eltypeMethod
eltype(queue::Queue{T}) -> Type{T}

Returns the type of elements stored in q.

Base.empty!Method
empty!(events::InsertionEventHistory)

Empties events by emptying all of its fields.

Base.empty!Method
empty!(cache::TriangulationCache)

Empties the cache by emptying the triangulation stored in it.

Base.findfirstMethod
findfirst(tree::BalancedBST{K}, key::K) -> Union{Nothing,BalancedBSTNode{K}}

Returns the node in tree with key key. If no such node exists, returns nothing.

Base.firstMethod
first(queue::MaxPriorityQueue) -> Pair{K, V}

Returns the element with the highest priority in a queue, without removing it from queue.

Base.getindexMethod
getindex(queue::MaxPriorityQueue, key) 
queue[key]

Returns the priority of the element with key key in a queue.

Base.getindexMethod
getindex(queue::RefinementQueue{T,E,F}, triangle::T) -> F
queue[triangle] -> F

Return the radius-edge ratio of triangle in queue.

Base.haskeyMethod
haskey(tree::BalancedBST{K}, key::K) -> Bool

Returns true if tree has a node with key key, false otherwise.

Base.haskeyMethod
haskey(queue::MaxPriorityQueue, key) -> Bool

Returns true if the queue has an element with key key.

Base.haskeyMethod
haskey(queue::RefinementQueue{T,E,F}, segment::E) -> Bool

Return true if queue has segment or its reverse, and false otherwise.

Base.haskeyMethod
haskey(queue::RefinementQueue{T,E,F}, triangle::T) -> Bool

Return true if queue has triangle or any of its counter-clockwise rotations, and false otherwise.

Base.inMethod
in(r1::BoundingBox, r2::BoundingBox) -> Bool
r1::BoundingBox ∈ r2::BoundingBox -> Bool

Tests whether r1 is in r2.

Base.inMethod
in(I::BoundingInterval, J::BoundingInterval) -> Bool
I::BoundingInterval ∈ J::BoundingInterval -> Bool

Tests whether the interval I is in the interval J.

Base.inMethod
in(a::Float64, I::BoundingInterval) -> Bool
a::Float64 ∈ I::BoundingInterval -> Bool

Tests whether a is in I.

Base.inMethod
in(p::NTuple{2,<:Number}, r::BoundingBox) -> Bool
p::NTuple{2,<:Number} ∈ r::BoundingBox -> Bool

Tests whether p is in r.

Base.insert!Method
insert!(node::AbstractNode, child, tree::RTree) -> Bool

Inserts child into node in tree. Returns true if the tree's bounding boxes had to be adjusted and false otherwise.

Base.insert!Method
insert!(tree::BoundaryRTree, i, j) -> Bool

Inserts the diametral circle of the edge between i and j into tree. Returns true if the tree's bounding boxes had to be adjusted and false otherwise.

Base.insert!Method
insert!(tree::RTree, bounding_box[, level = 1]) -> Bool

Inserts bounding_box into tree. Returns true if the tree's bounding boxes had to be adjusted and false otherwise.

Base.isemptyMethod
isempty(r::BoundingBox) -> Bool

Returns true if r is empty, i.e. if r.x or r.y is empty.

Base.isemptyMethod
isempty(I::BoundingInterval) -> Bool

Returns true if I is empty, i.e. if I.a or I.b is NaN or if length(I) < 0.

Base.isemptyMethod
isempty(queue::CellQueue) -> Bool

Returns true if the queue is empty, and false otherwise.

Base.isemptyMethod
isempty(queue::MaxPriorityQueue) -> Bool

Returns true if the queue is empty.

Base.isemptyMethod
isempty(cache::NodeCache) -> Bool

Returns true if cache is empty.

Base.isemptyMethod
isempty(queue::Queue) -> Bool

Returns true if the queue is empty, false otherwise.

Base.isemptyMethod
isempty(queue::RefinementQueue) -> Bool

Return true if queue has no segments or triangles, false otherwise.

Base.iterateMethod
iterate(itr::RTreeIntersectionIterator, state...)

Iterate over the next state of itr to find more intersections with the bounding box in RTreeIntersectionIterator.

Base.lengthMethod
length(I::BoundingInterval) -> Float64

Returns the length of the interval I.

Base.lengthMethod
Base.length(queue::MaxPriorityQueue) -> Int

Returns the number of elements in queue.

Base.lengthMethod
length(cache::NodeCache) -> Int

Returns the number of nodes in cache.

Base.lengthMethod
length(queue::Queue) -> Int

Returns the number of elements in the queue.

Base.minimumMethod
minimum(node::Union{BalancedBSTNode,Nothing}) -> Union{BalancedBSTNode,Nothing}

Returns the node with the minimum key in the subtree rooted at node. If node is nothing, returns nothing.

Base.pop!Method
pop!(cache::NodeCache) -> Node

Removes and returns the last node in cache.

Base.popfirst!Method
popfirst!(queue::MaxPriorityQueue{K, V}) where {K, V} -> Pair{K, V}

Removes and returns the element with the highest priority from the queue.

Base.popfirst!Method
popfirst!(queue::Queue)

Removes the element from the front of the queue and returns it.

Base.push!Method
push!(tree::BalancedBST{K}, key::K)

Inserts key into tree if it is not already present.

Base.push!Method
push!(queue::MaxPriorityQueue, pair)

Adds the key-value pair pair to the queue.

Base.push!Method
push!(cache::NodeCache, node)
Base.push!Method
push!(queue::Queue, item)

Adds item to the end of the queue.

Base.push!Method
push!(complex::SmallAngleComplex, member::SmallAngleComplexMember)

Pushes member onto the members of complex.

Base.setindex!Method
setindex!(branch::Branch, child, i::Integer)
branch[i] = child

Sets the ith child of branch to be child, also updating the parent of child to be branch.

Base.setindex!Method
Bassetindex!(queue::RefinementQueue{T,E,F}, ρ::F, triangle::T) where {T,E,F}
queue[triangle] = ρ

Add a triangle to queue whose radius-edge ratio is ρ. If the triangle is already in the queue, its priority is updated to ρ.

Base.setindex!Method
setindex!(queue::RefinementQueue{T,E,F}, ℓ²::F, segment::E) where {T,E,F}
queue[segment] = ℓ²

Add a segment to queue whose squared length is ℓ². If the segment is already in the queue, its priority is updated to .

Base.setindex!Method
setindex!(queue::MaxPriorityQueue, priority, key)
queue[key] = priority

Sets the priority of the element with key key in a queue to priority, or adds the element to the queue if it is not already present.

DelaunayTriangulation._centroidal_smooth_itrMethod
_centroidal_smooth_itr(vorn::VoronoiTessellation, set_of_boundary_nodes, points, rng; kwargs...) -> (VoronoiTessellation, Number)

Performs a single iteration of the centroidal smoothing algorithm.

Arguments

  • vorn: The VoronoiTessellation.
  • set_of_boundary_nodes: The set of boundary nodes in the underlying triangulation.
  • points: The underlying point set. This is a deepcopy of the points of the underlying triangulation.
  • rng: The random number generator.

Keyword Arguments

Outputs

DelaunayTriangulation._get_interval_for_get_circle_intersectionMethod
_get_interval_for_get_circle_intersection(c::AbstractParametricCurve, t₁, t₂, r) -> (Float64, Float64, NTuple{2, Float64})

Given a circle centered at c(t₁) with radius r, finds an initial interval for get_circle_intersection to perform bisection on to find a point of intersection. The returned interval is (tᵢ, tⱼ), where tᵢ is the parameter value of the first point in the interval and tⱼ is the parameter value of the last point in the interval. (The interval does not have to be sorted.) The third returned value is p = c(t₁).

DelaunayTriangulation._get_rayMethod
_get_ray(vorn, i, ghost_vertex) -> (Point, Point)

Extracts the ray from the ith polygon of vorn corresponding to the ghost_vertex, where ghost_vertex here means that get_polygon(vorn, i)[ghost_vertex] is a ghost vertex.

Arguments

  • vorn: The VoronoiTessellation.
  • i: The index of the polygon.
  • ghost_vertex: The index of the ghost vertex in the polygon.

Outputs

  • p: The first point of the ray.
  • q: A second point of the ray, so that pq gives the direction of the ray (which extends to infinity).
DelaunayTriangulation._getxMethod
_getx(p) -> Float64

Get the x-coordinate of p as a Float64.

Examples

julia> using DelaunayTriangulation

julia> p = (0.37, 0.7);

julia> DelaunayTriangulation._getx(p)
0.37

julia> p = (0.37f0, 0.7f0);

julia> DelaunayTriangulation._getx(p)
0.3700000047683716
DelaunayTriangulation._getxyMethod
_getxy(p) -> NTuple{2, Float64}

Get the coordinates of p as a Tuple.

Examples

julia> using DelaunayTriangulation

julia> p = [0.3, 0.5];

julia> DelaunayTriangulation._getxy(p)
(0.3, 0.5)

julia> p = [0.3f0, 0.5f0];

julia> DelaunayTriangulation._getxy(p)
(0.30000001192092896, 0.5)
DelaunayTriangulation._getyMethod
_gety(p) -> Float64

Get the y-coordinate of p as a Float64.

Examples

julia> using DelaunayTriangulation

julia> p = (0.5, 0.5);

julia> DelaunayTriangulation._gety(p)
0.5

julia> p = (0.5f0, 0.5f0);

julia> DelaunayTriangulation._gety(p)
0.5
DelaunayTriangulation._safe_get_adjacentMethod
_safe_get_adjacent(tri::Triangulation, uv) -> Vertex

This is the safe version of get_adjacent, which is used when the triangulation has multiple sections, ensuring that the correct ghost vertex is returned in case uv is a ghost edge.

DelaunayTriangulation._split_subsegment_curve_bounded!Method
_split_subsegment_curve_bounded!(tri::Triangulation, args::RefinementArguments, e)

Splits a subsegment e of tri at a position determined by split_subcurve! for curve-bounded domains. See split_subsegment!. See also _split_subsegment_curve_bounded_standard! and _split_subsegment_curve_bounded_small_angle!, as well as the original functions _split_subsegment_curve_standard! and _split_subcurve_complex!, respectively, used during boundary enrichment.

DelaunayTriangulation.add_adjacent!Method
add_adjacent!(adj::Adjacent, uv, w)
add_adjacent!(adj::Adjacent, u, v, w)

Adds the adjacency relationship (u, v, w) to adj.

Examples

julia> using DelaunayTriangulation

julia> adj = DelaunayTriangulation.Adjacent{Int64, NTuple{2, Int64}}();

julia> DelaunayTriangulation.add_adjacent!(adj, 1, 2, 3)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 1 entry:
  (1, 2) => 3

julia> DelaunayTriangulation.add_adjacent!(adj, (2, 3), 1)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 2 entries:
  (1, 2) => 3
  (2, 3) => 1

julia> DelaunayTriangulation.add_adjacent!(adj, 3, 1, 2)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 3 entries:
  (1, 2) => 3
  (3, 1) => 2
  (2, 3) => 1
DelaunayTriangulation.add_adjacent!Method
add_adjacent!(tri::Triangulation, uv, w)
add_adjacent!(tri::Triangulation, u, v, w)

Adds the key-value pair (u, v) ⟹ w to the adjacency map of tri.

DelaunayTriangulation.add_adjacent!Method
add_adjacent!(vor::VoronoiTessellation, ij, k)
add_adjacent!(vor::VoronoiTessellation, i, j, k)

Adds the adjacency relationship (i, j) ⟹ k between the oriented edge (i, j) and polygon index k to the Voronoi tessellation vor.

DelaunayTriangulation.add_adjacent2vertex!Method
add_adjacent2vertex!(tri::Triangulation, w, uv)
add_adjacent2vertex!(tri::Triangulation, w, u, v)

Adds the edge (u, v) into the set of edges returned by get_adjacent2vertex(tri, w).

DelaunayTriangulation.add_adjacent2vertex!Method
add_adjacent2vertex!(adj2v::Adjacent2Vertex, w, uv)
add_adjacent2vertex!(adj2v::Adjacent2Vertex, w, u, v)

Adds the edge uv to the set of edges E such that (u, v, w) is a positively oriented triangle in the underlying triangulation for each (u, v) ∈ E.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex{Int64, Set{NTuple{2, Int64}}}()
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}}()

julia> DelaunayTriangulation.add_adjacent2vertex!(adj2v, 1, (2, 3))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 1 entry:
  1 => Set([(2, 3)])

julia> DelaunayTriangulation.add_adjacent2vertex!(adj2v, 1, 5, 7)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 1 entry:
  1 => Set([(5, 7), (2, 3)])

julia> DelaunayTriangulation.add_adjacent2vertex!(adj2v, 17, (5, -1))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  17 => Set([(5, -1)])
  1  => Set([(5, 7), (2, 3)])
DelaunayTriangulation.add_all_boundary_polygons!Method
add_all_boundary_polygons!(vorn::VoronoiTessellation, boundary_sites)

Add all of the boundary polygons to the Voronoi tessellation.

Arguments

Outputs

There are no outputs, but the boundary polygons are added in-place.

DelaunayTriangulation.add_edge!Method
add_edge!(E, e...)

Add the edges e... to E.

Examples

julia> using DelaunayTriangulation

julia> E = Set(((1,5),(17,10),(5,3)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (5, 3)
  (17, 10)
  (1, 5)

julia> DelaunayTriangulation.add_edge!(E, (3, 2))

julia> E
Set{Tuple{Int64, Int64}} with 4 elements:
  (3, 2)
  (5, 3)
  (17, 10)
  (1, 5)

julia> DelaunayTriangulation.add_edge!(E, (1, -3), (5, 10), (1, -1))

julia> E
Set{Tuple{Int64, Int64}} with 7 elements:
  (3, 2)
  (5, 10)
  (1, -3)
  (1, -1)
  (5, 3)
  (17, 10)
  (1, 5)
DelaunayTriangulation.add_edge!Method
add_edge!(history::PointLocationHistory{T,E}, i, j)

Adds the edge (i, j) to the collinear_segments field of history.

DelaunayTriangulation.add_edge_to_voronoi_polygon!Method
add_edge_to_voronoi_polygon!(B, vorn::VoronoiTessellation, i, k, S, m, encountered_duplicate_circumcenter) -> (Vertex, Bool, Vertex)

Add the next edge to the Voronoi polygon for the point i in the VoronoiTessellation vorn.

Arguments

  • B: The vector of circumcenters defining the polygon.
  • vorn: The VoronoiTessellation.
  • i: The polygon index.
  • k: The vertex to add.
  • S: The surrounding polygon of i. See get_surrounding_polygon.
  • m: The index of the next vertex in S.
  • encountered_duplicate_circumcenter: Whether or not a duplicate circumcenter has been encountered.

Outputs

  • ci: The index for the circumcenter of the triangle considered.
  • encountered_duplicate_circumcenter: Whether or not a duplicate circumcenter has been encountered.
  • k: The next vertex in S after the input k.
DelaunayTriangulation.add_point!Method
add_point!(c::RepresentativeCoordinates, p)

Treating c as an arithmetic average, updates the coordinates of c to include p.

DelaunayTriangulation.add_point!Method
add_point!(tri::Triangulation, new_point; kwargs...) -> Triangle
add_point!(tri::Triangulation, x, y; kwargs...) -> Triangle

Arguments

  • tri::Triangulation: The Triangulation.
  • new_point: The point to be added to the triangulation. The second method uses (x, y) to represent the new point instead. If new_point is an integer, then the point added is get_point(tri, new_point).

Keyword Arguments

  • point_indices=each_solid_vertex(tri): The indices of the points to be used in the jump_and_march algorithm for selecting the initial point.
  • m=default_num_samples(length(point_indices)): The number of samples (without replacement) to be used in the jump_and_march algorithm for selecting the initial point.
  • try_points=(): Additional points to try for selecting the initial point, in addition to the m sampled.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to be used in jump_and_march.
  • initial_search_point=integer_type(tri)(select_initial_point(tri, new_point; point_indices, m, try_points, rng)): The initial point to be used in jump_and_march.
  • update_representative_point=false: Whether to update the representative point of the triangulation after adding the new point.
  • store_event_history=Val(false): Whether to store the event history of the triangulation from adding the new point.
  • event_history=nothing: The event history of the triangulation from adding the new point. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.
  • concavity_protection=false: Whether to use concavity protection for finding V below. See concavity_protection_check. This is only needed if your triangulation is not convex.
  • V=jump_and_march(tri, get_point(tri, new_point); m=nothing, point_indices=nothing, try_points=nothing, k=initial_search_point, concavity_protection, rng): The positively oriented triangle containing the point being added.
Non-convex domains

In cases where your triangulation is not convex and !concavity_protection, this V may not be correct, and you may encounter errors - errors either during add_point! or separately when you try to use the triangulation. In such cases, you should set concavity_protection=true to ensure that V is correct.

  • peek=Val(false): Whether the point should actually be added into the triangulation, or just 'peeked' at so that the events that would occur from its addition can be added into event_history.

Outputs

The triangulation is updated in-place, but we do return

  • V: The triangle containing the point being added.
Convex hull

In cases where (x, y) is outside of the triangulation, it will be added successfully but note that the convex_hull field of tri will no longer be accurate. You can use convex_hull! to fix it.

DelaunayTriangulation.add_point_bowyer_watson!Method
add_point_bowyer_watson!(tri::Triangulation, new_point, initial_search_point::I, rng::AbstractRNG=Random.default_rng(), update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::P=Val(false)) -> Triangle

Adds new_point into tri.

Arguments

  • tri: The triangulation.
  • new_point: The point to insert.
  • initial_search_point::I: The vertex to start the point location with jump_and_march at. See get_initial_search_point.
  • rng::AbstractRNG: The random number generator to use.
  • update_representative_point=true: If true, then the representative point is updated. See update_centroid_after_addition!.
  • store_event_history=Val(false): If true, then the event history from the insertion is stored.
  • event_history=nothing: The event history to store the event history in. Should be an InsertionEventHistory if store_event_history is true, and false otherwise.
  • peek=Val(false): Whether to actually add new_point into tri, or just record into event_history all the changes that would occur from its insertion.

Output

  • V: The triangle in tri containing new_point.

Extended help

This function works as follows:

  1. First, the triangle containing the new point, V, is found using jump_and_march.
  2. Once the triangle is found, we call into add_point_bowyer_watson_and_process_after_found_triangle to properly insert the point.
  3. Inside add_point_bowyer_watson_and_process_after_found_triangle, we first call into add_point_bowyer_watson_after_found_triangle to add the point into the cavity. We then call into add_point_bowyer_watson_onto_segment to make any changes necessary incase the triangulation is constrained and new_point lies on a segment, since the depth-first search of the triangles containing new_point in its circumcenter must be performed on each side of the segment that new_point lies on.

The function add_point_bowyer_watson_dig_cavities! is the main workhorse of this function from add_point_bowyer_watson_after_found_triangle. See its docstring for the details.

DelaunayTriangulation.add_point_bowyer_watson_dig_cavities!Method
add_point_bowyer_watson_dig_cavities!(tri::Triangulation, new_point::N, V, q, flag, update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::F=Val(false)) where {N,F}

Deletes all the triangles in tri whose circumcircle contains new_point. This leaves behind a polygonal cavity, whose boundary edges are then connected to new_point, restoring the Delaunay property from new_point's insertion.

Arguments

  • tri: The Triangulation.
  • new_point::N: The point to insert.
  • V: The triangle in tri containing new_point.
  • q: The point to insert.
  • flag: The position of q relative to V. See point_position_relative_to_triangle.
  • update_representative_point=true: If true, then the representative point is updated. See update_centroid_after_addition!.
  • store_event_history=Val(false): If true, then the event history from the insertion is stored.
  • event_history=nothing: The event history to store the event history in. Should be an InsertionEventHistory if store_event_history is true, and false otherwise.
  • peek=Val(false): Whether to actually add new_point into tri, or just record into event_history all the changes that would occur from its insertion.

Output

There are no changes, but tri is updated in-place.

Extended help

This function works as follows:

  1. To dig the cavity, we call dig_cavity! on each edge of V, stepping towards the adjacent triangles to excavate the cavity recursively.
  2. Once the cavity has been excavated, extra care is needed in case is_on(flag), meaning new_point is on one of the edges of V. In particular, extra care is needed if: is_on(flag) && (is_boundary_triangle(tri, V) || is_ghost_triangle(V) && !is_boundary_node(tri, new_point)[1]). The need for this check is in case new_point is on a boundary edge already exists, since we need to fix the associated ghost edges. For example, a boundary edge (i, k) might have been split into the edges (i, j) and (j, k), which requires that the ghost triangle (k, i, g) be split into (j, i, g) and (k, j, g), where g is the ghost vertex. This part of the function will fix this case. The need for is_ghost_triangle(V) && !is_boundary_node(tri, new_point)[1] is in case the ghost edges were already correctly added. Nothing happens if the edge of V that new_point is on is not the boundary edge.
DelaunayTriangulation.add_point_cavity_cdt!Method
add_point_cavity_cdt!(tri::Triangulation, u, v, w, marked_vertices)

Adds a point to the cavity V left behind when deleting triangles intersected in a triangulation by an edge, updating tri to do so.

Arguments

  • tri::Triangulation: The Triangulation to update.
  • u: The vertex to add.
  • v: The vertex along the polygon that is next to u.
  • w: The vertex along the polygon that is previous to u.
  • marked_vertices: Cache for marking vertices to re-triangulate during the triangulation. This gets mutated.

Outputs

There is no output, but tri is updated in-place, as is marked_vertices if necessary.

DelaunayTriangulation.add_point_convex_triangulation!Method
add_point_convex_triangulation!(tri::Triangulation, u, v, w, S)

Adds the point u into the triangulation tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • u: The vertex to add.
  • v: The vertex next to u.
  • w: The vertex previous to u.
  • S: The set of vertices of the polygon.

Outputs

There is no output, as tri is modified in-place.

Extended help

This function forms part of Chew's algorithm for triangulating a convex polygon. There are some important points to make.

  1. Firstly, checking that x = get_adjacent(tri, w, v) is needed to prevent the algorithm from exiting the polygon.

This is important in case this algorithm is used as part of delete_point!. When you are just triangulating a convex polygon by itself, this checked is the same as checking edge_exists(tri, w, v).

  1. For this method to be efficient, the set x ∈ S must be O(1) time. This is why we use a Set type for S.
  2. The algorithm is recursive, recursively digging further through the polygon to find non-Delaunay edges to adjoins with u.
DelaunayTriangulation.add_polygon!Method
add_polygon!(vor::VoronoiTessellation, B, i)

Adds, or replaces, the polygon associated with the index i with B. B should be a counter-clockwise sequence of vertices, with B[begin] == B[end].

DelaunayTriangulation.add_segment!Method
add_segment!(tri::Triangulation, segment; rng::AbstractRNG=Random.default_rng())
add_segment!(tri::Triangulation, i, j; rng::AbstractRNG=Random.default_rng())

Adds segment = (i, j) to tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • segment: The segment to add. The second method uses (i, j) to represent the segment instead.

Outputs

There is no output, but tri will be updated so that it now contains segment.

DelaunayTriangulation.add_segment_intersection!Method
add_segment_intersection!(segment_intersections, boundary_sites, intersection_point, incident_polygon::I) where {I} -> Integer

Adds the intersection_point into the list of segment_intersections.

Arguments

  • segment_intersections: The list of segment intersections.
  • boundary_sites: A mapping from boundary sites to the indices of the segment intersections that are incident to the boundary site.
  • intersection_point: The intersection point to add.
  • incident_polygon: The index of the polygon that is incident to the intersection point.

Outputs

  • idx: The index of the intersection point in the list of segment intersections. iF the intersection point already exists in the list, then the index of the existing point is returned and used instead.
DelaunayTriangulation.add_segment_to_list!Method
add_segment_to_list!(tri::Triangulation, e)

Adds e to get_interior_segments(tri) and get_all_segments(tri) if it, or reverse_edge(e), is not already in the sets.

Arguments

Outputs

There is no output, but tri will be updated so that e is in get_interior_segments(tri) and get_all_segments(tri).

DelaunayTriangulation.add_to_edges!Method
add_to_edges!(E, e)

Add the edge e to E.

Examples

julia> using DelaunayTriangulation

julia> E = Set(((1, 2),(3,5)))
Set{Tuple{Int64, Int64}} with 2 elements:
  (1, 2)
  (3, 5)

julia> DelaunayTriangulation.add_to_edges!(E, (1, 5))
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (3, 5)
  (1, 5)
DelaunayTriangulation.add_to_intersected_edge_cache!Method
add_to_intersected_edge_cache!(intersected_edge_cache, u, v, a, b)

Add the edge uv to the list of intersected edges.

Arguments

  • intersected_edge_cache: The list of intersected edges.
  • u: The first vertex of the edge of the Voronoi polygon intersecting the edge ab of the boundary.
  • v: The second vertex of the edge of the Voronoi polygon intersecting the edge ab of the boundary.
  • a: The first vertex of the edge of the boundary.
  • b: The second vertex of the edge of the boundary.

Outputs

There are no outputs, as intersected_edge_cache is modified in-place.

DelaunayTriangulation.add_to_triangles!Method
add_to_triangles!(T, V)

Add the triangle V to the collection of triangles T.

Examples

julia> using DelaunayTriangulation

julia> T = Set(((1, 2, 3), (17, 8, 9)));

julia> DelaunayTriangulation.add_to_triangles!(T, (1, 5, 12))
Set{Tuple{Int64, Int64, Int64}} with 3 elements:
  (1, 5, 12)
  (1, 2, 3)
  (17, 8, 9)

julia> DelaunayTriangulation.add_to_triangles!(T, (-1, 3, 6))
Set{Tuple{Int64, Int64, Int64}} with 4 elements:
  (1, 5, 12)
  (1, 2, 3)
  (17, 8, 9)
  (-1, 3, 6)
DelaunayTriangulation.add_triangle!Function
add_triangle!(T, V...)
add_triangle!(T, i, j, k)

Add the triangles V... or V = (i, j, k) to the collection of triangles T.

Examples

julia> using DelaunayTriangulation

julia> T = Set(((1, 2, 3), (4, 5, 6)))
Set{Tuple{Int64, Int64, Int64}} with 2 elements:
  (4, 5, 6)
  (1, 2, 3)

julia> add_triangle!(T, (7, 8, 9));

julia> add_triangle!(T, (10, 11, 12), (13, 14, 15));

julia> add_triangle!(T, 16, 17, 18);

julia> T
Set{Tuple{Int64, Int64, Int64}} with 6 elements:
  (7, 8, 9)
  (10, 11, 12)
  (4, 5, 6)
  (13, 14, 15)
  (16, 17, 18)
  (1, 2, 3)
DelaunayTriangulation.add_triangle!Method
add_triangle!(adj::Adjacent, u, v, w)
add_triangle!(adj::Adjacent, T)

Adds the adjacency relationships defined from the triangle T = (u, v, w) to adj.

Examples

julia> using DelaunayTriangulation

julia> adj = DelaunayTriangulation.Adjacent{Int32, NTuple{2, Int32}}();

julia> add_triangle!(adj, 1, 2, 3)
Adjacent{Int32, Tuple{Int32, Int32}}, with map:
Dict{Tuple{Int32, Int32}, Int32} with 3 entries:
  (1, 2) => 3
  (3, 1) => 2
  (2, 3) => 1

julia> add_triangle!(adj, 6, -1, 7)
Adjacent{Int32, Tuple{Int32, Int32}}, with map:
Dict{Tuple{Int32, Int32}, Int32} with 6 entries:
  (1, 2)  => 3
  (3, 1)  => 2
  (6, -1) => 7
  (-1, 7) => 6
  (2, 3)  => 1
  (7, 6)  => -1
DelaunayTriangulation.add_triangle!Method
add_triangle!(adj2v::Adjacent2Vertex, u, v, w)
add_triangle!(adj2v::Adjacent2Vertex, T)

Adds the relationships defined by the triangle T = (u, v, w) into adj2v.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex{Int32, Set{NTuple{2, Int32}}}()
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}}()

julia> add_triangle!(adj2v, 17, 5, 8)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 3 entries:
  5  => Set([(8, 17)])
  8  => Set([(17, 5)])
  17 => Set([(5, 8)])

julia> add_triangle!(adj2v, 1, 5, 13)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 5 entries:
  5  => Set([(8, 17), (13, 1)])
  13 => Set([(1, 5)])
  8  => Set([(17, 5)])
  17 => Set([(5, 8)])
  1  => Set([(5, 13)])
DelaunayTriangulation.add_triangle!Method
add_triangle!(G::Graph, u, v, w)
add_triangle!(G::Graph, T)

Adds the neighbourhood relationships defined by the triangle T = (u, v, w) to the graph G.

DelaunayTriangulation.add_triangle!Method
add_triangle!(tri::Triangulation, u, v, w; protect_boundary=false, update_ghost_edges=false)
add_triangle!(tri::Triangulation, T; protect_boundary=false, update_ghost_edges=false)

Adds the triangle T = (u, v, w) into tri. This won't add the points into tri, it will just update the fields so that its existence in the triangulation is known.

Arguments

  • tri::Triangulation: The triangulation to add the triangle to.
  • u, v, w: The vertices of the triangle to add.

Keyword Arguments

  • protect_boundary=false: If true, then the boundary edges will not be updated. Otherwise, add_boundary_edges_single!, add_boundary_edges_double!, or add_boundary_edges_triple! will be called depending on the number of boundary edges in the triangle.
  • update_ghost_edges=false: If true, then the ghost edges will be updated. Otherwise, the ghost edges will not be updated. Will only be used if protect_boundary=false.

Outputs

There are no outputs as tri is updated in-place.

DelaunayTriangulation.add_voronoi_polygon!Method
add_voronoi_polygon!(vorn::VoronoiTessellation, i) -> Vector

Add the Voronoi polygon for the point i to the VoronoiTessellation vorn.

Arguments

Outputs

  • B: The vector of circumcenters defining the polygon. This is a circular vector, i.e. B[begin] == B[end].
DelaunayTriangulation.adjust_θMethod
adjust_θ(θ₁, θ₂, positive) -> (Number, Number)

Given two angles θ₁ and θ₂ in radians, adjusts the angles to new angles θ₁′, θ₂′ so that θ₁′ ≤ θ₂′ if positive is true, and θ₁′ ≥ θ₂′ if positive is false.

DelaunayTriangulation.angle_betweenMethod
angle_between(c₁::AbstractParametricCurve, c₂::AbstractParametricCurve) -> Float64

Given two curves c₁ and c₂ such that c₁(1) == c₂(0), returns the angle between the two curves, treating the interior of the curves as being left of both.

DelaunayTriangulation.angle_betweenMethod
angle_between(L₁::LineSegment, L₂::LineSegment) -> Float64

Returns the angle between L₁ and L₂, assuming that L₁.last == L₂.first (this is not checked). For consistency with If the segments are part of some domain, then the line segments should be oriented so that the interior is to the left of both segments.

DelaunayTriangulation.arc_lengthFunction
arc_length(c::AbstractParametricCurve) -> Float64
arc_length(c::AbstractParametricCurve, t₁, t₂) -> Float64

Returns the arc length of the [AbstractParametricCurve] c. The second method returns the arc length in the interval [t₁, t₂], where 0 ≤ t₁ ≤ t₂ ≤ 1.

DelaunayTriangulation.assess_triangle_qualityMethod
assess_triangle_quality(tri::Triangulation, args::RefinementArguments, T) -> Float64, Bool

Assesses the quality of a triangle T of tri according to the RefinementArguments.

Arguments

Output

  • ρ: The radius-edge ratio of the triangle.
  • flag: Whether the triangle is bad quality.

A triangle is bad quality if it does not meet the area constraints, violates the custom constraint, or if it is skinny but neither seditious or nestled.

DelaunayTriangulation.bounding_boxMethod
bounding_box(points, i, j) -> DiametralBoundingBox

Returns the bounding box of the diametral circle of the points points[i] and points[j] with generator edge (i, j), returned as an DiametralBoundingBox.

DelaunayTriangulation.bounding_boxMethod
bounding_box(tree::BoundaryRTree, i, j) -> DiametralBoundingBox

Returns the bounding box of the diametral circle of the edge between i and j in tree.

DelaunayTriangulation.brute_force_searchMethod
brute_force_search(tri::Triangulation, q; itr = each_triangle(tri))

Searches for the triangle containing the point q by brute force. An exception will be raised if no triangle contains the point.

See also jump_and_march.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The point to be located.

Keyword Arguments

  • itr = each_triangle(tri): The iterator over the triangles of the triangulation.

Output

  • V: The triangle containing the point q.
DelaunayTriangulation.brute_force_search_enclosing_circumcircleMethod
brute_force_search_enclosing_circumcircle(tri::Triangulation, i) -> Triangle

Searches for a triangle in tri containing the vertex i in its circumcircle using brute force. If tri is a weighted Delaunay triangulation, the triangle returned instead has the lifted vertex i below its witness plane. If no such triangle exists, (0, 0, 0) is returned.

DelaunayTriangulation.centroidal_smoothMethod
centroidal_smooth(vorn::VoronoiTessellation; maxiters=1000, tol=default_displacement_tolerance(vorn), rng=Random.default_rng(), kwargs...) -> VoronoiTessellation

Smooths vorn into a centroidal tessellation so that the new tessellation is of a set of generators whose associated Voronoi polygon is that polygon's centroid.

Arguments

Keyword Arguments

  • maxiters=1000: The maximum number of iterations.
  • tol=default_displacement_tolerance(vorn): The displacement tolerance. See default_displacement_tolerance for the default.
  • rng=Random.default_rng(): The random number generator.
  • kwargs...: Extra keyword arguments passed to retriangulate.

Outputs

Extended help

The algorithm is simple. We iteratively smooth the generators, moving them to the centroid of their associated Voronoi polygon for the current tessellation, continuing until the maximum distance moved of any generator is less than tol. Boundary generators are not moved.

DelaunayTriangulation.check_argsMethod
check_args(points, boundary_nodes, hierarchy::PolygonHierarchy) -> Bool

Check that the arguments points and boundary_nodes to triangulate, and a constructed PolygonHierarchy given by hierarchy, are valid. In particular, the function checks:

  • The points are all unique. If they are not, a DuplicatePointsError is thrown.
  • There are at least three points. If there are not, an InsufficientPointsError is thrown.

If boundary_nodes are provided, meaning has_boundary_nodes, then the function also checks:

  • If the boundary curves all connect consistently. Here, this means that each section of a boundary curve ends at the start of the next boundary section; for contiguous boundary curves, this means that the start and end boundary nodes are the same.
  • If the orientation of the boundary curves are all consistent. This means that the curves are all positively oriented relative to the domain, so that e.g. the exterior boundary curves are all counter-clockwise (relative to just themselves), the next exterior-most curves inside those exteriors are all clockwise (again, relative to just themselves), and so on.
Intersecting boundaries

Another requirement for triangulate is that none of the boundaries intersect in their interior, which also prohibits interior self-intersections. This is NOT checked. Similarly, segments should not intersect in their interior, which is not checked.

DelaunayTriangulation.check_delete_point_argsMethod
check_delete_point_args(tri::Triangulation, vertex, S) -> Bool

Checks that the vertex vertex can be deleted from the triangulation tri. Returns true if so, and throws an InvalidVertexDeletionError otherwise. This will occur if:

  1. vertex is a boundary node of tri.
  2. vertex is a ghost vertex of tri.
  3. vertex adjoins a segment of tri.
DelaunayTriangulation.check_for_intersections_with_adjacent_boundary_edgesMethod
check_for_intersections_with_adjacent_boundary_edges(tri::Triangulation, k, q, ghost_vertex=𝒢) -> (Certificate, Certificate, Vertex, Certificate, Certificate)

Given a boundary vertex k, find a triangle adjacent to k to locate a triangle or edge containing q.

See also search_down_adjacent_boundary_edges, which uses this function to determine an initial direction to search along a straight boundary in case q is collinear with it.

Arguments

  • tri::Triangulation: The Triangulation.
  • k: The boundary vertex to start from.
  • q: The query point.
  • ghost_vertex=𝒢: The ghost vertex corresponding to the boundary that k resides on.

Outputs

  • direction_cert: The direction of q relative to the vertex k along the boundary, given as a Certificate Left, Right, or Outside. If is_outside(direction_cert), then q is not collinear with either of the adjacent boundary edges.
  • q_pos_cert: The position of q relative to the vertex k along the boundary, given as a Certificate Left, Right, On, Outside, or Degenerate. This is similar to direction_cert in that it will be Outside whenever direction_cert is, but this certificate can also be On to indicate that not only is q in the direction given by direction_cert, but it is directly on the edge in that direction. If is_degnerate(q_pos_cert), then q = get_point(tri, next_vertex).
  • next_vertex: The next vertex along the boundary in the direction of q, or k if q is not collinear with either of the adjacent boundary edges.
  • right_cert: The Certificate for the position of q relative to the boundary edge right of k.
  • left_cert: The Certificate for the position of q relative to the boundary edge left of k.
DelaunayTriangulation.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertexMethod
check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri::Triangulation, k, q, right_cert, left_cert, store_history=Val(false), history=nothing, ghost_vertex=𝒢) -> (Bool, Vertex, Vertex, Certificate, Certificate)

Checks for intersections between the line pq, where p = get_point(tri, k), and the edges neighbouring p, assuming k is a boundary node. This function should only be used after using check_for_intersections_with_adjacent_boundary_edges.

Arguments

Outputs

The output takes the form (i, j, edge_cert, triangle_cert). Rather than defining each output individually, here are the possible froms of the output:

  • (i, j, Single, Outside): The line pq intersects the edge pᵢpⱼ and (j, i, k) is a positively oriented triangle so that pᵢ is left of pq and pⱼ is right of pq.
  • (i, j, None, Inside): The point q is inside the positively oriented triangle (i, j, k).
  • (0, 0, None, Outside): The point q is outside of the triangulation.
  • (i, j, On, Inside): The point q is on the edge pᵢpⱼ, and thus inside the positively oriented triangle (i, j, k).
  • (i, j, Right, Outside):The pointqis collinear with the edgepᵢpⱼ`, but is off of it and further into the triangulation.
Non-convex geometries

This function assumes that the geometry is convex.

Extended help

This function works in two stages. Firstly, using check_for_intersections_with_single_interior_edge_adjacent_to_boundary_vertex, we check for the intersection of pq with the edges neighbouring the vertex k, rotating counter-clockwise until we find an intersection or reach the other side of the boundary, starting from the first edge counter-clockwise away from the boundary edge right of the vertex k. By keeping track of the positions of pq relative to the current vertex and the previous, we can identify when an intersection is found. If no intersection is found before reaching the boundary edge left of k, then check_for_intersections_with_triangle_left_to_boundary_vertex is used to check the remaining triangle.

DelaunayTriangulation.check_for_invisible_steiner_pointMethod
check_for_invisible_steiner_point(tri::Triangulation, V, T, flag, c) -> Point, Triangle

Determines if the Steiner point c's insertion will not affect the quality of T, and if so instead changes c to be T's centroid.

Arguments

  • tri::Triangulation: The Triangulation to split a triangle of.
  • V: The triangle that the Steiner point is in.
  • T: The triangle that the Steiner point is from.
  • flag: A Certificate which is Cert.On if the Steiner point is on the boundary of V, Cert.Outside if the Steiner point is outside of V, and Cert.Inside if the Steiner point is inside of V.
  • c: The Steiner point.

Output

  • c′: The Steiner point to use instead of c, which is T's centroid if c is not suitable.
  • V′: The triangle that the Steiner point is in, which is T if c is not suitable.
DelaunayTriangulation.check_for_steiner_point_on_segmentMethod
check_for_steiner_point_on_segment(tri::Triangulation, V, V′, new_point, flag) -> Bool

Checks if the Steiner point with vertex new_point is on a segment. If so, then its vertex is pushed into the offcenter-split list from args, indicating that it should no longer be regarded as a free vertex (see is_free).

Arguments

  • tri::Triangulation: The Triangulation.
  • V: The triangle that the Steiner point was originally in prior to check_for_invisible_steiner_point.
  • V′: The triangle that the Steiner point is in.
  • new_point: The vertex associated with the Steiner point.
  • flag: A Certificate which is Cert.On if the Steiner point is on the boundary of V, Cert.Outside if the Steiner point is outside of V, and Cert.Inside if the Steiner point is inside of V.

Output

  • onflag: Whether the Steiner point is on a segment or not.
DelaunayTriangulation.check_steiner_point_precisionMethod
check_steiner_point_precision(tri::Triangulation, T, c) -> Bool

Checks if the Steiner point c of a triangle T of tri can be computed without precision issues, returning true if there are precision issues and false otherwise.

DelaunayTriangulation.choose_uvwMethod
choose_uvw(e1, e2, e3, u, v, w) -> (Vertex, Vertex, Vertex)

Choose values for (u, v, w) based on the Booleans (e1, e2, e3), assuming only one is true. The three cases are:

  • If e1, returns (u, v, w).
  • If e2, returns (v, w, u).
  • If e3, returns (w, u, v).
DelaunayTriangulation.circular_equalityFunction
circular_equality(A, B, by=isequal) -> Bool

Compares the two circular vectors A and B for equality up to circular rotation, using by to compare individual elements.

DelaunayTriangulation.classify_and_compute_segment_intersectionMethod
classify_and_compute_segment_intersection(a, b, c, d) -> (Certificate, Certificate, Certificate, NTuple{2, Number})

Given two line segments (a, b) and (c, d), classifies the intersection of the two segments. The returned value is (cert, cert_c, cert_d, p), where:

  • cert: A Certificate indicating the intersection type.
  • cert_c: A Certificate indicating the position of c relative to the line through (a, b).
  • cert_d: A Certificate indicating the position of d relative to the line through (a, b).
  • p: The intersection point if cert is Cert.Single or Cert.Touching, and (NaN, NaN) otherwise.
DelaunayTriangulation.classify_intersections!Method
classify_intersections!(intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, left_edge, right_edge, current_edge)

Classify the intersections in intersected_edge_cache into left_edge_intersectors, right_edge_intersectors, and current_edge_intersectors based on whether they intersect left_edge, right_edge, or current_edge, respectively.

Arguments

  • intersected_edge_cache: The list of intersected edges currently being considered.
  • left_edge_intersectors: The set of sites that intersect the edge to the left of an edge currently being considered.
  • right_edge_intersectors: The set of sites that intersect the edge to the right of an edge currently being considered.
  • current_edge_intersectors: The set of sites that intersect the current edge being considered.
  • left_edge: The edge to the left of e on the boundary.
  • right_edge: The edge to the right of e on the boundary.
  • current_edge: The edge on the boundary being considered.

Outputs

There are no outputs, but left_edge_intersectors, right_edge_intersectors, or current_edge_intersectors are updated all in-place depending on the type of intersection for each edge in intersected_edge_cache.

DelaunayTriangulation.clear_empty_keys!Method
clear_empty_keys!(adj2v::Adjacent2Vertex)

Deletes all vertices w from adj2v such that get_adjacent2vertex(adj2v, w) is empty.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex{Int64, Set{NTuple{2, Int64}}}()
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}}()

julia> add_triangle!(adj2v, 1, 2, 3)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 3 entries:
  2 => Set([(3, 1)])
  3 => Set([(1, 2)])
  1 => Set([(2, 3)])

julia> delete_triangle!(adj2v, 2, 3, 1)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 3 entries:
  2 => Set()
  3 => Set()
  1 => Set()

julia> DelaunayTriangulation.clear_empty_keys!(adj2v)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}}()
DelaunayTriangulation.clip_all_polygons!Method
clip_all_polygons!(vorn::VoronoiTessellation, n, boundary_sites, exterior_circumcenters, equal_circumcenter_mapping, is_convex)

Clip all of the polygons in the Voronoi tessellation.

Arguments

  • vorn: The VoronoiTessellation.
  • n: The number of vertices in the tessellation before clipping.
  • boundary_sites: A dictionary of boundary sites.
  • exterior_circumcenters: Any exterior circumcenters to be filtered out.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.
  • is_convex: Whether the boundary is convex or not. Not currently used.

Outputs

There are no outputs, but the polygons are clipped in-place.

DelaunayTriangulation.clip_bounded_polygon_to_bounding_boxMethod
clip_bounded_polygon_to_bounding_box(vorn::VoronoiTessellation, i, bounding_box) -> Vector{NTuple{2,Number}}

Clips the ith polygon of vorn to bounding_box.

See also clip_polygon.

Arguments

  • vorn: The VoronoiTessellation.
  • i: The index of the polygon.
  • bounding_box: The bounding box to clip the polygon to.

Outputs

  • coords: The coordinates of the clipped polygon. This is a circular vector.
DelaunayTriangulation.clip_polygon!Method
clip_polygon!(vorn::VoronoiTessellation, n, points, polygon, new_verts, exterior_circumcenters, equal_circumcenter_mapping, is_convex)

Clip the polygon polygon by removing the vertices that are outside of the domain and adding the new vertices new_verts to the polygon.

Arguments

  • vorn: The VoronoiTessellation.
  • n: The number of vertices in the tessellation before clipping.
  • points: The polygon points of the tessellation.
  • polygon: The index of the polygon to be clipped.
  • new_verts: The indices of the new vertices that are added to the polygon.
  • exterior_circumcenters: Any exterior circumcenters to be filtered out.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.
  • is_convex: Whether the boundary is convex or not. Not currently used.

Outputs

There are no outputs, but the polygon is clipped in-place.

DelaunayTriangulation.clip_polygonMethod
clip_polygon(vertices, points, clip_vertices, clip_points) -> Vector

Clip a polygon defined by (vertices, points) to a convex clip polygon defined by (clip_vertices, clip_points) with the Sutherland-Hodgman algorithm. The polygons should be defined in counter-clockwise order.

Arguments

  • vertices: The vertices of the polygon to be clipped.
  • points: The underlying point set that the vertices are defined over.
  • clip_vertices: The vertices of the clipping polygon.
  • clip_points: The underlying point set that the clipping vertices are defined over.

Output

  • clipped_polygon: The coordinates of the clipped polygon, given in counter-clockwise order and clipped_polygon[begin] == clipped_polygon[end].
DelaunayTriangulation.clip_voronoi_tessellation!Function
clip_voronoi_tessellation!(vorn::VoronoiTessellation, is_convex=true)

Clip the Voronoi tessellation vorn to the convex hull of the generators in vorn.

Arguments

  • vorn: The VoronoiTessellation.
  • is_convex: Whether the boundary is convex or not. Not currently used.

Outputs

There are no outputs, but the Voronoi tessellation is clipped in-place.

DelaunayTriangulation.close_voronoi_polygon!Method
close_voronoi_polygon!(vorn::VoronoiTessellation, B, i, encountered_duplicate_circumcenter, prev_ci)

Close the Voronoi polygon for the point i in the VoronoiTessellation vorn.

Arguments

  • vorn: The VoronoiTessellation.
  • B: The vector of circumcenters defining the polygon.
  • i: The polygon index.
  • encountered_duplicate_circumcenter: Whether or not a duplicate circumcenter has been encountered.
  • prev_ci: The previous circumcenter index.

Outputs

There are no outputs, as vorn and B are modified in-place.

DelaunayTriangulation.coarse_discretisation!Method
coarse_discretisation!(points, boundary_nodes, boundary_curve; n=0)

Constructs an initial coarse discretisation of a curve-bounded domain with bonudary defines by (points, boundary_nodes, boundary_curves), where boundary_nodes and boundary_curves should come from convert_boundary_curves!. The argument n is the amount of times to split an edge. If non-zero, this should be a power of two (otherwise it will be rounded up to the next power of two). If it is zero, then the splitting will continue until the maximum total variation over any subcurve is less than π/2.

DelaunayTriangulation.collapse_after_deletion!Method
collapse_after_deletion!(node::AbstractNode, tree::RTree, detached)

Condenses tree after a deletion of one of node's children. The detached argument will contain the nodes that were detached from tree during the condensing process.

DelaunayTriangulation.compare_distanceMethod
compare_distance(current_dist, current_idx, pts, i, qx, qy) -> (Number, Vertex)

Computes the minimum of the distance between the ith point of pts and (qx, qy) and current_dist.

Arguments

  • current_dist: The current value for the distance to the point (qx, qy).
  • current_idx: The point of pts corresponding to the distance current_dist.
  • pts: The point set.
  • i: The vertex to compare with current_idx.
  • qx: The x-coordinate of the query point.
  • qy: The y-coordinate of the query point.

Outputs

  • current_dist: The minimum of the distance between the ith point of pts and (qx, qy) and current_dist.
  • current_idx: The point of pts corresponding to the distance current_dist, which will be either i or current_idx.
DelaunayTriangulation.compare_triangle_collectionsMethod
compare_triangle_collections(T, V) -> Bool

Compare the collections of triangles T and V by comparing their triangles according to compare_triangles.

Examples

julia> using DelaunayTriangulation

julia> T = Set(((1, 2, 3), (4, 5, 6), (7, 8, 9)));

julia> V = [[2, 3, 1], [4, 5, 6], [9, 7, 8]];

julia> DelaunayTriangulation.compare_triangle_collections(T, V)
true

julia> V[1] = [17, 19, 20];

julia> DelaunayTriangulation.compare_triangle_collections(T, V)
false

julia> V = [[1, 2, 3], [8, 9, 7]];

julia> DelaunayTriangulation.compare_triangle_collections(T, V)
false
DelaunayTriangulation.compare_trianglesMethod
compare_triangles(T, V) -> Bool

Compare the triangles T and V by comparing their vertices up to rotation.

Examples

julia> using DelaunayTriangulation

julia> T1 = (1, 5, 10);

julia> T2 = (17, 23, 20);

julia> DelaunayTriangulation.compare_triangles(T1, T2)
false

julia> T2 = (5, 10, 1);

julia> DelaunayTriangulation.compare_triangles(T1, T2)
true

julia> T2 = (10, 1, 5);

julia> DelaunayTriangulation.compare_triangles(T1, T2)
true

julia> T2 = (10, 5, 1);

julia> DelaunayTriangulation.compare_triangles(T1, T2)
false
DelaunayTriangulation.compare_unoriented_edgesMethod
compare_unoriented_edges(u, v) -> Bool

Compare the unoriented edges u and v, i.e. compare the vertices of u and v in any order.

Examples

julia> using DelaunayTriangulation

julia> u = (1, 3);

julia> v = (5, 3);

julia> DelaunayTriangulation.compare_unoriented_edges(u, v)
false

julia> v = (1, 3);

julia> DelaunayTriangulation.compare_unoriented_edges(u, v)
true

julia> v = (3, 1);

julia> DelaunayTriangulation.compare_unoriented_edges(u, v)
true
DelaunayTriangulation.complete_split_edge_and_legalise!Function
complete_split_edge_and_legalise!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing)

Given a triangulation tri, an edge (i, j), and a point r, splits both (i, j) and (j, i) at r using split_edge! and then subsequently legalises the new edges with legalise_split_edge!.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the edge to split.
  • j: The second vertex of the edge to split.
  • r: The vertex to split the edge at.
  • store_event_history=Val(false): Whether to store the event history of the flip.
  • event_history=nothing: The event history. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.

Outputs

There is no output, as tri is updated in-place.

DelaunayTriangulation.complete_split_triangle_and_legalise!Method
complete_split_triangle_and_legalise!(tri::Triangulation, i, j, k, r)

Splits the triangle (i, j, k) at the vertex r, assumed to be inside the triangle, and legalises the newly added edges in tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the triangle.
  • j: The second vertex of the triangle.
  • k: The third vertex of the triangle.
  • r: The vertex to split the triangle at.

Outputs

There is no output, as tri is updated in-place.

DelaunayTriangulation.compute_balanceMethod
compute_balance(node::Union{Nothing,BalancedBSTNode{K}}) -> Int8

Computes the balance of the subtree rooted at node. This is the difference between the left and right heights.

DelaunayTriangulation.compute_concentric_shell_ternary_split_positionMethod
compute_concentric_shell_ternary_split_position(p, q) -> Float64

Returns the value of t ∈ [0, 1] that gives the most balanced ternary split of the segment pq, so that one of the segments has a power-of-two length and both segments have lengths between 1/3 and 2/3 of the length of pq.

DelaunayTriangulation.compute_countMethod
compute_count(node::Union{Nothing,BalancedBSTNode{K}}) -> Int32

Computes the count of the subtree rooted at node, i.e. the number of nodes in the subtree rooted at node, including node.

DelaunayTriangulation.compute_representative_points!Method
compute_representative_points!(tri::Triangulation; use_convex_hull=!has_boundary_nodes(tri), precision=one(number_type(tri)))

Computes a new set of representative points for tri.

Arguments

  • tri::Triangulation: The Triangulation for which to compute the representative points.

Keyword Arguments

  • use_convex_hull=!has_boundary_nodes(tri): If true, then the representative points are computed using the convex hull of the triangulation. Otherwise, the representative points are computed using the boundary nodes of the triangulation.
  • precision=one(number_type(tri)): The precision to use when computing the representative points via pole_of_inaccessibility.

Output

There are no outputs as tri is updated in-place, but for each curve the representative point is computed using pole_of_inaccessibility.

Exterior curves

While get_exterior_curve_indices(tri) does store the curves corresponding to exterior curves, this function still treats the first curve as the most important exterior curve, computing the representative point so that it is in no holes. In particular, other exterior curves might have representative points that are in a hole of one of their interior holes. This isn't much of a problem, indeed it wouldn't be a significant problem even if we had the representative point in a hole of the first curve, but it is something to be aware of.

DelaunayTriangulation.compute_split_positionMethod
compute_split_position(enricher::BoundaryEnricher, i, j) -> (Float64, Float64, NTuple{2,Float64})

Gets the point to split the edge (i, j) at.

Arguments

  • enricher::BoundaryEnricher: The enricher.
  • i: The first point of the edge.
  • j: The second point of the edge.

Outputs

  • t: The parameter value of the split point.
  • Δθ: The total variation of the subcurve (i, t). If a split was created due to a small angle, this will be set to zero.
  • ct: The point to split the edge at.
DelaunayTriangulation.compute_split_positionMethod
compute_split_position(tri::Triangulation, args::RefinementArguments, e) -> NTuple{2, Float64}

Computes the position to split a segment e of tri at in split_subsegment!.

Arguments

Output

  • mx, my: The position to split the segment at.

This point is computed according to a set of rules:

  1. If e is not a subsegment, meaning it is an input segment, then its midpoint is returned.
  2. If e is a subsegment and the segment adjoins two other distinct segments (one for each vertex) at an acute angle, as determined by segment_vertices_adjoin_other_segments_at_acute_angle, then the point is returned so that e can be split such that one of the new subsegments has a power-of-two length between 1/4 and 1/2 of the length of e, computed using compute_concentric_shell_quarternary_split_position.
  3. If e is a subsegment and the segment adjoins one other segment at an acute angle, as determined by segment_vertices_adjoin_other_segments_at_acute_angle, then the point is returned so that e can be split such that one of the new subsegments has a power-of-two length between 1/3 and 2/3 of the length of e, computed using compute_concentric_shell_ternary_split_position.
  4. Otherwise, the midpoint is returned.
DelaunayTriangulation.concavity_protection_checkMethod
concavity_protection_check(tri::Triangulation, concavity_protection, V, q) -> Bool

Check whether the jump_and_march algorithm needs to restart. This is only needed if tri is not convex.

Arguments

  • tri::Triangulation: The Triangulation.
  • concavity_protection: Whether this check is needed.
  • V: The triangle that the algorithm has found.
  • q: The query point.

Outputs

  • need_to_restart: Whether the algorithm needs to restart. Will also be false if concavity_protection.

Extended help

This function uses dist to determine whether the query point q is inside or outside of the polygon defined by the triangulation, and also checks the position of q relative to V via point_position_relative_to_triangle. If q is outside of this triangle, then need_to_restart = true. If q is inside this triangle, then issues can still arise due to overlapping ghost triangles from the non-convexity. Thus, depending on the result from dist and whether V is a ghost triangle, need_to_restart will be set accordingly.

DelaunayTriangulation.connect_segments!Method
connect_segments!(segments)

Connects the ordered vector of segments so that the endpoints all connect, preserving order.

Example

julia> using DelaunayTriangulation

julia> segments = [(7, 12), (12, 17), (17, 22), (32, 37), (37, 42), (42, 47)];

julia> DelaunayTriangulation.connect_segments!(segments)
7-element Vector{Tuple{Int64, Int64}}:
 (7, 12)
 (12, 17)
 (17, 22)
 (22, 32)
 (32, 37)
 (37, 42)
 (42, 47)
DelaunayTriangulation.constrained_triangulation!Method
constrained_triangulation!(tri::Triangulation, segments, boundary_nodes, full_polygon_hierarchy; rng=Random.default_rng(), delete_holes=true) -> Triangulation

Creates a constrained triangulation from tri by adding segments and boundary_nodes to it. This will be in-place, but a new triangulation is returned to accommodate the changed types.

Arguments

  • tri::Triangulation: The Triangulation.
  • segments: The interior segments to add to the triangulation.
  • boundary_nodes: The boundary nodes to add to the triangulation.
  • full_polygon_hierarchy: The PolygonHierarchy defining the boundary. This will get copied into the existing polygon hierarchy.

Keyword Arguments

  • rng=Random.default_rng(): The random number generator to use.
  • delete_holes=true: Whether to delete holes in the triangulation. See delete_holes!.

Outputs

DelaunayTriangulation.construct_boundary_edge_mapMethod
construct_boundary_edge_map(boundary_nodes::A, IntegerType::Type{I}=number_type(boundary_nodes), EdgeType::Type{E}=NTuple{2,IntegerType}) where {A,I,E} -> Dict

Constructs a map that takes boundary edges in boundary_nodes to a Tuple giving the edge's position in boundary_nodes. In particular, if dict = construct_boundary_edge_map(boundary_nodes), then dict[e] = (pos, ℓ) so that bn = get_boundary_nodes(boundary_nodes, pos) gives the boundary nodes associated with the section that e lives on, and get_boundary_nodes(bn, ℓ) is the first vertex of e.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.construct_boundary_edge_map([17, 18, 15, 4, 3, 17])
Dict{Tuple{Int64, Int64}, Tuple{Vector{Int64}, Int64}} with 5 entries:
  (18, 15) => ([17, 18, 15, 4, 3, 17], 2)
  (3, 17)  => ([17, 18, 15, 4, 3, 17], 5)
  (17, 18) => ([17, 18, 15, 4, 3, 17], 1)
  (4, 3)   => ([17, 18, 15, 4, 3, 17], 4)
  (15, 4)  => ([17, 18, 15, 4, 3, 17], 3)

julia> DelaunayTriangulation.construct_boundary_edge_map([[5, 17, 3, 9], [9, 18, 13, 1], [1, 93, 57, 5]])
Dict{Tuple{Int64, Int64}, Tuple{Int64, Int64}} with 9 entries:
  (18, 13) => (2, 2)
  (17, 3)  => (1, 2)
  (9, 18)  => (2, 1)
  (13, 1)  => (2, 3)
  (3, 9)   => (1, 3)
  (93, 57) => (3, 2)
  (5, 17)  => (1, 1)
  (57, 5)  => (3, 3)
  (1, 93)  => (3, 1)

julia> DelaunayTriangulation.construct_boundary_edge_map([[[2, 5, 10], [10, 11, 2]], [[27, 28, 29, 30], [30, 31, 85, 91], [91, 92, 27]]])
Dict{Tuple{Int64, Int64}, Tuple{Tuple{Int64, Int64}, Int64}} with 12 entries:
  (92, 27) => ((2, 3), 2)
  (2, 5)   => ((1, 1), 1)
  (11, 2)  => ((1, 2), 2)
  (10, 11) => ((1, 2), 1)
  (30, 31) => ((2, 2), 1)
  (91, 92) => ((2, 3), 1)
  (29, 30) => ((2, 1), 3)
  (31, 85) => ((2, 2), 2)
  (27, 28) => ((2, 1), 1)
  (5, 10)  => ((1, 1), 2)
  (28, 29) => ((2, 1), 2)
  (85, 91) => ((2, 2), 3)
DelaunayTriangulation.construct_edgeFunction
construct_edge(::Type{E}, i, j) where {E} -> E

Construct an edge of type E from vertices i and j.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.construct_edge(NTuple{2,Int}, 2, 5)
(2, 5)

julia> DelaunayTriangulation.construct_edge(Vector{Int32}, 5, 15)
2-element Vector{Int32}:
  5
 15
DelaunayTriangulation.construct_ghost_vertex_mapMethod
construct_ghost_vertex_map(boundary_nodes::A, IntegerType::Type{I}=number_type(boundary_nodes)) where {A,I} -> Dict

Given a set of boundary_nodes, returns a Dict that maps ghost vertices to their associated section in boundary_nodes. There are three cases:

  • has_multiple_curves(boundary_nodes)

Returns dict::Dict{I, NTuple{2, I}}, mapping ghost vertices i to Tuples (m, n) so that get_boundary_nodes(boundary_nodes, m, n) are the boundary nodes associated with i, i.e. the nth section of the mth curve is associated with the ghost vertex i.

  • has_multiple_sections(boundary_nodes)

Returns dict::Dict{I, I}, mapping ghost vertices i to n so that get_boundary_nodes(boundary_nodes, n) are the boundary nodes associated with i, i.e. the nth section of the boundary is associated with the ghost vertex i.

  • otherwise

Returns dict::Dict{I, A}, mapping the ghost vertex i to boundary_nodes.

Examples

julia> using DelaunayTriangulation

julia> gv_map = DelaunayTriangulation.construct_ghost_vertex_map([1, 2, 3, 4, 5, 1])
Dict{Int64, Vector{Int64}} with 1 entry:
  -1 => [1, 2, 3, 4, 5, 1]

julia> gv_map = DelaunayTriangulation.construct_ghost_vertex_map([[17, 29, 23, 5, 2, 1], [1, 50, 51, 52], [52, 1]])
Dict{Int64, Int64} with 3 entries:
  -1 => 1
  -3 => 3
  -2 => 2

julia> gv_map = DelaunayTriangulation.construct_ghost_vertex_map([[[1, 5, 17, 18, 1]], [[23, 29, 31, 33], [33, 107, 101], [101, 99, 85, 23]]])
Dict{Int64, Tuple{Int64, Int64}} with 4 entries:
  -1 => (1, 1)
  -3 => (2, 2)
  -2 => (2, 1)
  -4 => (2, 3)

Extended help

This map can be useful for iterating over all boundary nodes. For example, you can iterate over all sections of a boundary using:

gv_map = construct_ghost_vertex_map(boundary_nodes)
for (ghost_vertex, section) in gv_map 
    nodes = get_boundary_nodes(boundary_nodes, section)
    # do something with nodes
end

This works for any form of boundary_nodes.

DelaunayTriangulation.construct_ghost_vertex_rangesMethod
construct_ghost_vertex_ranges(boundary_nodes::A, IntegerType::Type{I}=number_type(boundary_nodes)) where {A,I} -> Dict

Given a set of boundary_nodes, returns a Dict that maps ghost vertices to the range of all ghost vertices that the corresponding boundary curve could correspond to.

Examples

julia> using DelaunayTriangulation

julia> boundary_nodes = [
                  [
                      [1, 2, 3, 4], [4, 5, 6, 1]
                  ],
                  [
                      [18, 19, 20, 25, 26, 30]
                  ],
                  [
                      [50, 51, 52, 53, 54, 55], [55, 56, 57, 58], [58, 101, 103, 105, 107, 120], [120, 121, 122, 50]
                  ]
              ]
3-element Vector{Vector{Vector{Int64}}}:
 [[1, 2, 3, 4], [4, 5, 6, 1]]
 [[18, 19, 20, 25, 26, 30]]
 [[50, 51, 52, 53, 54, 55], [55, 56, 57, 58], [58, 101, 103, 105, 107, 120], [120, 121, 122, 50]]

julia> DelaunayTriangulation.construct_ghost_vertex_ranges(boundary_nodes)
Dict{Int64, UnitRange{Int64}} with 7 entries:
  -5 => -7:-4
  -1 => -2:-1
  -7 => -7:-4
  -3 => -3:-3
  -2 => -2:-1
  -4 => -7:-4
  -6 => -7:-4
DelaunayTriangulation.construct_polygon_hierarchyMethod
construct_polygon_hierarchy(points, boundary_nodes, boundary_curves; IntegerType=Int, n=4096) -> PolygonHierarchy{IntegerType}

Returns a PolygonHierarchy defining the polygon hierarchy for a given set of boundary_nodes that define a curve-bounded domain from the curves in boundary_curves. Uses polygonise to fill in the boundary curves.

Arguments

Keyword Arguments

  • IntegerType=Int: The integer type to use for indexing the polygons.
  • n=4096: The number of points to use for filling in the boundary curves in polygonise.
DelaunayTriangulation.construct_positively_oriented_triangleMethod
construct_positively_oriented_triangle(::Type{V}, i, j, k, points) where {V} -> V

Construct a triangle of type V from vertices i, j, and k such that the triangle is positively oriented, using points for the coordinates.

Examples

julia> using DelaunayTriangulation

julia> points = [(0.0, 0.0), (0.0, 1.0), (1.0, 0.0)];

julia> DelaunayTriangulation.construct_positively_oriented_triangle(NTuple{3, Int}, 1, 2, 3, points)
(2, 1, 3)

julia> DelaunayTriangulation.construct_positively_oriented_triangle(NTuple{3, Int}, 2, 3, 1, points)
(3, 2, 1)

julia> DelaunayTriangulation.construct_positively_oriented_triangle(NTuple{3, Int}, 2, 1, 3, points)
(2, 1, 3)

julia> DelaunayTriangulation.construct_positively_oriented_triangle(NTuple{3, Int}, 3, 2, 1, points)
(3, 2, 1)

julia> points = [(1.0, 1.0), (2.5, 2.3), (17.5, 23.0), (50.3, 0.0), (-1.0, 2.0), (0.0, 0.0), (5.0, 13.33)];

julia> DelaunayTriangulation.construct_positively_oriented_triangle(Vector{Int}, 5, 3, 2, points)
3-element Vector{Int64}:
 3
 5
 2

julia> DelaunayTriangulation.construct_positively_oriented_triangle(Vector{Int}, 7, 1, 2, points)
3-element Vector{Int64}:
 7
 1
 2

julia> DelaunayTriangulation.construct_positively_oriented_triangle(Vector{Int}, 7, 2, 1, points)
3-element Vector{Int64}:
 2
 7
 1

julia> DelaunayTriangulation.construct_positively_oriented_triangle(Vector{Int}, 5, 4, 3, points)
3-element Vector{Int64}:
 5
 4
 3
DelaunayTriangulation.construct_segment_mapMethod
construct_segment_map(segments, points, IntegerType) -> Dict{IntegerType, Vector{IntegerType}}

Returns the segment map of segments. This is a map that maps a vertex to all vertices that share a segment with that vertex. Segments are stored twice. The vertices associated with a vertex are sorted counter-clockwise, using the points argument to define the coordinates.

DelaunayTriangulation.construct_tree!Method
construct_tree!(enricher::BoundaryEnricher)

Constructs the spatial tree for enricher, modifying the spatial tree field in-place. The parent map must be correctly configured in order for this to be valid.

DelaunayTriangulation.construct_triangleFunction
construct_triangle(::Type{T}, i, j, k) where {T} -> Triangle

Construct a triangle of type T from vertices i, j, and k.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.construct_triangle(NTuple{3,Int}, 1, 2, 3)
(1, 2, 3)

julia> DelaunayTriangulation.construct_triangle(Vector{Int32}, 1, 2, 3)
3-element Vector{Int32}:
 1
 2
 3
DelaunayTriangulation.contains_boundary_edgeMethod
contains_boundary_edge(tri::Triangulation, ij) -> Bool 
contains_boundary_edge(tri::Triangulation, i, j) -> Bool

Returns true if the boundary edge (i, j) is in tri, and false otherwise. Orientation matters here.

DelaunayTriangulation.contains_edgeFunction
contains_edge(i, j, E) -> Bool
contains_edge(e, E) -> Bool

Check if E contains the edge e = (i, j).

Examples

julia> using DelaunayTriangulation

julia> E = Set(((1,3),(17,3),(1,-1)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, -1)
  (17, 3)
  (1, 3)

julia> DelaunayTriangulation.contains_edge((1, 2), E)
false

julia> DelaunayTriangulation.contains_edge((17, 3), E)
true

julia> DelaunayTriangulation.contains_edge(3, 17, E) # order
false

julia> E = [[1,2],[5,13],[-1,1]]
3-element Vector{Vector{Int64}}:
 [1, 2]
 [5, 13]
 [-1, 1]

julia> DelaunayTriangulation.contains_edge(1, 2, E)
true
DelaunayTriangulation.contains_segmentMethod
contains_segment(tri::Triangulation, ij) -> Bool 
contains_segment(tri::Triangulation, i, j) -> Bool

Returns true if (i, j) is a segment in tri, and false otherwise. Both (i, j) and (j, i) are checked.

DelaunayTriangulation.contains_triangleFunction
contains_triangle(T, V) -> (Triangle, Bool)

Check if the collection of triangles V contains the triangle T up to rotation. The Triangle returned is the triangle in V that is equal to T up to rotation, or T if no such triangle exists. The Bool is true if V contains T, and false otherwise.

Examples

julia> using DelaunayTriangulation

julia> V = Set(((1, 2, 3), (4, 5, 6), (7, 8, 9)))
Set{Tuple{Int64, Int64, Int64}} with 3 elements:
  (7, 8, 9)
  (4, 5, 6)
  (1, 2, 3)

julia> DelaunayTriangulation.contains_triangle((1, 2, 3), V)
((1, 2, 3), true)

julia> DelaunayTriangulation.contains_triangle((2, 3, 1), V)
((1, 2, 3), true)

julia> DelaunayTriangulation.contains_triangle((10, 18, 9), V)
((10, 18, 9), false)

julia> DelaunayTriangulation.contains_triangle(9, 7, 8, V)
((7, 8, 9), true)
DelaunayTriangulation.contains_triangleMethod
contains_triangle(tri::Triangulation, T) -> (Triangle, Bool)
contains_triangle(tri::Triangulation, i, j, k) -> (Triangle, Bool)

Tests whether tri contains T = (i, j, k) up to rotation, returning

  • V: The rotated form of T that is in tri, or simply T if T is not in tri.
  • flag: true if T is in tri, and false otherwise.
DelaunayTriangulation.convert_boundary_curves!Method
convert_boundary_curves!(points, boundary_nodes, IntegerType) -> (NTuple{N, AbstractParametricCurve} where N, Vector)

Converts the provided points and boundary_nodes into a set of boundary curves and modified boundary nodes suitable for triangulation. In particular:

  1. The function gets boundary_curves from to_boundary_curves.
  2. boundary_nodes is replaced with a set of initial boundary nodes (from get_skeleton). These nodes come from evaluating each boundary curve at t = 0 and t = 1. In the case of a piecewise linear boundary, the vertices are copied directly. Note that not all control points of a CatmullRomSpline (which is_interpolating) will be added - only those at t = 0 and t = 1.
  3. The points are modified to include the new boundary nodes. If a point is already in points, it is not added again.

Arguments

  • points: The point set. This is modified in place with the new boundary points.
  • boundary_nodes: The boundary nodes to be converted. This is not modified in place.
  • IntegerType: The type of integer to use for the boundary nodes.

Output

  • boundary_curves: The boundary curves associated with boundary_nodes.
  • boundary_nodes: The modified boundary nodes.
DelaunayTriangulation.convert_boundary_points_to_indicesFunction
convert_boundary_points_to_indices(x, y; existing_points = NTuple{2, Float64}[], check_args=true) -> (Vector, Vector)
convert_boundary_points_to_indices(xy; existing_points = NTuple{2, Float64}[], check_args=true) -> (Vector, Vector)

Converts a boundary represented by (x, y) or xy, where the points are combined rather than as separate sets of coordinates, into a set of boundary nodes for use in triangulate.

Arguments

  • x, y: The x and y-coordinates for the boundary points. The individual vectors must match the specification required for boundaries outlined in the documentation.
  • xy: As above, except the coordinates are combined rather than given as separate vectors.

Keyword Arguments

  • existing_points: The existing points to append the boundary points to. This is useful if you have a pre-existing set of points.
  • check_args: Whether to check that the arguments match the specification in the documentation.

Outputs

  • boundary_nodes: The boundary nodes.
  • points: The point set, which is the same as existing_points but with the boundary points appended to it.
DelaunayTriangulation.convert_certificateMethod
convert_certificate(cert::I, Cert1, Cert2, Cert3) -> Certificate

Given cert ∈ (-1, 0, 1), return Cert1, Cert2 or Cert3 depending on if cert == -1, cert == 0 or cert == 1, respectively.

DelaunayTriangulation.convex_hull!Method
convex_hull!(tri::Triangulation; reconstruct=has_boundary_nodes(tri))

Updates the convex_hull field of tri to match the current triangulation.

Arguments

Keyword Arguments

  • reconstruct=has_boundary_nodes(tri): If true, then the convex hull is reconstructed from scratch, using convex_hull on the points. Otherwise, computes the convex hull using the ghost triangles of tri. If there are no ghost triangles but reconstruct=true, then the convex hull is reconstructed from scratch.
DelaunayTriangulation.convex_hullMethod
convex_hull(points; IntegerType::Type{I}=Int) where {I} -> ConvexHull

Computes the convex hull of points. The monotone chain algorithm is used.

Arguments

  • points: The set of points.

Output

DelaunayTriangulation.curvatureMethod
curvature(c::AbstractParametricCurve, t) -> Float64

Returns the curvature of the [AbstractParametricCurve] c at t.

DelaunayTriangulation.default_displacement_toleranceMethod
default_displacement_tolerance(vorn::VoronoiTessellation) -> Number

Returns the default displacement tolerance for the centroidal smoothing algorithm. The default is given by max_extent / 1e4, where max_extent = max(width, height), where width and height are the width and height of the bounding box of the underlying point set.

Arguments

Outputs

  • tol: The default displacement tolerance.
DelaunayTriangulation.default_num_samplesMethod
default_num_samples(n) -> Integer

Given a number of points n, returns ∛n rounded up to the nearest integer. This is the default number of samples used in the jump-and-march algorithm.

DelaunayTriangulation.delete_adjacent!Method
delete_adjacent!(adj::Adjacent, uv)
delete_adjacent!(adj::Adjacent, u, v)

Deletes the edge uv from adj.

Examples

julia> using DelaunayTriangulation

julia> adj = DelaunayTriangulation.Adjacent(Dict((2, 7) => 6, (7, 6) => 2, (6, 2) => 2, (17, 3) => -1, (-1, 5) => 17, (5, 17) => -1));

julia> DelaunayTriangulation.delete_adjacent!(adj, 2, 7)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 5 entries:
  (-1, 5) => 17
  (17, 3) => -1
  (6, 2)  => 2
  (5, 17) => -1
  (7, 6)  => 2

julia> DelaunayTriangulation.delete_adjacent!(adj, (6, 2))
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 4 entries:
  (-1, 5) => 17
  (17, 3) => -1
  (5, 17) => -1
  (7, 6)  => 2

julia> DelaunayTriangulation.delete_adjacent!(adj, 5, 17)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 3 entries:
  (-1, 5) => 17
  (17, 3) => -1
  (7, 6)  => 2
DelaunayTriangulation.delete_adjacent!Method
delete_adjacent!(vor::VoronoiTessellation, ij)
delete_adjacent!(vor::VoronoiTessellation, i, j)

Deletes the edge (i, j) from the adjacency map of vor.

DelaunayTriangulation.delete_adjacent2vertex!Method
delete_adjacent2vertex!(adj2v::Adjacent2Vertex, w, uv)
delete_adjacent2vertex!(adj2v::Adjacent2Vertex, w, u, v)

Deletes the edge uv from the set of edges E such that (u, v, w) is a positively oriented triangle in the underlying triangulation for each (u, v) ∈ E.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex(Dict(1 => Set(((2, 3), (5, 7), (8, 9))), 5 => Set(((1, 2), (7, 9), (8, 3)))))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  5 => Set([(1, 2), (8, 3), (7, 9)])
  1 => Set([(8, 9), (5, 7), (2, 3)])

julia> DelaunayTriangulation.delete_adjacent2vertex!(adj2v, 5, 8, 3)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  5 => Set([(1, 2), (7, 9)])
  1 => Set([(8, 9), (5, 7), (2, 3)])

julia> DelaunayTriangulation.delete_adjacent2vertex!(adj2v, 1, (2, 3))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  5 => Set([(1, 2), (7, 9)])
  1 => Set([(8, 9), (5, 7)])
DelaunayTriangulation.delete_adjacent2vertex!Method
delete_adjacent2vertex!(adj2v::Adjacent2Vertex, w)

Deletes the vertex w from adj2v.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex(Dict(1 => Set(((2, 3), (5, 7))), 5 => Set(((-1, 2), (2, 3)))))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  5 => Set([(-1, 2), (2, 3)])
  1 => Set([(5, 7), (2, 3)])

julia> DelaunayTriangulation.delete_adjacent2vertex!(adj2v, 1)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 1 entry:
  5 => Set([(-1, 2), (2, 3)])

julia> DelaunayTriangulation.delete_adjacent2vertex!(adj2v, 5)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}}()
DelaunayTriangulation.delete_adjacent2vertex!Method
delete_adjacent2vertex!(tri::Triangulation, w, uv)
delete_adjacent2vertex!(tri::Triangulation, w, u, v)

Deletes the edge (u, v) from the set of edges returned by get_adjacent2vertex(tri, w).

DelaunayTriangulation.delete_boundary_node!Method
delete_boundary_node!(boundary_nodes, pos)

Deletes the boundary node at the position pos from boundary_nodes. Here, pos[1] is such that get_boundary_nodes(boundary_nodes, pos[1]) is the section that the node will be deleted from, and pos[2] gives the position of the array to delete from. In particular,

delete_boundary_node!(boundary_nodes, pos)

is the same as

deleteat!(get_boundary_nodes(boundary_nodes, pos[1]), pos[2])

Examples

julia> using DelaunayTriangulation

julia> boundary_nodes = [71, 25, 33, 44, 55, 10];

julia> DelaunayTriangulation.delete_boundary_node!(boundary_nodes, (boundary_nodes, 4))
5-element Vector{Int64}:
 71
 25
 33
 55
 10

julia> boundary_nodes = [[7, 13, 9, 25], [25, 26, 29, 7]];

julia> DelaunayTriangulation.delete_boundary_node!(boundary_nodes, (2, 3))
2-element Vector{Vector{Int64}}:
 [7, 13, 9, 25]
 [25, 26, 7]

julia> boundary_nodes = [[[17, 23, 18, 25], [25, 26, 81, 91], [91, 101, 17]], [[1, 5, 9, 13], [13, 15, 1]]];

julia> DelaunayTriangulation.delete_boundary_node!(boundary_nodes, ((2, 2), 2))
2-element Vector{Vector{Vector{Int64}}}:
 [[17, 23, 18, 25], [25, 26, 81, 91], [91, 101, 17]]
 [[1, 5, 9, 13], [13, 1]]
DelaunayTriangulation.delete_boundary_node!Method
delete_boundary_node!(tri::Triangulation, pos)

Deletes the boundary node at the specified position pos in tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • pos: The position to delete the node at, given as a Tuple so that delete_boundary_node!(tri, pos) is the same as deleteat!(get_boundary_nodes(tri, pos[1]), pos[2]).

Outputs

There are no outputs, but the boundary nodes of tri are updated in-place.

DelaunayTriangulation.delete_edge!Method
delete_edge!(E, e...)

Delete the edges e... from E.

Examples

julia> using DelaunayTriangulation

julia> E = Set(([1,2],[10,15],[1,-1],[13,23],[1,5]))
Set{Vector{Int64}} with 5 elements:
  [10, 15]
  [1, 5]
  [1, 2]
  [1, -1]
  [13, 23]

julia> DelaunayTriangulation.delete_edge!(E, [10,15])

julia> E
Set{Vector{Int64}} with 4 elements:
  [1, 5]
  [1, 2]
  [1, -1]
  [13, 23]

julia> DelaunayTriangulation.delete_edge!(E, [1,5], [1, -1])

julia> E
Set{Vector{Int64}} with 2 elements:
  [1, 2]
  [13, 23]
DelaunayTriangulation.delete_from_edges!Method
delete_from_edges!(E, e)

Delete the edge e from E.

Examples

julia> using DelaunayTriangulation

julia> E = Set(([1,2],[5,15],[17,10],[5,-1]))
Set{Vector{Int64}} with 4 elements:
  [17, 10]
  [5, 15]
  [5, -1]
  [1, 2]

julia> DelaunayTriangulation.delete_from_edges!(E, [5, 15])
Set{Vector{Int64}} with 3 elements:
  [17, 10]
  [5, -1]
  [1, 2]
DelaunayTriangulation.delete_from_triangles!Method
delete_from_triangles!(T, V)

Delete the triangle V from the collection of triangles T. Only deletes V if V is in T up to rotation.

Examples

julia> using DelaunayTriangulation

julia> V = Set(((1, 2, 3), (4, 5, 6), (7, 8, 9)))
Set{Tuple{Int64, Int64, Int64}} with 3 elements:
  (7, 8, 9)
  (4, 5, 6)
  (1, 2, 3)

julia> DelaunayTriangulation.delete_from_triangles!(V, (4, 5, 6))
Set{Tuple{Int64, Int64, Int64}} with 2 elements:
  (7, 8, 9)
  (1, 2, 3)

julia> DelaunayTriangulation.delete_from_triangles!(V, (9, 7, 8))
Set{Tuple{Int64, Int64, Int64}} with 1 element:
  (1, 2, 3)
DelaunayTriangulation.delete_ghost_triangles!Method
delete_ghost_triangles!(tri::Triangulation)

Deletes all the ghost triangles from tri.

Ghost vertices

Ghost vertices are still used in the keys of the Adjacent2Vertex of tri, and are still present in the Graph. If you want to delete the ghost vertex keys from the Adjacent2Vertex, you need to use delete_adjacent2vertex!. For deleting the ghost vertices from the Graph, you need delete_ghost_vertices_from_graph!. Additionally, edges in Adjacent can still map to ghost vertices. If you also want to delete those, you need to filter through the values of the Adjacent map that are ghost vertices, and use delete_adjacent!.

DelaunayTriangulation.delete_holes!Method
delete_holes!(tri::Triangulation)

Deletes all the exterior faces to the boundary nodes specified in the triangulation tri.

Extended help

This function works in several stages:

  1. First, find_all_points_to_delete is used to identify all points in the exterior faces.
  2. Once all the points to delete have been found, all the associated triangles are found using find_all_triangles_to_delete, taking care for any incorrectly identified triangles and points.
  3. Once the correct set of triangles to delete has been found, they are deleted using delete_all_exterior_triangles!.
DelaunayTriangulation.delete_node!Method
delete_node!(node::Union{Nothing,BalancedBSTNode{K}}, key::K) -> Union{Nothing,BalancedBSTNode{K}}

Deletes the node with key key from the subtree rooted at node if it exists. Returns the new root of the subtree.

DelaunayTriangulation.delete_point!Method
delete_point!(tri::Triangulation, vertex; kwargs...)

Deletes the vertex of tri, retriangulating the cavity formed by the surrounding polygon of vertex using triangulate_convex.

It is not possible to delete vertices that are on the boundary, are ghost vertices, or adjoin a segment of tri. See also check_delete_point_args.

Point deletion

This function will not actually delete the corresponding coordinates from get_points(tri), nor will it remove the associated weight from get_weights(tri).

Arguments

Keyword Arguments

  • store_event_history=Val(false): Whether to store the event history of the triangulation from deleting the point.
  • event_history=nothing: The event history of the triangulation from deleting the point. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to use for the triangulation.
DelaunayTriangulation.delete_polygon_vertices_in_random_order!Method
delete_polygon_vertices_in_random_order!(list::ShuffledPolygonLinkedList, tri::Triangulation, u, v, rng::AbstractRNG)

Deletes vertices from the polygon defined by list in a random order.

Arguments

  • list::ShuffledPolygonLinkedList: The linked list of polygon vertices.
  • tri::Triangulation: The Triangulation.
  • u, v: The vertices of the segment (u, v) that was inserted in order to define the polygon V = list.S.
  • rng::AbstractRNG: The random number generator to use.

Outputs

There is no output, but list is updated in-place.

DelaunayTriangulation.delete_triangle!Function
delete_triangle!(V, T...)
delete_triangle!(V, i, j, k)

Delete the triangles T... from the collection of triangles V.

Examples

julia> using DelaunayTriangulation

julia> V = Set(((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, 15)))
Set{Tuple{Int64, Int64, Int64}} with 5 elements:
  (7, 8, 9)
  (10, 11, 12)
  (4, 5, 6)
  (13, 14, 15)
  (1, 2, 3)

julia> delete_triangle!(V, (6, 4, 5))
Set{Tuple{Int64, Int64, Int64}} with 4 elements:
  (7, 8, 9)
  (10, 11, 12)
  (13, 14, 15)
  (1, 2, 3)

julia> delete_triangle!(V, (10, 11, 12), (1, 2, 3))
Set{Tuple{Int64, Int64, Int64}} with 2 elements:
  (7, 8, 9)
  (13, 14, 15)

julia> delete_triangle!(V, 8, 9, 7)
Set{Tuple{Int64, Int64, Int64}} with 1 element:
  (13, 14, 15)
DelaunayTriangulation.delete_triangle!Method
delete_triangle!(adj::Adjacent, u, v, w)
delete_triangle!(adj::Adjacent, T)

Deletes the adjacency relationships defined from the triangle T = (u, v, w) from adj.

Examples

julia> using DelaunayTriangulation

julia> adj = DelaunayTriangulation.Adjacent{Int32, NTuple{2, Int32}}();

julia> add_triangle!(adj, 1, 6, 7);

julia> add_triangle!(adj, 17, 3, 5);

julia> adj
Adjacent{Int32, Tuple{Int32, Int32}}, with map:
Dict{Tuple{Int32, Int32}, Int32} with 6 entries:
  (17, 3) => 5
  (1, 6)  => 7
  (6, 7)  => 1
  (7, 1)  => 6
  (5, 17) => 3
  (3, 5)  => 17

julia> delete_triangle!(adj, 3, 5, 17)
Adjacent{Int32, Tuple{Int32, Int32}}, with map:
Dict{Tuple{Int32, Int32}, Int32} with 3 entries:
  (1, 6) => 7
  (6, 7) => 1
  (7, 1) => 6

julia> delete_triangle!(adj, 7, 1, 6)
Adjacent{Int32, Tuple{Int32, Int32}}, with map:
Dict{Tuple{Int32, Int32}, Int32}()
DelaunayTriangulation.delete_triangle!Method
delete_triangle!(adj2v::Adjacent2Vertex, u, v, w)
delete_triangle!(adj2v::Adjacent2Vertex, T)

Deletes the relationships defined by the triangle T =(u, v, w) from adj2v.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex{Int32, Set{NTuple{2, Int32}}}()
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}}()

julia> add_triangle!(adj2v, 1, 2, 3)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 3 entries:
  2 => Set([(3, 1)])
  3 => Set([(1, 2)])
  1 => Set([(2, 3)])

julia> add_triangle!(adj2v, 17, 5, 2)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 5 entries:
  5  => Set([(2, 17)])
  2  => Set([(3, 1), (17, 5)])
  17 => Set([(5, 2)])
  3  => Set([(1, 2)])
  1  => Set([(2, 3)])

julia> delete_triangle!(adj2v, 5, 2, 17)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 5 entries:
  5  => Set()
  2  => Set([(3, 1)])
  17 => Set()
  3  => Set([(1, 2)])
  1  => Set([(2, 3)])

julia> delete_triangle!(adj2v, 2, 3, 1)
Adjacent2Vertex{Int32, Set{Tuple{Int32, Int32}}} with map:
Dict{Int32, Set{Tuple{Int32, Int32}}} with 5 entries:
  5  => Set()
  2  => Set()
  17 => Set()
  3  => Set()
  1  => Set()
DelaunayTriangulation.delete_triangle!Method
delete_triangle!(G::Graph, u, v, w)
delete_triangle!(G::Graph, T)

Deletes the neighbourhood relationships defined by the triangle T = (u, v, w) from the graph G.

DelaunayTriangulation.delete_triangle!Method
delete_triangle!(tri::Triangulation, u, v, w; protect_boundary=false, update_ghost_edges=false)
delete_triangle!(tri::Triangulation, T; protect_boundary=false, update_ghost_edges=false)

Deletes the triangle T = (u, v, w) from tri. This won't delete the points from tri, it will just update the fields so that its non-existence in the triangulation is known.

Arguments

  • tri::Triangulation: The triangulation to delete the triangle from.
  • u, v, w: The vertices of the triangle to delete.

Keyword Arguments

  • protect_boundary=false: If true, then the boundary edges will not be updated. Otherwise, delete_boundary_edges_single!, delete_boundary_edges_double!, or delete_boundary_edges_triple! will be called depending on the number of boundary edges in the triangle.
  • update_ghost_edges=false: If true, then the ghost edges will be updated. Otherwise, the ghost edges will not be updated. Will only be used if protect_boundary=false.

Outputs

There are no outputs as tri is updated in-place.

DelaunayTriangulation.delete_vertex!Method
delete_vertex!(list::ShuffledPolygonLinkedList, i)

Deletes the vertex S[πᵢ] from the linked list, where πᵢ = list.shuffled_indices[i]. This deletion is done symbolically rather than by mutating the vectors in list. In particular, we perform

  • next[prev[πᵢ]] = next[πᵢ]
  • prev[next[πᵢ]] = prev[πᵢ]

which is the same as removing S[πᵢ] from the linked list.

DelaunayTriangulation.delete_vertices_in_random_order!Method
delete_vertices_in_random_order!(list::Triangulation, tri::ShuffledPolygonLinkedList, rng)

Deletes the vertices of the polygon represented by list in random order, done by switching the pointers of the linked list. Only three vertices will survive. If these these three vertices are collinear, then the deletion is attempted again after reshuffling the vertices.

Arguments

  • list::ShuffledPolygonLinkedList: The linked list representing the polygon to be deleted.
  • tri::Triangulation: The Triangulation.
  • rng::AbstractRNG: The random number generator used to shuffle the vertices of S.

Outputs

There is no output, as list is modified in-place.

DelaunayTriangulation.dequeue_and_process!Method
dequeue_and_process!(vorn, polygon_edge_queue, edges_to_process,
    intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors,
    processed_pairs, boundary_sites, segment_intersections, exterior_circumcenters, equal_circumcenter_mapping)

Dequeue an edge from polygon_edge_queue and process it. If polygon_edge_queue is empty, then we process the first edge in edges_to_process.

Arguments

  • vorn: The VoronoiTessellation.
  • polygon_edge_queue: The queue of edges that need to be processed.
  • edges_to_process: The edges that need to be processed.
  • intersected_edge_cache: A cache of intersected edges.
  • left_edge_intersectors: The intersection points of left_edge with other edges.
  • right_edge_intersectors: The intersection points of right_edge with other edges.
  • current_edge_intersectors: The intersection points of current_edge with other edges.
  • processed_pairs: A set of pairs of edges and polygons that have already been processed.
  • boundary_sites: A dictionary of boundary sites.
  • segment_intersections: A dictionary of segment intersections.
  • exterior_circumcenters: A dictionary of exterior circumcenters.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.

Outputs

There are no outputs. Instead, the caches and queues are updated in-place.

Extended help

This function works as follows:

  1. Firstly, if there are no edges queued in polygon_edge_queue, then we enqueue the first in edge in edges_to_process using enqueue_new_edge!.
  2. We then dequeue the next edge to be processed. If the edge has already been processed, then we return early.
  3. If we're still here, then we process the (edge, polygon) pair enqueued from polygon_edge_queue using process_polygon!. This function checks for intersections of the edge with the polygon.
  4. Once the polygon has been processed, we then needed to classify all of the intersections using classify_intersections!, which determines, for each intersection, if the intersection is with edge, or with the edge left of edge, or to the edge right of edge.
  5. Then, process_intersection_points! is used to process the intersection points, enqueueing new edges when needed.
  6. We then delete the edge from edges_to_process if it is in there and return.
DelaunayTriangulation.detach!Method
detach!(node::AbstractNode, idx) -> Bool

Detaches the idxth child of node. Returns true if the node's bounding box had to be adjusted and false otherwise.

DelaunayTriangulation.dig_cavity!Method
dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_history=Val(false), event_history=nothing, peek::F=Val(false)) where {F}

Excavates the cavity in tri through the edge (i, j), stepping towards the adjacent triangles to excavate the cavity recursively, eliminating all triangles containing r in their circumcircle.

Arguments

  • tri: The Triangulation.
  • r: The new point being inserted.
  • i: The first vertex of the edge (i, j).
  • j: The second vertex of the edge (i, j).
  • : The vertex adjacent to (j, i), so that the triangle being stepped into is (j, i, ℓ).
  • flag: The position of r relative to V. See point_position_relative_to_triangle.
  • V: The triangle in tri containing r.
  • store_event_history=Val(false): If true, then the event history from the insertion is stored.
  • event_history=nothing: The event history to store the event history in. Should be an InsertionEventHistory if store_event_history is true, and false otherwise.
  • peek=Val(false): Whether to actually add new_point into tri, or just record into event_history all the changes that would occur from its insertion.

Output

There are no changes, but tri is updated in-place.

Extended help

This function works as follows:

  1. First, we check if is 0, which would imply that the triangle (j, i, ℓ) doesn't exist as it has already been deleted. If this is the check, we return and stop digging.
  2. If the edge (i, j) is not a segment, r is inside of the circumcenter of (j, i, ℓ), and is not a ghost vertex, then we can step forward into the next triangles. In particular, we delete the triangle (j, i, ℓ) from tri and then call dig_cavity! again on two edges of (j, i, ℓ) other than (j, i).
  3. If we did not do step 2, then this means that we are on the edge of the polygonal cavity; this also covers the case that is a ghost vertex, i.e. we are at the boundary of the triangulation. There are two cases to consider here. Firstly, if (i, j) is not a segment, we just need to add the triangle (r, i, j) into tri to connect r to this edge of the polygonal cavity. If (i, j) is a segment, then the situation is more complicated. In particular, r being on an edge of V might imply that we are going to add a degenerate triangle (r, i, j) into tri, and so this needs to be avoided. So, we check if is_on(flag) && contains_segment(tri, i, j) and, if the edge that r is on is (i, j), we add the triangle (r, i, j). Otherwise, we do nothing.
DelaunayTriangulation.distMethod
dist(p, q) -> Number

Assuming p and q are two-dimensional, computes the Euclidean distance between p and q.

DelaunayTriangulation.distMethod
dist(tri::Triangulation, p) -> Number

Given a point p, returns the distance from p to the triangulation, using the conventions from distance_to_polygon:

  • δ > 0: If the returned distance is positive, then p is inside the triangulation.
  • δ < 0: If the returned distance is negative, then p is outside the triangulation.
  • δ = 0: If the returned distance is zero, then p is on the boundary of the triangulation.

Where we say distance, we are referring to the distance from p to the boundary of the triangulation.

DelaunayTriangulation.dist_sqrMethod
dist_sqr(p, q) -> Number

Assuming p and q are two-dimensional, computes the square of the Euclidean distance between p and q.

DelaunayTriangulation.distance_to_offcenterMethod
distance_to_offcenter(β, ℓ) -> Number

Given a triangle with shortest edge length , computes the distance from the edge to the offcenter of the triangle with radius-edge ratio cutoff β.

DelaunayTriangulation.distance_to_polygonMethod
distance_to_polygon(q, points, boundary_nodes) -> Number

Given a query point q and a polygon defined by (points, boundary_nodes), returns the signed distance from q to the polygon. The boundary_nodes must match the specification in the documentation and in check_args.

See also dist.

DelaunayTriangulation.each_added_boundary_segmentMethod
each_added_boundary_segment(events::InsertionEventHistory) -> Iterator

Returns an iterator over the boundary segments that were added to the triangulation during the insertion of a point.

DelaunayTriangulation.each_added_segmentMethod
each_deleted_triangle(events::InsertionEventHistory) -> Iterator

Returns an iterator over the triangles that were deleted from the triangulation during the insertion of a point.

DelaunayTriangulation.each_added_triangleMethod
each_added_triangle(events::InsertionEventHistory) -> Iterator

Returns an iterator over the triangles that were added to the triangulation during the insertion of a point.

DelaunayTriangulation.each_boundary_nodeMethod
each_boundary_node(boundary_nodes) -> Iterator

Returns an iterator that goves over each node in boundary_nodes. It is assumed that boundary_nodes represents a single section or a single contiguous boundary; if you do want to loop over every boundary nodes for a boundary with multiple sections, you should to see the result from construct_ghost_vertex_map.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.each_boundary_node([7, 8, 19, 2, 17])
5-element Vector{Int64}:
  7
  8
 19
  2
 17

julia> DelaunayTriangulation.each_boundary_node([7, 8, 19, 2, 17, 7])
6-element Vector{Int64}:
  7
  8
 19
  2
 17
  7
DelaunayTriangulation.each_edgeFunction
each_edge(E) -> Iterator

Get an iterator over the edges in E.

Examples

julia> using DelaunayTriangulation

julia> E = Set(((1,2),(1,3),(2,-1)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (1, 3)
  (2, -1)

julia> each_edge(E)
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (1, 3)
  (2, -1)
DelaunayTriangulation.each_pointFunction
each_point(points) -> Iterator

Returns an iterator over each point in points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 2.0), (5.0, 13.0)];

julia> DelaunayTriangulation.each_point(points)
2-element Vector{Tuple{Float64, Float64}}:
 (1.0, 2.0)
 (5.0, 13.0)

julia> points = [1.0 5.0 17.7; 5.5 17.7 0.0];

julia> DelaunayTriangulation.each_point(points)
3-element ColumnSlices{Matrix{Float64}, Tuple{Base.OneTo{Int64}}, SubArray{Float64, 1, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:
 [1.0, 5.5]
 [5.0, 17.7]
 [17.7, 0.0]
DelaunayTriangulation.each_pointMethod
each_point(tri::Triangulation) -> Points

Returns an iterator over all points in tri.

Missing vertices

If tri has vertices that are not yet present in the triangulation, e.g. if you have deleted vertices or have some submerged vertices in a weighted triangulation, then the corresponding points will still be present in this iterator. It is recommended that you instead consider each_vertex, each_solid_vertex, or each_ghost_vertex together with get_point to get the coordinates.

DelaunayTriangulation.each_point_indexFunction
each_point_index(points) -> Iterator

Returns an iterator over each point index in points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 2.0), (-5.0, 2.0), (2.3, 2.3)];

julia> DelaunayTriangulation.each_point_index(points)
Base.OneTo(3)

julia> points = [1.0 -5.0 2.3; 2.0 2.0 2.3];

julia> DelaunayTriangulation.each_point_index(points)
Base.OneTo(3)
DelaunayTriangulation.each_point_indexMethod
each_point_index(tri::Triangulation) -> Indices

Returns an iterator over all point indices in tri.

Missing vertices

If tri has vertices that are not yet present in the triangulation, e.g. if you have deleted vertices or have some submerged vertices in a weighted triangulation, then the corresponding point indices will still be present in this iterator. It is recommended that you instead consider each_vertex, each_solid_vertex, or each_ghost_vertex.

DelaunayTriangulation.each_triangleFunction
each_triangle(T) -> Iterator

Return an iterator over the triangles in T.

Examples

julia> using DelaunayTriangulation

julia> T = Set(((1, 2, 3), (-1, 5, 10), (17, 13, 18)));

julia> each_triangle(T)
Set{Tuple{Int64, Int64, Int64}} with 3 elements:
  (-1, 5, 10)
  (1, 2, 3)
  (17, 13, 18)

julia> T = [[1, 2, 3], [10, 15, 18], [1, 5, 6]];

julia> each_triangle(T)
3-element Vector{Vector{Int64}}:
 [1, 2, 3]
 [10, 15, 18]
 [1, 5, 6]
DelaunayTriangulation.edge_lengthFunction
edge_length(tri::Triangulation, u, v) -> Number
edge_length(tri::Triangulation, e) -> Number

Computes the length of the edge e = (u, v).

DelaunayTriangulation.edge_length_sqrMethod
edge_length_sqr(tri::Triangulation, u, v) -> Number
edge_length_sqr(tri::Triangulation, e) -> Number

Computes the square of the length of the edge e = (u, v).

DelaunayTriangulation.edge_typeMethod
edge_type(E) -> DataType

Get the type of edges in E.

Examples

julia> using DelaunayTriangulation

julia> e = Set(((1,2),(2,3),(17,5)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (17, 5)
  (2, 3)

julia> DelaunayTriangulation.edge_type(e)
Tuple{Int64, Int64}

julia> e = [[1,2],[3,4],[17,3]]
3-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]
 [17, 3]

julia> DelaunayTriangulation.edge_type(e)
Vector{Int64} (alias for Array{Int64, 1})
DelaunayTriangulation.edge_typeMethod
edge_type(vorn::VoronoiTessellation) -> DataType

Type used for representing individual edges in the Voronoi tessellation.

DelaunayTriangulation.edge_verticesMethod
edge_vertices(e) -> NTuple{2, Vertex}

Get the vertices of e

Examples

julia> using DelaunayTriangulation

julia> e = (1, 5);

julia> edge_vertices(e)
(1, 5)

julia> e = [23, 50];

julia> edge_vertices(e)
(23, 50)
DelaunayTriangulation.enqueue_new_edge!Method
enqueue_new_edge!(polygon_edge_queue, vorn::VoronoiTessellation, e)

Enqueue the edge e of the boundary to be processed.

Arguments

  • polygon_edge_queue: The queue of edges that are to be processed.
  • vorn: The VoronoiTessellation.
  • e: The edge to be processed.

Outputs

There are no outputs, as polygon_edge_queue is modified in-place.

DelaunayTriangulation.enqueue_newly_encroached_segments!Method
enqueue_newly_encroached_segments!(args::RefinementArguments, tri::Triangulation) -> Bool

Enqueues all segments that are newly encroached upon after a point insertion into the triangulation into args.queue.

Arguments

Output

  • any_encroached: Whether any segments were newly encroached upon.
DelaunayTriangulation.enrich_boundary!Method
enrich_boundary!(enricher::BoundaryEnricher)

Enriches the initial boundary defined inside enricher, implementing the algorithm of Gosselin and Ollivier-Gooch (2007). At the termination of the algorithm, all edges will contain no other points inside their diametral circles.

DelaunayTriangulation.expandFunction
expand(box::BoundingBox, perc=0.10) -> BoundingBox

Expands the bounding box box by a factor perc in each direction.

DelaunayTriangulation.expand_bounds!Function
expand_bounds!(hierarchy::PolygonHierarchy, perc=0.10) -> PolygonHierarchy

Expands the bounding boxes of hierarchy by a factor of perc in each direction.

DelaunayTriangulation.extend_segments!Method
extend_segments!(segments, segment)

Given an ordered vector of segments, ensures that they also represent the replacement of segment. In particular, suppose segments represents the sequence of edges

    ---(i₁, i₂)---(i₂, i₃)---(⋯, ⋯)---(iₙ₋₁, iₙ)---

and segment is (i₀, iₙ₊₁). Then the extended sequence becomes

    ---(i₀, i₁)---(i₁, i₂)---(i₂, i₃)---(⋯, ⋯)---(iₙ₋₁, iₙ)---(iₙ, iₙ₊₁)---

Example

julia> using DelaunayTriangulation

julia> segments = [(2, 7), (7, 12), (12, 49)];

julia> segment = (1, 68);

julia> DelaunayTriangulation.extend_segments!(segments, segment)
5-element Vector{Tuple{Int64, Int64}}:
 (1, 2)
 (2, 7)
 (7, 12)
 (12, 49)
 (49, 68)
DelaunayTriangulation.exterior_jump_and_marchFunction
exterior_jump_and_march(tri::Triangulation, k, q, ghost_vertex=𝒢) -> (Vertex, Vertex)

Given a query point q outside of the triangulation, find the ghost triangle containing q.

Arguments

  • tri: The Triangulation.
  • k: The exterior boundary vertex to start from.
  • q: The query point.
  • ghost_vertex=𝒢: The ghost vertex corresponding to the boundary that k resides on.

Outputs

  • i: The first vertex of the edge on the boundary adjoining the positively oriented ghost triangle.
  • j: The second vertex of the edge on the boundary adjoining the positively oriented ghost triangle.
Non-convex geometries and internal query points

This function assumes that the geometry is convex. If the geometry is not convex, the returned value may not be correct and should be checked separately. Additionally, if q is actually inside the triangulation, then the result is meaningless.

Extended help

This function works by first finding the position of q relative to pₘp, where pₘ is the representative point for the ghost_vertex and p = get_point(tri, k). Depending on this position, we rotate counter-clockwise if q is left of the line using exterior_jump_and_march_rotate_left and clockwise otherwise using exterior_jump_and_march_rotate_right. By keeping track of the current position of q and its position relative to the next ghost edge, we can identify when q resides inside a ghost triangle.

DelaunayTriangulation.finalise!Method
finalise!(tri::Triangulation, args::RefinementArguments)

Finalises the triangulation after refinement, e.g. by deleting ghost triangles and unlocking the convex hull if needed.

DelaunayTriangulation.find_all_intersectionsMethod
find_all_intersections(vorn::VoronoiTessellation) -> (Dict, Vector, Set, Dict)

Find all intersections between the edges of the Voronoi tessellation and the boundary of the polygon.

Arguments

Outputs

  • boundary_sites: A dictionary of boundary sites.
  • segment_intersections: The intersection points.
  • exterior_circumcenters: The circumcenters that are outside of the domain.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.

Extended help

This algorithm works as follows:

  1. First, using initialise_clipping_arrays, we initialise the arrays that we will use to store the intersections, and queue up all boundary edges for processing.
  2. Then, starting with the first edge in edges_to_process, we dequeue an edge from polygon_edge_queue and process it via dequeue_and_process!.
  3. We repeat step 2 until polygon_edge_queue and edges_to_process are both empty.
  4. In the special case that there is just a single triangle in the underlying triangulation, we process the intersections using add_segment_intersection! directly.
  5. We then return.
DelaunayTriangulation.find_all_points_to_delete!Method
find_all_points_to_delete!(points_to_process, tri::Triangulation, seed, all_bn)

Starting at seed, finds more points to spread to and mark for deletion.

Arguments

  • points_to_process: The current list of points marked for deletion.
  • tri::Triangulation: The Triangulation.
  • seed: The seed vertex to start spreading from.
  • all_bn: All the boundary nodes in the triangulation, obtained from get_all_boundary_nodes.

Outputs

There are no outputs, as points_to_process is updated in-place.

Extended help

This function works by considering the neighbours around the vertex seed. For each neighbouring vertex, we designate that as a new seed, and consider if it needs to be added into points_to_process according to its distance from the triangulation computed from distance_to_polygon. We then call find_all_points_to_delete! recursively again on the new seed.

DelaunayTriangulation.find_all_points_to_deleteMethod
find_all_points_to_delete(tri::Triangulation) -> Set{Int}

Returns a set of all the points that are in the exterior faces of the triangulation tri.

Extended help

This function works by 'spreading' from some initial vertex. In particular, starting at each boundary node, we spread outwards towards adjacent vertices, recursively spreading so that all exterior points are identified with the help of find_all_points_to_delete!.

DelaunayTriangulation.find_all_triangles_to_deleteMethod
find_all_triangles_to_delete(tri::Triangulation, points_to_process) -> Set{Triangle}

Returns a set of all the triangles that are in the exterior faces of the triangulation tri.

Arguments

Outputs

  • triangles_to_delete: The set of triangles that are in the exterior faces of the triangulation tri.

Extended help

This function works in two stages.

  1. Firstly, all the non-boundary vertices, i.e. those from points_to_process, are processed. For each vertex v, the triangles adjoining it, given by get_adjacent2vertex(tri, v), aremarked for deletion.
  2. Next, all the boundary vertices need to be processed and carefully analysed to determine if any other triangles need to be deleted since, for example, a triangle may be adjoining three vertices that are all boundary vertices, and it might not be obvious if it is inside or outside of the triangulation. By applying dist to compute the distance between the triangle's centroid and the triangulation, the triangle can be accurately marked for deletion if it is outside of the triangulation.
DelaunayTriangulation.find_bounding_boxMethod
find_bounding_box(tree::RTree, id_bounding_box::DiametralBoundingBox) -> Tuple{Leaf{Branch}, Int}

Returns the leaf node and the index in the leaf node's children that id_bounding_box is associated with.

DelaunayTriangulation.find_duplicate_pointsMethod
find_duplicate_points(points) -> Dict{Point, Vector{Int}}

Returns a Dict of points that maps each duplicate point to a Vector of the indices of the duplicate points.

DelaunayTriangulation.find_edgeMethod
find_edge(tri::Triangulation, T, ℓ) -> Edge

Given a triangle T = (i, j, k) of tri and a vertex of tri, returns the edge of T that contains . If no such edge exists, the edge (k, i) is returned.

DelaunayTriangulation.find_point_indexMethod
find_point_index(points, x, y) -> Integer
find_point_index(points, p) -> Integer

Returns an index of a point in points that is equal to p = (x, y). If no such point exists, then 0 is returned.

DelaunayTriangulation.find_polygonMethod
find_polygon(tri::Triangulation, q) -> Integer

Given a point q, finds the index of the polygon in the triangulation tri that contains q. If q is on the boundary of the triangulation or outside the triangulation, the function returns 0.

See also dist and distance_to_polygon.

DelaunayTriangulation.find_subtreeMethod
find_subtree(tree, bounding_box, level) -> Union{Branch,Leaf{Branch}}

Returns the subtree of tree at level that bounding_box should be inserted into.

DelaunayTriangulation.find_treeMethod
find_tree(hierarchy::PolygonHierarchy, points, boundary_nodes, p) -> Union{Nothing,PolygonTree}

Finds a tree in hierarchy containing p.

Arguments

  • hierarchy::PolygonHierarchy: The PolygonHierarchy to search.
  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • p: The point to test the trees of hierarchy against.

Output

  • nothing if p is not inside any tree in hierarchy, and the PolygonTree containing p otherwise.
DelaunayTriangulation.find_treeMethod
find_tree(hierarchy::PolygonHierarchy, points, boundary_nodes, tree::PolygonTree, p) -> PolygonTree

Finds a tree in hierarchy containing p that is a child of tree, assuming p is inside tree.

Arguments

  • hierarchy::PolygonHierarchy: The PolygonHierarchy to search.
  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • tree::PolygonTree: The PolygonTree to search, assuming p is inside tree.
  • p: The point to test the children of tree against.

Output

  • tree if p is inside tree but none of its children, and a child containing p otherwise.
DelaunayTriangulation.fix_down!Method
fix_down!(queue::MaxPriorityQueue, k)

Fixes the queue after decreasing the value of one of its elements by percolating downwards.

DelaunayTriangulation.fix_segments!Method
fix_segments!(segments, bad_indices)

Fixes the overlapping segments in segments, referred to via bad_indices, by connecting consecutive edges where needed.

Arguments

  • segments: The segments to fix.
  • bad_indices: The indices of the segments to fix.

Outputs

There are no outputs as segments is updated in-place.

Example

julia> using DelaunayTriangulation

julia> segments = [(2, 15), (2, 28), (2, 41)]; # the edges all start with 2, so they are not actual segments in the triangulation, and so must be fixed

julia> bad_indices = [1, 2, 3];

julia> DelaunayTriangulation.fix_segments!(segments, bad_indices)
3-element Vector{Tuple{Int64, Int64}}:
 (2, 15)
 (15, 28)
 (28, 41)

julia> segments = [(2, 7), (2, 12), (12, 17), (2, 22), (2, 27), (2, 32), (32, 37), (2, 42), (42, 47)];

julia> bad_indices = [2, 4, 5, 6, 8]
5-element Vector{Int64}:
 2
 4
 5
 6
 8

julia> DelaunayTriangulation.fix_segments!(segments, bad_indices)
9-element Vector{Tuple{Int64, Int64}}:
 (2, 7)
 (7, 12)
 (12, 17)
 (17, 22)
 (22, 27)
 (27, 32)
 (32, 37)
 (37, 42)
 (42, 47)
DelaunayTriangulation.fix_up!Method
fix_up!(queue::MaxPriorityQueue, k)

Fixes the queue after increasing the value of one of its elements by percolating upwards.

DelaunayTriangulation.flip_edge!Method
flip_edge!(tri::Triangulation, i, j, store_event_history=Val(false), event_history=nothing)
flip_edge!(tri::Triangulation, i, j, k, ℓ, store_event_history=Val(false), event_history=nothing)

Flips the edge between vertices i and j in tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the edge to flip.
  • j: The second vertex of the edge to flip.
  • k: The vertex k = get_adjacent(tri, j, i). This is only used in the second method.
  • : The vertex ℓ = get_adjacent(tri, i, j). This is only used in the second method.
  • store_event_history=Val(false): Whether to store the event history of the flip.
  • event_history=nothing: The event history. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object. This storage is done using store_flip_edge_history!.

Outputs

There is no output, as tri is updated in-place.

Invalid flips

If (i, j, k, ℓ), where ℓ = get_adjacent(tri, i, j) and k = get_adjacent(tri, j, i), is not a convex quadrilateral, then this edge flip will make the triangulation non-planar.

DelaunayTriangulation.get_adjacentMethod
get_adjacent(adj::Adjacent) -> Dict

Returns the adjacent map of adj.

Examples

julia> using DelaunayTriangulation

julia> d = Dict((1, 2) => 3, (2, 3) => 1, (3, 1) => 2);

julia> adj = DelaunayTriangulation.Adjacent(d)
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 3 entries:
  (1, 2) => 3
  (3, 1) => 2
  (2, 3) => 1

julia> get_adjacent(adj)
Dict{Tuple{Int64, Int64}, Int64} with 3 entries:
  (1, 2) => 3
  (3, 1) => 2
  (2, 3) => 1

julia> get_adjacent(adj) == d
true
DelaunayTriangulation.get_adjacentMethod
get_adjacent(tri::Triangulation, uv) -> Vertex
get_adjacent(tri::Triangulation, u, v) -> Vertex

Returns the vertex w such that (u, v, w) is a positively oriented triangle in the underlying triangulation, or if no such triangle exists.

DelaunayTriangulation.get_adjacentMethod
get_adjacent(tri::Triangulation) -> Adjacent

Returns the adjacency map of the triangulation. This is a map from each edge (u, v) to a vertex w such that (u, v, w) is a positively oriented triangle in tri.

See also Adjacent.

DelaunayTriangulation.get_adjacentMethod
get_adjacent(vor::VoronoiTessellation, ij) -> Index 
get_adjacent(vor::VoronoiTessellation, i, j) -> Index

Gets the polygon index associated with the oriented edge ij in the Voronoi tessellation vor.

DelaunayTriangulation.get_adjacentMethod
get_adjacent(vorn::VoronoiTessellation) -> Adjacent{Index,Edge}

Gets the adjacency information of the Voronoi tessellation vorn as an Adjacent object. This object maps oriented edges to the polygons that they belong to.

DelaunayTriangulation.get_adjacentMethod
get_adjacent(adj::Adjacent{I, E}, uv::E) -> Vertex
get_adjacent(adj::Adjacent{I, E}, u, v) -> Vertex

Returns the vertex w such that (u, v, w) is a positively oriented triangle in the underlying triangulation, or if no such triangle exists.

Examples

julia> using DelaunayTriangulation

julia> adj = DelaunayTriangulation.Adjacent(Dict((1, 2) => 3, (2, 3) => 1, (3, 1) => 2, (4, 5) => -1))
Adjacent{Int64, Tuple{Int64, Int64}}, with map:
Dict{Tuple{Int64, Int64}, Int64} with 4 entries:
  (4, 5) => -1
  (1, 2) => 3
  (3, 1) => 2
  (2, 3) => 1

julia> get_adjacent(adj, 4, 5)
-1

julia> get_adjacent(adj, (3, 1))
2

julia> get_adjacent(adj, (1, 2))
3

julia> get_adjacent(adj, 17, 5)
0

julia> get_adjacent(adj, (1, 6))
0
DelaunayTriangulation.get_adjacent2vertexMethod
get_adjacent2vertex(adj2v::Adjacent2Vertex, w) -> Edges

Returns the set of edges E such that (u, v, w) is a positively oriented triangle in the underlying triangulation for each (u, v) ∈ E.

Examples

julia> using DelaunayTriangulation

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex(Dict(1 => Set(((2, 3), (5, 7), (8, 9))), 5 => Set(((1, 2), (7, 9), (8, 3)))))
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  5 => Set([(1, 2), (8, 3), (7, 9)])
  1 => Set([(8, 9), (5, 7), (2, 3)])

julia> get_adjacent2vertex(adj2v, 1)
Set{Tuple{Int64, Int64}} with 3 elements:
  (8, 9)
  (5, 7)
  (2, 3)

julia> get_adjacent2vertex(adj2v, 5)
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (8, 3)
  (7, 9)
DelaunayTriangulation.get_adjacent2vertexMethod
get_adjacent2vertex(adj2v::Adjacent2Vertex) -> Dict

Returns the adjacent2vertex map of adj2v.

Examples

julia> using DelaunayTriangulation

julia> e1 = Set(((1, 2), (5, 3), (7, 8)));

julia> e2 = Set(((2, 3), (13, 5), (-1, 7)));

julia> d = Dict(9 => e1, 6 => e2);

julia> adj2v = DelaunayTriangulation.Adjacent2Vertex(d)
Adjacent2Vertex{Int64, Set{Tuple{Int64, Int64}}} with map:
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  6 => Set([(13, 5), (-1, 7), (2, 3)])
  9 => Set([(1, 2), (7, 8), (5, 3)])

julia> get_adjacent2vertex(adj2v)
Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries:
  6 => Set([(13, 5), (-1, 7), (2, 3)])
  9 => Set([(1, 2), (7, 8), (5, 3)])

julia> get_adjacent2vertex(adj2v) == d
true
DelaunayTriangulation.get_adjacent2vertexMethod
get_adjacent2vertex(tri::Triangulation, w) -> Edges

Returns the set of all edges (u, v) in tri such that (u, v, w) is a positively oriented triangle in tri.

DelaunayTriangulation.get_adjacent2vertexMethod
get_adjacent2vertex(tri::Triangulation) -> Adjacent2Vertex

Returns the Adjacent2Vertex map of the triangulation tri. This is a map from a vertex w to a set of all edges (u, v) such that (u, v, w) is a positively oriented triangle in tri.

DelaunayTriangulation.get_all_segmentsMethod
get_all_segments(tri::Triangulation) -> Edges

Return all segments of the triangulation. This includes interior segments and boundary segments. Segments are edges that are forced to be in the triangulation.

DelaunayTriangulation.get_all_statMethod
get_all_stat(stats::TriangulationStatistics, stat::Symbol) -> Vector

Returns a vector of the statistic stat for each triangle in stats.

DelaunayTriangulation.get_boundary_chainMethod
get_boundary_chain(tri::Triangulation, i, j) -> Edges

Given two boundary vertices i and j on a boundary with ghost vertex ghost_vertex, walks counter-clockwise from i to j along the boundary and returns the collection of all vertices encountered in counter-clockwise order.

DelaunayTriangulation.get_boundary_curveMethod
get_boundary_curve(boundary_enricher::BoundaryEnricher, curve_index) -> AbstractParametricCurve

Returns the curve_indexth curve from the boundary curves in boundary_enricher.

DelaunayTriangulation.get_boundary_curvesMethod
get_boundary_curves(tri::Triangulation) -> NTuple{N, Function}

Returns the functions defining the boundaries of tri. If !is_curve_bounded(tri), then this returns an empty Tuple. Otherwise, this returns a Tuple of functions, one for each section of the boundary, where the ith element of the Tuple corresponds to the ith section of the boundary, which corresponds to the ghost vertex -i. For curves that are defined by boundary nodes rather than by a function, the function is PiecewiseLinear. For the other functions, these are all defined by t -> NTuple{2, Number}, where t ∈ [0, 1] and the NTuple{2, Number} is the coordinate on the curve at that t.

DelaunayTriangulation.get_boundary_edge_mapMethod
get_boundary_edge_map(boundary_enricher::BoundaryEnricher, i, j)

Returns the value from the key (i, j) in the boundary edge map of boundary_enricher. The returned value is a Tuple (position, index) so that boundary_nodes = get_boundary_nodes(get_boundary_nodes(boundary_enricher), position) are the boundary nodes associated with the section that (i, j) resides on, and i = get_boundary_nodes(boundary_nodes, index) and j = get_boundary_nodes(boundary_nodes, index + 1).

DelaunayTriangulation.get_boundary_edge_mapMethod
get_boundary_edge_map(tri::Triangulation, ij) 
get_boundary_edge_map(tri::Triangulation, i, j)

Returns the value from the key (i, j) in the boundary edge map of tri. The returned value is a Tuple (position, index) so that boundary_nodes = get_boundary_nodes(tri, position) are the boundary nodes associated with the section that (i, j) resides on, and i = get_boundary_nodes(boundary_nodes, index) and j = get_boundary_nodes(boundary_nodes, index + 1).

DelaunayTriangulation.get_boundary_edge_mapMethod
get_boundary_edge_map(tri::Triangulation) -> Dict

Returns the boundary edge map of the triangulation tri. This is a Dict that maps a boundary edge (u, v) to its position in get_boundary_nodes(tri). In particular, the returned value is a Tuple (position, index) so that boundary_nodes = get_boundary_nodes(tri, position) are the boundary nodes associated with the section that (u, v) resides on, and u = get_boundary_nodes(boundary_nodes, index) and v = get_boundary_nodes(boundary_nodes, index + 1).

See also construct_boundary_edge_map.

DelaunayTriangulation.get_boundary_nodesFunction
get_boundary_nodes(boundary_nodes, mnℓ...)

Given a collection of boundary_nodes, returns the specified component of the collection. There are several forms for the methods:

  1. get_boundary_nodes(boundary_nodes, m): If boundary_nodes has multiple curves, this returns the mth curve. If boundary_nodes has multiple sections, this returns the mth section. Otherwise, this returns the mth boundary node.
  2. get_boundary_nodes(boundary_nodes, m, n): If boundary_nodes has multiple curves, this returns the nth section of the mth curve. Otherwise, if boundary_nodes has multiple sections, this returns the nth boundary node of the mth section.
  3. get_boundary_nodes(boundary_nodes, (m, n)): This is equivalent to get_boundary_nodes(boundary_nodes, m, n).
  4. get_boundary_nodes(boundary_nodes::A, ::A): This just returns boundary_nodes.

Examples

julia> using DelaunayTriangulation

julia> get_boundary_nodes([[[1, 2, 3, 4], [4, 5, 1]], [[6, 7, 8, 9], [9, 10, 6]]], 2)
2-element Vector{Vector{Int64}}:
 [6, 7, 8, 9]
 [9, 10, 6]

julia> get_boundary_nodes([[1, 2, 3, 4], [4, 5, 1]], 1)
4-element Vector{Int64}:
 1
 2
 3
 4

julia> get_boundary_nodes([1, 2, 3, 4, 5, 6, 1], 4)
4

julia> get_boundary_nodes([[[1, 2, 3, 4], [4, 5, 1]], [[6, 7, 8, 9], [9, 10, 6]]], 1, 2)
3-element Vector{Int64}:
 4
 5
 1

julia> get_boundary_nodes([[1, 2, 3, 4], [4, 5, 6, 1]], 2, 3)
6

julia> get_boundary_nodes([1, 2, 3, 4, 5, 1], [1, 2, 3, 4, 5, 1])
6-element Vector{Int64}:
 1
 2
 3
 4
 5
 1
DelaunayTriangulation.get_boundary_nodesMethod
get_boundary_nodes(tri, mnℓ...)

Given a triangulation tri, returns the specified component of the boundary nodes. There are several forms for the methods:

  1. get_boundary_nodes(tri, m): If tri has multiple curves, this returns the mth curve. If tri has multiple sections, this returns the mth section. Otherwise, this returns the mth boundary node.
  2. get_boundary_nodes(tri, m, n): If tri has multiple curves, this returns the nth section of the mth curve. Otherwise, if tri has multiple sections, this returns the nth boundary node of the mth section.
  3. get_boundary_nodes(tri, (m, n)): This is equivalent to get_boundary_nodes(tri, m, n).
  4. get_boundary_nodes(tri::A, ::A): This just returns boundary_nodes.
DelaunayTriangulation.get_boundary_nodesMethod
get_boundary_nodes(tri::Triangulation) -> BoundaryNodes

Return the boundary nodes of the triangulation. This is only for triangulations with a constrained boundary. If the triangulation has no constrained boundary, then the boundary is instead given by its convex hull and this function returns an empty vector. See get_convex_hull.

DelaunayTriangulation.get_centroidMethod
get_centroid(vor::VoronoiTessellation, i) -> NTuple{2, Number}

Gets the centroid of the ith Voronoi polygon, given as a Tuple of the form (x, y).

DelaunayTriangulation.get_circle_intersectionMethod
get_circle_intersection(c::AbstractParametricCurve, t₁, t₂, r) -> (Float64, NTuple{2,Float64})

Given a circle centered at c(t₁) with radius r, finds the first intersection of the circle with the curve after t₁ and less than t₂. It is assumed that such an intersection exists. The returned value is (t, q), where t is the parameter value of the intersection and q is the point of intersection.

DelaunayTriangulation.get_circle_intersectionMethod
get_circle_intersection(enricher::BoundaryEnricher, curve_index, t₁, t₂, r) -> (Float64, NTuple{2,Float64})

Finds the intersection of the curve_indexth curve with the circle centered at the curve evaluated at t₁ with radius r. The argument t₂ defines the end of the subcurve to consider. The returned tuple is (t, p) where t is the parameter value of the intersection and p is the point of intersection.

DelaunayTriangulation.get_circumcenter_to_triangleMethod
get_circumcenter_to_triangle(vorn::VoronoiTessellation) -> Dict{Index,Triangle}

Gets the circumcenters of the Voronoi tessellation vorn as a Dict, mapping circumcenter indices to their corresponding triangles. The triangles are sorted so that the minimum vertex is last.

DelaunayTriangulation.get_clipping_poly_structsMethod
get_clipping_poly_structs(vorn::VoronoiTessellation, i, bounding_box) -> (Polygon, Polygon)

Returns the polygons used for clipping the ith polygon of vorn to bounding_box.

See also clip_polygon.

Arguments

  • vorn: The VoronoiTessellation.
  • i: The index of the polygon.
  • bounding_box: The bounding box to clip the polygon to.

Outputs

  • poly: The polygon to clip.
  • clip_poly: The polygon to clip to.
DelaunayTriangulation.get_closest_pointMethod
get_closest_point(b::AbstractParametricCurve p) -> (Float64, NTuple{2,Float64})

Returns the t-value and the associated point q on the curve b that is nearest to p using a binary search. The search is done until the binary search interval is smaller than 1e-12. This function will only work if the curve b has a lookup table.

Loops

This function is only tested on loop-free curves. It is not guaranteed to work on curves with loops. Moreover, for this function to be accurate, you want the lookup table in b to be sufficiently dense.

DelaunayTriangulation.get_cocircular_circumcentersMethod
get_cocircular_circumcenters(vorn::VoronoiTessellation) -> Set

Gets the cocircular circumcenters of the Voronoi tessellation vorn as a Set of circumcenter indices. These are circumcenters that come from triangles that are cocircular with another adjoining triangle.

DelaunayTriangulation.get_convex_hullMethod
get_convex_hull(tri::Triangulation) -> ConvexHull

Returns the convex hull of the points in tri. This is given as a ConvexHull object, where the vertices are sorted counter-clockwise and defined so that the first and last vertices are equal.

DelaunayTriangulation.get_countMethod
get_count(node::Union{Nothing, BalancedBSTNode}) -> Int32

Returns the count of node. If the node is nothing, returns 0.

DelaunayTriangulation.get_curve_indexFunction
get_curve_index(dict, ghost_vertex) -> Int
get_curve_index(ghost_vertex) -> Int

Given a Dict from construct_ghost_vertex_map and a ghost_vertex, returns the index of the curve corresponding to that ghost vertex. The second method maps ghost_vertex to 1 if it is an Integer or a Vector, and ghost_vertex[1] if it is a Tuple.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.get_curve_index(-1)
1

julia> DelaunayTriangulation.get_curve_index((5, 3))
5

julia> gv_map = DelaunayTriangulation.construct_ghost_vertex_map([[[1, 5, 17, 18, 1]], [[23, 29, 31, 33], [33, 107, 101], [101, 99, 85, 23]]])
Dict{Int64, Tuple{Int64, Int64}} with 4 entries:
  -1 => (1, 1)
  -3 => (2, 2)
  -2 => (2, 1)
  -4 => (2, 3)

julia> DelaunayTriangulation.get_curve_index(gv_map, -1)
1

julia> DelaunayTriangulation.get_curve_index(gv_map, -2)
2

julia> DelaunayTriangulation.get_curve_index(gv_map, -3)
2

julia> DelaunayTriangulation.get_curve_index(gv_map, -4)
2
DelaunayTriangulation.get_distance_to_planeMethod
get_distance_to_plane(a, b, c, p) -> Number

Returns the distance from the point p to the plane defined by the points (a, b, c). The distance is positive if p is above the plane.

DelaunayTriangulation.get_distance_to_witness_planeMethod

" getdistancetowitnessplane(tri::Triangulation, i, V) -> Float64

Computes the distance between the lifted companion of the vertex i and the witness plane to the triangle V. If V is a ghost triangle and i is not on its solid edge, then the distance is -Inf if it is below the ghost triangle's witness plane and Inf if it is above. If V is a ghost triangle and i is on its solid edge, then the distance returned is the distance associated with the solid triangle adjoining V.

In general, the distance is positive if the lifted vertex is above the witness plane, negative if it is below, and zero if it is on the plane.

See also point_position_relative_to_witness_plane and get_distance_to_plane.

DelaunayTriangulation.get_edgeMethod
get_edge(id_bounding_box::DiametralBoundingBox) -> NTuple{2,Int}

Returns the generator edge of id_bounding_box.

DelaunayTriangulation.get_edgesMethod
get_edges(tri::Triangulation) -> Set{NTuple{2,Vertex}}

Returns the set of all edges in tri. Orientation is ignored, so that only one of (i, j) and (j, i) will appear in the result. Note that, if has_ghost_triangles(tri), then some of these edges will be ghost edges.

See also each_edge, each_solid_edge, and each_ghost_edge.

DelaunayTriangulation.get_equidistant_splitMethod
get_equidistant_split(c::AbstractParametricCurve, t₁, t₂) -> Float64

Returns a value of t such that the arc length along c from t₁ to t is equal to the arc length along c from t to t₂. Uses the bisection method to compute the t-value.

DelaunayTriangulation.get_equidistant_splitMethod
get_equidistant_split(enricher::BoundaryEnricher, curve_index, t₁, t₂) -> Float64

Returns the equidistant split of the curve_indexth curve between t₁ and t₂.

DelaunayTriangulation.get_equivariation_splitMethod
get_equivariation_split(c::AbstractParametricCurve, t₁, t₂) -> Float64, Float64

Returns a value of t such that the total variation of c from t₁ to t is equal to the total variation of c from t to t₂. Uses the bisection method to compute the t-value. Also returns the new total variation of the two pieces.

DelaunayTriangulation.get_equivariation_splitMethod
get_equivariation_split(enricher::BoundaryEnricher, curve_index, t₁, t₂) -> Float64, Float64

Returns the equivariation split of the curve_indexth curve between t₁ and t₂. Also returns the total variation of the two pieces.

DelaunayTriangulation.get_generatorMethod
get_generator(vor::VoronoiTessellation, i) -> NTuple{2, Number}
get_generator(vor::VoronoiTessellation, i...) -> NTuple{length(i), NTuple{2, Number}}

Gets the coordinates for the generators i..., returned as Tuples of the form (x, y) for each generator.

DelaunayTriangulation.get_generatorsMethod
get_generators(vorn::VoronoiTessellation) -> Dict{Vertex,Point}

Gets the generators of the Voronoi tessellation vorn as a Dict, mapping vertices to their coordinates. These coordinates are given as Tuples of the form (x, y).

DelaunayTriangulation.get_ghost_vertexFunction
get_ghost_vertex(i, j, k) -> Vertex
get_ghost_vertex(i, j) -> Vertex

Given three vertices i, j, and k, returns the ghost vertex among them. If none of them are ghost vertices, returns k. The two-argument version is equivalent to get_ghost_vertex(i, j, j).

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.get_ghost_vertex(1, 7, -2)
-2

julia> DelaunayTriangulation.get_ghost_vertex(-1, 2, 3)
-1

julia> DelaunayTriangulation.get_ghost_vertex(1, 5, 10)
10

julia> DelaunayTriangulation.get_ghost_vertex(1, -1)
-1

julia> DelaunayTriangulation.get_ghost_vertex(-5, 2)
-5
DelaunayTriangulation.get_ghost_vertex_mapMethod
get_ghost_vertex_map(tri::Triangulation) -> Dict

Returns the ghost vertex map of the triangulation tri. This is a Dict that maps ghost vertices to their associated section in boundary_nodes. There are three cases; below, I is integer_type(tri):

  • has_multiple_curves(tri)

Returns dict::Dict{I, NTuple{2, I}}, mapping ghost vertices i to Tuples (m, n) so that get_boundary_nodes(tri, m, n) are the boundary nodes associated with i, i.e. the nth section of the mth curve is associated with the ghost vertex i.

  • has_multiple_sections(tri)

Returns dict::Dict{I, I}, mapping ghost vertices i to n so that get_boundary_nodes(tri, n) are the boundary nodes associated with i, i.e. the nth section of the boundary is associated with the ghost vertex i.

  • otherwise

Returns dict::Dict{I, A}, mapping the ghost vertex i to get_boundary_nodes(tri), where A = typeof(get_boundary_nodes(tri)).

See also construct_ghost_vertex_map.

DelaunayTriangulation.get_ghost_vertex_rangeMethod
get_ghost_vertex_range(tri::Triangulation, ℓ) -> UnitRange

Given a ghost vertex of tri, returns the range of all ghost vertices corresponding to the same curve or section as does.

DelaunayTriangulation.get_heightMethod
get_height(node::Union{Nothing, BalancedBSTNode}) -> Int8

Returns the height of node. If the node is nothing, returns 0.

DelaunayTriangulation.get_initial_search_pointMethod
get_initial_search_point(tri::Triangulation, num_points, new_point, insertion_order, num_sample_rule::F, rng, try_last_inserted_point) where {F} -> Vertex

For a given iteration of the Bowyer-Watson algorithm, finds the point to start the point location with jump_and_march at.

Arguments

  • tri: The triangulation.
  • num_points: The number of points currently in the triangulation.
  • new_point: The point to insert.
  • insertion_order: The insertion order of the points. See get_insertion_order.
  • num_sample_rule::F: The rule to use to determine the number of points to sample. See default_num_samples for the default.
  • rng::AbstractRNG: The random number generator to use.
  • try_last_inserted_point: If true, then the last inserted point is also considered as the start point.

Output

  • initial_search_point: The vertex to start the point location with jump_and_march at.
DelaunayTriangulation.get_initial_triangleFunction
get_initial_triangle(tri::Triangulation, insertion_order, itr=0) -> Triangle

Gets the initial triangle for the Bowyer-Watson algorithm.

Arguments

  • tri: The triangulation.
  • insertion_order: The insertion order of the points. See get_insertion_order.
  • itr=0: To avoid issues with degenerate triangles and infinite loops, this counts the number of times insertion_order had to be shifted using circshift! to find an initial non-degenerate triangle.

Output

  • initial_triangle: The initial triangle.
DelaunayTriangulation.get_insertion_orderMethod
get_insertion_order(points, randomise, skip_points, ::Type{I}, rng) where {I} -> Vector{I}
get_insertion_order(tri::Triangulation, randomise, skip_points, rng) -> Vector{I}

Gets the insertion order for points into a triangulation.

Arguments

  • points: The points to insert.
  • randomise: If true, then the insertion order is randomised. Otherwise, the insertion order is the same as the order of the points.
  • skip_points: The points to skip.
  • I::Type{I}: The type of the vertices.
  • rng::AbstractRNG: The random number generator to use.

Output

  • order: The order to insert the points in.
Mutation of `order`

This order might be mutated (by circshift!) in get_initial_triangle.

DelaunayTriangulation.get_interior_segmentsMethod
get_interior_segments(tri::Triangulation) -> Edges

Return the interior segments of the triangulation. These are segments that are forced to be in the triangulation - they are not the same as edges.

DelaunayTriangulation.get_intersectionsMethod
get_intersections(tree::BoundaryRTree, i, j, k; cache_id=1) -> RTreeIntersectionIterator

Returns an RTreeIntersectionIterator over the elements in tree that intersect with the bounding box of the triangle (i, j, k). cache_id must be 1 or 2, and determines what cache to use for the intersection query.

DelaunayTriangulation.get_intersectionsMethod
get_intersections(tree::BoundaryRTree, i, j; cache_id=1) -> RTreeIntersectionIterator

Returns an RTreeIntersectionIterator over the elements in tree that intersect with the diametral circle of the edge between i and j. cache_id must be 1 or 2, and determines what cache to use for the intersection query.

DelaunayTriangulation.get_intersectionsMethod
get_intersections(tree::BoundaryRTree, bbox::BoundingBox; cache_id=1) -> RTreeIntersectionIterator

Returns an RTreeIntersectionIterator over the elements in tree that intersect with bbox. cache_id must be 1 or 2, and determines what cache to use for the intersection query.

DelaunayTriangulation.get_intersectionsMethod
get_intersections(tree::RTree, bounding_box::BoundingBox; cache_id=1) -> RTreeIntersectionIterator

Returns an RTreeIntersectionIterator over the elements in tree that intersect with bounding_box. cache_id must be 1 or 2, and determines what cache to use for the intersection query.

DelaunayTriangulation.get_intersectionsMethod
get_intersections(tree::RTree, point::NTuple{2,<:Number}; cache_id=1) -> RTreeIntersectionIterator

Returns an RTreeIntersectionIterator over the elements in tree that intersect with point, representing point as a BoundingBox with zero width and height centered at point. cache_id must be 1 or 2, and determines what cache to use for the intersection query.

DelaunayTriangulation.get_leftMethod
get_left(node::BalancedBSTNode) -> Union{Nothing, BalancedBSTNode}

Returns the left child of node. If the node is nothing, returns nothing.

DelaunayTriangulation.get_left_boundary_nodeMethod
get_left_boundary_node(tri::Triangulation, k, ghost_vertex) -> Vertex

Returns the boundary node to the left of the vertex k in tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • k: The boundary vertex.
  • ghost_vertex: The ghost vertex associated with the boundary section that k is on.

Outputs

  • : The vertex left of k on the boundary.
DelaunayTriangulation.get_lifted_pointMethod
get_lifted_point(p, w) -> Tuple{Float64, Float64, Float64}

Returns the lifted companion of the point p, in particular (x, y, x^2 + y^2 - w), where (x, y) is p.

DelaunayTriangulation.get_lifted_pointMethod
get_lifted_point(tri::Triangulation, i) -> Tuple{Float64, Float64, Float64}

Returns the lifted companion of the ith vertex of tri, in particular (x, y, x^2 + y^2 - w), where w is the ith weight of tri and (x, y) is the ith point of tri.

DelaunayTriangulation.get_membersMethod
get_members(complex::SmallAngleComplex{I}) where {I} -> Vector{SmallAngleComplexMember{I}}

Returns the members of complex.

DelaunayTriangulation.get_neighbouring_boundary_edgesMethod
get_neighbouring_boundary_edges(tri::Triangulation, e) -> (Edge, Edge)

Returns the two boundary edges adjacent to the boundary edge e in the triangulation tri.

Arguments

  • tri::Triangulation: a triangulation
  • e: The boundary edge.

Outputs

  • left_e: The left edge.
  • right_e: The right edge.
DelaunayTriangulation.get_neighboursMethod
get_neighbours(tri::Triangulation, u) -> Set{Vertex}

Returns the set of neighbours of u in tri. Note that, if has_ghost_triangles(tri), then some of the neighbours and vertices will be ghost vertices.

DelaunayTriangulation.get_neighboursMethod
get_neighbours(tri::Triangulation) -> Dict{Vertex, Set{Vertex}}

Returns the neighbours map of tri. Note that, if has_ghost_triangles(tri), then some of the neighbours and vertices will be ghost vertices.

DelaunayTriangulation.get_new_polygon_indicesMethod
get_new_polygon_indices(vorn, vertices) -> (Vector{Int}, Vector{NTuple{2,Float64}}, Tuple{Int, Int})

Returns the new vertices and points of the polygon, as well as the indices of the ghost vertices in the polygon.

Arguments

Outputs

  • new_vertices: The new vertices of the polygon. This is not a circular vector. The vertices corresponding to a ghost vertex will be given by the ghost vertex itself.
  • new_points: The new points of the polygon. This is not a circular vector. The points corresponding to a ghost vertex will be given by by (NaN, NaN).
  • ghost_vertices: The indices of the ghost vertices in new_vertices.
DelaunayTriangulation.get_next_childMethod
get_next_child(node::AbstractNode, start_idx, need_tests, itr::RTreeIntersectionIterator) -> Int, QueryResult

Returns the index of the next child of node that intersects with the bounding box in itr and the QueryResult of the intersection.

DelaunayTriangulation.get_next_triangle_for_voronoi_polygonMethod
get_next_triangle_for_voronoi_polygon(vorn::VoronoiTessellation, i, k, S, m) -> (Vertex, Vertex)

Get the next triangle for the Voronoi polygon for the point i in the VoronoiTessellation.

Arguments

Outputs

  • ci: The index for the circumcenter of the next triangle.
  • k: The next vertex in S after the input k.
DelaunayTriangulation.get_ordinal_suffixMethod
get_ordinal_suffix(i) -> String

Returns the ordinal suffix for the integer i.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.get_ordinal_suffix(1)
"st"

julia> DelaunayTriangulation.get_ordinal_suffix(2)
"nd"

julia> DelaunayTriangulation.get_ordinal_suffix(3)
"rd"

julia> DelaunayTriangulation.get_ordinal_suffix(4)
"th"

julia> DelaunayTriangulation.get_ordinal_suffix(5)
"th"

julia> DelaunayTriangulation.get_ordinal_suffix(6)
"th"

julia> DelaunayTriangulation.get_ordinal_suffix(11)
"th"

julia> DelaunayTriangulation.get_ordinal_suffix(15)
"th"

julia> DelaunayTriangulation.get_ordinal_suffix(100)
"th"
DelaunayTriangulation.get_parentMethod
get_parent(node::BalancedBSTNode) -> Union{Nothing, BalancedBSTNode}

Returns the parent of node. If the node is nothing, returns nothing.

DelaunayTriangulation.get_parentMethod
get_parent(boundary_enricher::BoundaryEnricher{P,B,C,I}, i::I, j::I) -> I

Returns the parent of the edge (i, j) in boundary_enricher. If the edge is not in the parent map, then 0 is returned.

DelaunayTriangulation.get_parent_mapMethod
get_parent_map(boundary_enricher::BoundaryEnricher{P,B,C,I}) -> Dict{NTuple{2,I},I}

Returns the parent map associated with boundary_enricher.

DelaunayTriangulation.get_plane_through_three_pointsMethod
get_plane_through_three_points(a, b, c) -> NTuple{4, Number}

Given three points (a, b, c) in ℝ³ represented as Tuples, computes the equation of the plane through the points. The result is given in the form (α, β, γ, δ), so that the plane is given by

αx + βy + γz + δ = 0.

Extended help

The equation of the plane is computed by expanding the equation

\[\det \begin{bmatrix} x & y & z & 1 \\ a_x & a_y & a_z & 1 \\ b_x & b_y & b_z & 1 \\ c_x & c_y & c_z & 1 \end{bmatrix} = 0.\]

From this, we find:

\[\begin{align*} \alpha &= a_y b_z - a_z b_y - a_y c_z + a_z c_y + b_y c_z - b_z c_y, \\ \beta &= a_z b_x - a_x b_z + a_x c_z - a_z c_x - b_x c_z + b_z c_x, \\ \gamma &= a_x b_y - a_y b_x - a_x c_y + a_y c_x + b_x c_y - b_y c_x, \\ \delta &= a_x b_z c_y - a_x b_y c_z + a_y b_x c_z - a_y b_z c_x - a_z b_x c_y + a_z b_y c_x. \end{align*}\]

DelaunayTriangulation.get_pointFunction
get_point(points, vertices...) -> NTuple{length(vertices), NTuple{2, Number}}

Get the points associated with vertices in points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 2.0), (3.0, 5.5), (1.7, 10.3), (-5.0, 0.0)];

julia> get_point(points, 1)
(1.0, 2.0)

julia> get_point(points, 1, 2, 3, 4)
((1.0, 2.0), (3.0, 5.5), (1.7, 10.3), (-5.0, 0.0))

julia> points = [1.0 3.0 1.7 -5.0; 2.0 5.5 10.3 0.0];

julia> get_point(points, 1)
(1.0, 2.0)

julia> get_point(points, 1, 2, 3, 4)
((1.0, 2.0), (3.0, 5.5), (1.7, 10.3), (-5.0, 0.0))

julia> typeof(ans)
NTuple{4, Tuple{Float64, Float64}}
DelaunayTriangulation.get_pointMethod
get_point(tri::Triangulation, i) -> NTuple{2, Number}
get_point(tri::Triangulation, i...) -> NTuple{length(i), NTuple{2, Number}}

Returns the coordinates corresponding to the vertices i... of tri, given as a Tuple of the form (x, y) for each point. If i is a ghost vertex, then the coordinates of the representative point of the curve associated with i are returned instead.

DelaunayTriangulation.get_pointsMethod
get_points(tri::Triangulation) -> Points

Return the points of the triangulation. Note that this may include points not yet in tri.

DelaunayTriangulation.get_polygonMethod
get_polygon(vor::VoronoiTessellation, i) -> Vector{Vertex}

Gets the vector of vertices corresponding to the ith polygon, given in counter-clockwise order and with the first and last vertices equal. To obtain the coordinates, see get_polygon_point.

DelaunayTriangulation.get_polygon_coordinatesFunction
get_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box=nothing) -> Vector{NTuple{2,Number}}

Returns the coordinates of the polygon with index i in vorn. If bounding_box is provided, then the polygon is clipped to the bounding box. If the polygon is unbounded, then bounding_box must be provided.

See also get_unbounded_polygon_coordinates and get_bounded_polygon_coordinates.

Arguments

  • vorn: The VoronoiTessellation.
  • i: The index of the polygon.
  • bounding_box=nothing: The bounding box to clip the polygon to. If nothing, then the polygon is not clipped. If the polygon is unbounded, then bounding_box must be provided.

Outputs

  • coords: The coordinates of the polygon. This is a circular vector.
DelaunayTriangulation.get_polygon_pointMethod
get_polygon_point(vor::VoronoiTessellation, i) -> NTuple{2, Number}
get_polygon_point(vor::VoronoiTessellation, i...) -> NTuple{length(i), NTuple{2, Number}}

Gets the coordinates corresponding to the vertices i... of the polygons, returned as Tuples of the form (x, y) for each vertex.

DelaunayTriangulation.get_polygon_pointsMethod
get_polygon_points(vorn::VoronoiTessellation) -> Vector{Point}

Gets the polygon points of the Voronoi tessellation vorn. These are the vertices of the Voronoi polygons, and are given as Tuples of the form (x, y).

DelaunayTriangulation.get_polygonsMethod
get_polygons(vorn::VoronoiTessellation) -> Dict{Index,Vector{Vertex}}

Gets the polygons of the Voronoi tessellation vorn as a Dict, mapping polygon indices to their vertices, where the vertices refer to points in get_polygon_points(vorn). The vertices are given in counter-clockwise order and the first and last vertices are equal.

DelaunayTriangulation.get_power_distanceMethod
get_power_distance(tri::Triangulation, i, j) -> Float64

Returns the power distance between vertices i and j, defined by ||pᵢ - pⱼ||^2 - wᵢ - wⱼ, where wᵢ and wⱼ are the respective weights.

DelaunayTriangulation.get_queueMethod
get_queue(boundary_enricher::BoundaryEnricher{P,B,C,I}) -> Queue{I}

Returns the queue associated with boundary_enricher.

DelaunayTriangulation.get_rightMethod
get_right(node::BalancedBSTNode) -> Union{Nothing, BalancedBSTNode}

Returns the right child of node. If the node is nothing, returns nothing.

DelaunayTriangulation.get_right_boundary_nodeMethod
get_right_boundary_node(tri::Triangulation, k, ghost_vertex) -> Vertex

Returns the boundary node to the right of the vertex k in tri.

Arguments

  • tri::Triangulation: The Triangulation.
  • k: The boundary vertex.
  • ghost_vertex: The ghost vertex associated with the boundary section that k is on.

Outputs

  • r: The vertex right of k on the boundary.
DelaunayTriangulation.get_rootMethod
get_root(tree::BalancedBST{K}) -> Union{Nothing,BalancedBSTNode{K}}

Returns the root of tree. If tree is empty, returns nothing.

DelaunayTriangulation.get_section_indexFunction
get_section_index(dict, ghost_vertex) -> Int
get_section_index(ghost_vertex) -> Int

Given a Dict from construct_ghost_vertex_map and a ghost_vertex, returns the index of the section corresponding to that ghost vertex. The second method maps ghost_vertex to itself if it is an Integer, 1 if it is a Vector, and ghost_vertex[2] if it is a Tuple.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.get_section_index((2, 3)) # 3rd section of the 2nd curve
3

julia> DelaunayTriangulation.get_section_index(4)
4

julia> DelaunayTriangulation.get_section_index([1, 2, 3, 4, 5, 1])
1

julia> gv_map = DelaunayTriangulation.construct_ghost_vertex_map([[[1, 5, 17, 18, 1]], [[23, 29, 31, 33], [33, 107, 101], [101, 99, 85, 23]]])     
Dict{Int64, Tuple{Int64, Int64}} with 4 entries:
  -1 => (1, 1)
  -3 => (2, 2)
  -2 => (2, 1)
  -4 => (2, 3)

julia> DelaunayTriangulation.get_section_index(gv_map, -1)
1

julia> DelaunayTriangulation.get_section_index(gv_map, -2)
1

julia> DelaunayTriangulation.get_section_index(gv_map, -3)
2

julia> DelaunayTriangulation.get_section_index(gv_map, -4)
3
DelaunayTriangulation.get_shared_vertexMethod
get_shared_vertex(e, f) -> Vertex

Returns the vertex shared by the edges e and f, or if they do not share a vertex.

Arguments

  • e: The first edge.
  • f: The second edge.

Outputs

  • u: The shared vertex.

Example

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.get_shared_vertex((1, 3), (5, 7))
0

julia> DelaunayTriangulation.get_shared_vertex((1, 3), (3, 7))
3

julia> DelaunayTriangulation.get_shared_vertex((10, 3), (10, 5))
10

julia> DelaunayTriangulation.get_shared_vertex((9, 4), (9, 5))
9
DelaunayTriangulation.get_skeletonMethod
get_skeleton(boundary_nodes, IntegerType) -> empty(boundary_nodes)

Given a set of boundary nodes, returns the empty skeleton of the boundary nodes. This is essentially empty applied to boundary_nodes, but with vertices of type IntegerType. This is mainly needed for convert_boundary_curves!. You will need to implement a new method for this if you want your custom boundary node interface to be supported for curve-bounded domains.

DelaunayTriangulation.get_small_angle_complexesFunction
get_small_angle_complexes(points, boundary_nodes, boundary_curves, segments=nothing; IntegerType=Int) -> Dict{IntegerType,Vector{SmallAngleComplex{IntegerType}}}

Returns a map from an apex vertex to a list of all curves that define a small angle complex associated with that apex vertex.

DelaunayTriangulation.get_small_angle_complexesMethod
get_small_angle_complexes(boundary_enricher::BoundaryEnricher{P,B,C,I}) -> Dict{I,Vector{SmallAngleComplex{I}}}

Returns the small angle complexes associated with boundary_enricher.

DelaunayTriangulation.get_steepest_descent_directionMethod
get_steepest_descent_direction(a, b, c) -> NTuple{2, Number}

Given three points in ℝ³ defining a plane, returns the direction (x, y) of the steepest descent along the plane. In particular, if

αx + βy + γz + δ = 0

is the plane, then the steepest descent direction is (α, β)/γ. The returned value is given by (x, y) = sign(γ)(α, β).

See also get_plane_through_three_points.

DelaunayTriangulation.get_steiner_pointMethod
get_steiner_point(tri::Triangulation, args::RefinementArguments, T) -> Certificate, Point

Computes the Steiner point for a triangle T of tri to improve its quality in split_triangle!.

Arguments

Output

  • precision_flag: A Certificate which is Cert.PrecisionFailure if the Steiner point could not be computed due to precision issues, and Cert.None otherwise.
  • c: The Steiner point. If is_precision_failure(precision_flag), then this is just an arbitrary point of T to ensure type stability.
DelaunayTriangulation.get_surrounding_polygonMethod
get_surrounding_polygon(tri::Triangulation, u; skip_ghost_vertices=false) -> Vector

Returns the counter-clockwise sequence of neighbours of u in tri.

Arguments

Keyword Arguments

  • skip_ghost_vertices=false: Whether to skip ghost vertices in the returned polygon.

Outputs

  • S: The surrounding polygon. This will not be circular, meaning S[begin] ≠ S[end]. In case u is an exterior ghost vertex, the returned polygon is a clockwise list of vertices for the associated boundary curve. If you do not have ghost triangles and you try to get the surrounding polygon of a boundary vertex, then this function may return an invalid polygon.
DelaunayTriangulation.get_treeMethod
get_tree(hierarchy::PolygonHierarchy, index) -> PolygonTree{I}

Returns the PolygonTree of the indexth polygon in hierarchy. The index must be associated with an exterior polygon.

DelaunayTriangulation.get_triangle_to_circumcenterMethod
get_triangle_to_circumcenter(vor::VoronoiTessellation, T) -> Index

Gets the circumcenter index associated with the triangle T. The triangle should be sorted so that the minimum vertex is last.

DelaunayTriangulation.get_triangle_to_circumcenterMethod
get_triangle_to_circumcenter(vorn::VoronoiTessellation) -> Dict{Triangle,Index}

Gets the triangles of the Voronoi tessellation vorn as a Dict, mapping triangle indices to their corresponding circumcenters. The circumcenters are given as their vertices, referring to points in get_polygon_points(vorn).

DelaunayTriangulation.get_trianglesMethod
get_triangles(tri::Triangulation) -> Triangles

Return the triangles of the triangulation. These triangles are all given in counter-clockwise order, and may include ghost triangles.

DelaunayTriangulation.get_tripletMethod
get_triplet(list::ShuffledPolygonLinkedList, i) -> (Vertex, Vertex, Vertex)

Returns (u, v, w) = (S[πᵢ], S[next[πᵢ]], S[prev[πᵢ]]), where πᵢ = list.shuffled_indices[i] and S = list.S.

DelaunayTriangulation.get_unbounded_polygon_coordinatesMethod
get_unbounded_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box) -> Vector{NTuple{2,Number}}

Returns the coordinates of the ith polygon of vorn, clipped to bounding_box. The polygon is assumed to be unbounded.

DelaunayTriangulation.get_verticesMethod
get_vertices(convex_hull::ConvexHull) -> Vector{Vertices}

Returns the vertices of convex_hull. These are given in counter-clockwise order, and are defined so that the first and last vertices and equal.

DelaunayTriangulation.get_weightMethod
get_weight(weights, i) -> Float64

Gets the ith weight from weights. The default definition for this is weights[i], but this can be extended - e.g., ZeroWeight uses get_weight(weights, i) = 0.0.

DelaunayTriangulation.get_weighted_nearest_neighbourFunction
get_weighted_nearest_neighbour(tri::Triangulation, i, j = rand(each_solid_vertex(tri))) -> Vertex

Using a greedy search, finds the closest vertex in tri to the vertex i (which might not already be in tri), measuring distance in lifted space (i.e., using the power distance - see get_power_distance). The search starts from the vertex j which should be in tri.

DelaunayTriangulation.get_weightsMethod
get_weights(tri::Triangulation) -> Weights

Return the weights of the triangulation. These are the weights of the vertices of the triangulation.

DelaunayTriangulation.getiMethod
geti(T) -> Vertex

Get the first vertex of T.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.geti((1, 2, 3))
1

julia> DelaunayTriangulation.geti([2, 5, 1])
2
DelaunayTriangulation.getjMethod
getj(T) -> Vertex

Get the second vertex of T.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.getj((5, 6, 13))
6

julia> DelaunayTriangulation.getj([10, 19, 21])
19
DelaunayTriangulation.getkMethod
getk(T) -> Vertex

Get the third vertex of T.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.getk((1,2,3))
3

julia> DelaunayTriangulation.getk([1,2,3])
3
DelaunayTriangulation.getpointFunction
getpoint(points, vertex) -> NTuple{2, Number}

Get the point associated with vertex in points, returned as a Tuple of the coordinates. If vertex is not an integer, then vertex is returned so that points and vertices can be easily mixed.

Examples

julia> using DelaunayTriangulation

julia> points = [(0.3, 0.7), (1.3, 5.0), (5.0, 17.0)];

julia> DelaunayTriangulation.getpoint(points, 2)
(1.3, 5.0)

julia> points = [0.3 1.3 5.0; 0.7 5.0 17.0];

julia> DelaunayTriangulation.getpoint(points, 2)
(1.3, 5.0)

julia> DelaunayTriangulation.getpoint(points, (17.3, 33.0))
(17.3, 33.0)
DelaunayTriangulation.getxMethod
getx(p) -> Number

Get the x-coordinate of p.

Examples

julia> using DelaunayTriangulation

julia> p = (0.3, 0.7);

julia> getx(p)
0.3
DelaunayTriangulation.getxyMethod
getxy(p) -> NTuple{2, Number}

Get the coordinates of p as a Tuple.

Examples

julia> using DelaunayTriangulation

julia> p = [0.9, 23.8];

julia> getxy(p)
(0.9, 23.8)
DelaunayTriangulation.getyMethod
gety(p) -> Number

Get the y-coordinate of p.

Examples

julia> using DelaunayTriangulation

julia> p = (0.9, 1.3);

julia> gety(p)
1.3
DelaunayTriangulation.grow_polygon_outside_of_boxMethod
grow_polygon_outside_of_box(vorn::VoronoiTessellation, i, bounding_box) -> (Vector{Int}, Vector{NTuple{2,Number}})

Truncates the unbounded edges of the ith polygon of vorn so that the line connecting the truncated unbounded edges is entirely outside of bounding_box.

Arguments

  • vorn: The VoronoiTessellation.
  • i: The index of the polygon. The polygon must be unbounded.
  • bounding_box: The bounding box to clip the polygon to. See also polygon_bounds.

Outputs

  • new_vertices: The new vertices of the polygon. This is not a circular vector.
  • new_points: The new points of the polygon. This is not a circular vector.
DelaunayTriangulation.has_acute_neighbouring_anglesMethod
has_acute_neighbouring_angles(enricher::BoundaryEnricher, i, j) -> Int, Vertex

Given a boundary edge (i, j), tests if the neighbouring angles are acute. The first returned value is the number of angles adjoining (i, j) that are acute (0, 1, or 2). The second returned value is the vertex that adjoins the edge (i, j) that is acute. If there are no such angles, or if there are two, then this returned vertex is 0.

(The purpose of this function is similar to segment_vertices_adjoin_other_segments_at_acute_angle.)

DelaunayTriangulation.has_multiple_curvesFunction
has_multiple_curves(boundary_nodes) -> Bool

Check if boundary_nodes has multiple curves.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.has_multiple_curves([1, 2, 3, 1])
false

julia> DelaunayTriangulation.has_multiple_curves([[1, 2, 3], [3, 4, 1]])
false

julia> DelaunayTriangulation.has_multiple_curves([[[1, 2, 3], [3, 4, 1]], [[5, 6, 7, 8, 5]]])
true
DelaunayTriangulation.has_multiple_sectionsFunction
has_multiple_sections(boundary_nodes) -> Bool

Check if boundary_nodes has multiple sections.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.has_multiple_sections([1, 2, 3, 1])
false

julia> DelaunayTriangulation.has_multiple_sections([[1, 2, 3], [3, 4, 1]])
true

julia> DelaunayTriangulation.has_multiple_sections([[[1, 2, 3], [3, 4, 1]], [[5, 6, 7, 8, 5]]])
true
DelaunayTriangulation.has_segmentsMethod
has_segments(boundary_enricher::BoundaryEnricher -> Bool

Returns true if boundary_enricher has interior segments, and false otherwise.

DelaunayTriangulation.horizontal_inflection_pointsMethod
horizontal_inflection_points(c::AbstractParametricCurve; steps=200, iters = 50, tol = 1e-5) -> Vector{Float64}

Returns points t such that x''(t) = 0 and 0 ≤ t ≤ 1, where x'' is the second derivative of the x-coordinate of c. This function uses Newton's method to find the roots of x''. Note that these are only technically inflection points if x'''(t) ≠ 0 at these points, but this is not checked.

High-degree curves

For curves of very high degree, such as Bezier curves with steps control points or greater, this function might fail to return all inflection points.

Arguments

  • c::AbstractParametricCurve: The curve to find the horizontal inflection points of.

Keyword Arguments

  • steps=200: The number of t-values to use for seeding Newton's method. In particular, Newton's method is run for each initial value in LinRange(0, 1, steps).
  • iters=50: The number of iterations to run Newton's method for.
  • tol=1e-5: The tolerance to use for uniquetol. Also used for deciding whether a root is a valid root, i.e. if abs(x''(t)) > tol for a found root t, then t is not a valid root and is rejected.

Output

  • t: All inflection points, given in sorted order.
DelaunayTriangulation.horizontal_turning_pointsMethod
horizontal_turning_points(c::AbstractParametricCurve; steps=200, iters = 50, tol = 1e-5) -> Vector{Float64}

Returns points t such that x'(t) = 0 and 0 ≤ t ≤ 1, where x' is the derivative of the x-coordinate of c. This function uses Newton's method to find the roots of x'.

High-degree curves

For curves of very high degree, such as Bezier curves with steps control points or greater, this function might fail to return all turning points.

Arguments

  • c::AbstractParametricCurve: The curve to find the horizontal turning points of.

Keyword Arguments

  • steps=200: The number of t-values to use for seeding Newton's method. In particular, Newton's method is run for each initial value in LinRange(0, 1, steps).
  • iters=50: The number of iterations to run Newton's method for.
  • tol=1e-5: The tolerance to use for uniquetol. Also used for deciding whether a root is a valid root, i.e. if abs(x'(t)) > tol for a found root t, then t is not a valid root and is rejected.

Output

  • t: All turning points, given in sorted order.
DelaunayTriangulation.incircle_predicateMethod
incircle_predicate(a, b, c, p) -> Integer

Returns ExactPredicates.incircle(a, b, c, p), in particular we return:

  • 1: If p is inside the circle defined by (a, b, c).
  • 0: If p is on the circle defined by (a, b, c).
  • -1: If p is outside the circle defined by (a, b, c).

Extended help

The incircle predicate is defined by the determinant

\[\text{incircle}(a, b, c, d) = \text{sgn} \det \begin{bmatrix} a_x & a_y & a_x^2 + a_y^2 & 1 \\ b_x & b_y & b_x62 + b_y^2 & 1 \\ c_x & c_y & c_x^2 + c_y^2 & 1 \\ d_x & d_y & d_x^2 + d_y^2 & 1 \end{bmatrix} = \text{sgn} \det \begin{bmatrix} a_x - d_x & a_y - d_y & (a_x - d_x)^2 + (a_y - d_y)^2 \\ b_x - d_x & b_y - d_y & (b_x - d_x)^2 + (b_y - d_y)^2 \\ c_x - d_x & c_y - d_y & (c_x - d_x)^2 + (c_y - d_y)^2 \end{bmatrix}.\]

DelaunayTriangulation.inflection_pointsMethod
inflection_points(c::AbstractParametricCurve; steps=200, iters = 50, tol = 1e-5) -> Vector{Float64}

Returns points t such that κ(t) = 0 and 0 ≤ t ≤ 1, where κ is the curvature of c. This function uses Newton's method to find the roots of κ.

High-degree curves

For curves of very high degree, such as Bezier curves with steps control points or greater, this function might fail to return all inflection points.

Arguments

  • c::AbstractParametricCurve: The curve to find the inflection points of.

Keyword Arguments

  • steps=200: The number of t-values to use for seeding Newton's method. In particular, Newton's method is run for each initial value in LinRange(0, 1, steps).
  • iters=50: The number of iterations to run Newton's method for.
  • tol=1e-5: The tolerance to use for uniquetol. Also used for deciding whether a root is a valid root, i.e. if abs(κ(t)) > tol for a found root t, then t is not a valid root and is rejected.
DelaunayTriangulation.initialMethod
initial(e) -> Vertex

Get the initial vertex of e.

Examples

julia> using DelaunayTriangulation

julia> e = (1, 3);

julia> DelaunayTriangulation.initial(e)
1

julia> e = [2, 5];

julia> DelaunayTriangulation.initial(e)
2
DelaunayTriangulation.initialise_bowyer_watson!Method
initialise_bowyer_watson!(tri::Triangulation, insertion_order) -> Triangulation

Initialises the Bowyer-Watson algorithm.

Arguments

  • tri: The triangulation.
  • insertion_order: The insertion order of the points. See get_insertion_order.

Output

tri is updated in place to contain the initial triangle from which the Bowyer-Watson algorithm starts.

DelaunayTriangulation.initialise_clipping_arraysMethod
initialise_clipping_arrays(vorn::VoronoiTessellation) -> (Set{E}, Queue{Tuple{E,I}}, Dict{I,Set{I}}, NTuple{2,F}[], Set{Tuple{E,I}}, Pair{E,E}[], Set{I}, Set{E}, Set{E}, Set{E}, Dict{I,I})

Initialise the arrays used in the clipping algorithm for the VoronoiTessellation vorn.

Arguments

Outputs

  • edges_to_process: The set of edges that are to be processed.
  • polygon_edge_queue: The queue of edges that are to be processed.
  • boundary_sites: A mapping from boundary sites to the indices of the segment intersections that are incident to the boundary site.
  • segment_intersections: The list of segment intersections.
  • processed_pairs: The set of pairs of edges and polygons that have been processed.
  • intersected_edge_cache: The list of intersected edges currently being considered.
  • exterior_circumcenters: The list of circumcenters of sites that are outside the boundary.
  • left_edge_intersectors: The set of sites that intersect the edge to the left of an edge currently being considered.
  • right_edge_intersectors: The set of sites that intersect the edge to the right of an edge currently being considered.
  • current_edge_intersectors: The set of sites that intersect the current edge being considered.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.
DelaunayTriangulation.initialise_jump_and_march_boundary_vertexMethod
initialise_jump_and_march_boundary_vertex(tri::Triangulation, q, k, store_history:, history, ghost_vertex, concavity_protection) -> (Bool, Bool, Triangle, Point, Vertex, Vertex, Point, Point)

Initialise the jump-and-march algorithm for a boundary vertex k.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • k: The boundary vertex to start from.
  • store_history: Whether to store the history of the algorithm.
  • history: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • ghost_vertex: The ghost vertex corresponding to the boundary that k resides on.
  • concavity_protection: Whether to use concavity protection. See concavity_protection_check. This is only needed if your triangulation is not convex.

Outputs

  • restart_flag: Whether the algorithm needs to be restarted.
  • return_flag: Whether the algorithm can return immediately, returning V.
  • V: Either a triangle that can returned if return_flag = true, or some triangle that is used for type stability for this return value.
  • p: The point corresponding to the vertex k, or it may be q if the algorithm is going to be restarted or return_flag = true.
  • i: The first vertex of the triangle adjoining k to start from, or k if the algorithm is going to be restarted or return_flag = true.
  • j: The second vertex of the triangle adjoining k to start from, or k if the algorithm is going to be restarted or return_flag = true.
  • pᵢ: The point corresponding to the vertex i, or it may be q if the algorithm is going to be restarted or return_flag = true.
  • pⱼ: The point corresponding to the vertex j, or it may be q if the algorithm is going to be restarted or return_flag = true.

Extended help

There are multiple stages to this initialisation, starting from check_for_intersections_with_adjacent_boundary_edges.

  • If it is found that q is not outside of the triangulation, so that q is collinear with one of the boundary edges, then we use search_down_adjacent_boundary_edges to find where to start, noting that we can return immediately if q is found to be on an adjacent boundary edge. Otherwise, exterior_jump_and_march can then be used to find the ghost triangle containing q; if concavity_protection = true, then concavity_protection_check is used to determine if a restart is needed.

  • If is is not found that q is outside of the triangulation yet based on information from the adjacent boundary edges, then we need to check the neighbouring interior edges using check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex, returning early if q is found to be inside one of the neighbouring triangles. If the line pq, where p = get_point(tri, k), does not intersect any of the neighbouring edges and it is not inside any of the neighbouring triangles, then it must be outside of the triangulation and so we use exterior_jump_and_march to find the triangle; as before, concavity_protection_check is used on the found ghost triangle if needed. If there is an intersection, then we return the triangle containing the intersection point that we can start the algorithm from, and its associated vertices and points.

DelaunayTriangulation.initialise_jump_and_march_interior_vertexMethod
initialise_jump_and_march_interior_vertex(tri::Triangulation, q, k, store_history::F, history, rng) -> (Bool, Point, Vertex, Vertex, Point, Point)

Initialise the jump-and-march algorithm for an interior vertex k.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • k: The interior vertex to start from.
  • store_history: Whether to store the history of the algorithm.
  • history: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • rng: The random number generator to use.

Outputs

  • restart_flag: Whether the algorithm needs to be restarted.
  • p: The point corresponding to the vertex k.
  • i: The first vertex of the triangle adjoining k to start from.
  • j: The second vertex of the triangle adjoining k to start from.
  • pᵢ: The point corresponding to the vertex i.
  • pⱼ: The point corresponding to the vertex j.

Extended help

This function works by simply using select_initial_triangle_interior_vertex to find the initial triangle to start from. A check is made to see if the edge (i, j) refers to a non-existent edge (0, 0), in which case the algorithm needs to be restarted.

DelaunayTriangulation.initialise_voronoi_tessellationMethod
initialise_voronoi_tessellation(tri::Triangulation) -> VoronoiTessellation

Initialise a VoronoiTessellation from the triangulation tri.

Arguments

Output

  • vorn: The VoronoiTessellation. This tessellation is not yet filled in, as all the polygons and other fields need to be properly defined. This simply defines all the initial objects that will be pushed into.
DelaunayTriangulation.insert_boundary_node!Method
insert_boundary_node!(boundary_nodes, pos, node)

Inserts a boundary node node into boundary_nodes at the position pos. Here, pos[1] is such that get_boundary_nodes(boundary_nodes, pos[1]) is the section that the node will be inserted onto, and pos[2] gives the position of the array to insert node into. In particular,

insert_boundary_node!(boundary_nodes, pos, node)

is the same as

insert!(get_boundary_nodes(boundary_nodes, pos[1]), pos[2], node)

Examples

julia> using DelaunayTriangulation

julia> boundary_nodes = [1, 2, 3, 4, 5, 1];

julia> DelaunayTriangulation.insert_boundary_node!(boundary_nodes, (boundary_nodes, 4), 23)
7-element Vector{Int64}:
  1
  2
  3
 23
  4
  5
  1

julia> boundary_nodes = [[7, 13, 9, 25], [25, 26, 29, 7]];

julia> DelaunayTriangulation.insert_boundary_node!(boundary_nodes, (2, 1), 57)
2-element Vector{Vector{Int64}}:
 [7, 13, 9, 25]
 [57, 25, 26, 29, 7]

julia> boundary_nodes = [[[17, 23, 18, 25], [25, 26, 81, 91], [91, 101, 17]], [[1, 5, 9, 13], [13, 15, 1]]];

julia> DelaunayTriangulation.insert_boundary_node!(boundary_nodes, ((1, 3), 3), 1001)
2-element Vector{Vector{Vector{Int64}}}:
 [[17, 23, 18, 25], [25, 26, 81, 91], [91, 101, 1001, 17]]
 [[1, 5, 9, 13], [13, 15, 1]]
DelaunayTriangulation.insert_boundary_node!Method
insert_boundary_node!(tri::Triangulation, pos, node)

Inserts a boundary node into tri at the specified position.

Arguments

  • tri::Triangulation: The Triangulation.
  • pos: The position to insert the node at, given as a Tuple so that insert_boundary_node!(tri, pos, node) is the same as insert!(get_boundary_nodes(tri, pos[1]), pos[2], node).
  • node: The node to insert.

Outputs

There are no outputs, but the boundary nodes of tri are updated in-place.

DelaunayTriangulation.insert_node!Method
insert_node!(node::Union{Nothing,BalancedBSTNode{K}}, key::K) -> Union{Nothing,BalancedBSTNode{K}}

Inserts key into the subtree rooted at node if it is not already present. Returns the new root of the subtree.

DelaunayTriangulation.intersection_of_edge_and_bisector_rayMethod
intersection_of_edge_and_bisector_ray(a, b, c) -> (Certificate, NTuple{2, Number})

Given an edge (a, b) and a ray emanating from c perpendicular with the edge and collinear with its midpoint, tests if c intersects the edge. The returned value is (cert, p), where:

  • cert: A Certificate indicating the position of c relative to the line through (a, b).
  • p: The intersection point (which is the midpoint) if c intersects the edge, (NaN, NaN) otherwise.
DelaunayTriangulation.is_boundary_edgeMethod
is_boundary_edge(tri::Triangulation, ij) -> Bool
is_boundary_edge(tri::Triangulation, i, j) -> Bool

Tests if the edge (i, j) is a boundary edge of tri, meaning (j, i) adjoins a ghost vertex.

DelaunayTriangulation.is_boundary_nodeMethod
is_boundary_node(tri::Triangulation, i) -> (Bool, Vertex)

Tests if the vertex i is a boundary node of tri.

Arguments

Outputs

  • flag: true if i is a boundary node, and false otherwise.
  • g: Either the ghost vertex corresponding with the section that i lives on if flag is true, or 0 otherwise.
DelaunayTriangulation.is_boundary_triangleMethod
is_boundary_triangle(tri::Triangulation, T) -> Bool
is_boundary_triangle(tri::Triangulation, i, j, k) -> Bool

Returns true if the triangle T = (i, j, k) of tri has an edge on the boundary, and false otherwise.

DelaunayTriangulation.is_curve_boundedFunction
is_curve_bounded(tri::Triangulation) -> Bool 
is_curve_bounded(boundary_nodes) -> Bool

Returns true if tri is curve bounded, and false otherwise; similarly for the boundary_nodes method.

DelaunayTriangulation.is_exterior_curveMethod
is_exterior_curve(tri::Triangulation, curve_index) -> Bool

Returns true if the curve_indexth curve in tri is an exterior curve, and false otherwise.

DelaunayTriangulation.is_first_ghost_vertexMethod
is_first_ghost_vertex(cell, i) -> Bool

Assuming that the circular vector cell is such that ghost vertices only appear next to eachother in cell and there are only two, tests if i is the first ghost vertex in cell.

See also is_last_ghost_vertex.

Arguments

  • cell: The circular vector.
  • i: The index of the vertex in cell.

Outputs

  • flag: true if i is the first ghost vertex in cell, and false otherwise.
DelaunayTriangulation.is_freeMethod
is_free(args::RefinementArguments, u) -> Bool

Returns true if u is a free vertex, and false otherwise. A free vertex is a Steiner vertex (meaning a non-input vertex) that is not part of a segment or subsegment.

DelaunayTriangulation.is_fullMethod
is_full(node::AbstractNode, tree::RTree) -> Bool

Returns true if node is full, i.e. if num_children(node) ≥ get_size_limit(tree).

DelaunayTriangulation.is_fullMethod
is_full(cache::NodeCache) -> Bool

Returns true if cache is full, i.e. if length(cache) ≥ get_size_limit(cache).

DelaunayTriangulation.is_in_treeMethod
is_in_tree(hierarchy::PolygonHierarchy, points, boundary_nodes, tree::PolygonTree, p) -> Bool

Tests if the point p is inside tree.

Arguments

  • hierarchy::PolygonHierarchy: The PolygonHierarchy containing tree.
  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • tree::PolygonTree: The PolygonTree to test p against.
  • p: The point to test.

Output

  • true if p is inside tree, and false otherwise.
DelaunayTriangulation.is_interior_curveMethod
is_interior_curve(tri::Triangulation, curve_index) -> Bool

Returns true if the curve_indexth curve in tri is an interior curve, and false otherwise.

DelaunayTriangulation.is_last_ghost_vertexMethod
is_last_ghost_vertex(cell, i) -> Bool

Assuming that the circular vector cell is such that ghost vertices only appear next to eachother in cell, tests if i is the last ghost vertex in cell.

See also is_first_ghost_vertex.

Arguments

  • cell: The circular vector.
  • i: The index of the vertex in cell.

Outputs

  • flag: true if i is the last ghost vertex in cell, and false otherwise.
DelaunayTriangulation.is_legalFunction
is_legal(tri::Triangulation, i, j) -> Certificate 
is_legal(p, q, r, s) -> Certificate

Tests if the edge (p, q) (or the edge (i, j) of tri) is legal, where the edge (p, q) is incident to two triangles (p, q, r) and (q, p, s). In partiuclar, tests that s is not inside the triangle through (p, q, r). The returned value is a Certificate, which is one of:

  • Legal: The edge (p, q) is legal.
  • Illegal: The edge (p, q) is illegal.

If the edge (i, j) is a segment of tri or is a ghost edge, then the edge is always legal.

DelaunayTriangulation.is_piecewise_linearMethod
is_piecewise_linear(enricher::BoundaryEnricher, curve_index) -> Bool

Returns true if the curve_indexth curve in enricher is piecewise linear, and false otherwise.

DelaunayTriangulation.is_positively_orientedMethod
is_positively_oriented(tri::Triangulation, curve_index) -> Bool

Tests if the curve_indexth curve in tri is positively oriented, returning true if so and false otherwise.

DelaunayTriangulation.is_segmentMethod
is_segment(enricher::BoundaryEnricher, i, j) -> Bool

Returns true if (i, j) or (j, i) is an interior segment of enricher, and false otherwise.

DelaunayTriangulation.is_segment_vertexMethod
is_segment_vertex(args::RefinementArguments, u) -> Bool

Returns true if u is a vertex of a segment, and false otherwise. Note that this excludes vertices of subsegments.

DelaunayTriangulation.is_small_angle_complex_memberMethod
is_small_angle_complex_member(enricher::BoundaryEnricher, i, j) -> Bool, I, IntegerType, IntegerType

Returns true if the edge (i, j) is a member of a small angle complex in enricher, and false otherwise.

Outputs

  • flag: true if the edge is a member of a small angle complex, and false otherwise.
  • apex: If the edge is a member of a small angle complex, then apex is the apex of the complex. Otherwise, apex is 0.
  • complex_id: If the edge is a member of a small angle complex, then complex_id is the index of the complex in the list of complexes associated with apex. Otherwise, complex_id is 0.
  • member_id: If the edge is a member of a small angle complex, then member_id is the index of the member in the list of members associated with complex_id. Otherwise, member_id is 0.
DelaunayTriangulation.is_submergedFunction
is_submerged(tri::Triangulation, i) -> Bool 
is_submerged(tri::Triangulation, i, V) -> Bool

Returns true if the vertex i is submerged in tri and false otherwise. In the second method, V is a triangle containing tri.

DelaunayTriangulation.is_touchingMethod
is_touching(r1::BoundingBox, r2::BoundingBox) -> Bool

Tests whether r1 and r2 are touching, i.e. if they share a common boundary. This only considers interior touching.

DelaunayTriangulation.is_triangle_nestledMethod
is_triangle_nestled(tri::Triangulation, T, idx) -> Bool

Determines if a triangle T of tri is nestled in the corner of a small input angle.

See also is_triangle_seditious.

Arguments

  • tri::Triangulation: The Triangulation.
  • T: The triangle.
  • idx: The index of the smallest edge of the triangle, so that 1 means uv is the smallest edge, 2 means vw is the smallest edge, and 3 means wu is the smallest edge.

Output

  • flag: Whether the triangle is nestled in the corner of a small input angle.

A triangle is nestled in the corner of a small input angle if it is nestled in the corner of a small input angle and the shortest edge is seditious. The size of the angle is not checked by this function, and is instead determined by assess_triangle_quality.

DelaunayTriangulation.is_triangle_seditiousMethod
is_triangle_seditious(tri::Triangulation, args, u, v, w, smallest_idx) -> Bool

Determines if a triangle uvw of tri is seditious according to the RefinementArguments.

See also is_triangle_nestled.

Arguments

  • tri::Triangulation: The Triangulation.
  • args: The RefinementArguments.
  • u, v, w: The vertices of the triangle.
  • smallest_idx: The index of the smallest edge of the triangle, so that 1 means uv is the smallest edge, 2 means vw is the smallest edge, and 3 means wu is the smallest edge.

Output

  • flag: Whether the triangle is seditious.

A triangle is seditious if it is nestled in the corner of a small input angle, or if it is nestled in the corner of a small input angle and the shortest edge is seditious. Here, 'small' is defined by args.constraints.seditious_angle.

DelaunayTriangulation.is_trueFunction
is_true(b) -> Bool

Returns b represents a true value, and false otherwise.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.is_true(true)
true

julia> DelaunayTriangulation.is_true(false)
false

julia> DelaunayTriangulation.is_true(Val(true))
true

julia> DelaunayTriangulation.is_true(Val(false))
false
DelaunayTriangulation.is_vertex_closer_than_neighboursMethod
is_vertex_closer_than_neighbours(tri::Triangulation, u, v, jᵢ, jᵢ₋₁, jᵢ₊₁) -> Bool
is_vertex_closer_than_neighbours(tri::Triangulation, list::ShuffledPolygonLinkedList, u, v, j) -> Bool

Tests if the vertex jᵢ is closer to the line (u, v) than its neighbours jᵢ₋₁ and jᵢ₊₁, assuming all these vertices are to the left of the line.

See also point_closest_to_line.

Arguments

  • tri::Triangulation: The Triangulation.
  • u, v: The vertices of the line.
  • jᵢ, jᵢ₋₁, jᵢ₊₁: The vertices to compare.

The second method extracts these latter two vertices using the doubly-linked list of vertices.

Outputs

  • flag: Whether jᵢ is closer to the line than jᵢ₋₁ and jᵢ₊₁.
DelaunayTriangulation.is_weightedMethod
is_weighted(weights) -> Bool

Returns true if weights represents a set of weights that are not all zero, and false otherwise. Note that even for vectors like zeros(n), this will return true; by default, false is returned only for weights = ZeroWeight().

DelaunayTriangulation.iterated_neighbourhoodMethod
iterated_neighbourhood(tri::Triangulation, i, d) -> Set{Vertex}

Returns the set of vertices of tri in the iterated neighbourhood of the vertex i of depth d.

Extended help

The $d$-times iterated neighbourhood is defined by

\[N_i^d = \bigcup_{j \in N_i^{d-1}} N_j \setminus \{i\},\]

where $N_i^1 = N_i$ is the set of neighbours of $i$.

DelaunayTriangulation.jump_and_marchMethod
jump_and_march(tri, q; kwargs...) -> Triangle[, Bool]

Find the triangle in the triangulation tri containing the query point q using the jump-and-march algorithm.

Arguments

Keyword Arguments

  • point_indices=each_solid_vertex(tri): The indices of the vertices to consider as possible starting points for the algorithm.
  • m=default_num_samples(num_vertices(point_indices)): The number of samples to use when selecting the initial point.
  • try_points=(): A list of points to try as the initial point in addition to the m sampled.
  • rng=Random.default_rng(): The random number generator to use.
  • k=select_initial_point(tri, q; point_indices, m, try_points, rng): The initial point to start the algorithm from. See select_initial_point.
  • store_history=Val(false): Whether to store the history of the algorithm.
  • history=nothing: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • maxiters=2 + num_exterior_curves(tri) - num_solid_vertices(tri) + num_solid_edges(tri): The maximum number of iterations to perform before restarting the algorithm with restart_jump_and_march.
Restarting the algorithm

If the algorithm restarts, then the initial point k is selected again using select_initial_point, and the algorithm is restarted from there. This is done if the algorithm gets stuck in a loop, or if the algorithm is not able to find the correct triangle containing q after maxiters iterations. For a convex geometry, maxiters can be safely ignored, as the sequence of triangles visited is acyclic [see H. Edelsbrunner, An acyclicity theorem for cell complexes in d dimensions, Combinatorica 10 (1990) 251-260.)].

  • concavity_protection=false: Whether to use concavity protection. See concavity_protection_check. This is only needed if your triangulation is not convex.
  • use_barriers::Val{U}=Val(false): Whether to stop searching beyond any segments in the triangulation.
Found triangles with barriers

If you are using barriers, it will be your responsibility to verify that any found triangle from this function actually contains the triangle. This can be verified using the returned flag (see below), although the point might still be on the triangle's boundary.

Walking past vertices of barriers

If you are using barriers, it is possible that the algorithm can walk past vertices of barriers. One way this can happen is if the initial search line intersects a vertex, in which case the segment might not be considered. Another way this can happen is if you start the algorithm directly on a segment vertex, in which case the algorithm can go past it (e.g. this means that it is possible that a ghost triangle might still be returned if you start the algorithm on a boundary node).

Output

  • V: The triangle containing q, with type given by triangle_type(tri).
Hitting barriers

If a barrier is hit before any initial triangle is properly identified, the returned triangle is (0, 0, 0); this is only possible if use_barriers == Val(true). Moreover, if use_barriers == Val(true), the final triangle may not even be valid if invisible_flag == true (defined below).

If you have use_barriers == Val(true), then we also return

  • invisible_flag: false if the triangle was found without hitting a barrier, and true otherwise.
Non-convex geometries

While this function does still work for non-convex geometries, it may be significantly slower than for convex geometries, as most of the details of the algorithm assume that the geometry is convex, and so the algorithm may have to restart many times at new initial vertices k.

Ghost triangles

For this function to work best, the triangulation should have ghost triangles, which you can add using add_ghost_triangles! in case tri does not already have them. Without ghost triangles, the function may not be able to find the correct triangle containing q.

Extended help

The algorithm underlying this function is complicated and broken into many parts. Here, we describe a brief overview of the algorithm, but note that the documentation contains a much more detailed description.

  1. Firstly, the algorithm is initialised depending on whether k is a boundary or an interior vertex, using initialise_jump_and_march_boundary_vertex or initialise_jump_and_march_interior_vertex respectively.
  2. From the initial triangle (i, j, k) chosen, we then check if q is one of pᵢ, pⱼ, and p = pₖ and then return according to jump_and_march_return_on_vertex if needed.
  3. If we do not return above, we need to step from the initial triangle towards q. Since we put pᵢ and pⱼ to the left and right of the line pq, respectively, this means that we step until the triangle pᵢpⱼq is no longer positively oriented. So, while the triangle is positively oriented, we step according to jump_and_march_across_triangle.
  4. If we have not yet returned and the triangle is no longer positively oriented, we check if the triangle is degenerate using jump_and_march_degenerate_arrangement and reinitialise the algorithm if needed. Otherwise, we have found the triangle containing q and return the triangle.
DelaunayTriangulation.jump_and_march_across_triangleMethod
jump_and_march_across_triangle(tri::Triangulation, q, k, store_history, history, maxiters, cur_iter, concavity_protection, arrangement, original_k, last_changed, p, i, j, pᵢ, pⱼ) -> (Bool, Bool, Bool, Triangle, Integer, Certificate, Vertex, Vertex, Vertex, Point, Point, Integer, Integer)

Walks across the current triangle past the edge (i, j). progressing the jump_and_march algorithm.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • k: The vertex that the algorithm started from.
  • store_history: Whether to store the history of the algorithm.
  • history: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • maxiters: The maximum number of iterations to perform before restarting the algorithm with restart_jump_and_march.
  • cur_iter: The current iteration of the algorithm.
  • concavity_protection: Whether to use concavity protection. See concavity_protection_check. This is only needed if your triangulation is not convex.
  • arrangement: A Certificate defining the orientation of the triangle pᵢpⱼq.
  • original_k: The original vertex that the algorithm started from.
  • last_changed: The last vertex that was changed in the algorithm.
  • p: The point corresponding to the vertex original_k.
  • i: The first vertex of the triangle adjoining k to step from.
  • j: The second vertex of the triangle adjoining k to step from.
  • pᵢ: The point corresponding to the vertex i.
  • pⱼ: The point corresponding to the vertex j.

Outputs

  • restart_flag: Whether the algorithm needs to be restarted.
  • return_flag: Whether the algorithm can return immediately, returning V.
  • reinitialise_flag: Whether the algorithm needs to be reinitialised at a new vertex k. (This would only be needed if !has_ghost_triangles(tri).)
  • V: The triangle stepped into.
  • cur_iter: The new number of iterations of the algorithm.
  • arrangement: A Certificate defining the orientation of the triangle pᵢpⱼq with the updated values of i and j.
  • k: The new vertex that the algorithm is at.
  • last_changed: The last vertex that was changed in the algorithm.
  • original_k: The original vertex that the algorithm started from.
  • pᵢ: The point corresponding to the vertex i.
  • pⱼ: The point corresponding to the vertex j.
  • i: The first vertex of the triangle adjoining k to step from.
  • j: The second vertex of the triangle adjoining k to step from.

Extended help

This part of the algorithm is relatively complicated because there are many cases that need to be accounted for. Here we give a brief description of how this step works, and note that the documentation contains a much more detailed description.

  1. Firstly, we need to check whether k is an exterior ghost vertex or not. If k is an exterior ghost vertex, then this means that we are stepping outside of the triangulation. Thus, we use exterior_jump_and_march to find where q is, starting from the last_changed vertex. If concavity_protection = true, then concavity_protection_check is used to determine if a restart is needed, or if we can return safely. If we reach this step but !has_ghost_triangles(tri), then the algorithm should need to be reinitialised since q should not be outside of the triangulation, and so we return with reinitialise_flag = true.

  2. Now we consider the case where k is not an exterior ghost vertex. We move forward by updating the value of k so that k = get_adjacent(tri, i, j), and then consider where pₖ is relative to the line pq.

     2a. If `pₖ` is to the right of `pq`, then we should update `j` by `j = k`, ensuring that `j` is always to the right of `pq`.
     2b. If `pₖ` is to the left of `pq`, then we should update `i` by `i = k`, ensuring that `i` is always to the left of `pq`.
     2c. The alternative to 2a and 2b is that `pₖ` is collinear with the edge of `pq`, which could mean that `q` is in the current triangle or it is in a triangle further away. We compute a 
         [`Certificate`](@ref) that determines where `q` is relative to the triangle `pᵢpⱼpₖ`. If `q` is inside or on this triangle, then we return, restarting if necessary according to 
         `concavity_protection` and [`concavity_protection_check`](@ref). If we do not yet need to return, then we need to make a decision as to which of `i` and `j` to update, noting that 
         we want `i` to be left of `pq` and `j` to be right of `pq`, but this is no longer unambiguous since `pₖ` is collinear with `pq`. We make this decision according to `last_changed`:
         If `last_changed = i`, then moving left is what caused us to find this collinear edge, and so we send `k` left by letting `i = k`. Otherwise, we send `k` right by letting `j = k`.
  3. Now having stepped forward, we recompute the Certificate for arrangement and return, setting restart_flag = true if cur_iters ≥ maxiters.

DelaunayTriangulation.jump_and_march_degenerate_arrangementMethod
jump_and_march_degenerate_arrangement(tri::Triangulation, q, k, store_history::F, history, pᵢ, pⱼ, i, j) -> Bool

Given a degenerate arrangement pᵢpⱼq, reinitialise the jump and march algorithm.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • k: The vertex that the algorithm started from.
  • store_history: Whether to store the history of the algorithm.
  • history: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • pᵢ: The point corresponding to the vertex i.
  • pⱼ: The point corresponding to the vertex j.
  • i: The first vertex of the triangle adjoining k to step from.
  • j: The second vertex of the triangle adjoining k to step from.

Outputs

  • Bool: Whether the algorithm needs to be restarted.
DelaunayTriangulation.jump_and_march_return_on_vertexMethod
jump_and_march_return_on_vertex(tri::Triangulation, q, k, p, pᵢ, pⱼ, i, j) -> (Bool, Bool, Triangle)

Check if q is one of the vertices of the triangle (i, j, k) and return if needed.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • k: The vertex k that the algorithm started from.
  • p: The point corresponding to the vertex k.
  • pᵢ: The point corresponding to the vertex i.
  • pⱼ: The point corresponding to the vertex j.
  • i: The first vertex of the triangle adjoining k to start from.
  • j: The second vertex of the triangle adjoining k to start from.

Outputs

  • restart_flag: Whether the algorithm needs to be restarted.
  • return_flag: Whether the algorithm can return immediately, returning V.
  • V: The triangle (i, j, k).

Extended help

An extra check is made in this algorithm for the case that the point that q is equal to is one of the points corresponding to a ghost vertex, so it may be for example that q == pᵢ but is_ghost_vertex(i), in which case the algorithm would need to restart.

DelaunayTriangulation.keep_iteratingMethod
keep_iterating(tri::Triangulation, args::RefinementArguments) -> Bool

Returns true if the refinement should continue, and false otherwise. The check is based on whether the RefinementQueue is empty or not, and whether the number of points in the triangulation is less than or equal to the maximum number of points allowed by the RefinementConstraints.

DelaunayTriangulation.keep_splittingMethod
keep_splitting(tri::Triangulation, args::RefinementArguments) -> Bool

Returns true if more encroached segments need to be split, and false otherwise. The check is based on whether the segment queue in the RefinementQueue of args is empty or not, and whether the number of points in the triangulation is less than or equal to the maximum number of points allowed by the RefinementConstraints in args.

DelaunayTriangulation.legalise_edge!Function
legalise_edge!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing)

Legalises the edge (i, j) and other neighbouring edges in tri if they are illegal, assuming the vertex r was just added into a triangle that contains (i, j). flip_edge! is used.

See also is_legal.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the edge to legalise.
  • j: The second vertex of the edge to legalise.
  • r: The vertex that was just added into a triangle that contains (i, j).
  • store_event_history=Val(false): Whether to store the event history of the flip.
  • event_history=nothing: The event history. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.

Outputs

There is no output, as tri is updated in-place.

Invalid event histories

Edge flipping can lead to event_history having triangles both in event_history.added_triangles and event_history.deleted_triangles. To get around this, we only store in these fields the triangles necessary to allow undo_insertion! to work, so that at a triangle that might have appeared in both will only appear in one.

DelaunayTriangulation.legalise_split_edge!Function
legalise_split_edge!(tri::Triangulation, i, j, k, r, store_event_history=Val(false), event_history=nothing)

Legalises the newly added edges in tri after the edge (i, j) was split using split_edge!.

See also complete_split_edge_and_legalise!.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the edge that was split.
  • j: The second vertex of the edge that was split.
  • k: The vertex that was originally adjacent to (i, j).
  • r: The vertex that (i, j) was split at.
  • store_event_history=Val(false): Whether to store the event history of the flip.
  • event_history=nothing: The event history. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.

Outputs

There is no output, as tri is updated in-place.

DelaunayTriangulation.legalise_split_triangle!Method
legalise_split_triangle!(tri::Triangulation, i, j, k, r)

Legalises the newly added edges in tri after the triangle (i, j, k) was split using split_triangle!.

See also complete_split_triangle_and_legalise!.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the triangle.
  • j: The second vertex of the triangle.
  • k: The third vertex of the triangle.
  • r: The vertex to split the triangle at.

Outputs

There is no output, as tri is updated in-place.

DelaunayTriangulation.lexicographic_orderMethod
lexicographic_order(points) -> Vector{Int}

Returns a set of indices that give the lexicographic ordering of points, meaning the indices so that the points are sorted first by x and then by y.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 5.0), (0.0, 17.0), (0.0, 13.0), (5.0, 17.3), (3.0, 1.0), (5.0, -2.0)]
6-element Vector{Tuple{Float64, Float64}}:
 (1.0, 5.0)
 (0.0, 17.0)
 (0.0, 13.0)
 (5.0, 17.3)
 (3.0, 1.0)
 (5.0, -2.0)

julia> DelaunayTriangulation.lexicographic_order(points)
6-element Vector{Int64}:
 3
 2
 1
 5
 6
 4

julia> hcat(points, points[ans])
6×2 Matrix{Tuple{Float64, Float64}}:
 (1.0, 5.0)   (0.0, 13.0)
 (0.0, 17.0)  (0.0, 17.0)
 (0.0, 13.0)  (1.0, 5.0)
 (5.0, 17.3)  (3.0, 1.0)
 (3.0, 1.0)   (5.0, -2.0)
 (5.0, -2.0)  (5.0, 17.3)
DelaunayTriangulation.liang_barskyMethod
liang_barsky(a, b, c, d, p, q) -> (Point, Point)

Applies the Liang-Barsky algorithm to find the intersection of the line segment pq with the rectangle [a, b] × [c, d].

Arguments

  • p: The first point of the line segment.
  • q: The second point of the line segment.
  • a: The minimum x-coordinate of the rectangle.
  • b: The maximum x-coordinate of the rectangle.
  • c: The minimum y-coordinate of the rectangle.
  • d: The maximum y-coordinate of the rectangle.

Output

  • u: The first coordinate of the intersection, or (NaN, NaN) if there is no intersection.
  • v: The second coordinate of the intersection, or (NaN, NaN) if there is no intersection.
DelaunayTriangulation.line_segment_intersection_typeFunction
line_segment_intersection_type(p, q, a, b) -> Certificate 
line_segment_intersection_type(tri::Triangulation, u, v, i, j) -> Certificate

Given the coordinates (p, q) (or vertices (u, v)) and (a, b) (or vertices (i, j)) defining two line segments, tests the number of intersections between the two segments. The returned value is a Certificate, which is one of:

  • None: The line segments do not meet at any points.
  • Multiple: The closed line segments [p, q] and [a, b] meet in one or several points.
  • Single: The open line segments (p, q) and (a, b) meet in a single point.
  • Touching: One of the endpoints is on [a, b], but there are no other intersections.
DelaunayTriangulation.locate_intersecting_trianglesFunction
locate_intersecting_triangles(tri::Triangulation, e, rotate=Val(true), rng::AbstractRNG=Random.default_rng()) -> (Vector, Vector, Vector, Vector)

Find all the triangles intersected by an edge e.

See also jump_and_march.

Arguments

  • tri::Triangulation: The Triangulation.
  • e: The edge going through the triangulation.
  • rotate=Val(true): Whether to rotate the edge so that the minimum degree vertex of e is first.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to use.

Outputs

  • intersecting_triangles: The intersected triangles.
  • collinear_segments: Segments that are collinear with e.
  • left_vertices: The vertices of the intersected triangles that are left of e.
  • right_vertices: The vertices of the intersected triangles that are right of e.
DelaunayTriangulation.locate_steiner_pointMethod
locate_steiner_point(tri::Triangulation, args::RefinementArguments, T, c) -> Triangle, Cert

Locates the Steiner point c of a triangle T of tri in get_steiner_point. The Steiner point is located by walking from the initial vertex init to c using jump_and_march.

Arguments

  • tri::Triangulation: The Triangulation to split a triangle of.
  • args::RefinementArguments: The RefinementArguments for the refinement.
  • T: The triangle that the Steiner point is from.
  • c: The Steiner point.

Output

  • V: The triangle that the Steiner point is in.
  • flag: A Certificate which is Cert.On if the Steiner point is on the boundary of V, Cert.Outside if the Steiner point is outside of V, and Cert.Inside if the Steiner point is inside of V.
DelaunayTriangulation.lock_convex_hull!Method
lock_convex_hull!(tri::Triangulation)

Locks the convex hull of the unconstrained triangulation tri so that it is now treated as a constrained triangulation with boundary given by its convex hull.

Warning

If an edge is encountered along the convex hull that contains a segment from tri.interior_segments, then this edge will be deleted from tri.interior_segments; this will be undone from unlock_convex_hull!, possibly splitting the segments in case they were split before unlocking.

DelaunayTriangulation.make_shortest_edge_firstMethod
make_shortest_edge_first(p, q, r, idx) -> (NTuple{2, Number}, NTuple{2, Number}, NTuple{2, Number})

Given a triangle (p, q, r), rotate it (preserving orientation) so that the shortest edge is first. The argument idx gives the index of the shortest edge, where idx == 1 means (p, q), idx == 2 means (q, r), and idx == 3 means (r, p).

DelaunayTriangulation.map_curve_indexMethod
map_curve_index(boundary_enricher::BoundaryEnricher, curve_index) -> Integer

Returns the curve index in boundary_enricher associated with curve_index.

DelaunayTriangulation.marked_total_variationMethod
marked_total_variation(b::AbstractParametricCurve, t₁, t₂)

Returns the total variation of the curve b over the interval [t₁, t₂] using the orientation markers of b.

DelaunayTriangulation.maximum_distance_to_boxMethod
maximum_distance_to_box(a, b, c, d, p) -> Number

Computes the maximum squared distance from the point p to the box with corners (a, c), (b, c), (b, d), (a, d).

Arguments

  • a: The minimum x-coordinate of the box.
  • b: The maximum x-coordinate of the box.
  • c: The minimum y-coordinate of the box.
  • d: The maximum y-coordinate of the box.
  • p: The point.

Outputs

  • dist: The maximum squared distance from p to the box.
DelaunayTriangulation.mean_pointsFunction
mean_points(points[, vertices = each_point_index(points)]) -> NTuple{2, Number}

Returns the mean of the points in points indexed by vertices, given as a Tuple of the form (mean_x, mean_y).

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 2.0), (2.3, 5.0), (17.3, 5.3)]
3-element Vector{Tuple{Float64, Float64}}:
 (1.0, 2.0)
 (2.3, 5.0)
 (17.3, 5.3)

julia> DelaunayTriangulation.mean_points(points)
(6.866666666666667, 4.1000000000000005)

julia> (1.0 + 2.3 + 17.3)/3, (2.0 + 5.0 + 5.3)/3
(6.866666666666667, 4.1000000000000005)

julia> points = [1.0 2.3 17.3; 2.0 5.0 5.3]
2×3 Matrix{Float64}:
 1.0  2.3  17.3
 2.0  5.0   5.3

julia> DelaunayTriangulation.mean_points(points)
(6.866666666666667, 4.1000000000000005)

julia> DelaunayTriangulation.mean_points(points, (1, 3))
(9.15, 3.65)

julia> (1.0 + 17.3)/2, (2.0 + 5.3)/2
(9.15, 3.65)
DelaunayTriangulation.meet_predicateMethod
meet_predicate(p, q, a, b)

Returns ExactPredicates.meet(p, q, a, b), in particular we return:

  • 1: The open line segments (p, q) and (a, b) meet in a single point.
  • 0: The closed line segments [p, q] and [a, b] meet in one or several points.
  • -1: Otherwise.
DelaunayTriangulation.merge_segmentsMethod
merge_segments(tri::Triangulation, ghost_vertex_map) -> Edges

Creates a set of edges that merge all the boundary nodes in tri as well as its interior segments into a single collection.

Arguments

  • tri::Triangulation: The Triangulation.
  • ghost_vertex_map: The ghost vertex map to use.

Outputs

  • all_segments: The set of edges that merge all the boundary nodes in tri as well as its interior segments into a single collection, with type equal to that of get_interior_segments(tri)'s.
DelaunayTriangulation.midpointMethod
midpoint(p, q) -> Number or NTuple{2, Number}

Assuming p and q are either both numbers are both 2-vectors, computes their average.

DelaunayTriangulation.midpointMethod
midpoint(tri::Triangulation, u, v) -> NTuple{2, Number}
midpoint(tri::Triangulation, e) -> NTuple{2, Number}

Computes the midpoint of e = (u, v).

DelaunayTriangulation.minimise_enlargementMethod
minimise_enlargement(node, bounding_box) -> EnlargementValues

Returns the EnlargementValues associated with the child of node that minimises the enlargement, where enlargement is defined as the difference between the area of bounding_box and the area of the child's bounding box.

DelaunayTriangulation.move_generator_to_centroid!Method
move_generator_to_centroid!(points, vorn::VoronoiTessellation, generator) -> Number

Moves the generator generator to the centroid of its Voronoi cell. Returns the distance moved.

Arguments

  • points: The underlying point set. This is a deepcopy of the points of the underlying triangulation.
  • vorn: The VoronoiTessellation.
  • generator: The generator to move.

Outputs

  • dist: The distance moved.
DelaunayTriangulation.num_boundary_edgesMethod
num_boundary_edges(boundary_nodes) -> Integer

Get the number of boundary edges in boundary_nodes, assuming that boundary_nodes defines a boundary with only one curve and a single section.

DelaunayTriangulation.num_curvesMethod
num_curves(boundary_nodes) -> Integer

Get the number of curves in boundary_nodes.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.num_curves([1, 2, 3, 1])
1

julia> DelaunayTriangulation.num_curves([[1, 2, 3], [3, 4, 1]])
1

julia> DelaunayTriangulation.num_curves([[[1, 2, 3], [3, 4, 1]], [[5, 6, 7, 8, 5]]])
2
DelaunayTriangulation.num_edgesMethod
num_edges(E) -> Integer

Get the number of edges in E.

Examples

julia> using DelaunayTriangulation

julia> e = [(1, 2), (3, 4), (1, 5)];

julia> num_edges(e)
3
DelaunayTriangulation.num_edgesMethod
num_edges(G::Graph) -> Integer

Returns the number of edges in G. The edges (i, j) and (j, i) are counted as one edge.

DelaunayTriangulation.num_neighboursMethod
num_neighbours(tri::Triangulation, u) -> Integer

Returns the number of neighbours of u in tri. Note that, if has_ghost_triangles(tri), then some of the neighbours counted might be ghost vertices if u is a boundary vertex.

DelaunayTriangulation.num_pointsFunction
num_points(points) -> Integer

Returns the number of points in points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 1.0), (2.3, 1.5), (0.0, -5.0)];

julia> DelaunayTriangulation.num_points(points)
3

julia> points = [1.0 5.5 10.0 -5.0; 5.0 2.0 0.0 0.0];

julia> DelaunayTriangulation.num_points(points)
4
DelaunayTriangulation.num_pointsMethod
num_points(tri::Triangulation) -> Integer

Returns the number of points in tri.

Danger

If tri has vertices that are not yet present in the triangulation, e.g. if you have deleted vertices or have some submerged vertices in a weighted triangulation, then the corresponding points will still be counted in this function. It is recommended that you instead consider num_vertices, num_solid_vertices, or num_ghost_vertices.

DelaunayTriangulation.num_polygon_verticesMethod
num_polygon_vertices(vor::VoronoiTessellation) -> Integer

Returns the number of polygon vertices in the Voronoi tessellation vor. This might include duplicate vertices if get_polygon_points(vor) has duplicates.

DelaunayTriangulation.num_sectionsMethod
num_sections(boundary_nodes) -> Integer

Assuming boundary_nodes has only one curve, get the number of sections in boundary_nodes.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.num_sections([1, 2, 3, 4, 5, 1])
1

julia> DelaunayTriangulation.num_sections([[1, 2, 3, 4], [4, 5, 1]])
2

julia> DelaunayTriangulation.num_sections([[1, 2, 3], [3, 4, 5, 6, 7, 8], [8, 9], [9, 1]])
4
DelaunayTriangulation.num_trianglesMethod
num_triangles(T) -> Integer

Get the number of triangles in T.

Examples

julia> using DelaunayTriangulation

julia> T1, T2, T3 = (1, 5, 10), (17, 23, 10), (-1, 10, 5);

julia> T = Set((T1, T2, T3));

julia> num_triangles(T)
3
DelaunayTriangulation.num_trianglesMethod
num_triangles(tri::Triangulation) -> Integer

Returns the number of triangles in tri. Note that, if has_ghost_triangles(tri), then some of these triangles will be ghost triangles.

DelaunayTriangulation.number_typeFunction
number_type(x) -> DataType

Given a container x, returns the number type used for storing coordinates.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.number_type([1, 2, 3])
Int64

julia> DelaunayTriangulation.number_type((1, 2, 3))
Int64

julia> DelaunayTriangulation.number_type([1.0 2.0 3.0; 4.0 5.0 6.0])
Float64

julia> DelaunayTriangulation.number_type([[[1, 2, 3, 4, 5, 1]], [[6, 8, 9], [9, 10, 11], [11, 12, 6]]])
Int64

julia> DelaunayTriangulation.number_type((1.0f0, 2.0f0))
Float32

julia> DelaunayTriangulation.number_type(Vector{Float64})
Float64

julia> DelaunayTriangulation.number_type(Vector{Vector{Float64}})
Float64

julia> DelaunayTriangulation.number_type(NTuple{2, Float64})
Float64
DelaunayTriangulation.number_typeMethod
number_type(vorn::VoronoiTessellation) -> DataType

Type used for representing individual coordinates in the Voronoi tessellation.

DelaunayTriangulation.opposite_angleMethod
opposite_angle(p, q, r) -> Certificate

Tests the angle opposite to the edge (p, q) in the triangle (p, q, r), meaning ∠prq. The returned value is a Certificate, which is one of:

  • Obtuse: The angle opposite to (p, q) is obtuse.
  • Right: The angle opposite to (p, q) is a right angle.
  • Acute: The angle opposite to (p, q) is acute.
Angle between two vectors

This function computes (p - r) ⋅ (q - r). If you want the angle between vectors a = pq and b = pr, then you should use opposite_angle(r, q, p) = (r - p) ⋅ (q - p).

DelaunayTriangulation.optimise_edge_orderMethod
optimise_edge_order(tri::Triangulation, segment) -> Edge

Optimises the orientation of segment for inserting it into the triangulation.

Arguments

  • tri::Triangulation: The Triangulation.
  • segment: The segment to arrange.

Outputs

  • e: If segment is a boundary edge, then e = segment, Otherwise, e = sort_edge_by_degree(tri, segment) so that initial(e) has the smaller degree of the two vertices.
DelaunayTriangulation.orient_predicateMethod
orient_predicate(p, q, r, s) -> Integer

Returns ExactPredicates.orient(p, q, r, s), in particular we return:

  • 1: (p, q, r, s) is positively oriented.
  • 0: (p, q, r, s) is collinear / degenerate.
  • -1: (p, q, r, s) is negatively oriented.

Here, a positively oriented tetrahedron (p, q, r, s) takes the form

                               z.
                             .
                           ,/
                         s
                       ,/|'\
                     ,/  |  '\
                   ,/    '.   '\
                 ,/       |     '\                 
               ,/         |       '\              
              p-----------'.--------q --> x
               '\.         |      ,/              
                  '\.      |    ,/                 
                     '\.   '. ,/    
                        '\. |/      
                           'r       
                             '\.

Extended help

The orient predicate is defined by the determinant

\[\text{orient}(p, q, r, s) = \text{sgn} \det \begin{bmatrix} p_x & p_y & p_y & 1 \\ q_x & q_y & q_r & 1 \\ r_x & r_y & r_z & 1 \\ s_x & s_y & s_z & 1 \end{bmatrix} = \text{sgn} \det \begin{bmatrix} p_x - s_x & p_y - s_y & p_z - s_y \\ q_x - s_x & q_y - s_y & q_z - s_z \\ r_x - s_x & r_y - s_y & r_z - s_z \end{bmatrix}.\]

DelaunayTriangulation.orient_predicateMethod
orient_predicate(p, q, r) -> Integer

Returns ExactPredicates.orient(p, q, r), in particular we return:

  • 1: (p, q, r) is positively oriented.
  • 0: (p, q, r) is collinear / degenerate.
  • -1: (p, q, r) is negatively oriented.

Extended help

The orient predicate is defined by the determinant

\[\text{orient}(p, q, r) = \text{sgn} \det \begin{bmatrix} p_x & p_y & 1 \\ q_x & q_y & 1 \\ r_x & r_y & 1 \end{bmatrix} = \text{sgn} \det \begin{bmatrix} p_x-r_x & p_y-r_y \\ q_x-r_x & q_y-r_y \end{bmatrix}.\]

DelaunayTriangulation.orientation_markersMethod
orientation_markers(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) -> Vector{Float64}

Finds all orientation markers of the AbstractParametricCurve c. These are points t where any of the following conditions hold (not necessarily simultaneously), letting c(t) = (x(t), y(t)):

  • x'(t) = 0
  • y'(t) = 0
  • κ(t; x) = 0, where κ(t; x) is the curvature of the component function x(t)
  • κ(t; y) = 0, where κ(t; y) is the curvature of the component function y(t)
  • κ(t) = 0, where κ is the curvature of c(t)

Note that the third and fourth conditions give all the inflection points of the component functions, and similarly for the fifth condition.

See also horizontal_turning_points, vertical_turning_points, horizontal_inflection_points, vertical_inflection_points, and inflection_points.

High-degree curves

For curves of very high degree, such as Bezier curves with steps control points or greater, this function might fail to return all inflection points.

Arguments

Keyword Arguments

  • steps=200: The number of equally spaced points to use for initialising Newton's method.
  • iters=50: How many iterations to use for Newton's method.
  • tol=1e-5: The tolerance used for determining if two t-values are the same.

Output

  • markers::Vector{Float64}: The t-values of the orientation markers of b. The returned vector is sorted, and also includes the endpoints 0 and 1; any t-values outside of [0, 1] are discarded, and multiplicity of any t is not considered (so the t-values in the returned vector are unique). These values can be used to split the curve into monotone pieces, meaning the orientation is monotone. These markers also guarantee that, over any monotone piece, the orientation changes by an angle of at most π/2.
DelaunayTriangulation.parallelorder_predicateMethod
parallelorder_predicate(a, b, p, q) -> Integer

Returns ExactPredicates.parallelorder(a, b, p, q), in particular we return:

  • 1: q is closer to the line (a, b) than p.
  • 0: p and q are equidistant from the line (a, b).
  • -1: p is closer to the line (a, b) than q.
DelaunayTriangulation.partition_membersMethod
partition_members(complexes::Vector{SmallAngleComplex{I}}, points) where {I} -> Vector{SmallAngleComplex{I}}

Partitions the members of each complex in complexes into a new set of complexes. The complexes in complexes are assumed to be sorted in a counter-clockwise order around the apex of each complex. The partitioning is done so that the original set of members are now correctly split into their own complexes, since the original complexes might not have formed a properly contiguous set of small angles.

DelaunayTriangulation.point_closest_to_lineFunction
point_closest_to_line(a, b, p, q) -> Certificate
point_closest_to_line(tri::Triangulation, i, j, u, v) -> Certificate

Given a line through (a, b) (or through the vertices (i, j)), tests if p (or the vertex u) is closer to than q (or the vertex v), assuming that p and q are to the left of , returning a Certificate which is one of:

  • Closer: p is closer to .
  • Further: q is closer to .
  • Equidistant: p and q are the same distance from .
DelaunayTriangulation.point_position_on_line_segmentFunction
point_position_on_line_segment(a, b, p) -> Certificate
point_position_on_line_segment(tri::Triangulation, i, j, u) -> Certificate

Given a point p (or vertex u) and the line segment (a, b) (or edge (i, j)), assuming p to be collinear with a and b, computes the position of p relative to the line segment. The returned value is a Certificate which is one of:

  • On: p is on the line segment, meaning between a and b.
  • Degenerate: Either p == a or p == b, i.e. p is one of the endpoints.
  • Left: p is off and to the left of the line segment.
  • Right: p is off and to the right of the line segment.
DelaunayTriangulation.point_position_relative_to_circleMethod
point_position_relative_to_circle(a, b, c, p) -> Certificate

Given a circle through the coordinates (a, b, c), assumed to be positively oriented, computes the position of p relative to the circle. Returns a Certificate, which is one of:

  • Inside: p is inside the circle.
  • On: p is on the circle.
  • Outside: p is outside the triangle.
DelaunayTriangulation.point_position_relative_to_circumcircleFunction
point_position_relative_to_circumcircle(tri::Triangulation, i, j, k, ℓ) -> Certificate
point_position_relative_to_circumcircle(tri::Triangulation, T, ℓ) -> Certificate

Tests the position of the vertex of tri relative to the circumcircle of the triangle T = (i, j, k). The returned value is a Certificate, which is one of:

  • Outside: is outside of the circumcircle of T.
  • On: is on the circumcircle of T.
  • Inside: is inside the circumcircle of T.
Ghost triangles

The circumcircle of a ghost triangle is defined as the oriented outer halfplane of the solid edge of the triangle. See point_position_relative_to_oriented_outer_halfplane.

Weighted triangulations

If tri is a weighted triangulation, then an orientation test is instead applied, testing the orientation of the lifted companions of each point to determine if is above or below the witness plane relative to (i, j, k). For ghost triangles, the same rule applies, although if the vertex is on the solid edge of the ghost triangle then, in addition to checking point_position_relative_to_oriented_outer_halfplane, we must check if the new vertex is not submerged by the adjoining solid triangle.

DelaunayTriangulation.point_position_relative_to_curveMethod
point_position_relative_to_curve(e::AbstractParametricCurve, p) -> Certificate

Returns the position of the point p relative to the curve c. This function returns a [Certificate]:

  • Left: p is to the left of c.
  • Right: p is to the right of c.
  • On: p is on c.
DelaunayTriangulation.point_position_relative_to_curveMethod
point_position_relative_to_curve(enricher::BoundaryEnricher, curve_index, p) -> Certificate

Returns a Certificate which is

  • Left: If p is to the left of the curve_indexth curve.
  • Right: If p is to the right of the curve_indexth curve.
  • On: If p is on the curve_indexth curve.
DelaunayTriangulation.point_position_relative_to_diametral_circleMethod
point_position_relative_to_diametral_circle(p, q, r) -> Certificate

Given an edge (p, q) and a point r, returns the position of r relative to the diametral circle of (p, q). The returned value is a Certificate, which is one of:

  • Inside: r is inside the diametral circle.
  • On: r is on the diametral circle.
  • Outside: r is outside the diametral circle.

Extended help

The check is done by noting that a point is in the diametral circle if, and only if, the angle at r is obtuse.

DelaunayTriangulation.point_position_relative_to_diametral_lensFunction
point_position_relative_to_diametral_lens(p, q, r, lens_angle=30.0) -> Certificate

Given an edge (p, q) and a point r, returns the position of r relative to the diametral lens of (p, q) with lens angle lens_angle (in degrees). The returned value is a Certificate, which is one of:

  • Inside: r is inside the diametral lens.
  • On: r is on the diametral lens.
  • Outside: r is outside the diametral lens.
Warning

This function assumes that the lens angle is at most 45°.

Extended help

The diametral lens is slightly similar to a diametral circle. Let us first define the standard definition of a diametral lens, where lens_angle = 30°, and then we define its generalisation. The standard definition was introduced by Shewchuk in 2002 in this paper, and the generalisation was originally described in Section 3.4 of Shewchuk's 1997 PhD thesis here (as was the standard definition, of course).

Standard definition: Let the segment be s ≔ (p, q) and let be the perpendicular bisector of s. Define two circles C⁺ and C⁻ whose centers lie left and right of s, respectively, both the same distance away from the midpoint m = (p + q)/2. By placing each disk a distance |s|/(2√3) away from m and extending the disks so that they both touch p and q, meaning they each have radius |s|/√3, we obtain disks that touch p and q as well as the center of the other disk. The intersection of the two disks defines the diametral lens. The lens angle associated with this lens is 30°, as we could draw lines between p and q and the poles of the disks to form isosceles triangles on each side, giving angles of 30° at p and q.

Generalised definition: The generalisation of the above definition aims to generalise the lens angle to some angle θ. In particular, let us draw a line from p towards some point u which is left of s and on the perpendicular bisector, where the line is at an angle θ. This defines a triplet of points (p, q, u) from which we can define a circle, and similarly for a point v right of s. The intersection of these two circles is the diametral lens with angle θ. We can also figure out how far u is along the perpendicular bisector, i.e. how far away it is from (p + q)/2, using basic trigonometry. Let m = (p + q)/2, and consider the triangle △pmu. The side lengths of this triangle are |pm| = |s|/2, |mu| ≔ b, and |up| ≔ c. Let us first compute c. We have cos(θ) = |pm|/|up| = |s|/(2c), and so c = |s|/(2cos(θ)). So, sin(θ) = |mu|/|up| = b/c, which gives b = csin(θ) = |s|sin(θ)/(2cos(θ)) = |s|tan(θ)/2. So, u is a distance |s|tan(θ)/2 from the midpoint. Notice that in the case θ = 30°, tan(θ) = √3/3, giving b = |s|√3/6 = |s|/(2√3), which is the same as the standard definition.

To test if a point r is inside the diametral lens with lens angle θ°, we simply have to check the angle at that point, i.e. the angle at r in the triangle pqr. If this angle is greater than 180° - 2θ°, then r is inside of the lens. This result comes from Shewchuk (2002). Note that this is the same as a diametral circle in the case θ° = 45°.

DelaunayTriangulation.point_position_relative_to_lineFunction
point_position_relative_to_line(a, b, p) -> Certificate
point_position_relative_to_line(tri::Triangulation, i, j, u) -> Certificate

Tests the position of p (or the vertex u of tri) relative to the edge (a, b) (or the edge with vertices (i, j) of tri), returning a Certificate which is one of:

  • Left: p is to the left of the line.
  • Collinear: p is on the line.
  • Right: p is to the right of the line.
DelaunayTriangulation.point_position_relative_to_oriented_outer_halfplaneMethod
point_position_relative_to_oriented_outer_halfplane(a, b, p) -> Certificate

Given an edge with coordinates (a, b) and a point p, tests the position of p relative to the oriented outer halfplane defined by (a, b). The returned value is a Certificate, which is one of:

  • Outside: p is outside of the oriented outer halfplane, meaning to the right of the line (a, b) or collinear with a and b but not on the line segment (a, b).
  • On: p is on the line segment [a, b].
  • Inside: p is inside of the oriented outer halfplane, meaning to the left of the line (a, b).

Extended help

The oriented outer halfplane is the union of the open halfplane defined by the region to the left of the oriented line (a, b), and the open line segment (a, b).

DelaunayTriangulation.point_position_relative_to_triangleFunction
point_position_relative_to_triangle(a, b, c, p) -> Certificate
point_position_relative_to_triangle(tri::Triangulation, i, j, k, u) -> Certificate
point_position_relative_to_triangle(tri::Triangulation, T, u) -> Certificate

Given a positively oriented triangle with coordinates (a, b, c) (or triangle T = (i, j, k) of tri), computes the position of p (or vertex u) relative to the triangle. The returned value is a Certificate, which is one of:

  • Outside: p is outside of the triangle.
  • On: p is on one of the edges.
  • Inside: p is inside the triangle.
Ghost triangles

If T is a ghost triangle, then it is not checked if the point is on any of the ghost edges,

DelaunayTriangulation.point_position_relative_to_witness_planeMethod
point_position_relative_to_witness_plane(tri::Triangulation, i, j, k, ℓ) -> Certificate

Given a positively oriented triangle T = (i, j, k) of tri and a vertex of tri, returns the position of relative to the witness plane of T. The returned value is a Certificate, which is one of:

  • Above: is above the witness plane of T.
  • On: is on the witness plane of T.
  • Below: is below the witness plane of T.

Extended help

The witness plane of a triangle is defined as the plane through the triangle (i⁺, j⁺, k⁺) where, for example, pᵢ⁺ = (x, y, x^2 + y^2 - wᵢ) is the lifted companion of i and (x, y) are the coordinates of the ith vertex. Moreover, by the orientation of relative to this witness plane we are referring to ℓ⁺'s position, not the plane point .

DelaunayTriangulation.points_are_uniqueMethod
points_are_unique(points) -> Bool

Returns true if all points in points are unique.

Examples

julia> using DelaunayTriangulation

julia> points = [1.0 2.0 3.0 4.0 5.0; 0.0 5.5 2.0 1.3 17.0]
2×5 Matrix{Float64}:
 1.0  2.0  3.0  4.0   5.0
 0.0  5.5  2.0  1.3  17.0

julia> DelaunayTriangulation.points_are_unique(points)
true

julia> points[:, 4] .= points[:, 1];

julia> DelaunayTriangulation.points_are_unique(points)
false
DelaunayTriangulation.pole_of_inaccessibilityMethod
pole_of_inaccessibility(points, boundary_nodes; precision = one(number_type(points)))

Finds the pole of inaccessibility for the polygon defined by points and boundary_nodes. The boundary_nodes must match the specification given in the documentation. See also check_args for this specification.

Arguments

  • points: The points defining the polygon.
  • boundary_nodes: The boundary nodes defining the polygon.

Keyword Arguments

  • precision=one(number_type(points)): The precision of the returned pole. The default is one(number_type(points)).

Outputs

  • x: The x-coordinate of the pole.
  • y: The y-coordinate of the pole.

Extended help

The pole of inaccessibility is the point within a polygon that is furthest from an edge. For DelaunayTriangulation.jl, this is useful as it is a representative point for ghost edges that is guaranteed to be inside the polygon, in contrast to for example a centroid which is not always inside the polygon. Some useful links are this blog post and the the original repo. Our implementation is partially based on on the python implementation and this other Julia implementation.

DelaunayTriangulation.polygon_boundsFunction
polygon_bounds(points, boundary_nodes, check_all_curves=Val(false)) -> (Number, Number, Number, Number)

Computes the bounding box of the polygon defined by (points, boundary_nodes). The boundary_nodes must match the specification in the documentation and in check_args. If check_all_curves is true, then the bounding box of the union of all curves of the polygon is computed instead of just the first curve.

DelaunayTriangulation.polygon_boundsFunction
polygon_bounds(vorn::VoronoiTessellation, unbounded_extension_factor=0.0; include_polygon_vertices=true) -> (Number, Number, Number, Number)

Gets the bounding box for the Voronoi tessellation vorn.

Arguments

  • vorn::VoronoiTessellation: The Voronoi tessellation.
  • unbounded_extension_factor=0.0: The factor by which to extend the bounding box for unbounded polygons.

Keyword Arguments

  • include_polygon_vertices=true: If true, then the bounding box will also include the polygon vertices. Otherwise, only the generators are included.

Output

  • xmin: Given by xmin′ - unbounded_extension_factor * (xmin′ - xmin′), where xmin′ is the original minimum x-coordinate of the computed bounding box and similarly for xmax′.
  • xmax: Given by xmax′ + unbounded_extension_factor * (xmax′ - xmax′), where xmax′ is the original maximum x-coordinate of the computed bounding box and similarly for xmin′.
  • ymin: Given by ymin′ - unbounded_extension_factor * (ymin′ - ymin′), where ymin′ is the original minimum y-coordinate of the computed bounding box and similarly for ymax′.
  • ymax: Given by ymax′ + unbounded_extension_factor * (ymax′ - ymax′), where ymax′ is the original maximum y-coordinate of the computed bounding box and similarly for ymin′.
DelaunayTriangulation.polygon_featuresMethod
polygon_features(points, boundary_nodes) -> (Number, NTuple{2, Number})

Computes the signed area and centroid of the polygon defined by (points, boundary_nodes). The boundary_nodes must match the specification in the documentation and in check_args.

DelaunayTriangulation.polygoniseMethod
polygonise(points, boundary_nodes, boundary_curves; n=4096)

Fills out a set of points for a curve-bounded domain for use with PolygonHierarchy.

Warning

If the boundary curves are complicated so that they take a lot of points in order to be accurately resolved, then you should increase n.

Arguments

  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • boundary_curves: The boundary curves.

Keyword Arguments

  • n=4096: The number of points to use for filling in each boundary curves.

Output

  • new_points: The points defining the filled out boundaries.
  • new_boundary_nodes: The boundary nodes associated with new_points.
Aliasing

If the boundary is not curve bounded, then new_points and new_boundary_nodes remain aliased with the input points and boundary_nodes.

DelaunayTriangulation.pop_point!Function
pop_point!(points)

Pops the last point from points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 2.0), (1.3, 5.3)]
2-element Vector{Tuple{Float64, Float64}}:
 (1.0, 2.0)
 (1.3, 5.3)

julia> DelaunayTriangulation.pop_point!(points) # returns the popped vector
(1.3, 5.3)

julia> points
1-element Vector{Tuple{Float64, Float64}}:
 (1.0, 2.0)
DelaunayTriangulation.popfirst_triangle!Method
popfirst_triangle!(queue::RefinementQueue) -> (Triangle, Number)

Dequeue the next triangle from queue, returning the triangle and its radius-edge ratio.

DelaunayTriangulation.postprocess_triangulate!Method
postprocess_triangulate!(tri; delete_ghosts=false, delete_empty_features=true, recompute_representative_points=true)

Postprocesses the triangulation tri after it has been constructed using triangulate. This includes:

DelaunayTriangulation.postprocess_triangulate_convex!Method
postprocess_triangulate_convex!(tri::Triangulation, S; delete_ghosts, delete_empty_features)

Postprocesses the completed triangulation tri of the convex polygon S.

Arguments

Keyword Arguments

  • delete_ghosts=false: If true, the ghost triangles are deleted after triangulation.
  • delete_empty_features=true: If true, the empty features are deleted after triangulation.

Output

There are no output, as tri is modified in-place. The postprocessing that is done is:

  1. The convex hull of tri is set to S.
  2. The ghost triangles are deleted if delete_ghosts=true.
  3. The empty features are deleted if delete_empty_features=true.
  4. The representative points are set to the centroid of S.
DelaunayTriangulation.prepare_initial_edgeFunction
prepare_initial_edge(tri::Triangulation, edges, p, q, rng::AbstractRNG=Random.default_rng()) -> (Vertex, Vertex, Point, Point, Certificate, Certificate)

Selects a random edge from the set of edges edges and computes the certificates for the points corresponding to the initial and terminal vertices of the edge.

Arguments

  • tri::Triangulation: The Triangulation.
  • edges: The set of edges to sample from.
  • p: The initial point.
  • q: The query point.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to use.

Outputs

  • i: The initial vertex of the edge.
  • j: The terminal vertex of the edge.
  • pᵢ: The point corresponding to i.
  • pⱼ: The point corresponding to j.
  • line_cert_i: The Certificate for pᵢ's position relative to the oriented line pq.
  • line_cert_j: The Certificate for pⱼ's position relative to the oriented line pq.
DelaunayTriangulation.prepare_vertex_linked_listMethod
prepare_vertex_linked_list(V) -> ShuffledPolygonLinkedList

Given a list of polygon vertices V, returns the doubly-linked list of polygon vertices.

Arguments

  • V: The list of polygon vertices.

Outputs

  • list::ShuffledPolygonLinkedList: A ShuffledPolygonLinkedList. In list, prev[begin], prev[end], next[begin], and next[end] are all 0 as are shuffled_indices[begin] and shuffled_indices[end]. Moreover, shuffled_indices will not have been shuffled yet.
DelaunayTriangulation.process_collinear_segments!Method
process_intersecting_triangles!(tri::Triangulation, e, collinear_segments; rng::AbstractRNG=Random.default_rng()) -> Bool

Given segments in collinear_segments that are collinear with an edge e, updates tri so that this edge e is instead split so that it is instead represented by collinear_segments. These new segments will be placed into the triangulation using add_segment!.

See also connect_segments!, extend_segments!, split_segment! and split_boundary_edge_at_collinear_segments!.

DelaunayTriangulation.process_intersection_points!Method
process_intersection_points!(polygon_edge_queue, vorn, current_incident_polygon,
    left_edge_intersectors, right_edge_intersectors, current_edge_intersectors,
    left_edge, right_edge, current_edge, processed_pairs, segment_intersections, boundary_sites)

Process the intersection points in left_edge_intersectors, right_edge_intersectors, and current_edge_intersectors and add the new edges to polygon_edge_queue if necessary. Special care is taken to not miss any corner points.

Arguments

  • polygon_edge_queue: The queue of edges that need to be processed.
  • vorn: The VoronoiTessellation.
  • current_incident_polygon: The index of the current polygon being processed.
  • left_edge_intersectors: The intersection points of left_edge with other edges.
  • right_edge_intersectors: The intersection points of right_edge with other edges.
  • current_edge_intersectors: The intersection points of current_edge with other edges.
  • left_edge: The left edge of the current polygon.
  • right_edge: The right edge of the current polygon.
  • current_edge: The current edge of the current polygon.
  • processed_pairs: A set of pairs of edges and polygons that have already been processed.
  • segment_intersections: A dictionary of segment intersections.
  • boundary_sites: A dictionary of boundary sites.

Outputs

There are no outputs, but the caches and queues are updated in-place.

Extended help

The rules are based on the paper "Efficient Computation of Clipped Voronoi Diagram for Mesh Generation" by Yan, Wang, Levy, and Liu. Namely, an edge that intersects a boundary edge and one adjacent to it has its shared vertex added to the queue together with the current polygon (current_incident_polygon) being considered, and any intersections have the adjacent polygon added to the queue together with the intersecting edge. (These are not strictly the rules in the paper.)

This function works as follows:

  1. First, assuming that there is more than one triangle in the underlying triangulation of vorn, we need to consider left_edge and right_edge individually.
  2. The procedure for each edge is the same, so here we just describe the left_edge. If there are any intersectors with the left_edge, and neither of (left_edge, current_incident_polygon) or (reverse_edge(left_edge), current_incident_polygon) have already been processed (i.e., in processed_pairs), then we enqueue (left_edge, i) and (left_edge, j) into polygon_edge_queue, where i and j are the vertices of left_edge which correspond to polygons. This will ensure that we can find intersections next to this polygon.
  3. After enqueueing these pairs, we also need to protect against corner points, which we check for by considering current_incident_polygon ∈ all_indices, where all_indices are the vertices of left_edge, right_edge, and current_edge. If this is true, and if the shared vertex of current_edge and left_edge is equal to current_incident_polygon, then we need to add the point generator of current_incident_polygon as an intersection. This need comes from having to worry about corners, i.e. points where the two unbounded polygons meet and go directly left and right of a vertex so that that vertex is not considered an intersection; this point needs to be included.
  4. Once the left_edge and right_edge have been processed as above, we need to then consider all of left_edge, right_edge, and current_edge, and each of the intersections through the respective edge. This step is done regardless of whether there is a single triangle in the underlying triangulation. The procedure for each edge is the same, so let us just describe the current_edge. For each edge uv in the current_edge_intersectors, we need to get the polygon adjacent to that edge. Then, if (current_edge, adjacent_incident_polygon) or (reverse_edge(current_edge), adjacent_incident_polygon) have not been processed, we enqueue (current_edge, adjacent_incident_polygon).
  5. Once the edges have all been processed as above, we return.
DelaunayTriangulation.process_polygon!Method
process_polygon!(vorn::VoronoiTessellation, e, incident_polygon, boundary_sites, segment_intersections, intersected_edge_cache, exterior_circumcenters, equal_circumcenter_mapping) -> (Edge, Edge, Edge)

Processes the polygon incident_polygon for all of its intersections based on the boundary edge e.

Arguments

  • vorn::VoronoiTessellation: The VoronoiTessellation.
  • e: The edge on the boundary being considered.
  • incident_polygon: The index of the polygon being considered.
  • boundary_sites: The mapping from the indices of the sites on the boundary to the indices of the edges on the boundary that they intersect.
  • segment_intersections: The list of segment intersections.
  • intersected_edge_cache: A cache of the edges that have been intersected by the ray from u to v.
  • exterior_circumcenters: A list of the circumcenters of the sites that are outside the convex hull of the sites on the boundary.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.

Outputs

  • left_edge: The edge to the left of e on the boundary.
  • right_edge: The edge to the right of e on the boundary.
  • e: The edge on the boundary being considered.

In addition to these outputs, the caches are also updated in-place.

Extended help

This function works as follows:

  1. First, for the current edge e, we get the edges left_edge and right_edge that neighbour it via get_neighbouring_boundary_edges.
  2. For each edge of the incident_polygon, we need to process it depending on whether the edge (u, v) is finite, between two ghosts, going out to infinity, or coming in from infinity. If the edge is between two ghosts, we skip the edge. For rays that go out or in to infinity, we use process_ray_intersection! and process_ray_intersection_with_other_edges! to process the intersection of the ray with the boundary edges. The function process_ray_intersection_with_other_edges! is needed since rays going out to infinity may have to go through other boundary edges in order to do so, e.g. at a corner it may be that it crosses two boundary edges. For finite segments, process_segment_intersection! is used to process the intersection. We apply this function with each of e, left_edge, and right_edge to check for all intersections.
  3. The function is done once each of the polygon edges has been considered.
DelaunayTriangulation.process_ray_intersection!Method
process_ray_intersection!(
    vorn::VoronoiTessellation,
    u,
    v,
    incident_polygon,
    intersected_edge_cache,
    segment_intersections,
    boundary_sites,
    exterior_circumcenters,
    equal_circumcenter_mapping) -> Point

Process the intersection of the Voronoi polygon of the site u with the ray emanating from the circumcenter of the site v.

Arguments

  • vorn: The VoronoiTessellation.
  • u: The index of the site u, given as a ghost vertex for the associated ghost triangle.
  • v: The index of the site v.
  • incident_polygon: The index of the Voronoi polygon of the site u that is incident to the ray emanating from the circumcenter of the site v.
  • intersected_edge_cache: The list of intersected edges currently being considered.
  • segment_intersections: The list of segment intersections.
  • boundary_sites: A mapping from boundary sites to the indices of the segment intersections that are incident to the boundary site.
  • exterior_circumcenters: The list of circumcenters of sites that are outside the boundary.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.

Outputs

  • p: The coordinates of the intersection.

In addition to the point p, add_segment_intersection! is also updated to incorporate the new intersection point, as is add_to_intersected_edge_cache!.

DelaunayTriangulation.process_ray_intersection_with_other_edges!Method
process_ray_intersection_with_other_edges!(vorn::VoronoiTessellation,
    u,
    v,
    e,
    left_edge,
    right_edge,
    r,
    segment_intersections,
    boundary_sites,
    incident_polygon,
    equal_circumcenter_mapping,
    intersected_edge_cache)

Process the intersection of the ray from the ghost site u to the site v with the edges e, left_edge and right_edge.

Arguments

  • vorn::VoronoiTessellation: The VoronoiTessellation.
  • u: The index of the ghost site.
  • v: The index of the site u is going to.
  • e: The edge on the boundary being considered.
  • left_edge: The edge to the left of e on the boundary.
  • right_edge: The edge to the right of e on the boundary.
  • r: The coordinates of the intersection of the ray from u to v with some edge. If any(isnan, r), then the ray does not intersect any edge and we skip.
  • segment_intersections: The list of segment intersections.
  • boundary_sites: The mapping from the indices of the sites on the boundary to the indices of the edges on the boundary that they intersect.
  • incident_polygon: The index of the polygon that contains the intersection of the ray from u to v with the boundary.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.
  • intersected_edge_cache: A cache of the edges that have been intersected by the ray from u to v.

Outputs

There are no outputs, but add_segment_intersection! and add_to_intersected_edge_cache! are used to update the intersection objects.

DelaunayTriangulation.process_roots_and_residuals!Method
process_roots_and_residuals!(roots, residuals, tol) -> Vector{Float64}

Processes the roots and residuals of a root-finding algorithm. This function removes all NaN values from roots and residuals, sorts the roots in ascending order, and removes all roots with residuals greater than tol. The returned vector is the vector of roots with duplicates (i.e. roots that are within tol of each other) removed.

DelaunayTriangulation.process_segment_intersection!Method
process_segment_intersection!(
    vorn::VoronoiTessellation,
    u,
    v,
    e,
    incident_polygon,
    intersected_edge_cache,
    segment_intersections,
    boundary_sites,
    exterior_circumcenters,
    equal_circumcenter_mapping) -> Point

Process the intersection of the Voronoi polygon's edge (u, v) with the edge e of the boundary, returning the coordinates of the intersection and updating via add_segment_intersection!.

Arguments

  • vorn: The VoronoiTessellation.
  • u: The index of the site u.
  • v: The index of the site v.
  • e: The edge e of the boundary.
  • incident_polygon: The index of the Voronoi polygon currently being considered.
  • intersected_edge_cache: The list of intersected edges currently being considered.
  • segment_intersections: The list of segment intersections.
  • boundary_sites: A mapping from boundary sites to the indices of the segment intersections that are incident to the boundary site.
  • exterior_circumcenters: The list of circumcenters of sites that are outside the boundary.
  • equal_circumcenter_mapping: A mapping from the indices of the segment intersections that are equal to the circumcenter of a site to the index of the site.

Outputs

  • p: The coordinates of the intersection. If there is no intersection, this is (NaN, NaN).

In addition to the point p, add_segment_intersection! is also updated to incorporate the new intersection point, as is add_to_intersected_edge_cache!.

DelaunayTriangulation.protect_against_bad_division!Method
protect_against_bad_division!(roots, residuals, val, i) -> Bool

Protects against bad division in root-finding algorithms. This function checks if val is close to 0 or if roots[i] is outside of [0, 1]. If either of these conditions are true, then roots[i] and residuals[i] are set to NaN and true is returned. Otherwise, false is returned.

DelaunayTriangulation.push_point!Function
push_point!(points, x, y)
push_point!(points, p) = push_point!(points, getx(p), gety(p))

Pushes the point p = (x, y) into points.

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 3.0), (5.0, 1.0)]
2-element Vector{Tuple{Float64, Float64}}:
 (1.0, 3.0)
 (5.0, 1.0)

julia> DelaunayTriangulation.push_point!(points, 2.3, 5.3)
3-element Vector{Tuple{Float64, Float64}}:
 (1.0, 3.0)
 (5.0, 1.0)
 (2.3, 5.3)

julia> DelaunayTriangulation.push_point!(points, (17.3, 5.0))
4-element Vector{Tuple{Float64, Float64}}:
 (1.0, 3.0)
 (5.0, 1.0)
 (2.3, 5.3)
 (17.3, 5.0)
DelaunayTriangulation.push_point!Method
push_point!(tri::Triangulation, x, y)
push_point!(tri::Triangulation, p)

Pushes the point p = (x, y) into the points of tri.

DelaunayTriangulation.push_polygon_point!Method
push_polygon_point!(vor::VoronoiTessellation, p)
push_polygon_point!(vor::VoronoiTessellation, x, y)

Adds the point p = (x, y) into the vector of polygon points of vor.

DelaunayTriangulation.random_edgeFunction
random_edge([rng], E) -> E

Get a random edge from E.

Examples

julia> using DelaunayTriangulation, StableRNGs

julia> E = Set(((1,2),(10,15),(23,20)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (1, 2)
  (23, 20)
  (10, 15)

julia> rng = StableRNG(123);

julia> DelaunayTriangulation.random_edge(rng, E)
(10, 15)

julia> DelaunayTriangulation.random_edge(rng, E)
(10, 15)

julia> DelaunayTriangulation.random_edge(rng, E)
(23, 20)
julia> DelaunayTriangulation.random_edge(E)
(1, 2)
DelaunayTriangulation.refine!Method
refine!(tri::Triangulation; kwargs...)

Refines the given Triangulation tri to meet the given quality constraints.

See the documentation for more information about mesh refinement, e.g. convergence issues and issues with small input-angles.

Arguments

Keyword Arguments

  • min_angle=30.0: The minimum angle constraint, in degrees.
  • max_angle=180.0: The maximum angle constraint, in degrees.
Maximum angle constraints

Maximum angle constraints are not currently implemented.

  • min_area=get_area(tri) / 1e9: The minimum area constraint.
  • max_area=typemax(number_type(tri)): The maximum area constraint.
  • max_points=max(1_000, num_solid_vertices(tri))^2: The maximum number of vertices allowed in the triangulation. Note that this refers to num_solid_vertices, not the amount returned by num_points.
  • seditious_angle=20.0: The angle at which a triangle is considered seditious, in degrees. See is_triangle_seditious.
  • custom_constraint=(tri, T) -> false: A custom constraint function that takes a Triangulation and a triangle, and returns true if the triangle should be refined and false otherwise.
  • use_circumcenter=true: Whether to insert circumcenters for refining a triangle or generalised Steiner points.
Generalised Steiner points

Generalised Steiner points are not yet implemented. Thus, this argument must be true (and the steiner_scale keyword below is ignored).

  • use_lens=true: Whether to use the diametral lens or the diametral circle for checking encroachment.
  • steiner_scale=0.999: The perturbation factor to use for generalised Steiner points if use_circumcenter=false. (Not currently used - see above.)
  • rng=Random.default_rng(): The random number generator to use in case it is needed during point location.
  • concavity_protection=false: Whether to use concavity protection or not for jump_and_march. Most likely not needed, but may help in pathological cases.

Output

The triangulation is refined in-place.

Duplicate points and unused points

During refinement, points are often deleted, which may often lead to points in get_points(tri) that do not appear anywhere in the triangulation. (This is why we recommend e.g. each_solid_vertex over each_point.) Similarly, since points are deleted, when two triangles have a common circumcenter it might happen (if they are near an input segment) that a point is duplicated inside get_points(tri), in case one circumcenter was deleted previously.

DelaunayTriangulation.refine_itr!Method
refine_itr!(tri::Triangulation, args::RefinementArguments)

Performs a single iteration of the refinement algorithm.

Arguments

Output

The triangulation is refined in-place.

DelaunayTriangulation.remake_triangulation_with_constraintsMethod
remake_triangulation_with_constraints(tri::Triangulation, segments, boundary_nodes) -> (Dict, Dict, Triangulation)

Remakes the triangulation tri so that it contains segments and boundary_nodes in its fields.

See also replace_ghost_vertex_information.

Arguments

  • tri::Triangulation: The triangulation to remake.
  • segments: The segments to add to the triangulation.
  • boundary_nodes: The boundary nodes to add to the triangulation.

Outputs

  • new_ghost_vertex_map: The new ghost vertex map. This will not yet be added to the triangulation.
  • new_ghost_vertex_ranges: The new ghost vertex ranges. This will not yet be added to the triangulation.
  • new_tri::Triangulation: The new triangulation, now containing boundary_nodes in the boundary_nodes field and segments in the interior_segments field.
DelaunayTriangulation.reorder_hierarchy!Method
reorder_hierarchy!(hierarchy::PolygonHierarchy, points, boundary_nodes, new_tree::PolygonTree)

Given a new_tree that is not contained inside any other polygon in hierarchy, adds it into hierarchy. The existing trees are checked to see if they are contained inside new_tree, and if so, they are added as children of new_tree and removed from hierarchy.

Arguments

  • hierarchy::PolygonHierarchy: The PolygonHierarchy to add new_tree to.
  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • new_tree::PolygonTree: The PolygonTree to add to hierarchy.
DelaunayTriangulation.reorder_subtree!Method
reorder_subtree!(hierarchy::PolygonHierarchy, points, boundary_nodes, tree::PolygonTree, new_tree)

Given a new_tree contained inside tree, adds it into hierarchy. The children of tree are reordered if necessary, in case they are now contained inside new_tree.

Arguments

  • hierarchy::PolygonHierarchy: The PolygonHierarchy to add new_tree to.
  • points: The point set.
  • boundary_nodes: The boundary nodes.
  • tree::PolygonTree: The PolygonTree to add new_tree to.
  • new_tree::PolygonTree: The PolygonTree to add to hierarchy and tree.
DelaunayTriangulation.reorient_edgeMethod
reorient_edge(enricher::BoundaryEnricher, i, j) -> NTuple{2,Integer}

Given an edge (i, j), reorients it so that it is correctly oriented with the boundary. If (i, j) is instead an interior segment rather than a boundary edge, then (i, j) is returned.

DelaunayTriangulation.replace!Method
replace!(node::AbstractNode, left, right, original_bounding_box, tree::RTree)

Replaces the node in tree with left and right. Returns true if the tree's bounding boxes had to be adjusted and false otherwise.

DelaunayTriangulation.replace_ghost_vertex_informationMethod
replace_ghost_vertex_information(tri::Triangulation, ghost_vertex_map, ghost_vertex_ranges) -> Triangulation

Replaces the ghost vertex information in tri with ghost_vertex_map and ghost_vertex_ranges, using the results from remake_triangulation_with_constraints.

Arguments

  • tri::Triangulation: The triangulation to remake.
  • ghost_vertex_map: The ghost vertex map to add to the triangulation.
  • ghost_vertex_ranges: The ghost vertex ranges to add to the triangulation.

Outputs

  • new_tri::Triangulation: The new triangulation, now containing ghost_vertex_map in the ghost_vertex_map field and ghost_vertex_ranges in the ghost_vertex_ranges field.
DelaunayTriangulation.replace_next_edge!Method
replace_next_edge!(enricher::BoundaryEnricher, apex, complex_id, member_id, next_edge)

Replaces the next edge of the member_idth member of the complex_idth complex associated with apex with next_edge.

DelaunayTriangulation.replace_next_edgeMethod
replace_next_edge(member::SmallAngleComplexMember{I}, next_edge) where {I} -> SmallAngleComplexMember{I}

Returns a new SmallAngleComplexMember with the same parent curve as member but with next_edge as the next edge.

DelaunayTriangulation.reset!Method
reset!(list::ShuffledPolygonLinkedList; rng::AbstractRNG=Random.default_rng())

Resets the linked list, so that list.next[i] = mod1(i+1, list.k) and list.prev[i] = mod1(i-1, list.k), and also reshuffles the list.shuffled_indices vector.

DelaunayTriangulation.restart_jump_and_marchMethod
restart_jump_and_march(tri::Triangulation, q, store_history, history, rng, maxiters, cur_iter, concavity_protection, num_restarts, use_barriers) -> Triangle[, Bool]

Restart the jump_and_march algorithm, or use brute_force_search to find q if num_restarts ≥ 25.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point.
  • store_history: Whether to store the history of the algorithm.
  • history: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • rng: The random number generator to use.
  • maxiters: The maximum number of iterations to perform before restarting the algorithm with restart_jump_and_march.
  • cur_iter: The current iteration of the algorithm.
  • concavity_protection: Whether to use concavity protection. See concavity_protection_check. This is only needed if your triangulation is not convex.
  • num_restarts: The number of times the algorithm has been restarted.
  • use_barriers: Whether to use barriers, stopping the algorithm at any segment.

Outputs

  • V: The triangle containing q.

In addition, if use_barriers = Val(true), then a second output is returned, which is a boolean indicating whether the algorithm reached a barrier (true) or not (false).

DelaunayTriangulation.retriangulateMethod
retriangulate(tri::Triangulation, points=get_points(tri); kwargs...)

Retriangulates the triangulation tri using the points points, returning a new Triangulation.

Arguments

  • tri::Triangulation: The triangulation to retriangulate.
  • points=get_points(tri): The points to use for retriangulating the triangulation. By default, this is simply get_points(tri).

Keyword Arguments

  • skip_points=Set(filter(i -> !has_vertex(tri, i), each_point_index(tri))): The points to skip when inserting points into the triangulation.
  • kwargs...: Extra keyword arguments passed to triangulate. Other keyword arguments, like segments and boundary_nodes, are automatically passed from the fields of tri, but may be overridden by passing the corresponding keyword arguments.
DelaunayTriangulation.retriangulate_fan!Method
retriangulate_fan!(tri::Triangulation, tri_fan::Triangulation, fan, fan_triangles; rng::AbstractRNG=Random.default_rng())

Given a sorted set of vertices fan in a fan of triangles associated with fan_triangles, retriangulates the fan, updating tri to do so and using tri_fan as a temporary triangulation. (This implements Lines 17–19 and Line 28 of the algorithms in this paper.)

DelaunayTriangulation.reverse_edgeMethod
reverse_edge(e) -> Edge

Get the edge with the vertices of e in reverse order.

Examples

julia> using DelaunayTriangulation

julia> e = (17, 3);

julia> DelaunayTriangulation.reverse_edge(e)
(3, 17)

julia> e = [1, 2];

julia> DelaunayTriangulation.reverse_edge(e)
2-element Vector{Int64}:
 2
 1
DelaunayTriangulation.rotate_left!Method
rotate_left!(parent::BalancedBSTNode{K}) -> BalancedBSTNode{K}

Rotates a subtree rooted at parent to the left, returning the new root of the subtree. This local operation is used to preserve the binary search tree property after inserting or deleting a node.

DelaunayTriangulation.rotate_right!Method
rotate_right!(parent::BalancedBSTNode{K}) -> BalancedBSTNode{K}

Rotates a subtree rooted at parent to the right, returning the new root of the subtree. This local operation is used to preserve the binary search tree property after inserting or deleting a node.

DelaunayTriangulation.rotate_triangleMethod
rotate_triangle(T, rotation) -> Triangle

Rotate the vertices of T by rotation. In particular, if T = (i, j, k):

  • rotation = 0: (i, j, k)
  • rotation = 1: (j, k, i)
  • rotation = 2: (k, i, j)
  • Otherwise, return rotate_triangle(T, rotation % 3).

Examples

julia> using DelaunayTriangulation

julia> T = (1, 2, 3)
(1, 2, 3)

julia> DelaunayTriangulation.rotate_triangle(T, 0)
(1, 2, 3)

julia> DelaunayTriangulation.rotate_triangle(T, 1)
(2, 3, 1)

julia> DelaunayTriangulation.rotate_triangle(T, 2)
(3, 1, 2)

julia> DelaunayTriangulation.rotate_triangle(T, 3)
(1, 2, 3)
DelaunayTriangulation.sameside_predicateMethod
sameside_predicate(a, b, p) -> Integer

Returns ExactPredicates.sameside(p, a, b) where all three points are collinear, in particular we return:

  • 1: a and b are on the same side of p on the line.
  • 0: a == p or b == p.
  • -1: a and b are on different sides of p on the line.
Note

The difference in the argument order to ExactPredicates.jl is to match the convention that the main point being tested is the last argument.

DelaunayTriangulation.search_down_adjacent_boundary_edgesMethod
search_down_adjacent_boundary_edges(tri::Triangulation, k, q, direction_cert, q_pos_cert, next_vertex, store_history=Val(false), history=nothing, ghost_vertex=𝒢) -> (Bool, Certificate, Vertex, Vertex, Vertex)

Starting at the boundary vertex k, walks down the boundary in the direction of q until finding q or finding that it is outside of the triangulation.

See also check_for_intersections_with_adjacent_boundary_edges, which uses this function to determine an initial direction to search along.

Arguments

Outputs

  • return_flag: Whether to return, or throw an exception.
  • q_pos_cert: A Certificate that is On if q is on the edge (u, v), and Outside if q is outside of the triangulation.
  • u: If is_on(q_pos_cert), this is the first vertex of a positively oriented triangle that q is on, so that q is on the edge (u, v). Otherwise, (u, v, w) is a ghost triangle close to q.
  • v: If is_on(q_pos_cert), this is the second vertex of a positively oriented triangle that q is on, so that q is on the edge (u, v). Otherwise, (u, v, w) is a ghost triangle close to q.
  • w: If is_on(q_pos_cert), this is the third vertex of a positively oriented triangle that q is on, so that q is on the edge (u, v) and w = get_adjacent(tri, u, v). Otherwise, (u, v, w) is a ghost triangle close to q.
Non-convex geometries

This function assumes that the geometry is convex. The function will still be able to return, but is_outside(q_pos_cert) may not necessarily mean q is outside of the triangulation. The main function jump_and_march will have to restart the algorithm if it is found that is_outside(q_pos_cert) was incorrect.

Extended help

This function works by stepping along vertices on the boundaries in the direction specified by direction_cert, using search_right_down_adjacent_boundary_edges if is_right(direction_cert) and search_left_down_adjacent_boundary_edges otherwise. In these functions, a while loop is used to keep stepping until q_pos_cert, which is updated at each iteration, changes value.

DelaunayTriangulation.segment_vertices_adjoin_other_segments_at_acute_angleMethod
segment_vertices_adjoin_other_segments_at_acute_angle(tri::Triangulation, e) -> Int, Vertex

Determines if the vertices of a segment e of tri adjoin other segments at an acute angle.

Arguments

Output

  • num_adjoin: The number of vertices of e that adjoin other segments at an acute angle.
  • adjoin_vert: The vertex of e that adjoins another segment at an acute angle if num_adjoin == 1, and otherwise.
DelaunayTriangulation.select_initial_pointFunction
select_initial_point(tri::Triangulation, q; kwargs...) -> Vertex

Selects the initial point for jump_and_march to start from.

Arguments

  • tri::Triangulation: The Triangulation.
  • q: The query point. Can be either a point or a vertex - if it is a vertex, the corresponding point get_point(tri, q) will be used.

Keyword Arguments

  • point_indices=each_solid_vertex(tri): The indices to sample from.
  • m=default_num_samples(num_vertices(point_indices)): The number of samples to take. Replacement is not used, so there may be duplicates.
  • try_points=(): A list of points to try in addition to those randomly sampled.
  • allow_boundary_points=!is_disjoint(tri): Whether to allow boundary points to be selected.
  • rng=Random.default_rng(): The random number generator to use.

Outputs

  • i: The index of the point closest to q out of those queried.
DelaunayTriangulation.select_initial_triangle_interior_vertexMethod
select_initial_triangle_interior_vertex(tri::Triangulation, k, q, store_history=Val(false), history=nothing, rng::AbstractRNG=Random.default_rng()) -> (Point, Vertex, Vertex, Point, Point)

Selects the initial triangle for jump_and_march to start from, for the case where k is an interior vertex.

Arguments

  • tri::Triangulation: The Triangulation.
  • k: The vertex to start from.
  • q: The query point.
  • store_history=Val(false): Whether to store the history of the algorithm.
  • history=nothing: The history of the algorithm. If store_history, then this should be a PointLocationHistory object.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to use.

Outputs

  • p: The point corresponding to k.
  • i: The initial vertex of the triangle.
  • j: The terminal vertex of the triangle.
  • pᵢ: The point corresponding to i.
  • pⱼ: The point corresponding to j.
Non-convex geometries

This function assumes that the geometry is convex. To deal with this, when an infinite loop is detected we return for both i and j, and then let jump_and_march handle how to correct the algorithm from there.

Extended help

This part of the algorithm works by rotating around the vertex k, looking for a triangle whose edges adjoining k are to the left and to the right of k. By choosing the initial edge at random via prepare_initial_edge, and computing the position of q relative to this initial edge, the rotation will be either clockwise or counter-clockwise, and the triangle is then found using either select_initial_triangle_clockwise or select_initial_triangle_counterclockwise, respectively.

In case the initial edge is collinear with the line pq, where p = get_point(tri, q), then fix_initial_collinear_edge_for_interior_vertex to find a non-collinear edge resample more edges from prepare_initial_edge if necessary.

DelaunayTriangulation.select_random_edgeFunction
select_random_edge(tri::Triangulation, edges, rng::AbstractRNG=Random.default_rng()) -> (Vertex, Vertex, Point, Point)

Selects a random edge from the set of edges edges.

Arguments

  • tri::Triangulation: The Triangulation.
  • edges: The set of edges to sample from.
  • rng::AbstractRNG=Random.default_rng(): The random number generator to use.

Outputs

  • i: The initial vertex of the edge.
  • j: The terminal vertex of the edge.
  • pᵢ: The point corresponding to i.
  • pⱼ: The point corresponding to j.
DelaunayTriangulation.select_random_vertexMethod
select_random_vertex(tri::Triangulation, list::ShuffledPolygonLinkedList, u, v, range, rng) -> Vertex

Selects a random vertex that is not closer to the line (u, v) than both of its neighbours.

Arguments

  • tri::Triangulation: The Triangulation.
  • list::ShuffledPolygonLinkedList: The linked list of polygon vertices.
  • u, v: The vertices of the line.
  • range: The range of indices of the vertices to select from.
  • rng::AbstractRNG: The random number generator to use.

Outputs

  • j: The selected vertex.
DelaunayTriangulation.select_shortest_edge_for_offcenterMethod
select_shortest_edge_for_offcenter(p, q, r, c, ℓ²) -> (NTuple{2, Number}, NTuple{2, Number}, NTuple{2, Number})

Given a triangle (p, q, r) with more than one edge attaining the shortest length, selects the appropriate shortest edge for triangle_offcenter.

Arguments

  • p: The first vertex of the triangle.
  • q: The second vertex of the triangle.
  • r: The third vertex of the triangle.
  • c: The circumcenter of the triangle.
  • ℓ²: The squared shortest edge length.

The arguments should be so that (p, q, r) is positively oriented and ℓ² = |p - q|² is the squared shortest edge length.

Outputs

  • u: The first vertex of the rotated triangle.
  • v: The second vertex of the rotated triangle.
  • w: The third vertex of the rotated triangle.

These outputs (u, v, w) are a permutation of (p, q, r) (maintaining positive orientation) such that |m - c₁| is maximised over all other shortest edges, where m = (u + v)/2. If there is no unique maximiser, then the output is the permutation that is lexicographically smallest (i.e., sorted by x and then by y).

DelaunayTriangulation.set_bounding_box!Method
set_bounding_box!(hierarchy::PolygonHierarchy, index, bounding_box)

Sets the bounding box of the indexth polygon in hierarchy to bounding_box. If index is greater than the length of the bounding boxes vector, the vector is resized.

DelaunayTriangulation.set_orientation!Method
set_orientation!(hierarchy::PolygonHierarchy, index, orientation)

Sets the polygon orientation of the indexth polygon in hierarchy to orientation. If index is greater than the length of the polygon orientations vector, the vector is resized.

DelaunayTriangulation.set_point!Function
set_point!(points, i, x, y)
set_point!(points, i, p) = set_point!(points, i, getx(p), gety(p))

Sets the point at index i in points to (x, y).

Examples

julia> using DelaunayTriangulation

julia> points = [(1.0, 3.0), (5.0, 17.0)]
2-element Vector{Tuple{Float64, Float64}}:
 (1.0, 3.0)
 (5.0, 17.0)

julia> DelaunayTriangulation.set_point!(points, 1, 0.0, 0.0)
(0.0, 0.0)

julia> points
2-element Vector{Tuple{Float64, Float64}}:
 (0.0, 0.0)
 (5.0, 17.0)

julia> points = [1.0 2.0 3.0; 4.0 5.0 6.0]
2×3 Matrix{Float64}:
 1.0  2.0  3.0
 4.0  5.0  6.0

julia> DelaunayTriangulation.set_point!(points, 2, (17.3, 0.0))
2-element view(::Matrix{Float64}, :, 2) with eltype Float64:
 17.3
  0.0

julia> points
2×3 Matrix{Float64}:
 1.0  17.3  3.0
 4.0   0.0  6.0
DelaunayTriangulation.set_tree!Method
set_tree!(hierarchy::PolygonHierarchy, index, tree)

Sets the PolygonTree of the indexth polygon in hierarchy to tree, or adds it if it is not an existing key. The index must be associated with an exterior polygon.

DelaunayTriangulation.setup_cavity_cdtMethod
setup_cavity_cdt(tri::Triangulation, V; rng::AbstractRNG=Random.default_rng()) -> ShuffledPolygonLinkedList

Prepares the linked list required for triangulating a cavity excavated by segment insertion in a constrained triangulation.

See also prepare_vertex_linked_list and delete_polygon_vertices_in_random_order!.

Arguments

  • tri::Triangulation: The Triangulation.
  • V: The list of polygon vertices, given as a counter-clockwise list of vertices, defining the cavity.

Keyword Arguments

  • rng::AbstractRNG=Random.default_rng(): The random number generator to use.

Outputs

  • list::ShuffledPolygonLinkedList: The linked list of polygon vertices representing the cavity.
DelaunayTriangulation.sort_convex_polygon!Method
sort_convex_polygon!(vertices, points)

Sorts the vertices of a convex polygon in counter-clockwise order. The polygon is defined by (points, vertices), and the vertices are sorted in-place. It is assumed that the vertices are not circular, i.e. vertices[begin] ≠ vertices[end].

DelaunayTriangulation.sort_fan!Method
sort_fan!(fan, fan_triangles, tri::Triangulation)

Given a set of triangles in a fan, fan_triangles, associated with some triangulation tri, places all the triangle vertices and sorts them counter-clockwise, placing the results into fan.

DelaunayTriangulation.sort_members!Method
sort_members!(complex::SmallAngleComplex, points)

Sorts the members of complex in a counter-clockwise order around the apex of complex.

DelaunayTriangulation.sort_triangleFunction
sort_triangle(T) -> Triangle
sort_triangle(i, j, k) -> Triangle

Sort the triangle T = (i, j, k) so that its last vertex is the smallest, respecting the orientation of T.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.sort_triangle((1, 5, 3))
(5, 3, 1)

julia> DelaunayTriangulation.sort_triangle((1, -1, 2))
(2, 1, -1)

julia> DelaunayTriangulation.sort_triangle((3, 2, 1))
(3, 2, 1)
DelaunayTriangulation.sort_trianglesMethod
sort_triangles(T) -> Triangle

Sort the triangles in T so that the first vertex of each triangle is the largest, respecting the orientation of the triangles. See sort_triangle.

Examples

julia> using DelaunayTriangulation

julia> T = Set(((1, 3, 2), (5, 2, 3), (10, 1, 13), (-1, 10, 12), (10, 1, 17), (5, 8, 2)))
Set{Tuple{Int64, Int64, Int64}} with 6 elements:
  (5, 8, 2)
  (10, 1, 13)
  (10, 1, 17)
  (5, 2, 3)
  (1, 3, 2)
  (-1, 10, 12)

julia> DelaunayTriangulation.sort_triangles(T)
Set{Tuple{Int64, Int64, Int64}} with 6 elements:
  (13, 10, 1)
  (3, 5, 2)
  (10, 12, -1)
  (5, 8, 2)
  (17, 10, 1)
  (3, 2, 1)
DelaunayTriangulation.spawn_branch!Method
spawn_branch!(tree::RTree, bounding_box::BoundingBox, level) -> Branch

Returns a new branch node with bounding box bounding_box and level level from tree.

DelaunayTriangulation.spawn_leaf!Method
spawn_leaf!(tree::RTree, bounding_box::BoundingBox) -> Leaf{Branch}

Returns a new leaf node with bounding box bounding_box from tree.

DelaunayTriangulation.spawn_node!Method
spawn_node!(cache::NodeCache{Node}) where {Node} -> Node

Returns a node from cache. If cache is empty, returns a new node.

DelaunayTriangulation.spawn_node!Method
spawn_node!(tree::RTree, ::Type{N}, [bounding_box::BoundingBox], level) where {N} -> N

Returns a new node of type N with bounding box bounding_box and level level from tree. If bounding_box is not provided, it is replaced with InvalidBoundingBox.

DelaunayTriangulation.split!Method
split!(node::AbstractNode, tree::RTree) -> Branch, Branch

Splits node into two other nodes using a linear splitting rule. Returns the two new nodes.

DelaunayTriangulation.split_boundary_edge!Function
split_boundary_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes = Val(true))

Updates the fields of enricher after splitting a boundary edge (i, j) at the rth vertex. The update_boundary_nodes argument can be used to avoid inserting an additional boundary node when boundary_nodes was already updated somewhere else (e.g., we need this for mesh refinement which already updates the boundary_nodes which is aliased with the same field in the enricher).

DelaunayTriangulation.split_boundary_edge!Method
split_boundary_edge!(events::InsertionEventHistory, u, v, new_point)

Add the edge (u, v) to the deleted_boundary_segments of events and add the edges (u, new_point) and (new_point, v) to the added_boundary_segments of events.

DelaunayTriangulation.split_boundary_edge_at_collinear_segments!Method
split_boundary_edge_at_collinear_segments!(tri::Triangulation, collinear_segments)

Splits a boundary edge into pieces defined by collinear_segments. In particular, if r = collinear_segments and

u = initial(r[1])
v = terminal(r[end]),

then the boundary edge is (u, v) and the edges are split so that all segments in collinear_segments appear instead.

DelaunayTriangulation.split_edge!Function
split_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes = Val(true), update_segments = Val(true), is_interior = is_segment(enricher, i, j))

Updates the fields of enricher after splitting an edge (i, j) at the rth vertex. The update_boundary_nodes argument can be used to avoid inserting an additional boundary node when boundary_nodes was already updated somewhere else (e.g., we need this for mesh refinement which already updates the boundary_nodes which is aliased with the same field in the enricher). The same point goes for update_segments which can be used to avoid inserting an additional segment when segments was already updated somewhere else. The is_interior argument can be used to specify whether the edge is an interior segment or a boundary edge.

See also split_boundary_edge! and split_interior_segment!.

DelaunayTriangulation.split_edge!Function
split_edge!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing)

Splits the edge (i, j) in tri at the vertex r. For the triangulation to be valid after this splitting, it is assumed that r is collinear with, or at least very close to collinear with, the edge (i, j).

See also legalise_split_edge! and complete_split_edge_and_legalise!.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the edge to split.
  • j: The second vertex of the edge to split.
  • r: The vertex to split the edge at.
  • store_event_history=Val(false): Whether to store the event history of the flip.
  • event_history=nothing: The event history. Only updated if store_event_history is true, in which case it needs to be an InsertionEventHistory object.

Outputs

There is no output, as tri is updated in-place.

Handling unoriented edges

The triangulation will only be updated as if (i, j) has been split rather than also (j, i). You will need to call split_edge! again with (j, i) if you want to split that edge as well.

DelaunayTriangulation.split_edge!Method
split_edge!(tree::BoundaryRTree, i, j, r)

Splits the diametral bounding box associated with (i, j) into two new boxes associated with the diametral circles of (i, r) and (j, r).

DelaunayTriangulation.split_interior_segment!Function
split_interior_segment!(enricher::BoundaryEnricher, i, j, r, update_segments = Val(true))

Updates the fields of enricher after splitting an interior segment (i, j) at the rth vertex. The update_segments argument can be used to avoid inserting an additional segment when segments was already updated somewhere else (e.g., we need this for mesh refinement which already updates the interior_segments which is aliased with the segments field in the enricher).

DelaunayTriangulation.split_marked_vertices!Method
split_marked_vertices!(fan_triangles, tri::Triangulation, marked_vertices)

Given a set of marked_vertices indicating a crossed triangle (like in Figure 9 of this paper), finds all triangles whose three vertices are all in marked_vertices and places them into fan_triangles.

DelaunayTriangulation.split_segment!Method
split_segment!(tri::Triangulation, segment, collinear_segments)
split_segment!(segments, segment, collinear_segments)

Splits segment at the segments in collinear_segments, which are assumed to be collinear with segment.

Arguments

  • tri::Triangulation: The Triangulation.
  • segments: The underlying set of segments. This is get_interior_segments(tri) if tri is a Triangulation.
  • segment: The segment to split.
  • collinear_segments: The segments that are collinear with segment.

Outputs

There is no output, as segments is updated in-place.

Example

julia> using DelaunayTriangulation

julia> segments = Set(((2, 3), (3, 5), (10, 12)))
Set{Tuple{Int64, Int64}} with 3 elements:
  (2, 3)
  (3, 5)
  (10, 12)

julia> collinear_segments = [(2, 10), (11, 15), (2, 3)]
3-element Vector{Tuple{Int64, Int64}}:
 (2, 10)
 (11, 15)
 (2, 3)

julia> segment = (3, 5)
(3, 5)

julia> DelaunayTriangulation.split_segment!(segments, segment, collinear_segments)
Set{Tuple{Int64, Int64}} with 4 elements:
  (2, 10)
  (2, 3)
  (11, 15)
  (10, 12)
DelaunayTriangulation.split_subcurve!Method
split_subcurve!(enricher::BoundaryEnricher, i, j) -> Bool

Splits the curve associated with the edge (i, j) into two subcurves by inserting a point r between (i, j) such that the total variation of the subcurve is equal on (i, r) and (r, j). The returned value is a flag that is true if there was a precision issue, and false otherwise.

DelaunayTriangulation.split_triangle!Method
split_triangle!(tri::Triangulation, args::RefinementArguments, T) -> Certificate

Splits a bad triangle T of tri to improve its quality.

Arguments

Output

  • cert: A Certificate indicating whether the split was successful or not. In particular, returns one of:
    • Cert.SuccessfulInsertion: The triangle was split successfully.
    • Cert.EncroachmentFailure: The triangle was not split successfully as the newly inserted point encroached upon a segment.
    • Cert.PrecisionFailure: The triangle was not split successfully due to precision issues.
DelaunayTriangulation.split_triangle!Method
split_triangle!(tri::Triangulation, i, j, k, r)

Splits the triangle (i, j, k) at the vertex r, assumed to be inside the triangle.

See also legalise_split_triangle! and complete_split_triangle_and_legalise!.

Arguments

  • tri::Triangulation: The Triangulation.
  • i: The first vertex of the triangle.
  • j: The second vertex of the triangle.
  • k: The third vertex of the triangle.
  • r: The vertex to split the triangle at.

Outputs

There is no output, but tri will be updated so that it now contains the triangles (i, j, r), (j, k, r), and (k, i, r).

DelaunayTriangulation.squared_distance_to_segmentMethod
squared_distance_to_segment(x₁, y₁, x₂, y₂, x, y) -> Number

Given a line segment (x₁, y₁) → (x₂, y₂) and a query point (x, y), returns the squared distance from (x, y) to the line segment.

DelaunayTriangulation.squared_triangle_areaMethod
squared_triangle_area(p, q, r) -> Number

Computes the squared area of the triangle with coordinates p, q, r. Initially, squared_triangle_area is used for this, unless the squared area is found to be negative due to precision issues, in which case squared_triangle_area_v2 is used instead.

DelaunayTriangulation.squared_triangle_areaMethod
squared_triangle_area(ℓ₁², ℓ₂², ℓ₃²) -> Number

Compute the squared area of a triangle given the squares of its edge lengths. Heron's formula is used, so that the squared area is

\[A^2 = \dfrac{1}{16}\left[4\ell_1^2\ell_2^2 - \left(\ell_1^2 + \ell_2^2 - \ell_3^2\right)^2\right]..\]

See also squared_triangle_area_v2.

DelaunayTriangulation.squared_triangle_area_v2Method
squared_triangle_area_v2(ℓ₁², ℓ₂², ℓ₃²) -> Number

Compute the squared area of a triangle given the squares of its edge lengths, given in sorted order so that ℓ₁² ≤ ℓ₂² ≤ ℓ₃². This is a more numerically stable version of squared_triangle_area using the formula from Kahan (2014):

\[A^2 = \dfrac{1}{16}\left\{\left[\ell_3 + \left(\ell_2 + \ell_1\right)\right]\left[\ell_1 - \left(\ell_3 - \ell_2\right)\right]\left[\ell_1 + \left(\ell_3 - \ell_2\right)\right]\left[\ell_3 + \left(\ell_2 - \ell_1\right)\right]\right\}.\]

DelaunayTriangulation.squared_triangle_lengthsMethod
squared_triangle_lengths(p, q, r) -> (Number, Number, Number)

Computes the squared lengths of the edges of the triangle with coordinates p, q, r. The squared lengths are returned in sorted order.

DelaunayTriangulation.squared_triangle_lengths_and_smallest_indexMethod
squared_triangle_lengths_and_smallest_index(p, q, r) -> (Number, Number, Number, Integer)

Computes the squared lengths of the edges of the triangle with coordinates p, q, r. The squared lengths are returned in sorted order, and the index of the shortest edge is returned as well. Here, the index refers to which edge in the order (p, q), (q, r), (q, p).

DelaunayTriangulation.swap_permutation!Method
swap_permutation!(list::ShuffledPolygonLinkedList, i, j)

Reorders the permutation list.shuffled_indices of the linked list, swapping πᵢ and πⱼ where πₖ = list.shuffled_indices[k].

DelaunayTriangulation.terminalMethod
terminal(e) -> Vertex

Get the terminal vertex of e.

Examples

julia> using DelaunayTriangulation

julia> e = (1, 7);

julia> DelaunayTriangulation.terminal(e)
7

julia> e = [2, 13];

julia> DelaunayTriangulation.terminal(e)
13
DelaunayTriangulation.test_visibilityMethod
test_visibility(enricher::BoundaryEnricher, i, j, k) -> Certificate

Tests if the vertex k is visible from the edge (i, j). Returns a Certificate which is

  • Invisible: If k is not visible from (i, j).
  • Visible: If k is visible from (i, j).

For this function, k should be inside the diametral circle of (i, j).

We say that k is invisibile from (i, j) if the edges (i, k) or (j, k) intersect any other boundary edges, or there is a hole between (i, j) and k.

Definition incompatibility

This is not the same definition used in defining constrained Delaunay triangulations, where visibility means visible from ANY point on the edge instead of only from the endpoints.

DelaunayTriangulation.test_visibilityMethod
test_visibility(tri::Triangulation, u, v, i; shift=0.0, attractor=get_point(tri,i)) -> Certificate

Tests if the edge (u, v) and the point i can see each other. Here, visibility means that any point in the interior of (u, v) can see i. To test this, we only check 10 points equally spaced between u and v, excluding u and v.

Arguments

  • tri: The Triangulation.
  • u: The first vertex of the edge.
  • v: The second vertex of the edge.
  • i: The vertex we are testing visibility of.

Keyword Arguments

  • shift=0.0: The amount by which to shift each point on the edge towards attractor, i.e. if p is a point on the edge, then p .+ shift .* (attractor - p) is the point used to test visibility rather than p itself.

Outputs

  • cert: A Certificate. This will be Visible if i is visible from (u, v), and Invisible otherwise.
DelaunayTriangulation.test_visibilityMethod
test_visibility(tri::Triangulation, q, i) -> Certificate

Tests if the vertex i and the point q can see each other. Here, visibility means that the line segment joining the two does not intersect any segments.

Arguments

  • tri: The Triangulation.
  • 1: The point from which we are testing visibility.
  • i: The vertex we are testing visibility of.

Outputs

  • cert: A Certificate. This will be Visible if i is visible from q, and Invisible otherwise.
DelaunayTriangulation.to_boundary_curvesMethod
to_boundary_curves(points, boundary_nodes) -> NTuple{N, AbstractParametricCurve} where N

Returns the set of boundary curves associated with boundary_nodes and points.

DelaunayTriangulation.total_variationFunction
total_variation(c::AbstractParametricCurve) -> Float64
total_variation(c::AbstractParametricCurve, t₁, t₂) -> Float64

Returns the total variation of a curve c, or the subcurve over [t₁, t₂] with 0 ≤ t₁ ≤ t₂ ≤ 1, defined as the integral of the absolute curvature over this interval. (This is also known as the total absolute curvature.)

DelaunayTriangulation.triangle_anglesMethod
triangle_angles(p, q, r) -> (Number, Number, Number)

Computes the angles of a triangle with vertices p, q, and r. The formula for, say, the angle at p is given by

\[\theta_1 = \arctan\left(\dfrac{2A}{\left(p - q\right)\cdot\left(p - r\right)}\right),\]

where A is the area of the triangle. The angles are returned in sorted order.

DelaunayTriangulation.triangle_areaMethod
triangle_area(ℓ₁², ℓ₂², ℓ₃²) -> Number

Compute the area of a triangle given the squares of its edge lengths. If there are precision issues that cause the area to be negative, then the area is set to zero.

See also squared_triangle_area.

DelaunayTriangulation.triangle_aspect_ratioMethod
triangle_aspect_ratio(inradius::Number, circumradius::Number) -> Number

Computes the aspect ratio of a triangle with inradius inradius and circumradius circumradius. The aspect ratio is given by

\[\tau = \dfrac{r_i}{r},\]

where $r_i$ is the inradius and $r$ is the circumradius.

DelaunayTriangulation.triangle_centroidMethod
triangle_centroid(p, q, r) -> (Number, Number)

Computes the centroid of a triangle with vertices p, q, and r, given by

\[c = \dfrac{p + q + r}{3}.\]

DelaunayTriangulation.triangle_circumcenterFunction
triangle_circumcenter(p, q, r, A=triangle_area(p, q, r)) -> (Number, Number)

Computes the circumcenter of the triangle with coordinates (p, q, r). The circumcenter is given by

\[c_x = r_x + \dfrac{d_{11}d_{22} - d_{12}d_{21}}{4A}, \quad c_y = r_y + \dfrac{e_{11}e_{22} - e_{12}e_{21}}{4A},\]

where $d_{11} = \|p - r\|_2^2$, $d_{12} = p_y - r_y$, $d_{21} = \|q - r\|_2^2$, $d_{22} = q_y - r_y$, $e_{11} = p_x - r_x$ $e_{12} = d_{11}$, $e_{21} = q_x - r_x$, and $e_{22} = d_{21}$.

DelaunayTriangulation.triangle_circumradiusMethod
triangle_circumradius(A, ℓmin², ℓmed², ℓmax²) -> Number

Computes the circumradius of a triangle with area A and squared edge lengths ℓmin² ≤ ℓmed² ≤ ℓmax². The circumradius is given by

\[r = \dfrac{\ell_{\min}\ell_{\text{med}}\ell_{\max}}{4A}.\]

DelaunayTriangulation.triangle_edgesFunction
triangle_edges(T) -> NTuple{3, Edge}
triangle_edges(i, j, k) -> NTuple{3, Edge}

Get the edges of T = (i, j, k) as a Tuple, in particular

((i, j), (j, k), (k, i)).

Examples

julia> using DelaunayTriangulation

julia> T = (1, 2, 3);

julia> DelaunayTriangulation.triangle_edges(T)
((1, 2), (2, 3), (3, 1))

julia> DelaunayTriangulation.triangle_edges(1, 2, 3)
((1, 2), (2, 3), (3, 1))
DelaunayTriangulation.triangle_inradiusMethod
triangle_inradius(A, perimeter) -> Number

Computes the inradius of a triangle with area A and perimeter perimeter. The inradius is given by

\[r_i = \dfrac{2A}{P},\]

where $P$ is the perimeter.

DelaunayTriangulation.triangle_lengthsMethod
triangle_lengths(p, q, r) -> (Number, Number, Number)

Computes the lengths of the edges of the triangle with coordinates p, q, r. The lengths are returned in sorted order.

DelaunayTriangulation.triangle_line_segment_intersectionFunction
triangle_line_segment_intersection(p, q, r, a, b) -> Certificate 
triangle_line_segment_intersection(tri::Triangulation, i, j, k, u, v) -> Certificate

Classifies the intersection of the line segment (a, b) (or the edge (u, v) of tri) with the triangle (p, q, r) (or the triangle (i, j, k) of tri). The returned value is a Certificate, which is one of:

  • Inside: (a, b) is entirely inside (p, q, r).
  • Single: (a, b) has one endpoint inside (p, q, r), and the other is outside.
  • Outside: (a, b) is entirely outside (p, q, r).
  • Touching: (a, b) is on (p, q, r)'s boundary, but not in its interior.
  • Multiple: (a, b) passes entirely through (p, q, r). This includes the case where a point is on the boundary of (p, q, r).
DelaunayTriangulation.triangle_offcenterFunction
triangle_offcenter(p, q, r, c₁=triangle_circumcenter(p, q, r), β=1.0) -> (Number, Number)

Computes the off-center of the triangle (p, q, r).

Arguments

  • p, q, r: The coordinates of the triangle, given in counter-clockwise order.
  • c₁=triangle_circumcenter(p, q, r): The circumcenter of the triangle.
  • β=1.0: The radius-edge ratio cutoff.

Output

  • cx: The x-coordinate of the off-center.
  • cy: The y-coordinate of the off-center.
Difference in definitions

In the original this paper, the off-center is defined to instead be the circumcenter if it the triangle pqc₁ has radius-edge ratio less than β. Here, we just let the off-center be the point c so that pqc has radius-edge ratio of exactly β.

DelaunayTriangulation.triangle_orientationFunction
triangle_orientation(tri::Triangulation, i, j, k) -> Certificate 
triangle_orientation(tri::Triangulation, T) -> Certificate
triangle_orientation(p, q, r) -> Certificate

Computes the orientation of the triangle T = (i, j, k) with correspondig coordinates (p, q, r). The returned value is a Certificate, which is one of:

  • PositivelyOriented: The triangle is positively oriented.
  • Degenerate: The triangle is degenerate, meaning the coordinates are collinear.
  • NegativelyOriented: The triangle is negatively oriented.
DelaunayTriangulation.triangle_perimeterMethod
triangle_perimeter(ℓmin::Number, ℓmed::Number, ℓmax::Number) -> Number

Computes the perimeter of a triangle with edge lengths ℓmin ≤ ℓmed ≤ ℓmax. The perimeter is given by

\[P = \ell_{\min} + \ell_{\text{med}} + \ell_{\max}.\]

DelaunayTriangulation.triangle_radius_edge_ratioMethod
triangle_radius_edge_ratio(circumradius::Number, ℓmin::Number) -> Number

Computes the radius-edge ratio of a triangle with circumradius circumradius and minimum edge length ℓmin, given by

\[\rho = \dfrac{r}{\ell_{\min}},\]

where $r$ is the circumradius and $\ell_{\min}$ is the shortest edge length.

DelaunayTriangulation.triangle_sinkFunction
triangle_sink(p, q, r, tri::Triangulation) -> (Number, Number)

Computes the sink of each triangle in tri. See this paper for more information.

Extended help

Sinks were introduced in this paper. For a given triangle T, the sink of T is defined as follows:

  1. If c, the circumcenter of T, is in the interior of T, then the sink of T is T.
  2. If T is a boundary triangle, then the sink of T is T.
  3. If neither 1 or 2, then the sink is defined as the sink of the triangle V, where V is the triangle adjoining the edge of T which intersects the line mc, where m is the centroid of T.

In cases where the triangulation has holes, this definition can lead to loops. In such a case, we just pick one of the triangles in the loop as the sink triangle.

DelaunayTriangulation.triangle_typeMethod
triangle_type(::Type{T}) -> DataType

Get the triangle type of T.

Examples

julia> using DelaunayTriangulation

julia> DelaunayTriangulation.triangle_type(Set{NTuple{3,Int64}})
Tuple{Int64, Int64, Int64}

julia> DelaunayTriangulation.triangle_type(Vector{NTuple{3,Int32}})
Tuple{Int32, Int32, Int32}

julia> DelaunayTriangulation.triangle_type(Vector{Vector{Int64}})
Vector{Int64} (alias for Array{Int64, 1})
DelaunayTriangulation.triangle_verticesMethod
triangle_vertices(T) -> NTuple{3, Vertex}

Returns the vertices of T as a Tuple.

Examples

julia> using DelaunayTriangulation

julia> triangle_vertices((1, 5, 17))
(1, 5, 17)

julia> triangle_vertices([5, 18, 23]) # -> tuple
(5, 18, 23)
DelaunayTriangulation.triangulateMethod
triangulate(points; segments=nothing, boundary_nodes=nothing, kwargs...) -> Triangulation

Computes the Delaunay triangulation of points, and then the constrained Delaunay triangulation if any of segments and boundary_nodes are not nothing.

Arguments

  • points: The points to triangulate.
Mutation

For curve-bounded domains, points may get mutated to include the endpoints of the provided curves, and when inserting Steiner points to split segments or refine boundaries.

Keyword Arguments

  • segments=nothing: The segments to include in the triangulation. If nothing, then no segments are included.
Segments outside of the domain

When segments are outside of the domain, are if they are not entirely contained with the domain, you may run into issues - especially for curve-bounded domains. It is your responsibility to ensure that the segments are contained within the domain.

Mutation

The segments may get mutated in two ways: (1) Segments may get rotated so that (i, j) becomes (j, i). (2) If there are segments that are collinear with other segments, then they may get split into chain of non-overlapping connecting segments (also see below). For curve-bounded domains, segments are also split so that no subsegment's diametral circle contains any other point.

Intersecting segments

Currently, segments that intersect in their interiors (this excludes segments that only intersect by sharing a vertex) cause problems for triangulating. While there is some support for collinear segments that lie on top of each other (they get split automatically), this is not the case for segments that intersect in their interiors. Moreover, this automatic splitting should not be heavily relied upon, and for curve-bounded domains you should not rely on it at all as it causes problems during the enrichment phase from enrich_boundary!.

  • boundary_nodes=nothing: The boundary nodes to include in the triangulation. If nothing, then no boundary nodes are included, and the convex hull of points remains as the triangulation. These boundary nodes should match the specification given in check_args if a boundary is provided as a set of vertices, meaning the boundary is a piecewise linear curve. To specify a curve-bounded domain, you should follow the same specification, but use AbstractParametricCurves to fill out the vector, and any piecewise linear section should still be provided as a sequence of vertices.
Points outside of boundary curves

While for standard domains with piecewise linear boundaries (or no boundaries) it is fine for points to be outside of the domain (they just get automatically deleted if needed), they may cause problems for curve-bounded domains. Please ensure that all your points are inside the curve-bounded domain if you are providing curves in boundary_nodes.

Aliasing

For curve-bounded domains, the boundary_nodes in the resulting Triangulation will not be aliased with the input boundary nodes.

Refinement

For curve-bounded domains, note that the triangulation produced from this function is really just an initial coarse discretisation of the true curved boundaries. You will need to refine further, via refine!, to improve the discretisation, or increase coarse_n below. See also polygonise for a more direct approach to discretising a boundary (which might not give as high-quality meshes as you can obtain from refine! though, note).

  • weights=ZeroWeight(): The weights to use for the triangulation. By default, the triangulation is unweighted. The weights can also be provided as a vector, with the ith weight referring to the ith vertex, or more generally any object that defines get_weight. The weights should be Float64.
Weighted triangulations

Weighted triangulations are not yet fully implemented due to certain bugs with the implementation.

  • IntegerType=Int: The integer type to use for the triangulation. This is used for representing vertices.
  • EdgeType=isnothing(segments) ? NTuple{2,IntegerType} : (edge_type ∘ typeof)(segments): The edge type to use for the triangulation.
  • TriangleType=NTuple{3,IntegerType}: The triangle type to use for the triangulation.
  • EdgesType=isnothing(segments) ? Set{EdgeType} : typeof(segments): The type to use for storing the edges of the triangulation.
  • TrianglesType=Set{TriangleType}: The type to use for storing the triangles of the triangulation.
  • randomise=true: Whether to randomise the order in which the points are inserted into the triangulation. This is done using get_insertion_order.
  • delete_ghosts=false: Whether to delete the ghost triangles after the triangulation is computed. This is done using delete_ghost_triangles!.
  • delete_empty_features=true: Whether to delete empty features after the triangulation is computed. This is done using clear_empty_features!.
  • try_last_inserted_point=true: Whether to try the last inserted point first when inserting points into the triangulation.
  • skip_points=(): The points to skip when inserting points into the triangulation. Note that, for curve-bounded domains, skip_points is ignored when using enrich_boundary!.
  • num_sample_rule=default_num_samples: A function mapping a number of points n to a number of samples m to use for sampling the initial points during the point location step of the algorithm within jump_and_march.
  • rng::AbstractRNG=Random.default_rng(): The random number generator.
  • insertion_order::Vector=get_insertion_order(points, randomise, skip_points, IntegerType, rng): The insertion order to use for inserting points into the triangulation. This is ignored if you are defining a curve-bounded domain.
  • recompute_representative_points=true: Whether to recompute the representative points after the triangulation is computed. This is done using compute_representative_points!.
  • delete_holes=true: Whether to delete holes after the triangulation is computed. This is done using delete_holes!.
  • check_arguments=true: Whether to check the arguments points and boundary_nodes are valid. This is done using check_args.
  • polygonise_n=4096: Number of points to use for polygonising the boundary when considering the poylgon hierarchy for a curve-bounded domain using polygonise. See triangulate_curve_bounded.
  • coarse_n=0: Number of points to use for initialising a curve-bounded domain. See triangulate_curve_bounded. (A value of 0 means the number of points is chosen automatically until the diametral circles of all edges are empty.)
  • conform=false: If true, then the triangulation will be enriched so that all segments are split until each segment's diametral circle contains no other points. This is done by treating the triangulation as a curve-bounded triangulation and using enrich_boundary!.

Outputs

  • tri::Triangulation: The triangulation.
DelaunayTriangulation.triangulate_cavity_cdt!Method
triangulate_cavity_cdt!(tri::Triangulation, V, marked_vertices; rng::AbstractRNG=Random.default_rng())

Triangulates the cavity V left behind when deleting triangles intersected in a triangulation by an edge, updating tri to do so.

Arguments

  • tri::Triangulation: The Triangulation to update. This should be an empty triangulation.
  • V: The list of polygon vertices, given as a counter-clockwise list of vertices, defining the cavity.
  • tri_fan::Triangulation: The Triangulation to use for the fan of triangles to be re-triangulated. This should be an empty triangulation.
  • marked_vertices: Cache for marking vertices to re-triangulate during the triangulation.
  • fan_triangles: A cache used for sorting and identifying triangles in a fan for retriangulation.

Keyword Arguments

  • rng::AbstractRNG=Random.default_rng(): The random number generator to use or setup_cavity_cdt.

Outputs

There is no output, but tri is updated in-place.

DelaunayTriangulation.triangulate_convex!Method
triangulate_convex!(tri::Triangulation, S; rng::AbstractRNG=Random.default_rng())

Triangulates the convex polygon S in-place into tri.

Arguments

  • tri::Triangulation: The triangulation to be modified.
  • S: A convex polygon represented as a vector of vertices. The vertices should be given in counter-clockwise order, and must not be circular so that S[begin] ≠ S[end].

Keyword Arguments

  • store_event_history=Val(false): Whether to store the event history of the triangulation from triangulating the polygon.

Outputs

There is no output, as tri is updated in-place. This function does not do any post-processing, e.g. deleting any ghost triangles. This is done by triangulate_convex or postprocess_triangulate_convex!.

DelaunayTriangulation.triangulate_convexMethod
triangulate_convex(points, S; delete_ghosts=false, delete_empty_features=true, rng=Random.default_rng(), kwargs...) -> Triangulation

Triangulates the convex polygon S.

Arguments

  • points: The point set corresponding to the vertices in S.
  • S: A convex polygon represented as a vector of vertices. The vertices should be given in counter-clockwise order, and must not be circular so that S[begin] ≠ S[end].

Keyword Arguments

  • delete_ghosts=false: If true, the ghost triangles are deleted after triangulation.
  • delete_empty_features=true: If true, the empty features are deleted after triangulation.
  • rng=Random.default_rng(): The random number generator used to shuffle the vertices of S before triangulation.
  • kwargs...: Additional keyword arguments passed to Triangulation.
Weighted triangulations

While weighted triangulations are not yet supported from triangulate directly, they are supported through this triangulate_convex. In particular, you can use the weights keyword argument to pass the weights of the vertices in points.

Output

  • tri::Triangulation: The triangulated polygon.
DelaunayTriangulation.triangulate_curve_boundedMethod
triangulate_curve_bounded(points::P;
segments=nothing,
boundary_nodes=nothing,
IntegerType::Type{I}=Int,
polygonise_n=4096,
coarse_n=0,
check_arguments=true,
delete_ghosts=false,
delete_empty_features=true,
recompute_representative_points=true,
rng::AbstractRNG=Random.default_rng(),
insertion_order=nothing, 
kwargs...) where {P,I} -> Triangulation

Triangulates a curve-bounded domain defined by (points, segments, boundary_nodes). Please see triangulate for a description of the arguments. The only differences are:

  • insertion_order=nothing: This argument is ignored for curve-bounded domains.
  • polygonise_n=4096: For generating a high-resolution discretisation of a boundary initially for the construction of a PolygonHierarchy, many points are needed. This number of points is defined by polygonise_n, and must be a power of 2 (otherwise, the next highest power of 2 is used). See polygonise.
  • coarse_n=0: This is the number of points to use for initialising a curve-bounded domain via coarse_discretisation!. The default coarse_n=0 means the discretisation is performed until the maximum variation over any subcurve is less than π/2.
  • skip_points: This is still used, but it is ignored during the enrichment phase (see enrich_boundary!).

See also BoundaryEnricher and enrich_boundary!.

Refinement

To refine the mesh further beyond its initial coarse discretisation, as produced from this function, please see refine!.

DelaunayTriangulation.triangulate_rectangleMethod
triangulate_rectangle(a, b, c, d, nx, ny; kwargs...) -> Triangulation

Triangulates the rectangle [a, b] × [c, d].

Arguments

  • a: The minimum x-coordinate.
  • b: The maximum x-coordinate.
  • c: The minimum y-coordinate.
  • d: The maximum y-coordinate.
  • nx: The number of points in the x-direction.
  • ny: The number of points in the y-direction.

Keyword Arguments

  • single_boundary=false: If true, then the boundary nodes are stored as a contiguous section. Otherwise, the boundary is split into four sections, in the order bottom, right, top, left.
  • delete_ghosts=false: If true, then the ghost triangles are deleted. Otherwise, they are kept.
  • IntegerType::Type{I}=Int: The type of the vertices.
  • EdgeType::Type{E}=NTuple{2,IntegerType}: The type of the edges.
  • TriangleType::Type{V}=NTuple{3,IntegerType}: The type of the triangles.
  • EdgesType::Type{Es}=Set{EdgeType}: The type of the edges container.
  • TrianglesType::Type{Ts}=Set{TriangleType}: The type of the triangles container.

Outputs

  • tri: The triangulation of the rectangle.