#! /usr/bin/python3 # Last edited on 2024-09-18 19:11:52 by stolfi from math import sin, cos, tan, sqrt, pi, inf, floor, sqrt import rn import sys import re from slicing_lib import make_edge, make_face, check_repeated_edge, prte, prtf def make_edges_faces_orig(Ni, Vind, Vlst, prec, verbose): # See {slicing_box_example} for the object's description. # # Builds lists of the faces and edges of the object, given the # vertices in structured form {Vind} and flat list {Vlst}, expected to # be the output of {slicing_box_vertices.make_vertices}. . # # Returns the records representing the faces as a flat list {Flst} with # indices from 1 to {Nf}, where {nf} is the total number of faces. # Element {Flst[0]} is not used. See {make_face} for the face record # format. # # The edges are returned as single flat list {Elst} indexed from 1 to # {Ne}, Element {Elst[0]} is not used. See {make_edge} for the edge # record format. (This module generates only edges with {etype # = 0}.) # # Faces with {flab} of the form "fi.{ks}{kz}.{ki} are indentation # facets. Here {ks} is a box side index in {0..3}, {kz} is 0 for # bottom chain and 1 for top chain, and {ki} is a facet index in # {0..2*Ni-1}. The facets of both chains are listed in CCW order as # seen from the outside of the outer plaza. # # Faces with {flab} of the form "fh.{ks}{kz}" are the 8 horizontal # trapezoidal faces at the bottom and top of the walls. Here {ks,kz} # are as above. Specifically, that face connects the last indentation # facet "fi.{ks}{kz}.{2*Ni-1} to the first facet "fi.{ks'}{kz}.0" where # {ks'} is {ks+1} for {kz=0} and {ks-1} for {kz=1}. # # Faces with {flab} of the form "fp.{ks}{kr}" are the 8 plazas (major # wall surfaces), where {ks} is the wall index, as above, and {kr} is # 0 for the internal wall surface and 1 for the external surface. # # Faces with {flab} of the form "fc.{ks}{kr}" are the chamfer faces # Here {ks,kr} are as above. Specifically, that chamfer lies between # plaza "fp.{ks}{kr}" and "fp.{ks'}{kr} where {ks'} is {ks+1} modulo 4. # Output element counts PER WALL: Nv_w = 2*2*(2*Ni+1) # Indentation vertices, inner/outer, lower/upper. Ne_w_i = 2*(3*2*Ni + 1) # Indentation edges, lower/upper. Ne_w_h = 2*2 # Horizontal corner edges, inner/outer, lower/upper. Ne_w_c = 2*2 # Chamfer edges, inner/outer, fore/back. Nf_w_i = 2*(2*Ni) # Indentation faces, lower/upper. Nf_w_h = 2 # Horizontal corner faces, lower/upper. Nf_w_c = 2 # Chamfer faces, inner/outer. Nf_w_p = 2 # Plaza faces, inner/outer. Nv = 4*Nv_w # Expected total number of vertices. Ne = 4*(Ne_w_i + Ne_w_h + Ne_w_c) # Expected total number of edges. Nf = 4*(Nf_w_i + Nf_w_h + Nf_w_c + Nf_w_p) # Expected total number of faces. sys.stderr.write("Expecting %d faces\n" % Nf) sys.stderr.write("Expecting %d edges\n" % Ne) assert Nv == len(Vlst)-1, "{Nv,Vlst} inconsistent" # Variables that are global to the nested functions: Fiv = [] # Indices of vertices of current face. Flab = "???" # Current face label. nf = 0; # Number of faces found so far. ne = 0; # Number of edges found so far. debug_face = False Flst = [None]*(Nf+1) Elst = [None]*(Ne+1) Eset = set() # Set of edges as pairs, to check for repetitions. def Sved(kv_org, kv_dst): # Saves the edge from {Vlst[kv_org]} to {Vlst[kv_dst]} in {Elst}, if traversed # in increasing vertex index sense. nonlocal Fiv, Flab, nf, ne, debug_face, Elst, Flst elab = Vlst[kv_org][4] + "--" + Vlst[kv_dst][4] + ":" + Flab etype = 0 e = make_edge(Vlst[kv_org], Vlst[kv_dst], ne+1, etype, elab, prec) if e != None: if verbose: prte(e, prec) ne += 1 Elst[ne] = e # Check for repeated edges: */ check_repeated_edge(ne, Elst, Eset, prec) return None def Ptit(tit, debug = False): # Title for a face or set of faces. nonlocal Fiv, Flab, nf, ne, debug_face, Elst, Flst if (verbose): sys.stderr.write(" defining %s \n" % (tit)); debug_face = debug def Bof(flab,debug = False): # Start of a new face. nonlocal Fiv, Flab, nf, ne, debug_face, Elst, Flst assert len(Fiv) == 0 Flab = flab if (verbose): sys.stderr.write("\n"); debug_face = debug def Addv(ki): # Adds vertex with OBJ index {ki} to the current face. nonlocal Fiv, Flab, nf, ne, debug_face, Elst, Flst p = Vlst[ki] assert p[3] == ki if debug_face: sys.stderr.write(" v%4d = ( %9.*f %9.*f %9.*f ) %s\n" % (ki, prec, p[0], prec, p[1], prec, p[2], p[4])); # Saves vertex in list {Fiv} of face vertices: Fiv.append(ki); return None def Eof(order): # Close current face with edge from last to first vertex: nonlocal Fiv, Flab, nf, ne, debug_face, Elst, Flst deg = len(Fiv) assert deg >= 3, "face has only %d corners" % deg if order == -1: # Reverse vertex list: Fiv = [ Fiv[deg-1-k] for k in range(deg) ] nf += 1; f = make_face(Fiv, nf, Flab, Vlst, prec) if verbose or debug_face: prtf(f, Vlst, prec) Flst[nf] = f; # Save the edges: for jv in range(deg): jv1 = (jv+1) % deg Sved(Fiv[jv], Fiv[jv1]) Fiv = [] # CREATE THE FACES: for ks in range(4): ksp = (ks+1) % 4 ksm = (ks-1) % 4 for kz in range(2): zdir = 2*kz - 1 Ptit("indentation faces -- ks = %d kz = %d" % (ks,kz)) for jf in range(2*Ni): Bof(f"fi.{ks}{kz}.{jf}") Addv(Vind['vi'][ks][1][kz][jf]) Addv(Vind['vi'][ks][0][kz][jf]) Addv(Vind['vi'][ks][0][kz][jf+1]) Addv(Vind['vi'][ks][1][kz][jf+1]) Eof(+1) Ptit("corner face -- ks = %d kz = %d" % (ks,kz)) ksz = (ks - zdir) % 4 Bof(f"fh.{ks}{kz}") Addv(Vind['vi'][ks][0][kz][2*Ni]) Addv(Vind['vi'][ksz][0][kz][0]) Addv(Vind['vi'][ksz][1][kz][0]) Addv(Vind['vi'][ks][1][kz][2*Ni]) Eof(+1) for kr in range(2): rdir = 2*kr - 1 Ptit("chamfer face -- ks = %d kr = %d" % (ks,kr)) Bof(f"fc.{ks}{kz}") Addv(Vind['vi'][ks][kr][0][2*Ni]) Addv(Vind['vi'][ksp][kr][0][0]) Addv(Vind['vi'][ksp][kr][1][2*Ni]) Addv(Vind['vi'][ks][kr][1][0]) Eof(rdir) Ptit("plaza face -- ks = %d kr = %d" % (ks,kr)) Bof(f"fp.{ks}{kr}") for ki in range(2*Ni+1): Addv(Vind['vi'][ks][kr][0][ki]) for ki in range(2*Ni+1): Addv(Vind['vi'][ks][kr][1][ki]) Eof(rdir) if nf < Nf: sys.stderr.write("!! missing some faces\n") assert nf <= Nf if ne < Ne: sys.stderr.write("!! missing some edges\n") assert ne <= Ne return Elst, Flst