#! /usr/bin/python3 # Last edited on 2024-09-19 08:39:35 by stolfi from math import sin, cos, tan, sqrt, pi, inf, floor, sqrt import rn import sys import re from slicing_naf_vertices import make_vertices from slicing_naf_faces_orig import make_edges_faces_orig from slicing_naf_faces_mono import monotonize from slicing_naf_faces_convex import convexify from slicing_naf_faces_triang import triangulate from slicing_lib import min_edge_length, min_triangle_width import OBJ_format import POV_format prec = 4 # Decimal digits eps = 0.1**prec # Coordinate quantum. # The generic object of the family is a fan-like solid, symmetric about the {Y=0} and {X=0} # planes. It has two large congruent faces (the /plazas/) perpendicular # to the {X}-axis, connected by a ring of rectangular faces. The two # plazas are indexed by {km} in {0,1}; plaza [0] has positive {X} and # plaza [1] is its mirror image across the plane {X = 0}. # # The object is defined by parameters: # # {Ni} # Number of facets on upper side of fan # {Ru} # Circumradius of upper chain. # {Hx} # Nominal half-thickness of fan. # {Aspoke} # Elevation angle of spokes. # # The border of each plaza consists of a polygonal /upper chain/ of {Ni} edges, # plus two long edges (the /spokes/) whose lower endpoints lie on the {X}-axis. # The number {Ni} must be even. The spokes make an angle {Aspoke} with the # {Z=0} plane. # # The upper chain has two /extreme vertices/, convex, and {Ni-1} # /interior vertices/, all concave. Those vertices lie on the same # circle parallel to the {YZ} plane, with radius {Ru}, whose center lies # on the {Y=0} plane, well above the fan. # # COMMAND LINE # # The program takes two parameters from the command line: {Tag} and {Ni}, # The other parameters are defined internally. def main(): Tag = sys.argv[1] Ni = int(sys.argv[2]) # Parameter defining chain lengths. Ru = 100 # Circumradius of upper chain. Hx = 5 # Nominal half-thickness of fan. Aspoke = 60 # Elevation angle of spokes. assert Ni >= 2 and Ni % 2 == 0, "{Ni} must be even and 2 or more" Vind, Vlst = make_vertices(Ni, Ru, Hx, Aspoke, prec, verbose = False) Elst, Flst = make_edges_faces_orig(Ni, Vind, Vlst, prec, verbose = False) Emon, Fmon = monotonize(Ni, Vind, Vlst, Elst, Flst, prec, verbose = False) Ecvx, Fcvx = convexify(Ni, Vind, Vlst, Elst, Flst, prec, verbose = False) Etri, Ftri = triangulate(Ni, Vind, Vlst, Elst, Flst, prec, verbose = False) dmin = min_edge_length(Vlst, Etri) sys.stderr.write("min edge length = %.16f\n" % dmin) hmin = min_triangle_width(Vlst, Ftri) sys.stderr.write("min triangle width = %.16f\n" % hmin) opref = f"out/{Tag}_{Ni:08d}" OBJ_format.write_object(opref + "_orig.obj", Vlst, Elst, Flst, prec) OBJ_format.write_object(opref + "_mono.obj", Vlst, Emon, Fmon, prec) OBJ_format.write_object(opref + "_convex.obj", Vlst, Ecvx, Fcvx, prec) OBJ_format.write_object(opref + "_triang.obj", Vlst, Etri, Ftri, prec) if Ni < 20: Np = Ni - 1; # Find min {Z} of upper chain: umid = Vlst[Vind['vu'][0][Ni//2]] Zmid = umid[2] Zp_min = 2*Zmid/6; Zp_max = 5*Zmid/6 emag = 1.5 vmag = 1.0 POV_format.write_object(opref + "_orig.inc", Vlst, Elst, Flst, Np, Zp_min, Zp_max, emag, vmag, prec) POV_format.write_object(opref + "_mono.inc", Vlst, Emon, Fmon, Np, Zp_min, Zp_max, emag, vmag, prec) POV_format.write_object(opref + "_convex.inc", Vlst, Ecvx, Fcvx, Np, Zp_min, Zp_max, emag, vmag, prec) POV_format.write_object(opref + "_triang.inc", Vlst, Etri, Ftri, Np, Zp_min, Zp_max, emag, vmag, prec) return 0 main()