File headers: use SPDX license identifiers
[blender-addons.git] / add_mesh_geodesic_domes / vefm_271.py
blobbc6a38dc449489be7fd3d381ab3beed6f977ef2e
1 # vert class and overloading experiments
2 import bpy
3 # PKHG>NEEDED?
4 import bmesh
5 from math import acos, pi, sin, cos, atan, tan
6 from mathutils import Vector
7 from bpy_extras.object_utils import AddObjectHelper
9 # PKHG>DBG change the DBG_info and use extra_DBG_info
10 DBG_info = {"MeshInfo": False, "StrutMesh": False, "HubMesh": False}
13 def extra_DBG_info(name="value from DBG_info", info_text="default\n", info_obj=None):
14 global DBG_info
15 DBG_keys = DBG_info.keys()
16 if name in DBG_keys:
17 if DBG_info[name]:
18 print(info_text, info_obj)
20 sgn = lambda x: (x > 0) - (x < 0) # missing signum function in Python
23 def vefm_add_object(selfobj):
24 for i in range(len(selfobj.verts)):
25 selfobj.verts[i].index = i
26 v = [el.vector for el in selfobj.verts]
28 e = [[edge.a.index, edge.b.index] for edge in selfobj.edges]
30 if type(selfobj.faces[0]) == type([]):
31 # PKHG should be a list of vertices, which have an index
32 f = [[v.index for v in face] for face in selfobj.faces]
33 else:
34 f = [[v.index for v in face.vertices] for face in selfobj.faces]
36 m = bpy.data.meshes.new(name=selfobj.name)
37 m.from_pydata(v, e, f)
38 # useful for development when the mesh may be invalid.
39 m.validate(verbose=False)
40 return m
43 # extra test phase
45 class vertex:
46 def __init__(self, vec=(0, 0, 0)): # default x = 0, y = 0, z = 0):
47 self.vector = Vector(vec)
48 self.length = self.vector.length
49 self.index = 0
50 self.normal = 0
51 self.edges = []
52 self.faces = []
53 self.boundary = 0
55 def findlength(self):
56 self.length = self.vector.length
58 def normalize(self):
59 self.findlength()
60 if self.length > 0:
61 tmp = 1.0 / self.length
62 self.vector = tmp * self.vector
63 self.length = 1.0
65 def findnormal(self):
66 target = []
67 if self.faces[:] == []:
68 print("vefm vertex L68 pkhg:*****ERROR**** findnormal has no faces")
69 return
70 for currentface in self.faces:
71 target.append(currentface.normal)
72 self.normal = average(target).centroid()
73 self.normal.findlength()
74 if self.length == 0:
75 print("******ERROR*** length zero in findnormal, j = (0,1,0) replaced")
76 self.normal = vertex((0, 1, 0))
77 self.normal.normalize()
79 def clockwise(self): # PKHG self is a vertex
80 if self.boundary:
81 start = self.boundarystart()
82 else:
83 start = self.faces[0]
85 self.tempedges = []
86 self.tempfaces = []
87 for i in range(len(self.edges)):
89 self.tempfaces.append(start)
90 for corner in start.corners:
91 if corner[0] is not self:
92 pass
93 elif corner[0] is self:
94 self.tempedges.append(corner[1])
95 nextedge = corner[2]
96 for facey in nextedge.faces:
97 if facey is not start:
98 start = facey
99 break
100 self.edges = self.tempedges
101 self.faces = self.tempfaces
103 def boundarystart(self):
105 pass
107 def __add__(self, other):
108 if isinstance(other, Vector):
109 tmp = self.vector + other
110 else:
111 tmp = self.vector + other.vector
112 return vertex(tmp)
114 def __sub__(self, other):
115 if isinstance(other, Vector):
116 tmp = self.vector - other
117 else:
118 tmp = self.vector - other.vector
119 return vertex(tmp)
121 def __mul__(self, other):
122 tmp = self.vector * other
123 return vertex(tmp)
125 def __truediv__(self, other):
126 denom = 1.0 / other
127 tmp = self.vector * denom
128 return (tmp)
130 def negative(self):
131 return vertex(-self.vector)
134 class crossp:
135 # Takes in two vertices(vectors), returns the cross product.
136 def __init__(self, v1, v2):
137 self.v1 = v1
138 self.v2 = v2
140 def docrossproduct(self):
141 tmp = self.v1.vector.cross(self.v2.vector)
142 return vertex(tmp)
145 class average:
146 # Takes a list of vertices and returns the average. If two verts are passed, returns midpoint.
147 def __init__(self, vertlist):
148 self.vertlist = vertlist
150 def centroid(self):
151 tmp = Vector()
152 # PKHG avoid emptylist problems
153 divisor = 1.0
154 nr_vertices = len(self.vertlist)
155 if nr_vertices > 1:
156 divisor = 1.0 / len(self.vertlist)
157 elif nr_vertices == 0:
158 print("\n***WARNING*** empty list in vefm_271.centroid! L158")
159 for vert in self.vertlist:
160 tmp = tmp + vert.vector
161 tmp = tmp * divisor
162 return vertex(tmp)
165 class edge:
166 def __init__(self, a=0, b=0):
167 self.a = a
168 self.b = b
169 self.index = 0
170 self.normal = 0
171 self.cross = 0
172 self.unit = 0
173 self.faces = []
174 self.vect = 0 # PKHG becomes b - a
175 self.vectb = 0 # PKHG becomes a - b
176 self.boundary = 0
177 self.findvect()
178 self.findlength()
180 def findvect(self):
181 self.vect = self.b - self.a
182 self.vectb = self.a - self.b
184 def findlength(self):
185 self.vect.findlength()
186 self.vectb.length = self.vect.length
188 def findnormal(self):
189 if self.boundary:
190 self.normal = self.faces[0].normal # average([self.a, self.b]).centroid()
191 else:
192 self.normal = average([self.faces[0].normal, self.faces[1].normal]).centroid()
193 self.normal.normalize()
196 class face:
197 def __init__(self, vertices=[]):
198 # PKHG ok good for tri's at least
199 self.vertices = vertices # List of vertex instances
200 self.edges = [] # Will be filled with the sides of the face
201 self.boundary = 0 # When set will have bool and id of edge concerned
202 self.normal = 0 # Face normal found through cross product
203 self.corners = []
204 self.spokes = [] # Vectors of the bisecting angles from each corner to the centre + dotproduct
206 self.index = 0
208 # dotproduct is misleading name, it is the hook between two vectors!
209 def dotproduct(self, v1, v2):
210 v1.findlength()
211 v2.findlength()
212 if v1.length == 0 or v2.length == 0:
213 print("\nPKHG warning, ===== vefm_271 dotproduct L212 ======"
214 " at least one zero vector 0 used")
215 return 0
216 dot = v1.vector.dot(v2.vector)
217 costheta = dot / (v1.length * v2.length)
218 tmp = acos(costheta)
219 return tmp
221 def orderedges(self):
222 temp = []
223 finish = len(self.vertices)
224 for i in range(finish):
225 current = self.vertices[i]
226 if i == finish - 1:
227 next = self.vertices[0]
228 else:
229 next = self.vertices[i + 1]
230 for edge in face.edges:
231 if edge.a == current and edge.b == next:
232 face.clockw.append(edge.vect)
233 face.aclockw.append(edge.vectb)
234 temp.append(edge)
235 if edge.b == current and edge.a == next:
236 face.clockw.append(edge.vectb)
237 face.aclockw.append(edge.vect)
238 temp.append(edge)
239 for edge in face.edges:
240 if edge.a == current and edge.b == next:
241 face.clockw.append(edge.vect)
242 face.aclockw.append(edge.vectb)
243 temp.append(edge)
244 if edge.b == current and edge.a == next:
245 face.clockw.append(edge.vectb)
246 face.aclockw.append(edge.vect)
247 temp.append(edge)
248 face.vertices = temp
250 def docorners(self):
251 # This function identifies and stores the vectors coming from each vertex
252 # allowing easier calculation of cross and dot products.
253 finish = len(self.vertices)
255 for i in range(finish):
256 current = self.vertices[i]
257 if i == finish - 1:
258 next = self.vertices[0]
259 else:
260 next = self.vertices[i + 1]
261 if i == 0:
262 previous = self.vertices[-1]
263 else:
264 previous = self.vertices[i - 1]
265 corner = [current] # PKHG new for each vertex = current
266 # corner = current
267 rightedge = None
268 leftedge = None
269 teller = -1
270 for edge in self.edges:
271 if finish == 3 and len(self.edges) == 2 and i == 2:
272 return
273 teller += 1
274 # next and previous are vertex with respect to ith vertex
275 if edge.a is current or edge.b is current: # does this edge contain our current vert
276 if edge.a is current:
277 if edge.b is next:
278 rightedge = edge
279 rightvect = edge.vect
280 if edge.b is previous:
281 leftedge = edge
282 leftvect = edge.vect
283 elif edge.b is current:
284 if edge.a is next:
285 rightedge = edge
286 rightvect = edge.vectb
287 if edge.a is previous:
288 leftedge = edge
289 leftvect = edge.vectb
290 corner.append(rightedge)
291 corner.append(leftedge)
292 if rightedge and leftedge:
294 dotty = self.dotproduct(rightvect, leftvect)
295 corner.append(dotty)
296 self.corners.append(corner)
298 def findnormal(self):
299 one = self.corners[1][2]
300 two = self.corners[1][1]
301 if one.a is self.corners[1][0]:
302 one = one.vect
303 elif one.b is self.corners[1][0]:
304 one = one.vectb
305 if two.a is self.corners[1][0]:
306 two = two.vect
307 elif two.b is self.corners[1][0]:
308 two = two.vectb
309 self.normal = crossp(one, two).docrossproduct()
310 self.normal.findlength()
311 self.normal.normalize()
313 def dospokes(self):
314 for corner in self.corners:
315 vert = corner[0]
316 right = corner[1]
317 left = corner[2]
318 if right.a is vert:
319 one = vertex(right.vect.vector)
320 elif right.b is vert:
321 one = vertex(right.vectb.vector)
322 if left.a is vert:
323 two = vertex(left.vect.vector)
324 elif left.b is vert:
325 two = vertex(left.vectb.vector)
327 one.normalize()
328 two.normalize()
329 spoke = one + two
330 spoke.normalize()
331 self.spokes.append(spoke)
333 def artspokes(self):
334 centre = average(self.vertices).centroid()
335 for point in self.vertices:
336 newedge = edge(point, centre)
337 self.spokes.append(newedge)
340 class mesh:
341 def __init__(self, name="GD_mesh"):
342 self.name = name
343 self.verts = []
344 self.edges = []
345 self.faces = []
346 self.edgeflag = 0
347 self.faceflag = 0
348 self.vertexflag = 0
349 self.vertedgeflag = 0
350 self.vertfaceflag = 0
351 self.faceedgeflag = 0
352 self.boundaryflag = 0
353 self.vertnormalflag = 0
354 self.edgenormalflag = 0
355 self.facenormalflag = 0
356 self.a45 = pi * 0.25
357 self.a90 = pi * 0.5
358 self.a180 = pi
359 self.a270 = pi * 1.5
360 self.a360 = pi * 2
362 def power(self, a, b): # Returns a power, including negative numbers
363 result = sgn(a) * (abs(a) ** b)
364 return result
366 def sign(self, d): # Works out the sign of a number.
367 return sgn(d)
369 def ellipsecomp(self, efactor, theta):
370 if theta == self.a90:
371 result = self.a90
372 elif theta == self.a180:
373 result = self.a180
374 elif theta == self.a270:
375 result = self.a270
376 elif theta == self.a360:
377 result = 0.0
378 else:
379 result = atan(tan(theta) / efactor ** 0.5)
380 if result < 0.0:
381 if theta > self.a180:
382 result = result + self.a180
383 elif theta < self.a180:
384 result = result + self.a180
386 if result > 0.0:
387 if theta > self.a180:
388 result = result + self.a180
389 elif theta < self.a180:
390 result = result
391 return result
393 def connectivity(self):
394 self.dovertedge()
395 self.dovertface()
396 self.dofaceedge()
397 self.boundary()
399 def superell(self, n1, uv, turn):
400 t1 = sin(uv + turn)
401 t1 = abs(t1)
402 t1 = t1 ** n1
403 t2 = cos(uv + turn)
404 t2 = abs(t2)
405 t2 = t2 ** n1
406 r = self.power(1.0 / (t1 + t2), (1.0 / n1))
407 return r
409 def superform(self, m, n1, n2, n3, uv, a, b, twist):
410 t1 = cos(m * (uv + twist) * .25) * a
411 t1 = abs(t1)
412 t1 = t1 ** n2
413 t2 = sin(m * (uv + twist) * .25) * b
414 t2 = abs(t2)
415 t2 = t2 ** n3
416 r = self.power(1.0 / (t1 + t2), n1)
417 return r
419 def dovertedge(self):
420 if not self.vertedgeflag:
421 for vert in self.verts:
422 vert.edges = []
423 for currentedge in self.edges:
424 currentedge.a.edges.append(currentedge)
425 currentedge.b.edges.append(currentedge)
426 self.vertedgeflag = 1
428 def dovertface(self):
429 if not self.vertfaceflag:
430 for vert in self.verts:
431 vert.faces = []
432 for face in self.faces:
433 for vert in face.vertices:
434 vert.faces.append(face)
435 self.vertfaceflag = 1
437 def dofaceedge(self):
438 self.dovertedge() # just in case they haven't been done
439 self.dovertface()
440 if not self.faceedgeflag:
441 for edge in self.edges:
442 edge.faces = []
443 for face in self.faces:
444 face.edges = []
445 for face in self.faces:
446 finish = len(face.vertices)
447 for i in range(finish):
448 current = face.vertices[i]
449 if i == finish - 1:
450 next = face.vertices[0]
451 else:
452 next = face.vertices[i + 1]
453 for edge in current.edges:
454 if edge.a is current or edge.b is current:
455 if edge.b is next or edge.a is next:
456 edge.faces.append(face)
457 face.edges.append(edge)
458 self.faceedgeflag = 1
460 def boundary(self):
461 if not self.boundaryflag:
462 for edge in self.edges:
463 if len(edge.faces) < 2:
464 edge.boundary = 1
465 edge.faces[0].boundary = 1
466 edge.a.boundary = 1
467 edge.b.boundary = 1
469 # The functions below turn the basic triangular faces into
470 # hexagonal faces, creating the buckyball effect.
471 # PKHG seems to work only for meshes with tri's ;-)
472 def hexify(self):
473 self.hexverts = []
474 self.hexedges = []
475 self.hexfaces = []
476 # PKHG renumbering the index of the verts
477 for i in range(len(self.verts)):
478 self.verts[i].index = i
479 # PKHG renumbering the index of the edges
480 for i in range(len(self.edges)):
481 self.edges[i].index = i
483 self.connectivity()
484 hexvert_counter = 0
485 for edge in self.edges:
487 self.hexshorten(edge, hexvert_counter)
488 hexvert_counter += 2 # PKHG two new vertices done
490 for face in self.faces:
491 self.makehexfaces(face)
493 for vert in self.verts:
494 vert.clockwise()
495 self.hexvertface(vert)
496 self.verts = self.hexverts
497 self.edges = self.hexedges
498 self.faces = self.hexfaces
499 self.vertedgeflag = 0
500 self.vertfaceflag = 0
501 self.faceedgeflag = 0
503 def hexshorten(self, currentedge, hexvert_counter):
504 third = vertex(currentedge.vect / 3.0)
505 newvert1 = vertex(currentedge.a.vector)
506 newvert2 = vertex(currentedge.b.vector)
507 newvert1 = newvert1 + third
508 newvert1.index = hexvert_counter
509 newvert2 = newvert2 - third
510 newvert2.index = hexvert_counter + 1 # PKHG caller adjusts +=2
511 newedge = edge(newvert1, newvert2)
512 newedge.index = currentedge.index
513 self.hexverts.append(newvert1)
514 self.hexverts.append(newvert2)
515 self.hexedges.append(newedge)
517 def makehexfaces(self, currentface):
518 vertices = []
519 currentface.docorners()
520 for corner in currentface.corners:
521 vert = corner[0]
522 rightedge = corner[1]
523 leftedge = corner[2]
524 lid = leftedge.index
525 rid = rightedge.index
527 if leftedge.a is vert:
528 vertices.append(self.hexedges[lid].a)
529 elif leftedge.b is vert:
530 vertices.append(self.hexedges[lid].b)
532 if rightedge.a is vert:
533 vertices.append(self.hexedges[rid].a)
534 elif rightedge.b is vert:
535 vertices.append(self.hexedges[rid].b)
537 newface = face(vertices)
538 newedge1 = edge(vertices[0], vertices[1])
539 newedge2 = edge(vertices[2], vertices[3])
540 newedge3 = edge(vertices[4], vertices[5])
541 self.hexfaces.append(newface)
542 self.hexedges.append(newedge1)
543 self.hexedges.append(newedge2)
544 self.hexedges.append(newedge3)
546 def hexvertface(self, vert):
547 vertices = []
548 for edge in vert.edges:
549 eid = edge.index
550 if edge.a is vert:
551 vertices.append(self.hexedges[eid].a)
552 elif edge.b is vert:
553 vertices.append(self.hexedges[eid].b)
554 newface = face(vertices)
555 self.hexfaces.append(newface)
557 def starify(self):
558 self.starverts = []
559 self.staredges = []
560 self.starfaces = []
561 for i in range(len(self.verts)):
562 self.verts[i].index = i
563 for i in range(len(self.edges)):
564 self.edges[i].index = i
565 self.connectivity()
566 star_vert_counter = 0
567 for currentedge in self.edges:
568 newvert = average([currentedge.a, currentedge.b]).centroid()
569 newvert.index = star_vert_counter
570 star_vert_counter += 1
571 self.starverts.append(newvert)
572 star_face_counter = 0
573 star_edge_counter = 0
574 for currentface in self.faces:
575 currentface.docorners()
576 vertices = []
577 for corner in currentface.corners:
578 vert = self.starverts[corner[1].index]
579 vertices.append(vert)
580 newface = face(vertices)
581 newface.index = star_face_counter
582 star_face_counter += 1
583 newedge1 = edge(vertices[0], vertices[1])
584 newedge1.index = star_edge_counter
585 newedge2 = edge(vertices[1], vertices[2])
586 newedge2.index = star_edge_counter + 1
587 newedge3 = edge(vertices[2], vertices[0])
588 newedge3.index = star_edge_counter + 2
589 star_edge_counter += 3
590 self.starfaces.append(newface)
591 self.staredges.append(newedge1)
592 self.staredges.append(newedge2)
593 self.staredges.append(newedge3)
594 for vert in self.verts:
595 vertices = []
596 vert.clockwise()
597 for currentedge in vert.edges:
598 eid = currentedge.index
599 vertices.append(self.starverts[eid])
600 newface = face(vertices)
601 newface.index = star_face_counter
602 star_face_counter += 1
603 self.starfaces.append(newface)
604 self.verts = self.starverts
605 self.edges = self.staredges
606 self.faces = self.starfaces
607 self.vertedgeflag = 0
608 self.vertfaceflag = 0
609 self.faceedgeflag = 0
611 def class2(self):
612 self.class2verts = []
613 self.class2edges = []
614 self.class2faces = []
616 newvertstart = len(self.verts)
617 newedgestart = len(self.edges)
618 counter_verts = len(self.verts)
619 for i in range(counter_verts):
620 self.verts[i].index = i
621 for i in range(len(self.edges)):
622 self.edges[i].index = i
623 for i in range(len(self.faces)):
624 self.faces[i].index = i
625 self.connectivity()
626 for currentface in self.faces:
627 currentface.docorners()
628 newvert = average(currentface.vertices).centroid()
629 newvert.index = counter_verts
631 counter_verts += 1
632 self.verts.append(newvert)
633 newedge1 = edge(currentface.vertices[0], newvert)
634 newedge2 = edge(currentface.vertices[1], newvert)
635 newedge3 = edge(currentface.vertices[2], newvert)
637 self.edges.append(newedge1)
638 self.edges.append(newedge2)
639 self.edges.append(newedge3)
640 for currentedge in range(newedgestart):
641 self.edges[currentedge].a = self.verts[self.edges[currentedge].faces[0].index + newvertstart]
642 self.edges[currentedge].b = self.verts[self.edges[currentedge].faces[1].index + newvertstart]
643 self.edges[currentedge].findvect()
645 for currentvert in range(newvertstart):
646 vert = self.verts[currentvert]
647 vertices = []
648 vert.clockwise()
649 for currentface in vert.faces:
650 eid = currentface.index
651 vertices.append(self.verts[newvertstart + eid])
653 for i in range(len(vertices)):
654 if i == len(vertices) - 1:
655 next = vertices[0]
656 else:
657 next = vertices[i + 1]
659 newface = face([vert, vertices[i], next])
660 self.class2faces.append(newface)
662 self.faces = self.class2faces
663 self.vertedgeflag = 0
664 self.vertfaceflag = 0
665 self.faceedgeflag = 0
667 def dual(self):
668 self.dualverts = []
670 self.dualfaces = []
672 counter_verts = len(self.verts)
673 for i in range(counter_verts):
674 self.verts[i].index = i
675 for i in range(len(self.edges)):
676 self.edges[i].index = i
677 for i in range(len(self.faces)):
678 self.faces[i].index = i
679 self.connectivity()
680 counter_verts = 0
681 for currentface in self.faces:
682 currentface.docorners()
683 newvert = average(currentface.vertices).centroid()
684 newvert.index = counter_verts # PKHG needed in >= 2.59
685 counter_verts += 1
686 self.dualverts.append(newvert)
687 for vert in self.verts:
688 vertices = []
689 vert.clockwise()
690 for currentface in vert.faces:
691 eid = currentface.index
692 vertices.append(self.dualverts[eid])
693 newface = face(vertices)
694 self.dualfaces.append(newface)
695 for currentedge in self.edges:
696 currentedge.a = self.dualverts[currentedge.faces[0].index]
697 currentedge.b = self.dualverts[currentedge.faces[1].index]
698 self.verts = self.dualverts
700 self.faces = self.dualfaces
701 self.vertedgeflag = 0
702 self.vertfaceflag = 0
703 self.faceedgeflag = 0
706 class facetype(mesh):
707 def __init__(self, basegeodesic, parameters, width, height, relative):
708 mesh.__init__(self)
709 self.detach = parameters[0]
710 self.endtype = parameters[1]
711 self.coords = parameters[2]
712 self.base = basegeodesic
713 self.relative = relative
714 self.width = width
716 if not self.relative:
717 newwidth = self.findrelative()
718 self.width = width * newwidth
719 self.height = height
720 self.base.connectivity()
721 for coord in self.coords:
722 coord[0] = coord[0] * self.width
723 coord[1] = coord[1] * self.height
724 if not self.base.facenormalflag:
725 for currentface in self.base.faces:
727 currentface.docorners()
728 currentface.findnormal()
730 self.base.facenormalflag = 1
731 if self.endtype == 4 and not self.base.vertnormalflag:
732 for currentvert in self.base.verts:
733 currentvert.findnormal()
734 self.base.vertnormalflag = 1
735 self.createfaces()
737 def findrelative(self):
738 centre = average(self.base.faces[0].vertices).centroid()
739 edgelist = []
740 for point in self.base.faces[0].vertices:
741 newedge = edge(centre, point)
742 edgelist.append(newedge)
743 length = 0
744 for edg in edgelist:
745 extra = edg.vect.length
746 length = length + extra
748 length = length / len(edgelist)
750 return length
752 def createfaces(self):
753 if not self.detach:
754 for point in self.base.verts:
755 self.verts.append(point)
756 if self.endtype == 4:
757 self.createghostverts()
758 for currentface in self.base.faces:
759 self.doface(currentface)
761 def createghostverts(self):
762 self.ghoststart = len(self.verts)
763 for vert in self.base.verts:
764 newvert = vert + (vert.normal * self.coords[-1][1])
765 self.verts.append(newvert)
767 def doface(self, candidate):
768 grid = []
769 candidate.dospokes()
771 if not self.detach:
772 line = []
773 for vert in candidate.vertices:
774 line.append(vert)
775 grid.append(line)
776 else:
777 line = []
778 for point in candidate.vertices:
779 newvert = vertex(point.vector)
780 self.verts.append(newvert)
781 line.append(newvert)
782 grid.append(line)
783 finish = len(self.coords)
784 if self.endtype == 1 or self.endtype == 4:
785 finish = finish - 1
786 for i in range(finish):
787 up = candidate.normal * self.coords[i][1]
788 line = []
789 for j in range(len(candidate.vertices)):
790 dotfac = candidate.corners[j][3] * 0.5
791 vec = (candidate.spokes[j] * (self.coords[i][0] / sin(dotfac)))
793 newvert = candidate.vertices[j] + vec + up
794 line.append(newvert)
795 self.verts.append(newvert)
796 grid.append(line)
797 if self.endtype == 4:
798 line = []
799 for i in range(len(candidate.vertices)):
800 vert = self.verts[candidate.vertices[i].index + self.ghoststart]
801 line.append(vert)
803 grid.append(line)
804 for line in grid:
805 line.append(line[0])
806 if self.endtype == 3:
807 grid.append(grid[0])
808 for i in range(len(grid) - 1):
809 for j in range(len(grid[i]) - 1):
810 one = grid[i][j]
811 two = grid[i][j + 1]
812 three = grid[i + 1][j + 1]
813 four = grid[i + 1][j]
814 newface = face([one, two, three, four])
815 self.faces.append(newface)
816 if self.endtype == 2:
817 finalfaceverts = grid[-1]
818 newface = face(finalfaceverts[:-1])
819 self.faces.append(newface)
820 if self.endtype == 1:
821 lastvert = average(candidate.vertices).centroid()
822 up = candidate.normal * self.coords[-1][1]
823 newvert = lastvert + up
824 self.verts.append(newvert)
825 ring = grid[-1]
826 for i in range(len(ring) - 1):
827 newface = face([newvert, ring[i], ring[i + 1]])
828 self.faces.append(newface)
831 class importmesh(mesh):
832 def __init__(self, meshname, breakquadflag):
833 mesh.__init__(self)
835 obj = bpy.data.objects[meshname]
836 bpy.context.view_layer.objects.active = obj
837 obj.select_set(True)
838 impmesh = None
839 if not breakquadflag:
840 bpy.ops.object.mode_set(mode='EDIT')
841 impmesh = bmesh.new() # create an empty BMesh
842 impmesh.from_mesh(obj.data) # fill it in from a Mesh
843 bpy.ops.object.mode_set(mode='OBJECT')
845 if breakquadflag:
846 bpy.ops.object.mode_set(mode='EDIT')
847 bpy.ops.mesh.quads_convert_to_tris()
848 impmesh = bmesh.new() # create an empty BMesh
849 impmesh.from_mesh(obj.data) # fill it in from a Mesh
850 bpy.ops.object.mode_set(mode='OBJECT')
852 for v in impmesh.verts:
853 vert = vertex(v.co)
854 vert.index = v.index
855 self.verts.append(vert)
856 # PKHG verts is now a list of vertex, so to say a copy of the Vectors
858 # PKHG edges
859 for e in impmesh.edges:
860 tmp = []
861 for vert in e.verts:
862 a = self.verts[vert.index]
863 tmp.append(a)
864 newedge = edge(tmp[0], tmp[1])
865 newedge.index = e.index
866 self.edges.append(newedge)
867 # PKHG faces
868 extra_DBG_info("MeshInfo", "vefm L868 the mesh impmesh", impmesh.faces[:])
870 for f in impmesh.faces:
871 temp = []
872 for vert in f.verts: # PKHG a list! of indices ??? PKHG>???
873 a = self.verts[vert.index] # PKHG verts contains already vertex objects
874 temp.append(a)
875 newface = face(temp)
876 newface.index = f.index # indexcount
877 self.faces.append(newface)
878 self.dovertedge()
879 self.dovertface()
880 self.temp = []
882 for i in range(len(self.verts)):
883 self.temp.append([])
884 self.verts[i].index = i
885 for i in range(len(self.verts)):
886 target = self.surroundingverts(self.verts[i])
887 for j in range(len(target)): # go through those verts
888 temptarg = self.temp[target[j].index]
889 flag = 0 # set a flag up
891 for k in range(len(temptarg)): # go through temp list for each of those verts
893 if temptarg[k] == i: # if we find a match to the current vert...
894 flag = 1 # raise the flag
896 if flag == 0: # if there is no flag after all that...
897 self.temp[target[j].index].append(i) # add current vert to temp list of this surrounding vert
898 self.temp[i].append(target[j].index) # add this surrounding vert to the current temp list
899 newedge = edge(self.verts[i], self.verts[target[j].index])
900 self.edges.append(newedge) # add the newly found edge to the edges list
902 for edg in self.edges:
903 edg.findvect()
904 self.vertedgeflag = 0
905 self.vertedgeflag = 0
906 self.connectivity()
908 def surroundingverts(self, vert):
909 ''' Find the verts surrounding vert'''
910 surround = [] # list to be filled and returned
911 for faces in vert.faces: # loop through faces attached to vert
912 finish = len(faces.vertices)
913 for i in range(finish):
914 if i == finish - 1:
915 next = faces.vertices[0]
916 else:
917 next = faces.vertices[i + 1]
918 if vert == faces.vertices[i]:
919 surround.append(next)
920 return surround
922 def breakquad(self, quad_face):
923 ''' turn quads into triangles'''
924 distance1 = quad_face.vertices[0] - quad_face.vertices[2]
925 distance2 = quad_face.vertices[1] - quad_face.vertices[3]
926 distance1.findlength()
927 distance2.findlength()
928 if abs(distance1.length) < abs(distance2.length):
929 self.faces[quad_face.index] = face([quad_face.vertices[0], quad_face.vertices[1], quad_face.vertices[2]])
930 self.faces.append(face([quad_face.vertices[0], quad_face.vertices[2], quad_face.vertices[3]]))
931 else:
932 self.faces[quad_face.index] = face([quad_face.vertices[0], quad_face.vertices[1], quad_face.vertices[3]])
933 self.faces.append(face([quad_face.vertices[1], quad_face.vertices[2], quad_face.vertices[3]]))
936 class strut(mesh):
937 def __init__(self, base, struttype, width, height, length, widthtog, heighttog,
938 lengthtog, meshname, stretchflag, lift):
940 extra_DBG_info(name="StrutMesh", info_text="vefm L940\nstrut called: ",
941 info_obj=[base, struttype, width, height, length, widthtog,
942 heighttog, lengthtog, meshname, stretchflag, lift])
943 mesh.__init__(self)
944 # put in strut prep stuff here
945 if struttype is None:
946 return
947 total = 0
948 divvy = len(base.faces[0].edges)
949 for lengf in base.faces[0].edges:
950 lengf.vect.findlength()
951 total = total + lengf.vect.length
952 yardstick = total / divvy
953 if widthtog:
954 self.width = width
955 else:
956 self.width = width * yardstick
957 if heighttog:
958 self.height = height
959 else:
960 self.height = height * yardstick
961 if lengthtog:
962 self.shrink = length
963 else:
964 self.shrink = length * yardstick
965 if not base.facenormalflag:
966 for currentface in base.faces:
967 currentface.docorners()
968 currentface.findnormal()
969 base.facenormalflag = 1
970 for edj in base.edges:
971 edj.findnormal()
972 side = edge(edj.a, edj.b)
973 edj.unit = side.vect
974 edj.unit.normalize()
975 edj.cross = crossp(edj.normal, edj.unit).docrossproduct()
976 template = importmesh(meshname, 0)
977 maxx = 0
978 minx = 0
979 for vert in template.verts:
980 if vert.vector.x > maxx:
981 maxx = vert.vector.x
982 if vert.vector.x < minx:
983 minx = vert.vector.x
984 for edj in base.edges:
985 start = len(self.verts)
986 centre = average([edj.a, edj.b]).centroid()
987 split = edj.vect.length / 2
988 # PKHG no division by zero!!
989 tmp = 1.0
990 if maxx != minx:
991 tmp = 1.0 / (maxx - minx)
992 dubbl = edj.vect.length * tmp
993 # PKHG end no division by zero!!
994 diffplus = split - maxx
995 diffminus = -split - minx
996 for point in template.verts:
997 ay = (edj.normal * point.vector.z * self.height) + (edj.normal * lift)
998 ce = edj.cross * point.vector.y * self.width
1000 if stretchflag:
1001 be = edj.unit * self.shrink * dubbl * point.vector.x
1002 else:
1003 if point.vector.x > 0.0:
1004 be = edj.unit * self.shrink * (point.vector.x + diffplus)
1005 elif point.vector.x < 0.0:
1006 be = edj.unit * self.shrink * (point.vector.x + diffminus)
1007 elif point.vector.x == 0.0:
1008 be = edj.unit * self.shrink * point.vector.x
1009 de = ay + be + ce
1010 newvert = centre + de
1011 self.verts.append(newvert)
1012 for edjy in template.edges:
1013 one = edjy.a.index + start
1014 two = edjy.b.index + start
1015 newedge = edge(self.verts[one], self.verts[two])
1016 self.edges.append(newedge)
1017 for facey in template.faces:
1018 faceverts = []
1019 for verty in facey.vertices:
1020 index = verty.index + start
1021 faceverts.append(self.verts[index])
1022 newface = face(faceverts)
1023 self.faces.append(newface)
1024 self.vertedgeflag = 0
1025 self.vertedgeflag = 0
1026 self.connectivity()
1029 class hub(mesh):
1030 def __init__(self, base, hubtype, width, height, length,
1031 widthtog, heighttog, lengthtog, meshname):
1032 mesh.__init__(self)
1033 self.width = 1.0
1034 self.height = 1.0
1035 self.shrink = 1.0
1036 # put in strut prep stuff here
1037 extra_DBG_info("vefm L1037 HubMesh", "base is ", str(dir(base)) + "\n and meshname = " + meshname)
1038 if hubtype is None:
1039 return
1040 total = 0
1041 divvy = len(base.faces[0].edges)
1042 for lengf in base.verts[0].edges:
1043 lengf.vect.findlength()
1044 total = total + lengf.vect.length
1045 yardstick = total / divvy
1046 if widthtog:
1047 self.width = width
1048 else:
1049 self.width = width * yardstick
1050 if heighttog:
1051 self.height = height
1052 else:
1053 self.height = height * yardstick
1054 if lengthtog:
1055 self.shrink = length
1056 else:
1057 self.shrink = length * yardstick
1059 if not base.facenormalflag:
1060 for currentface in base.faces:
1061 currentface.docorners()
1062 currentface.findnormal()
1063 base.facenormalflag = 1
1065 for apex in base.verts:
1066 apex.findnormal()
1067 side = edge(apex.edges[0].a, apex.edges[0].b)
1068 apex.unit = side.vect # PKHG is Vector: b - a
1069 apex.unit.normalize()
1070 apex.cross = crossp(apex.normal, apex.unit).docrossproduct()
1071 apex.unit = crossp(apex.cross, apex.normal).docrossproduct()
1073 template = importmesh(meshname, 0)
1074 for apex in base.verts:
1075 start = len(self.verts)
1076 centre = apex
1077 for point in template.verts:
1078 ay = apex.normal * point.vector.z * self.height
1079 ce = apex.cross * point.vector.y * self.width
1080 be = apex.unit * point.vector.x * self.shrink
1081 de = ay + be + ce
1082 newvert = centre + de
1083 self.verts.append(newvert)
1084 for edjy in template.edges:
1085 one = edjy.a.index + start
1086 two = edjy.b.index + start
1087 newedge = edge(self.verts[one], self.verts[two])
1088 self.edges.append(newedge)
1089 for facey in template.faces:
1090 faceverts = []
1091 for verty in facey.vertices:
1092 index = verty.index + start
1093 faceverts.append(self.verts[index])
1094 newface = face(faceverts)
1095 self.faces.append(newface)
1096 self.vertedgeflag = 0
1097 self.vertedgeflag = 0
1098 self.connectivity()
1101 # ???PKHG TODO Nmesh used yet wrong!
1102 def finalfill(source, target):
1103 if source == target: # PKHG: otherwise >infinite< loop
1104 print("\n***WARNING*** vefm_271.finalfill L1104 source == target empty mesh used")
1105 target = mesh()
1106 # PKHG_??? maybe renumverting and checking faces with >=4 5 vertices?
1107 count = 0
1109 for point in source.verts:
1110 newvert = vertex(point.vector)
1111 newvert.index = count
1112 target.verts.append(newvert)
1113 point.index = count # PKHG_INFO source renumbered too!
1115 count += 1
1117 for facey in source.faces:
1118 row = len(facey.vertices)
1119 if row >= 5:
1120 tmp = Vector()
1121 for el in facey.vertices:
1122 tmp = tmp + target.verts[el.index].vector
1123 tmp = tmp / row
1124 centre = vertex(tmp)
1125 centre.index = count # PKHG_??? give it a good index
1126 count += 1
1128 target.verts.append(centre)
1129 for i in range(row):
1130 if i == row - 1:
1131 a = target.verts[facey.vertices[-1].index]
1132 b = target.verts[facey.vertices[0].index]
1133 else:
1134 a = target.verts[facey.vertices[i].index]
1135 b = target.verts[facey.vertices[i + 1].index]
1136 target.faces.append([a, b, centre])
1137 else:
1138 f = []
1140 for j in range(len(facey.vertices)):
1141 a = facey.vertices[j]
1142 f.append(target.verts[a.index])
1144 target.faces.append(f)