argp = argparse.ArgumentParser(description='''Navigate around a hypercube or a mesh from a file. By default, a 3-dimensional cube will be displayed. To display a hypercube, use --dimension to specify the dimensionality. Alternatively, an arbitrary 3D mesh can be specified with --file, which should specify the path to a wavefront obj file. When using a file, only the polygon data will displayed. Lines and curves will be ignored.''') argp.add_argument('-d','--dimension',default=3,type=int,metavar='N',help='the dimensionality of the hypercube and the navigable space.') argp.add_argument('-f','--file',metavar='PATH',help='a wavefront obj file to load and display') argp.add_argument('--debug',action='store_true',help="don't catch exceptions from errors") args = argp.parse_args() if args.debug: sys.excepthook = sys.__excepthook__ ntracer = NTracer(args.dimension) if args.file: if ntracer.dimension != 3: sys.exit('a file can only be displayed with a dimensionality of 3') try: triangles = wavefront_obj.load_obj(args.file) except Exception as e: if args.debug: raise sys.exit('could not load file: ' + str(e)) scene = ntracer.build_composite_scene(triangles) else: scene = ntracer.BoxScene()
def star_tesselation(self): t = getattr(self,'_star_tesselation',None) if t is None: co_nt = NTracer(self.dimension) lines = [] planes = [Plane(co_nt,co_nt.Vector(islice(part.position,co_nt.dimension))) for part in self.parts] las = self.line_apothem_square() for pgroup in combinations(planes,co_nt.dimension-1): try: line = plane_line_intersection(co_nt,pgroup) except ValueError: pass else: if line: for lineb in lines: if almost_equal(line.p0,lineb.p0) and almost_equal(line.v,lineb.v): lineb.planes |= line.planes break else: outer_dist = line.dist_square(co_nt.Vector()) - las if outer_dist < 0.1: line.outer = outer_dist > -0.1 lines.append(line) pmap = {} for line in lines: pmap[line] = {} graph = FuzzyGraph() maxr = self.circumradius_square() + 0.1 for l1,l2 in combinations(lines,2): inter = line_intersection(co_nt,l1,l2) if inter and inter[0].square() < maxr: n = graph.add(inter[0],l1.planes | l2.planes,l1.outer or l2.outer) pmap[l1][n] = inter[1] pmap[l2][n] = inter[2] for line,poss in list(pmap.items()): if len(poss) == 0: continue if len(poss) == 1: graph.remove(poss[0]) continue poss = sorted(list(poss.items()),key=(lambda x: x[1])) if line.outer: for i in range(len(poss)-1): join(poss[i][0],poss[i+1][0]) elif len(poss) == 2: join(poss[0][0],poss[1][0]) elif len(poss) > 3: for i in range(2,len(poss)-2): graph.remove(poss[i][0]) join(poss[0][0],poss[1][0]) join(poss[-1][0],poss[-2][0]) t = [] self._star_tesselation = t for n in islice(graph.nodes,0,len(graph.nodes)-co_nt.dimension): for cycle in n.find_cycles(co_nt.dimension): t.append([nt.Vector(tuple(x.pos) + (0,) * (nt.dimension-co_nt.dimension)) for x in cycle] + [nt.Vector()]) n.detach() return t
parser.add_argument('-t','--type',metavar='TYPE',default='h264', help='Specifies output type when --output is used. If TYPE is "png", the '+ 'output is a series of PNG images. For any other value, it is used '+ 'as the video codec for ffmpeg.') parser.add_argument('-f','--frames',metavar='F',type=positive_int,default=160,help='when creating an animation or benchmarking, the number of frames to render') parser.add_argument('-s','--screen',metavar='WIDTHxHEIGHT',type=screen_size,default=(800,600),help='screen size') parser.add_argument('-a','--fov',metavar='FOV',type=fov_type,default=0.8,help='field of vision in degrees') parser.add_argument('-d','--cam-dist',metavar='DIST',type=float,default=4, help='How far the view-port is from the center of the polytope. The '+ 'value is a multiple of the outer raidius of the polytope.') parser.add_argument('--benchmark',action='store_true',help='measure the speed of rendering the scene') args = parser.parse_args() material = Material((1,0.5,0.5)) nt = NTracer(max(len(args.schlafli)+1,3)) def higher_dihedral_supplement(schlafli,ds): a = math.pi*schlafli.denominator/schlafli.numerator return 2*math.asin(math.sin(math.acos(1/(math.tan(ds/2)*math.tan(a))))*math.sin(a)) def almost_equal(a,b,threshold=0.1): return (a-b).absolute() < threshold def radial_vector(angle): return nt.Vector.axis(0,math.sin(angle)) + nt.Vector.axis(1,math.cos(angle)) class Instance: def __init__(self,shape,position,orientation=nt.Matrix.identity()):
parser.add_argument("-a", "--fov", metavar="FOV", type=fov_type, default=0.8, help="field of vision in degrees") parser.add_argument( "-d", "--cam-dist", metavar="DIST", type=float, default=4, help="How far the view-port is from the center of the polytope. The " + "value is a multiple of the outer raidius of the polytope.", ) parser.add_argument("--benchmark", action="store_true", help="measure the speed of rendering the scene") args = parser.parse_args() material = Material((1, 0.5, 0.5)) nt = NTracer(max(len(args.schlafli) + 1, 3)) def higher_dihedral_supplement(schlafli, ds): a = math.pi * schlafli.denominator / schlafli.numerator return 2 * math.asin(math.sin(math.acos(1 / (math.tan(ds / 2) * math.tan(a)))) * math.sin(a)) def almost_equal(a, b, threshold=0.1): return (a - b).absolute() < threshold def radial_vector(angle): return nt.Vector.axis(0, math.sin(angle)) + nt.Vector.axis(1, math.cos(angle))