/
triangulation.jl
42 lines (40 loc) · 1.89 KB
/
triangulation.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
export triangulation, triangulation_indices
# Implementation of Cohen & Hickey algorithm for triangulation; see [CH79] and [BEK00].
#
# [CH79] Cohen, J., & Hickey, T. (1979). Two algorithms for determining volumes of convex polyhedra. Journal of the ACM (JACM), 26(3), 401-414.
# [BEK00] Büeler, B., Enge, A., & Fukuda, K. (2000). Exact volume computation for polytopes: a practical study. In Polytopes—combinatorics and computation (pp. 131-154). Birkhäuser, Basel.
# TODO parallelize: this is inherently parallelizable
function _triangulation(Δs, Δ, v_idx, h_idx, incident_idx, is_weak_adjacent)
isempty(v_idx) && return
v = first(v_idx)
Δ = push!(copy(Δ), v)
if isone(length(v_idx))
push!(Δs, Δ)
return
end
tail = true
for h in h_idx
if !(v in incident_idx[h])
tail = false
# The adjacency may be outside the current face under scrutiny but that's ok,
# it will simply end up calling `_triangulation` with an empty `v_idx`.
weak_adjacent = [hj for hj in h_idx if hj != h && is_weak_adjacent[(h, hj)]]
active = [point for point in v_idx if point in incident_idx[h]]
_triangulation(Δs, Δ, active, weak_adjacent, incident_idx, is_weak_adjacent)
end
end
end
function triangulation_indices(p::Polyhedron)
hasrays(p) && error("Triangulation only supported for polytope.")
v_idx = eachindex(points(p))
h_idx = eachindex(halfspaces(p))
Δ = eltype(v_idx)[]
Δs = typeof(Δ)[]
incident_idx = Dict(h => Set(incidentpointindices(p, h)) for h in h_idx)
is_weak_adjacent = Dict((hi, hj) => !isempty(incident_idx[hi] ∩ incident_idx[hj]) for hi in h_idx for hj in h_idx)
_triangulation(Δs, Δ, v_idx, h_idx, incident_idx, is_weak_adjacent)
return Δs
end
function triangulation(p::Polyhedron)
return map(Δ -> vrep(get.(p, Δ)), triangulation_indices(p))
end