Skip to content
This repository was archived by the owner on Nov 22, 2023. It is now read-only.

Gjk #86

Merged
merged 4 commits into from
Jun 7, 2017
Merged

Gjk #86

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
52 changes: 25 additions & 27 deletions src/convexhulls.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


Base.eltype(fg::AFG) = eltype(typeof(fg))
Base.length(fg::AFG) = length(vertices(fg))
nvertices(fg::AFG) = length(fg)
Expand All @@ -19,7 +17,7 @@ Base.deleteat!(c::AbstractFlexibleGeometry, i) = (deleteat!(vertices(c), i); c)
Base.copy{FG <: AFG}(fl::FG) = FG(copy(vertices(fl)))
push(fl::AFG, pt) = push!(copy(fl), pt)

vertices{T}(x::AbstractFlexibleGeometry{T}) = x._
vertices(x::AbstractFlexibleGeometry) = x.vertices
vertices(s::Simplex) = Tuple(s)

standard_cube_vertices(::Type{Val{1}}) = [Vec(0), Vec(1)]
Expand All @@ -41,37 +39,37 @@ end
_combine_vcat(vert_1, vert_last)
end
end
@generated function vertices_rettype(r::HyperRectangle)
N = ndims(r)
T = eltype(r)
RET = NTuple{(2^N), Vec{N,T}}
:($RET)
end

@generated function vertices{N,T}(r::HyperRectangle{N,T})
ret_type = NTuple{(2^N), Vec{N,T}}
quote
o = origin(r)
v = widths(r)
f(sv) = o + sv .* v
tuple(map(f, standard_cube_vertices(Val{N}))...)::$ret_type
end
function vertices(r::HyperRectangle)
N = ndims(r)
ret_type = vertices_rettype(r)
o = origin(r)
v = widths(r)
f(sv) = o + sv .* v
tuple(map(f, standard_cube_vertices(Val{N}))...)::ret_type
end

vertices(c::HyperCube) = vertices(convert(HyperRectangle, c))
#vertices(s::AbstractConvexHull) = Tuple(s)

vertexmat{M, T}(s::Simplex{M, T}) = Mat{length(T)}(vcat(vertices(s)...))
vertexmat{M}(s::AbstractGeometry{M}) = Mat{M}(vcat(vertices(s)...))

function vertexmat(s::AbstractFlexibleGeometry)
verts = vcat(vertices(s)...)
M, N = spacedim(s), nvertices(s)
Mat{M, N}(verts)
end
vertexmat(s) = hcat(vertices(s)...)
vertexmatrix(s::AbstractConvexHull) = Matrix(vertexmat(s))::Matrix{numtype(s)}

convert{S <: Simplex}(::Type{S}, fs::FlexibleSimplex) = S(tuple(vertices(fs)...))
convert{F <: AFG}(::Type{F}, s::Simplex) = F(collect(vertices(s)))
convert{FS <: FlexibleSimplex}(::Type{FS}, f::FS) = f
convert{FG <: AFG, FS <: FlexibleSimplex}(::Type{FG}, f::FS) = FG(vertices(f))
convert{R <: HyperRectangle}(::Type{R}, c::HyperCube) = R(origin(c), widths(c))
convert{F <: FlexibleConvexHull}(::Type{F}, s::Simplex) = F(collect(vertices(s)))
convert{F <: FlexibleConvexHull}(::Type{F}, c) = F(collect(vertices(c)))
convert(S::Type{<: Simplex}, fs::FlexibleSimplex) = S(tuple(vertices(fs)...))
convert(F::Type{<: AFG}, s::Simplex) = F(collect(vertices(s)))
convert(FG::Type{<: AFG}, f::FlexibleSimplex) = FG(vertices(f))
convert(R::Type{<: HyperRectangle}, c::HyperCube) = R(origin(c), widths(c))
convert(F::Type{<:FlexibleConvexHull}, s::Simplex) = F(collect(vertices(s)))
convert(F::Type{<:FlexibleConvexHull}, s::FlexibleSimplex) = F(vertices(s))
convert(F::Type{FlexibleConvexHull}, c::FlexibleConvexHull) = c
convert(F::Type{<:FlexibleConvexHull}, c::FlexibleConvexHull) = F(vertices(c))
convert(::Type{F}, x::F) where {F <: FlexibleConvexHull} = x
convert(F::Type{<:FlexibleConvexHull}, c) = F(collect(vertices(c)))

