|
PH Logo
Logo intepreter modeled after UCB Logo.
|
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 }
1.7.4