Промена величине цртежа

Када смо говорили о померању цртежа, поменули смо да је боље да се сва рачунања обаве у програму, јер је тако једноставније да се по потреби цео цртеж помери или нацрта на више места. Слична је ситуација ако је потребно да цртеж буде мањи, или већи, или да се нацрта на више места у различитим величинама. Уместо рачунања свих координата испочетка, при програмском рачунању може бити довољно да се промени један једини број, па да добијемо цртеж друге величине.

Да бисмо научили како да правимо цртеже којима величина може лако да се мења, хајде прво да видимо шта све треба да се промени у неком програму за цртање, па да цртеж буде неке друге одређене величине. На пример, ако смо нацртали облак помоћу ових наредби:

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 = 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))