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