Joonistamine
Käesolevas aines kasutame joonistamiseks pythoni turtle moodulit, mis põhineb kilpkonnagraafikal.
Kilpkonnagraafika ajalugu
Kilpkonnagraafikat kasutati esmakordselt Logo programmeerimiskeeles 1960. aastate lõpul. Kilpkonnadeks nimetati esialgu roboteid, mille külge oli kinnitatud pliiats ning mida oli võimalik juhtida, andes liikumiseks erinevaid käske. Peagi lisandusid neile ka simuleeritud robotid, mis töötasid samal põhimõttel, kuid tegid seda arvutiekraanil.
Kilpkonnagraafikast sai peagi populaarne viis õpetada programmmeerimist ning sarnased vahendid on tänapäeval olemas paljudes programmeerimiskeeltes - sealhulgas ka pythonis. Kilpkonnale käske jagades ja tema teekonda jälgides on võimalik lihtsamini visualiseerida seda, mis toimub programmi täitmise käigus, ning on seetõttu abiks programmeerimise aluste mõistmisel.
Kasutamine
Kilpkonnagraafika kasutamiseks vajalikud funktsioonid asuvad pythoni turtle moodulis. Mooduli lisamiseks enda koodile piisab, kui lisame kõige algusesse rea import turtle. Mooduli kohta saab täpsemalt lugeda siit Moodul.
Selleks, et kilpkonn näeks ka välja nagu kilpkonn, kasutame funktsiooni shape, ning liigutamiseks funktsiooni forward. Kuna need funktsioonid asuvad moodulis, peame ka eraldi täpsustama, et tahame kasutada just turtle mooduli funktsioone.
import turtle # import turtle module, allowing us to use turtle commands
turtle.shape("turtle") # make the cursor look like a turtle
turtle.forward(15) # tell the turtle to move 15px in the direction it is facing
Kui nüüd kood käima panna, siis ilmselt märkate, et ekraan ilmub korraks nähtavale ning kaob kohe ära. Mis võiks olla selle põhjuseks?
Kui viimane käsk jõuab lõpule, lõpetab programm oma töö ning aken pannakse kinni. Kui soovime akent kauem lahti hoida, peame andma selleks eraldi käsu.
turtle.done() # drawing is finished, do not close window
Proovime joonistada mõne lihtsa kujundi, näiteks ruudu. Seda saab teha mitmel erineval viisil.
turtle.forward(200)
turtle.left(90)
turtle.forward(200)
turtle.left(90)
turtle.forward(200)
turtle.left(90)
turtle.forward(200)
Panime iga käsu eraldi kirja ning kilpkonna teekonnale jääb tõepoolest maha ilus ruut. Koodi vaadates näeme aga, et oleme ennast korranud. Kuigi copy-paste aitab olukorra mugavamaks teha, võime siiski eeldada, et arvuti oskab ridu ka ise korrata. Meenutame, mida oleme esimestes tundides õppinud. Vihje Tsükkel (loop).
for i in range(4):
turtle.forward(200)
turtle.left(90)
Mida teha siis, kui tahame joonistada mitut erineva suurusega ruutu? Kõige mõistlikum oleks ruudu joonistamine teha eraldi funktsiooniks:
def draw_square(width):
for i in range(4):
turtle.forward(width)
turtle.left(90)
Nüüd võime enda funktsiooni välja kutsuda iga kord, kui tahame joonistada ruutu. Rohkem infot funktsioonide kohta leiad siit Funktsiooni mõiste ja kasutamine.
Kilpkonn kui objekt
Seni pöördusime kilpkonna liigutamiseks otse turtle mooduli poole. Tegelikkuses võib kilpkonna vaadelda kui eraldiseisvat objekti. Võime teha näiteks mitu kilpkonna ning anda neile käske eraldi. Igal kilpkonnal on oma seis ehk kogum kindlate väärtustega muutujaid, näiteks suund, asukoht või joone värv. Selleks, et saaksime kilpkonni eraldi liigutada, peame neid seostama sobivalt nimetatud muutujatega.
import turtle
# create Turtle objects as defined in turtle module
kilbi = turtle.Turtle()
kilpron = turtle.Turtle()
Loomise hetkel on kaks kilpkonna peaaegu identsed. Vaatame, mis juhtub, kui liigutame ühte neist veidi edasi. Kahe kilpkonna eristamiseks teeme ainult ühe neist kilpkonnakujuliseks.
kilbi.shape("turtle")
kilbi.forward(25)
turtle.done() # done() is still a function of the turtle module
Koodi käivitamisel näeme, et üks kilpkonn liikus ja muutis oma kuju, teine aga jäi paigale. Ükskõik mis hetkel ja kui palju kilpkonni me juurde teeme, alustavad nad kõik samast keskpunktist, kus esimesed kaks. Mitte ükski kilpkonn ei tea midagi teiste olekutest ning me saame pöörduda vaid ühe poole korraga.
Kõiki kilpkonni, ehk Turtle objekte, ühendab asjaolu, et neil on olemas samad muutujad ja funktsioonid. Seega võib öelda, et kõik meie kilpkonnad on Turtle klassi instantsid. Klassidest ja objektidest saab täpsemalt lugeda Klassid ja objektid.
Ka esimestes näidetes luuakse tegelikult turtle objekt, kuid see tegevus on meie eest peidetud turtle mooduli sisse. Lihtsustus on tehtud selleks, et joonistada saaks ka siis, kui objektorienteeritusest midagi ei tea.
Lisaks on kasulik teada, et objekte saab täpselt samamoodi argumentidena kasutada, nagu teisi muutujaid. Näiteks võime ruudu joonistamise funktsiooni täiendada:
def draw_square(width, turtle_obj):
for i in range(4):
turtle_obj.forward(width)
turtle_obj.left(90)
Nüüd saame funktsiooni väljakutsel valida, milline kilpkonna objekt ruudu joonistab.
kilbi = turtle.Turtle()
kilpron = turtle.Turtle()
draw_square(20, kilbi) # only kilbi starts drawing
Kilpkonna liigutamine
Liikumine edasi või tagasi
distance = 5 # pixels
turtle.forward(distance)
turtle.fd(distance) # shorter version, same command
turtle.backward(distance)
turtle.bk(distance)
turtle.back(distance)
Liikumine kindlasse punkti. Kõik kolm viisi on identsed, seega võimalik on ka näiteks setposition(x, y), goto(position) jne.
x, y = 100, 50 # coordinates
turtle.goto(x, y)
turtle.setpos(x, y)
position = (20, 20)
turtle.setposition(position)
Ühe koordinaadi muutmine
turtle.setx(24) # move along x-axis only
turtle.sety(10) # move along y-axis only
Pööramine n kraadi võrra. Näiteks kui alguses on kilpkonna suund 90 kraadi ehk üles, siis right(90) järel on suund 0 kraadi ehk paremale.
angle = 10 # degrees
turtle.right(angle)
turtle.rt(angle)
turtle.left(angle)
turtle.lt(angle)
Suuna seadmine. Suund määratakse kraadidena olenemata sellest, mis oli suund enne.
turtle.setheading(180)
turtle.seth(180)
Joonistamine
Joonistamise alustamine ja lõpetamine. Vajalik selleks, et kilpkonna saaks liigutada ka ilma joone tõmbamiseta.
# start drawing - draw every move after this
turtle.pendown()
turtle.pd()
turtle.down()
# stop drawing - draw no lines when moving after this
turtle.penup()
turtle.pu()
turtle.up()
# return True if pen is down, change nothing
turtle.isdown()
Pliiatsi jämedus
# return current pen width
turtle.pensize()
turtle.width()
# set pen width to 20
turtle.pensize(20)
turtle.width(20)
Pliiatsi värv. Kasutada võib värvi nimetust või koodi sõnena (nt #33cc8c) ning ka rgb väärtust.
turtle.colormode(255) # use rgb values 0 ... 255
turtle.colormode(1.0) # use rgb values 0 ... 1.0 (default)
# return current pen color
turtle.pencolor()
# change pen color
turtle.pencolor("blue")
turtle.pencolor(0.2, 0.3, 1.0) # if colormode = 1.0
turtle.pencolor((0.2, 0.3, 1.0))
Täitevärv. Kasutatakse kujundi täitmisel.
# return current fill color
turtle.fillcolor()
# change fill color
turtle.fillcolor("blue")
turtle.fillcolor((255, 200, 13)) # if colormode = 255
turtle.fillcolor(255, 200, 13)
Pliiatsi- ja täitevärvi saab seada ka korraga:
turtle.color("blue")
turtle.color((255, 200, 13)) # if colormode = 255
turtle.color(255, 200, 13)
Täitmine. Joonte vaheline ala täidetakse värviga fillcolor.
turtle.filling() # return True if filling
# fill in a circle
turtle.begin_fill()
turtle.circle(50)
turtle.end_fill()
Ringi joonistamine. Kuna pikslitena ei saa kujutada ideaalset ringi, on tegelikult tegu hulknurgaga. Seetõttu saab sama funktsiooni kasutada ka hulknurkade joonistamiseks, andes kaasa argumendi steps. Võimalik on joonistada ringi ka osaliselt, andes argumendi extent, mille väärtuseks on kraadide hulk, mida soovitakse joonistada.
radius = 50
turtle.circle(radius)
turtle.circle(radius, extent=180) # semicircle
turtle.circle(radius, steps=6) # hexagon
turtle.circle(radius, extent=270, steps=6) # three quarters of a hexagon
Täpi joonistamine. Kui suurust pole antud, arvutatakse välja pensize+4 ja 2*pensize ja täpi diameetriks saab neist suurim.
turtle.dot()
turtle.dot(size=20)
turtle.dot("blue")
Teksti lisamine pildile.
turtle.write("Hello, world!")
Kilpkonna olek
Kilpkonna nähtavus. Kilpkonna peitmine muudab joonistamise kiiremaks.
turtle.hideturtle()
turtle.isvisible() # False
turtle.showturtle()
turtle.isvisible() # True
turtle.ht() # same as hideturtle
turtle.st() # same as showturtle
Kilpkonna kuju. Saab kasutada kujundeid “arrow”, “turtle”, “circle”, “square”, “triangle” ja “classic”.
turtle.shape() # return current shape
turtle.shape("turtle") # set shape to turtle
Kilpkonna kiirus. Määrab, kui kiiresti joonistamine toimub. Võib määrata täisarvuga 1-10 või sõnena:
“fastest”: 0
“fast”: 10
“normal”: 6
“slow”: 3
“slowest”: 1
# return current speed
turtle.speed()
# set speed
turtle.speed(9)
turtle.speed("normal")
On olemas veel erinevaid funktsioone ja täpsustusi, mida siin materjalides välja pole toodud. Need leiad pythoni dokumentatsioonist.
Viited
https://docs.python.org/3/library/turtle.html turtle mooduli ametlik dokumentatsioon
https://helloworld.raspberrypi.org/helloworld/issues/1 lk 32-33 kilpkonnagraafika tähtsusest programmeerimise õpetamisel