Skip to content

Commit 936482a

Browse files
authored
Update of upstream patch version of TetGen and API improvements (#25)
Update of upstream patch version of TetGen and API improvements * Update of upstream patch version of TetGen to "August 18, 2018". Formally this still appears to be 1.5.1 , and it is manifest in TetGen_jll 1.5.1+1 * Catch errors thrown by TetGen in a rc variable, throw julia error if rc!=0 * Handle unsuitable callback to allow local refinement. Co-authored-by: Juergen Fuhrmann <[email protected]>
1 parent 85eb7c7 commit 936482a

File tree

8 files changed

+307
-12
lines changed

8 files changed

+307
-12
lines changed

Project.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
name = "TetGen"
22
uuid = "c5d3f3f7-f850-59f6-8a2e-ffc6dc1317ea"
33
authors = ["SimonDanisch <[email protected]>", "Juergen Fuhrmann <[email protected]"]
4-
version = "1.0.0"
4+
version = "1.1.0"
55

66
[deps]
77
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
88
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
9-
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
9+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
10+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1011
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1112
TetGen_jll = "b47fdcd6-d2c1-58e9-bbba-c1cee8d8c179"
1213

1314
[compat]
1415
DocStringExtensions = "^0.8"
1516
GeometryBasics = "0.2, 0.3"
1617
StaticArrays = "0.11, 0.12"
17-
TetGen_jll = "^1.5.1"
18+
TetGen_jll = "1.5.1"
1819
julia = "1.3"
1920

2021
[extras]

README.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
The `TetGen.jl` package is a Julia wrapper for the C++ project [TetGen](https://wias-berlin.de/software/index.jsp?id=TetGen&lang=1). This wrapper enables TetGen based tetrahedral meshing, and (constrained) 3D Delaunay and Voronoi tesselation.
1111

12-
## Example
12+
## Example using GeometryBasics datatypes
1313

1414
```julia
1515
using TetGen
@@ -51,6 +51,55 @@ Plotted with Makie:
5151
![image](https://user-images.githubusercontent.com/1010467/82307971-69252000-99c1-11ea-8b82-e3a206381bd3.png)
5252

5353

54+
## Example using plain Julia arrays
55+
56+
```julia
57+
using TetGen
58+
let
59+
tetunsuitable() do pa,pb,pc,pd
60+
vol=det(hcat(pb-pa,pc-pa,pd-pa))/6
61+
center=0.25*(pa+pb+pc+pd)-[0.5,0.5,0.5]
62+
vol> 0.05*norm(center)^2.5
63+
end
64+
65+
input=TetGen.RawTetGenIO{Cdouble}()
66+
input.pointlist=[0 0 0;
67+
1 0 0;
68+
1 1 0;
69+
0 1 0;
70+
0 0 1;
71+
1 0 1;
72+
1 1 1;
73+
0 1 1]'
74+
75+
TetGen.facetlist!(input,[1 2 3 4;
76+
5 6 7 8;
77+
1 2 6 5;
78+
2 3 7 6;
79+
3 4 8 7;
80+
4 1 5 8]')
81+
tetrahedralize(input, "pQa")
82+
end
83+
```
84+
85+
Output:
86+
87+
```julia
88+
RawTetGenIO(
89+
numberofpoints=169,
90+
numberofedges=27,
91+
numberoftrifaces=112,
92+
numberoftetrahedra=809,
93+
pointlist'=[0.0 1.0 0.500059730245037 0.4996534431688176; 0.0 0.0 0.5074057466787957 0.49707528530503103; 0.0 0.0 0.5033015055704277 0.4953177845338027],
94+
tetrahedronlist'=Int32[34 47 15 143; 6 24 143 15; 58 52 154 150; 70 73 168 168],
95+
trifacelist'=Int32[3 58 99 22; 19 6 22 8; 78 70 158 158],
96+
trifacemarkerlist'=Int32[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
97+
edgelist'=Int32[3 5 70 157; 18 24 6 32],
98+
edgemarkerlist'=Int32[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
99+
)
100+
```
101+
102+
54103
## [Contributing](https://github.com/JuliaGeometry/TetGen.jl/blob/master/CONTRIBUTING.md)
55104

56105

examples/examples.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using TetGen
2+
using LinearAlgebra
23

34
"""
45
random_delaunay(;npoints=20)
@@ -38,6 +39,44 @@ function cube(;vol=1)
3839
tetrahedralize(input, "pQa$(vol)")
3940
end
4041

42+
43+
44+
"""
45+
cube_localref()
46+
47+
Tetrahedralization of cube with local refinement callback
48+
"""
49+
50+
function cube_localref()
51+
52+
tetunsuitable() do pa,pb,pc,pd
53+
vol=det(hcat(pb-pa,pc-pa,pd-pa))/6
54+
center=0.25*(pa+pb+pc+pd)-[0.5,0.5,0.5]
55+
vol> 0.05*norm(center)^2.5
56+
end
57+
58+
input=TetGen.RawTetGenIO{Cdouble}()
59+
input.pointlist=[0 0 0;
60+
1 0 0;
61+
1 1 0;
62+
0 1 0;
63+
0 0 1;
64+
1 0 1;
65+
1 1 1;
66+
0 1 1]'
67+
68+
TetGen.facetlist!(input,[1 2 3 4;
69+
5 6 7 8;
70+
1 2 6 5;
71+
2 3 7 6;
72+
3 4 8 7;
73+
4 1 5 8]')
74+
tetrahedralize(input, "pQa")
75+
end
76+
77+
78+
79+
4180
"""
4281
prism(;vol=1)
4382

src/TetGen.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
module TetGen
22
using DocStringExtensions
33
using TetGen_jll
4+
45
using GeometryBasics
56
using GeometryBasics: Polygon, MultiPolygon, Point, LineFace, Polytope, Line,
67
Simplex, connect, Triangle, NSimplex, Tetrahedron,
78
TupleView, TriangleFace, SimplexFace, LineString, Mesh, TetrahedronP, TriangleP,
89
NgonFace, Ngon, faces, coordinates, metafree, meta, faces
910

11+
12+
using Printf
13+
1014
using StaticArrays
1115

1216

@@ -18,6 +22,8 @@ include("api.jl")
1822

1923

2024
export tetrahedralize
25+
export tetunsuitable
26+
export TetGenError
2127
export RawTetGenIO, facetlist!, RawFacet
2228
export numberofpoints,numberoftetrahedra,numberoftrifaces,numberofedges
2329
export volumemesh,surfacemesh

src/cpptetgenio.jl

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,80 @@ struct CPPTetGenIO{T}
5757
numberofedges::Cint
5858
end
5959

60-
tetrahedralize(input::CPPTetGenIO{Float64}, command::String)=ccall((:tetrahedralizef64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring), input, command)
60+
"""
61+
Error struct for TetGen
62+
"""
63+
struct TetGenError <: Exception
64+
rc::Cint
65+
end
66+
67+
"""
68+
Show TetGen error, messages have been lifted
69+
from TetGen
70+
"""
71+
function Base.show(io::IO, e::TetGenError)
72+
if e.rc==1
73+
println(io,"TetGen error $(e.rc): out of memory.");
74+
elseif e.rc==2
75+
println(io,"TetGen error $(e.rc): internal error.")
76+
elseif e.rc==3
77+
println(io,"TetGen error $(e.rc): a self-intersection was detected. Hint: use -d option to detect all self-intersections.");
78+
elseif e.rc==4
79+
println(io,"TetGen error $(e.rc): a very small input feature size was detected. Hint: use -T option to set a smaller tolerance.")
80+
elseif e.rc==5
81+
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");
82+
elseif e.rc==10
83+
println(io,"TetGen error $(e.rc): an input error was detected.\n");
84+
else
85+
println(io,"TetGen error $(e.rc): unknown error.\n");
86+
end
87+
end
88+
89+
90+
"""
91+
$(SIGNATURES)
92+
93+
Tetrahedralization with error handling
94+
"""
95+
function tetrahedralize(input::CPPTetGenIO{Float64}, command::String)
96+
rc=Cint[0]
97+
output = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command, rc)
98+
if rc[1]!=0
99+
throw(TetGenError(rc[1]))
100+
end
101+
output
102+
end
61103

104+
105+
"""
106+
Trivial Julia tetunsuitable function
107+
"""
108+
my_jl_tetunsuitable=(pa,pb,pc,pd)->0
109+
110+
111+
"""
112+
Tetunsuitable function called from C wrapper
113+
"""
114+
function jl_wrap_tetunsuitable(pa::Ptr{Float64}, pb::Ptr{Float64}, pc::Ptr{Float64}, pd::Ptr{Float64})
115+
pax=Base.unsafe_wrap(Array,pa,(3,),own=false)
116+
pbx=Base.unsafe_wrap(Array,pb,(3,),own=false)
117+
pcx=Base.unsafe_wrap(Array,pc,(3,),own=false)
118+
pdx=Base.unsafe_wrap(Array,pd,(3,),own=false)
119+
Cint(my_jl_tetunsuitable(pax,pbx,pcx,pdx))
120+
end
121+
122+
123+
"""
124+
Set tetunsuitable function called from C wrapper.
125+
Setting this function is valid only for one subsequent
126+
call to tetrahedralize
127+
"""
128+
function tetunsuitable(unsuitable::Function;check_signature=true)
129+
if check_signature
130+
unsuitable(rand(3),rand(3),rand(3),rand(3))
131+
end
132+
global my_jl_tetunsuitable
133+
my_jl_tetunsuitable=unsuitable
134+
c_wrap_tetunsuitable=@cfunction(jl_wrap_tetunsuitable, Cint, (Ptr{Cdouble},Ptr{Cdouble},Ptr{Cdouble},Ptr{Cdouble}))
135+
ccall((:tetunsuitable_callback,libtet),Cvoid,(Ptr{Cvoid},),c_wrap_tetunsuitable)
136+
end

src/jltetgenio.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,11 @@ function Base.unsafe_convert(::Type{CPPTetGenIO{T}}, x::Tuple{CPPTetGenIO{T}, Ve
329329
end
330330

331331

332-
333332
function tetrahedralize(input::JLTetGenIO{Float64}, command::String)
334-
cres = ccall((:tetrahedralizef64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring), input, command)
333+
rc=Cint[0]
334+
cres = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}), input, command,rc)
335+
if rc[1]!=0
336+
throw(TetGenError(rc[1]))
337+
end
335338
return convert(JLTetGenIO, cres)
336339
end

src/rawtetgenio.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,7 @@ function CPPTetGenIO(tio::RawTetGenIO{T}) where T
419419
edgemarkerlist=pointer(tio.edgemarkerlist)
420420
end
421421
end
422-
423-
422+
424423
# Create struct
425424
CPPTetGenIO{T}(firstnumber,
426425
mesh_dim,
@@ -469,10 +468,10 @@ function RawTetGenIO(ctio::CPPTetGenIO{T}) where T
469468
tio.pointlist = convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointlist, (3,Int(ctio.numberofpoints)), own=true))
470469
end
471470
if ctio.numberofpointattributes>0 && ctio.pointattributelist!=C_NULL
472-
tio.pointattributelist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointattributelistlist, (Int(ctio.numberofpointattributes),Int(ctio.numberofpoints)), own=true))
471+
tio.pointattributelist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointattributelist, (Int(ctio.numberofpointattributes),Int(ctio.numberofpoints)), own=true))
473472
end
474473
if ctio.numberofpointmtrs>0 && ctio.pointmtrlist!=C_NULL
475-
tio.pointmtrlist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointmtrlistlist, (Int(ctio.numberofpointmtrs),Int(ctio.numberofpoints)), own=true))
474+
tio.pointmtrlist=convert(Array{T,2}, Base.unsafe_wrap(Array, ctio.pointmtrlist, (Int(ctio.numberofpointmtrs),Int(ctio.numberofpoints)), own=true))
476475
end
477476
if ctio.pointmarkerlist!=C_NULL
478477
tio.pointmarkerlist=convert(Array{Cint,1}, Base.unsafe_wrap(Array, ctio.pointmarkerlist, (Int(ctio.numberofpoints)), own=true))
@@ -626,7 +625,12 @@ Tetrahedralize input.
626625
"""
627626
function tetrahedralize(input::RawTetGenIO{Float64}, flags::String)
628627
cinput,flist,plist=CPPTetGenIO(input)
629-
coutput = ccall((:tetrahedralizef64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring), cinput, flags)
628+
rc=Cint[0]
629+
coutput = ccall((:tetrahedralize2_f64, libtet), CPPTetGenIO{Float64}, (CPPTetGenIO{Float64}, Cstring, Ptr{Cint}),
630+
cinput, flags, rc)
631+
if rc[1]!=0
632+
throw(TetGenError(rc[1]))
633+
end
630634
RawTetGenIO(coutput)
631635
end
632636

0 commit comments

Comments
 (0)