Промяна на размера на чертежа¶
Когато говорихме за преместване на чертеж, споменахме, че е по-добре да се направят всички изчисления в програмата, защото по този начин е по-лесно да преместите чертежа или да го направите на няколко места, когато е необходимо. Подобна е ситуацията, когато искаме да нарисуваме една и съща рисунка с различен размер, възможно на няколко места (всяко може да бъде с различен размер). Вместо да изчисляваме всички координати от нулата, може да е достатъчно да промените едно единствено число в нашата програма, за да получите чертеж с друг размер.
За да научите как да правите рисунки, които могат да бъдат оразмерени лесно, нека първо да видим какво трябва да се промени в програма за рисуване, така че чертежът да получи различен размер. Например, ако нарисувахме облак, използвайки тези операции:
def cloud(x, y, shade):
# draw a cloud of three circles
gray = (shade, shade, shade)
pg.draw.circle(canvas, gray, (x, y), 50)
pg.draw.circle(canvas, gray, (x - 50, y), 30)
pg.draw.circle(canvas, gray, (x + 50, y), 30)
cloud(200, 200, 180)
и сега искаме облакът да е два пъти по-малък, а средната му точка да е все още в точка (200, 200), тогава бихме променили функцията, дадена по-горе на:
def cloud(x, y, shade):
# draw a cloud of three circles
gray = (shade, shade, shade)
pg.draw.circle(canvas, gray, (x, y), 25)
pg.draw.circle(canvas, gray, (x - 25, y), 15)
pg.draw.circle(canvas, gray, (x + 25, y), 15)
Радиусите и на трите кръга трябва да бъдат намалени до половината от предишния размер (25 пиксела вместо 50 и 15 вместо 30), но това не е достатъчно. Ако центровете на малките кръгове останаха там, където бяха, щяхме да получим три отделни кръга (опитайте). За да може рисунката все още да изглежда като облак, ние също трябва да приближим кръговете. По-конкретно, разстоянията на центровете на по-малките кръгове от центъра на големия кръг също трябва да бъдат два пъти по-малко от преди, тоест 25 вместо 50 пиксела. По принцип не винаги искаме облак, който да е два пъти по-малък, но че облаците могат да бъдат с различни размери. В допълнение, ние не искаме да създаваме отделна функция за всеки размер на облака, а да имаме една функция, която може да нарисува облак с определен размер. IUt би било най-удобно, ако можехме да зададем размера на облака само с едно число и да променим размера на облака, като променим това едно число. За да направите това, трябва да изразим всички размери, които се променят с промяната на размера на облака (което е разстоянието между центровете на кръговете и радиусите на тези кръгове), като използваме един избран размер. Например, за този избран размер можем да вземем радиуса на средния кръг, който ще обозначим с \(r\). Разстоянията на центровете на по-малките кръгове до центъра на по-големия кръг са точно \(r\), а радиусът на по-малките кръгове е равен \({3 \ over 5}r\), независимо от размера от облака. Когато използваме всички тези отношения, които забелязахме, функцията изглежда така:
def cloud(x, y, r, shade):
# draw a cloud of three circles
gray = (shade, shade, shade)
r_small = round(3 * r / 5)
pg.draw.circle(canvas, gray, (x, y), r)
pg.draw.circle(canvas, gray, (x - r, y), r_small)
pg.draw.circle(canvas, gray, (x + r, y), r_small)
Функцията има още един параметър - освен позицията и нюанса на сивото, ние също задаваме размера на облака на тази функция. Сега можем да направим рисунки по този начин:
Сега, нека да изброим стъпките за обща процедура за преработка на всеки подвижен чертеж, така че да може да бъде променен също така:
Трябва да определим една дължина в чертежа, която ще бъде зададена директно. Можем да наречем тази избрана дължина основна дължина или мерна единица. В примера на облаците основната дължина е радиусът на средния кръг.
Всички радиуси на кръговете, от които се състои чертежът, се изразяват пропорционално на основната дължина. Това означава, че ако основната ни дължина се обозначава с \(a\), всички останали дължини в програмата ще бъдат кратни на \(a\), например \(2a\) или \(5a\). Определяме числото \(a\) от съотношението на необходимата дължина и избраната основна дължина в началния чертеж (това съотношение остава същото, когато размерът на чертежа се промени). В примера с облака радиусът на малкия кръг винаги е \({3 \ over 5}\) на избраната основна дължина \(r\). Ако на чертежа се появят правоъгълници или елипси, височините и ширините на тези правоъгълници и елипси също трябва да бъдат изразени пропорционално на основната дължина, по същия начин като радиусите на кръговете.
Определяме координатите на всички точки по отношение на основната точка, като добавяме или изваждаме определен брой основни дължини към координатите на главната точка. Необходимият брой основни дължини се определя отново от отношението в началния чертеж. В примера с облака, за да получим \(x\) координата на центъра на левия кръг, изваждаме една основна дължина от \(x\) координата на главната точка (център на средата кръг). Правим го, защото съотношението на разликата на \(x\) координати и основна дължина е равно на единица. Същата процедура се прилага по принцип за: math: y координати, въпреки че в този случай е особено проста. Тъй като \(y\) координатите на центровете на кръговете са еднакви, съотношението на разликата на координатите \(y\) и основната дължина е нула, така че нула основни дължини трябва да се добавят към \(y\) координата на котвата, за да се получи \(y\) координата на центъра на по-малък кръг.
За да разберем по-добре процеса на оразмеряване на рисунка, ще го приложим и към примера на плюшено мече.
Размерът на плюшеното мече¶
Представена е следната програма, която показва главата на плюшено мече, за да може лесно да се движи:
За да промените размера на чертежа, въвеждаме основна дължина, например \(a = 5\). Сега можем да изразим всички радиуси, използвайки \(a\) така:
framed_circle(canvas, pg.Color("yellow"), (cx - 60, cy - 70), 9*a) # left ear
framed_circle(canvas, pg.Color("yellow"), (cx + 60, cy - 70), 9*a) # right ear
framed_circle(canvas, pg.Color("yellow"), (cx, cy) , 20*a) # head
framed_circle(canvas, pg.Color("yellow"), (cx, cy + 50), 10*a) # snout
framed_circle(canvas, pg.Color("black"), (cx - 50, cy - 30), 3*a) # left eye
framed_circle(canvas, pg.Color("black"), (cx + 50, cy - 30), 3*a) # right eye
framed_circle(canvas, pg.Color("black"), (cx, cy + 20), 3*a) # snout top
Всяко число може да бъде избрано като основна дължина и като изберем базова дължина от 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\). Когато правим това за всички центрове на кръговете, стигаме до следната форма на програмата:
Сега можем не само да движим или копираме плюшено мече по екрана, но и да го показваме в различни размери. За да потвърдите, че оразмеряването наистина работи, извикайте функцията
draw_teddy(width // 2, height // 2, 6)
който рисува мечка с централната точка в центъра на прозореца, може да бъде заменен със следните пет:
draw_teddy(85, 100, 4)
draw_teddy(235, 100, 3)
draw_teddy(50, 250, 2)
draw_teddy(150, 250, 2)
draw_teddy(250, 250, 2)
Копирайте или въведете отново тези пет реда код в програмата и я изпробвайте! Помислете колко работа би била тези пет мечки да се показват без изчисления в програмата.
Сега опитайте да завършите един започнат пример.
Задача - размер на къщата¶
Ще започнем с програма, която рисува четири къщи в дадените позиции на екрана:
Попълнете реконструкцията на програмата в полето по-долу, така че къщите да бъдат лесно преоразмерени. Например, можете да вземете 10 пиксела за основния размер, защото в този случай изразяването на всички дължини с помощта на основна дължина е много лесно. Когато потвърдите, че програмата след римейка показва същото изображение като стартовата програма по-горе, заменете дадените обаждания за функция * house * със следните 4 и потвърдете, че оразмеряването на къщата работи правилно (трябва да получите изображението, сякаш щракнахте върху бутона „Play Task“):
house(150, 90, 8, pg.Color(220, 220, 220))
house(250, 130, 9, pg.Color("white"))
house(350, 160, 10, (255,255,150))
house( 50, 150, 10, pg.Color("khaki"))
След като успешно промените функцията house, опитайте различни оформления, цветове и размери на къщи, като например тази по-долу или друга избрана от вас:
house(278, 110, 1, (211, 207, 169))
house(231, 119, 2, (217, 211, 164))
house(174, 130, 3, (228, 221, 152))
house(112, 142, 4, (231, 222, 150))
house( 18, 160, 6, (240, 230, 140))