CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

| Download

Sage Turtle via JSXGraph

Views: 515

CoCalc Turtle Graphics using JSXGraph

Authors: Norbert Domes (sagenb version), William Stein (modified for CoCalc)

examples (sage code see below)

def displacement(s,alpha): """ returns the displacement vector with length s and direction alpha INPUT:: s - number alpha - number (degrees from 0 to 360) """ return s*vector(RR,(cos(pi*alpha/180),sin(pi*alpha/180))) class Turtle(): jsx_template = u""" <p><!-- JSXGraph MediaWiki extension 0.3.1 --> <link rel='stylesheet' type='text/css' href='http://jsxgraph.uni-bayreuth.de/distrib/jsxgraph.css' /> <script src='https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.5/jsxgraphcore.js' type='text/javascript'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.5/geonext.min.js' type='text/javascript'></script> <div id='jxgbox-_id_' class='jxgbox' style='width:600px; height:600px;'></div> <script type='text/javascript'> // board options see JSXGraph reference var brd = JXG.JSXGraph.initBoard('jxgbox-_id_', _board_options_ ); // create turtle at point (0,0) looking in direction 0 var t = brd.create('turtle',[[0,0],0]); Code = _code_list_ function run() { eval(Code.shift()); setTimeout(run,delay); if (Code.length < 1) return; } delay = _delay_; run() </script> </p> """ def __init__(self,board_options="{boundingbox:[-300,300,300,-300]}"): """ create a new turtle and the 'board' to be moved on. the geometry of the board is fixed to 600x600px origin (0,0) in the center valid board options see JSXGraph reference set turtle to (0,0) and direction to 0 (turtle looking to the right) TODO:: create more than one turtle on one board NOTE: only those python turtle methods with a counterpart in JSXGraph are implemented AUTHORS: Norbert Domes """ import uuid self.html = Turtle.jsx_template.replace('_id_', str(uuid.uuid4())).replace('_board_options_',board_options) self.code = [] self.position = vector((0,0)) self.heading = 0 def forward(self,x): """ move turtle x units in turtle's direction """ self.code.append("t.forward(%s);"%str(x)) self.position += displacement(x,self.heading) fd = forward def backward(self,x): """ move turtle x units backward to turtle's direction """ self.code.append("t.back(%s);"%str(x)) self.position -= displacement(x,self.heading) back = backward bk = backward def left(self,alpha): """ turn turtle alpha degrees to the left ``alpha`` - number """ self.code.append("t.left(%s);"%str(alpha)) self.heading += alpha self.heading = self.heading%360 lt = left def right(self,alpha): """ turn turtle alpha degrees to the right ``alpha`` - number """ self.code.append("t.right(%s);"%str(alpha)) self.heading -= alpha self.heading = self.heading%360 rt = right def setheading(self,alpha): """ set turtle's direction (degrees from 0 to 360) ``alpha`` - number """ self.code.append("t.left(%s);"%str(alpha - self.heading)) self.heading = alpha self.heading = self.heading%360 def goto(self,*args): """ move turtle to new position with drawing """ if len(args) == 2: x = args[0] y = args[1] elif len(args)==1: x = args[0][0] y = args[0][1] else: raise ValueError('error message') self.code.append("t.moveTo(%s);"%str(list((x,y)))) self.position = vector((x,y)) def setpos(self,*args): """ move turtle to new position without drawing INPUT:: x , y - two numbers or (x,y) - pair of numbers """ if len(args) == 2: x = args[0] y = args[1] elif len(args)==1: x = args[0][0] y = args[0][1] else: raise ValueError('error message') self.code.append("t.setPos(%s);"%str(list((x,y)))) self.position = vector((x,y)) def penup(self): """ further turtle movements without drawing """ self.code.append("t.penUp();") pu = penup def pendown(self): """ further turtle movements with drawing """ self.code.append("t.penDown();") pd = pendown def home(self): """ set turtle to (0,0) and direction to 0 (turtle looking to the right) """ self.code.append("t.home();") self.position = vector((0,0)) self.heading = 0 def clear(self): """ erase all drawings not changing turtle's position and direction """ self.code.append("t.clean();") def reset(self): """ set turtle to (0,0) and direction to 0 (turtle looking to the right) and erase all drawings """ self.code.append("t.clearScreen();") self.position = vector((0,0)) self.heading=0 def hideturtle(self): """ make turtle invisible """ self.code.append("t.hideTurtle();") def showturtle(self): """ make turtle visible """ self.code.append("t.showTurtle();") def color(self,color): """ set color of turtle's pen ``color`` - color string like 'red' or '#ff0000' """ self.code.append("t.setPenColor('%s');"%(color)) def pensize(self,size): """ set size of turtle's pen ``size`` - integer """ self.code.append("t.setPenSize(%s);"%(str(size))) def show(self, delay=10): """ creates html file containing javascript code using JSXGraph library returns link to the file TODO: automatically reload html when changed """ salvus.html(self.html.replace('_delay_',str(delay)).replace('_code_list_',str(self.code)))

Spirals

t = Turtle() t.pensize(2) t.color('red') t.penup() t.goto(0,100) t.pendown() t.left(90) t.hideturtle() for k in range(1,100): t.fd(10+k/6) t.rt(10) t.color('green') for k in range(1,100): t.fd(10+k/6) t.left(10) t.show(delay=30)

Tree

t = Turtle() t.pensize(4) t.color('pink') t.hideturtle() def tree(pos,dx,dy,n): if n <= 0: return x,y = pos pos_left = (x-dx,y-dy) pos_right = (x+dx,y-dy) t.setpos(pos) t.goto(pos_left) tree(pos_left,dx/2,4/5*dy,n-1) t.setpos(pos) t.goto(pos) t.goto(pos_right) tree(pos_right,dx/2,4/5*dy,n-1) tree((0,200),128,80,5) t.show()