1- using LinearAlgebra
2- using Roots
3- using GeometryTypes
4- using FileIO
5- using StaticArrays
6- using ForwardDiff
7-
81# Cardinal directions
9- dirs = [ [ 1 ,0 ,0 ], [ 0 ,1 ,0 ], [ 0 ,0 ,1 ] ]
2+ const dirs = ( Point ( 1 ,0 ,0 ), Point ( 0 ,1 ,0 ), Point ( 0 ,0 ,1 ) )
103
114# Vertices of cube
12- cube_verts = [[0 , 0 , 0 ], [0 , 0 , 1 ], [0 , 1 , 0 ], [0 , 1 , 1 ],
13- [1 , 0 , 0 ], [1 , 0 , 1 ], [1 , 1 , 0 ], [1 , 1 , 1 ]]
5+ const cube_verts = (Point (0 , 0 , 0 ), Point (0 , 0 , 1 ), Point (0 , 1 , 0 ),
6+ Point (0 , 1 , 1 ), Point (1 , 0 , 0 ), Point (1 , 0 , 1 ),
7+ Point (1 , 1 , 0 ), Point (1 , 1 , 1 ))
148
159
1610# Edges of cube
17- cube_edges = [ (0 , 1 ), (0 , 2 ), (0 , 1 ), (0 , 4 ), (0 , 2 ), (0 , 4 ), (2 , 3 ), (1 , 3 ),
11+ const cube_edges_dc = ( (0 , 1 ), (0 , 2 ), (0 , 1 ), (0 , 4 ), (0 , 2 ), (0 , 4 ), (2 , 3 ), (1 , 3 ),
1812 (4 , 5 ), (1 , 5 ), (4 , 6 ), (2 , 6 ), (4 , 5 ), (4 , 6 ), (2 , 3 ), (2 , 6 ),
19- (1 , 3 ), (1 , 5 ), (6 , 7 ), (5 , 7 ), (6 , 7 ), (3 , 7 ), (5 , 7 ), (3 , 7 )]
13+ (1 , 3 ), (1 , 5 ), (6 , 7 ), (5 , 7 ), (6 , 7 ), (3 , 7 ), (5 , 7 ), (3 , 7 ))
2014
2115
2216# Use non-linear root finding to compute intersection point
3226# f = implicit function
3327# df = gradient of f
3428# nc = resolution
35- function dual_contour (f, nc )
29+ function dual_contours (f, bounds :: HyperRectangle , nc :: NTuple{3,Int} )
3630
31+ orig = origin (bounds)
32+ width = widths (bounds)
33+ scale = width ./ Point (nc)
3734 # Compute vertices
3835 dc_verts = []
3936 vindex = Dict ()
40- for x in 0 : nc, y in 0 : nc, z in 0 : nc
41- o = [x,y,z]
37+ for x in 0 : nc[1 ], y in 0 : nc[2 ], z in 0 : nc[3 ]
38+ idx = Point (x,y,z)
39+ o = Point (x,y,z) .* scale + orig
4240
4341 # Get signs for cube
44- cube_signs = [ f (o+ v )> 0 for v in cube_verts ]
42+ cube_signs = [ f (o+ (v .* scale) )> 0 for v in cube_verts ]
4543
4644 if all (cube_signs) || ! any (cube_signs)
4745 continue
4846 end
4947
5048 # Estimate hermite data
51- h_data = [ estimate_hermite (f, o+ cube_verts[e[1 ]+ 1 ], o+ cube_verts[e[2 ]+ 1 ])
52- for e in cube_edges if cube_signs[e[1 ]+ 1 ] != cube_signs[e[2 ]+ 1 ] ]
49+ h_data = [ estimate_hermite (f, o+ cube_verts[e[1 ]+ 1 ]. * scale , o+ cube_verts[e[2 ]+ 1 ]. * scale )
50+ for e in cube_edges_dc if cube_signs[e[1 ]+ 1 ] != cube_signs[e[2 ]+ 1 ] ]
5351
5452 # Solve qef to get vertex
5553 A = Array {Float64,2} (undef,length (h_data),3 )
@@ -65,70 +63,44 @@ function dual_contour(f, nc)
6563 end
6664
6765 # Emit one vertex per every cube that crosses
68- push! (vindex, o => length (dc_verts))
66+ push! (vindex, idx => length (dc_verts))
6967 push! (dc_verts, (v, ForwardDiff. gradient (f,v)))
7068 end
7169
7270 # Construct faces
73- dc_faces = []
74- for x in 0 : nc, y in 0 : nc, z in 0 : nc
75- if ! haskey (vindex,[x,y,z])
71+ dc_faces = Face[]
72+ for x in 0 : nc[1 ], y in 0 : nc[2 ], z in 0 : nc[3 ]
73+
74+ idx = Point (x,y,z)
75+ if ! haskey (vindex,idx)
7676 continue
7777 end
7878
7979 # Emit one face per each edge that crosses
80- o = [ x,y,z]
80+ o = Point ( x,y,z) .* scale + orig
8181 for i in (1 ,2 ,3 )
8282 for j in 1 : i
83- if haskey (vindex,o + dirs[i]) && haskey (vindex,o + dirs[j]) && haskey (vindex,o + dirs[i] + dirs[j])
83+ if haskey (vindex,idx + dirs[i]) && haskey (vindex,idx + dirs[j]) && haskey (vindex,idx + dirs[i] + dirs[j])
8484 # determine orientation of the face from the true normal
85- v1, tn1 = dc_verts[vindex[o ]+ 1 ]
86- v2, tn2 = dc_verts[vindex[o + dirs[i]]+ 1 ]
87- v3, tn3 = dc_verts[vindex[o + dirs[j]]+ 1 ]
88- @show v1,v2, v3
85+ v1, tn1 = dc_verts[vindex[idx ]+ 1 ]
86+ v2, tn2 = dc_verts[vindex[idx + dirs[i]]+ 1 ]
87+ v3, tn3 = dc_verts[vindex[idx + dirs[j]]+ 1 ]
88+
8989 e1 = v1- v2
9090 e2 = v1- v3
9191 c = cross (e1,e2)
9292 if dot (c, tn1) > 0
93- push! (dc_faces, [ vindex[o] , vindex[o + dirs[i]], vindex[o + dirs[j]]] )
94- push! (dc_faces, [ vindex[o + dirs[i]+ dirs[j]], vindex[o + dirs[j]], vindex[o + dirs[i]]] )
93+ push! (dc_faces, Face {3,Int} ( vindex[idx] + 1 , vindex[idx + dirs[i]]+ 1 , vindex[idx + dirs[j]]+ 1 ) )
94+ push! (dc_faces, Face {3,Int} ( vindex[idx + dirs[i]+ dirs[j]]+ 1 , vindex[idx + dirs[j]]+ 1 , vindex[idx + dirs[i]]+ 1 ) )
9595 else
96- push! (dc_faces, [ vindex[o] , vindex[o + dirs[j]], vindex[o + dirs[i]]] )
97- push! (dc_faces, [ vindex[o + dirs[i]+ dirs[j]], vindex[o + dirs[i]], vindex[o + dirs[j]]] )
96+ push! (dc_faces, Face {3,Int} ( vindex[idx] + 1 , vindex[idx + dirs[j]]+ 1 , vindex[idx + dirs[i]]+ 1 ) )
97+ push! (dc_faces, Face {3,Int} ( vindex[idx + dirs[i]+ dirs[j]]+ 1 , vindex[idx + dirs[i]]+ 1 , vindex[idx + dirs[j]]+ 1 ) )
9898 end
9999 end
100100 end
101101 end
102102
103103 end
104- return dc_verts, dc_faces
105- end
106-
107-
108- center = [16 ,16 ,16 ]
109- radius = 10
110-
111- function test_f (x)
112- d = x- center
113- return dot (d,d) - radius^ 2
114- end
115-
116- function runion (x,y)
117- x + y - sqrt (x* x + y* y)
118- end
119-
120- function softmax (x,y)
121- log (exp (3 * x)+ exp (3 * y))/ 3
122- end
123-
124- function test_sq (x)
125- d = x- center
126- softmax (softmax (- d[3 ], d[3 ]- 5 ), d[1 ]* d[1 ] + d[2 ]* d[2 ] - radius )
104+ return HomogenousMesh ([Point (v[1 ]. .. ) for v in dc_verts], dc_faces)
127105end
128106
129-
130- verts, tris = dual_contour (test_sq, 36 )
131-
132- m = HomogenousMesh ([Point (v[1 ]. .. ) for v in verts], [Face (t[1 ]+ 1 ,t[2 ]+ 1 ,t[3 ]+ 1 ) for t in tris])
133-
134- save (" test2.ply" ,m)
0 commit comments