Skip to content

Commit 7890824

Browse files
authored
Upgrade to AdaptivePredicates 1.2 (#185)
1 parent 6f24f16 commit 7890824

22 files changed

+535
-283
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 1.4.0
4+
5+
- Updated to AdaptivePredicates.jl v1.2, now allowing caches to be passed to the predicates involving `incircle` and `orient3`. These are only useful when using the `AdaptiveKernel()` kernel. Outside of triangulating, these caches are not passed by default, but can be provided. The functions `get_incircle_cache` and `get_orient3_cache` can be used for this purpose on a triangulation (without a triangulation, refer to AdaptivePredicate.jl's `incircleadapt_cache` and `orient3adapt_cache`). See [#185](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/185).
6+
37
## 1.3.1
48

59
- Fix an issue with a weighted triangulation where the lifted points' convex hull was entirely coplanar. See [#184](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/184)

Project.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "DelaunayTriangulation"
22
uuid = "927a84f5-c5f4-47a5-9785-b46e178433df"
33
authors = ["Daniel VandenHeuvel <[email protected]>"]
4-
version = "1.3.1"
4+
version = "1.4.0"
55

66
[deps]
77
AdaptivePredicates = "35492f91-a3bd-45ad-95db-fcad7dcfedb7"
@@ -10,7 +10,7 @@ ExactPredicates = "429591f6-91af-11e9-00e2-59fbe8cec110"
1010
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1111

1212
[compat]
13-
AdaptivePredicates = "1"
13+
AdaptivePredicates = "1.2"
1414
EnumX = "1.0"
1515
ExactPredicates = "2.2"
1616
Random = "1"

docs/src/extended/utils.md

+4
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ DefaultAdjacentValue
3333
GhostVertex
3434
ε
3535
36+
fix_orient3_cache
37+
fix_incircle_cache
38+
validate_orient3_cache
39+
validate_incircle_cache
3640
```

src/DelaunayTriangulation.jl

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import EnumX
2525
import Random
2626

2727
abstract type AbstractPredicateKernel end # needs to be defined early for use in data_structures.jl
28+
const PredicateCacheType = Union{Nothing, <:Tuple}
2829

2930
include("data_structures.jl")
3031
include("predicates.jl")

src/algorithms/point_location/brute_force.jl

+9-3
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,22 @@ function brute_force_search(tri::Triangulation, q; itr = each_triangle(tri), pre
3838
end
3939

4040
"""
41-
brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel=AdaptiveKernel()) -> Triangle
41+
brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel=AdaptiveKernel(); cache = nothing) -> Triangle
4242
4343
Searches for a triangle in `tri` containing the vertex `i` in its circumcircle using brute force. If
4444
`tri` is a weighted Delaunay triangulation, the triangle returned instead has the lifted vertex `i`
4545
below its witness plane. If no such triangle exists, `($∅, $∅, $∅)` is returned. You can control
4646
the method used for computing predicates via the `predicates` argument.
47+
48+
The `cache` argument is passed to [`point_position_relative_to_circumcircle`] and should be one of
49+
- `nothing`: No cache is used.
50+
- `get_incircle_cache(tri)`: The cache stored inside `tri`.
51+
- `AdaptivePredicates.incircleadapt_cache(number_type(tri))`: Compute a new cache.
52+
The cache is only needed if an `AdaptiveKernel()` is used.
4753
"""
48-
function brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel = AdaptiveKernel())
54+
function brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel = AdaptiveKernel(); cache::PredicateCacheType = nothing)
4955
for V in each_triangle(tri)
50-
cert = point_position_relative_to_circumcircle(predicates, tri, V, i)
56+
cert = point_position_relative_to_circumcircle(predicates, tri, V, i; cache)
5157
!is_outside(cert) && return V
5258
end
5359
tri_type = triangle_type(tri)

src/algorithms/triangulation/basic_operations/add_point.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function add_point!(
6767
end
6868
q = get_point(tri, new_point)
6969
if is_weighted(tri)
70-
cert = point_position_relative_to_circumcircle(predicates, tri, V, new_point) # redirects to point_position_relative_to_witness_plane
70+
cert = point_position_relative_to_circumcircle(predicates, tri, V, new_point; cache = get_orient3_cache(tri)) # redirects to point_position_relative_to_witness_plane
7171
is_outside(cert) && return V # If the point is submerged, then we don't add it
7272
end
7373
flag = point_position_relative_to_triangle(predicates, tri, V, q)

src/algorithms/triangulation/basic_operations/legalise_edge.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ There is no output, as `tri` is updated in-place.
2727
so that at a triangle that might have appeared in both will only appear in one.
2828
"""
2929
function legalise_edge!(tri::Triangulation, i, j, r, store_event_history = Val(false), event_history = nothing; predicates::AbstractPredicateKernel = AdaptiveKernel())
30-
cert = is_legal(predicates, tri, i, j)
30+
cert = is_legal(predicates, tri, i, j; cache = get_incircle_cache(tri))
3131
if is_illegal(cert)
3232
e = get_adjacent(tri, j, i)
3333
flip_edge!(tri, i, j, e, r, store_event_history, event_history)

src/algorithms/triangulation/constrained_triangulation.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ function add_point_cavity_cdt!(tri::Triangulation, u, v, w, marked_vertices, pre
652652
insert_flag = true
653653
else
654654
p, q, r, s = get_point(tri, w, v, x, u) # Don't want to deal with boundary handling here
655-
incircle_test = point_position_relative_to_circle(predicates, p, q, r, s)
655+
incircle_test = point_position_relative_to_circle(predicates, p, q, r, s; cache = get_incircle_cache(tri))
656656
orient_test = triangle_orientation(predicates, tri, u, v, w)
657657
insert_flag = !is_inside(incircle_test) && is_positively_oriented(orient_test)
658658
end

src/algorithms/triangulation/triangulate_convex.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ to make.
121121
"""
122122
function add_point_convex_triangulation!(tri::Triangulation, u, v, w, S, predicates::AbstractPredicateKernel = AdaptiveKernel())
123123
x = get_adjacent(tri, w, v)
124-
if edge_exists(x) && is_inside(point_position_relative_to_circumcircle(predicates, tri, u, v, w, x))
124+
if edge_exists(x) && is_inside(point_position_relative_to_circumcircle(predicates, tri, u, v, w, x; cache = get_incircle_cache(tri)))
125125
# uvw and wvx are not Delaunay
126126
delete_triangle!(tri, w, v, x; protect_boundary = true, update_ghost_edges = false)
127127
add_point_convex_triangulation!(tri, u, v, x, S, predicates)

src/algorithms/triangulation/unconstrained_triangulation.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function add_point_bowyer_watson!(tri::Triangulation, new_point, initial_search_
153153
q = get_point(tri, _new_point)
154154
V = find_triangle(tri, q; predicates, m = nothing, point_indices = nothing, try_points = nothing, k = initial_search_point, rng)
155155
if is_weighted(tri)
156-
cert = point_position_relative_to_circumcircle(predicates, tri, V, _new_point) # redirects to point_position_relative_to_witness_plane
156+
cert = point_position_relative_to_circumcircle(predicates, tri, V, _new_point; cache = get_orient3_cache(tri)) # redirects to point_position_relative_to_witness_plane
157157
is_outside(cert) && return V # If the point is submerged, then we don't add it
158158
end
159159
flag = point_position_relative_to_triangle(predicates, tri, V, q)
@@ -298,9 +298,9 @@ Determines whether to enter the cavity in `tri` through the edge `(i, j)` when i
298298
function enter_cavity(tri::Triangulation, r, i, j, ℓ, predicates::AbstractPredicateKernel = AdaptiveKernel())
299299
contains_segment(tri, i, j) && return false
300300
if is_ghost_vertex(ℓ)
301-
cert = point_position_relative_to_circumcircle(tri, j, i, ℓ, r)
301+
cert = point_position_relative_to_circumcircle(predicates, tri, j, i, ℓ, r; cache = get_incircle_cache(tri))
302302
else
303-
cert = point_position_relative_to_circumcircle(tri, r, i, j, ℓ)
303+
cert = point_position_relative_to_circumcircle(predicates, tri, r, i, j, ℓ; cache = get_incircle_cache(tri))
304304
end
305305
return is_weighted(tri) ? !is_outside(cert) : is_inside(cert)
306306
end

src/data_structures/triangulation/methods/weights.jl

+26-10
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,24 @@ function get_power_distance(tri::Triangulation, i, j)
9898
end
9999

100100
""""
101-
get_distance_to_witness_plane(tri::Triangulation, i, V) -> Number
101+
get_distance_to_witness_plane([kernel::AbstractPredicateKernel = AdaptiveKernel(), ] tri::Triangulation, i, V; cache = nothing) -> Number
102102
103103
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
104104
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`
105105
is on its solid edge, then the distance returned is the distance associated with the solid triangle adjoining `V`.
106106
107107
In general, the distance is positive if the lifted vertex is above the witness plane, negative if it is below,
108108
and zero if it is on the plane.
109+
110+
The `kernel` argument determines how this result is computed, and should be
111+
one of [`ExactKernel`](@ref), [`FastKernel`](@ref), and [`AdaptiveKernel`](@ref) (the default).
112+
See the documentation for more information about these choices.
113+
114+
The `cache` keyword argument is passed to [`point_position_relative_to_circumcircle`]. Please see the documentation for that function for more information.
109115
110116
See also [`point_position_relative_to_witness_plane`](@ref) and [`get_distance_to_plane`](@ref).
111117
"""
112-
function get_distance_to_witness_plane(tri::Triangulation, i, V)
118+
function get_distance_to_witness_plane(kernel::AbstractPredicateKernel, tri::Triangulation, i, V; cache::PredicateCacheType = nothing)
113119
if !is_ghost_triangle(V)
114120
u, v, w = triangle_vertices(V)
115121
p⁺ = get_lifted_point(tri, u)
@@ -118,17 +124,19 @@ function get_distance_to_witness_plane(tri::Triangulation, i, V)
118124
s⁺ = get_lifted_point(tri, i)
119125
return get_distance_to_plane(p⁺, q⁺, r⁺, s⁺)
120126
else
121-
cert = point_position_relative_to_circumcircle(tri, V, i)
127+
cert = point_position_relative_to_circumcircle(kernel, tri, V, i; cache)
122128
if is_inside(cert)
123129
return -Inf
124130
elseif is_outside(cert)
125131
return Inf
126132
else # is_on(cert)
127133
V′ = replace_ghost_triangle_with_boundary_triangle(tri, V)
128-
return get_distance_to_witness_plane(tri, i, V′)
134+
return get_distance_to_witness_plane(kernel, tri, i, V′; cache)
129135
end
130136
end
131137
end
138+
get_distance_to_witness_plane(tri::Triangulation, i, V; cache::PredicateCacheType = nothing) = get_distance_to_witness_plane(AdaptiveKernel(), tri, i, V; cache)
139+
132140

133141
"""
134142
get_weighted_nearest_neighbour(tri::Triangulation, i, j = rand(each_solid_vertex(tri))) -> Vertex
@@ -164,24 +172,32 @@ function _get_weighted_nearest_neighbour(tri, i, j)
164172
end
165173

166174
@doc """
167-
is_submerged(tri::Triangulation, i) -> Bool
168-
is_submerged(tri::Triangulation, i, V) -> Bool
175+
is_submerged([kernel::AbstractPredicateKernel = AdaptiveKernel(), ] tri::Triangulation, i; cache = nothing) -> Bool
176+
is_submerged([kernel::AbstractPredicateKernel = AdaptiveKernel(), ] tri::Triangulation, i, V; cache = nothing) -> Bool
169177
170178
Returns `true` if the vertex `i` is submerged in `tri` and `false` otherwise. In the
171179
second method, `V` is a triangle containing `tri`.
180+
181+
The `kernel` argument determines how this result is computed, and should be
182+
one of [`ExactKernel`](@ref), [`FastKernel`](@ref), and [`AdaptiveKernel`](@ref) (the default).
183+
See the documentation for more information about these choices.
184+
185+
The `cache` keyword argument is passed to [`point_position_relative_to_circumcircle`]. Please see the documentation for that function for more information.
172186
"""
173187
is_submerged
174-
function is_submerged(tri::Triangulation, i)
188+
function is_submerged(kernel::AbstractPredicateKernel, tri::Triangulation, i; cache::PredicateCacheType = nothing)
175189
# A source that mentions that testing if `i` is submerged only needs to consider the triangle that contains it
176190
# is given in https://otik.uk.zcu.cz/bitstream/11025/21574/1/Zemek.pdf on p.17.
177191
# (If the link dies, it is the PhD thesis of Michal Zemek, "Regular Triangulation in 3D and Its Applications".)
178192
is_ghost_vertex(i) && return false
179193
q = get_point(tri, i)
180194
V = find_triangle(tri, q)
181-
return is_submerged(tri, i, V)
195+
return is_submerged(kernel, tri, i, V; cache)
182196
end
183-
function is_submerged(tri::Triangulation, i, V)
197+
function is_submerged(kernel::AbstractPredicateKernel, tri::Triangulation, i, V; cache::PredicateCacheType = nothing)
184198
is_ghost_vertex(i) && return false
185-
cert = point_position_relative_to_circumcircle(tri, V, i)
199+
cert = point_position_relative_to_circumcircle(kernel, tri, V, i; cache)
186200
return is_outside(cert)
187201
end
202+
is_submerged(tri::Triangulation, i; cache::PredicateCacheType = nothing) = is_submerged(AdaptiveKernel(), tri, i; cache)
203+
is_submerged(tri::Triangulation, i, V; cache::PredicateCacheType = nothing) = is_submerged(AdaptiveKernel(), tri, i, V; cache)

0 commit comments

Comments
 (0)