function Base.isapprox(s1::AbstractConvexHull, s2::AbstractConvexHull;kw...)
isapprox(vertexmat(s1), vertexmat(s2); kw...)
Expand Down
30 changes: 22 additions & 8 deletions src/gjk.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,34 @@

using Base.Cartesian

type_immutable{T, n}(::Type{FlexibleSimplex{T}}, ::Type{Val{n}}) = Simplex{n,T}
type_immutable(::Type{FlexibleSimplex{T}}, ::Type{Val{n}}) where {T,n}= Simplex{n,T}
type_immutable(s, v=Val{length(s)}) = type_immutable(typeof(s), v)
make_immutable(s, v=Val{length(s)}) = convert(type_immutable(s, v), s)

#@generated function with_immutable{n}(f, s, max_depth::Type{Val{n}}=Val{10})
# quote
# l = length(s)
# @nif $n d->(d == l) d->(f(make_immutable(s, Val{d}))) d->error("length(s) = $s < max_depth = {n}")
# end
#end

"""
with_immutable{n}(f, s, max_depth::Type{Val{n}}=Val{10})

Apply function f to immutable variant of s without introducing a type instability.
"""
@generated function with_immutable{n}(f, s, max_depth::Type{Val{n}}=Val{10})
quote
l = length(s)
@nif $n d->(d == l) d->(f(make_immutable(s, Val{d}))) d->error("length(s) = $s < max_depth = {n}")
function with_immutable(f, s)
l = length(s)
if l == 1
f(make_immutable(s, Val{1}))
elseif l == 2
f(make_immutable(s, Val{2}))
elseif l == 3
f(make_immutable(s, Val{3}))
elseif l == 4
f(make_immutable(s, Val{4}))
else
f(make_immutable(s, Val{l}))
end
end

Expand Down Expand Up @@ -80,7 +95,7 @@ end
support_vector(ch, v) = support_vector_max(ch,v)[1]

"""
s = shrink!(s::FlexibleSimplex, pt, atol=0.)
s = shrink!(s::FlexibleSimplex, pt, atol=0.)

Drop as many vertices from s as possible, while keeping pt inside.
"""
Expand All @@ -96,7 +111,7 @@ end


"""
pt_best, dist = gjk0(c)
pt_best, dist = gjk0(c)

Compute the distance of a convex set to the origin using gjk algorithm. If c
is not convex, the algorithm may or may not yield an optimal solution.
Expand Down Expand Up @@ -132,7 +147,6 @@ function gjk0(c,
push!(sim, wk)
pt_best::T, sqd = proj_sqdist(zero_point, sim)
sqd == 0 && return pt_best, norm(pt_best)
#@show weights(pt_best, sim)
shrink!(sim, pt_best, atol)
end
end
Expand Down
10 changes: 5 additions & 5 deletions src/simplices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ simplex_face(s::Simplex, i::Int) = Simplex(deleteat(vertices(s), i))
"""
proj_sqdist{T}(pt::T, s::LineSegment{T}, best_sqd=eltype(T)(Inf))
"""
function proj_sqdist{T}(pt::T, s::LineSegment{T}, best_sqd=eltype(T)(Inf))
function proj_sqdist{T}(pt::T, s::LineSegment{T}, best_sqd=Inf)
v0, v1 = vertices(s)
pt = pt - v0
v = v1 - v0
Expand Down Expand Up @@ -143,7 +143,7 @@ distance is greater then best_sqd, the behaviour of pt_proj is not defined.
distance is greater then best_sqd is returned instead.

"""
function proj_sqdist{nv,T}(pt::T, s::Simplex{nv,T}, best_sqd = eltype(T)(Inf))
function proj_sqdist{nv,T}(pt::T, s::Simplex{nv,T}, best_sqd=Inf)
w = weights(pt, s)
best_proj = Vec(vertexmat(s) * w)
# at this point best_proj lies in the subspace spanned by s,
Expand All @@ -167,17 +167,17 @@ function proj_sqdist{nv,T}(pt::T, s::Simplex{nv,T}, best_sqd = eltype(T)(Inf))
end
end

