python光學(xué)仿真面向?qū)ο蠊鈱W(xué)元件類(lèi)的實(shí)現(xiàn)
光學(xué)元件類(lèi)
平面反射鏡是一種極為簡(jiǎn)單的模型,因?yàn)槲覀冎恍枰紤]一個(gè)平面即可。但是除此之外的其他光學(xué)元件,可能會(huì)變得有些復(fù)雜:我們必須考慮光在入射面和出射面的行為。
這當(dāng)然是一句廢話,而且我們也有了一個(gè)初步的解決方案:將光學(xué)元件拆成前表面和后表面即可。如果光需要在光學(xué)元件中反射多次,那就將光學(xué)元件拆成需要反射次數(shù)的表面?zhèn)€數(shù)即可,完美而無(wú)腦。
這說(shuō)明我們已經(jīng)熟悉了程序員的思維,我們眼中的世界已經(jīng)不再是一個(gè)所見(jiàn)即所得的世界,我們看到的是一個(gè)個(gè)抽象零部件的表現(xiàn)。但是也不要驚慌,程序員和正常人也未必有很大的區(qū)別,因?yàn)槲覀兂丝梢詫⑦@個(gè)世界拆解,也可以將拆解之后的部件重新構(gòu)造回這個(gè)世界。
嘗試著將問(wèn)題想得復(fù)雜一些,光學(xué)系統(tǒng)中有許多光學(xué)元件,光會(huì)透過(guò)每個(gè)光學(xué)元件很多次,而且每次的入射點(diǎn)、出射點(diǎn)都會(huì)有一定的偏差。由于光學(xué)元件可能會(huì)對(duì)光的能量有所吸收,從而引起發(fā)熱。而且每次的入射點(diǎn)、出射點(diǎn)不同,則發(fā)熱位置也不一樣。由于發(fā)熱會(huì)導(dǎo)致光學(xué)元件發(fā)生形變,所以下一次光和光學(xué)元件的作用也會(huì)發(fā)生變化。
也就是說(shuō),對(duì)于每個(gè)光學(xué)元件來(lái)說(shuō),除了有固定的前表面、后表面,還有入射點(diǎn)、出射點(diǎn)、發(fā)熱、形變等不斷變化的參數(shù)。這樣的一個(gè)過(guò)于實(shí)際的問(wèn)題促使我們構(gòu)造一種更加貼近現(xiàn)實(shí)的數(shù)據(jù)類(lèi)型,換句話說(shuō),我們要?jiǎng)?chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象能夠封裝各種變量和功能,我們輸入一個(gè)參量,這個(gè)對(duì)象的狀態(tài)也會(huì)跟著發(fā)生變化。
這就是所謂的面向?qū)ο蟆?/p>
class Opti(): def __init__(self,edge1,edge2): self.edge1 = edge1 self.edge2 = edge2
在上例中,我們定義了一個(gè)光學(xué)元件類(lèi),這個(gè)光學(xué)元件有兩個(gè)表面,這兩個(gè)表面既可以是平面,也可以說(shuō)弧面。這樣,我們就建立了一個(gè)類(lèi)。其中,__init__
為初始化方法,self
表示我們所創(chuàng)建的這個(gè)類(lèi)本身。一般來(lái)說(shuō),如果類(lèi)中的方法不加修飾符的話,就必須將self
當(dāng)作第一個(gè)參數(shù)。
self.edge1
表示這個(gè)Opti
類(lèi)中,有一個(gè)成員的名字叫edge1
。當(dāng)這個(gè)類(lèi)被初始化的時(shí)候,我們就可以對(duì)其進(jìn)行賦值了。
有些元件可能只有一個(gè)表面,比如全反鏡;有些可能有多個(gè)表面,比如偏振立方體。而且,我們?cè)谧鰧?shí)驗(yàn)的時(shí)候,也需要對(duì)不同的光學(xué)元件進(jìn)行比較,從而得到最好的實(shí)驗(yàn)結(jié)果。所以,如果我們想改變已經(jīng)建好的光學(xué)元件,應(yīng)該怎么辦呢?
其實(shí)很簡(jiǎn)單,只要增加一個(gè)方法,使得可以插入或者刪除新的表面即可。
#文件Opti.py class Opti(): def __init__(self,edges=[[(0,-1),(0,1)],[(0,1),(0,-1),(1/2,0)]]): self.edges = [{'index':i,'dots':edges[i]} for i in range(len(edges))] #edge格式為(dot1,dot2,...) def insertEdge(self,edge,albedo=0): self.edges.append( {'index':len(self.edges),'dots':edge}) #可接受編號(hào)和點(diǎn)集 def delEdge(self,edge): try: if isinstance(edge,list):#如果edge的類(lèi)型是list for edg in self.edges: if edg['dots']==edge:edge = edg['index'] del self.edges[edge] except: print("no this edge")
在上面的代碼中,可以看到初始化函數(shù)被預(yù)設(shè)了一些值,這點(diǎn)與普通函數(shù)并無(wú)二致。我們可以看到,默認(rèn)插入的兩個(gè)曲面分別是平面[(0,-1),(0,1)]
和弧面[(0,1),(0,-1),(1/2,0)]
,可見(jiàn)默認(rèn)生成一個(gè)平凸鏡。
成員變量self.edges
即光學(xué)表面的列表,每個(gè)光學(xué)表面有兩個(gè)參數(shù),分別是索引index
和點(diǎn)集dots
。由此前的光學(xué)抽象可知,當(dāng)點(diǎn)對(duì)中有兩個(gè)點(diǎn)的時(shí)候,代表平面;有三個(gè)點(diǎn)的時(shí)候,代表弧面。
方法insertEdge
為插入一個(gè)光學(xué)表面,其中,編號(hào)為這個(gè)光學(xué)表面在self.edges
中的索引號(hào);delEdge
顧名思義為刪除某個(gè)光學(xué)表面。如果傳入的edge
為一個(gè)列表,則說(shuō)明傳入的是一個(gè)參數(shù)確定的曲面,此時(shí)通過(guò)遍歷self.edges
找到這個(gè)表面,并得到其索引。
如果傳入的參數(shù)為一個(gè)單值,那么說(shuō)明傳入的是索引號(hào),所以直接刪除即可。
在這個(gè)方法中,使用了一種新的代碼塊try:...except...
,這是一種異常機(jī)制,即嘗試運(yùn)行try:
塊中的代碼,如果運(yùn)行失敗,則執(zhí)行except
。如果我們沒(méi)能執(zhí)行成功delEdge
,則說(shuō)明我們輸入的表面并不在這個(gè)光學(xué)元件中,所以輸出"no this edge"
。
這好像是第一次看到print
這個(gè)命令呢,一般來(lái)說(shuō)這應(yīng)該是最先接觸到的函數(shù),畢竟對(duì)于大多數(shù)程序員來(lái)說(shuō),敲下的第一行代碼就是
print("hello world") print('hello world')
同時(shí),我們除了數(shù)值類(lèi)型之外,又認(rèn)識(shí)了另一種數(shù)據(jù)類(lèi)型,即字符。在python中,可以通過(guò)雙引號(hào)或者單引號(hào)來(lái)表示單個(gè)字符或者字符串。即上述的hello world代碼中,兩行均正確,而且沒(méi)什么區(qū)別。
現(xiàn)在,我們已經(jīng)寫(xiě)了一個(gè)類(lèi),于是可以創(chuàng)建一個(gè)對(duì)象,在命令行中輸入:
>>> from Opti import Opti >>> Opti.__name__#這是什么鬼 'Opti' >>> x = Opti()#創(chuàng)建對(duì)象,由于未輸入?yún)?shù),故皆為默認(rèn)值 >>> x.edges#現(xiàn)實(shí)類(lèi)成員 [{'index': 0, 'dots': [(0, -1), (0, 1)]}, {'index': 1, 'dots': [(0, 1), (0, -1), (0.5, 0)]}] >>> x.delEdge(1) #調(diào)用類(lèi)方法 >>> x.edges#果然少了一個(gè)邊 [{'index': 0, 'dots': [(0, -1), (0, 1)]}] >>> x.delEdge(1) #刪除不存在的邊是不可能的 no this edge >>>
首先,from Opti import Opti
的這兩個(gè)Opti并不相同,前者代表包`Opti.py',后者代表Opti.py中的類(lèi)'Opti',import之后便可以調(diào)用了。
然后出現(xiàn)了一個(gè)比較吊詭的事情,我們?cè)陬?lèi)中并沒(méi)有定義__name__
,然而調(diào)用之后卻有值產(chǎn)生。
請(qǐng)勿驚慌,其實(shí)是老熟人了??梢詫?code>__name__理解為python內(nèi)部的內(nèi)置屬性,當(dāng)我們直接執(zhí)行某一.py文件時(shí),這個(gè)__name__
的值為__main__
,否則的話就是類(lèi)的名字。所以,到這個(gè)時(shí)候,我們似乎應(yīng)該能明白入口函數(shù)的真正意義了吧。
繼續(xù)向下,幾乎所有的事情就都不出所料了。
以上就是python光學(xué)仿真面向?qū)ο蠊鈱W(xué)元件類(lèi)的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于python光學(xué)元件類(lèi)的實(shí)現(xiàn)的資料請(qǐng)關(guān)注本站其它相關(guān)文章!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。