def ram_horn2(): b0 = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ], dtype=numpy.float64) - [0.5, 0.5, 0] xf0_to_1 = meshutil.Transform().translate(0, 0, 1) b1 = xf0_to_1.apply_to(b0) meshes = [] meshes.append(meshutil.join_boundary_simple(b0, b1)) meshes.append(meshutil.close_boundary_simple(b0)) for i in range(4): # Opening boundary: xf = meshutil.Transform() \ .translate(0,0,-1) \ .scale(0.5) \ .translate(0.25,0.25,1) \ .rotate([0,0,1], i*numpy.pi/2) gen = ram_horn_gen(b1, xf) mesh = meshgen.gen2mesh(gen, count=128, close_last=True) meshes.append(mesh) mesh = meshutil.FaceVertexMesh.concat_many(meshes) return mesh
def twist_nonlinear(dx0=2, dz=0.2, count=3, scale=0.99, layers=100): # This can be a function rather than a constant: angs = numpy.power(numpy.linspace(0.4, 2.0, layers), 2.0) / 10.0 ang_fn = lambda i: angs[i] # (could it also be a function of space rather than which layer?) b = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ], dtype=numpy.float64) - [0.5, 0.5, 0] meshes = [] for i in range(count): xf = meshutil.Transform() \ .translate(dx0, 0, 0) \ .rotate([0,0,1], numpy.pi * 2 * i / count) b0 = xf.apply_to(b) meshes.append(meshutil.close_boundary_simple(b0)) for layer in range(layers): b_sub0 = xf.apply_to(b) ang = ang_fn(layer) incr = meshutil.Transform() \ .rotate([0,0,1], ang) \ .translate(0,0,dz) \ .scale(scale) b_sub1 = xf.compose(incr).apply_to(b) m = meshutil.join_boundary_simple(b_sub0, b_sub1) meshes.append(m) xf = xf.compose(incr) # Close final boundary: meshes.append(meshutil.close_boundary_simple(b_sub1[::-1, :])) mesh = meshutil.FaceVertexMesh.concat_many(meshes) return mesh
def twist(ang=0.1, dz=0.2, dx0=2, count=4, scale=0.98): b = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ], dtype=numpy.float64) - [0.5, 0.5, 0] meshes = [] for i in range(count): xf = meshutil.Transform() \ .translate(dx0, 0, 0) \ .rotate([0,0,1], numpy.pi * 2 * i / count) b0 = xf.apply_to(b) meshes.append(meshutil.close_boundary_simple(b0)) for layer in range(256): b_sub0 = xf.apply_to(b) incr = meshutil.Transform() \ .rotate([0,0,1], ang) \ .translate(0,0,dz) \ .scale(scale) b_sub1 = xf.compose(incr).apply_to(b) m = meshutil.join_boundary_simple(b_sub0, b_sub1) meshes.append(m) xf = xf.compose(incr) # Close final boundary: meshes.append(meshutil.close_boundary_simple(b_sub1[::-1, :])) mesh = meshutil.FaceVertexMesh.concat_many(meshes) return mesh
def xf_sub(i): # (dx,dy) should be normalized, but I reused from something else dx = 1 if i == 0 or i == 1 else -1 dy = 1 if i == 0 or i == 3 else -1 return meshutil.Transform().translate(0, 0, 0.5).rotate([-dy, dx, 0], -numpy.pi / 6)
def ram_horn_branch(): center = meshutil.Transform().translate(-0.5, -0.5, 0) cage0 = cage.Cage.from_arrays([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ]).transform(center) incr = meshutil.Transform() \ .scale(0.9) \ .rotate([-1,0,1], 0.3) \ .translate(0,0,0.8) def recur(xf, cage1, count): for i in range(count): if i > 0: c = cage1.transform(xf) yield c xf0 = xf xf = incr.compose(xf) def xf_sub(i): # (dx,dy) should be normalized, but I reused from something else dx = 1 if i == 0 or i == 1 else -1 dy = 1 if i == 0 or i == 3 else -1 return meshutil.Transform().translate(0, 0, 0.5).rotate([-dy, dx, 0], -numpy.pi / 6) subdiv, trans_vs, trans_es = cage1.subdivide_deprecated() gens = [ cage.CageGen( itertools.chain([cage_sub.transform(xf)], recur(xf_sub(i).compose(xf), cage_sub, 8))) for i, cage_sub in enumerate(subdiv) ] yield cage.CageFork(gens, xf.apply_to(trans_vs), trans_es) cg = cage.CageGen( itertools.chain( [cage0], recur(meshutil.Transform(), cage0, 8), )) # TODO: if this is just a list it seems silly to require itertools mesh = cg.to_mesh(count=32, close_first=True, close_last=True) return mesh
def ram_horn(): b0 = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ], dtype=numpy.float64) - [0.5, 0.5, 0] xf0_to_1 = meshutil.Transform().translate(0, 0, 1) b1 = xf0_to_1.apply_to(b0) meshes = [] meshes.append(meshutil.join_boundary_simple(b0, b1)) meshes.append(meshutil.close_boundary_simple(b0)) for i in range(4): # Opening boundary: b = b1 xf = meshutil.Transform() \ .translate(0,0,-1) \ .scale(0.5) \ .translate(0.25,0.25,1) \ .rotate([0,0,1], i*numpy.pi/2) for layer in range(128): b_sub0 = xf.apply_to(b) incr = meshutil.Transform() \ .scale(0.9) \ .rotate([-1,0,1], 0.3) \ .translate(0,0,0.8) b_sub1 = incr.compose(xf).apply_to(b) m = meshutil.join_boundary_simple(b_sub0, b_sub1) meshes.append(m) xf = incr.compose(xf) # Close final boundary: meshes.append(meshutil.close_boundary_simple(b_sub1[::-1, :])) # ::-1 is to reverse the boundary's order to fix winding order. # Not sure of the "right" way to fix winding order here. # The boundary vertices go in an identical order... it's just # that clockwise/counter-clockwise flip. # I keep confusing the 'incremental' transform with the # transform to get b_open in the first place # I don't need to subdivide *geometry*. # I need to subdivide *space* and then put geometry in it. mesh = meshutil.FaceVertexMesh.concat_many(meshes) return mesh
def ram_horn_gen(b, xf): while True: b1 = xf.apply_to(b) yield [b1] incr = meshutil.Transform() \ .scale(0.9) \ .rotate([-1,0,1], 0.3) \ .translate(0,0,0.8) xf = incr.compose(xf)
def gen_torus_xy(gen, rad=2, frames=100): ang = numpy.pi*2 / frames xf = meshutil.Transform().translate(rad, 0, 0) for i,bs in enumerate(gen): if i >= frames: break bs2 = [xf.apply_to(b) for b in bs] yield bs2 xf = xf.rotate([0,0,1], ang)
def dream_pendant(): center = meshutil.Transform().translate(-0.5, -0.5, 0) cage0 = cage.Cage.from_arrays([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ]).transform(center) incr = meshutil.Transform() \ .scale(0.95, 1.0, 0.95) \ .rotate([0,1,0], 0.2) \ .translate(0,0,0.9) def recur(xf, cage1, count): for i in range(count): if i > 0: c = cage1.transform(xf) yield c xf0 = xf xf = incr.compose(xf) def xf_rot(a): return meshutil.Transform().rotate([0, 1, 0], a) subdiv, trans_vs, trans_es = cage1.subdivide_x_deprecated() gens = [ cage.CageGen( itertools.chain([cage_sub.transform(xf)], recur(xf_rot(ang).compose(xf), cage_sub, 5))) for cage_sub, ang in zip(subdiv, [-0.2, 0.7]) ] yield cage.CageFork(gens, xf.apply_to(trans_vs), trans_es) cg = cage.CageGen( itertools.chain( [cage0], recur(meshutil.Transform(), cage0, 3), )) # TODO: if this is just a list it seems silly to require itertools mesh1 = cg.to_mesh(count=32, close_first=False, close_last=True) mesh2 = mesh1.transform(meshutil.Transform().rotate([0, 1, 0], math.pi)) return meshutil.FaceVertexMesh.concat_many([mesh1, mesh2])
def branch_test(): b0 = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ], dtype=numpy.float64) - [0.5, 0.5, 0] parts = [ meshutil.Transform().scale(0.5).translate(dx, dy, 1) for dx in (-0.25, +0.25) for dy in (-0.25, +0.25) ] xf = meshutil.Transform().translate(0, 0, 0.1).scale(0.95) def gen(): b = b0 for i in range(10): b = xf.apply_to(b) yield [b] return meshgen.gen2mesh(gen(), close_first=True, close_last=True)
def ram_horn3(): center = meshutil.Transform().translate(-0.5, -0.5, 0) cage0 = cage.Cage.from_arrays([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], ]).transform(center) xf0_to_1 = meshutil.Transform().translate(0, 0, 1) cage1 = cage0.transform(xf0_to_1) opening_boundary = lambda i: meshutil.Transform() \ .translate(0,0,-1) \ .scale(0.5) \ .translate(0.25,0.25,1) \ .rotate([0,0,1], i*numpy.pi/2) incr = meshutil.Transform() \ .scale(0.9) \ .rotate([-1,0,1], 0.3) \ .translate(0,0,0.8) def recur(xf): while True: cage2 = cage1.transform(xf) yield cage2 xf = incr.compose(xf) # TODO: I think there is a way to express 'recur' in the form of # itertools.accumulate, and it might be clearer. This function is # just iteratively re-composing 'incr' into a seed transformation, # and applying this transformation (at every stage) to the same # mesh. gens = [cage.CageGen(recur(opening_boundary(i))) for i in range(4)] cg = cage.CageGen(itertools.chain([cage0, cage1, cage.CageFork(gens)])) # TODO: if this is just a list it seems silly to require itertools mesh = cg.to_mesh(count=128, close_first=True, close_last=True) return mesh
def gen_twisted_boundary(gen=None, count=4, dx0=2, ang=0.1): if gen is None: b = numpy.array([ [0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1], ], dtype=numpy.float64) - [0.5, 0, 0.5] gen = itertools.repeat([b]) # Generate 'seed' transformations: xfs = [meshutil.Transform().translate(dx0, 0, 0).rotate([0,1,0], numpy.pi * 2 * i / count) for i in range(count)] # (we'll increment the transforms in xfs as we go) for bs in gen: xfs_new = [] bs2 = [] for i, xf in enumerate(xfs): # Generate a boundary from running transform: bs2 += [xf.apply_to(b) for b in bs] # Increment transform i: xf2 = xf.rotate([0,1,0], ang) xfs_new.append(xf2) xfs = xfs_new yield bs2
def xf_rot(a): return meshutil.Transform().rotate([0, 1, 0], a)
def gen_inc_y(gen, dy=0.1): xf = meshutil.Transform() for bs in gen: bs2 = [xf.apply_to(b) for b in bs] yield bs2 xf = xf.translate(0, dy, 0)