sqdist(pt, s, best = Inf) = proj_sqdist(pt, s, best)[2]
sqdist(pt, s, best=Inf) = proj_sqdist(pt, s, best)[2]

"""
proj_sqdist(p::Vec, q::Vec, best_sqd=eltype(p)(Inf))
"""
@inline function proj_sqdist(p::Vec, q::Vec, best_sqd = eltype(p)(Inf))
@inline function proj_sqdist(p::Vec, q::Vec, best_sqd=Inf)
q, min(best_sqd, sqnorm(p-q))
end
"""
proj_sqdist{T}(pt::T, s::Simplex{1, T}, best_sqd=eltype(T)(Inf))
"""
@inline function proj_sqdist{T}(pt::T, s::Simplex{1, T}, best_sqd=eltype(T)(Inf))
@inline function proj_sqdist{T}(pt::T, s::Simplex{1, T}, best_sqd=Inf)
proj_sqdist(pt, translation(s), best_sqd)
end
4 changes: 2 additions & 2 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ FlexibleConvexHull{T}
Represents the convex hull of finitely many points. The number of points is not fixed.
"""
immutable FlexibleConvexHull{T} <: AFG{T}
_::Vector{T}
vertices::Vector{T}
end

"""
Expand All @@ -200,7 +200,7 @@ FlexibleSimplex{T}
Represents a Simplex whos number of vertices is not fixed.
"""
immutable FlexibleSimplex{T} <: AFG{T}
_::Vector{T}
vertices::Vector{T}
end

"""
Expand Down
1 change: 0 additions & 1 deletion test/REQUIRE

This file was deleted.

52 changes: 25 additions & 27 deletions test/gjk.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import GeometryTypes: ⊖, support_vector_max
import GeometryTypes: gjk0
import GeometryTypes: type_immutable, with_immutable, make_immutable
import GeometryTypes: gjk0, ⊖, support_vector_max

@testset "gjk" begin

Expand All @@ -11,76 +10,75 @@ import GeometryTypes: type_immutable, with_immutable, make_immutable
@test gjk(c1,c2) ≈5
@test min_euclidean(c1,c2) ≈5

c1 = Simplex(Vec(-1.,0,0))
c2 = Simplex(Vec(4.,0,0))
c1 = Simplex(Vec(-1.,0.,0.))
c2 = Simplex(Vec(4.,0.,0.))
@test gjk(c1,c2) ≈5
@test min_euclidean(c1,c2) ≈5

c1 = FlexibleConvexHull([Vec(0.,0), Vec(0.,1), Vec(1.,0),Vec(1.,1)])
c1 = FlexibleConvexHull([Vec(0.,0.), Vec(0.,1.), Vec(1.,0.),Vec(1.,1.)])
c2 = Simplex(Vec(4.,0.5))
@test gjk(c1, c2) ≈3
@test min_euclidean(c1,c2) ≈3
@test gjk(c1, c2) ≈ 3
@test min_euclidean(c1,c2) ≈ 3

pt1 = Vec(1,2,3.)
pt2 = Vec(3,4,5.)
pt1 = Vec(1.,2.,3.)
pt2 = Vec(3.,4.,5.)
@test gjk(pt1, pt2) ≈norm(pt1-pt2)
@test min_euclidean(pt1, pt2) ≈norm(pt1-pt2)
end

@testset "gjk intersecting lines" begin
c1 = Simplex(Vec(1,1.), Vec(1, 2.))
c1 = Simplex(Vec(1.,1.), Vec(1., 2.))
@test gjk(c1, c1) == 0.
@test min_euclidean(c1,c1) == 0.

c2 = Simplex(Vec(1,1.), Vec(10, 2.))
c2 = Simplex(Vec(1.,1.), Vec(10., 2.))
@test gjk(c1, c2) == 0.
@test min_euclidean(c1,c2) == 0.

