溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤

發(fā)布時(shí)間:2021-10-19 17:06:17 來(lái)源:億速云 閱讀:241 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤”吧!

光線追跡

得益于計(jì)算機(jī)的計(jì)算的能力,通過(guò)追蹤具有代表性的光線的傳播軌跡,可以更加精確地描述光學(xué)系統(tǒng)的性能,光線追跡方法也因此大展其能,諸如Zemax、tracepro等軟件便都提供了相應(yīng)的功能。

而建立在折射定律基礎(chǔ)之上的光線追跡方法,對(duì)數(shù)學(xué)功底要求較低,所以比較適合作為python初學(xué)者的入門項(xiàng)目。在接下來(lái)的這一章,希望通過(guò)對(duì)光線追跡的實(shí)現(xiàn),掌握python中的列表、元組、字典、集合等數(shù)據(jù)類型的基本概念,并且對(duì)面向?qū)ο笈c函數(shù)式編程有一個(gè)基本的了解。

幾何抽象

光線

光線追跡描述的是光線與光學(xué)元件接觸之后的行為變化,因此首先需要對(duì)光線與光學(xué)元件進(jìn)行刻劃。由于我們希望最終建立一個(gè)二維的光路系統(tǒng),光線既可能水平,也可能豎直,因此通過(guò) a x + b y + c = 0 來(lái)表示一條光線。即只需$a b c $這三個(gè)數(shù)字,便可以確定二維空間中的一條直線。

在python中,可以通過(guò)序列-list來(lái)表示一組數(shù)據(jù),在list中,每個(gè)元素都分配一個(gè)數(shù)字作為索引,可以通過(guò)索引來(lái)提取或改變list中的值。需要注意的是,和諸多編程語(yǔ)言類似,python中的索引也是從0開始的。所以我們可以在python中新建一個(gè)變量來(lái)表示一條過(guò)原點(diǎn)斜率為1的直線:

>>> abc=[1,-1,0]    #在python中,list用方括號(hào)表示
>>> type(abc)       #type函數(shù)可以返回?cái)?shù)據(jù)類型
<class 'list'>
>>> abc[0]          #在python中,用方括號(hào)進(jìn)行索引
1
>>> abc[1] = 5      #list中的值可以更改
>>> abc[-1]         #在python中,索引-1往往表示倒數(shù)第一個(gè)值
0
>>> abc             #修改后的abc
[1, 5, 0]

當(dāng)然,光線實(shí)質(zhì)上是一種有源的射線,所以需要對(duì)直線方程 a x + b y + c = 0 進(jìn)行符號(hào)約定,進(jìn)而明確其方向性。
考慮到[a,b,c]與[-a,-b,-c]可以表示同一條直線,所以我們可以通過(guò) a 和 b的正負(fù)號(hào)來(lái)表明其方向。通過(guò)射線終點(diǎn)所在象限對(duì)[a,b]的正負(fù)號(hào)進(jìn)行限定,可以得到幾組不同的符號(hào)約定,在此我們選取如下約定:

Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤

可以看到第一、三條射線的方程表示同一條直線,但由于引入符號(hào)約定,所以我們可以區(qū)分其方向上的差別,從而可以判斷這條光線是否會(huì)與某一光學(xué)元件相交。

如果希望繪制出一條光線,可以調(diào)用python的UI庫(kù)wxpython,為了不影響內(nèi)容的連貫性,這種方法會(huì)在后面統(tǒng)一講解。

除了這里所推薦的直線的abc表示法,我們還可以通過(guò)始點(diǎn)與角度來(lái)對(duì)光線進(jìn)行表示,我們同樣可以使用三個(gè)參數(shù)[x0,y0,theta]。但是在進(jìn)行計(jì)算的時(shí)候,需要先將其轉(zhuǎn)換成為[a,b,c]的表示方法,因此需要定義轉(zhuǎn)換函數(shù),即通過(guò)初始點(diǎn)和角度生成射線的函數(shù),考慮到此前的符號(hào)約定,其轉(zhuǎn)換公式為

Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤

需要注意的一點(diǎn)是,這里需要調(diào)用numpy包來(lái)使用三角函數(shù)。

import numpy as np
x0,y0,theta = [0,0,np.pi/4]     #np.pi即圓周率
abc = [np.sin(theta),           #在python中,括號(hào)內(nèi)換行可以不用標(biāo)記
      -np.cos(theta),
      -(np.sin(theta)*x0-np.cos(theta)*y0)]

