1# vert class and overloading experiments 2import bpy 3# PKHG>NEEDED? 4import bmesh 5from math import acos, pi, sin, cos, atan, tan 6from mathutils import Vector 7from bpy_extras.object_utils import AddObjectHelper 8 9# PKHG>DBG change the DBG_info and use extra_DBG_info 10DBG_info = {"MeshInfo": False, "StrutMesh": False, "HubMesh": False} 11 12 13def 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) 19 20sgn = lambda x: (x > 0) - (x < 0) # missing signum function in Python 21 22 23def 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] 27 28 e = [[edge.a.index, edge.b.index] for edge in selfobj.edges] 29 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] 35 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 41 42 43# extra test phase 44 45class 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 54 55 def findlength(self): 56 self.length = self.vector.length 57 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 64 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() 78 79 def clockwise(self): # PKHG self is a vertex 80 if self.boundary: 81 start = self.boundarystart() 82 else: 83 start = self.faces[0] 84 85 self.tempedges = [] 86 self.tempfaces = [] 87 for i in range(len(self.edges)): 88 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 102 103 def boundarystart(self): 104 105 pass 106 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) 113 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) 120 121 def __mul__(self, other): 122 tmp = self.vector * other 123 return vertex(tmp) 124 125 def __truediv__(self, other): 126 denom = 1.0 / other 127 tmp = self.vector * denom 128 return (tmp) 129 130 def negative(self): 131 return vertex(-self.vector) 132 133 134class 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 139 140 def docrossproduct(self): 141 tmp = self.v1.vector.cross(self.v2.vector) 142 return vertex(tmp) 143 144 145class 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 149 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) 163 164 165class 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() 179 180 def findvect(self): 181 self.vect = self.b - self.a 182 self.vectb = self.a - self.b 183 184 def findlength(self): 185 self.vect.findlength() 186 self.vectb.length = self.vect.length 187 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() 194 195 196class 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 205 206 self.index = 0 207 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 220 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 249 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) 254 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: 293 294 dotty = self.dotproduct(rightvect, leftvect) 295 corner.append(dotty) 296 self.corners.append(corner) 297 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() 312 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) 326 327 one.normalize() 328 two.normalize() 329 spoke = one + two 330 spoke.normalize() 331 self.spokes.append(spoke) 332 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) 338 339 340class 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 361 362 def power(self, a, b): # Returns a power, including negative numbers 363 result = sgn(a) * (abs(a) ** b) 364 return result 365 366 def sign(self, d): # Works out the sign of a number. 367 return sgn(d) 368 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 385 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 392 393 def connectivity(self): 394 self.dovertedge() 395 self.dovertface() 396 self.dofaceedge() 397 self.boundary() 398 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 408 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 418 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 427 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 436 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 459 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 468 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 482 483 self.connectivity() 484 hexvert_counter = 0 485 for edge in self.edges: 486 487 self.hexshorten(edge, hexvert_counter) 488 hexvert_counter += 2 # PKHG two new vertices done 489 490 for face in self.faces: 491 self.makehexfaces(face) 492 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 502 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) 516 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 526 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) 531 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) 536 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) 545 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) 556 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 610 611 def class2(self): 612 self.class2verts = [] 613 self.class2edges = [] 614 self.class2faces = [] 615 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 630 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) 636 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() 644 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]) 652 653 for i in range(len(vertices)): 654 if i == len(vertices) - 1: 655 next = vertices[0] 656 else: 657 next = vertices[i + 1] 658 659 newface = face([vert, vertices[i], next]) 660 self.class2faces.append(newface) 661 662 self.faces = self.class2faces 663 self.vertedgeflag = 0 664 self.vertfaceflag = 0 665 self.faceedgeflag = 0 666 667 def dual(self): 668 self.dualverts = [] 669 670 self.dualfaces = [] 671 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 699 700 self.faces = self.dualfaces 701 self.vertedgeflag = 0 702 self.vertfaceflag = 0 703 self.faceedgeflag = 0 704 705 706class 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 715 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: 726 727 currentface.docorners() 728 currentface.findnormal() 729 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() 736 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 747 748 length = length / len(edgelist) 749 750 return length 751 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) 760 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) 766 767 def doface(self, candidate): 768 grid = [] 769 candidate.dospokes() 770 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))) 792 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) 802 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) 829 830 831class importmesh(mesh): 832 def __init__(self, meshname, breakquadflag): 833 mesh.__init__(self) 834 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') 844 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') 851 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 857 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[:]) 869 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 = [] 881 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 890 891 for k in range(len(temptarg)): # go through temp list for each of those verts 892 893 if temptarg[k] == i: # if we find a match to the current vert... 894 flag = 1 # raise the flag 895 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 901 902 for edg in self.edges: 903 edg.findvect() 904 self.vertedgeflag = 0 905 self.vertedgeflag = 0 906 self.connectivity() 907 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 921 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]])) 934 935 936class strut(mesh): 937 def __init__(self, base, struttype, width, height, length, widthtog, heighttog, 938 lengthtog, meshname, stretchflag, lift): 939 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 999 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() 1027 1028 1029class 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 1058 1059 if not base.facenormalflag: 1060 for currentface in base.faces: 1061 currentface.docorners() 1062 currentface.findnormal() 1063 base.facenormalflag = 1 1064 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() 1072 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() 1099 1100 1101# ???PKHG TODO Nmesh used yet wrong! 1102def 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 1108 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! 1114 1115 count += 1 1116 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 1127 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 = [] 1139 1140 for j in range(len(facey.vertices)): 1141 a = facey.vertices[j] 1142 f.append(target.verts[a.index]) 1143 1144 target.faces.append(f) 1145