仍未解決 - 問題在於paralaxtrace2方法,在更新通過兩個鏡片錯誤使用類A的兩個對象A1和A2作爲B類的對象B1上的函數的參數:B1不更新屬性?
我試圖建立一個與光線跟蹤使用Python兩種不同類型的傳播之間的射線對象:(含有平面sphericalrefraction,凸和凹透鏡)和輸出平面(僅包含一個無限大平面),從一類光學繼承而來。在這些類的每一個下,有方法截距(計算具有給定方向和點的光線與透鏡相交的位置),並折射(使用光線的最新方向矢量計算光線的新方向矢量)。它們在每個光學元素中都有傳播方法,它們將最新的點作爲截距()點,將最新的方向作爲折射()方向。該射線僅包含具有x,y,z元素的1d陣列,一個用於點和一個用於方向,例如
class Ray:
def __init__(self, p = [0.0, 0.0, 0.0], k = [0.0, 0.0, 0.0]):
self._points = [np.array(p)]
self._directions = [np.array(k)/np.sqrt(sum(n**2 for n in k))]
self.checklength()
def p(self):
return self._points[len(self._points)-1]
def k(self):
return self._directions[len(self._directions)-1]
class SphericalRefraction(OpticalElement):
def __init__(self, z0 = 0.0, c = 0.0, n1 = 1.0, n2 = 1.0, ar = 0.0):
self.z0 = z0
self.c = c
self.n1 = n1
self.n2 = n2
self.ar = ar
self.R = self.radius()
self.s = self.surface()
self.centre = self.centre()
def intercept(self, ray):
ar_z = np.sqrt(self.R**2 - self.ar**2)
#ar_z = distance from aperture radius z intercept to centre of sphere
r = ray.p() - self.centre
r_mag = np.sqrt(sum(n**2 for n in r))
rdotk = np.dot(r, ray.k())
if (rdotk**2 - r_mag**2 + self.R**2) < 0:
return None
else:
l1 = -rdotk + np.sqrt(rdotk**2 - r_mag**2 + self.R**2)
l2 = -rdotk - np.sqrt(rdotk**2 - r_mag**2 + self.R**2)
lplane = (self.z0 - ray.p()[2])/ray.k()[2]
if self.s == "convex":
if (rdotk**2 - r_mag**2 + self.R**2) == 0:
if self.centre[2] - ar_z >= (ray.p() + -rdotk*ray.k())[2]:
return ray.p() + -rdotk*ray.k()
def refract(self, ray):
n_unit = self.unitsurfacenormal(ray)
k1 = ray.k()
ref = self.n1/self.n2
ndotk1 = np.dot(n_unit, k1)
if np.sin(np.arccos(ndotk1)) > (1/ref):
return None
else:
return ref*k1 - (ref*ndotk1 - np.sqrt(1- (ref**2)*(1-ndotk1**2)))*n_unit
def propagate_ray(self, ray):
if self.intercept(ray) is None or self.refract(ray) is None:
return "Terminated"
else:
p = self.intercept(ray)
k2 = self.refract(ray)
ray.append(p, k2)
return "Final Point: %s" %(ray.p()) + " and Final Direction: %s" %(ray.k())
當我穿過1個sphericalrefraction和一個輸出平面上的兩個射線,我用這個方法:
DEF paralaxtrace(個體,雷,SphericalRefraction,OutputPlane): SphericalRefraction.propagate_ray(個體) SphericalRefraction .propagate_ray(雷) OutputPlane.propagate_ray(個體經營) OutputPlane.propagate_ray(雷) self.plotparalax(雷)
我得到的是一張看起來像這樣,例如:
我已經實現了這種方法,通過兩個球面反射對象和一個輸出平面,並且由於某種原因,它不會在球面折射元素之間更新?
def paralaxtrace2(self, Ray, sr1, sr2, OutputPlane):
sr1.propagate_ray(self)
sr1.propagate_ray(Ray)
sr2.propagate_ray(self)
sr2.propagate_ray(Ray)
OutputPlane.propagate_ray(self)
OutputPlane.propagate_ray(Ray)
self.plotparalax(Ray)
正如你可以看到,攔截/折射方法總是使用ray.p(),所以最新的點,但由於某些原因,它實際上並沒有新的點/方向在交叉和折射與追加第二個球形元件?該圖看起來與上面的完全一樣。
我錯了嗎?還有其他問題嗎?如果您需要更多我的代碼,請讓我知道,因爲我已經盡力瞭解這個問題。
編輯:
在控制檯:
>> import raytracer as rt
>> lense1 = rt.SphericalRefraction(50, .02, 1, 1.5168, 49.749)
>> lense2 = rt.SphericalRefraction(60, .02, 1, 1.5168, 49.749)
>> ray = rt.Ray([.1,.2,0],[0,0,1])
>> ray.paralaxtrace2(rt.Ray([-0.1, -0.2, 0],[0,0,1]), lense1, lense2, rt.OutputPlane(100))
x, y of 'ray' = [0.0, 50.000500002500019, 100.0] [0.20000000000000001, 0.20000000000000001, -0.13186017048586818]
x, y of passed ray: [0.0, 50.000500002500019, 100.0] [-0.20000000000000001, -0.20000000000000001, 0.13186017048586818]
對於這一點,我得到上面的曲線圖。它應該做的是,因爲第二個凸透鏡在60°,它應該更加聚焦射線。相反,它看起來沒有任何反應。
編輯2:
問題似乎並不在光線的可變默認參數;我仍然得到同樣的錯誤。出於某種原因,它將更多的鏡頭作爲參數添加到函數中。在每個透鏡中的傳播之間,它不更新座標。這是否與透鏡類中的可變默認參數錯誤有關?
更少的代碼會比越多越好。你可以創建一個玩具示例,只是演示對象/參數/屬性交互,不像你期望的那樣工作嗎? –
我無法真正理解此代碼(例如,我不明白爲什麼要將'Ray'和'OutputPlane'類作爲參數傳遞給'paralaxtrace2'),但在'Ray中使用默認的可變參數。 __init__'總是一個紅旗:請參閱[這個問題](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)一個很好的解釋。 –
+1 @ DanielRoseman對可變默認參數的預感是您問題的原因。 –