diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19810de..8b47daf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: fail-fast: false matrix: version: - - '1.10' # latest LTS + - 'lts' - '1' experimental: - false diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index ff80d77..ede02f3 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -30,6 +30,7 @@ jobs: else @error "Some files have not been formatted !!!" write(stdout, out) + run(`git diff`) exit(1) end ' diff --git a/src/MarchingCubes.jl b/src/MarchingCubes.jl index 346ee45..e68a14c 100644 --- a/src/MarchingCubes.jl +++ b/src/MarchingCubes.jl @@ -73,7 +73,11 @@ struct MC{F,I} y::AbstractVector{F} = F[], z::AbstractVector{F} = F[], ) where {F<:AbstractFloat,G<:Integer} = begin - abs(normal_sign) == 1 || throw(ArgumentError("`normal_sign` should be either -1 or +1")) + isa(x, AbstractRange) && (x = collect(x)) + isa(y, AbstractRange) && (y = collect(y)) + isa(z, AbstractRange) && (z = collect(z)) + abs(normal_sign) == 1 || + throw(ArgumentError("`normal_sign` should be either -1 or +1")) m = new{F,I}( size(vol)..., Ref(vol), diff --git a/src/example.jl b/src/example.jl index 7b8ae21..dbfd1a8 100644 --- a/src/example.jl +++ b/src/example.jl @@ -126,7 +126,7 @@ makemesh_GeometryBasics(GeometryBasics::Module, m::MC) = begin vertices = map(GeometryBasics.Point3f, m.vertices) normals = map(GeometryBasics.Vec3f, m.normals) triangles = map(t -> GeometryBasics.TriangleFace(t...), m.triangles) - GeometryBasics.Mesh(GeometryBasics.meta(vertices; normals), triangles) + GeometryBasics.Mesh(vertices, triangles; normal = normals) end makemesh(mod::Module, m::MC) = diff --git a/test/runtests.jl b/test/runtests.jl index 10e1e55..4c81f33 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,3 @@ -using BenchmarkTools using GeometryBasics using MarchingCubes using Meshes @@ -118,14 +117,6 @@ end MarchingCubes.output(PlyIO, mc, tempname(); verbose = false) end -@testset "types" begin - for F ∈ (Float16, Float32, Float64) - for I ∈ (Int16, Int32, Int64, Int128, UInt16, UInt32, UInt64, UInt128) - @test march(MarchingCubes.scenario(4, 4, 4; F, I)) isa Nothing - end - end -end - @testset "normalize" begin nx, ny, nz = 10, 20, 30 start_x, stop_x = -0.1, 0.1 @@ -187,7 +178,54 @@ end msh = MarchingCubes.makemesh(GeometryBasics, mc) @test msh isa GeometryBasics.Mesh @test length(msh.position) == length(mc.vertices) - @test length(msh.normals) == length(mc.normals) + @test length(msh.normal) == length(mc.normals) @test_throws ArgumentError MarchingCubes.makemesh(PlyIO, mc) end + +@testset "coordinate input variations" begin + atol = 1e-3 # precision level + + # define coordinate ranges (also creating 3 different lengths) + nx, ny, nz = 55, 46, 67 # these should be high enough to reach precision level + start_x, stop_x = -1.0, 1.0 # range limits centered on 0 + start_y, stop_y = -1.2, 1.2 # range limits centered on 0 + start_z, stop_z = -2.3, 2.3 # range limits centered on 0 + x = range(start_x, stop_x; length = nx) + y = range(start_y, stop_y; length = ny) + z = range(start_z, stop_z; length = nz) + + # create image (simple coordinate norm leading to spherical isosurface) + A = [√(xi^2 + yi^2 + zi^2) for xi ∈ x, yi ∈ y, zi ∈ z] + + level = 0.5 # isolevel should produce sphere with this radius + + # process isosurface with ranged coordinate input + mc_ranged = MC(A, Int; x, y, z) + march(mc_ranged, level) + + xv, yv, zv = collect.(Float64, (x, y, z)) + + # process isosurface with vector coordinate input + mc_vector = MC(A, Int; x = xv, y = yv, z = zv) + march(mc_vector, level) + + # test equivalence between ranged and vector input + @test mc_ranged.vertices == mc_vector.vertices + @test mc_ranged.triangles == mc_vector.triangles + + # test if coordinate input was used appropriately geometrically as expected + n = length(mc_ranged.vertices) + c = sum(mc_ranged.vertices) / n # mean coordinate i.e. center + r = sum(v -> √(sum(abs2, v)), mc_ranged.vertices) / n # mean radius + @test isapprox(c, zeros(3); atol) # approximately zero mean for sphere + @test isapprox(r, level; atol) # approximately radius matching level +end + +@testset "types" begin + for F ∈ (Float16, Float32, Float64), + I ∈ (Int16, Int32, Int64, Int128, UInt16, UInt32, UInt64, UInt128) + + @test march(MarchingCubes.scenario(4, 4, 4; F, I)) isa Nothing + end +end