diff --git a/README.md b/README.md index ebd5275..f5cccac 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ using BoundingSphere pts = [randn(3) for _ in 1:10] -center, radius = miniball(pts) +center, radius = boundingsphere(pts) using StaticArrays pts = [@SVector(randn(3)) for _ in 1:10] # use static arrays for performance algorithm = Ritter() # fast but inaccurate -center, radius = miniball(pts, algorithm) # customize algorithm +center, radius = boundingsphere(pts, algorithm) # customize algorithm ``` diff --git a/src/api.jl b/src/api.jl index 38a0406..557e609 100644 --- a/src/api.jl +++ b/src/api.jl @@ -1,11 +1,11 @@ -export miniball +export boundingsphere export WelzlMTF export WelzlPivot export Ritter -abstract type MiniballAlgorithm end +abstract type BoundingSphereAlg end """ WelzlMTF() @@ -20,7 +20,7 @@ In almost all situations it is better to use [`WelzlPivot`](@ref) instead. ## Cons * Prone to numerical stability issues """ -struct WelzlMTF <: MiniballAlgorithm end +struct WelzlMTF <: BoundingSphereAlg end """ WelzlPivot(;max_iterations=1000) @@ -33,7 +33,7 @@ Welzl algorithm with pivoting. See Algorithm II in https://people.inf.ethz.ch/ga ## Cons * In very rare cases can be numerically instable """ -struct WelzlPivot <: MiniballAlgorithm +struct WelzlPivot <: BoundingSphereAlg max_iterations::Int end @@ -42,7 +42,7 @@ function WelzlPivot(;max_iterations=1000) end """ - center, radius = miniball(pts [, algorithm=WelzlPivot()]) + center, radius = boundingsphere(pts [, algorithm=WelzlPivot()]) Compute the smallest sphere that contains each point in `pts`. @@ -51,9 +51,9 @@ Compute the smallest sphere that contains each point in `pts`. * pts: A list of points. Points should be vectors with floating point entries. * algorithm: An optional algorithm to do the computation. See names(BoundingSphere) to get """ -function miniball end +function boundingsphere end -function miniball!(pts, alg::WelzlMTF=WelzlMTF()) +function boundingsphere!(pts, alg::WelzlMTF=WelzlMTF()) bdry = create_boundary_device(pts, alg) ball, support_count = welzl!(pts, bdry, alg) r = radius(ball) @@ -61,7 +61,7 @@ function miniball!(pts, alg::WelzlMTF=WelzlMTF()) c, r end -function miniball!(pts, alg::MiniballAlgorithm) +function boundingsphere!(pts, alg::BoundingSphereAlg) bdry = create_boundary_device(pts, alg) ball = welzl!(pts, bdry, alg) r = radius(ball) @@ -69,6 +69,6 @@ function miniball!(pts, alg::MiniballAlgorithm) c, r end -@noinline function miniball(pts, alg::MiniballAlgorithm=WelzlMTF()) - miniball!(copy(pts), alg) +@noinline function boundingsphere(pts, alg::BoundingSphereAlg=WelzlMTF()) + boundingsphere!(copy(pts), alg) end diff --git a/src/ritter.jl b/src/ritter.jl index 3610f77..b5f9965 100644 --- a/src/ritter.jl +++ b/src/ritter.jl @@ -8,7 +8,7 @@ ## Cons * Very inaccurate. """ -struct Ritter <: MiniballAlgorithm end +struct Ritter <: BoundingSphereAlg end function max_distance_point(pts, pt1) pt_best = first(pts) @@ -45,4 +45,4 @@ end c, r end -miniball(pts, alg::Ritter) = ritter(pts) +boundingsphere(pts, alg::Ritter) = ritter(pts) diff --git a/test/helpers.jl b/test/helpers.jl index b65db37..3bb2ace 100644 --- a/test/helpers.jl +++ b/test/helpers.jl @@ -119,7 +119,7 @@ function random_test(alg, npoints, dim; P = eltype(pts) F = eltype(P) - c, r = miniball(pts, alg) + c, r = boundingsphere(pts, alg) ball = MB.SqBall(c, r^2) r_ref = MB.radius(ball_ref) diff --git a/test/perf.jl b/test/perf.jl index 45c6f08..85932ba 100644 --- a/test/perf.jl +++ b/test/perf.jl @@ -8,10 +8,10 @@ for (dim, npoints) in [ (3,1000) ] pts = [@SVector(randn(3)) for _ in 1:npoints] - for A in subtypes(MB.MiniballAlgorithm) + for A in subtypes(MB.BoundingSphereAlg) alg = A() println("Running $alg on $npoints points of dimension $dim") - trial = @benchmark miniball($pts, $alg) + trial = @benchmark boundingsphere($pts, $alg) show(STDOUT, MIME"text/plain"(), trial) println() end diff --git a/test/test_broken.jl b/test/test_broken.jl index 95b0aa4..c17f3b4 100644 --- a/test/test_broken.jl +++ b/test/test_broken.jl @@ -7,7 +7,7 @@ [3.279069514617182434790265688207000494003295898437500000000000000000000000000000, -2.195389590186907824431727931369096040725708007812500000000000000000000000000000], [3.279069514617182434790265688207000494003295898437500000000000000000000000000000, -2.195389590186907824431727931369096040725708007812500000000000000000000000000000]] - c,r = miniball(pts, WelzlPivot()) + c,r = boundingsphere(pts, WelzlPivot()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, atol=10) @test_broken MB.allinside(pts, ball, rtol=1e-1) diff --git a/test/test_degenerate_examples.jl b/test/test_degenerate_examples.jl index 83e6f29..f5c15ff 100644 --- a/test/test_degenerate_examples.jl +++ b/test/test_degenerate_examples.jl @@ -3,13 +3,13 @@ ball_ref = MB.SqBall{Array{Float64,1},Float64}([1.79979, -0.419288], 38.387992027461046) pts = StaticArrays.SArray{Tuple{2},Float64,1,2}[[0.379453, 0.65952], [1.29807, 1.06029], [1.66662, -0.225889]] - c,r = miniball(pts, WelzlPivot()) + c,r = boundingsphere(pts, WelzlPivot()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, rtol=1e-1) @test MB.allinside(pts, ball, rtol=1e-6) # not sure if WelzlMTF should give a good result - c,r = miniball(pts, WelzlMTF()) + c,r = boundingsphere(pts, WelzlMTF()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, rtol=1e-1) @test MB.allinside(pts, ball, rtol=1e-6) @@ -21,12 +21,12 @@ end y = x + 10*eps(Float64) pts = [[x], [y]] - c,r = miniball(pts, WelzlPivot()) + c,r = boundingsphere(pts, WelzlPivot()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, atol=100eps(Float64)) # not sure if WelzlMTF should give a good result - @test_broken miniball(pts, WelzlMTF()) + @test_broken boundingsphere(pts, WelzlMTF()) # ball = MB.SqBall(c, r^2) # @test_broken MB.allinside(pts, ball, rtol=1e-1) # @test_broken MB.allinside(pts, ball, rtol=1e-6) @@ -38,13 +38,13 @@ end ball_ref = MB.SqBall{Array{Float64,1},Float64}([1.05415, -2.52996, -0.584979], 20.953846606252085) pts = StaticArrays.SArray{Tuple{3},Float64,1,3}[[1.18024, 0.0853978, -3.01374], [0.20966, -3.69213, 3.76129], [4.51103, -0.881877, 1.92254]] - c,r = miniball(pts, WelzlPivot()) + c,r = boundingsphere(pts, WelzlPivot()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, rtol=1e-1) @test MB.allinside(pts, ball, rtol=1e-6) # not sure if WelzlMTF should give a good result - c,r = miniball(pts, WelzlMTF()) + c,r = boundingsphere(pts, WelzlMTF()) ball = MB.SqBall(c, r^2) @test MB.allinside(pts, ball, rtol=1e-1) @test MB.allinside(pts, ball, rtol=1e-6) diff --git a/test/test_welzl.jl b/test/test_welzl.jl index 78c1545..2ec6258 100644 --- a/test/test_welzl.jl +++ b/test/test_welzl.jl @@ -10,15 +10,15 @@ using StaticArrays push!(inputs, pts) end end - for A in subtypes(MB.MiniballAlgorithm) + for A in subtypes(MB.BoundingSphereAlg) for pts in inputs alg = A() - c, r = miniball(pts, alg) + c, r = boundingsphere(pts, alg) P = eltype(pts) F = eltype(P) @test typeof(c) == P @test typeof(r) == F - @inferred miniball(pts, alg) + @inferred boundingsphere(pts, alg) @test norm(c) < sqrt(eps(F)) @test r ≈ 1 end @@ -74,7 +74,7 @@ end # support set suffices pts2 = pts[1:support_count] - c, r = miniball(pts2, alg) + c, r = boundingsphere(pts2, alg) @test MB.center(ball) ≈ c @test MB.radius(ball) ≈ r @@ -83,7 +83,7 @@ end if length(pts3) > 1 index = rand(1:length(pts3)) deleteat!(pts3, index) - c, r = miniball(pts3, alg) + c, r = boundingsphere(pts3, alg) @test r < MB.radius(ball) end end