-
Notifications
You must be signed in to change notification settings - Fork 1
/
survey_utils.py
121 lines (87 loc) · 3.28 KB
/
survey_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import bpy
import bmesh
import time
from mathutils import Vector, Matrix
def silouette_brute_force(context, ob, view, world = True, smooth = True, debug = False):
'''
args:
ob - mesh object
view - Mathutils Vector
return:
new mesh of type Mesh (not BMesh)
'''
if debug:
start = time.time()
#careful, this can get expensive with multires
bme = bmesh.new()
bme.from_object(ob, context.scene)
bme.normal_update()
#keep track of the world matrix
mx = ob.matrix_world
if world:
#meaning the vector is in world coords
#we need to take it back into local
i_mx = mx.inverted()
view = i_mx.to_quaternion() * view
if debug:
face_time = time.time()
print("took %f to initialze the bmesh" % (face_time - start))
face_directions = [[0]] * len(bme.faces)
for f in bme.faces:
if debug > 1:
print(f.normal)
face_directions[f.index] = f.normal.dot(view)
if debug:
edge_time = time.time()
print("%f seconds to test the faces" % (edge_time - face_time))
if debug > 2:
print(face_directions)
delete_edges = []
keep_verts = set()
for ed in bme.edges:
if len(ed.link_faces) == 2:
silhouette = face_directions[ed.link_faces[0].index] * face_directions[ed.link_faces[1].index]
if silhouette < 0:
keep_verts.add(ed.verts[0])
keep_verts.add(ed.verts[1])
else:
delete_edges.append(ed)
if debug > 1:
print("%i edges to be delted" % len(delete_edges))
print("%i verts to be deleted" % (len(bme.verts) - len(keep_verts)))
if debug:
delete_time = time.time()
print("%f seconds to test the edges" % (delete_time - edge_time))
delete_verts = set(bme.verts) - keep_verts
delete_verts = list(delete_verts)
#https://svn.blender.org/svnroot/bf-blender/trunk/blender/source/blender/bmesh/intern/bmesh_operator_api.h
bmesh.ops.delete(bme, geom = bme.faces, context = 3)
bmesh.ops.delete(bme, geom = delete_verts, context = 1)
#bmesh.ops.delete(bme, geom = delete_edges, context = 2) #presuming the delte enum is 0 = verts, 1 = edges, 2 = faces? who knows.
return bme
def undercut_faces(context, ob, view, threshold = .01, world = True):
'''
args:
ob - mesh object
view - Mathutils Vector
return:
location and radius of undercut faces
'''
#careful, this can get expensive with multires
bme = bmesh.new()
bme.from_object(ob, context.scene)
bme.normal_update()
#keep track of the world matrix
mx = ob.matrix_world
if world:
#meaning the vector is in world coords
#we need to take it back into local
i_mx = mx.inverted()
view = i_mx.to_quaternion() * view
undercut_locations = []
undercut_radii = []
for f in bme.faces:
if f.normal.dot(view) < -threshold:
undercut_locations += [f.calc_center_median()]
undercut_radii += [2 * f.calc_area()**.5]
return undercut_locations, undercut_radii