Department of Computer Science | Institute of Theoretical Computer Science | CADMO

Theory of Combinatorial Algorithms

Prof. Emo Welzl and Prof. Bernd Gärtner

// ----------------------------------------------------------------- // file: turtle_ps.C // Version: $Revision: 1.5 $ from $Date: 1998/12/03 17:33:32 $ // ----------------------------------------------------------------- // provides a simple function-based turtle-graphic interface #include #include #include #include #include #include #include #include #include #include namespace IFM_NAMESPACE { const int coordwidth = 512; const int borderwidth = 40; // types for arithmetic stuff: typedef int INT; typedef double FT; struct TurtlePoint { FT x, y; TurtlePoint( FT xx, FT yy) : x( xx), y ( yy) {} }; struct Turtle { // turtle commands static const int forward = 0; static const int left = 1; static const int right = 2; // defines the turtle commands: struct Command; // default con- and destructor: Turtle(); ~Turtle(); // execute a command: void operator()( int c, int steps = 1); // return turtle coordinates: FT x() const; FT y() const; FT xmax() const; FT xmin() const; FT ymax() const; FT ymin() const; private: INT Turtle::round( FT r); FT Turtle::map_x( FT x); FT Turtle::map_y( FT y); bool pen; bool used; FT _x, _y, _phi, _xmin, _xmax, _ymin, _ymax, _xcw, _ycw; // to store the coordinates after any forward cmd: typedef std::deque< TurtlePoint > Cont; Cont positions; // draw function: void draw(); }; // member functions of class Turtle Turtle::Turtle() : pen( false), used( false), _x( 0), _y( 0), _phi( 0), _xmin( 0), _xmax( 0), _ymin( 0), _ymax( 0) { positions.push_back( TurtlePoint( 0, 0)); } INT Turtle::round( FT r) { if ( r < floor( r) + 0.5) return INT( floor( r)); else return INT( ceil( r)); } FT Turtle::map_x( FT x) { assert( x >= _xmin && x <= _xmax); return borderwidth + (_xmax == _xmin ? 0 : round( (x - _xmin) / (_xmax - _xmin) * _xcw)); } FT Turtle::map_y( FT y) { assert( y >= _ymin && y <= _ymax); return borderwidth + _ycw - (_ymax == _ymin ? 0 : round( (y - _ymin) / (_ymax - _ymin) * _ycw)); } void Turtle::draw() { std::cout << "%!PS-Adobe-2.0\n" << "%%Creator: turtle_ps / Michael Hoffmann\n" << "%%Title: Turtle Graphics\n" << "%%Pages: 1\n" << "%%PageOrder: Ascend\n" << "%%BoundingBox: 0 0 " << round(_xcw + 2 * borderwidth) << " " << round(_ycw + 2 * borderwidth) << "\n" << "%%EndComments\n"; Cont::iterator i = positions.begin(); TurtlePoint p = *i; while ( ++i != positions.end()) { std::cout << round( map_x( p.x)) << " " << round( map_y( p.y)) << " moveto " << round( map_x( (*i).x)) << " " << round( map_y( (*i).y)) << " lineto stroke\n"; p = *i; } std::cout << "showpage\n%% EOF" << std::endl; } Turtle::~Turtle() { if ( used) { // compute coordinate width: if ( xmax() - xmin() > ymax() - ymin()) { _xcw = coordwidth; if ( ymax() == ymin()) _ycw = 0; else _ycw = coordwidth * (ymax() - ymin()) / (xmax() - xmin()); } else { if ( ymax() == ymin()) { _ycw = 0; _xcw = 0; } else { _ycw = coordwidth; if ( xmax() == xmin()) _xcw = 0; else _xcw = coordwidth * (xmax() - xmin()) / (ymax() - ymin()); } } // draw picture: std::cerr << "----------------------------------------------------\n" << "One moment, please ..." << std::endl; draw(); // Wait for mouse-click/handle expose events: std::cerr << "----------------------------------------------------\n" << "Drawing complete.\n" << "----------------------------------------------------" << std::endl; } } void Turtle::operator()( int c, int steps) { used = true; switch( c) { case forward: _x += steps * cos( _phi / 180 * M_PI); _y += steps * sin( _phi / 180 * M_PI); _xmin = std::min( _xmin, _x); _xmax = std::max( _xmax, _x); _ymin = std::min( _ymin, _y); _ymax = std::max( _ymax, _y); positions.push_back( TurtlePoint( _x, _y)); break; case right: _phi += steps; while ( _phi > 360) _phi -= 360; break; case left: _phi -= steps; while ( _phi < 0) _phi += 360; break; } } // return turtle coordinates: FT Turtle::x() const { return _x; } FT Turtle::y() const { return _y; } FT Turtle::xmax() const { return _xmax; } FT Turtle::xmin() const { return _xmin; } FT Turtle::ymax() const { return _ymax; } FT Turtle::ymin() const { return _ymin; } // static stuff for simple function interface: Turtle the_turtle; void forward(unsigned int n_steps) // POST: turtle has moved n_steps steps in its current direction. { the_turtle( Turtle::forward, n_steps); } void left(int deg) // POST: turtle has turned left by deg degrees. { the_turtle( Turtle::left, deg); } void right(int deg) // POST: turtle has turned right by deg degrees. { the_turtle( Turtle::right, deg); } } // namespace IFM_NAMESPACE // EOF