This repository has been archived by the owner on Mar 8, 2023. It is now read-only.
/
geometry.jl
61 lines (51 loc) · 1.78 KB
/
geometry.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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export
Unconstrained,
Polygonal,
nextboundary
abstract type Domain end
"""
Unconstrained
Signature of domains without boundaries.
"""
struct Unconstrained <: Domain end
"""
Polygonal
Encapsulate a domain with polygonal boundaries. The boundaries are defined with
the normals to the facets and the intercepts of the corresponding hyperplanes.
"""
struct Polygonal <: Domain
normals::Matrix{Real} # dim CxD where C=#constraints, D=#features
intercepts::Vector{Real} # dim C
end
# -----------------------------------------------------------------------------
"""
nextboundary(ud::Unconstrained, x, v)
Return (NaN, NaN) corresponding to the unconstrained case.
"""
function nextboundary(ud::Unconstrained,
x::Vector{<:Real}, v::Vector{<:Real})
return (NaN, NaN)
end
"""
nextboundary(pd::Polygonal, x, v)
Return the time of next boundary hit along the current trajectory when the
domain is polygonal and return the normal of the corresponding boundary.
The current point is `x` and the velocity `v`.
"""
function nextboundary(pd::Polygonal,
x::Vector{<:Real}, v::Vector{<:Real})
# hitting time along trajectory (x+tv) for a boundary (normal,intercept) is
# t = intercept/(normal dot v) - (x dot normal)/(normal dot v)
nsv = pd.normals * v
hits = (pd.intercepts - pd.normals * x) ./ nsv
# hard threshold times with nsv ~ 0 (near-parallel case),
# remove negative times and times ~ 0 (for numerical stability)
mask = map(|, abs.(nsv) .< 1e-10, hits .< 1e-10)
for (i, e) ∈ enumerate(mask)
e && (hits[i] = Inf)
end
# get time of hit + index of corresponding boundary
(t_hit, j) = findmin(hits)
# return time of hit + normal vector to boundary
(t_hit, pd.normals[j, :])
end