由于這個(gè)方法可能會(huì)被經(jīng)常使用,所以可以封裝成函數(shù),在python中,通過(guò)關(guān)鍵字def進(jìn)行函數(shù)的定義。對(duì)于參數(shù)個(gè)數(shù)和返回值的個(gè)數(shù)以及數(shù)據(jù)類型幾乎沒有限制。故可以寫為

import numpy as np
def getABC(x0,y0,theta):    #函數(shù)定義格式為 def 函數(shù)名(傳入?yún)?shù)):
    a = np.sin(theta)       #函數(shù)下方需要進(jìn)行縮進(jìn)
    b = -np.cos(theta)
    c = -(np.sin(theta)*x0-np.cos(theta)*y0)
return a,b,c                #在python中,通過(guò)return返回abc參數(shù)

也可以寫為

import numpy as np
def getABC(x0,y0,theta):
    return [np.sin(theta),      #在括號(hào)內(nèi)可以直接換行
            -np.cos(theta),
            -(np.sin(theta)*x0-np.cos(theta)*y0)]

在命令行中調(diào)用

>>> import test
>>> import numpy as np
>>> test.getABC(0,0,-np.pi/4)
[-0.7071067811865476, -0.7071067811865476, 0.0]
線段與圓弧

在光學(xué)系統(tǒng)中,最常見的光學(xué)器件便是平面鏡和透鏡,則其在入射光線子午面上的投影可拆解為線段和圓弧。

對(duì)于線段,可以非常直觀地通過(guò)兩個(gè)點(diǎn)進(jìn)行表示。在python中,除了列表之外,可以用元組(tuple)來(lái)表示序列,不同之處在于元組的元素不能修改。在此,用飽含兩個(gè)元素的元組來(lái)表示一個(gè)點(diǎn),將兩個(gè)點(diǎn)組成列表來(lái)表示線段:

>>> a = (0,0)       #在python中,元組用小括號(hào)表示
>>> b = (1,1)
>>> seg = [a,b]     #列表中的元素可以有不同的類型
>>> seg
[(0, 0), (1, 1)]
>>>

圓可以通過(guò)圓心與半徑來(lái)表示,簡(jiǎn)潔而利于計(jì)算。圓弧則可以通過(guò)圓與角度來(lái)表示。但是作為光學(xué)元件的組成部分,為了便于后面的處理,其表現(xiàn)形式最好與線段相似,即通過(guò)三點(diǎn)即A、B、C來(lái)確認(rèn)一段圓弧。

Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤

但是具體計(jì)算的過(guò)程中往往需要將圓弧轉(zhuǎn)換成圓的表達(dá)形式進(jìn)行操作,所以定義函數(shù)arc2cir來(lái)實(shí)現(xiàn)這個(gè)功能。由于其數(shù)學(xué)過(guò)程過(guò)于簡(jiǎn)單,故只對(duì)一些命令進(jìn)行說(shuō)明,其中np.lialg為numpy的線性代數(shù)包,np.linalg.norm為求范數(shù),np.linalg.norm(a-b)相當(dāng)于求a、b兩點(diǎn)之間的距離。

def arc2cir(arc):
    arc = np.array(arc)     #list不能進(jìn)行數(shù)組運(yùn)算,需要轉(zhuǎn)成np.array的形式
    dCD = np.linalg.norm(1/2*(arc[0]+arc[1])-arc[2])  #CD長(zhǎng)度
    dBC2 = np.sum(np.square(arc[1]-arc[2]))           #BC**2
    radius = 0.5*dBC2/dCD                             #圓半徑
    theta = (arc[2]-1/2*(arc[0]+arc[1]))/dCD          #三角函數(shù)值
    zero = arc[2]-radius*theta
    return list(zero)+[radius]                        #列表相加為其內(nèi)部元素的合并

需要注意的是,在python中,listtuple都不支持整體上的數(shù)學(xué)計(jì)算,這很容易理解,因?yàn)槎咧写鎯?chǔ)的不一定是數(shù)字,而可能是其他的什么東西。格式不同,自然無(wú)法計(jì)算。因此在考慮計(jì)算之前,需要將二者轉(zhuǎn)換成numpy.array這種數(shù)組格式。

列表、元組、數(shù)組之間的轉(zhuǎn)換非常簡(jiǎn)單而直觀。

import numpy as np
>>> lis = [1,2,3]
>>> tup = tuple(lis)
>>> arr = np.array(tup)
>>> arr
array([1, 2, 3])
>>> lis
[1, 2, 3]
>>> tup
(1, 2, 3)

到此,相信大家對(duì)“Python光學(xué)仿真教程怎么實(shí)現(xiàn)光線追蹤”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI