Skip to content
This repository was archived by the owner on Nov 22, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/GeometryTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ include("typealias.jl")
include("simplices.jl")
include("faces.jl")
include("hyperrectangles.jl")
include("hyperellipse.jl")
include("hypersphere.jl")
include("hypercube.jl")
include("meshes.jl")
Expand All @@ -57,6 +58,7 @@ export AABB,
AbstractMesh,
AbstractSimplex,
AbstractDistanceField,
Ellipse,
Circle,
centered,
contains,
Expand Down Expand Up @@ -90,6 +92,7 @@ export AABB,
HomogenousMesh,
HyperRectangle,
HyperCube,
HyperEllipse,
HyperSphere,
intersects,
isinside,
Expand All @@ -116,6 +119,7 @@ export AABB,
SimpleMesh,
SimpleRectangle,
Simplex,
Ellipsoid,
Sphere,
TextureCoordinate,
Triangle,
Expand Down
45 changes: 45 additions & 0 deletions src/decompose.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ isdecomposable(::Type{T}, ::Type{HR}) where {T<:Face, HR<:SimpleRectangle} = tru
isdecomposable(::Type{T}, ::Type{HR}) where {T<:TextureCoordinate, HR<:SimpleRectangle} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:Normal, HR<:SimpleRectangle} = true

isdecomposable(::Type{T}, ::Type{HR}) where {T<:Point, HR <: HyperEllipse} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:Face, HR <: HyperEllipse} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:TextureCoordinate, HR <: HyperEllipse} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:Normal, HR <: HyperEllipse} = true

isdecomposable(::Type{T}, ::Type{HR}) where {T<:Point, HR <: HyperSphere} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:Face, HR <: HyperSphere} = true
isdecomposable(::Type{T}, ::Type{HR}) where {T<:TextureCoordinate, HR <: HyperSphere} = true
Expand Down Expand Up @@ -354,6 +359,21 @@ function decompose(::Type{T}, mesh::AbstractMesh) where T <: Colorant
end


function decompose(PT::Type{Point{3, T}}, s::Ellipse, n=64) where T
points2d = decompose(Point{2, T}, s, n)
map(x-> Point{3, T}(x[1], x[2], 0), points2d)
end

function decompose(PT::Type{Point{2,T}}, s::Ellipse, n=64) where T
rad = radius(s)
map(range(T(0), stop=T(2pi), length=n)) do fi
PT(
rad[1]*sin(fi + pi),
rad[2]*cos(fi + pi)
) + origin(s)
end
end


function decompose(PT::Type{Point{3, T}}, s::Circle, n=64) where T
points2d = decompose(Point{2, T}, s, n)
Expand All @@ -370,6 +390,31 @@ function decompose(PT::Type{Point{2,T}}, s::Circle, n=64) where T
end
end

function decompose(PT::Type{Point{N,T}}, s::Ellipsoid, n = 24) where {N,T}
θ = LinRange(0, pi, n); φ = LinRange(0, 2pi, n)
vec(map((θ, φ) for θ in θ, φ in φ) do (θ, φ,)
Point3f0(cos(φ)*sin(θ), sin(φ)*sin(θ), cos(θ)) .* Point{N,T}(s.r) + PT(s.center)
end)
end

function decompose(PT::Type{UV{T}}, s::Ellipsoid, n = 24) where T
ux = LinRange(0, 1, n)
vec([UV{Float32}(φ, θ) for θ in reverse(ux), φ in ux])
end

function decompose(::Type{FT}, s::Ellipsoid, n = 24) where FT <: Face
decompose(FT, SimpleRectangle(0, 0, 1, 1), (n, n))
end

function decompose(::Type{T}, s::Ellipsoid, n = 24) where T <: Normal
r² = radius(s).^2
θ = LinRange(0, pi, n); φ = LinRange(0, 2pi, n)
vec(map((θ, φ) for θ in θ, φ in φ) do (θ, φ,)
normalize(Point{3,Float32}(cos(φ)*sin(θ), sin(φ)*sin(θ), cos(θ)) ./ r²)
end)
end


