#! /usr/bin/python3 # Last edited on 2024-09-18 22:16:34 by stolfi from math import sin, cos, tan, sqrt, pi, inf, floor, sqrt import rn import sys import re from slicing_lib import reven, make_null_array, make_vertex, prtv def make_vertices(Ni, S_box, H_box, T_box, H_den, prec, verbose): # Computes the vertices of the object. # # See {slicing_box_example.py} for explanation of the parameters # {Ni,S_box,H_box,T_box.H_den}. The parameter {prec}is the number of # decimal digits to use for vertex coords. # # The procedure returns the vertices as a flat list {Vlst}, and also # as a {dict} structure {Vind} that provides access to vertices # by structural indexing. # # The {Vlst} return value is a flat list of the vertex records, # indexed {1..Nv} (as in an OBJ file) where {Nv} is the total vertex # count. Element {Vlst[0]} is not used. See {make_vertex} for a # rescription of a vertex record. # # All vertex coordinates are rounded to an even multiple of {10^{-prec}}. # # The structure {Vind} is a dict with a single key 'vi'. # # The 'vi' element of {Vi} has the indices of the vertices of the # indentations. It is an array {Vi[ks][kr][kz][ki]} for {ks} in # {0..3}, {kr,kz} in {[0..1]}, and {ki} in {0..2*Ni}. Subarray # {Vi[0][1][0]} has the indices of the vertices on the lower # ({kz=0}) chain of the outer ({kr=1}) plaza facing the {+X} direction # ({ks=0}), in order of increasing {Y}. Subarray {Vi[0][1][1]} has # the vertices of the upper chain of the same plaza, in order of # *decreasing* {Y}. Subarrays {Vi[0][0][0]} and {Vi[0][0][1]} have # the corresponding chains on the inner plaza facing the {+X} # direction. Finally, the other subarrays {Vi[ks][ks][kz]} for other # values of {ks} are the vertices of {Vi[0][kr][kz]} rotated {ks*90} # degrees about the {Z}-axis. # # The label of each vertes is "vi.{ks}{kr}{kz}.{ki}". eps = 0.1**prec # Coordinate quantum. sys.stderr.write("make_vertices:\n") sys.stderr.write(" Ni = %d \n" % Ni) sys.stderr.write(" S_box = %.*f H_box = %.*f T_box = %.*f\n" % (prec, S_box, prec, H_box, prec, T_box)) sys.stderr.write(" H_den = %.*f\n" % (prec, H_den)) sys.stderr.write(" eps = %.*f\n" % (prec, eps)) assert S_box - H_den - T_box >= 0.125*T_box, "{S_box-T_box} should be a tad bigger than {H_den}" Nv = 4*2*2*(2*Ni + 1) # Expected vertex count. Vi = make_null_array((4,2,2,2*Ni+1)) Vlst = [ None ]*(Nv+1) # Generate generic indentation vertices (for wall 0, bottom): YZden = indent_yz_coords(Ni, H_den) assert len(YZden) == 2*Ni+1 nv = 0; # Number of vertices generated so far. */ for ks in range(4): for kr in range(2): S_pla = S_box if kr == 1 else S_box - T_box; # Half-with and inradius of plaza. for kz in range(2): for ki in range(2*Ni+1): yzi = YZden[ki] nv += 1 plab = f"vi.{ks}{kr}{kz}.{ki}" px = reven(+S_pla, eps) py = reven(yzi[0], eps) pz = reven(yzi[1] - H_box, eps) if kz == 1: # Rotate {pp} by 180 about {X}. Note that rounding is preserved: py, pz = -py, -pz; for js in range(ks): # Rotate {pp} by 90 about {Z}. Note that rounding is preserved: px, py = -py, px pp = make_vertex(px, py, pz, nv, plab) if verbose: prtv(pp, prec) Vi[ks][kr][kz][ki] = nv; Vlst[nv] = pp assert nv == Nv, "unexpected vertex count" Vind = { 'vi': Vi } return Vind, Vlst def indent_yz_coords(Ni, H_den): # Computes the {Y} and {Z} coords of vertices at the indentation at the bottom of a plaza {ks=0}, # as an array of {2*Ni+1} pairs {(Yk,Zk)}. Parameters: # {Ni} Half the number of facets in each indentation. # {H_den} Half-width of indentations. YZden = [ None ]*((2*Ni)+1) dango = pi/(4*Ni) # Argument increment per indentation face. for ki in range((2*Ni)+1): ai = pi/4 + ki*dango # argument of vertex. Yi = - H_den*cos(ai) # {Y} coord of indentation vertex. Zi = + H_den*(sin(ai) - sin(pi/4)) # {Z} coord of indentation vertex above box edge. YZden[ki] = ( Yi, Zi ) return YZden