Промена величине цртежа¶
Када смо говорили о померању цртежа, поменули смо да је боље да се сва рачунања обаве у програму, јер је тако једноставније да се по потреби цео цртеж помери или нацрта на више места. Слична је ситуација ако је потребно да цртеж буде мањи, или већи, или да се нацрта на више места у различитим величинама. Уместо рачунања свих координата испочетка, при програмском рачунању може бити довољно да се промени један једини број, па да добијемо цртеж друге величине.
Да бисмо научили како да правимо цртеже којима величина може лако да се мења, хајде прво да видимо шта све треба да се промени у неком програму за цртање, па да цртеж буде неке друге одређене величине. На пример, ако смо нацртали облак помоћу ових наредби:
def oblak(x, y, siva):
# crtamo oblak od tri kruga
boja = (siva, siva, siva)
pg.draw.circle(prozor, boja, (x, y), 50)
pg.draw.circle(prozor, boja, (x - 50, y), 30)
pg.draw.circle(prozor, boja, (x + 50, y), 30)
oblak(200, 200, 180)
и сада желимо да облак буде двоструко мањи, а да му средина и даље буде у тачки (200, 200), онда бисмо функцију дату горе изменили у:
def oblak(x, y, siva):
# crtamo oblak od tri kruga
boja = (siva, siva, siva)
pg.draw.circle(prozor, boja, (x, y), 25)
pg.draw.circle(prozor, boja, (x - 25, y), 15)
pg.draw.circle(prozor, boja, (x + 25, y), 15)
Треба смањити полупречнике сва три круга на пола претходне величине (25 пиксела уместо 50, а 15 уместо 30), али то није довољно. Ако би центри малих кругова остали где су били, добили бисмо три раздвојена круга (испробајте). Да би цртеж и даље личио на облак, потребно је и да кругове међусобно приближимо. Прецизније речено, растојања центара мањих кругова од центра великог круга треба такође да буду два пута мања него пре, то јест по 25 уместо по 50 пиксела.
У општем случају не желимо увек двоструко мањи облак него да облаци могу да буду различитих величина. Осим тога, не желимо да за сваку величину облака правимо посебну функцију, него да имамо једну функцију која може да црта облак задате величине. Најудобније би било да можемо величину облака да задајемо само једним бројем и да променом тог једног броја мењамо величину облака. Да бисмо то постигли, потребно је да све величине које се мењају са променом величине облака (а то су растојања између центара кругова и полупречници тих кругова) изразимо помоћу једне величине. Можемо на пример за ту једну величину да узмемо полупречник средњег круга, који ћемо да означимо са \(r\). Растојања центара мањих кругова до центра већег круга су једнака управо по \(r\), а полупречник мањих кругова је једнак \({3 \over 5} r\) без обзира на величину облака. Када искористимо све ове везе које смо уочили, функција добија следећи изглед:
def oblak(x, y, r, siva):
# crtamo oblak od tri kruga
boja = (siva, siva, siva)
r_malo = round(3 * r / 5)
pg.draw.circle(prozor, boja, (x, y), r)
pg.draw.circle(prozor, boja, (x - r, y), r_malo)
pg.draw.circle(prozor, boja, (x + r, y), r_malo)
Функција има један параметар више, тако да осим положаја и нијансе сиве боје, овој функцији задајемо и величину облака. Сада можемо да правимо и овакве цртеже:
Хајде да сада набројимо кораке за уопштени поступак, којим бисмо преправили цртање било ког помичног цртежа тако да му се може мењати и величина:
Треба да одредимо једну дужину на цртежу, која ће да се задаје директно. Ову изабрану дужину можемо да назовемо основна дужина или јединица мере. У примеру облака, основна дужина је полупречник средњег круга.
Све полупречнике кругова од којих се цртеж састоји изражавамо сразмерно основној дужини. То значи да, ако је наша основна дужина означена са \(a\), све друге дужине у програму ће бити неки број помножен са \(a\), на пример \(2a\) или \(5a\). Овај број одређујемо из односа тражене дужине и изабране основне дужине на почетном цртежу (тај однос остаје исти и када се величина цртежа промени). У примеру са облаком, полупречник малог круга је увек \({3 \over 5}\) изабране основне дужине \(r\). Ако се на цртежу појављују и правоугаоници или елипсе, дужине и ширине тих правоугаоника и елипси такође треба да изразимо сразмерно основној дужини, на исти начин као и полупречнике кругова.
Координате свих тачака одређујемо у односу на главну тачку, тако што \(x\) и \(y\) координати главне тачке додајемо или одузимамо одређени број основних дужина. Потребан број основних дужина се и у овом случају одређује из односа на почетном цртежу. У примеру са облаком, да бисмо добили \(x\) координату центра левог круга, од \(x\) координате главне тачке (центра средњег круга) одузимамо једну основну дужину, јер је однос разлике \(x\) координата и основне дужине једнак један. Исти поступак се у принципу примењује и на \(y\) координате, мада је у овом случају то посебно једностано. Како су \(y\) координате центара кругова исте, однос разлике \(y\) координата и основне дужине је нула, па на \(y\) координату сидра треба додати нула основних дужина да бисмо добили \(y\) координату центра мањег круга.
Да бисмо боље разумели поступак промене величине цртежа, применићемо га и на примеру медведића.
Меда - величина¶
Дат је следећи програм, који приказује главу медведића играчке, тако да се она лако може премештати:
Да бисмо могли да мењамо величину цртежа, уведимо основну дужину, на пример \(a = 5\). Сада све полупречнике можемо да изразимо помоћу \(a\) овако:
uokviren_krug(prozor, pg.Color("yellow"), (cx - 60, cy - 70), 9*a) # levo uvo
uokviren_krug(prozor, pg.Color("yellow"), (cx + 60, cy - 70), 9*a) # desno uvo
uokviren_krug(prozor, pg.Color("yellow"), (cx, cy) , 20*a) # glava
uokviren_krug(prozor, pg.Color("yellow"), (cx, cy + 50), 10*a) # njuska
uokviren_krug(prozor, pg.Color("black"), (cx - 50, cy - 30), 3*a) # levo oko
uokviren_krug(prozor, pg.Color("black"), (cx + 50, cy - 30), 3*a) # desno oko
uokviren_krug(prozor, pg.Color("black"), (cx, cy + 20), 3*a) # vrh njuske
Као основна дужина се може изабрати било који број, а избором основне дужине од 5 пиксела, постигли смо да не морамо да користимо реалне бројеве - сви полупречници су целобројни умношци од \(a\) и можемо лако да их израчунамо напамет. На пример, полупречник од 45 пикесла изражавамо као \(45=9 \cdot 5 = 9 \cdot a\), и тако даље.
Сада је потребно да координате центара свих осталих кругова изразимо полазећи од главне тачке \((cx, cy)\), померајући се за потребан број дужина \(a\) у смеру \(x\) и \(y\) осе. Узмимо као пример десно уво медведића.
\(x\) координата центра десног увета је \(cx + 60 = cx + 12 a\), док је \(y\) координата \(cy - 70 = cy - 14 a\). Када ово урадимо за све центре кругова, долазимо до следећег облика програма:
Сада можемо не само да премештамо или копирамо медведића по екрану, него и да га приказујемо у разним величинама. Као потврду да мењање величине заиста ради, можете позив функције
crtaj_medu(sirina // 2, visina // 2, 6)
која црта медведића са главном тачком у центру прозора, да замените са следећих пет:
crtaj_medu(85, 100, 4)
crtaj_medu(235, 100, 3)
crtaj_medu(50, 250, 2)
crtaj_medu(150, 250, 2)
crtaj_medu(250, 250, 2)
Ископирајте или препишите ових пет линија кода у програм и испробајте! Размислите колико би посла било да се ових пет медведића прикажу без рачунања у програму.
Покушајте сада да довршите један започети пример.
Задатак - величина куће¶
Почећемо од програма који црта четири кућице на задатим местима на екрану:
Довршите преправку програма у пољу испод, тако да кућице могу једноставно да се повећавају и смањују. За основну величину можете да узмете на пример 10 пиксела, јер је у том случају изражавање свих дужина помоћу основне дужине врло једноставно. Када потврдите да програм након преправке приказује исту слику као и полазни програм који је дат горе, замените дате позиве функције kuca са следећа 4, и тако проверите да ли промена величине куће ради како треба (треба да добијете слику као при клику на дугме „Прикажи пример”):
kuca(150, 90, 8, pg.Color(220, 220, 220))
kuca(250, 130, 9, pg.Color("white"))
kuca(350, 160, 10, (255,255,150))
kuca( 50, 150, 10, pg.Color("khaki"))
Након што сте успешно изменили функцију kuca, испробајте разне распореде, боје и величине кућа, на пример овај испод, или неки који сами изаберете:
kuca(278, 110, 1, (211, 207, 169))
kuca(231, 119, 2, (217, 211, 164))
kuca(174, 130, 3, (228, 221, 152))
kuca(112, 142, 4, (231, 222, 150))
kuca( 18, 160, 6, (240, 230, 140))