#! /usr/bin/python3 # Last edited on 2024-09-18 10:33:24 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(Ns, Nr, Nb, R_keg, H_keg, prec, verbose): # Computes the vertices of the object. # # See {slicing_keg_example.py} for explanation of the parameters # {Ns,Nr,Nb,R_keg,H_keg}. 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 {slicing_lib.make_vertex} for a # description of a vertex record. # # All vertex coordinates are rounded to an even multiple of {10^{-prec}}. # # The structure {Vind} is a dict with keys 'vp', 've', 'vc'. # # The 'vp' element of {Vind} is an array {Vp[ks][kr]} with the # vertices of the basic grid of quadrangular faces. Here {ks} varies # in {0..Ns-1}, around the {Z} axis in CCW order, and {kr} varies in # {[0..Nr]}, from bottom to top. The label of each vertex in this set # is "vp.{ks}.{kr}". # # The 've' element of {Vind} is an array {Ve[ks][kr][kb]} where {ks} # varies in {0..Ns-1}, {kr} varies {[0..Nr-1]}, and {kb} varies in # {0..Nb-1}. This is the extra vertex indexed {kb}, from bottom up, # inserted in the vertcal-ish edge whose bottom endpoint is # {Vp[ks][kr]}. The label of each vertex in this set is # "ve.{ks}.{kr}.{kb}". # # The 'vc' element of {Vind} is an array {Vc[kz]} with the central vertices # of the bottom ({kz=0}) and top ({kz=1}) lids of the barrel. # The label of each vertex in this set is "vc.{kz}". eps = 0.1**prec # Coordinate quantum. sys.stderr.write("make_vertices:\n") sys.stderr.write(" Ns = %d Nr = %d Nb = %d\n" % (Ns, Nr, Nb)) sys.stderr.write(" R_keg = %.*f H_keg = %.*f\n" % (prec, R_keg, prec, H_keg)) sys.stderr.write(" eps = %.*f\n" % (prec, eps)) Nv = Ns*(Nr*(Nb+1) + 1) + 2 # Expected vertex count. sys.stderr.write(" expecting %d vertices\n" % Nv) Vp = make_null_array((Ns,Nr+1)) Ve = make_null_array((Ns,Nr,Nb)) Vc = [ None, None ] Vlst = [ None ]*(Nv+1) nv = 0; # Number of vertices generated so far. */ lat0 = pi/6 # Nominal angle of top edge of keg. R0 = H_keg/sin(lat0) # Nominal radius of keg profile. DR = R0 - R_keg # Offset of keg profile center from {Z}-axis. for kr in range(Nr+1): lat = (pi/3)*kr/Nr - lat0 for ks in range(Ns): lon = 2*pi*ks/Ns xy = R0*cos(lat) - DR px = xy*cos(lon) py = xy*sin(lon) pz = R0*sin(lat) nv += 1 plab = f"vp.{ks}.{kr}" pp = make_vertex(reven(px, eps), reven(py, eps), reven(pz, eps), nv, plab) if verbose: prtv(pp, prec) Vlst[nv] = pp Vp[ks][kr] = nv; if Nb > 0 and kr > 0: # Get vertex {qq} on same meridian, just below {pp}: qq = Vlst[Vp[ks][kr-1]] qx, qy, qz = qq[:3] for kb in range(Nb): f = (kb + 1)/(Nb + 1) ux = (1-f)*qx + f*px uy = (1-f)*qy + f*py uz = (1-f)*qz + f*pz nv += 1 ulab = f"ve.{ks}.{kr-1}.{kb}" uu = make_vertex(reven(ux, eps), reven(uy, eps), reven(uz, eps), nv, ulab) if verbose: prtv(uu, prec) Vlst[nv] = uu Ve[ks][kr-1][kb] = nv; for kz in range(2): cx = 0; cy = 0; cz = -H_keg if kz == 0 else +H_keg nv += 1 clab = f"vc.{kz}" cc = make_vertex(cx, cy, cz, nv, clab) if verbose: prtv(cc, prec) Vlst[nv] = cc Vc[kz] = nv; assert nv == Nv, "unexpected vertex count" Vind = { 'vp': Vp, 've': Ve, 'vc': Vc } return Vind, Vlst