#! /usr/bin/python3 # Last edited on 2024-09-19 08:08:42 by stolfi from math import sin, cos, tan, sqrt, pi, inf, floor, sqrt import rn import sys import re from slicing_lib import reven, radians, make_null_array, make_vertex, prtv def make_vertices(Ni, Ru, Hx, Aspoke, prec, verbose): # Computes the vertices of the object. # # See {slicing_naf_example.py} for explanation of the parameters # {Ni,Ru,Hx,Aspoke}. 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 two keys, 'vu' and 'vc'. # # The 'vu' element of {Vind} has the indices of the vertices of the # upper chains, in order of incrasing {Y}. It is an array {Vu[kx][ki]} # for {kx} in {[0..1]} and {ki} in {0..Ni}. Subarray {Vu[0]} has the # indices of the vertices with {X=-Hx}, and {Vu[1]} has those with # {X=+Hx}. The label of each vertes is "vu.{kx}.{ki}". # # The 'vc' element of {Vind} is an array {Vc[kx]} for {kx} in # {[0..1]}, with the bottom vertices where the spokes meet.. Subarray # {Vc[0]} is the index of the vertex with {X=-Hx}, and {Vc[1]} is that # with {X=+Hx}. The label of each vertes is "vc.{kx}". eps = 0.1**prec # Coordinate quantum. sys.stderr.write("make_vertices:\n") sys.stderr.write(" Ni = %d \n" % Ni) sys.stderr.write(" Ru = %.*f Hx = %.*f\n" % (prec, Ru, prec, Hx)) sys.stderr.write(" Aspoke = %.2f\n" % Aspoke) sys.stderr.write(" eps = %.*f\n" % (prec, eps)) Nv = 2*(Ni + 2) # Expected vertex count. sys.stderr.write(" expecting %d vertices\n" % Nv) Vu = make_null_array((2,Ni+1)) # Upper chain vertices. Vc = [ None, None ] # Bottom (center) vertices. Vlst = [ None ]*(Nv+1) YZuch = upper_chain_yz_coords(Ni, Ru, Aspoke) assert len(YZuch) == Ni+1 nv = 0; # Number of vertices generated so far. */ for kx in range(2): x_pla = -Hx if kx == 0 else +Hx for ki in range(Ni+1): yzi = YZuch[ki] nv += 1 plab = f"vu.{kx}.{ki}" px = x_pla; py = yzi[0]; pz = yzi[1] pp = make_vertex(reven(px, eps), reven(py, eps), reven(pz, eps), nv, plab) if verbose: prtv(pp, prec) Vlst[nv] = pp Vu[kx][ki] = nv; nv += 1 qlab = f"vc.{kx}" qx = x_pla; qy = 0; qz = 0; qq = make_vertex(reven(qx, eps), reven(qy, eps), reven(qz, eps), nv, qlab) Vlst[nv] = qq Vc[kx] = nv; assert nv == Nv, "unexpected vertex count" Vind = { 'vu': Vu, 'vc': Vc } return Vind, Vlst def upper_chain_yz_coords(Ni, Ru, Aspoke): # Computes the vertices of a plaza at {X=0}, as an array of # pairs {(Yk, Zk)}, in order of increasing {Y}. Parameters: # {Ni} Number of edges in the upper chain. # {Ru} Radius of vertices in upper chain in each plaza. # {Aspoke} Spoke angle from {Z=0} plane (degrees). # Spoke elevation???s in radians: ang0 = radians(180 - Aspoke) # Elevation of {-Y} spoke (radians). ang1 = radians(Aspoke) # Elevation of {+Y} spoke (radians). YZuch = [ None ]*(Ni+1) Zm = Ru*sin(ang1) # {Z} coord of chord. sys.stderr.write(" Zm = %.8f\n" % Zm) dango = (ang1 - ang0)/Ni # Angle increment of upper edge faces (radians). for iv in range(Ni+1): ai = ang0 + iv*dango # Argument angle of vertex. Yi = Ru*cos(ai) # {Y} coord of {YZuch[]iv]}. Zi = Ru*sin(ai) # {Z} coord of {YZuch[]iv]}. YZuch[iv] = ( Yi, 2*Zm - Zi) return YZuch