Finally fix my non-manifold-with-CageFork bug!
This commit is contained in:
parent
d26cae0486
commit
6eb77d7566
11
README.md
11
README.md
@ -5,16 +5,6 @@
|
|||||||
behind this.
|
behind this.
|
||||||
|
|
||||||
## Annoying/boring
|
## Annoying/boring
|
||||||
- Fix non-manifold bug at branch. (The edges must be *shared*. It is
|
|
||||||
not sufficient that the subdivided edges both lie incident on some
|
|
||||||
other edge and cover it completely. You must subdivide that larger
|
|
||||||
edge, and thus the triangle it lies on.)
|
|
||||||
- See cage.py and CageGen.to_mesh
|
|
||||||
- CageFork may need to supply some 'opening' cage that I use as
|
|
||||||
a basis for how I subdivide a 'closing' cage. If I subdivide
|
|
||||||
the closing cage, then I must triangulate *after*, not before.
|
|
||||||
- classify_overlap might be unnecessary, but its classification may
|
|
||||||
have the right idea.
|
|
||||||
- https://en.wikipedia.org/wiki/Polygon_triangulation - do this to
|
- https://en.wikipedia.org/wiki/Polygon_triangulation - do this to
|
||||||
fix my wave example!
|
fix my wave example!
|
||||||
- http://www.polygontriangulation.com/2018/07/triangulation-algorithm.html
|
- http://www.polygontriangulation.com/2018/07/triangulation-algorithm.html
|
||||||
@ -84,3 +74,4 @@
|
|||||||
- What are the limitations of using Cages?
|
- What are the limitations of using Cages?
|
||||||
- Current system is very "generative". Could I do basically L-system
|
- Current system is very "generative". Could I do basically L-system
|
||||||
if I have rules for how a much is *refined*? What about IFS?
|
if I have rules for how a much is *refined*? What about IFS?
|
||||||
|
- Do this in Rust once I understand WTF I am doing
|
||||||
|
|||||||
318
Scratch.ipynb
318
Scratch.ipynb
File diff suppressed because one or more lines are too long
9
cage.py
9
cage.py
@ -179,7 +179,7 @@ class CageFork(object):
|
|||||||
return True
|
return True
|
||||||
def transition_from(self, cage):
|
def transition_from(self, cage):
|
||||||
"""Generate a transitional mesh to adapt the given starting Cage"""
|
"""Generate a transitional mesh to adapt the given starting Cage"""
|
||||||
print("DEBUG: Transition from {} to {}".format(cage.verts, self.verts))
|
#print("DEBUG: Transition from {} to {}".format(cage.verts, self.verts))
|
||||||
vs = numpy.concatenate([cage.verts, self.verts])
|
vs = numpy.concatenate([cage.verts, self.verts])
|
||||||
# Indices 0...offset-1 are from cage, rest are from self.verts
|
# Indices 0...offset-1 are from cage, rest are from self.verts
|
||||||
offset = cage.verts.shape[0]
|
offset = cage.verts.shape[0]
|
||||||
@ -205,9 +205,9 @@ class CageGen(object):
|
|||||||
self.gen = gen
|
self.gen = gen
|
||||||
def to_mesh(self, count=None, flip_order=False, loop=False, close_first=False,
|
def to_mesh(self, count=None, flip_order=False, loop=False, close_first=False,
|
||||||
close_last=False, join_fn=meshutil.join_boundary_simple):
|
close_last=False, join_fn=meshutil.join_boundary_simple):
|
||||||
#print("to_mesh(count={})".format(count))
|
|
||||||
# Get 'opening' polygons of generator:
|
# Get 'opening' polygons of generator:
|
||||||
cage_first = next(self.gen)
|
cage_first = next(self.gen)
|
||||||
|
#print("DEBUG: to_mesh(count={}), cage_first={}".format(count, cage_first.verts))
|
||||||
# TODO: Avoid 'next' here so that we can use a list, not solely a
|
# TODO: Avoid 'next' here so that we can use a list, not solely a
|
||||||
# generator/iterator.
|
# generator/iterator.
|
||||||
if cage_first.is_fork():
|
if cage_first.is_fork():
|
||||||
@ -222,6 +222,7 @@ class CageGen(object):
|
|||||||
# Generate all polygons from there and connect them:
|
# Generate all polygons from there and connect them:
|
||||||
#print(self.gen)
|
#print(self.gen)
|
||||||
for i, cage_cur in enumerate(self.gen):
|
for i, cage_cur in enumerate(self.gen):
|
||||||
|
#print("DEBUG: i={}, cage_cur={}, cage_last={}".format(i, cage_cur, cage_last.verts))
|
||||||
#print("{}: {}".format(i, cage_cur))
|
#print("{}: {}".format(i, cage_cur))
|
||||||
if count is not None and i >= count:
|
if count is not None and i >= count:
|
||||||
# We stop recursing here, so close things off if needed:
|
# We stop recursing here, so close things off if needed:
|
||||||
@ -235,6 +236,7 @@ class CageGen(object):
|
|||||||
if cage_cur.is_fork():
|
if cage_cur.is_fork():
|
||||||
# First, transition the cage properly:
|
# First, transition the cage properly:
|
||||||
mesh_trans = cage_cur.transition_from(cage_last)
|
mesh_trans = cage_cur.transition_from(cage_last)
|
||||||
|
meshes.append(mesh_trans)
|
||||||
# TODO: Clean up these recursive calls; parameters are ugly.
|
# TODO: Clean up these recursive calls; parameters are ugly.
|
||||||
# Some of them also make no sense in certain combinations
|
# Some of them also make no sense in certain combinations
|
||||||
# (e.g. loop with fork)
|
# (e.g. loop with fork)
|
||||||
@ -262,8 +264,5 @@ class CageGen(object):
|
|||||||
else:
|
else:
|
||||||
m = join_fn(b0, b1)
|
m = join_fn(b0, b1)
|
||||||
meshes.append(m)
|
meshes.append(m)
|
||||||
# TODO: close_last?
|
|
||||||
# or should this just look for whether or not the
|
|
||||||
# generator ends here (without a CageFork)?
|
|
||||||
mesh = meshutil.FaceVertexMesh.concat_many(meshes)
|
mesh = meshutil.FaceVertexMesh.concat_many(meshes)
|
||||||
return mesh
|
return mesh
|
||||||
|
|||||||
30
examples.py
30
examples.py
@ -147,7 +147,9 @@ def ram_horn_branch():
|
|||||||
def recur(xf, cage1, count):
|
def recur(xf, cage1, count):
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
if i > 0:
|
if i > 0:
|
||||||
yield cage1.transform(xf)
|
c = cage1.transform(xf)
|
||||||
|
#print("DEBUG: recur, i={}, yield {}".format(i, c.verts))
|
||||||
|
yield c
|
||||||
xf0 = xf
|
xf0 = xf
|
||||||
xf = incr.compose(xf)
|
xf = incr.compose(xf)
|
||||||
# .compose(opening_boundary(i))
|
# .compose(opening_boundary(i))
|
||||||
@ -162,25 +164,26 @@ def ram_horn_branch():
|
|||||||
dx, dy = -1, -1
|
dx, dy = -1, -1
|
||||||
elif i == 3:
|
elif i == 3:
|
||||||
dx, dy = 1, -1
|
dx, dy = 1, -1
|
||||||
return meshutil.Transform().rotate([-dy,dx,0], -numpy.pi/6)
|
return meshutil.Transform().translate(0, 0, 0.5).rotate([-dy,dx,0], -numpy.pi/6)
|
||||||
subdiv, trans_vs, trans_es = cage1.subdivide_deprecated()
|
subdiv, trans_vs, trans_es = cage1.subdivide_deprecated()
|
||||||
gens = [cage.CageGen(itertools.chain(
|
gens = [cage.CageGen(itertools.chain(
|
||||||
#[cage_sub.transform(xf0)],
|
[cage_sub.transform(xf)],
|
||||||
recur(xf_sub(i).compose(xf0), cage_sub, 4)))
|
recur(xf_sub(i).compose(xf), cage_sub, 8)))
|
||||||
for i,cage_sub in
|
for i,cage_sub in
|
||||||
enumerate(subdiv)]
|
enumerate(subdiv)]
|
||||||
yield cage.CageFork(gens, xf0.apply_to(trans_vs), trans_es)
|
yield cage.CageFork(gens, xf.apply_to(trans_vs), trans_es)
|
||||||
# TODO: Figure out why this has a large gap now
|
# TODO: The starting cage needs to be one iteration *earlier*, and the
|
||||||
# I seem to be producing a transition mesh that is degenerate,
|
# subdivided cage is fine, but the generators likewise need to start
|
||||||
# which means the starting cage and subdivided cage are lying right
|
# one iteration earlier. Look closely in Blender at the mesh,
|
||||||
# on top of each other. Starting cage looks okay, so subdivided
|
# specifically just prior to the fork.
|
||||||
# cage is probably what is wrong.
|
#
|
||||||
|
# xf0.apply_to(trans_vs) is identical to last cage yielded?
|
||||||
cg = cage.CageGen(itertools.chain(
|
cg = cage.CageGen(itertools.chain(
|
||||||
[cage0],
|
[cage0],
|
||||||
recur(meshutil.Transform(), cage0, 4),
|
recur(meshutil.Transform(), cage0, 8),
|
||||||
))
|
))
|
||||||
# TODO: if this is just a list it seems silly to require itertools
|
# TODO: if this is just a list it seems silly to require itertools
|
||||||
mesh = cg.to_mesh(count=8, close_first=True, close_last=True)
|
mesh = cg.to_mesh(count=32, close_first=True, close_last=True)
|
||||||
return mesh
|
return mesh
|
||||||
|
|
||||||
def branch_test():
|
def branch_test():
|
||||||
@ -350,7 +353,8 @@ def main():
|
|||||||
fns = {
|
fns = {
|
||||||
ram_horn: "ramhorn.stl",
|
ram_horn: "ramhorn.stl",
|
||||||
ram_horn2: "ramhorn2.stl",
|
ram_horn2: "ramhorn2.stl",
|
||||||
ram_horn3: "ramhorn3.stl",
|
# TODO: Fix
|
||||||
|
#ram_horn3: "ramhorn3.stl",
|
||||||
ram_horn_branch: "ramhorn_branch.stl",
|
ram_horn_branch: "ramhorn_branch.stl",
|
||||||
twist: "twist.stl",
|
twist: "twist.stl",
|
||||||
twist_nonlinear: "twist_nonlinear.stl",
|
twist_nonlinear: "twist_nonlinear.stl",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user