From fdc15885b62f661ba10b7269458420526d59b7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 16:45:54 +0100 Subject: [PATCH 1/8] fix imports/named using from GeometryBasics add juliaformatter --- .JuliaFormatter.toml | 7 +++ .github/workflows/format_check.yml | 45 ++++++++++++++++ src/TetGen.jl | 11 ++-- src/api.jl | 14 ++--- src/cpptetgenio.jl | 85 +++++++++++++++--------------- src/meshes.jl | 4 -- 6 files changed, 104 insertions(+), 62 deletions(-) create mode 100644 .JuliaFormatter.toml create mode 100644 .github/workflows/format_check.yml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..00e9c65 --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,7 @@ +style = "sciml" +pipe_to_function_call=false +always_for_in = false +separate_kwargs_with_semicolon = true +margin = 132 +yas_style_nesting=true +ignore = "examples/pluto-examples.jl" \ No newline at end of file diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 0000000..3b1e618 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,45 @@ + +name: format-check + +on: + push: + branches: + - 'master' + - 'release-' + tags: '*' + pull_request: + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1.3.0] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - uses: actions/checkout@v1 + - name: Install JuliaFormatter and format + # This will use the latest version by default but you can set the version like so: + # + # julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.0"))' + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + - name: Format check + run: | + julia -e ' + out = Cmd(`git diff --name-only`) |> read |> String + if out == "" + exit(0) + else + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) + end' + + diff --git a/src/TetGen.jl b/src/TetGen.jl index d791416..9f9b989 100644 --- a/src/TetGen.jl +++ b/src/TetGen.jl @@ -2,30 +2,27 @@ module TetGen using DocStringExtensions using TetGen_jll -using GeometryBasics -using GeometryBasics: Polygon, MultiPolygon, Point, LineFace, Polytope, Line, +import GeometryBasics +using GeometryBasics: Polygon, MultiPolygon, Point, Point3f, LineFace, Polytope, Line, Simplex, connect, Triangle, NSimplex, Tetrahedron, TupleView, TriangleFace, SimplexFace, LineString, Mesh, TetrahedronP, TriangleP, NgonFace, Ngon, faces, coordinates, metafree, meta, faces - using Printf using StaticArrays - include("cpptetgenio.jl") include("jltetgenio.jl") include("rawtetgenio.jl") include("meshes.jl") include("api.jl") - export tetrahedralize export tetunsuitable export TetGenError export RawTetGenIO, facetlist!, RawFacet -export numberofpoints,numberoftetrahedra,numberoftrifaces,numberofedges -export volumemesh,surfacemesh +export numberofpoints, numberoftetrahedra, numberoftrifaces, numberofedges +export volumemesh, surfacemesh end # module diff --git a/src/api.jl b/src/api.jl index 9744f44..a38326c 100644 --- a/src/api.jl +++ b/src/api.jl @@ -5,24 +5,21 @@ Create voronoi diagram of point set. Returns a mesh of triangles. """ -function voronoi(points::Vector{Point{3, T}}) where T <: AbstractFloat +function voronoi(points::Vector{Point{3, T}}) where {T <: AbstractFloat} result = tetrahedralize(JLTetGenIO(points), "Qw") Mesh{Triangle}(result) end - """ $(SIGNATURES) Tetrahedralize a mesh of polygons with optional facet markers. Returns a mesh of tetrahdra. """ -function TetGen.tetrahedralize( - mesh::Mesh{3, Float64, <: TetGen.Ngon}, command = "Qp"; - marker = :markers, holes = Point{3, Float64}[] - ) +function TetGen.tetrahedralize(mesh::Mesh{3, Float64, <:TetGen.Ngon}, command = "Qp"; + marker = :markers, holes = Point{3, Float64}[]) f = faces(mesh) - kw_args = Any[:facets => metafree(f),:holes => holes] + kw_args = Any[:facets => metafree(f), :holes => holes] if hasproperty(f, marker) push!(kw_args, :facetmarkers => getproperty(f, marker)) end @@ -31,14 +28,13 @@ function TetGen.tetrahedralize( return Mesh{Tetrahedron}(result) end - """ $(SIGNATURES) Tetrahedralize a domain described by a mesh of triangles. Returns a mesh of tetrahdra. """ -function TetGen.tetrahedralize(mesh::Mesh{3, Float64, <: TetGen.Triangle}, command = "Qp") +function TetGen.tetrahedralize(mesh::Mesh{3, Float64, <:TetGen.Triangle}, command = "Qp") tio = JLTetGenIO(coordinates(mesh); facets = faces(mesh)) result = tetrahedralize(tio, command) Mesh{Tetrahedron}(result) diff --git a/src/cpptetgenio.jl b/src/cpptetgenio.jl index 35dc647..118954b 100644 --- a/src/cpptetgenio.jl +++ b/src/cpptetgenio.jl @@ -1,16 +1,15 @@ struct CPolygon - vertexlist::Ptr{Cint} - numberofvertices::Cint + vertexlist::Ptr{Cint} + numberofvertices::Cint end struct CFacet{T} - polygonlist::Ptr{CPolygon} - numberofpolygons::Cint - holelist::Ptr{T} - numberofholes::Cint + polygonlist::Ptr{CPolygon} + numberofpolygons::Cint + holelist::Ptr{T} + numberofholes::Cint end - struct CPPTetGenIO{T} firstnumber::Cint # 0 or 1, default 0. mesh_dim::Cint # must be 3. @@ -69,71 +68,73 @@ end from TetGen """ function Base.show(io::IO, e::TetGenError) - if e.rc==1 - println(io,"TetGen error $(e.rc): out of memory."); - elseif e.rc==2 - println(io,"TetGen error $(e.rc): internal error.") - elseif e.rc==3 - println(io,"TetGen error $(e.rc): a self-intersection was detected. Hint: use -d option to detect all self-intersections."); - elseif e.rc==4 - println(io,"TetGen error $(e.rc): a very small input feature size was detected. Hint: use -T option to set a smaller tolerance.") - elseif e.rc==5 - println(io,"TetGen error $(e.rc): two very close input facets were detected. Hint: use -Y option to avoid adding Steiner points in boundary.\n"); - elseif e.rc==10 - println(io,"TetGen error $(e.rc): an input error was detected.\n"); - elseif e.rc==101 - println(io,"TetGen error: unable to load stl file\n"); + if e.rc == 1 + println(io, "TetGen error $(e.rc): out of memory.") + elseif e.rc == 2 + println(io, "TetGen error $(e.rc): internal error.") + elseif e.rc == 3 + println(io, "TetGen error $(e.rc): a self-intersection was detected. Hint: use -d option to detect all self-intersections.") + elseif e.rc == 4 + println(io, + "TetGen error $(e.rc): a very small input feature size was detected. Hint: use -T option to set a smaller tolerance.") + elseif e.rc == 5 + println(io, + "TetGen error $(e.rc): two very close input facets were detected. Hint: use -Y option to avoid adding Steiner points in boundary.\n") + elseif e.rc == 10 + println(io, "TetGen error $(e.rc): an input error was detected.\n") + elseif e.rc == 101 + println(io, "TetGen error: unable to load stl file\n") else - println(io,"TetGen error $(e.rc): unknown error.\n"); - end + println(io, "TetGen error $(e.rc): unknown error.\n") + end end - """ $(SIGNATURES) Tetrahedralization with error handling """ function tetrahedralize(input::CPPTetGenIO{Float64}, command::String) - rc=Cint[0] - output = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command, rc) - if rc[1]!=0 + rc = Cint[0] + output = ccall((:tetrahedralize2_f64, libtet), + CPPTetGenIO{Float64}, + (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), + input, + command, + rc) + if rc[1] != 0 throw(TetGenError(rc[1])) end output end - - """ Trivial Julia tetunsuitable function """ -my_jl_tetunsuitable=(pa,pb,pc,pd)->0 - +my_jl_tetunsuitable = (pa, pb, pc, pd) -> 0 """ Tetunsuitable function called from C wrapper """ function jl_wrap_tetunsuitable(pa::Ptr{Float64}, pb::Ptr{Float64}, pc::Ptr{Float64}, pd::Ptr{Float64}) - pax=Base.unsafe_wrap(Array,pa,(3,),own=false) - pbx=Base.unsafe_wrap(Array,pb,(3,),own=false) - pcx=Base.unsafe_wrap(Array,pc,(3,),own=false) - pdx=Base.unsafe_wrap(Array,pd,(3,),own=false) - Cint(my_jl_tetunsuitable(pax,pbx,pcx,pdx)) + pax = Base.unsafe_wrap(Array, pa, (3,); own = false) + pbx = Base.unsafe_wrap(Array, pb, (3,); own = false) + pcx = Base.unsafe_wrap(Array, pc, (3,); own = false) + pdx = Base.unsafe_wrap(Array, pd, (3,); own = false) + Cint(my_jl_tetunsuitable(pax, pbx, pcx, pdx)) end - """ Set tetunsuitable function called from C wrapper. Setting this function is valid only for one subsequent call to tetrahedralize """ -function tetunsuitable(unsuitable::Function;check_signature=true) +function tetunsuitable(unsuitable::Function; check_signature = true) if check_signature - unsuitable(rand(3),rand(3),rand(3),rand(3)) + unsuitable(rand(3), rand(3), rand(3), rand(3)) end global my_jl_tetunsuitable - my_jl_tetunsuitable=unsuitable - c_wrap_tetunsuitable=@cfunction(jl_wrap_tetunsuitable, Cint, (Ptr{Cdouble},Ptr{Cdouble},Ptr{Cdouble},Ptr{Cdouble})) - ccall((:tetunsuitable_callback,libtet),Cvoid,(Ptr{Cvoid},),c_wrap_tetunsuitable) + my_jl_tetunsuitable = unsuitable + c_wrap_tetunsuitable = @cfunction(jl_wrap_tetunsuitable, Cint, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble})) + ccall((:tetunsuitable_callback, libtet), Cvoid, (Ptr{Cvoid},), c_wrap_tetunsuitable) end diff --git a/src/meshes.jl b/src/meshes.jl index a527c40..63dadea 100644 --- a/src/meshes.jl +++ b/src/meshes.jl @@ -1,5 +1,3 @@ -using GeometryBasics: Triangle, Tetrahedron, Mesh, Polytope - """ Mesh{Tetrahedron}(result::JLTetGenIO) @@ -25,12 +23,10 @@ function GeometryBasics.Mesh{P}(x::JLTetGenIO{T}) where {P <: Polytope{N, T} whe Mesh{Polytope(P, Point{3, T})}(x) end - function GeometryBasics.Mesh{TetrahedronP{ET, P}}(x::JLTetGenIO) where {ET, P} Mesh(convert(Vector{P}, x.points), x.tetrahedra) end - function GeometryBasics.Mesh{TriangleP{3, ET, P}}(x::JLTetGenIO) where {ET, P} Mesh(convert(Vector{P}, x.points), x.trifaces) end From 97c4aa4c085f24c8c963dbb3abed17f709c455bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 16:50:35 +0100 Subject: [PATCH 2/8] @deprecate tetunsuitable tetunsuitable! --- Project.toml | 2 +- src/TetGen.jl | 2 +- src/cpptetgenio.jl | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index b40c9bb..0ddf709 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TetGen" uuid = "c5d3f3f7-f850-59f6-8a2e-ffc6dc1317ea" authors = ["SimonDanisch ", "Juergen Fuhrmann Date: Mon, 13 Nov 2023 17:10:21 +0100 Subject: [PATCH 3/8] really format --- .JuliaFormatter.toml | 1 - docs/make.jl | 22 +- examples/examples.jl | 281 ++++++++++++------------ src/TetGen.jl | 6 +- src/api.jl | 2 +- src/cpptetgenio.jl | 14 +- src/jltetgenio.jl | 237 +++++++++----------- src/rawtetgenio.jl | 498 ++++++++++++++++++++++--------------------- test/runtests.jl | 293 +++++++++++-------------- 9 files changed, 634 insertions(+), 720 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 00e9c65..d9ebd59 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -4,4 +4,3 @@ always_for_in = false separate_kwargs_with_semicolon = true margin = 132 yas_style_nesting=true -ignore = "examples/pluto-examples.jl" \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 6ffa55e..5b1c84d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,20 +2,18 @@ using Documenter, TetGen function make_all() makedocs( + ; sitename = "TetGen.jl", + modules = [TetGen], + clean = true, + doctest = false, + authors = "Simon Danisch, Juergen Fuhrmann", + repo = "https://github.com/JuliaGeometry/TetGen.jl", + pages = [ + "Home" => "index.md", + ]) - sitename="TetGen.jl", - modules = [TetGen], - clean = true, - doctest = false, - authors = "Simon Danisch, Juergen Fuhrmann", - repo="https://github.com/JuliaGeometry/TetGen.jl", - pages=[ - "Home"=>"index.md" - ] - ) - if !isinteractive() - deploydocs(repo = "github.com/JuliaGeometry/TetGen.jl.git") + deploydocs(; repo = "github.com/JuliaGeometry/TetGen.jl.git") end end diff --git a/examples/examples.jl b/examples/examples.jl index 525553b..f6b2c1b 100644 --- a/examples/examples.jl +++ b/examples/examples.jl @@ -9,8 +9,8 @@ This is a tetrahedralization of the convex hull of the points. If the points are in general position (which we assume here), it is unique. """ -function random_delaunay(;npoints=20) - input=TetGen.RawTetGenIO{Cdouble}(pointlist=rand(3,npoints)) +function random_delaunay(; npoints = 20) + input = TetGen.RawTetGenIO{Cdouble}(; pointlist = rand(3, npoints)) tetrahedralize(input, "Q") end @@ -19,103 +19,96 @@ end Tetrahedralization of cube witn maximum tetrahedron volume. """ -function cube(;vol=1) - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1]' - - TetGen.facetlist!(input,[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') +function cube(; vol = 1) + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1]' + + TetGen.facetlist!(input, [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa$(vol)") end - - """ cubewithhole(;vol=1) Tetrahedralization of cube witn maximum tetrahedron volume. """ -function cubewithhole(;vol=1) - input=TetGen.RawTetGenIO{Cdouble}() - outerpoints=[-1 -1 -1; - 1 -1 -1; - 1 1 -1; - -1 1 -1; - -1 -1 1; - 1 -1 1; - 1 1 1; - -1 1 1;]' - - input.pointlist=hcat(outerpoints,outerpoints/2) - - outerfacets=[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8; - ]' - - input.holelist=[0 0 0;]' - - TetGen.facetlist!(input,hcat(outerfacets,outerfacets.+8)) +function cubewithhole(; vol = 1) + input = TetGen.RawTetGenIO{Cdouble}() + outerpoints = [-1 -1 -1; + 1 -1 -1; + 1 1 -1; + -1 1 -1; + -1 -1 1; + 1 -1 1; + 1 1 1; + -1 1 1]' + + input.pointlist = hcat(outerpoints, outerpoints / 2) + + outerfacets = [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]' + + input.holelist = [0 0 0;]' + + TetGen.facetlist!(input, hcat(outerfacets, outerfacets .+ 8)) tetrahedralize(input, "pQa$(vol)") end - - """ cube_localref() Tetrahedralization of cube with local refinement callback """ function cube_localref() - - tetunsuitable() do pa,pb,pc,pd - vol=det(hcat(pb-pa,pc-pa,pd-pa))/6 - center=0.25*(pa+pb+pc+pd)-[0.5,0.5,0.5] - vol> 0.05*norm(center)^2.5 + tetunsuitable() do pa, pb, pc, pd + vol = det(hcat(pb - pa, pc - pa, pd - pa)) / 6 + center = 0.25 * (pa + pb + pc + pd) - [0.5, 0.5, 0.5] + vol > 0.05 * norm(center)^2.5 end - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1]' - - TetGen.facetlist!(input,[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1]' + + TetGen.facetlist!(input, [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa") end - """ cube_stl() Tetrahedralization of cube from an stl file """ function cube_stl() - modeldir=joinpath(dirname(pathof(TetGen)),"..","test","surfaceModels") - modelfile=joinpath(modeldir,"cube.stl") + modeldir = joinpath(dirname(pathof(TetGen)), "..", "test", "surfaceModels") + modelfile = joinpath(modeldir, "cube.stl") tetrahedralize(modelfile, "pQa1.0") end """ @@ -123,20 +116,20 @@ end Tetrahedralization of a prism with maximum tetrahedron volume. """ -function prism(vol=2) - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 0 1 0; - 0 0 1; - 1 0 1; - 0 1 1]' - - TetGen.facetlist!(input,[[1,2,3], - [4,5,6], - [1,2,5,4], - [2,3,6,5], - [3,1,4,6]]) +function prism(vol = 2) + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 0 1 0; + 0 0 1; + 1 0 1; + 0 1 1]' + + TetGen.facetlist!(input, [[1, 2, 3], + [4, 5, 6], + [1, 2, 5, 4], + [2, 3, 6, 5], + [3, 1, 4, 6]]) tetrahedralize(input, "pQa$(vol)") end @@ -146,76 +139,70 @@ end Tetrahedralization of a prism with two regions with different tet volumes """ -function material_prism(;vol1=0.01, vol2=0.1) - input=TetGen.RawTetGenIO{Cdouble}() - - input.pointlist=[0 0 0; - 1 0 0; - 0 1 0; - 0 0 1; - 1 0 1; - 0 1 1; - 0 0 2; - 1 0 2; - 0 1 2]' - - - TetGen.facetlist!(input,[[1,2,3], - [7,8,9], - [1,2,5,4], - [2,3,6,5], - [3,1,4,6], - [1,2,5,4].+3, - [2,3,6,5].+3, - [3,1,4,6].+3]) - - input.facetmarkerlist=[1,2,3,3,3,3,3,3] - input.regionlist=[0.1 0.1 0.5 1 vol1; - 0.1 0.1 1.5 2 vol2]' - +function material_prism(; vol1 = 0.01, vol2 = 0.1) + input = TetGen.RawTetGenIO{Cdouble}() + + input.pointlist = [0 0 0; + 1 0 0; + 0 1 0; + 0 0 1; + 1 0 1; + 0 1 1; + 0 0 2; + 1 0 2; + 0 1 2]' + + TetGen.facetlist!(input, + [[1, 2, 3], + [7, 8, 9], + [1, 2, 5, 4], + [2, 3, 6, 5], + [3, 1, 4, 6], + [1, 2, 5, 4] .+ 3, + [2, 3, 6, 5] .+ 3, + [3, 1, 4, 6] .+ 3]) + + input.facetmarkerlist = [1, 2, 3, 3, 3, 3, 3, 3] + input.regionlist = [0.1 0.1 0.5 1 vol1; + 0.1 0.1 1.5 2 vol2]' + tetrahedralize(input, "paAqQ") end - """ cutprism(;vol=0.05) Tetrahedralization of a prism with a prism cut out in the middle. This tests the use of facet holes. """ -function cutprism(;vol=0.05) - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 0 1 0; - - 0 0 10; - 1 0 10; - 0 1 10; - - - -1 -1 0; # 7 - 2 -1 0; - 2 2 0; - -1 2 0; - - -1 -1 10; # 11 - 2 -1 10; - 2 2 10; - -1 2 10]' - - push!(input.facetlist,RawFacet([Cint[1, 2, 3],Cint[7, 8, 9, 10]], [0.1 0.1 0.0;])) - push!(input.facetlist,RawFacet([Cint[4, 5, 6],Cint[11,12,13,14]], [0.1 0.1 1.0;])) - push!(input.facetlist,RawFacet([Cint[1, 2, 5, 4 ]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[2, 3, 6, 5 ]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[3, 1, 4, 6 ]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[7, 8, 12,11]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[8, 9, 13,12]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[9, 10,14,13]], Array{Cdouble,2}(undef,0,0))) - push!(input.facetlist,RawFacet([Cint[10,7, 11,14]], Array{Cdouble,2}(undef,0,0))) - - input.facetmarkerlist=[1,2,3,3,3,4,5,6,7] - input.regionlist=[ -0.1 -0.1 0.1 1 vol;]' +function cutprism(; vol = 0.05) + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 0 1 0; + 0 0 10; + 1 0 10; + 0 1 10; + -1 -1 0; # 7 + 2 -1 0; + 2 2 0; + -1 2 0; + -1 -1 10; # 11 + 2 -1 10; + 2 2 10; + -1 2 10]' + + push!(input.facetlist, RawFacet([Cint[1, 2, 3], Cint[7, 8, 9, 10]], [0.1 0.1 0.0;])) + push!(input.facetlist, RawFacet([Cint[4, 5, 6], Cint[11, 12, 13, 14]], [0.1 0.1 1.0;])) + push!(input.facetlist, RawFacet([Cint[1, 2, 5, 4]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[2, 3, 6, 5]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[3, 1, 4, 6]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[7, 8, 12, 11]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[8, 9, 13, 12]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[9, 10, 14, 13]], Array{Cdouble, 2}(undef, 0, 0))) + push!(input.facetlist, RawFacet([Cint[10, 7, 11, 14]], Array{Cdouble, 2}(undef, 0, 0))) + + input.facetmarkerlist = [1, 2, 3, 3, 3, 4, 5, 6, 7] + input.regionlist = [-0.1 -0.1 0.1 1 vol;]' tetrahedralize(input, "paqAQ") end - diff --git a/src/TetGen.jl b/src/TetGen.jl index 7900842..9fe3441 100644 --- a/src/TetGen.jl +++ b/src/TetGen.jl @@ -4,9 +4,9 @@ using TetGen_jll import GeometryBasics using GeometryBasics: Polygon, MultiPolygon, Point, Point3f, LineFace, Polytope, Line, - Simplex, connect, Triangle, NSimplex, Tetrahedron, - TupleView, TriangleFace, SimplexFace, LineString, Mesh, TetrahedronP, TriangleP, - NgonFace, Ngon, faces, coordinates, metafree, meta, faces + Simplex, connect, Triangle, NSimplex, Tetrahedron, + TupleView, TriangleFace, SimplexFace, LineString, Mesh, TetrahedronP, TriangleP, + NgonFace, Ngon, faces, coordinates, metafree, meta, faces using Printf diff --git a/src/api.jl b/src/api.jl index a38326c..c8891b5 100644 --- a/src/api.jl +++ b/src/api.jl @@ -17,7 +17,7 @@ Tetrahedralize a mesh of polygons with optional facet markers. Returns a mesh of tetrahdra. """ function TetGen.tetrahedralize(mesh::Mesh{3, Float64, <:TetGen.Ngon}, command = "Qp"; - marker = :markers, holes = Point{3, Float64}[]) + marker = :markers, holes = Point{3, Float64}[]) f = faces(mesh) kw_args = Any[:facets => metafree(f), :holes => holes] if hasproperty(f, marker) diff --git a/src/cpptetgenio.jl b/src/cpptetgenio.jl index 47b5c81..f2a9f09 100644 --- a/src/cpptetgenio.jl +++ b/src/cpptetgenio.jl @@ -76,10 +76,10 @@ function Base.show(io::IO, e::TetGenError) println(io, "TetGen error $(e.rc): a self-intersection was detected. Hint: use -d option to detect all self-intersections.") elseif e.rc == 4 println(io, - "TetGen error $(e.rc): a very small input feature size was detected. Hint: use -T option to set a smaller tolerance.") + "TetGen error $(e.rc): a very small input feature size was detected. Hint: use -T option to set a smaller tolerance.") elseif e.rc == 5 println(io, - "TetGen error $(e.rc): two very close input facets were detected. Hint: use -Y option to avoid adding Steiner points in boundary.\n") + "TetGen error $(e.rc): two very close input facets were detected. Hint: use -Y option to avoid adding Steiner points in boundary.\n") elseif e.rc == 10 println(io, "TetGen error $(e.rc): an input error was detected.\n") elseif e.rc == 101 @@ -97,11 +97,11 @@ Tetrahedralization with error handling function tetrahedralize(input::CPPTetGenIO{Float64}, command::String) rc = Cint[0] output = ccall((:tetrahedralize2_f64, libtet), - CPPTetGenIO{Float64}, - (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), - input, - command, - rc) + CPPTetGenIO{Float64}, + (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), + input, + command, + rc) if rc[1] != 0 throw(TetGenError(rc[1])) end diff --git a/src/jltetgenio.jl b/src/jltetgenio.jl index cb469d0..c20bf11 100644 --- a/src/jltetgenio.jl +++ b/src/jltetgenio.jl @@ -9,26 +9,24 @@ # return facets # end - struct JLFacet{T, A <: AbstractVector{Cint}} polygons::Vector{A} holelist::Vector{T} end JLFacet(x::AbstractVector{Cint}) = JLFacet([x]) -JLFacet(x::Vector{<: AbstractVector{Cint}}) = JLFacet{Float64, eltype(typeof(x))}(x, Float64[]) - +JLFacet(x::Vector{<:AbstractVector{Cint}}) = JLFacet{Float64, eltype(typeof(x))}(x, Float64[]) function JLPolygon(x::CPolygon) - JLPolygon(unsafe_wrap(Array, x.vertexlist, x.numberofvertices, own = true)) + JLPolygon(unsafe_wrap(Array, x.vertexlist, x.numberofvertices; own = true)) end -function JLFacet(f::CFacet{T}) where T - c_polys = unsafe_wrap(Array, f.polygonlist, f.numberofpolygons, own = true) - holes = unsafe_wrap(Array, f.holelist, f.numberofholes, own = true) +function JLFacet(f::CFacet{T}) where {T} + c_polys = unsafe_wrap(Array, f.polygonlist, f.numberofpolygons; own = true) + holes = unsafe_wrap(Array, f.holelist, f.numberofholes; own = true) JLFacet{T}(JLPolygon.(c_polys), holes) end -function convert_poly(x::Vector{T}) where T <: Union{NgonFace{N, Cint}, NTuple{N, Cint}} where N +function convert_poly(x::Vector{T}) where {T <: Union{NgonFace{N, Cint}, NTuple{N, Cint}}} where {N} return map(1:length(x)) do i CPolygon(pointer(x, i), N) end @@ -40,7 +38,6 @@ function convert_poly(x::Vector{Vector{Cint}}) end end - struct Region{T} pos::Point{3, T} attribute::T @@ -56,10 +53,6 @@ struct SegmentationConstraint{IT, T} max_length_bound::T end - - - - inttype(::Type{Float64}) = Int64 inttype(::Type{Float32}) = Int32 @@ -91,97 +84,83 @@ struct JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, FT} edges::Vector{LineFace{Cint}} edgemarkers::Vector{Cint} - function JLTetGenIO( - points::Vector{Point{3, T}}, - pointattributes::Vector{SVector{NAttributes, T}}, - pointmtrs::Vector{SVector{NMTr, T}}, - pointmarkers::Vector{Cint}, - tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, - tetrahedronattributes::Vector{T}, - tetrahedronvolumes::Vector{T}, - neighbors::Vector{Cint}, - facets::FT, - facetmarkers::Vector{Cint}, - holes::Vector{Point{3, T}}, - regions::Vector{Region{T}}, - facetconstraints::Vector{FacetConstraint{IT, T}}, - segmentconstraints::Vector{SegmentationConstraint{IT, T}}, - trifaces::Vector{TriangleFace{Cint}}, - trifacemarkers::Vector{Cint}, - edges::Vector{LineFace{Cint}}, - edgemarkers::Vector{Cint}, - ) where {T, NSimplex, NAttributes, NMTr, IT, FT} - - - new{T, NSimplex, NAttributes, NMTr, IT, FT}( - points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers, - ) + function JLTetGenIO(points::Vector{Point{3, T}}, + pointattributes::Vector{SVector{NAttributes, T}}, + pointmtrs::Vector{SVector{NMTr, T}}, + pointmarkers::Vector{Cint}, + tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, + tetrahedronattributes::Vector{T}, + tetrahedronvolumes::Vector{T}, + neighbors::Vector{Cint}, + facets::FT, + facetmarkers::Vector{Cint}, + holes::Vector{Point{3, T}}, + regions::Vector{Region{T}}, + facetconstraints::Vector{FacetConstraint{IT, T}}, + segmentconstraints::Vector{SegmentationConstraint{IT, T}}, + trifaces::Vector{TriangleFace{Cint}}, + trifacemarkers::Vector{Cint}, + edges::Vector{LineFace{Cint}}, + edgemarkers::Vector{Cint}) where {T, NSimplex, NAttributes, NMTr, IT, FT} + new{T, NSimplex, NAttributes, NMTr, IT, FT}(points, + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end - end -function JLTetGenIO( - points::Vector{Point{3, T}}; - pointattributes = SVector{0, T}[], - pointmtrs = SVector{0, T}[], - pointmarkers = Cint[], - tetrahedrons = SimplexFace{4, Cint}[], - tetrahedronattributes = T[], - tetrahedronvolumes = T[], - neighbors = Cint[], - facets = JLFacet{T, Vector{Cint}}[], - facetmarkers = Cint[], - holes = Point{3, T}[], - regions = Region{T}[], - facetconstraints = FacetConstraint{inttype(T), T}[], - segmentconstraints = SegmentationConstraint{inttype(T), T}[], - trifaces = TriangleFace{Cint}[], - trifacemarkers = Cint[], - edges = LineFace{Cint}[], - edgemarkers = Cint[] - - ) where T - JLTetGenIO( - points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers, - ) - +function JLTetGenIO(points::Vector{Point{3, T}}; + pointattributes = SVector{0, T}[], + pointmtrs = SVector{0, T}[], + pointmarkers = Cint[], + tetrahedrons = SimplexFace{4, Cint}[], + tetrahedronattributes = T[], + tetrahedronvolumes = T[], + neighbors = Cint[], + facets = JLFacet{T, Vector{Cint}}[], + facetmarkers = Cint[], + holes = Point{3, T}[], + regions = Region{T}[], + facetconstraints = FacetConstraint{inttype(T), T}[], + segmentconstraints = SegmentationConstraint{inttype(T), T}[], + trifaces = TriangleFace{Cint}[], + trifacemarkers = Cint[], + edges = LineFace{Cint}[], + edgemarkers = Cint[]) where {T} + JLTetGenIO(points, + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end - function number_of_elements_field(io, basename) nfield = if basename == "tetrahedra" Symbol("numberof" * basename) @@ -207,7 +186,7 @@ function get_array(io, field::Symbol, Typ) basename = if field == :tetrahedra string(field) else - string(field)[1:end-1] # cut of s + string(field)[1:(end - 1)] # cut of s end ptr = if field == :tetrahedra io.tetrahedronlist @@ -217,19 +196,18 @@ function get_array(io, field::Symbol, Typ) ptr == C_NULL && return Typ[] n = getfield(io, number_of_elements_field(io, basename)) # own true, since we disable freeing in the c-part - return unsafe_wrap(Array, Base.unsafe_convert(Ptr{Typ}, ptr), n, own = true) + return unsafe_wrap(Array, Base.unsafe_convert(Ptr{Typ}, ptr), n; own = true) end -function Base.convert( - IOT::Type{JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}}, io::CPPTetGenIO{T} - ) where {T, NSimplex, NAttributes, NMTr, IT, A} +function Base.convert(IOT::Type{JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}}, + io::CPPTetGenIO{T}) where {T, NSimplex, NAttributes, NMTr, IT, A} JLTetGenIO(ntuple(fieldcount(IOT)) do i - fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) - get_array(io, fname, eltype(ftype)) - end...) + fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) + get_array(io, fname, eltype(ftype)) + end...) end -function Base.convert(::Type{JLTetGenIO}, io::CPPTetGenIO{T}) where T +function Base.convert(::Type{JLTetGenIO}, io::CPPTetGenIO{T}) where {T} NSimplex = Int(io.numberofcorners) NAttributes = Int(io.numberofpointattributes) NMTr = Int(io.numberofpointmtrs) @@ -237,7 +215,6 @@ function Base.convert(::Type{JLTetGenIO}, io::CPPTetGenIO{T}) where T convert(JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, Vector{CFacet{T}}}, io) end - function Base.cconvert(::Type{Ptr{CFacet{T}}}, facets::Vector{JLFacet{T, A}}) where {T, A} c_polys = map(facets) do facet convert_poly(facet.polygons) @@ -261,22 +238,17 @@ function Base.cconvert(::Type{Ptr{CFacet{T}}}, facets::Vector{NgonFace{N, Cint}} return (facets, c_polys, c_facets) end - -function unsafe_array_convert( - ::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}} - ) where {F, T} +function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, + facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end -function unsafe_array_convert( - ::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}} - ) where {F, T} +function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, + facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end -function unsafe_array_convert(P::Type{Ptr{T}}, x::Vector{T}) where T +function unsafe_array_convert(P::Type{Ptr{T}}, x::Vector{T}) where {T} Base.unsafe_convert(P, x) end @@ -284,21 +256,20 @@ function unsafe_array_convert(P::Type{Ptr{T1}}, x::Vector{T2}) where {T1, T2} Ptr{T1}(Base.unsafe_convert(Ptr{T2}, x)) end -function Base.cconvert(CIO::Type{CPPTetGenIO{T}}, obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} +function Base.cconvert(CIO::Type{CPPTetGenIO{T}}, + obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} cfnames = fieldnames(CIO) - dict = Dict{Symbol, Any}( - :numberofpointattributes => NAttributes, - :numberofpointmtrs => NMTr, - :numberofcorners => NSimplex, - :firstnumber => Cint(1), - :mesh_dim => Cint(3), - ) + dict = Dict{Symbol, Any}(:numberofpointattributes => NAttributes, + :numberofpointmtrs => NMTr, + :numberofcorners => NSimplex, + :firstnumber => Cint(1), + :mesh_dim => Cint(3)) gc_tack_cconvert = [] for field in fieldnames(typeof(obj)) basename = if field == :tetrahedra string(field) else - string(field)[1:end-1] # cut of s + string(field)[1:(end - 1)] # cut of s end listname = Symbol(replace(basename * "list", "tetrahedra" => "tetrahedron")) FT = fieldtype(CIO, listname) @@ -324,15 +295,15 @@ function Base.cconvert(CIO::Type{CPPTetGenIO{T}}, obj::JLTetGenIO{T, NSimplex, N return (CPPTetGenIO{T}(fields_tuple...), gc_tack_cconvert) end -function Base.unsafe_convert(::Type{CPPTetGenIO{T}}, x::Tuple{CPPTetGenIO{T}, Vector{Any}}) where T +function Base.unsafe_convert(::Type{CPPTetGenIO{T}}, x::Tuple{CPPTetGenIO{T}, Vector{Any}}) where {T} return x[1] end - function tetrahedralize(input::JLTetGenIO{Float64}, command::String) - rc=Cint[0] - cres = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command,rc) - if rc[1]!=0 + rc = Cint[0] + cres = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command, + rc) + if rc[1] != 0 throw(TetGenError(rc[1])) end return convert(JLTetGenIO, cres) diff --git a/src/rawtetgenio.jl b/src/rawtetgenio.jl index a06aab8..318fd18 100644 --- a/src/rawtetgenio.jl +++ b/src/rawtetgenio.jl @@ -10,16 +10,15 @@ struct RawFacet{T} Polygons given as arrays of indices which point into the pointlist array describing the input points. """ - polygonlist::Array{Array{Cint,1},1} + polygonlist::Array{Array{Cint, 1}, 1} """ Array of points given by their coordinates marking polygons describing holes in the facet. """ - holelist::Array{T,2} + holelist::Array{T, 2} end - """ $(TYPEDEF) @@ -49,23 +48,23 @@ mutable struct RawTetGenIO{T} """ 'pointlist': Array of point coordinates with `size(pointlist,1)==3`. """ - pointlist::Array{T,2} + pointlist::Array{T, 2} """ 'pointattributelist': Array of point attributes. The number of attributes per point is determined by `size(pointattributelist,1)` """ - pointattributelist::Array{T,2} + pointattributelist::Array{T, 2} """ 'pointmtrlist': An array of metric tensors at points. """ - pointmtrlist::Array{T,2} + pointmtrlist::Array{T, 2} """ 'pointmarkerlist': An array of point markers; one integer per point. """ - pointmarkerlist::Array{Cint,1} + pointmarkerlist::Array{Cint, 1} """ 'tetrahedronlist': An array of tetrahedron corners represented by indices of points in `pointlist`. Unless option `-o2` is given, @@ -74,40 +73,40 @@ mutable struct RawTetGenIO{T} `size(tetrahedronlist,1)==10` and the 4 corners are followed by 6 edge midpoints. """ - tetrahedronlist::Array{Cint,2} + tetrahedronlist::Array{Cint, 2} """ 'tetrahedronattributelist': An array of tetrahedron attributes. """ - tetrahedronattributelist::Array{T,2} + tetrahedronattributelist::Array{T, 2} """ 'tetrahedronvolumelist': An array of constraints, i.e. tetrahedron's volume; Input only. This can be used for triggering local refinement. """ - tetrahedronvolumelist::Array{T,1} + tetrahedronvolumelist::Array{T, 1} """ 'neighborlist': An array of tetrahedron neighbors; 4 ints per element. Output only. """ - neighborlist::Array{Cint,2} + neighborlist::Array{Cint, 2} """ 'facetlist': An array of facets. Each entry is a structure of facet. """ - facetlist::Array{RawFacet{T},1} + facetlist::Array{RawFacet{T}, 1} """ 'facetmarkerlist': An array of facet markers; one int per facet. """ - facetmarkerlist::Array{Cint,1} + facetmarkerlist::Array{Cint, 1} """ 'holelist': An array of holes (in volume). Each hole is given by a point which lies strictly inside it. """ - holelist::Array{T,2} + holelist::Array{T, 2} """ 'regionlist': An array of regions (subdomains). Each region is given by @@ -119,7 +118,7 @@ mutable struct RawTetGenIO{T} switch, and each volume constraint is used only if you select the 'a' switch (with no number following). """ - regionlist::Array{T,2} + regionlist::Array{T, 2} """ 'facetconstraintlist': An array of facet constraints. Each constraint @@ -128,7 +127,7 @@ mutable struct RawTetGenIO{T} maximum area bound at index [2]. Note: the facet marker is actually an integer. """ - facetconstraintlist::Array{T,2} + facetconstraintlist::Array{T, 2} """ 'segmentconstraintlist': An array of segment constraints. Each constraint @@ -137,22 +136,22 @@ mutable struct RawTetGenIO{T} index [1] and [2], and the maximum length bound at index [3]. Note the segment endpoints are actually integers. """ - segmentconstraintlist::Array{T,2} + segmentconstraintlist::Array{T, 2} """ 'trifacelist': An array of face (triangle) corners. """ - trifacelist::Array{Cint,2} + trifacelist::Array{Cint, 2} """ 'trifacemarkerlist': An array of face markers; one int per face. """ - trifacemarkerlist::Array{Cint,1} + trifacemarkerlist::Array{Cint, 1} """ 'edgelist': An array of edge endpoints. """ - edgelist::Array{Cint,2} + edgelist::Array{Cint, 2} """ 'edgemarkerlist': An array of edge markers. @@ -166,75 +165,69 @@ $(TYPEDSIGNATURES) Create RawTetGenIO structure with empty data. """ function RawTetGenIO{T}(; - pointlist=Array{T,2}(undef,0,0), - pointattributelist=Array{T,2}(undef,0,0), - pointmtrlist=Array{T,2}(undef,0,0), - pointmarkerlist=Array{Cint,1}(undef,0), - tetrahedronlist=Array{Cint,2}(undef,0,0), - tetrahedronattributelist=Array{T,2}(undef,0,0), - tetrahedronvolumelist=Array{T,1}(undef,0), - neighborlist=Array{Cint,2}(undef,0,0), - facetlist=Array{RawFacet{T},1}(undef,0), - facetmarkerlist=Array{Cint,1}(undef,0), - holelist=Array{T,2}(undef,0,0), - regionlist=Array{T,2}(undef,0,0), - facetconstraintlist=Array{T,2}(undef,0,0), - segmentconstraintlist=Array{T,2}(undef,0,0), - trifacelist=Array{Cint,2}(undef,0,0), - trifacemarkerlist=Array{Cint,1}(undef,0), - edgelist=Array{Cint,2}(undef,0,0), - edgemarkerlist=Array{Cint}(undef,0) - ) where T - RawTetGenIO{T}( - pointlist, - pointattributelist, - pointmtrlist, - pointmarkerlist, - tetrahedronlist, - tetrahedronattributelist, - tetrahedronvolumelist, - neighborlist, - facetlist, - facetmarkerlist, - holelist, - regionlist, - facetconstraintlist, - segmentconstraintlist, - trifacelist, - trifacemarkerlist, - edgelist, - edgemarkerlist - ) + pointlist = Array{T, 2}(undef, 0, 0), + pointattributelist = Array{T, 2}(undef, 0, 0), + pointmtrlist = Array{T, 2}(undef, 0, 0), + pointmarkerlist = Array{Cint, 1}(undef, 0), + tetrahedronlist = Array{Cint, 2}(undef, 0, 0), + tetrahedronattributelist = Array{T, 2}(undef, 0, 0), + tetrahedronvolumelist = Array{T, 1}(undef, 0), + neighborlist = Array{Cint, 2}(undef, 0, 0), + facetlist = Array{RawFacet{T}, 1}(undef, 0), + facetmarkerlist = Array{Cint, 1}(undef, 0), + holelist = Array{T, 2}(undef, 0, 0), + regionlist = Array{T, 2}(undef, 0, 0), + facetconstraintlist = Array{T, 2}(undef, 0, 0), + segmentconstraintlist = Array{T, 2}(undef, 0, 0), + trifacelist = Array{Cint, 2}(undef, 0, 0), + trifacemarkerlist = Array{Cint, 1}(undef, 0), + edgelist = Array{Cint, 2}(undef, 0, 0), + edgemarkerlist = Array{Cint}(undef, 0)) where {T} + RawTetGenIO{T}(pointlist, + pointattributelist, + pointmtrlist, + pointmarkerlist, + tetrahedronlist, + tetrahedronattributelist, + tetrahedronvolumelist, + neighborlist, + facetlist, + facetmarkerlist, + holelist, + regionlist, + facetconstraintlist, + segmentconstraintlist, + trifacelist, + trifacemarkerlist, + edgelist, + edgemarkerlist) end - - - function Base.show(io::IO, tio::RawTetGenIO) - nonempty(a)=size(a,ndims(a))>0 - println(io,"RawTetGenIO(") - print(io,"numberofpoints=") - print(io,numberofpoints(tio)) - println(io,",") - print(io,"numberofedges=") - print(io,numberofedges(tio)) - println(io,",") - print(io,"numberoftrifaces=") - print(io,numberoftrifaces(tio)) - println(io,",") - print(io,"numberoftetrahedra=") - print(io,numberoftetrahedra(tio)) - println(io,",") + nonempty(a) = size(a, ndims(a)) > 0 + println(io, "RawTetGenIO(") + print(io, "numberofpoints=") + print(io, numberofpoints(tio)) + println(io, ",") + print(io, "numberofedges=") + print(io, numberofedges(tio)) + println(io, ",") + print(io, "numberoftrifaces=") + print(io, numberoftrifaces(tio)) + println(io, ",") + print(io, "numberoftetrahedra=") + print(io, numberoftetrahedra(tio)) + println(io, ",") for name in fieldnames(typeof(tio)) -# a=round.(getfield(tio,name),sigdigits=3)' - a=getfield(tio,name) + # a=round.(getfield(tio,name),sigdigits=3)' + a = getfield(tio, name) if nonempty(a) - print(io,"$(name)'=") - print(io,a) - println(io,",") + print(io, "$(name)'=") + print(io, a) + println(io, ",") end end - println(io,")") + println(io, ")") end """ @@ -243,10 +236,10 @@ end size (e.g. triangles) """ function facetlist!(tio::RawTetGenIO{T}, facets::AbstractMatrix) where {T} - numberoffacets=size(facets,2) - tio.facetlist=Array{RawFacet{T},1}(undef,numberoffacets) - for ifacet=1:numberoffacets - tio.facetlist[ifacet]=RawFacet{T}([Vector{Cint}(facets[:,ifacet])],Array{T,2}(undef,0,0)) + numberoffacets = size(facets, 2) + tio.facetlist = Array{RawFacet{T}, 1}(undef, numberoffacets) + for ifacet = 1:numberoffacets + tio.facetlist[ifacet] = RawFacet{T}([Vector{Cint}(facets[:, ifacet])], Array{T, 2}(undef, 0, 0)) end tio end @@ -256,24 +249,21 @@ end Set list of input facets from a vector of polygons of different size """ function facetlist!(tio::RawTetGenIO{T}, facets::Vector) where {T} - numberoffacets=size(facets,1) - tio.facetlist=Array{RawFacet{T},1}(undef,numberoffacets) - for ifacet=1:numberoffacets - tio.facetlist[ifacet]=RawFacet{T}([Vector{Cint}(facets[ifacet])],Array{T,2}(undef,0,0)) + numberoffacets = size(facets, 1) + tio.facetlist = Array{RawFacet{T}, 1}(undef, numberoffacets) + for ifacet = 1:numberoffacets + tio.facetlist[ifacet] = RawFacet{T}([Vector{Cint}(facets[ifacet])], Array{T, 2}(undef, 0, 0)) end tio end - - # # Create CPPTetGenIO from RawTetGenIO # -function CPPTetGenIO(tio::RawTetGenIO{T}) where T - +function CPPTetGenIO(tio::RawTetGenIO{T}) where {T} firstnumber = 1 mesh_dim = 3 - + # Set dummy defaults pointlist = C_NULL pointattributelist = C_NULL @@ -283,17 +273,17 @@ function CPPTetGenIO(tio::RawTetGenIO{T}) where T numberofpoints = zero(Cint) numberofpointattributes = zero(Cint) numberofpointmtrs = zero(Cint) - + tetrahedronlist = C_NULL tetrahedronattributelist = C_NULL tetrahedronvolumelist = C_NULL - + neighborlist = C_NULL numberoftetrahedra = zero(Cint) numberofcorners = zero(Cint) numberoftetrahedronattributes = zero(Cint) - - facetlist = C_NULL + + facetlist = C_NULL facetmarkerlist = C_NULL numberoffacets = zero(Cint) @@ -319,105 +309,106 @@ function CPPTetGenIO(tio::RawTetGenIO{T}) where T # these need to be returned in order # to prevent their content from being garbage collected - facetlist_array=Array{CFacet{T},1}(undef,numberoffacets) - polygonlist_array=Array{Array{CPolygon,1},1}(undef,0) - + facetlist_array = Array{CFacet{T}, 1}(undef, numberoffacets) + polygonlist_array = Array{Array{CPolygon, 1}, 1}(undef, 0) + # Override defaults - numberofpoints=size(tio.pointlist,2) - @assert numberofpoints>zero(Cint) - @assert size(tio.pointlist,1) == 3 - pointlist=pointer(tio.pointlist) - - numberofpointattributes=size(tio.pointattributelist,1) - if numberofpointattributes>0 - @assert size(tio.pointattributelist,2)==numberofpoints - pointattributelist=pointer(tio.pointattributelist) + numberofpoints = size(tio.pointlist, 2) + @assert numberofpoints > zero(Cint) + @assert size(tio.pointlist, 1) == 3 + pointlist = pointer(tio.pointlist) + + numberofpointattributes = size(tio.pointattributelist, 1) + if numberofpointattributes > 0 + @assert size(tio.pointattributelist, 2) == numberofpoints + pointattributelist = pointer(tio.pointattributelist) end - - numberofpointmtrs=size(tio.pointmtrlist,1) - if numberofpointmtrs>0 - @assert size(tio.pointmtrlist,2)==numberofpoints - pointmtrlist=pointer(tio.pointmtrlist) + + numberofpointmtrs = size(tio.pointmtrlist, 1) + if numberofpointmtrs > 0 + @assert size(tio.pointmtrlist, 2) == numberofpoints + pointmtrlist = pointer(tio.pointmtrlist) end - - numberoftetrahedra=size(tio.tetrahedronlist,2) - if numberoftetrahedra>0 - tetrahedronlist=pointer(tio.tetrahedronlist) - numberoftetrahedronattributes=size(tio.tetrahedronattributelist,1) - numberofcorners=size(tio.tetrahedronlist,1) - if numberoftetrahedronattributes>0 - @assert size(tio.tetrahedronattributelist,2)==numberoftetrahedra - tetrahedronattributelist=pointer(tio.tetrahedronattributelist) + + numberoftetrahedra = size(tio.tetrahedronlist, 2) + if numberoftetrahedra > 0 + tetrahedronlist = pointer(tio.tetrahedronlist) + numberoftetrahedronattributes = size(tio.tetrahedronattributelist, 1) + numberofcorners = size(tio.tetrahedronlist, 1) + if numberoftetrahedronattributes > 0 + @assert size(tio.tetrahedronattributelist, 2) == numberoftetrahedra + tetrahedronattributelist = pointer(tio.tetrahedronattributelist) end - if size(tio.tetrahedronvolumelist,1)>0 - @assert size(tio.tetrahedronvolumelist,1)==numberoftetrahedra - tetrahedronvolumelist=pointer(tio.tetrahedronvolumelist) + if size(tio.tetrahedronvolumelist, 1) > 0 + @assert size(tio.tetrahedronvolumelist, 1) == numberoftetrahedra + tetrahedronvolumelist = pointer(tio.tetrahedronvolumelist) end end - - numberoffacets=size(tio.facetlist,1) - if numberoffacets>0 - for ifacet=1:numberoffacets - facet=tio.facetlist[ifacet] - numberofpolygons=size(facet.polygonlist,1) - polygonlist=Array{CPolygon,1}(undef, numberofpolygons) - for ipolygon=1:numberofpolygons - polygonlist[ipolygon]=CPolygon(pointer(facet.polygonlist[ipolygon]),size(facet.polygonlist[ipolygon],1)) + + numberoffacets = size(tio.facetlist, 1) + if numberoffacets > 0 + for ifacet = 1:numberoffacets + facet = tio.facetlist[ifacet] + numberofpolygons = size(facet.polygonlist, 1) + polygonlist = Array{CPolygon, 1}(undef, numberofpolygons) + for ipolygon = 1:numberofpolygons + polygonlist[ipolygon] = CPolygon(pointer(facet.polygonlist[ipolygon]), size(facet.polygonlist[ipolygon], 1)) end - numberofholes=size(facet.holelist,2) - push!(polygonlist_array,polygonlist) - push!(facetlist_array,CFacet(pointer(polygonlist),Cint(numberofpolygons),pointer(facet.holelist),Cint(numberofholes))) + numberofholes = size(facet.holelist, 2) + push!(polygonlist_array, polygonlist) + push!(facetlist_array, + CFacet(pointer(polygonlist), Cint(numberofpolygons), pointer(facet.holelist), Cint(numberofholes))) end - facetlist=pointer(facetlist_array) + facetlist = pointer(facetlist_array) end - - if size(tio.facetmarkerlist,1)>0 - @assert size(tio.facetmarkerlist,1)==numberoffacets - facetmarkerlist=pointer(tio.facetmarkerlist) + + if size(tio.facetmarkerlist, 1) > 0 + @assert size(tio.facetmarkerlist, 1) == numberoffacets + facetmarkerlist = pointer(tio.facetmarkerlist) end - numberofholes=size(tio.holelist,2) - if numberofholes>0 - @assert size(tio.holelist,1)==3 - holelist=pointer(tio.holelist) + numberofholes = size(tio.holelist, 2) + if numberofholes > 0 + @assert size(tio.holelist, 1) == 3 + holelist = pointer(tio.holelist) end - - numberofregions=size(tio.regionlist,2) - if numberofregions>0 - @assert size(tio.regionlist,1)==5 # coord+attribute + volume - regionlist=pointer(tio.regionlist) + + numberofregions = size(tio.regionlist, 2) + if numberofregions > 0 + @assert size(tio.regionlist, 1) == 5 # coord+attribute + volume + regionlist = pointer(tio.regionlist) end - if size(tio.facetconstraintlist,2)>0 - @assert size(tio.facetconstraintlist,1) == 2 - numberoffacetconstraints=size(tio.facetconstraintlist,2) - facetconstraintlist=pointer(tio.facetconstraintlist) + if size(tio.facetconstraintlist, 2) > 0 + @assert size(tio.facetconstraintlist, 1) == 2 + numberoffacetconstraints = size(tio.facetconstraintlist, 2) + facetconstraintlist = pointer(tio.facetconstraintlist) end - if size(tio.segmentconstraintlist,2)>0 - @assert size(tio.segmentconstraintlist,1) == 3 - numberofsegmentconstraints=size(tio.segmentconstraintlist,2) - segmentconstraintlist=pointer(tio.segmentconstraintlist) + if size(tio.segmentconstraintlist, 2) > 0 + @assert size(tio.segmentconstraintlist, 1) == 3 + numberofsegmentconstraints = size(tio.segmentconstraintlist, 2) + segmentconstraintlist = pointer(tio.segmentconstraintlist) end - if size(tio.trifacelist,2)>0 - @assert size(tio.trifacelist,1) == 3 - numberoftrifaces=size(tio.trifacelist,2) - trifacelist=pointer(tio.trifacelist) - if size(tio.trifacemarkerlist,1) > 0 - @assert size(tio.trifacemarkerlist,1) == numberoftrifaces - trifacemarkerlist=pointer(tio.trifacemarkerlist) - end + if size(tio.trifacelist, 2) > 0 + @assert size(tio.trifacelist, 1) == 3 + numberoftrifaces = size(tio.trifacelist, 2) + trifacelist = pointer(tio.trifacelist) + if size(tio.trifacemarkerlist, 1) > 0 + @assert size(tio.trifacemarkerlist, 1) == numberoftrifaces + trifacemarkerlist = pointer(tio.trifacemarkerlist) + end end - - if size(tio.edgelist,2)>0 - @assert size(tio.edgelist,1) == 2 - numberofedges=size(tio.edgelist,2) - edgelist=pointer(tio.edgelist) - if size(tio.edgemarkerlist,1) > 0 - @assert size(tio.edgemarkerlist,1) == numberofedges - edgemarkerlist=pointer(tio.edgemarkerlist) - end + + if size(tio.edgelist, 2) > 0 + @assert size(tio.edgelist, 1) == 2 + numberofedges = size(tio.edgelist, 2) + edgelist = pointer(tio.edgelist) + if size(tio.edgemarkerlist, 1) > 0 + @assert size(tio.edgemarkerlist, 1) == numberofedges + edgemarkerlist = pointer(tio.edgemarkerlist) + end end # Create struct @@ -453,44 +444,53 @@ function CPPTetGenIO(tio::RawTetGenIO{T}) where T numberoftrifaces, edgelist, edgemarkerlist, - numberofedges),facetlist_array, polygonlist_array + numberofedges), facetlist_array, polygonlist_array end - - # # Create RawTetGenIO from CPPTetGenIO # -function RawTetGenIO(ctio::CPPTetGenIO{T}) where T - - tio=RawTetGenIO{T}() - if ctio.numberofpoints>0 && ctio.pointlist!=C_NULL - tio.pointlist = convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointlist, (3,Int(ctio.numberofpoints)), own=true)) +function RawTetGenIO(ctio::CPPTetGenIO{T}) where {T} + tio = RawTetGenIO{T}() + if ctio.numberofpoints > 0 && ctio.pointlist != C_NULL + tio.pointlist = convert(Array{T, 2}, Base.unsafe_wrap(Array, ctio.pointlist, (3, Int(ctio.numberofpoints)); own = true)) end - if ctio.numberofpointattributes>0 && ctio.pointattributelist!=C_NULL - tio.pointattributelist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointattributelist, (Int(ctio.numberofpointattributes),Int(ctio.numberofpoints)), own=true)) + if ctio.numberofpointattributes > 0 && ctio.pointattributelist != C_NULL + tio.pointattributelist = convert(Array{T, 2}, + Base.unsafe_wrap(Array, ctio.pointattributelist, + (Int(ctio.numberofpointattributes), Int(ctio.numberofpoints)); + own = true)) end - if ctio.numberofpointmtrs>0 && ctio.pointmtrlist!=C_NULL - tio.pointmtrlist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointmtrlist, (Int(ctio.numberofpointmtrs),Int(ctio.numberofpoints)), own=true)) + if ctio.numberofpointmtrs > 0 && ctio.pointmtrlist != C_NULL + tio.pointmtrlist = convert(Array{T, 2}, + Base.unsafe_wrap(Array, ctio.pointmtrlist, + (Int(ctio.numberofpointmtrs), Int(ctio.numberofpoints)); own = true)) end - if ctio.pointmarkerlist!=C_NULL - tio.pointmarkerlist=convert(Array{Cint,1}, Base.unsafe_wrap(Array, ctio.pointmarkerlist, (Int(ctio.numberofpoints)), own=true)) + if ctio.pointmarkerlist != C_NULL + tio.pointmarkerlist = convert(Array{Cint, 1}, + Base.unsafe_wrap(Array, ctio.pointmarkerlist, (Int(ctio.numberofpoints)); own = true)) end - @assert ctio.numberofcorners==4 - if ctio.numberoftetrahedra>0 && ctio.tetrahedronlist!=C_NULL - tio.tetrahedronlist=convert(Array{Cint,2}, Base.unsafe_wrap(Array, ctio.tetrahedronlist, (4,Int(ctio.numberoftetrahedra)), own=true)) + @assert ctio.numberofcorners == 4 + if ctio.numberoftetrahedra > 0 && ctio.tetrahedronlist != C_NULL + tio.tetrahedronlist = convert(Array{Cint, 2}, + Base.unsafe_wrap(Array, ctio.tetrahedronlist, (4, Int(ctio.numberoftetrahedra)); own = true)) end - if ctio.numberoftetrahedronattributes>0 && ctio.tetrahedronattributelist!=C_NULL - tio.tetrahedronattributelist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.tetrahedronattributelist, (Int(ctio.numberoftetrahedronattributes),Int(ctio.numberoftetrahedra)), own=true)) + if ctio.numberoftetrahedronattributes > 0 && ctio.tetrahedronattributelist != C_NULL + tio.tetrahedronattributelist = convert(Array{T, 2}, + Base.unsafe_wrap(Array, ctio.tetrahedronattributelist, + (Int(ctio.numberoftetrahedronattributes), + Int(ctio.numberoftetrahedra)); own = true)) end - if ctio.tetrahedronvolumelist!=C_NULL - tio.tetrahedronvolumelist=convert(Array{T,1}, Base.unsafe_wrap(Array, ctio.tetrahedronvolumelist, (Int(ctio.numberoftetrahedra)), own=true)) + if ctio.tetrahedronvolumelist != C_NULL + tio.tetrahedronvolumelist = convert(Array{T, 1}, + Base.unsafe_wrap(Array, ctio.tetrahedronvolumelist, (Int(ctio.numberoftetrahedra)); + own = true)) end - if ctio.numberoftetrahedra>0 && ctio.neighborlist!=C_NULL - tio.neighborlist=convert(Array{Cint,2}, Base.unsafe_wrap(Array, ctio.neighborlist, (4,Int(ctio.numberoftetrahedra)), own=true)) + if ctio.numberoftetrahedra > 0 && ctio.neighborlist != C_NULL + tio.neighborlist = convert(Array{Cint, 2}, + Base.unsafe_wrap(Array, ctio.neighborlist, (4, Int(ctio.numberoftetrahedra)); own = true)) end - # Essentially, facetlist appears to be used only during input, so we can skip the # conversion here (and increase test coverage...). # The created facets are in the trifacelist further down this code. @@ -516,69 +516,73 @@ function RawTetGenIO(ctio::CPPTetGenIO{T}) where T # Usually, this ctio comes from the output of tetrahedralize(). In this case, the holelist pointer is copied from the input # so we would get a double free corruption if we own it here. - if ctio.numberofholes>0 && ctio.holelist!=C_NULL - tio.holelist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.holelist, (3,Int(ctio.numberofholes)), own=false)) + if ctio.numberofholes > 0 && ctio.holelist != C_NULL + tio.holelist = convert(Array{T, 2}, Base.unsafe_wrap(Array, ctio.holelist, (3, Int(ctio.numberofholes)); own = false)) end - + # Usually, this ctio comes from the output of tetrahedralize(). In this case, the regionlist pointer is copied from the input # so we would get a double free corruption if we own it here. - if ctio.numberofregions>0 && ctio.regionlist!=C_NULL - tio.regionlist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.regionlist, (5,Int(ctio.numberofregions)), own=false)) + if ctio.numberofregions > 0 && ctio.regionlist != C_NULL + tio.regionlist = convert(Array{T, 2}, Base.unsafe_wrap(Array, ctio.regionlist, (5, Int(ctio.numberofregions)); own = false)) end # own ? May be comes from input - if ctio.numberoffacetconstraints>0 - tio.facetconstraintlist=convert(Array{T,1}, Base.unsafe_wrap(Array, ctio.facetconstraintlist, (2,ctio.numberoffacetconstraints), own=false)) + if ctio.numberoffacetconstraints > 0 + tio.facetconstraintlist = convert(Array{T, 1}, + Base.unsafe_wrap(Array, ctio.facetconstraintlist, (2, ctio.numberoffacetconstraints); + own = false)) end - + # own ? May be comes from input - if ctio.numberofsegmentconstraints>0 - tio.segmentconstraintlist=convert(Array{T,1}, Base.unsafe_wrap(Array, ctio.segmentconstraintlist, (3,ctio.numberofsegmentconstraints), own=false)) + if ctio.numberofsegmentconstraints > 0 + tio.segmentconstraintlist = convert(Array{T, 1}, + Base.unsafe_wrap(Array, ctio.segmentconstraintlist, + (3, ctio.numberofsegmentconstraints); own = false)) end - - if ctio.numberoftrifaces>0 && ctio.trifacelist!=C_NULL && ctio.trifacemarkerlist!=C_NULL - tio.trifacelist=convert(Array{Cint,2}, Base.unsafe_wrap(Array, ctio.trifacelist, (3,Int(ctio.numberoftrifaces)), own=true)) - tio.trifacemarkerlist=convert(Array{Cint,1}, Base.unsafe_wrap(Array, ctio.trifacemarkerlist, (Int(ctio.numberoftrifaces)), own=true)) + if ctio.numberoftrifaces > 0 && ctio.trifacelist != C_NULL && ctio.trifacemarkerlist != C_NULL + tio.trifacelist = convert(Array{Cint, 2}, + Base.unsafe_wrap(Array, ctio.trifacelist, (3, Int(ctio.numberoftrifaces)); own = true)) + tio.trifacemarkerlist = convert(Array{Cint, 1}, + Base.unsafe_wrap(Array, ctio.trifacemarkerlist, (Int(ctio.numberoftrifaces)); own = true)) end - if ctio.numberofedges>0 && ctio.edgelist!=C_NULL && ctio.edgemarkerlist!=C_NULL - tio.edgelist=convert(Array{Cint,2}, Base.unsafe_wrap(Array, ctio.edgelist, (2,Int(ctio.numberofedges)), own=true)) - tio.edgemarkerlist=convert(Array{Cint,1}, Base.unsafe_wrap(Array, ctio.edgemarkerlist, (Int(ctio.numberofedges)), own=true)) + if ctio.numberofedges > 0 && ctio.edgelist != C_NULL && ctio.edgemarkerlist != C_NULL + tio.edgelist = convert(Array{Cint, 2}, Base.unsafe_wrap(Array, ctio.edgelist, (2, Int(ctio.numberofedges)); own = true)) + tio.edgemarkerlist = convert(Array{Cint, 1}, + Base.unsafe_wrap(Array, ctio.edgemarkerlist, (Int(ctio.numberofedges)); own = true)) end return tio end - """ $(TYPEDSIGNATURES) Number of points in tetrahedralization """ -numberofpoints(tio::RawTetGenIO{T}) where T= size(tio.pointlist,2) +numberofpoints(tio::RawTetGenIO{T}) where {T} = size(tio.pointlist, 2) """ $(TYPEDSIGNATURES) Number of tetrahedra in tetrahedralization """ -numberoftetrahedra(tio::RawTetGenIO{T}) where T= size(tio.tetrahedronlist,2) +numberoftetrahedra(tio::RawTetGenIO{T}) where {T} = size(tio.tetrahedronlist, 2) """ $(TYPEDSIGNATURES) Number of triangle faces in tetrahedralization """ -numberoftrifaces(tio::RawTetGenIO{T}) where T= size(tio.trifacelist,2) +numberoftrifaces(tio::RawTetGenIO{T}) where {T} = size(tio.trifacelist, 2) """ $(TYPEDSIGNATURES) Number of edges in tetrahedralization """ -numberofedges(tio::RawTetGenIO{T}) where T= size(tio.edgelist,2) - +numberofedges(tio::RawTetGenIO{T}) where {T} = size(tio.edgelist, 2) """ $(TYPEDSIGNATURES) @@ -624,11 +628,11 @@ Tetrahedralize input. ```` """ function tetrahedralize(input::RawTetGenIO{Float64}, flags::String) - cinput,flist,plist=CPPTetGenIO(input) - rc=Cint[0] + cinput, flist, plist = CPPTetGenIO(input) + rc = Cint[0] coutput = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), cinput, flags, rc) - if rc[1]!=0 + if rc[1] != 0 throw(TetGenError(rc[1])) end RawTetGenIO(coutput) @@ -640,16 +644,15 @@ $(SIGNATURES) Tetrahedralize stl file. """ function tetrahedralize(stlfile::String, flags::String) - base=rsplit(stlfile,".",limit=2)[1] - rc=Cint[0] - coutput = ccall((:tetrahedralize2_stl_f64, libtet), CPPTetGenIO{Float64}, (Cstring, Cstring, Ptr{Cint}), base, flags, rc) - if rc[1]!=0 + base = rsplit(stlfile, "."; limit = 2)[1] + rc = Cint[0] + coutput = ccall((:tetrahedralize2_stl_f64, libtet), CPPTetGenIO{Float64}, (Cstring, Cstring, Ptr{Cint}), base, flags, rc) + if rc[1] != 0 throw(TetGenError(rc[1])) end RawTetGenIO(coutput) end - """ $(TYPEDSIGNATURES) @@ -657,9 +660,9 @@ Create GeometryBasics.Mesh from the triface list (for quick visualization purposes using Makie's wireframe). """ function surfacemesh(tgio::RawTetGenIO) - points=[ Point3f(tgio.pointlist[:,i]...) for i=1:size(tgio.pointlist,2)] - faces= [TriangleFace(tgio.trifacelist[:,i]...) for i=1:size(tgio.trifacelist,2)] - mesh=GeometryBasics.Mesh(points,faces) + points = [Point3f(tgio.pointlist[:, i]...) for i = 1:size(tgio.pointlist, 2)] + faces = [TriangleFace(tgio.trifacelist[:, i]...) for i = 1:size(tgio.trifacelist, 2)] + mesh = GeometryBasics.Mesh(points, faces) end """ @@ -669,16 +672,15 @@ Create GeometryBasics.Mesh of all tetrahedron faces (for quick visualization purposes using Makie's wireframe). """ function volumemesh(tgio::RawTetGenIO) - points=[ Point3f(tgio.pointlist[:,i]...) for i=1:size(tgio.pointlist,2)] - faces=Array{NgonFace{3,Int32},1}(undef,0) - tetlist=tgio.tetrahedronlist - for itet=1:size(tetlist,2) - tet=view(tetlist,:, itet) - push!(faces,TriangleFace(tet[1],tet[2],tet[3])) - push!(faces,TriangleFace(tet[1],tet[2],tet[4])) - push!(faces,TriangleFace(tet[2],tet[3],tet[4])) - push!(faces,TriangleFace(tet[3],tet[1],tet[4])) + points = [Point3f(tgio.pointlist[:, i]...) for i = 1:size(tgio.pointlist, 2)] + faces = Array{NgonFace{3, Int32}, 1}(undef, 0) + tetlist = tgio.tetrahedronlist + for itet = 1:size(tetlist, 2) + tet = view(tetlist, :, itet) + push!(faces, TriangleFace(tet[1], tet[2], tet[3])) + push!(faces, TriangleFace(tet[1], tet[2], tet[4])) + push!(faces, TriangleFace(tet[2], tet[3], tet[4])) + push!(faces, TriangleFace(tet[3], tet[1], tet[4])) end - mesh=GeometryBasics.Mesh(points,faces) + mesh = GeometryBasics.Mesh(points, faces) end - diff --git a/test/runtests.jl b/test/runtests.jl index b8178bb..8cc851f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,25 +8,21 @@ using Test @testset "mesh based API" begin # Construct a cube out of Quads - points = Point{3, Float64}[ - (0.0, 0.0, 0.0), (2.0, 0.0, 0.0), + points = Point{3, Float64}[(0.0, 0.0, 0.0), (2.0, 0.0, 0.0), (2.0, 2.0, 0.0), (0.0, 2.0, 0.0), (0.0, 0.0, 12.0), (2.0, 0.0, 12.0), - (2.0, 2.0, 12.0), (0.0, 2.0, 12.0) - ] + (2.0, 2.0, 12.0), (0.0, 2.0, 12.0)] - facets = QuadFace{Cint}[ - 1:4, + facets = QuadFace{Cint}[1:4, 5:8, - [1,5,6,2], - [2,6,7,3], + [1, 5, 6, 2], + [2, 6, 7, 3], [3, 7, 8, 4], - [4, 8, 5, 1] - ] + [4, 8, 5, 1]] markers = Cint[-1, -2, 0, 0, 0, 0] # attach some additional information to our faces! - mesh = Mesh(points, meta(facets, markers = markers)) + mesh = Mesh(points, meta(facets; markers = markers)) result = tetrahedralize(mesh) @test result isa Mesh @@ -34,30 +30,23 @@ using Test result = tetrahedralize(mesh, "vpq1.414a0.1") @test result isa Mesh - points = rand(Point{3, Float64}, 100) result = TetGen.voronoi(points) @test result isa Mesh - - tetpoints = Point{3, Float64}[ - (0.0, 0.0, 0.0), + tetpoints = Point{3, Float64}[(0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0), - (0.0, 0.0, 1.0) - ] - - tetfacets = TriangleFace{Cint}[ - [1,2,3], - [1,2,4], - [1,3,4], - [2,3,4] - ] - - tetmesh=Mesh(tetpoints,tetfacets) - result = tetrahedralize(tetmesh,"pQqAa0.01") - @test result isa Mesh + (0.0, 0.0, 1.0)] + tetfacets = TriangleFace{Cint}[[1, 2, 3], + [1, 2, 4], + [1, 3, 4], + [2, 3, 4]] + + tetmesh = Mesh(tetpoints, tetfacets) + result = tetrahedralize(tetmesh, "pQqAa0.01") + @test result isa Mesh ################# cube with hole example # Construct a cube out of Quads @@ -72,35 +61,30 @@ using Test (-1.0, -1.0, -1.0), (1.0, -1.0, -1.0), (1.0, 1.0, -1.0), (-1.0, 1.0, -1.0), (-1.0, -1.0, 1.0), (1.0, -1.0, 1.0), - (1.0, 1.0, 1.0), (-1.0, 1.0, 1.0), - ] + (1.0, 1.0, 1.0), (-1.0, 1.0, 1.0)] facets = QuadFace{Cint}[ # outer cube: - [1,2,3,4], - [5,6,7,8], - [1,5,6,2], - [2,6,7,3], - [3,7,8,4], - [4,8,5,1], + [1, 2, 3, 4], + [5, 6, 7, 8], + [1, 5, 6, 2], + [2, 6, 7, 3], + [3, 7, 8, 4], + [4, 8, 5, 1], # inner cube: - [1,2,3,4].+8, - [5,6,7,8].+8, - [1,5,6,2].+8, - [2,6,7,3].+8, - [3,7,8,4].+8, - [4,8,5,1].+8, - ] - - markers = ones(Cint,12) - mesh = Mesh(points, meta(facets, markers = markers)) - resultx = tetrahedralize(mesh,holes = [Point{3, Float64}(0,0,0)],"pQqAa1.0") + [1, 2, 3, 4] .+ 8, + [5, 6, 7, 8] .+ 8, + [1, 5, 6, 2] .+ 8, + [2, 6, 7, 3] .+ 8, + [3, 7, 8, 4] .+ 8, + [4, 8, 5, 1] .+ 8] + + markers = ones(Cint, 12) + mesh = Mesh(points, meta(facets; markers = markers)) + resultx = tetrahedralize(mesh, "pQqAa1.0"; holes = [Point{3, Float64}(0, 0, 0)]) @test result isa Mesh - - - # s = Sphere{Float64}(Point(0.0, 0.0, 0.0), 2.0) # # x = PlainMesh{Float64, Triangle{Cint}}(s) @@ -119,142 +103,119 @@ using Test end - - @testset "examples.jl" begin - include("../examples/examples.jl") function generic_test(result::RawTetGenIO) @test volumemesh(result) isa Mesh - if numberoftrifaces(result)>0 + if numberoftrifaces(result) > 0 @test surfacemesh(result) isa Mesh end - - buf=IOBuffer() - Base.show(buf,result) - @test length(buf.data)>0 - - ctio,flist,plist=TetGen.CPPTetGenIO(result) - @test ctio.numberofpoints==numberofpoints(result) - @test ctio.numberoftetrahedra==numberoftetrahedra(result) - @test ctio.numberoftrifaces==numberoftrifaces(result) + + buf = IOBuffer() + Base.show(buf, result) + @test length(buf.data) > 0 + + ctio, flist, plist = TetGen.CPPTetGenIO(result) + @test ctio.numberofpoints == numberofpoints(result) + @test ctio.numberoftetrahedra == numberoftetrahedra(result) + @test ctio.numberoftrifaces == numberoftrifaces(result) end - result = random_delaunay(npoints=100) - @test numberofpoints(result)==100 + result = random_delaunay(; npoints = 100) + @test numberofpoints(result) == 100 generic_test(result) result = cube() - @test numberofpoints(result)==8 - @test numberoftetrahedra(result)==6 - @test numberofedges(result)==12 - @test numberoftrifaces(result)==12 + @test numberofpoints(result) == 8 + @test numberoftetrahedra(result) == 6 + @test numberofedges(result) == 12 + @test numberoftrifaces(result) == 12 generic_test(result) result = cube_stl() - @test numberofpoints(result)==8 - @test numberoftetrahedra(result)==6 - @test numberofedges(result)==12 - @test numberoftrifaces(result)==12 + @test numberofpoints(result) == 8 + @test numberoftetrahedra(result) == 6 + @test numberofedges(result) == 12 + @test numberoftrifaces(result) == 12 generic_test(result) - - result = cubewithhole() - @test numberofpoints(result)==56 - @test numberoftetrahedra(result)==168 - @test numberofedges(result)==36 - @test numberoftrifaces(result)==104 + @test numberofpoints(result) == 56 + @test numberoftetrahedra(result) == 168 + @test numberofedges(result) == 36 + @test numberoftrifaces(result) == 104 generic_test(result) - result = prism() - @test numberofpoints(result)==8 - @test numberofedges(result)==11 - @test numberoftrifaces(result)==12 - @test numberoftetrahedra(result)==6 + @test numberofpoints(result) == 8 + @test numberofedges(result) == 11 + @test numberoftrifaces(result) == 12 + @test numberoftetrahedra(result) == 6 generic_test(result) - - - - - - - # exact numbers depend on FP aritmetic and # compiler optimizations result = cube_localref() generic_test(result) - result = material_prism() - @test numberoftetrahedra(result)>100 + @test numberoftetrahedra(result) > 100 generic_test(result) result = cutprism() - @test numberoftetrahedra(result)>100 + @test numberoftetrahedra(result) > 100 generic_test(result) - end - - - - @testset "error handling" begin - - function badcube1(;vol=1) - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 2; - 1 1 1; - 0 1 2]' - - TetGen.facetlist!(input,[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + function badcube1(; vol = 1) + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 2; + 1 1 1; + 0 1 2]' + + TetGen.facetlist!(input, [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa$(vol)") end - function badcube2(;vol=1) - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1; - 0 1 1-1.0e-5; - ]' - - TetGen.facetlist!(input,[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + function badcube2(; vol = 1) + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1; + 0 1 1-1.0e-5]' + + TetGen.facetlist!(input, [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa$(vol)") end - - function test_catch_error(geom) try - result=geom() + result = geom() catch err - if typeof(err)==TetGenError + if typeof(err) == TetGenError println("Catched TetGenError") println(err) return true @@ -262,7 +223,7 @@ end end false end - if !Sys.iswindows() + if !Sys.iswindows() @test test_catch_error(badcube2) end end @@ -270,38 +231,34 @@ end ############################################## # Solely for increasing codecov - @testset "codecov" begin - - input=TetGen.RawTetGenIO{Cdouble}() - input.pointlist=[0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1]' - - TetGen.facetlist!(input,[1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') - - cinput,x1,x2=TetGen.CPPTetGenIO(input) - coutput=tetrahedralize(cinput, "pQa") - - @test coutput.numberofpoints==8 + input = TetGen.RawTetGenIO{Cdouble}() + input.pointlist = [0 0 0; + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1]' + + TetGen.facetlist!(input, [1 2 3 4; + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') + + cinput, x1, x2 = TetGen.CPPTetGenIO(input) + coutput = tetrahedralize(cinput, "pQa") + + @test coutput.numberofpoints == 8 function test_error_output() - for i=1:10 - println( TetGenError(i)) + for i = 1:10 + println(TetGenError(i)) end true end @test test_error_output() - end - From 49bd2ff87c63a808075dddf45456b65c50744631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 17:12:10 +0100 Subject: [PATCH 4/8] (blindly) try to fix MemoryRef issue on nightly --- src/jltetgenio.jl | 170 ++++++++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 80 deletions(-) diff --git a/src/jltetgenio.jl b/src/jltetgenio.jl index c20bf11..01c4dba 100644 --- a/src/jltetgenio.jl +++ b/src/jltetgenio.jl @@ -85,80 +85,80 @@ struct JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, FT} edgemarkers::Vector{Cint} function JLTetGenIO(points::Vector{Point{3, T}}, - pointattributes::Vector{SVector{NAttributes, T}}, - pointmtrs::Vector{SVector{NMTr, T}}, - pointmarkers::Vector{Cint}, - tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, - tetrahedronattributes::Vector{T}, - tetrahedronvolumes::Vector{T}, - neighbors::Vector{Cint}, - facets::FT, - facetmarkers::Vector{Cint}, - holes::Vector{Point{3, T}}, - regions::Vector{Region{T}}, - facetconstraints::Vector{FacetConstraint{IT, T}}, - segmentconstraints::Vector{SegmentationConstraint{IT, T}}, - trifaces::Vector{TriangleFace{Cint}}, - trifacemarkers::Vector{Cint}, - edges::Vector{LineFace{Cint}}, - edgemarkers::Vector{Cint}) where {T, NSimplex, NAttributes, NMTr, IT, FT} + pointattributes::Vector{SVector{NAttributes, T}}, + pointmtrs::Vector{SVector{NMTr, T}}, + pointmarkers::Vector{Cint}, + tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, + tetrahedronattributes::Vector{T}, + tetrahedronvolumes::Vector{T}, + neighbors::Vector{Cint}, + facets::FT, + facetmarkers::Vector{Cint}, + holes::Vector{Point{3, T}}, + regions::Vector{Region{T}}, + facetconstraints::Vector{FacetConstraint{IT, T}}, + segmentconstraints::Vector{SegmentationConstraint{IT, T}}, + trifaces::Vector{TriangleFace{Cint}}, + trifacemarkers::Vector{Cint}, + edges::Vector{LineFace{Cint}}, + edgemarkers::Vector{Cint}) where {T, NSimplex, NAttributes, NMTr, IT, FT} new{T, NSimplex, NAttributes, NMTr, IT, FT}(points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers) + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end end function JLTetGenIO(points::Vector{Point{3, T}}; - pointattributes = SVector{0, T}[], - pointmtrs = SVector{0, T}[], - pointmarkers = Cint[], - tetrahedrons = SimplexFace{4, Cint}[], - tetrahedronattributes = T[], - tetrahedronvolumes = T[], - neighbors = Cint[], - facets = JLFacet{T, Vector{Cint}}[], - facetmarkers = Cint[], - holes = Point{3, T}[], - regions = Region{T}[], - facetconstraints = FacetConstraint{inttype(T), T}[], - segmentconstraints = SegmentationConstraint{inttype(T), T}[], - trifaces = TriangleFace{Cint}[], - trifacemarkers = Cint[], - edges = LineFace{Cint}[], - edgemarkers = Cint[]) where {T} + pointattributes = SVector{0, T}[], + pointmtrs = SVector{0, T}[], + pointmarkers = Cint[], + tetrahedrons = SimplexFace{4, Cint}[], + tetrahedronattributes = T[], + tetrahedronvolumes = T[], + neighbors = Cint[], + facets = JLFacet{T, Vector{Cint}}[], + facetmarkers = Cint[], + holes = Point{3, T}[], + regions = Region{T}[], + facetconstraints = FacetConstraint{inttype(T), T}[], + segmentconstraints = SegmentationConstraint{inttype(T), T}[], + trifaces = TriangleFace{Cint}[], + trifacemarkers = Cint[], + edges = LineFace{Cint}[], + edgemarkers = Cint[]) where {T} JLTetGenIO(points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers) + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end function number_of_elements_field(io, basename) @@ -200,11 +200,11 @@ function get_array(io, field::Symbol, Typ) end function Base.convert(IOT::Type{JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}}, - io::CPPTetGenIO{T}) where {T, NSimplex, NAttributes, NMTr, IT, A} + io::CPPTetGenIO{T}) where {T, NSimplex, NAttributes, NMTr, IT, A} JLTetGenIO(ntuple(fieldcount(IOT)) do i - fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) - get_array(io, fname, eltype(ftype)) - end...) + fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) + get_array(io, fname, eltype(ftype)) + end...) end function Base.convert(::Type{JLTetGenIO}, io::CPPTetGenIO{T}) where {T} @@ -239,12 +239,12 @@ function Base.cconvert(::Type{Ptr{CFacet{T}}}, facets::Vector{NgonFace{N, Cint}} end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} + facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} + facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end @@ -256,14 +256,24 @@ function unsafe_array_convert(P::Type{Ptr{T1}}, x::Vector{T2}) where {T1, T2} Ptr{T1}(Base.unsafe_convert(Ptr{T2}, x)) end +@static if VERSION > v"1.10" + function unsafe_array_convert(P::Type{Ptr{T1}}, x::MemoryRef{T2}) where {T1, T2} + Ptr{T1}(Base.unsafe_convert(Ptr{T2}, x)) + end + + function unsafe_array_convert(P::Type{Ptr{T}}, x::MemoryRef{T}) where {T} + Base.unsafe_convert(P, x) + end +end + function Base.cconvert(CIO::Type{CPPTetGenIO{T}}, - obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} + obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} cfnames = fieldnames(CIO) dict = Dict{Symbol, Any}(:numberofpointattributes => NAttributes, - :numberofpointmtrs => NMTr, - :numberofcorners => NSimplex, - :firstnumber => Cint(1), - :mesh_dim => Cint(3)) + :numberofpointmtrs => NMTr, + :numberofcorners => NSimplex, + :firstnumber => Cint(1), + :mesh_dim => Cint(3)) gc_tack_cconvert = [] for field in fieldnames(typeof(obj)) basename = if field == :tetrahedra @@ -302,7 +312,7 @@ end function tetrahedralize(input::JLTetGenIO{Float64}, command::String) rc = Cint[0] cres = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command, - rc) + rc) if rc[1] != 0 throw(TetGenError(rc[1])) end From 4d80f0b471e6e20fb6ecdc05aa7177d5ac837b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 22:33:28 +0100 Subject: [PATCH 5/8] format --- src/jltetgenio.jl | 162 +++++++++++++++++++++++----------------------- test/runtests.jl | 156 ++++++++++++++++++++++---------------------- 2 files changed, 159 insertions(+), 159 deletions(-) diff --git a/src/jltetgenio.jl b/src/jltetgenio.jl index 01c4dba..227c49c 100644 --- a/src/jltetgenio.jl +++ b/src/jltetgenio.jl @@ -85,80 +85,80 @@ struct JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, FT} edgemarkers::Vector{Cint} function JLTetGenIO(points::Vector{Point{3, T}}, - pointattributes::Vector{SVector{NAttributes, T}}, - pointmtrs::Vector{SVector{NMTr, T}}, - pointmarkers::Vector{Cint}, - tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, - tetrahedronattributes::Vector{T}, - tetrahedronvolumes::Vector{T}, - neighbors::Vector{Cint}, - facets::FT, - facetmarkers::Vector{Cint}, - holes::Vector{Point{3, T}}, - regions::Vector{Region{T}}, - facetconstraints::Vector{FacetConstraint{IT, T}}, - segmentconstraints::Vector{SegmentationConstraint{IT, T}}, - trifaces::Vector{TriangleFace{Cint}}, - trifacemarkers::Vector{Cint}, - edges::Vector{LineFace{Cint}}, - edgemarkers::Vector{Cint}) where {T, NSimplex, NAttributes, NMTr, IT, FT} + pointattributes::Vector{SVector{NAttributes, T}}, + pointmtrs::Vector{SVector{NMTr, T}}, + pointmarkers::Vector{Cint}, + tetrahedrons::Vector{SimplexFace{NSimplex, Cint}}, + tetrahedronattributes::Vector{T}, + tetrahedronvolumes::Vector{T}, + neighbors::Vector{Cint}, + facets::FT, + facetmarkers::Vector{Cint}, + holes::Vector{Point{3, T}}, + regions::Vector{Region{T}}, + facetconstraints::Vector{FacetConstraint{IT, T}}, + segmentconstraints::Vector{SegmentationConstraint{IT, T}}, + trifaces::Vector{TriangleFace{Cint}}, + trifacemarkers::Vector{Cint}, + edges::Vector{LineFace{Cint}}, + edgemarkers::Vector{Cint}) where {T, NSimplex, NAttributes, NMTr, IT, FT} new{T, NSimplex, NAttributes, NMTr, IT, FT}(points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers) + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end end function JLTetGenIO(points::Vector{Point{3, T}}; - pointattributes = SVector{0, T}[], - pointmtrs = SVector{0, T}[], - pointmarkers = Cint[], - tetrahedrons = SimplexFace{4, Cint}[], - tetrahedronattributes = T[], - tetrahedronvolumes = T[], - neighbors = Cint[], - facets = JLFacet{T, Vector{Cint}}[], - facetmarkers = Cint[], - holes = Point{3, T}[], - regions = Region{T}[], - facetconstraints = FacetConstraint{inttype(T), T}[], - segmentconstraints = SegmentationConstraint{inttype(T), T}[], - trifaces = TriangleFace{Cint}[], - trifacemarkers = Cint[], - edges = LineFace{Cint}[], - edgemarkers = Cint[]) where {T} + pointattributes = SVector{0, T}[], + pointmtrs = SVector{0, T}[], + pointmarkers = Cint[], + tetrahedrons = SimplexFace{4, Cint}[], + tetrahedronattributes = T[], + tetrahedronvolumes = T[], + neighbors = Cint[], + facets = JLFacet{T, Vector{Cint}}[], + facetmarkers = Cint[], + holes = Point{3, T}[], + regions = Region{T}[], + facetconstraints = FacetConstraint{inttype(T), T}[], + segmentconstraints = SegmentationConstraint{inttype(T), T}[], + trifaces = TriangleFace{Cint}[], + trifacemarkers = Cint[], + edges = LineFace{Cint}[], + edgemarkers = Cint[]) where {T} JLTetGenIO(points, - pointattributes, - pointmtrs, - pointmarkers, - tetrahedrons, - tetrahedronattributes, - tetrahedronvolumes, - neighbors, - facets, - facetmarkers, - holes, - regions, - facetconstraints, - segmentconstraints, - trifaces, - trifacemarkers, - edges, - edgemarkers) + pointattributes, + pointmtrs, + pointmarkers, + tetrahedrons, + tetrahedronattributes, + tetrahedronvolumes, + neighbors, + facets, + facetmarkers, + holes, + regions, + facetconstraints, + segmentconstraints, + trifaces, + trifacemarkers, + edges, + edgemarkers) end function number_of_elements_field(io, basename) @@ -200,11 +200,11 @@ function get_array(io, field::Symbol, Typ) end function Base.convert(IOT::Type{JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}}, - io::CPPTetGenIO{T}) where {T, NSimplex, NAttributes, NMTr, IT, A} + io::CPPTetGenIO{T}) where {T, NSimplex, NAttributes, NMTr, IT, A} JLTetGenIO(ntuple(fieldcount(IOT)) do i - fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) - get_array(io, fname, eltype(ftype)) - end...) + fname, ftype = fieldname(IOT, i), fieldtype(IOT, i) + get_array(io, fname, eltype(ftype)) + end...) end function Base.convert(::Type{JLTetGenIO}, io::CPPTetGenIO{T}) where {T} @@ -239,12 +239,12 @@ function Base.cconvert(::Type{Ptr{CFacet{T}}}, facets::Vector{NgonFace{N, Cint}} end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} + facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, - facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} + facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) end @@ -265,15 +265,15 @@ end Base.unsafe_convert(P, x) end end - + function Base.cconvert(CIO::Type{CPPTetGenIO{T}}, - obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} + obj::JLTetGenIO{T, NSimplex, NAttributes, NMTr, IT, A}) where {T, NSimplex, NAttributes, NMTr, IT, A} cfnames = fieldnames(CIO) dict = Dict{Symbol, Any}(:numberofpointattributes => NAttributes, - :numberofpointmtrs => NMTr, - :numberofcorners => NSimplex, - :firstnumber => Cint(1), - :mesh_dim => Cint(3)) + :numberofpointmtrs => NMTr, + :numberofcorners => NSimplex, + :firstnumber => Cint(1), + :mesh_dim => Cint(3)) gc_tack_cconvert = [] for field in fieldnames(typeof(obj)) basename = if field == :tetrahedra @@ -312,7 +312,7 @@ end function tetrahedralize(input::JLTetGenIO{Float64}, command::String) rc = Cint[0] cres = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command, - rc) + rc) if rc[1] != 0 throw(TetGenError(rc[1])) end diff --git a/test/runtests.jl b/test/runtests.jl index 8cc851f..68d1328 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,23 +2,23 @@ using TetGen using TetGen: JLPolygon, JLFacet, Point using GeometryBasics using GeometryBasics: Mesh, Triangle, Tetrahedron, TriangleFace, QuadFace, - PointMeta, NgonFaceMeta, meta, faces, metafree + PointMeta, NgonFaceMeta, meta, faces, metafree using GeometryBasics.StructArrays using Test @testset "mesh based API" begin # Construct a cube out of Quads points = Point{3, Float64}[(0.0, 0.0, 0.0), (2.0, 0.0, 0.0), - (2.0, 2.0, 0.0), (0.0, 2.0, 0.0), - (0.0, 0.0, 12.0), (2.0, 0.0, 12.0), - (2.0, 2.0, 12.0), (0.0, 2.0, 12.0)] + (2.0, 2.0, 0.0), (0.0, 2.0, 0.0), + (0.0, 0.0, 12.0), (2.0, 0.0, 12.0), + (2.0, 2.0, 12.0), (0.0, 2.0, 12.0)] facets = QuadFace{Cint}[1:4, - 5:8, - [1, 5, 6, 2], - [2, 6, 7, 3], - [3, 7, 8, 4], - [4, 8, 5, 1]] + 5:8, + [1, 5, 6, 2], + [2, 6, 7, 3], + [3, 7, 8, 4], + [4, 8, 5, 1]] markers = Cint[-1, -2, 0, 0, 0, 0] # attach some additional information to our faces! @@ -35,14 +35,14 @@ using Test @test result isa Mesh tetpoints = Point{3, Float64}[(0.0, 0.0, 0.0), - (1.0, 0.0, 0.0), - (0.0, 1.0, 0.0), - (0.0, 0.0, 1.0)] + (1.0, 0.0, 0.0), + (0.0, 1.0, 0.0), + (0.0, 0.0, 1.0)] tetfacets = TriangleFace{Cint}[[1, 2, 3], - [1, 2, 4], - [1, 3, 4], - [2, 3, 4]] + [1, 2, 4], + [1, 3, 4], + [2, 3, 4]] tetmesh = Mesh(tetpoints, tetfacets) result = tetrahedralize(tetmesh, "pQqAa0.01") @@ -51,34 +51,34 @@ using Test ################# cube with hole example # Construct a cube out of Quads points = Point{3, Float64}[ - # outer cube: - (-2.0, -2.0, -2.0), (2.0, -2.0, -2.0), - (2.0, 2.0, -2.0), (-2.0, 2.0, -2.0), - (-2.0, -2.0, 2.0), (2.0, -2.0, 2.0), - (2.0, 2.0, 2.0), (-2.0, 2.0, 2.0), - - # inner cube: - (-1.0, -1.0, -1.0), (1.0, -1.0, -1.0), - (1.0, 1.0, -1.0), (-1.0, 1.0, -1.0), - (-1.0, -1.0, 1.0), (1.0, -1.0, 1.0), - (1.0, 1.0, 1.0), (-1.0, 1.0, 1.0)] + # outer cube: + (-2.0, -2.0, -2.0), (2.0, -2.0, -2.0), + (2.0, 2.0, -2.0), (-2.0, 2.0, -2.0), + (-2.0, -2.0, 2.0), (2.0, -2.0, 2.0), + (2.0, 2.0, 2.0), (-2.0, 2.0, 2.0), + + # inner cube: + (-1.0, -1.0, -1.0), (1.0, -1.0, -1.0), + (1.0, 1.0, -1.0), (-1.0, 1.0, -1.0), + (-1.0, -1.0, 1.0), (1.0, -1.0, 1.0), + (1.0, 1.0, 1.0), (-1.0, 1.0, 1.0)] facets = QuadFace{Cint}[ - # outer cube: - [1, 2, 3, 4], - [5, 6, 7, 8], - [1, 5, 6, 2], - [2, 6, 7, 3], - [3, 7, 8, 4], - [4, 8, 5, 1], - - # inner cube: - [1, 2, 3, 4] .+ 8, - [5, 6, 7, 8] .+ 8, - [1, 5, 6, 2] .+ 8, - [2, 6, 7, 3] .+ 8, - [3, 7, 8, 4] .+ 8, - [4, 8, 5, 1] .+ 8] + # outer cube: + [1, 2, 3, 4], + [5, 6, 7, 8], + [1, 5, 6, 2], + [2, 6, 7, 3], + [3, 7, 8, 4], + [4, 8, 5, 1], + + # inner cube: + [1, 2, 3, 4] .+ 8, + [5, 6, 7, 8] .+ 8, + [1, 5, 6, 2] .+ 8, + [2, 6, 7, 3] .+ 8, + [3, 7, 8, 4] .+ 8, + [4, 8, 5, 1] .+ 8] markers = ones(Cint, 12) mesh = Mesh(points, meta(facets; markers = markers)) @@ -173,41 +173,41 @@ end function badcube1(; vol = 1) input = TetGen.RawTetGenIO{Cdouble}() input.pointlist = [0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 2; - 1 1 1; - 0 1 2]' + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 2; + 1 1 1; + 0 1 2]' TetGen.facetlist!(input, [1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa$(vol)") end function badcube2(; vol = 1) input = TetGen.RawTetGenIO{Cdouble}() input.pointlist = [0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1; - 0 1 1-1.0e-5]' + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1; + 0 1 1-1.0e-5]' TetGen.facetlist!(input, [1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') tetrahedralize(input, "pQa$(vol)") end @@ -234,20 +234,20 @@ end @testset "codecov" begin input = TetGen.RawTetGenIO{Cdouble}() input.pointlist = [0 0 0; - 1 0 0; - 1 1 0; - 0 1 0; - 0 0 1; - 1 0 1; - 1 1 1; - 0 1 1]' + 1 0 0; + 1 1 0; + 0 1 0; + 0 0 1; + 1 0 1; + 1 1 1; + 0 1 1]' TetGen.facetlist!(input, [1 2 3 4; - 5 6 7 8; - 1 2 6 5; - 2 3 7 6; - 3 4 8 7; - 4 1 5 8]') + 5 6 7 8; + 1 2 6 5; + 2 3 7 6; + 3 4 8 7; + 4 1 5 8]') cinput, x1, x2 = TetGen.CPPTetGenIO(input) coutput = tetrahedralize(cinput, "pQa") From 76824be822ed8ee0e118065c821f0ebc833d34e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 22:40:05 +0100 Subject: [PATCH 6/8] pass pointer to unsafe_convert Seems to fix problem on 1.11 and works for earlier versions --- src/jltetgenio.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jltetgenio.jl b/src/jltetgenio.jl index 227c49c..47e7b45 100644 --- a/src/jltetgenio.jl +++ b/src/jltetgenio.jl @@ -240,12 +240,12 @@ end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, facets::Tuple{Vector{F}, Vector{Vector{CPolygon}}, Vector{CFacet{T}}}) where {F, T} - return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) + return Base.unsafe_convert(Ptr{CFacet{T}}, pointer(facets[3])) end function unsafe_array_convert(::Type{Ptr{CFacet{T}}}, facets::Tuple{Vector{F}, Vector{CPolygon}, Vector{CFacet{T}}}) where {F, T} - return Base.unsafe_convert(Ptr{CFacet{T}}, facets[3]) + return Base.unsafe_convert(Ptr{CFacet{T}}, pointer(facets[3])) end function unsafe_array_convert(P::Type{Ptr{T}}, x::Vector{T}) where {T} From de610dbe4688fc6f9bc174fef7d23d7b6ccc3640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 23:09:14 +0100 Subject: [PATCH 7/8] Test for type of return value of unsuitable function --- src/cpptetgenio.jl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/cpptetgenio.jl b/src/cpptetgenio.jl index f2a9f09..7f5c285 100644 --- a/src/cpptetgenio.jl +++ b/src/cpptetgenio.jl @@ -125,13 +125,24 @@ function jl_wrap_tetunsuitable(pa::Ptr{Float64}, pb::Ptr{Float64}, pc::Ptr{Float end """ - Set tetunsuitable function called from C wrapper. - Setting this function is valid only for one subsequent - call to tetrahedralize +$(SIGNATURES) + +Set tetunsuitable function called from C wrapper. +Setting this function is valid only for one subsequent call to tetrahedralize. +The function to be passed has the signature +``` +unsuitable(p1::Vector{Float64},p2::Vector{Float64},p3::Vector{Float64},p4::Vector{Float64})::Bool +``` +where `p1...p4` are 3-Vectors describing the corners of a tetrahedron, and the return value is `true` if +its volume is seen as too large. + """ function tetunsuitable!(unsuitable::Function; check_signature = true) if check_signature - unsuitable(rand(3), rand(3), rand(3), rand(3)) + retval = unsuitable(rand(3), rand(3), rand(3), rand(3)) + if !isa(retval, Bool) + error("unsuitable function should return a Bool") + end end global my_jl_tetunsuitable my_jl_tetunsuitable = unsuitable From 181d78eef8b8bb2fdad5324aaed0eb03493a75c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Mon, 13 Nov 2023 23:09:41 +0100 Subject: [PATCH 8/8] fix make.jl for Documenter v1 * set warnonly=true as the missing docstrings are not relevant for user API. --- Project.toml | 2 +- docs/Project.toml | 3 +++ docs/make.jl | 7 ++++--- docs/src/index.md | 4 ++++ examples/examples.jl | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 0ddf709..6cdcd19 100644 --- a/Project.toml +++ b/Project.toml @@ -15,8 +15,8 @@ TetGen_jll = "b47fdcd6-d2c1-58e9-bbba-c1cee8d8c179" DocStringExtensions = "0.8,0.9" GeometryBasics = "0.2, 0.3, 0.4" StaticArrays = "1" -julia = "1.6" TetGen_jll = "1.5.3" +julia = "1.6" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/docs/Project.toml b/docs/Project.toml index ea6ecb7..1998ffc 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,6 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" TetGen = "c5d3f3f7-f850-59f6-8a2e-ffc6dc1317ea" + +[compat] +Documenter = "1" \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 5b1c84d..83a06d6 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,10 +1,11 @@ using Documenter, TetGen function make_all() - makedocs( - ; sitename = "TetGen.jl", + makedocs(; + sitename = "TetGen.jl", modules = [TetGen], - clean = true, + warnonly = true, + clean = false, doctest = false, authors = "Simon Danisch, Juergen Fuhrmann", repo = "https://github.com/JuliaGeometry/TetGen.jl", diff --git a/docs/src/index.md b/docs/src/index.md index e1f6a65..14e8f46 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -25,6 +25,10 @@ Modules = [TetGen] Pages = [ "rawtetgenio.jl"] ``` +```@docs +tetunsuitable! +``` + ## TetGen C++ code diff --git a/examples/examples.jl b/examples/examples.jl index f6b2c1b..77d1d37 100644 --- a/examples/examples.jl +++ b/examples/examples.jl @@ -76,7 +76,7 @@ end Tetrahedralization of cube with local refinement callback """ function cube_localref() - tetunsuitable() do pa, pb, pc, pd + tetunsuitable!() do pa, pb, pc, pd vol = det(hcat(pb - pa, pc - pa, pd - pa)) / 6 center = 0.25 * (pa + pb + pc + pd) - [0.5, 0.5, 0.5] vol > 0.05 * norm(center)^2.5