c3 = Simplex(Vec(0, 1.), Vec(2,2.))
c3 = Simplex(Vec(0., 1.), Vec(2.,2.))
md = vertices(c1 ⊖ c3)
@test md == [Vec(1.0,0.0),Vec(-1.0,-1.0),Vec(1.0,1.0),Vec(-1.0,0.0)]
@test gjk0(FlexibleConvexHull(md)) == (Vec(0, 0.), 0.)
@test gjk0(FlexibleConvexHull(md)) == (Vec(0., 0.), 0.)
@test gjk(c1, c3) == 0.
@test min_euclidean(c1,c3) == 0.

end

@testset "Cube" begin
c = HyperCube(Vec(0.5,0.5,0.5), 1.)
@test min_euclidean(Vec(2,2,2.), c) ≈ gjk(Vec(2,2,2.), c) ≈ √(3/4)
@test min_euclidean(Vec(2.,2.,2.), c) ≈ gjk(Vec(2.,2.,2.), c) ≈ √(3/4)

s = Simplex(Vec(1, 0.5, 0.5), Vec(1,2,3.))
s = Simplex(Vec(1., 0.5, 0.5), Vec(1.,2.,3.))
@test 0 <= min_euclidean(s, c) <= 1e-14
@test 0 <= gjk(s, c) <= 1e-14

s = Simplex(Vec(2,2,2.), Vec(2,3,2.), Vec(2,2,7.), Vec(3,4,5.))
s = Simplex(Vec(2.,2.,2.), Vec(2.,3.,2.), Vec(2.,2.,7.), Vec(3.,4.,5.))
@test min_euclidean(s,c) ≈ gjk(s, c) ≈ √(3/4)
end

end

@testset "support_vector_max" begin
r = HyperRectangle(Vec(-0.5, -1.), Vec(1., 2.))
@test support_vector_max(r, Vec(1,0.)) == (Vec(0.5,-1.), 0.5)
@test support_vector_max(r, Vec(2,0.)) == (Vec(0.5,-1.), 1.)
@test support_vector_max(r, Vec(-1,0.)) == (Vec(-0.5,-1.), 0.5)
@test support_vector_max(r, Vec(0, 1.)) == (Vec(-0.5,1.), 1.)
@test support_vector_max(r, Vec(1, 1.)) == (Vec(0.5,1.), 1.5)
@test support_vector_max(FlexibleConvexHull(r), Vec(1, 1.)) == (Vec(0.5,1.), 1.5)

c1 = Simplex(Vec(1,1.), Vec(1, 2.))
c3 = Simplex(Vec(0, 1.), Vec(2,2.))
@test support_vector_max(r, Vec(1.,0.)) == (Vec(0.5,-1.), 0.5)
@test support_vector_max(r, Vec(2.,0.)) == (Vec(0.5,-1.), 1.)
@test support_vector_max(r, Vec(-1.,0.)) == (Vec(-0.5,-1.), 0.5)
@test support_vector_max(r, Vec(0., 1.)) == (Vec(-0.5,1.), 1.)
@test support_vector_max(r, Vec(1., 1.)) == (Vec(0.5,1.), 1.5)
@test support_vector_max(FlexibleConvexHull(r), Vec(1., 1.)) == (Vec(0.5,1.), 1.5)

c1 = Simplex(Vec(1.,1.), Vec(1., 2.))
c3 = Simplex(Vec(0., 1.), Vec(2.,2.))
md = c1 ⊖ c3
fh = FlexibleConvexHull(md)
for v in [Vec(1,0.), Vec(12,-10.), Vec(0,-1.), Vec(1,1.)]
for v in [Vec(1.,0.), Vec(12.,-10.), Vec(0.,-1.), Vec(1.,1.)]
v_md, s_md = support_vector_max(md, v)
v_fh, s_fh = support_vector_max(fh, v)
@test s_md ≈ s_fh
@test v_md ≈ v_fh
end
end


@testset "make immutable" begin
T = Vec{2, Float64}
n = 3
Expand Down
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Base.Test.@inferred


@testset "GeometryTypes" begin
include("convexhulls.jl")
include("polygons.jl")
include("hyperrectangles.jl")
include("faces.jl")
Expand All @@ -15,9 +16,8 @@ import Base.Test.@inferred
include("hypersphere.jl")
include("typeutils.jl")
include("simplices.jl")
include("gjk.jl")
include("lines.jl")
include("polygons.jl")
#include("convexhulls.jl")
#include("gjk.jl")
include("cylinder.jl")
end