/* * l-system interpreters */ #include "config.h" #include "lsys.h" #include "interp.h" #include "interface.h" #include "attr.h" #include #include #include #ifndef M_PI # define M_PI 3.14159265358979323846 /* pi */ #endif bool interpreter::execute_child (const module &m, const lsys &l) t_err { hash_map::const_iterator i; const lsys *sys = &l; do { if ((i = sys->sub_lsys.find (m.str)) != sys->sub_lsys.end ()) { module_vec v = m.wrap (); if (i->second->eval (v)) { execute (v, *i->second); return true; } break; } sys = sys->parent; } while (sys); return false; } void simple_interpreter::execute(const module_vec &v, const lsys &l) t_err { depth--; string s; module m; for (module_pos i = v.begin (); i != v.end(); ++i) if (!depth || !execute_child (*i, l)) cout << *i << " "; depth++; } void simple_interpreter::operator ()(const module_vec &v, const lsys &l) t_err { if (maxdepth > 0) { depth = maxdepth + 1; execute (v, l); cout << endl; } } #define MK(m) point((m), cur.pos, cur.dir[2], cur.attr) turtle_interpreter::turtle_interpreter (gfx_int &interface, bool flat_world) t_no : iface (interface), flat(flat_world) { } void turtle_interpreter::rotate_tl (double phi) t_no { phi *= M_PI/180; double s = sin (phi), c = cos (phi); cur.dir = mat ( vec ( c, s, 0), vec (-s, c, 0), vec ( 0, 0, 1)) * cur.dir; } void turtle_interpreter::rotate_pd (double phi) t_no { if (flat) return; phi *= M_PI/180; double s = sin (phi), c = cos (phi); cur.dir = mat ( vec ( c, 0,-s), vec ( 0, 1, 0), vec ( s, 0, c)) * cur.dir; } void turtle_interpreter::rotate_rl (double phi) t_no { if (flat) return; phi *= M_PI/180; double s = sin (phi), c = cos (phi); cur.dir = mat ( vec ( 1, 0, 0), vec ( 0, c, s), vec ( 0,-s, c)) * cur.dir; } void turtle_interpreter::forward (double d) t_no { cur.pos = cur.pos + d * cur.dir[0]; } void turtle_interpreter::attrs_changed () t_err { delta = cur.attr("delta", 45); distance = cur.attr("distance", 10); } void turtle_interpreter::execute (const module_vec &v, const lsys &l) t_err { // cout << "interp " << v << endl; string s; double d; module m; const module_vec damnit; for (module_pos i = v.begin (); i != v.end (); ++i) { // cout << delta << "|" << distance << "> " << cur.pos << " " << cur.dir << " " << i->str << endl; if (i->is_func ("[")) { state_stack.push (cur); } else if (i->is_func ("]")) { cur = state_stack.top (), state_stack.pop (); attrs_changed (); } else if (i->is_func ("attr", s, m)) { if (m.is_expr) m = module (eval_expr (m, cur.attr)); cur.attr[s] = m; attrs_changed (); } else if (i->is_func ("+")) rotate_tl (delta); else if (i->is_func ("-")) rotate_tl (-delta); else if (i->is_func ("+", d)) rotate_tl (d); else if (i->is_func ("-", d)) rotate_tl (-d); else if (i->is_func ("&")) rotate_pd (delta); else if (i->is_func ("^")) rotate_pd (-delta); else if (i->is_func ("&", d)) rotate_pd (d); else if (i->is_func ("^", d)) rotate_pd (-d); else if (i->is_func ("\\")) rotate_rl (delta); else if (i->is_func ("/")) rotate_rl (-delta); else if (i->is_func ("\\", d)) rotate_rl (d); else if (i->is_func ("/", d)) rotate_rl (-d); else if (i->is_func ("|")) rotate_tl (180); else if (i->is_func ("f")) forward (distance); else if (i->is_func ("f", d)) forward (d); else if (i->is_func ("F")) { if (obj_stack.empty ()) { point o(MK(damnit)); forward (distance); iface.segment (o, MK(damnit)); } else { forward (distance); cur_obj.push_back (MK(damnit)); } } else if (i->is_func ("F", d)) { if (obj_stack.empty ()) { point o(MK(damnit)); forward (d); iface.segment (o, MK(damnit)); } else { forward (d); cur_obj.push_back (MK(damnit)); } } else if (i->is_func (".")) cur_obj.push_back (MK(*i)); else if (i->is_func ("{")) { obj_stack.push (cur_obj); cur_obj.erase (cur_obj.begin (), cur_obj.end ()); } else if (i->is_func ("}")) { iface.object (cur_obj); if (obj_stack.empty ()) throw error ("polygon stack underflow", *i); else { cur_obj = obj_stack.top (); obj_stack.pop (); } } else execute_child (*i, l); } } void turtle_interpreter::operator ()(const module_vec &v, const lsys &l) t_err { cur.pos = vec(0, 0, 0); cur.dir = mat (vec ( 0, 1, 0), vec ( 1, 0, 0), vec ( 0, 0, 1)); srand (1); // zero breaks certain libc versins cur.attr["delta"] = 45.0; cur.attr["distance"] = 10.0; attrs_changed (); iface.begin_fig (); execute (v, l); iface.end_fig (); }