#! /usr/bin/python3 # Last edited on 2024-09-18 22:20:35 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_naf_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_naf_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 "fu.{ki} are upper chain facets. Here # {ki} is a facet index in {0..Ni-1}, numbered in order of increasing # {Y} coordinate. # # Faces with {flab} of the form "fs.{ky}" are the two faces # bounded by the spokes. Here {ky} is 0 for the spoke face in negative {Y}, # and 1 for the spoke face at positive {Y}. # # Faces with {flab} of the form "fp.{kx}" are the two plazas, where {kx} is # 0 for negative {X} and 1 for positive {X}. # Rounds each coordinate to even multiple of {eps}. Returns an array # {Pind} with the same shape as {Vind} but where each point is # replaced by the integer index of the vertex, as expected by the OBJ # format (from 1). # # Also returns a list {Vpos} where element {Vpos[i]} is the # coordinates of the vertex with OBJ index {i}, for {i} in {1..Nv} # where {Nv} is the total number of vertices. Note that {Vpos[0]} is # undefined. The vertices are listed in ccw order around the origin # as seen from {(+oo,0,0)}, first all on plaza [0], then all on plaza [1]. # # Also returns a list {Vlab} where element {Vlab[i]} is the # position in {Vind} of vertex {Vpos[i]}. Namely # "vo.0.5" to mean {Vind[0]['vo'][5]} or "vi.1.4" to mean {Vind[1]['vi'][4]}. # Output element counts: Nv = 2*(Ni+2) # Expected number of vertices. Ne = 3*(Ni+2) # Expected number of edges. Nf = Ni+4 # Expected number of faces. 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: Ptit("upper chain faces") for ki in range(Ni): Bof(f"fu.{ki}") Addv(Vind['vu'][0][ki]) Addv(Vind['vu'][1][ki]) Addv(Vind['vu'][1][ki+1]) Addv(Vind['vu'][0][ki+1]) Eof(+1) for ky in range(2): ydir = 2*ky - 1 Ptit("spoke face ky = %d" % ky) Bof(f"fs.{ky}") ki = 0 if ky == 0 else Ni Addv(Vind['vu'][0][ki]) Addv(Vind['vu'][1][ki]) Addv(Vind['vc'][1]) Addv(Vind['vc'][0]) Eof(ydir) for kx in range(2): xdir = 2*kx - 1 Ptit("plaza face kx = %d" % kx) Bof(f"fp.{kx}") for ki in range(Ni+1): Addv(Vind['vu'][kx][ki]) Addv(Vind['vc'][kx]) Eof(-xdir) 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