Closure-ified my Twist example
This commit is contained in:
parent
02cfa49bd7
commit
f8f2d4ac31
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
|
- If my `closure_try2` branch seems to be working: start converting
|
||||||
|
other things and cleaning them up. Modify `twist` to have the
|
||||||
|
things I wrote this for in the first place!
|
||||||
- See `automata_scratch/examples.py` and implement some of the tougher
|
- See `automata_scratch/examples.py` and implement some of the tougher
|
||||||
examples.
|
examples.
|
||||||
- `spiral_nested_2` & `spiral_nested_3` (how to compose
|
- `spiral_nested_2` & `spiral_nested_3` (how to compose
|
||||||
@ -11,7 +14,7 @@
|
|||||||
|
|
||||||
## Important but less critical:
|
## Important but less critical:
|
||||||
|
|
||||||
- Elegance & succinctness:
|
- Elegance & succinctness (my recent closure work may help with this):
|
||||||
- Why must I repeat myself so much in these definitions?
|
- Why must I repeat myself so much in these definitions?
|
||||||
- The notation for transforms is really cumbersome. Some syntactic
|
- The notation for transforms is really cumbersome. Some syntactic
|
||||||
sugar might go far.
|
sugar might go far.
|
||||||
|
|||||||
154
src/examples.rs
154
src/examples.rs
@ -362,90 +362,38 @@ impl RamHorn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
struct Twist {
|
// Meant to be a copy of twist_from_gen from Python & automata_scratch
|
||||||
seed: Vec<Vertex>,
|
fn twist(f: f32, subdiv: usize) -> Rule {
|
||||||
seed_sub: Vec<Vertex>,
|
// TODO: Clean this code up. It was a very naive conversion from
|
||||||
dx0: f32,
|
// the non-closure version.
|
||||||
dy: f32,
|
let xf = geometry::Rotation3::from_axis_angle(&Vector3::x_axis(), -0.7).to_homogeneous();
|
||||||
ang: f32,
|
let seed = transform(&vec![
|
||||||
count: usize,
|
vertex(-0.5, 0.0, -0.5),
|
||||||
subdiv: usize,
|
vertex( 0.5, 0.0, -0.5),
|
||||||
}
|
vertex( 0.5, 0.0, 0.5),
|
||||||
|
vertex(-0.5, 0.0, 0.5),
|
||||||
|
], &xf);
|
||||||
|
let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
||||||
|
let dx0: f32 = 2.0;
|
||||||
|
let dy: f32 = 0.1/f;
|
||||||
|
let ang: f32 = 0.1/f;
|
||||||
|
let count: usize = 4;
|
||||||
|
|
||||||
impl Twist {
|
let n = seed_sub.len();
|
||||||
|
|
||||||
pub fn init(f: f32, subdiv: usize) -> Rule {
|
|
||||||
let xf = geometry::Rotation3::from_axis_angle(&Vector3::x_axis(), -0.7).to_homogeneous();
|
|
||||||
let seed = transform(&vec![
|
|
||||||
vertex(-0.5, 0.0, -0.5),
|
|
||||||
vertex( 0.5, 0.0, -0.5),
|
|
||||||
vertex( 0.5, 0.0, 0.5),
|
|
||||||
vertex(-0.5, 0.0, 0.5),
|
|
||||||
], &xf);
|
|
||||||
let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
|
||||||
let t = Twist {
|
|
||||||
dx0: 2.0,
|
|
||||||
dy: 0.1/f,
|
|
||||||
ang: 0.1/f,
|
|
||||||
count: 4,
|
|
||||||
seed: seed,
|
|
||||||
seed_sub: seed_sub,
|
|
||||||
subdiv: subdiv,
|
|
||||||
};
|
|
||||||
Rule { eval: Box::new(|| t.start()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Meant to be a copy of twist_from_gen from Python & automata_scratch
|
// Quarter-turn in radians:
|
||||||
pub fn start(&self) -> RuleEval {
|
let qtr = std::f32::consts::FRAC_PI_2;
|
||||||
|
let y = Vector3::y_axis();
|
||||||
|
|
||||||
let n = self.seed_sub.len();
|
let recur = move |self_: Rc<Rule>| -> RuleEval {
|
||||||
|
let incr = geometry::Translation3::new(-dx0, 0.0, 0.0).to_homogeneous() *
|
||||||
|
geometry::Rotation3::from_axis_angle(&y, ang).to_homogeneous() *
|
||||||
|
geometry::Translation3::new(dx0, dy, 0.0).to_homogeneous();
|
||||||
|
|
||||||
// Quarter-turn in radians:
|
let seed_orig = transform(&seed, &incr);
|
||||||
let qtr = std::f32::consts::FRAC_PI_2;
|
let seed_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
||||||
let y = &Vector3::y_axis();
|
|
||||||
let xform = |i| {
|
|
||||||
(geometry::Rotation3::from_axis_angle(y, qtr * (i as f32)).to_homogeneous() *
|
|
||||||
geometry::Translation3::new(self.dx0, 0.0, 0.0).to_homogeneous())
|
|
||||||
};
|
|
||||||
|
|
||||||
// First generate 'count' children, each one shifted/rotated
|
|
||||||
// differently:
|
|
||||||
let children: Vec<Child> = (0..self.count).map(|i| {
|
|
||||||
let xf = xform(i);
|
|
||||||
Child {
|
|
||||||
rule: Rule { eval: Box::new(|| self.recur()) },
|
|
||||||
xf: xf,
|
|
||||||
vmap: ((n+1)*i..(n+1)*(i+self.count)).collect(), // N.B.
|
|
||||||
// note n+1, not n. the +1 is for the centroid below
|
|
||||||
}
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
// Use byproducts of this to make 'count' copies of 'seed' with
|
|
||||||
// this same transform:
|
|
||||||
let meshes = children.iter().map(|child| {
|
|
||||||
let mut vs = transform(&self.seed_sub, &child.xf);
|
|
||||||
// and in the process, generate faces for these seeds:
|
|
||||||
let (centroid, f) = util::connect_convex(&vs, false);
|
|
||||||
vs.push(centroid);
|
|
||||||
OpenMesh { verts: vs, faces: f }
|
|
||||||
});
|
|
||||||
|
|
||||||
RuleEval {
|
|
||||||
geom: OpenMesh::append(meshes),
|
|
||||||
final_geom: prim::empty_mesh(),
|
|
||||||
children: children,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recur(&self) -> RuleEval {
|
|
||||||
let y = &Vector3::y_axis();
|
|
||||||
let incr = geometry::Translation3::new(-self.dx0, 0.0, 0.0).to_homogeneous() *
|
|
||||||
geometry::Rotation3::from_axis_angle(y, self.ang).to_homogeneous() *
|
|
||||||
geometry::Translation3::new(self.dx0, self.dy, 0.0).to_homogeneous();
|
|
||||||
|
|
||||||
let seed_orig = transform(&self.seed, &incr);
|
|
||||||
let seed_sub = util::subdivide_cycle(&seed_orig, self.subdiv);
|
|
||||||
let n = seed_sub.len();
|
let n = seed_sub.len();
|
||||||
|
|
||||||
let (vc, faces) = util::connect_convex(&seed_sub, true);
|
let (vc, faces) = util::connect_convex(&seed_sub, true);
|
||||||
@ -458,15 +406,52 @@ impl Twist {
|
|||||||
final_geom: OpenMesh { verts: vec![vc], faces },
|
final_geom: OpenMesh { verts: vec![vc], faces },
|
||||||
children: vec![
|
children: vec![
|
||||||
Child {
|
Child {
|
||||||
rule: Rule { eval: Box::new(move || self.recur()) },
|
rule: self_.clone(),
|
||||||
xf: incr,
|
xf: incr,
|
||||||
vmap: (0..n).collect(),
|
vmap: (0..n).collect(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let start = move |self_: Rc<Rule>| -> RuleEval {
|
||||||
|
|
||||||
|
let xform = |i| {
|
||||||
|
(geometry::Rotation3::from_axis_angle(&y, qtr * (i as f32)).to_homogeneous() *
|
||||||
|
geometry::Translation3::new(dx0, 0.0, 0.0).to_homogeneous())
|
||||||
|
};
|
||||||
|
|
||||||
|
// First generate 'count' children, each one shifted/rotated
|
||||||
|
// differently:
|
||||||
|
let children: Vec<Child> = (0..count).map(|i| {
|
||||||
|
let xf = xform(i);
|
||||||
|
Child {
|
||||||
|
rule: Rc::new(Rule { eval: Box::new(recur.clone()) }),
|
||||||
|
xf: xf,
|
||||||
|
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
||||||
|
// note n+1, not n. the +1 is for the centroid below
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
// Use byproducts of this to make 'count' copies of 'seed' with
|
||||||
|
// this same transform:
|
||||||
|
let meshes = children.iter().map(|child| {
|
||||||
|
let mut vs = transform(&seed_sub, &child.xf);
|
||||||
|
// and in the process, generate faces for these seeds:
|
||||||
|
let (centroid, f) = util::connect_convex(&vs, false);
|
||||||
|
vs.push(centroid);
|
||||||
|
OpenMesh { verts: vs, faces: f }
|
||||||
|
});
|
||||||
|
|
||||||
|
RuleEval {
|
||||||
|
geom: OpenMesh::append(meshes),
|
||||||
|
final_geom: prim::empty_mesh(),
|
||||||
|
children: children,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Rule { eval: Box::new(start) }
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
||||||
@ -533,9 +518,8 @@ pub fn main() {
|
|||||||
// let f = 20;
|
// let f = 20;
|
||||||
// run_test_iter(Twist::init(f as f32, 32), 100*f, "twist2");
|
// run_test_iter(Twist::init(f as f32, 32), 100*f, "twist2");
|
||||||
|
|
||||||
let rule = Rc::new(cube_thing());
|
run_test_iter(&Rc::new(cube_thing()), 3, "cube_thing3");
|
||||||
|
run_test_iter(&Rc::new(twist(1.0, 2)), 100, "twist");
|
||||||
run_test_iter(&rule, 3, "cube_thing3");
|
|
||||||
|
|
||||||
if false
|
if false
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,6 +14,8 @@ pub struct Rule {
|
|||||||
// no function call.
|
// no function call.
|
||||||
// TODO: Do I benefit with Rc<Rule> below so Rule can be shared?
|
// TODO: Do I benefit with Rc<Rule> below so Rule can be shared?
|
||||||
|
|
||||||
|
// TODO: Why *can't* I make this FnOnce?
|
||||||
|
|
||||||
// The above looks like it is going to require a lifetime parameter
|
// The above looks like it is going to require a lifetime parameter
|
||||||
// regardless, in which case I don't really need Box.
|
// regardless, in which case I don't really need Box.
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user