Triply-nested spiral! And more notes.

This commit is contained in:
Chris Hodapp 2019-10-11 20:53:45 +02:00
parent 10f6128579
commit ac022b3b9b
4 changed files with 140 additions and 58 deletions

View File

@ -1,8 +1,21 @@
To-do items, wanted features, bugs: # To-do items, wanted features, bugs:
## Cool
- Examples of branching. This will probably need recursion via functions - Examples of branching. This will probably need recursion via functions
(or an explicit stack some other way). (or an explicit stack some other way). If I simply
- I need to figure out winding order. It is consistent through seemingly split a boundary into sub-boundaries per the rules I already
have in my notes, then this still lets me split any way I want
to without having to worry about joining N boundaries instead
of 2, doesn't it?
- More complicated: Examples of *merging*. I'm not sure on the theory
behind this.
## Annoying
- I really need to standardize some of the behavior of fundamental
operations (with regard to things like sizes they generate). This
is behavior that, if it changes, will change a lot of things that I'm
trying to keep consistent so that my examples still work.
- Winding order. It is consistent through seemingly
everything, except for reflection and close_boundary_simple. everything, except for reflection and close_boundary_simple.
(When there are two parallel boundaries joined with something like (When there are two parallel boundaries joined with something like
join_boundary_simple, traversing these boundaries in their actual order join_boundary_simple, traversing these boundaries in their actual order
@ -10,17 +23,11 @@ To-do items, wanted features, bugs:
opposite winding order on each. Imagine a transparent clock: seen from the opposite winding order on each. Imagine a transparent clock: seen from the
front, it moves clockwise, but seen from the back, it moves front, it moves clockwise, but seen from the back, it moves
counter-clockwise.) counter-clockwise.)
- Make it easier to build up meshes a bit at a time?
- Factor out recursive/iterative stuff to be a bit more concise
- Embed this in Blender?
- File that bug that I've seen in trimesh/three.js - File that bug that I've seen in trimesh/three.js
(see trimesh_fail.ipynb) (see trimesh_fail.ipynb)
- Parametrize gen_twisted_boundary over boundaries and
do my nested spiral
- Why do I get the weird zig-zag pattern on the triangles, - Why do I get the weird zig-zag pattern on the triangles,
despite larger numbers of them? Is it something in how I despite larger numbers of them? Is it something in how I
twist the frames? twist the frames?
- How can I compute the *torsion* on a quad? I think it - How can I compute the *torsion* on a quad? I think it
comes down to this: torsion applied across the quad I'm comes down to this: torsion applied across the quad I'm
triangulating leading to neither diagonal being a triangulating leading to neither diagonal being a
@ -29,26 +36,33 @@ twist the frames?
quad to 4 triangles by adding the centroid) could be good quad to 4 triangles by adding the centroid) could be good
too. too.
- Facets/edges are just oriented the wrong way... - Facets/edges are just oriented the wrong way...
- I need an actual example of branching/forking. If I simply - Picking at random the diagonal on the quad to triangulate with
split a boundary into sub-boundaries per the rules I already
have in my notes, then this still lets me split any way I want
to without having to worry about joining N boundaries instead
of 2, doesn't it?
Other notes:
- Picking at random the diagonal on the quad to triangulate with
does seem to turn 'error' just to noise, and in its own way this does seem to turn 'error' just to noise, and in its own way this
is preferable. is preferable.
# Abstractions ## Abstractions
- Encode the notions of "generator which transforms an - Encode the notions of "generator which transforms an
existing list of boundaries", "generator which transforms existing list of boundaries", "generator which transforms
another generator" another generator"
- This has a lot of functions parametrized over a lot - This has a lot of functions parametrized over a lot
of functions. Need to work with this somehow. (e.g. should of functions. Need to work with this somehow. (e.g. should
it subdivide this boundary? should it merge opening/closing it subdivide this boundary? should it merge opening/closing
boundaries?) boundaries?)
- Work directly with lists of boundaries. The only thing - Work directly with lists of boundaries. The only thing
I ever do with them is apply transforms to all of them, or I ever do with them is apply transforms to all of them, or
join adjacent ones with corresponding elements. join adjacent ones with corresponding elements.
- Some generators produce boundaries that can be directly merged
and produce sensible geometry. Some generators produce
boundaries that are only usable when they are further
transformed (and would produce degenerate geometry). What sort
of nomenclature captures this?
- How can I capture the idea of a group of parameters which, if
they are all scaled in the correct way (some linearly, others
inversely perhaps), generated geometry that is more or less
identical except that it is higher-resolution?
## ????
- Embed this in Blender?

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import stl.mesh import itertools
import numpy import numpy
import stl.mesh
import trimesh import trimesh
import meshutil import meshutil
@ -171,7 +173,9 @@ def twist_from_gen():
b = meshutil.subdivide_boundary(b) b = meshutil.subdivide_boundary(b)
b = meshutil.subdivide_boundary(b) b = meshutil.subdivide_boundary(b)
bs = [b] bs = [b]
gen = meshgen.gen_inc_y(meshgen.gen_twisted_boundary(bs)) # since it needs a generator:
gen_inner = itertools.repeat(bs)
gen = meshgen.gen_inc_y(meshgen.gen_twisted_boundary(gen_inner))
mesh = meshgen.gen2mesh(gen, 100, True) mesh = meshgen.gen2mesh(gen, 100, True)
return mesh return mesh
@ -189,11 +193,54 @@ def twisty_torus(frames = 200, turns = 4, count = 4, rad = 4):
b = meshutil.subdivide_boundary(b) b = meshutil.subdivide_boundary(b)
b = meshutil.subdivide_boundary(b) b = meshutil.subdivide_boundary(b)
bs = [b] bs = [b]
# since it needs a generator:
gen_inner = itertools.repeat(bs)
# In order to make this line up properly: # In order to make this line up properly:
angle = numpy.pi * 2 * turns / frames angle = numpy.pi * 2 * turns / frames
gen = meshgen.gen_torus_xy(meshgen.gen_twisted_boundary(bs=bs, count=count, ang=angle), rad=rad, frames=frames) gen = meshgen.gen_torus_xy(meshgen.gen_twisted_boundary(gen=gen_inner, count=count, ang=angle), rad=rad, frames=frames)
return meshgen.gen2mesh(gen, 0, flip_order=True, loop=True) return meshgen.gen2mesh(gen, 0, flip_order=True, loop=True)
def spiral_nested_2():
# Slow.
b = numpy.array([
[0, 0, 0],
[1, 0, 0],
[1, 0, 1],
[0, 0, 1],
], dtype=numpy.float64) - [0.5, 0, 0.5]
b *= 0.3
b = meshutil.subdivide_boundary(b)
b = meshutil.subdivide_boundary(b)
bs = [b]
# since it needs a generator:
gen1 = itertools.repeat(bs)
gen2 = meshgen.gen_twisted_boundary(gen1, ang=-0.2, dx0=0.5)
gen3 = meshgen.gen_twisted_boundary(gen2, ang=0.05, dx0=1)
gen = meshgen.gen_inc_y(gen3, dy=0.1)
return meshgen.gen2mesh(
gen, count=250, flip_order=True, close_first=True, close_last=True)
def spiral_nested_3():
# Slower.
b = numpy.array([
[0, 0, 0],
[1, 0, 0],
[1, 0, 1],
[0, 0, 1],
], dtype=numpy.float64) - [0.5, 0, 0.5]
b *= 0.3
b = meshutil.subdivide_boundary(b)
b = meshutil.subdivide_boundary(b)
bs = [b]
# since it needs a generator:
gen1 = itertools.repeat(bs)
gen2 = meshgen.gen_twisted_boundary(gen1, ang=-0.2, dx0=0.5)
gen3 = meshgen.gen_twisted_boundary(gen2, ang=0.07, dx0=1)
gen4 = meshgen.gen_twisted_boundary(gen3, ang=-0.03, dx0=3)
gen = meshgen.gen_inc_y(gen4, dy=0.1)
return meshgen.gen2mesh(
gen, count=500, flip_order=True, close_first=True, close_last=True)
def main(): def main():
fns = { fns = {
ram_horn: "ramhorn.stl", ram_horn: "ramhorn.stl",
@ -202,6 +249,8 @@ def main():
twist_nonlinear: "twist_nonlinear.stl", twist_nonlinear: "twist_nonlinear.stl",
twist_from_gen: "twist_from_gen.stl", twist_from_gen: "twist_from_gen.stl",
twisty_torus: "twisty_torus.stl", twisty_torus: "twisty_torus.stl",
spiral_nested_2: "spiral_nested_2.stl",
spiral_nested_3: "spiral_nested_3.stl",
} }
for f in fns: for f in fns:
fname = fns[f] fname = fns[f]

