fix for error in line 164
[blender-addons-contrib.git] / mesh_extra_tools / mesh_extras.py
1 import bpy, mathutils, math
2 from mathutils import geometry
3
4 # Get a matrix for the selected faces that you can use to do local transforms
5 def get_selection_matrix(faces=False):
6         
7         me = bpy.context.active_object.data
8         
9         if not faces:
10                 faces = get_selected_faces()
11         
12         yVec = mathutils.Vector()
13         zVec = mathutils.Vector()
14         
15         # Ok so we have a basic matrix, but lets base it more on the mesh!
16         for f in faces:
17                         
18                 v1 = me.vertices[f.vertices[0]].co
19                 v2 = me.vertices[f.vertices[1]].co
20                 edge = v2-v1
21                 
22                 yVec += edge
23                 
24                 if len(f.vertices) == 4:
25                         v1 = me.vertices[f.vertices[2]].co
26                         v2 = me.vertices[f.vertices[3]].co
27                         edge = v1-v2
28                         
29                         yVec += edge
30                 
31                 zVec += mathutils.Vector(f.normal)
32                                         
33         if not yVec.length:
34                 quat = zVec.to_track_quat('-Z', 'Y')
35                 tMat = quat.to_matrix()
36                 yVec = tMat[1]
37                 yVec = yVec.normalized()
38         else:
39                 yVec = yVec.normalized()
40         zVec = zVec.normalized()
41         
42         # Rotate yVec so it's 90 degrees to zVec
43         cross =yVec.cross(zVec)
44         vec = float(yVec.angle(zVec) - math.radians(90))
45         mat = mathutils.Matrix.Rotation(vec, 3, cross)
46         yVec =  (mat * yVec)
47         
48         xVec = yVec.cross(zVec)
49         
50         xVec = xVec.normalized()
51         
52         nMat = mathutils.Matrix((xVec, yVec, zVec))
53         
54         return nMat
55
56
57
58 # Get the selection radius (minimum distance of an outer edge to the centre)
59 def get_selection_radius():
60
61         ob = bpy.context.active_object
62
63         radius = 0.0
64         
65         # no use continueing if nothing is selected
66         if contains_selected_item(ob.data.polygons):
67         
68                 # Find the center of the selection
69                 cent = mathutils.Vector()
70                 nr = 0
71                 nonVerts = []
72                 selVerts = []
73                 for f in ob.data.polygons:
74                         if f.select:
75                                 nr += 1
76                                 cent += f.center
77                         else:
78                                 nonVerts.extend(f.vertices)
79                                 
80                 cent /= nr
81                 
82                 chk = 0
83                 
84                 # Now that we know the center.. we can figure out how close the nearest point on an outer edge is
85                 for e in get_selected_edges():
86                 
87                         nonSection = [v for v in e.vertices if v in nonVerts]
88                         if len(nonSection):
89                         
90                                 v0 = ob.data.vertices[e.vertices[0]].co
91                                 v1 = ob.data.vertices[e.vertices[1]].co
92                                 
93                                 # If there's more than 1 vert of this edge on the outside... we need the edge length to be long enough too!
94                                 if len(nonSection) > 1:
95                                         edge = v0 - v1
96                                         edgeRad = edge.length * 0.5
97                                         
98                                         if edgeRad < radius or not chk:
99                                                 radius = edgeRad
100                                                 chk += 1
101                                 
102                                 int = geometry.intersect_point_line(cent, v0, v1)
103                                 
104                                 rad = cent - int[0]
105                                 l = rad.length
106                                 
107                                 if l < radius or not chk:
108                                         radius = l
109                                         chk += 1
110                                         
111         return radius
112         
113         
114         
115 # Get the average length of the outer edges of the current selection
116 def get_shortest_outer_edge_length():
117
118         ob = bpy.context.active_object
119
120         min = False
121         me = ob.data
122         
123         delVerts = []
124         for f in me.faces:
125                 if not f.select:
126                         delVerts.extend(f.vertices)
127         selEdges = [e.vertices for e in me.edges if e.select]
128
129         if len(selEdges) and len(delVerts):
130                 
131                 for eVerts in selEdges:
132                         
133                         v0 = eVerts[0]
134                         v1 = eVerts[1]
135                         
136                         if v0 in delVerts and v1 in delVerts:
137                                 ln = (me.vertices[v0].co - me.vertices[v1].co).length
138                                 if min is False or (ln > 0.0 and ln < min):
139                                         min = ln
140                                                 
141         return min
142
143
144 # Get the average length of the outer edges of the current selection
145 def get_average_outer_edge_length():
146
147         ob = bpy.context.active_object
148
149         ave = 0.0
150         me = ob.data
151         
152         delFaces = [f.vertices for f  in me.polygons if not f.select]
153         selEdges = [e.vertices for e in me.edges if e.select]
154
155         if len(selEdges) and len(delFaces):
156         
157                 number = 0
158                 
159                 for eVerts in selEdges:
160                         
161                         v0 = eVerts[0]
162                         v1 = eVerts[1]
163                         
164                         for fVerts in delFaces:
165                                 if v0 in fVerts and v1 in fVerts:
166                                         number += 1
167                                         ave += (me.vertices[v0].co - me.vertices[v1].co).length
168                                         break
169                                                 
170                 if number:
171                         ave /= number
172                         
173         return ave
174
175
176         
177 # Get the selected (or deselected items)
178 def get_selected(type='vertices',invert=False):
179         
180         mesh = bpy.context.active_object.data
181         
182         if type == 'vertices':
183                 items = mesh.vertices
184         elif type == 'edges':
185                 items = mesh.edges
186         else:
187                 items = mesh.polygons
188                 
189         if invert:
190                 L = [i for i in items if not i.select]
191         else:
192                 L = [i for i in items if i.select]
193         return L
194         
195         
196         
197 # See if the mesh has something selected
198 def has_selected(type='vertices',invert=False):
199         
200         mesh = bpy.context.active_object.data
201         
202         if type == 'vertices':
203                 items = mesh.vertices
204         elif type == 'edges':
205                 items = mesh.edges
206         else:
207                 items = mesh.polygons
208                 
209         for i in items:
210                 if not invert and i.select:
211                         return True
212                 elif invert and not i.select:
213                         return True
214                         
215         return False
216                 
217                 
218
219 # Get all the selected vertices (mode is selected or deselected)
220 def get_selected_vertices(mode='selected'):
221
222         vertices = bpy.context.active_object.data.vertices
223
224         if mode == 'deselected':
225                 L = [v for v in vertices if not v.select]
226         else:
227                 L = [v for v in vertices if v.select]
228         return L
229         
230         
231         
232 # Get all the selected edges (mode is selected or deselected)
233 def get_selected_edges(mode='selected'):
234
235         edges = bpy.context.active_object.data.edges
236
237         if mode == 'deselected':
238                 L = [e for e in edges if not e.select]
239         else:
240                 L = [e for e in edges if e.select]
241         return L
242
243
244         
245 # Get all the selected faces (mode is selected or deselected)
246 def get_selected_faces(mode='selected'):
247         
248         polygons = bpy.context.active_object.data.polygons
249         
250         if mode == 'deselected':
251                 L = [f for f in polygons if not f.select]
252         else:
253                 L = [f for f in polygons if f.select]
254         return L
255         
256         
257         
258 # See if there is at least one selected item in 'items'
259 def contains_selected_item(items):
260
261         for item in items:
262                 if item.select:
263                         return True
264                                 
265         return False
266         
267
268
269
270
271
272         
273         
274