-
Notifications
You must be signed in to change notification settings - Fork 78
/
paraboloidsurface.jl
107 lines (77 loc) · 3.13 KB
/
paraboloidsurface.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------
"""
ParaboloidSurface(apex, radius, focallength)
A paraboloid surface embedded in R³ and extending up to a distance
`radius` from its focal axis, which is aligned along the z direction
and passes through `apex` (the apex of the paraboloid). The equation
of the paraboloid is the following:
```math
f(x, y) = \\frac{(x - x_0)^2 + (y - y_0)^2}{4f} + z_0\\qquad\\text{for } x^2 + y^2 < r^2,
```
where ``(x_0, y_0, z_0)`` is the apex of the parabola, ``f`` is the
focal length, and ``r`` is the clip radius.
ParaboloidSurface(apex, radius)
This creates a paraboloid surface with focal length equal to 1.
ParaboloidSurface(apex)
This creates a paraboloid surface with focal length equal to 1 and a rim with unit
radius.
ParaboloidSurface()
Same as above, but here the apex is at `Apex(0, 0, 0)`.
See also <https://en.wikipedia.org/wiki/Paraboloid>.
"""
struct ParaboloidSurface{T} <: Primitive{3,T}
apex::Point{3,T}
radius::T
focallength::T
end
ParaboloidSurface(apex::Point{3,T}, radius, focallength) where {T} = ParaboloidSurface{T}(apex, radius, focallength)
ParaboloidSurface(apex::Tuple, radius, focallength) = ParaboloidSurface(Point(apex), radius, focallength)
ParaboloidSurface(apex::Point{3,T}, radius) where {T} = ParaboloidSurface(apex, T(radius), T(1))
ParaboloidSurface(apex::Tuple, radius) = ParaboloidSurface(Point(apex), radius)
ParaboloidSurface(apex::Point{3,T}) where {T} = ParaboloidSurface(apex, T(1))
ParaboloidSurface(apex::Tuple) = ParaboloidSurface(Point(apex))
ParaboloidSurface() = ParaboloidSurface(Point(0, 0, 0))
paramdim(::Type{<:ParaboloidSurface}) = 2
"""
focallength(p::ParaboloidSurface)
Return the focal length of the paraboloid.
"""
focallength(p::ParaboloidSurface) = p.focallength
"""
focallength(p::ParaboloidSurface)
Return the radius of the rim of the paraboloid.
"""
radius(p::ParaboloidSurface) = p.radius
"""
apex(p::ParaboloidSurface)
Return the apex of the paraboloid.
"""
apex(p::ParaboloidSurface) = p.apex
"""
axis(p::ParaboloidSurface)
Return the focal axis, connecting the focus with the apex of the paraboloid.
The axis is always aligned with the z direction.
"""
axis(p::ParaboloidSurface{T}) where {T} = Line(p.apex, p.apex + Vec(T(0), T(0), p.focallength))
Base.isapprox(p₁::ParaboloidSurface{T}, p₂::ParaboloidSurface{T}) where {T} =
p₁.apex ≈ p₂.apex &&
isapprox(p₁.focallength, p₂.focallength, atol=atol(T)) &&
isapprox(p₁.radius, p₂.radius, atol=atol(T))
function (p::ParaboloidSurface{T})(ρ, θ) where {T}
if (ρ < 0 || ρ > 1)
throw(DomainError((ρ, θ), "p(ρ, θ) is not defined for ρ outside [0, 1]."))
end
c = p.apex
r = p.radius
f = p.focallength
l = T(ρ) * r
sθ, cθ = sincospi(2 * T(θ))
x = l * cθ
y = l * sθ
z = (x^2 + y^2) / 4f
c + Vec(x, y, z)
end
Random.rand(rng::Random.AbstractRNG, ::Random.SamplerType{ParaboloidSurface{T}}) where {T} =
ParaboloidSurface(rand(rng, Point{3,T}), rand(rng, T), rand(rng, T))