View File

@ -1,35 +1,34 @@
import itertools
import meshutil import meshutil
import stl.mesh import stl.mesh
import numpy import numpy
import trimesh import trimesh
# Generate a frame with 'count' boundaries in the XZ plane. # Generate a frame with 'count' boundaries in the XZ plane.
# Each one rotates by 'ang' as it moves by 'dz'. # Each one rotates by 'ang' at each step.
# dx0 is center-point distance from each to the origin. # dx0 is center-point distance from each to the origin.
# #
# TODO: This needs to transform an existing generator, not just # This doesn't generate usable geometry on its own.
# a boundary! def gen_twisted_boundary(gen=None, count=4, dx0=2, ang=0.1):
def gen_twisted_boundary(bs=None, count=4, dx0=2, dz=0.2, ang=0.1): if gen is None:
if bs is None:
b = numpy.array([ b = numpy.array([
[0, 0, 0], [0, 0, 0],
[1, 0, 0], [1, 0, 0],
[1, 0, 1], [1, 0, 1],
[0, 0, 1], [0, 0, 1],
], dtype=numpy.float64) - [0.5, 0, 0.5] ], dtype=numpy.float64) - [0.5, 0, 0.5]
b = meshutil.subdivide_boundary(b) gen = itertools.repeat([b])
b = meshutil.subdivide_boundary(b)
b = meshutil.subdivide_boundary(b)
bs = [b]
# Generate 'seed' transformations: # Generate 'seed' transformations:
xfs = [meshutil.Transform().translate(dx0, 0, 0).rotate([0,1,0], numpy.pi * 2 * i / count) xfs = [meshutil.Transform().translate(dx0, 0, 0).rotate([0,1,0], numpy.pi * 2 * i / count)
for i in range(count)] for i in range(count)]
# (we'll increment the transforms in xfs as we go) # (we'll increment the transforms in xfs as we go)
while True: for bs in gen:
xfs_new = [] xfs_new = []
bs2 = []
for i, xf in enumerate(xfs): for i, xf in enumerate(xfs):
# Generate a boundary from running transform: # Generate a boundary from running transform:
bs2 = [xf.apply_to(b) for b in bs] bs2 += [xf.apply_to(b) for b in bs]
# Increment transform i: # Increment transform i:
xf2 = xf.rotate([0,1,0], ang) xf2 = xf.rotate([0,1,0], ang)
xfs_new.append(xf2) xfs_new.append(xf2)