function decompose(PT::Type{Point{N,T}}, s::Sphere, n = 24) where {N,T}
θ = LinRange(0, pi, n); φ = LinRange(0, 2pi, n)
vec(map((θ, φ) for θ in θ, φ in φ) do (θ, φ,)
Expand Down
16 changes: 16 additions & 0 deletions src/hyperellipse.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Ellipsoid(x...) = HyperEllipse(x...)

Ellipse(x...) = HyperEllipse(x...)

widths(c::HyperEllipse{N, T}) where {N, T} = Vec{N, T}(radius(c)*2)
radius(c::HyperEllipse) = c.r
origin(c::HyperEllipse) = c.center
minimum(c::HyperEllipse{N, T}) where {N, T} = Vec{N, T}(origin(c)) - radius(c)
maximum(c::HyperEllipse{N, T}) where {N, T} = Vec{N, T}(origin(c)) + radius(c)

_ellipseterm(p, c, r) = ((p - c)/r)^2
isinside(c::HyperEllipse{N,T}, p::Point{N,R}) where {N, T, R} = mapreduce(_ellipseterm, +, p, origin(c), radius(c)) ≤ 1
isinside(c::Ellipse, x::Real, y::Real) = isinside(c, Point(x, y))

centered(S::Type{HyperEllipse{N, T}}) where {N, T} = S(Vec{N,T}(0), Vec{N,T}(0.5))
centered(::Type{T}) where {T <: HyperEllipse} = centered(HyperEllipse{ndims_or(T, 3), eltype_or(T, Float32)})
1 change: 1 addition & 0 deletions src/hyperrectangles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ function isinside(rect::SimpleRectangle, x::Real, y::Real)
end

# TODO only have point in c and deprecate above methods
in(x::AbstractPoint{2}, c::Ellipse) = isinside(c, x...)
in(x::AbstractPoint{2}, c::Circle) = isinside(c, x...)
in(x::AbstractPoint{2}, c::SimpleRectangle) = isinside(c, x...)

Expand Down
10 changes: 10 additions & 0 deletions src/typealias.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ const GLQuad = Face{4, GLIndex}

const Cube{T} = HyperCube{3, T}

"""
An alias for a HyperEllipse of dimension 2. i.e. `Ellipse{T}` -> `HyperEllipse{2, T}`
"""
const Ellipse{T} = HyperEllipse{2, T}

"""
An alias for a HyperEllipse of dimension 3. i.e. `Ellipsoid{T}` -> `HyperEllipse{3, T}`
"""
const Ellipsoid{T} = HyperEllipse{3, T}

"""
An alias for a HyperSphere of dimension 2. i.e. `Circle{T}` -> `HyperSphere{2, T}`
"""
Expand Down
9 changes: 9 additions & 0 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ struct HyperCube{N, T} <: GeometryPrimitive{N, T}
width::T
end

"""
A `HyperEllipse` is a generalization of an ellipse into N-dimensions.
A `center` and radii, `r` must be specified.
"""
struct HyperEllipse{N, T} <: GeometryPrimitive{N, T}
center::Point{N, T}
r::Vec{N, T}
end


"""
A `HyperSphere` is a generalization of a sphere into N-dimensions.
Expand Down
27 changes: 27 additions & 0 deletions test/decompose.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,33 @@ end

end

@testset "HyperEllipse" begin
ellipsoid = Ellipsoid{Float32}(Point3f0(0), Vec3f0(1))

points = decompose(Point, ellipsoid, 3)
point_target = Point{3,Float32}[
[0.0, 0.0, 1.0], [1.0, 0.0, 6.12323e-17], [1.22465e-16, 0.0, -1.0],
[-0.0, 0.0, 1.0], [-1.0, 1.22465e-16, 6.12323e-17],
[-1.22465e-16, 1.49976e-32, -1.0], [0.0, -0.0, 1.0],
[1.0, -2.44929e-16, 6.12323e-17], [1.22465e-16,-2.99952e-32, -1.0]
]
@test points ≈ point_target

f = decompose(Face{3, Int}, ellipsoid, 3)
face_target = Face{3,Int64}[
[1, 2, 5], [1, 5, 4], [2, 3, 6], [2, 6, 5],
[4, 5, 8], [4, 8, 7], [5, 6, 9], [5, 9, 8]
]
@test f == face_target
ellipse = Ellipse(Point2f0(0), Vec2f0(1))
points = decompose(Point2f0, ellipse, 20)
@test length(points) == 20
# TODO: currently, no ellipse meshes
Copy link
Member Author

@yakir12 yakir12 Mar 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SimonDanisch I dunno how to implement src/primitives.jl#L28 for an Ellipse...

Copy link

@asinghvi17 asinghvi17 Mar 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to do the same thing, since the triangulation is the same either way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried adding

function (::Type{T})(c::Ellipse, n = 32) where T <: AbstractMesh

to primitives.jl but I don't understand why it isn't working. Honestly, my understanding here is really low, I'm basically copy pasting things that were implemented specifically for HyperSphere and adjusting them to an ellipse (so 2 radii, not one). Stumped, do you know what's missing?

# mesh = GLNormalMesh(ellipse, 32)
# # end-1, since we add a middle point for the mesh!
# @test decompose(Point2f0, mesh)[1:end-1] ≈ decompose(Point2f0, ellipse, 32)
end

@testset "HyperSphere" begin
sphere = Sphere{Float32}(Point3f0(0), 1f0)

Expand Down
36 changes: 36 additions & 0 deletions test/hyperellipse.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@testset "HyperEllipse" begin
@test Ellipsoid(Point(0,0,0), Vec(4, 3, 2)) == HyperEllipse{3,Int}(Point{3,Int}((0,0,0)),Vec{3,Int}((4,3,2)))
c = Ellipse(Point(0,0), Vec(1,2))
@test c == HyperEllipse(Point(0,0), Vec(1,2))
@test origin(c) == Point(0,0)
@test !( isinside(c, 1, 2) )
@test isinside(c, 0.5, 0.5)

centered_rect = centered(HyperEllipse)
@test centered_rect == HyperEllipse{3,Float32}(Point3f0(0), Vec3f0(0.5))
centered_rect = centered(HyperEllipse{2})
@test centered_rect == HyperEllipse{2,Float32}(Point2f0(0), Vec2f0(0.5))

centered_rect = centered(HyperEllipse{2, Float64})
@test centered_rect == HyperEllipse{2,Float64}(Point(0.,0.), Vec(0.5, 0.5))

centered_rect = centered(HyperEllipse{3, Float32})
@test centered_rect == HyperEllipse{3,Float32}(Point3f0(0), Vec3f0(0.5))

@test widths(centered_rect) == Vec3f0(1)
@test radius(centered_rect) == Vec3f0(0.5)
@test maximum(centered_rect) == Vec3f0(0.5f0)
@test minimum(centered_rect) == Vec3f0(-0.5f0)
s = Ellipsoid(Point3f0(0), Vec3f0(1))
f = decompose(Face{2, Int}, s, 3)
# TODO 54 linesegments for 3 facets is too much.
@test length(f) == 16

s = Ellipsoid(Point3f0(-1, 10, 5), Vec3f0(3))
ps = decompose(Point3f0, s)
bb = AABB(ps)
# The maximum radius doesn't get sampled in the ellipsoid mesh, hence the smaller widths
@test all(x-> x > 5.9 && x <= 6.0, widths(bb))
middle = (minimum(bb) .+ (widths(bb) ./ 2))
@test all(((x,y),)-> isapprox(x, y, atol = 0.05), zip((-1, 10, 5), middle))
end
8 changes: 8 additions & 0 deletions test/hyperrectangles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,14 @@ end
bb1 = HyperRectangle(x)
bb2 = HyperRectangle(v)
@test bb1 == bb2

s = Ellipsoid(Point3f0(0), Vec3f0(1,2,3))
f = decompose(Face{2, Int}, s, 3)
v = decompose(Point3f0, s, 3)
x = view(v, f)
bb1 = HyperRectangle(x)
bb2 = HyperRectangle(v)
@test bb1 == bb2
end

@testset "face-orientation" begin
Expand Down
5 changes: 5 additions & 0 deletions test/meshes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ end
@test length(vertices(m)) == 576
@test length(faces(m)) == 1058
@test length(normals(m)) == 576

m = GLNormalMesh(Ellipsoid(Point3f0(0),Vec3f0(1)))
@test length(vertices(m)) == 576
@test length(faces(m)) == 1058
@test length(normals(m)) == 576
end


Expand Down
5 changes: 5 additions & 0 deletions test/polygons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ end
triangles = polygon2faces(points)
@test !isempty(triangles)
@test points[1] ≈ points[end]

points = decompose(Point2f0, Ellipse(Point2f0(0), Vec2f0(1)))
triangles = polygon2faces(points)
@test !isempty(triangles)
@test points[1] ≈ points[end]
end

end