1
- using LinearAlgebra
2
- using Roots
3
- using GeometryTypes
4
- using FileIO
5
- using StaticArrays
6
- using ForwardDiff
7
-
8
1
# 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 ) )
10
3
11
4
# 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 ))
14
8
15
9
16
10
# 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 ),
18
12
(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 ))
20
14
21
15
22
16
# Use non-linear root finding to compute intersection point
32
26
# f = implicit function
33
27
# df = gradient of f
34
28
# nc = resolution
35
- function dual_contour (f, nc )
29
+ function dual_contours (f, bounds :: HyperRectangle , nc :: NTuple{3,Int} )
36
30
31
+ orig = origin (bounds)
32
+ width = widths (bounds)
33
+ scale = width ./ Point (nc)
37
34
# Compute vertices
38
35
dc_verts = []
39
36
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
42
40
43
41
# 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 ]
45
43
46
44
if all (cube_signs) || ! any (cube_signs)
47
45
continue
48
46
end
49
47
50
48
# 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 ] ]
53
51
54
52
# Solve qef to get vertex
55
53
A = Array {Float64,2} (undef,length (h_data),3 )
@@ -65,70 +63,44 @@ function dual_contour(f, nc)
65
63
end
66
64
67
65
# Emit one vertex per every cube that crosses
68
- push! (vindex, o => length (dc_verts))
66
+ push! (vindex, idx => length (dc_verts))
69
67
push! (dc_verts, (v, ForwardDiff. gradient (f,v)))
70
68
end
71
69
72
70
# 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)
76
76
continue
77
77
end
78
78
79
79
# Emit one face per each edge that crosses
80
- o = [ x,y,z]
80
+ o = Point ( x,y,z) .* scale + orig
81
81
for i in (1 ,2 ,3 )
82
82
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])
84
84
# 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
+
89
89
e1 = v1- v2
90
90
e2 = v1- v3
91
91
c = cross (e1,e2)
92
92
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 ) )
95
95
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 ) )
98
98
end
99
99
end
100
100
end
101
101
end
102
102
103
103
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)
127
105
end
128
106
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