在利用Processing繪出很酷的圖形之前捞魁,你需要先學(xué)習(xí)Python編程語(yǔ)言的基礎(chǔ)知識(shí)鞋拟。本文假設(shè)你已經(jīng)安裝Python
和Processing
,如果沒(méi)有稀轨,歡迎你訪問(wèn)我在B站的視頻課程姿现,你可以在編程入門—使用python語(yǔ)言開發(fā)游戲課程中學(xué)習(xí)下載Python并安裝以及Python的基礎(chǔ)操作肠仪,可以在在python編程中發(fā)現(xiàn)數(shù)學(xué)之美中學(xué)習(xí)如何下載和安裝Processing。本文是在Python編程中發(fā)現(xiàn)數(shù)學(xué)之美的第五章的部分內(nèi)容备典,視頻內(nèi)容在這兒异旧。
這篇文章的最終目的是繪制一個(gè)如下的圖形:
在幾何課上,你學(xué)的所有東西都是關(guān)于空間里的形狀和尺寸提佣。一般來(lái)說(shuō)你先學(xué)習(xí)一維的直線吮蛹,然后學(xué)習(xí)二維的圓、正方形或三角形拌屏,然后學(xué)習(xí)三維的物體如立方體和球體潮针。當(dāng)今時(shí)代,利用很多先進(jìn)的技術(shù)和免費(fèi)的軟件可以很容易地創(chuàng)建幾何圖形倚喂,但是要處理和改變你的圖形每篷,可能就有點(diǎn)挑戰(zhàn)性了。
下面我們從簡(jiǎn)單的圓和三角形開始,學(xué)習(xí)怎樣利用processing處理和改變圖形焦读。這些簡(jiǎn)單的圖形是我們后面將要學(xué)到的分形和細(xì)胞繁殖的基礎(chǔ)子库。你還將學(xué)習(xí)如何將復(fù)雜的物體分解成簡(jiǎn)單的部件。
畫圓
我們先畫一個(gè)簡(jiǎn)單的圓矗晃。在processing中打開新的繪圖版仑嗅,保存為文件名geometry,然后輸入下面的代碼:
def setup():
size(600,600)
def draw():
ellipse(200,100,20,20)
繪制圓之前张症,我們首先需要定義繪圖窗口的尺寸仓技,或者叫坐標(biāo)平面。這個(gè)例子中我們使用size函數(shù)聲明我們的繪圖板將有600個(gè)像素寬600個(gè)像素高俗他。
定義了坐標(biāo)系統(tǒng)之后浑彰,我們就可以使用draw()
中的ellipse
函數(shù)繪制橢圓。前面兩個(gè)參數(shù)200和100定義這個(gè)圓的圓心所在的位置拯辙。200是圓心的x坐標(biāo),100是y坐標(biāo)颜价。后面兩個(gè)參數(shù)定義橢圓的寬度和高度涯保,以像素為單位。這個(gè)例子中周伦,這個(gè)形狀是20個(gè)像素寬20個(gè)像素高夕春,因?yàn)檫@兩個(gè)參數(shù)是相等的,也就是說(shuō)圓的邊緣上的點(diǎn)離圓心的距離是相等的专挪,所以這個(gè)橢圓是一個(gè)圓形及志。
單機(jī)run按鈕,一個(gè)新的窗口彈出來(lái)寨腔,上面有我們繪制的圓速侈。
現(xiàn)在你了解了在processing中如何繪制圓,為了創(chuàng)建動(dòng)態(tài)的交互式的圖形迫卢,我們還需要學(xué)習(xí)圖形的位置和變換倚搬,讓我們從位置開始。
使用坐標(biāo)系為圖形定位
上一節(jié)的代碼中乾蛤,ellipse函數(shù)的前兩個(gè)參數(shù)指定了橢圓的圓心的位置每界。我們使用processing繪制的每一個(gè)圖形,都需要指定它在坐標(biāo)系統(tǒng)中的位置家卖,一般是用兩個(gè)點(diǎn)來(lái)表示:x和y眨层。在傳統(tǒng)的幾何數(shù)學(xué)中,原點(diǎn)一般在圖像的中心位置上荡。
然而在計(jì)算機(jī)圖形中趴樱,坐標(biāo)系統(tǒng)與傳統(tǒng)的幾何系統(tǒng)不一樣。計(jì)算機(jī)圖形系統(tǒng)中的原點(diǎn),在屏幕的左上角伊佃,x和y隨著屏幕向右向下而增加窜司。
上面屏幕中的每一個(gè)坐標(biāo),表達(dá)了屏幕上的每一個(gè)像素航揉。你可能已經(jīng)注意到了塞祈,在這樣的坐標(biāo)系統(tǒng)中,不需要處理負(fù)的坐標(biāo)帅涂。我們將使用函數(shù)在上面這樣的坐標(biāo)系統(tǒng)中议薪,逐漸地實(shí)現(xiàn)圖形的轉(zhuǎn)換和變換。
畫一個(gè)單個(gè)的圓相對(duì)很容易媳友,但是畫多個(gè)圓可能就變得有點(diǎn)兒復(fù)雜斯议,例如,我們需要設(shè)計(jì)下面的圖形:
為每一個(gè)小圓確定位置醇锚,需要輸入許多行相似的代碼哼御。幸運(yùn)的是,你不需要精確的知道每一個(gè)圓的x和y坐標(biāo)焊唬。在processing中恋昼,可以很容易的把坐標(biāo)上的任何圖形放到想放的地方。讓我們從一個(gè)簡(jiǎn)單的例子開始赶促。
轉(zhuǎn)移函數(shù)
你可能還記得在幾何課堂上使用紙和鉛筆液肌,如何費(fèi)力的做幾何圖形的轉(zhuǎn)換。在計(jì)算機(jī)中圖形轉(zhuǎn)換變得非常有趣而且容易鸥滨。在processing中嗦哆,可以很容易的移動(dòng)或旋轉(zhuǎn)一個(gè)三角形或類似的圖形。
使用translate移動(dòng)坐標(biāo)系
幾何中的圖形移動(dòng)婿滓,表示在坐標(biāo)系中被移動(dòng)的圖形上的每個(gè)點(diǎn)都移動(dòng)相同的方向老速、相同的距離】栈茫或者說(shuō)圖形的移動(dòng)烁峭,就是改變圖形的位置,但是圖形的形狀沒(méi)有任何改變秕铛。
在數(shù)學(xué)課堂上移動(dòng)物體约郁,牽扯到重新計(jì)算圖像中的每個(gè)點(diǎn)的坐標(biāo)。但是在processing中但两,物體的移動(dòng)鬓梅,只需要移動(dòng)坐標(biāo)系本身,物體本身不會(huì)改變谨湘。讓我們用下面的矩形作為例子绽快。先修改上面講的一段代碼芥丧。
def setup():
size(600,600)
def draw():
rect(20,40,50,30)
這兒我們使用rect函數(shù)繪制了一個(gè)矩形。前兩個(gè)參數(shù)告訴processing這個(gè)矩形左上角的坐標(biāo)坊罢,第3和第4個(gè)參數(shù)指明長(zhǎng)方形的寬度和高度续担。運(yùn)行代碼:
我們使用下面的代碼,移動(dòng)這個(gè)矩形活孩。注意我們不會(huì)改變這個(gè)矩形的坐標(biāo)物遇。
def setup():
size(600,600)
def draw():
translate(50,80)
rect(20,40,50,30)
這兒我們使用translate
移動(dòng)這個(gè)矩形。我們提供了兩個(gè)參數(shù)憾儒,第1個(gè)參數(shù)告訴processing在水平方向也就是x方向移動(dòng)的數(shù)量询兴,第2個(gè)參數(shù)是在垂直方向也就是y方向上移動(dòng)的數(shù)量。所以translate(50,80)
將會(huì)向右50個(gè)像素向下80個(gè)像素移動(dòng)整個(gè)坐標(biāo)系起趾,像下面圖中顯示的那樣诗舰。
我們還是習(xí)慣坐標(biāo)系的原點(diǎn)在屏幕的正中間,就像我們?cè)跀?shù)學(xué)課上學(xué)到的那樣训裆。你可以很容易地使用translate
把坐標(biāo)的原點(diǎn)移到屏幕的中間眶根。你也可以使用它改變窗口畫布的高度和寬度。讓我們看看processing的內(nèi)置的width
和height
變量边琉,這兩個(gè)變量可以讓你很容易的改變畫布的寬度和高度汛闸。讓我們來(lái)更新以前的代碼:
def setup():
size(600,600)
def draw():
translate(width/2, height/2)
rect(0,0,50,30)
你在size
中聲明的參數(shù)將成為畫布的寬度和高度。在這個(gè)例子中艺骂,因?yàn)槭褂昧?code>size(600,600),它們都是600個(gè)像素隆夯。我們調(diào)用translate
時(shí)钳恕,兩個(gè)參數(shù)沒(méi)有使用具體的數(shù)值而使用了變量width/2
和height/2
,我們告訴processing將原點(diǎn)移動(dòng)到當(dāng)前窗口的中心蹄衷,不管當(dāng)前窗口的寬度和高度是多少忧额。這也表示掰邢,如果你改變了窗口的尺寸电爹,processing會(huì)自動(dòng)的更新width
和height
而不必手動(dòng)修改。
運(yùn)行代碼你將會(huì)看到下面的圖像:
注意原點(diǎn)仍然被標(biāo)記為(0,0)
母市,實(shí)際上我們并沒(méi)有移動(dòng)原點(diǎn)耍属,只是移動(dòng)了整個(gè)坐標(biāo)系托嚣,這樣把原點(diǎn)移動(dòng)到屏幕中央來(lái)了。
使用rotate旋轉(zhuǎn)對(duì)象
在幾何中旋轉(zhuǎn)表示將一個(gè)物體圍繞著一個(gè)中心轉(zhuǎn)動(dòng)厚骗。Processing中rotate
函數(shù)圍繞著原點(diǎn)旋轉(zhuǎn)坐標(biāo)系示启。它只接受一個(gè)參數(shù),這個(gè)參數(shù)是旋轉(zhuǎn)坐標(biāo)系的角度领舰。角度的單位是弧度夫嗓。旋轉(zhuǎn)一周是360度迟螺,換算成弧度就是2pi,大概6.28弧度舍咖。如果你像我一樣習(xí)慣了使用度而不是弧度矩父,你可以使用radians()
函數(shù)方便的把度轉(zhuǎn)化為弧度。
下面的代碼展示了rotate
函數(shù)如何工作排霉,修改代碼然后運(yùn)行:
上面的代碼表示圍繞著原點(diǎn)旋轉(zhuǎn)坐標(biāo)系20度窍株,這兒的原點(diǎn)在窗口的左上角。下面的圖形首先移動(dòng)原點(diǎn)到窗口中心郑诺,然后旋轉(zhuǎn)20度夹姥。
Rotate函數(shù)使在圓上繪制對(duì)象變得很容易:
- 移動(dòng)原點(diǎn),到你想要畫的圓的圓心辙诞。
- 旋轉(zhuǎn)坐標(biāo)系辙售,將你想要繪制的圖形,繪制在圓的邊上飞涂。
繪制圓形組成的圓形
要繪制上面的圖形旦部,我們需要用到for
循環(huán),在循環(huán)中繪制圓较店,并且確保每個(gè)圓之間的距離是相等的士八。我們要考慮要畫的圓之間的角度是多少,注意一個(gè)圓周是360度梁呈,輸入下面的代碼:
def setup():
size(600,600)
def draw():
translate(width/2, height/2)
for i in range(12):
ellipase(200,0,50,50)
rotate(radians(360/12))
注意婚度,translate
函數(shù)將坐標(biāo)系的原點(diǎn)移動(dòng)到屏幕的中央。接下來(lái)我們開始了一個(gè)for循環(huán)官卡,循環(huán)中創(chuàng)建圓蝗茁,圓心坐標(biāo)在(200,0)
,半徑是50
寻咒。然后旋轉(zhuǎn)坐標(biāo)系360÷12
度或者說(shuō)30
度哮翘,但是在旋轉(zhuǎn)之前我們需要將它轉(zhuǎn)換成弧度。這也就是說(shuō)每個(gè)小圓之間的角度是30
度毛秘。
繪制由方塊組成的圓
修改上一節(jié)的代碼饭寺,將圓換成正方形。只需要改變ellipse
函數(shù)為rect
函數(shù)叫挟。
def setup():
size(600,600)
def draw():
translate(width/2, height/2)
for i in range(12):
rect(200,0,50,50)
rotate(radians(360/12))
使對(duì)象動(dòng)起來(lái)
Processing
使用對(duì)象創(chuàng)建動(dòng)畫的功能很強(qiáng)大艰匙。對(duì)于你的第一個(gè)動(dòng)畫,咱們使用rotate
函數(shù)抹恳。正常來(lái)說(shuō)旬薯,rotate
是瞬間發(fā)生的,所以你幾乎不可能看到動(dòng)作的發(fā)生适秩,只看到rotate
的結(jié)果绊序,但是這次我們會(huì)用一個(gè)時(shí)間變量t硕舆,它可以使我們實(shí)時(shí)看到旋轉(zhuǎn)。
創(chuàng)建t變量
讓我們使用由方塊組成的圓來(lái)創(chuàng)建動(dòng)畫程序骤公,開始之前先創(chuàng)建t變量抚官,然后把它初始化為0
。然后插入下面的代碼阶捆。
t = 0
def setup():
size(600,600)
def draw():
translate(width/2, height/2)
rotate(radians(t))
for i in range(12):
rect(200,0,50,50)
rotate(radians(360/12))
t += 1
但是如果運(yùn)行這個(gè)代碼的話凌节,你會(huì)得到下面的錯(cuò)誤提示。
UnboundLocalError: local variable 't' referenced before assignment
這是因?yàn)镻ython語(yǔ)言不知道我們?cè)诤瘮?shù)中引用的變量t
是全局變量洒试。所以我們需要聲明global t倍奢,輸入完整的代碼如下:
t = 0
def setup():
size(600,600)
def draw():
global t
background(255) # set background white
translate(width/2, height/2)
rotate(radians(t))
for i in range(12):
rect(200,0,50,50)
rotate(radians(360/12))
t += 1
這個(gè)代碼開始的時(shí)候t設(shè)置為0,然后旋轉(zhuǎn)坐標(biāo)系垒棋,然后t增加1卒煞,然后重復(fù)。運(yùn)行代碼:
接下來(lái)我們?cè)囍D(zhuǎn)每個(gè)單獨(dú)的方塊叼架。
旋轉(zhuǎn)單獨(dú)的方塊
因?yàn)樵趐rocessing中旋轉(zhuǎn)是圍繞著原點(diǎn)的畔裕,在循環(huán)中我們需要首先移動(dòng)到我們需要旋轉(zhuǎn)的方塊,然后旋轉(zhuǎn)乖订,最后繪制這個(gè)方塊扮饶。修改循環(huán)中的代碼如下:
for i in range(12):
translate(200,0)
rotate(radians(t))
rect(0,0,50,50)
rotate(radians(360/12))
我們移動(dòng)到需要放置方塊的位置,旋轉(zhuǎn)坐標(biāo)系以使方塊旋轉(zhuǎn)乍构,然后繪制方塊甜无。
使用pushMatrix和popMatrix保存方向
但你運(yùn)行上面的代碼,你將會(huì)看到一些奇怪的動(dòng)作哥遮,這些方塊沒(méi)有圍繞著中心選擇毫蚓,只是在屏幕上一直在移動(dòng)。
這是因?yàn)楦淖兞俗鴺?biāo)系的原點(diǎn)同時(shí)也改變了整個(gè)坐標(biāo)系的方向昔善。當(dāng)移動(dòng)到方塊的位置之后,在移動(dòng)到下一個(gè)方塊之前畔乙,我們需要再回到方塊組成的圓的圓心君仆。可以使用另一個(gè)translate
函數(shù)返回到之前的狀態(tài)牲距,但是因?yàn)樾枰祷氐奶喾翟郏銜?huì)很容易搞混。幸運(yùn)的是有一個(gè)簡(jiǎn)單的辦法牍鞠。
Processing
有兩個(gè)內(nèi)置的函數(shù)用來(lái)保存坐標(biāo)系在某個(gè)點(diǎn)的方向并且返回:pushMatrix()
和popMatrix()
咖摹。在這個(gè)例子中,我們需要保存原點(diǎn)位于屏幕中心時(shí)的方向难述。要做到這一點(diǎn)萤晴,像下面一樣修改代碼:
for i in range(12):
pushMatrix()
translate(200,0)
rotate(radians(t))
rect(0,0,50,50)
popMatrix()
rotate(radians(360/12))
pushMatrix()
函數(shù)保存以方塊為圓的圓心的位置時(shí)的坐標(biāo)吐句,然后我們移動(dòng)到需要繪制方塊的位置,旋轉(zhuǎn)坐標(biāo)系店读,繪制方塊嗦枢。然后我們使用popMatrix()
返回保存的方向,然后重復(fù)繪制12個(gè)方塊屯断。
圍繞原點(diǎn)旋轉(zhuǎn)
前面的代碼能夠正常的工作文虏,但是這個(gè)旋轉(zhuǎn)看上去有點(diǎn)奇怪。這是因?yàn)?code>processing默認(rèn)定位矩形是定位在它的左上角殖演,旋轉(zhuǎn)也是圍繞著左上角氧秘。如果想要方塊圍繞中心旋轉(zhuǎn),可以再setup()函數(shù)中增加一行代碼:
rectMode(CENTER)
注意在編程中所有全部是大寫的代碼都非常重要趴久。加上rectMode(CENTER)
將使每個(gè)方塊的旋轉(zhuǎn)是圍繞著它的中心丸相。如果想要方塊兒旋轉(zhuǎn)的更快,修改rotate這一行朋鞍,增加里面的t的值已添。
rotate(radians(5*t))
在這兒,5
是旋轉(zhuǎn)的頻率滥酥,這就意味著程序在處理5×t
的時(shí)候更舞,旋轉(zhuǎn)的速度是原來(lái)的5
倍。修改之后運(yùn)行看一看坎吻。你還可以注釋掉循環(huán)外部的rotate(radians(t))
看看方塊在自己位置上轉(zhuǎn)動(dòng)的效果缆蝉。
使用translate()
、rotate()
創(chuàng)建動(dòng)態(tài)圖形是非常強(qiáng)大的技術(shù)瘦真,但是如果你弄錯(cuò)了執(zhí)行的順序它會(huì)產(chǎn)生意想不到的結(jié)果刊头。
創(chuàng)建交互式彩虹表格
你學(xué)習(xí)了如何使用循環(huán)和旋轉(zhuǎn)來(lái)創(chuàng)建不同的圖形,接下來(lái)我們會(huì)創(chuàng)建一個(gè)很漂亮的東西诸尽,一個(gè)方塊組成的表格原杂,里面的顏色會(huì)根據(jù)你鼠標(biāo)的顏色來(lái)變換,第1步是創(chuàng)建一個(gè)表格您机。
繪制對(duì)象的表格
數(shù)學(xué)編程穿肄、游戲編程中(譬如掃雷)都常常需要繪制表格,這個(gè)教程中后面章節(jié)中許多地方都會(huì)用到表格际看,所以我們將會(huì)學(xué)習(xí)寫繪制表格的代碼咸产,這些代碼應(yīng)該是可重用的,以備我們將來(lái)用到仲闽。作為開始脑溢,我們會(huì)制作一個(gè)12×12
的方塊的表格,這些方塊的尺寸和直徑的距離都是相等的赖欣。逐個(gè)繪制表格中的方塊看起來(lái)好像很費(fèi)時(shí)屑彻,但其實(shí)使用循環(huán)語(yǔ)句實(shí)現(xiàn)非常容易验庙。
打開一個(gè)新的processing
,保存文件名為colorGrid.pyde
酱酬。我們將會(huì)在白色的背景上繪制20×20的格子壶谒。繪制方塊需要使用rect
,還要用到for
循環(huán)膳沽。我們需要每隔30
個(gè)像素繪制25
個(gè)像素寬的方塊:
rect(30*x, 30*y, 25, 25)
隨著x
和y
變量的增加汗菜,方塊之間的距離是50個(gè)像素。我們?nèi)匀粡?code>setup()和draw()
函數(shù)開始:
def setup():
size(600,600)
def draw():
background(255)
上面的代碼設(shè)置的窗口尺寸是600×600
像素挑社,設(shè)置背景顏色為白色陨界。我們會(huì)寫一個(gè)嵌套的循環(huán),里面的兩個(gè)變量都會(huì)從0~19
痛阻,一共循環(huán)20
次菌瘪,因?yàn)槲覀冃枰?code>20行20
列:
def setup():
size(600,600)
def draw():
background(255)
for x in range(20):
for y in range(20):
rect(30*x,30*y,25,25)
現(xiàn)在我們已經(jīng)創(chuàng)建了20×20的表格,下面的任務(wù)是為他們?cè)黾宇伾?/p>
為對(duì)象增加彩虹顏色
Processing
的colorMode()
函數(shù)能夠幫我們?cè)黾雍芸岬念伾宓薄K梢栽?code>RGB和HSB
模式之間切換俏扩。RGB
就是紅色,綠色和藍(lán)色弊添。HSB
三個(gè)數(shù)字分別表示色調(diào)录淡、飽和度和亮度。這里我們需要改變的只是第1
個(gè)值油坝,也就是色調(diào)嫉戚,其他的兩個(gè)值都可以保持在最大值255
。下面的圖展示了如何通過(guò)只改變色調(diào)來(lái)制造出彩虹顏色效果澈圈。方塊下面的值就是它們的色調(diào)值彬檀,飽和度和亮度都是255
。
我們將方塊定位在(30x,30y)
瞬女,我們將要?jiǎng)?chuàng)建一個(gè)變量來(lái)測(cè)量鼠標(biāo)到這個(gè)位置的距離:
d = dist(30*x, 30*y, mouseX, mouseY)
Processing
中dist()
函數(shù)用于測(cè)量?jī)蓚€(gè)點(diǎn)之間的距離窍帝。在這個(gè)例子中,就是這個(gè)方塊和鼠標(biāo)之間的距離诽偷。程序把距離保存在變量d
中坤学,我們將會(huì)把它與色調(diào)聯(lián)系起來(lái)。
def setup():
size(600,600)
rectMode(CENTER)
colorMode(HSB)
def draw():
background(0)
translate(20,20)
for x in range(20):
for y in range(20):
d = dist(30*x, 30*y, mouseX, mouseY)
fill(0.5*d, 255, 255)
rect(30*x, 30*y, 25, 25)
我們使用了colorMode()
函數(shù)渤刃,把HSB
作為參數(shù)傳遞給它。在draw()
中贴膘,我們首先設(shè)置背景為黑色卖子,然后我們計(jì)算鼠標(biāo)和方塊的距離,下一行中刑峡,我們使用HSB
的值填充顏色洋闽。色調(diào)的值是距離的一半玄柠,飽和度和亮度的值都是255
。
唯一改變的就是色調(diào):根據(jù)鼠標(biāo)到方塊的距離改變色調(diào)值诫舅。我們使用dist()
測(cè)量?jī)蓚€(gè)點(diǎn)的距離羽利。
運(yùn)行代碼你會(huì)看到,方塊上的顏色會(huì)根據(jù)你所標(biāo)的位置的變化而變化刊懈。
使用三角形創(chuàng)建復(fù)雜圖形
我們現(xiàn)在學(xué)習(xí)怎樣使用triangle()
函數(shù)創(chuàng)建等邊三角形这弧。首先啟動(dòng)processing
,新建一個(gè)文件取名叫triangle
虚汛,輸入下面的代碼:
def setup():
size(600,600)
rectMode(CENTER)
t = 0
def draw():
global t
translate(width/2, height/2)
rotate(radians(t))
triangle(0,0,100,100,200,-200)
t += 0.5
上面的代碼中使用的知識(shí)都是我們已經(jīng)學(xué)習(xí)過(guò)的:創(chuàng)建了一個(gè)t變量匾浪,將坐標(biāo)系移動(dòng)到我們想繪制三角形的位置,旋轉(zhuǎn)坐標(biāo)系卷哩,繪制三角形蛋辈,最后增加t的值。運(yùn)行代碼你將會(huì)看到下面的圖形:
三角形圍繞著它的一個(gè)端點(diǎn)旋轉(zhuǎn)将谊,因此三角形外邊的點(diǎn)組成了一個(gè)圓冷溶。你可能也發(fā)現(xiàn)了,這個(gè)三角形是一個(gè)直角三角形尊浓,它的一個(gè)角的角度是90度逞频,不是等邊三角形。
我們需要繪制等邊三角形眠砾,也就是說(shuō)每個(gè)邊的邊長(zhǎng)相等虏劲。還需要找到這個(gè)等邊三角形的中點(diǎn),使三角形圍繞著它的中心旋轉(zhuǎn)褒颈。要實(shí)現(xiàn)這些柒巫,我們需要確定等邊三角形的三個(gè)頂點(diǎn)的坐標(biāo)。想一想谷丸,在確定一個(gè)等邊三角形的中心之后堡掏,如何繪制這個(gè)等邊三角形?
30-60-90度三角形
要確定等邊三角形的三個(gè)頂點(diǎn)的坐標(biāo)刨疼,我們需要溫習(xí)一下你在幾何課上學(xué)到的直角三角形的知識(shí):30-60-90
度的三角形泉唁,是特殊的直角三角形】剑看下面的圖形:
這個(gè)等邊三角形是由三個(gè)相同的圖形組成亭畜。中間的點(diǎn)是這個(gè)三角形的中點(diǎn),也是里面三個(gè)相同的三角形的交點(diǎn)迎卤,它們?cè)谶@一點(diǎn)相交的角度是120
度拴鸵。在Processing
中繪制三角形,需要給triangle
函數(shù)提供6
個(gè)參數(shù):三個(gè)頂點(diǎn)的x
坐標(biāo)和y
坐標(biāo)。要找到上面圖形中三個(gè)頂點(diǎn)的坐標(biāo)劲藐,我們把上面的三角形中下面的部分一分為二八堡,就像下面的圖形一樣:
將下面的三角形分成相同的兩部分,就創(chuàng)建了兩個(gè)直角三角形聘芜,兩個(gè)直角三角形都是經(jīng)典的30-60-90
度的三角形兄渺。如果你沒(méi)有忘記幾何老師教給你的知識(shí),應(yīng)該還記得30-60-90
度的三角形汰现,邊長(zhǎng)可以表示為下面的圖形:
如果我們?cè)O(shè)這個(gè)小三角形中短的一邊邊長(zhǎng)為x
挂谍,那么斜邊的邊長(zhǎng)是2x
,另一條長(zhǎng)邊的邊長(zhǎng)是[圖片上傳失敗...(image-bb3423-1587535142394)]服鹅,大約是1.732x凳兵。我們將使用上面圖形中大三角形的中點(diǎn)到它的一個(gè)頂點(diǎn)的距離作為參數(shù)來(lái)創(chuàng)建一個(gè)函數(shù),這個(gè)距離正好是30-60-90度三角形中的斜邊企软。我們假設(shè)斜邊的長(zhǎng)度是length庐扫,短邊的長(zhǎng)度就是length÷2,長(zhǎng)邊的長(zhǎng)度就是 [圖片上傳失敗...(image-3224f3-1587535142394)]仗哨,如下面圖形顯示的那樣:
你已經(jīng)看到了30-60-90
度三角形形庭,其內(nèi)角分別是30
、60
和90
度厌漂,邊長(zhǎng)成比例萨醒。講到這兒,你應(yīng)該想起了勾股定理苇倡。
我們假設(shè)大的三角形中心到它任意一個(gè)頂點(diǎn)的距離是length
富纸,也就是30-60-90
三角形的斜邊。你要明白在這個(gè)特殊的三角形中各邊長(zhǎng)的比例旨椒,然后才能繪出這個(gè)三角形的各個(gè)頂點(diǎn)晓褪。右邊三角形中和30
度角相對(duì)的短邊的長(zhǎng)度總是等于斜邊的一半,長(zhǎng)邊的長(zhǎng)度等于短邊乘以[圖片上傳失敗...(image-f384fa-1587535142394)] 综慎。所以如果我們根據(jù)這個(gè)大三角形的中心點(diǎn)位置繪制等邊三角形的話涣仿,三個(gè)頂點(diǎn)的坐標(biāo)應(yīng)該如下圖所示:
如你所見,這個(gè)三角形的三條邊是由幾個(gè)30-60-90
三角形組成示惊,我們可以利用比例計(jì)算出這個(gè)大三角形的三個(gè)頂點(diǎn)離中心的距離好港。
繪制等邊三角形
現(xiàn)在你可以利用上面的方法求出等邊三角形的三個(gè)點(diǎn)的坐標(biāo),使用下面的代碼:
def setup():
size(600,600)
rectMode(CENTER)
t = 0
def draw():
global t
translate(width/2, height/2)
rotate(radians(t))
tri(200)
t += 0.5
def tri(length):
'''Draw an equilateral triangle
around center of triangle'''
triangle(0, -length,
-length*sqrt(3)/2, length/2,
length*sqrt(3)/2, length/2)
首先我們寫了自定義函數(shù)tri()米罚,這個(gè)函數(shù)只有一個(gè)參數(shù)length钧汹,length是從大三角形中分割的30-60-90度三角形的斜邊。然后我們使用計(jì)算的三個(gè)頂點(diǎn)繪制三角形录择。運(yùn)行代碼你會(huì)看到下面的圖形:
現(xiàn)在我們可以擦掉所有已經(jīng)繪制的三角形拔莱,通過(guò)在draw函數(shù)的第1行加入下面的代碼:
background(255)
這行代碼會(huì)擦掉原來(lái)繪制的旋轉(zhuǎn)的三角形类嗤,所以我們?cè)谄聊簧现皇O乱粋€(gè)等邊三角形。下來(lái)我們要在一個(gè)圓上繪制90個(gè)三角形辨宠,就像我們?cè)谶@一章中前面部分學(xué)過(guò)的,我們將使用rotate函數(shù)货裹。
繪制多個(gè)旋轉(zhuǎn)的三角形
現(xiàn)在你學(xué)會(huì)了如何繪制旋轉(zhuǎn)的單個(gè)三角形嗤形,我們需要找到將多個(gè)三角形放在一個(gè)圓上的辦法。這和前面學(xué)過(guò)的將方塊放在圓上的方法類似弧圆,這次我們使用tri
函數(shù)赋兵。輸入下面的代碼:
def setup():
size(600,600)
rectMode(CENTER)
t = 0
def draw():
background(255)
global t
translate(width/2, height/2)
for i in range(90):
rotate(radians(360/90))
pushMatrix()
translate(200,0)
rotate(radians(t))
tri(100)
popMatrix()
t += 0.5
def tri(length):
'''Draw an equilateral triangle
around center of triangle'''
noFill()
triangle(0, -length,
-length*sqrt(3)/2, length/2,
length*sqrt(3)/2, length/2)
在程序中我們使用for
循環(huán)重復(fù)繪制90
個(gè)三角形在同一個(gè)圓上,通過(guò)旋轉(zhuǎn)坐標(biāo)系360/90
來(lái)確保三角形之間的距離是相等的搔预。我們使用pullMatrix
在移動(dòng)坐標(biāo)系之前保存當(dāng)前坐標(biāo)系霹期。在循環(huán)結(jié)束之前,我們使用popMatrix
返回保存的坐標(biāo)系拯田。在tri
函數(shù)中历造,我們加入了noFill
函數(shù)設(shè)置三角形為透明。
現(xiàn)在我們繪制了90個(gè)旋轉(zhuǎn)的透明的三角形船庇,但是他們旋轉(zhuǎn)的方式完全一樣吭产,接下來(lái)我們要學(xué)習(xí)怎么讓每個(gè)三角形以自己的角度旋轉(zhuǎn),使圖形看上去更有趣鸭轮。
旋轉(zhuǎn)相移
我們可以使用相移改變?nèi)切涡D(zhuǎn)的方式臣淤,使每個(gè)三角形的旋轉(zhuǎn)角度和它的鄰居稍有不同,給圖形制造一種波浪的效果窃爷。循環(huán)中的每個(gè)三角形已經(jīng)被賦予了一個(gè)值邑蒋,就是i
。我們需要將i
加在t
上按厘,作為rotate
的參數(shù)医吊,就像這樣:
rotate(radians(t+i))
保存然后運(yùn)行,注意在圖形中的右側(cè)有一塊缺口刻剥。這個(gè)缺口的出現(xiàn)是因?yàn)榈?個(gè)三角形的相移和最后一個(gè)三角形的相移不匹配造成的遮咖。我們需要的圖形是完美的,平滑的造虏,因此需要是相移的角度是360度的倍數(shù)御吞。因?yàn)閳A中有90
個(gè)三角形,我們使用360÷90
漓藕,然后乘以i
陶珠。
rotate(radians(t+i*360/90))
360÷90=4
,我們完全可以直接把4
插入代碼中享钞,但是不建議這樣做揍诽,因?yàn)橐紤]以后也許會(huì)繪制不同數(shù)量的三角形【魅兀現(xiàn)在在運(yùn)行應(yīng)該能夠得到一個(gè)完美的圖案:
最后的工作
為了使圖形看上去更有趣,我們需要再調(diào)整一下相移的角度暑脆。在這里你可以自己將角度設(shè)成任意的數(shù)渠啤,看看圖形會(huì)有什么有趣的變化。
我們將會(huì)使相移的角度為i×2添吗,這會(huì)使每個(gè)三角形和它的鄰居相比差別更大一點(diǎn)沥曹。將rotate這一行的代碼修改成下面的樣子:
rotate(radians(t+2*i*360/90))
修改代碼之后運(yùn)行,你可以看到下面的圖案
若您喜歡請(qǐng)贊賞支持碟联。更多視頻內(nèi)容歡迎訪問(wèn)我的B站專欄妓美。