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.

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

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

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 siit.

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äpsustusio, 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