PH Logo
Logo intepreter modeled after UCB Logo.
/Users/paul/Documents/phlogo/core/GraphicVerbs.cpp
00001 /*
00002  *  GraphicVerbs.cpp
00003  *
00004  *  Author: Paul Hamilton
00005  *      Date: 7 Aug 2011
00006  *
00007  */
00008 #include "Verbs.h"
00009         
00010 #include "Interpreter.h"
00011 #include "Thing.h"
00012 #include "Exceptions.h"
00013 #include "World.h"
00014 #include "Turtle.h"
00015 
00016 //#include <boost/lexical_cast.hpp>
00017 #include <math.h>
00018 
00019 using namespace std;
00020 using namespace boost;
00021 
00022 #define PI 3.14159265
00023 
00024 namespace phlogo {
00025 
00026 // from ArithmeticVerbs
00027 double degToRad(double deg);
00028     
00029 void Verbs::fd(TokenStream *ts) {
00030     
00031     Turtle *t = _world->getTurtle();
00032         long amount = getLong(ts);
00033     
00034     double h = t->getHeading();
00035     double x2 = t->getX() + ((double)amount * ::sin(h));
00036     double y2 = t->getY() - ((double)amount * ::sin((PI/2.0)-h));
00037     
00038     if (t->getPendown()) {
00039         t->lineTo(x2, y2);
00040         t->stroke();
00041     }
00042     else {
00043         t->moveTo(x2, y2);       
00044     }
00045     t->setXY(x2, y2);    
00046     
00047 }
00048     
00049 void Verbs::bk(TokenStream *ts) {
00050         
00051     Turtle *t = _world->getTurtle();
00052         long amount = getLong(ts);
00053     
00054     double h = t->getHeading();
00055     double x2 = t->getX() - ((double)amount * ::sin(h));
00056     double y2 = t->getY() + ((double)amount * ::sin((PI/2.0)-h));
00057     
00058     if (t->getPendown()) {
00059         t->lineTo(x2, y2);
00060         t->stroke();
00061     }
00062     else {
00063         t->moveTo(x2, y2);       
00064     }
00065 
00066     t->setXY(x2, y2);    
00067     
00068 }
00069     
00070 void Verbs::lt(TokenStream *ts) {
00071     
00072     Turtle *t = _world->getTurtle();
00073         long amount = getLong(ts);
00074     double heading = t->getHeading();
00075     heading -= degToRad(amount);
00076     if (heading < 0)
00077         heading = (PI*2.0) + heading;
00078     t->setHeading(heading);
00079     
00080 }
00081 
00082 void Verbs::rt(TokenStream *ts) {
00083     
00084     Turtle *t = _world->getTurtle();
00085         long amount = getLong(ts);
00086     double heading = t->getHeading();
00087     heading += degToRad(amount);
00088     if (heading > (PI*2.0))
00089         heading -= PI*2.0;
00090     t->setHeading(heading);
00091                 
00092 }
00093     
00094 void Verbs::repeat(TokenStream *ts) {
00095     
00096         long count = getLong(ts);
00097     
00098         pThing thing;
00099         _itp->getNextThing(_world, ts, &thing);
00100         if (!thing->isList())
00101                 BOOST_THROW_EXCEPTION( no_list_in_thing_exception() );
00102         
00103     // we need to build a string back from the args, since that's what our evaluator operates on.
00104     string s = "";
00105     for (tListArray::const_iterator i=thing->getList().begin(); i != thing->getList().end(); i++) {
00106         if (!s.empty())
00107             s += " ";
00108         s += (*i)->getWord();
00109     }
00110     
00111     for (int i=0; i<count; i++)
00112         _itp->runTokenized(_world, s);
00113 }
00114     
00115 void Verbs::penup(TokenStream *ts) {
00116     
00117     _world->getTurtle()->setPendown(false);
00118 }
00119 
00120 void Verbs::pendown(TokenStream *ts) {
00121     
00122     _world->getTurtle()->setPendown(true);
00123 }
00124 
00125 void Verbs::setpos(TokenStream *ts) {
00126     
00127         pThing thing;
00128         _itp->getNextThing(_world, ts, &thing);
00129         if (!thing->isList())
00130                 BOOST_THROW_EXCEPTION( no_list_in_thing_exception() );
00131     
00132     _world->getTurtle()->setXY(thing->getList().get(0)->asLong(), thing->getList().get(1)->asLong());
00133     
00134 }
00135     
00136 void Verbs::setxy(TokenStream *ts) {
00137 
00138     _world->getTurtle()->setXY(getLong(ts), getLong(ts));
00139     
00140 }
00141     
00142 void Verbs::setx(TokenStream *ts) {
00143     
00144     _world->getTurtle()->setXY(getLong(ts), _world->getTurtle()->getY());
00145 
00146 }
00147 
00148 void Verbs::sety(TokenStream *ts) {
00149     
00150     _world->getTurtle()->setXY(_world->getTurtle()->getX(), getLong(ts));
00151     
00152 }
00153 
00154 void Verbs::setheading(TokenStream *ts) {
00155     
00156     _world->getTurtle()->setHeading(degToRad(getDouble(ts)));
00157     
00158 }
00159 
00160 void Verbs::home(TokenStream *ts) {
00161     
00162     _world->getTurtle()->home();
00163 
00164 }
00165 
00166 void Verbs::pos(TokenStream *ts) {
00167     
00168     pThing t(new Thing());
00169     List l = t->allocList();
00170     {
00171         pThing n(new Thing());
00172         n->set(_world->getTurtle()->getX());
00173         l.add(n);
00174     }
00175     {
00176         pThing n(new Thing());
00177         n->set(_world->getTurtle()->getY());
00178         l.add(n);
00179     }
00180     _world->setResult(t);
00181 }
00182 
00183 void Verbs::xcor(TokenStream *ts) {
00184     
00185     setDoubleResult(_world->getTurtle()->getX());
00186 
00187 }
00188 
00189 void Verbs::ycor(TokenStream *ts) {
00190     
00191     setDoubleResult(_world->getTurtle()->getY());
00192     
00193 }
00194 
00195 double radToDeg(double rad) {
00196     return (rad/PI)*180.0;
00197 }
00198 
00199 void Verbs::heading(TokenStream *ts) {
00200     
00201     setDoubleResult(radToDeg(_world->getTurtle()->getHeading()));
00202     
00203 }
00204 
00205 void Verbs::towards(TokenStream *ts) {
00206     
00207         pThing thing;
00208         _itp->getNextThing(_world, ts, &thing);
00209         if (!thing->isList())
00210                 BOOST_THROW_EXCEPTION( no_list_in_thing_exception() );
00211     
00212     Turtle *t = _world->getTurtle();
00213     double x1 = t->getX();
00214     double y1 = t->getY();
00215     double x2 = thing->getList().get(0)->asDouble();
00216     double y2 = thing->getList().get(1)->asDouble();
00217 
00218     double deg;
00219     if (x2 == x1) {
00220         if (y2 > y1)
00221             deg = 180;
00222         else
00223             deg = 0;
00224     }
00225     else if (y2 == y1) {
00226         if (x2 > x1)
00227             deg = 90;
00228         else
00229             deg = 270;
00230     }
00231     else {
00232         double slope = (x2 - x1) / (y2 - y1);
00233         if (slope < 0)
00234             slope *= -1;
00235         deg = radToDeg(atan(slope)) + (x2 > x1 ? (y2 > y1 ? 90 : 0) : (y2 > y1 ? 180 : 270));
00236     }
00237     
00238     setDoubleResult(deg);
00239    
00240 }
00241     
00242 }
 All Classes Functions