ModuleMirror
44class MirrorPlane: 45 """ 46 A plane mirror. 47 48 Attributes 49 ---------- 50 support : ART.ModuleSupport.Support 51 Mirror support 52 type : str = 'Plane Mirror' 53 Human readable mirror type 54 Methods 55 ------- 56 MirrorPlane.get_normal(Point) 57 58 MirrorPlane.get_centre() 59 60 MirrorPlane.get_grid3D(NbPoints) 61 """ 62 63 def __init__(self, Support): 64 """ 65 Create a plane mirror on a given Support. 66 67 Parameters 68 ---------- 69 Support : ART.ModuleSupport.Support 70 71 """ 72 self.support = Support 73 self.type = "Plane Mirror" 74 75 def _get_intersection(self, Ray): 76 """Return the intersection point between Ray and the xy-plane.""" 77 t = -Ray.point[2] / Ray.vector[2] 78 Intersect = Ray.vector * t + Ray.point 79 if t > 0 and self.support._IncludeSupport(Intersect): 80 PointIntersection = Ray.vector * t + Ray.point 81 else: 82 PointIntersection = None 83 84 return PointIntersection 85 86 def get_normal(self, Point: np.ndarray): 87 """Return normal unit vector in point 'Point' on the plane mirror.""" 88 Normal = np.array([0, 0, 1]) 89 return Normal 90 91 def get_centre(self): 92 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 93 return np.array([0, 0, 0]) 94 95 def get_grid3D(self, NbPoint: int, **kwargs): 96 """ 97 Get grid of points on mirror surface. 98 99 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 100 sampling the support in a number NbPoints of points. 101 """ 102 E = "edges" in kwargs and kwargs["edges"] 103 ListCoordXYZ = [] 104 contour = int(round(0.1 * NbPoint)) 105 contours = self.support._Contour_points(contour, **kwargs) 106 if E: 107 contours, contour_edges = contours 108 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 109 for k in ListCoordXY: 110 z = 0 111 ListCoordXYZ.append(np.array([k[0], k[1], z])) 112 if E: 113 return ListCoordXYZ, contour_edges 114 115 return ListCoordXYZ
A plane mirror.
Attributes
support : ART.ModuleSupport.Support
Mirror support
type : str = 'Plane Mirror'
Human readable mirror type
Methods
MirrorPlane.get_normal(Point)
MirrorPlane.get_centre()
MirrorPlane.get_grid3D(NbPoints)
86 def get_normal(self, Point: np.ndarray): 87 """Return normal unit vector in point 'Point' on the plane mirror.""" 88 Normal = np.array([0, 0, 1]) 89 return Normal
Return normal unit vector in point 'Point' on the plane mirror.
91 def get_centre(self): 92 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 93 return np.array([0, 0, 0])
Return 3D coordinates of the point on the mirror surface at the center of its support.
95 def get_grid3D(self, NbPoint: int, **kwargs): 96 """ 97 Get grid of points on mirror surface. 98 99 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 100 sampling the support in a number NbPoints of points. 101 """ 102 E = "edges" in kwargs and kwargs["edges"] 103 ListCoordXYZ = [] 104 contour = int(round(0.1 * NbPoint)) 105 contours = self.support._Contour_points(contour, **kwargs) 106 if E: 107 contours, contour_edges = contours 108 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 109 for k in ListCoordXY: 110 z = 0 111 ListCoordXYZ.append(np.array([k[0], k[1], z])) 112 if E: 113 return ListCoordXYZ, contour_edges 114 115 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
119class MirrorSpherical: 120 """ 121 Spherical mirror surface with eqn. $x^2 + y^2 + z^2 = R^2$, where $R$ is the radius. 122 123 ![Illustration of a spherical mirror.](sphericalmirror.svg) 124 125 Attributes 126 ---------- 127 radius : float 128 Radius of curvature. A postive value for concave mirror, a negative value for a convex mirror. 129 130 support : ART.ModuleSupport.Support 131 132 type : str SphericalCC Mirror' or SphericalCX Mirror' 133 134 Methods 135 ------- 136 MirrorSpherical.get_normal(Point) 137 138 MirrorSpherical.get_centre() 139 140 MirrorSpherical.get_grid3D(NbPoints) 141 142 """ 143 144 def __init__(self, Radius, Support): 145 """ 146 Construct a spherical mirror. 147 148 Parameters 149 ---------- 150 Radius : float 151 The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror. 152 153 Support : ART.ModuleSupport.Support 154 155 """ 156 if Radius < 0: 157 self.type = "SphericalCX Mirror" 158 self.radius = -Radius 159 else: 160 self.type = "SphericalCC Mirror" 161 self.radius = Radius 162 163 self.support = Support 164 165 def _get_intersection(self, Ray): 166 """Return the intersection point between the ray and the sphere.""" 167 a = np.dot(Ray.vector, Ray.vector) 168 b = 2 * np.dot(Ray.vector, Ray.point) 169 c = np.dot(Ray.point, Ray.point) - self.radius**2 170 171 Solution = mgeo.SolverQuadratic(a, b, c) 172 Solution = mgeo.KeepPositiveSolution(Solution) 173 174 ListPointIntersection = [] 175 for t in Solution: 176 Intersect = Ray.vector * t + Ray.point 177 if Intersect[2] < 0 and self.support._IncludeSupport(Intersect): 178 ListPointIntersection.append(Intersect) 179 180 return _IntersectionRayMirror(Ray.point, ListPointIntersection) 181 182 def get_normal(self, Point): 183 """Return the normal unit vector on the spherical surface at point Point.""" 184 Gradient = Point 185 return mgeo.Normalize(-Gradient) 186 187 def get_centre(self): 188 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 189 return np.array([0, 0, -self.radius]) 190 191 def get_grid3D(self, NbPoint, **kwargs): 192 """ 193 Get grid of points on mirror surface. 194 195 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 196 sampling the support in a number NbPoints of points. 197 """ 198 E = "edges" in kwargs and kwargs["edges"] 199 ListCoordXYZ = [] 200 contour = int(round(0.1 * NbPoint)) 201 contours = self.support._Contour_points(contour, **kwargs) 202 if E: 203 contours, contour_edges = contours 204 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 205 for k in ListCoordXY: 206 z = -np.sqrt(self.radius**2 - (k[0] ** 2 + k[1] ** 2)) 207 ListCoordXYZ.append(np.array([k[0], k[1], z])) 208 if E: 209 return ListCoordXYZ, contour_edges 210 return ListCoordXYZ
Spherical mirror surface with eqn. $x^2 + y^2 + z^2 = R^2$, where $R$ is the radius.
Attributes
radius : float
Radius of curvature. A postive value for concave mirror, a negative value for a convex mirror.
support : ART.ModuleSupport.Support
type : str SphericalCC Mirror' or SphericalCX Mirror'
Methods
MirrorSpherical.get_normal(Point)
MirrorSpherical.get_centre()
MirrorSpherical.get_grid3D(NbPoints)
144 def __init__(self, Radius, Support): 145 """ 146 Construct a spherical mirror. 147 148 Parameters 149 ---------- 150 Radius : float 151 The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror. 152 153 Support : ART.ModuleSupport.Support 154 155 """ 156 if Radius < 0: 157 self.type = "SphericalCX Mirror" 158 self.radius = -Radius 159 else: 160 self.type = "SphericalCC Mirror" 161 self.radius = Radius 162 163 self.support = Support
Construct a spherical mirror.
Parameters
Radius : float
The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror.
Support : ART.ModuleSupport.Support
182 def get_normal(self, Point): 183 """Return the normal unit vector on the spherical surface at point Point.""" 184 Gradient = Point 185 return mgeo.Normalize(-Gradient)
Return the normal unit vector on the spherical surface at point Point.
187 def get_centre(self): 188 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 189 return np.array([0, 0, -self.radius])
Return 3D coordinates of the point on the mirror surface at the center of its support.
191 def get_grid3D(self, NbPoint, **kwargs): 192 """ 193 Get grid of points on mirror surface. 194 195 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 196 sampling the support in a number NbPoints of points. 197 """ 198 E = "edges" in kwargs and kwargs["edges"] 199 ListCoordXYZ = [] 200 contour = int(round(0.1 * NbPoint)) 201 contours = self.support._Contour_points(contour, **kwargs) 202 if E: 203 contours, contour_edges = contours 204 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 205 for k in ListCoordXY: 206 z = -np.sqrt(self.radius**2 - (k[0] ** 2 + k[1] ** 2)) 207 ListCoordXYZ.append(np.array([k[0], k[1], z])) 208 if E: 209 return ListCoordXYZ, contour_edges 210 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
214class MirrorParabolic: 215 r""" 216 Parabolic mirror. 217 218 A paraboloid with vertex at the origin [0,0,0] and symmetry axis z, 219 with the center of the support shifted off axis along the x-direction. 220 Its eqn. is therefore $z = \frac{1}{2p}[(x+x_c)^2 + y^2]$ where $p$ is the semi latus rectum, 221 equal to twice the focal lenght of the *mother* parabola (i.e. off-axis angle $\alpha=0$). 222 223 The effective focal length $f_\mathrm{eff}$ is related to the semi latus rectum by 224 $ p = f_\mathrm{eff} (1+\cos\alpha)$, where $\alpha$ is the off-axis angle. 225 226 ![Illustration of a parabolic mirror.](parabola.svg) 227 228 Attributes 229 ---------- 230 offaxisangle : float 231 Off-axis angle of the parabola. Modifying this also updates p, keeping feff constant. 232 Attention: The off-axis angle must be *given in degrees*, but is stored and will be *returned in radian* ! 233 234 feff : float 235 Effective focal length of the parabola in mm. Modifying this also updates p, keeping offaxisangle constant. 236 237 p : float 238 Semi latus rectum of the parabola in mm. Modifying this also updates feff, keeping offaxisangle constant. 239 240 support : ART.ModuleSupport.Support 241 242 type : str 'Parabolic Mirror'. 243 244 Methods 245 ------- 246 MirrorParabolic.get_normal(Point) 247 248 MirrorParabolic.get_centre() 249 250 MirrorParabolic.get_grid3D(NbPoints) 251 252 """ 253 254 def __init__(self, FocalEffective: float, OffAxisAngle: float, Support): 255 """ 256 Initialise an Parabolic mirror. 257 258 Parameters 259 ---------- 260 FocalEffective : float 261 Effective focal length of the parabola in mm. 262 263 OffAxisAngle : float 264 Off-axis angle *in degrees* of the parabola. 265 266 Support : ART.ModuleSupport.Support 267 268 """ 269 self._offaxisangle = np.deg2rad(OffAxisAngle) 270 self.support = Support 271 self.type = "Parabolic Mirror" 272 self._feff = FocalEffective # effective focal length 273 self._p = FocalEffective * ( 274 1 + np.cos(self.offaxisangle) 275 ) # semi latus rectum 276 277 @property 278 def offaxisangle(self): 279 """Return off-axis angle of parabolic mirror.""" 280 return self._offaxisangle 281 282 @offaxisangle.setter 283 def offaxisangle(self, OffAxisAngle): 284 self._offaxisangle = np.deg2rad(OffAxisAngle) 285 self._p = self._feff * ( 286 1 + np.cos(self._offaxisangle) 287 ) # make sure to always update p 288 289 @property 290 def feff(self): 291 """Get effective focal length.""" 292 return self._feff 293 294 @feff.setter 295 def feff(self, FocalEffective): 296 self._feff = FocalEffective 297 self._p = self._feff * ( 298 1 + np.cos(self._offaxisangle) 299 ) # make sure to always update p 300 301 @property 302 def p(self): 303 """Get simi-latus-rectum.""" 304 return self._p 305 306 @p.setter 307 def p(self, SemiLatusRectum): 308 self._p = SemiLatusRectum 309 self._feff = self._p / ( 310 1 + np.cos(self._offaxisangle) 311 ) # make sure to always update feff 312 313 def _get_intersection(self, Ray): 314 """Return the intersection point between the ray and the parabola.""" 315 ux = Ray.vector[0] 316 uy = Ray.vector[1] 317 uz = Ray.vector[2] 318 xA = Ray.point[0] 319 yA = Ray.point[1] 320 zA = Ray.point[2] 321 322 da = ux**2 + uy**2 323 db = 2 * (ux * xA + uy * yA) - 2 * self._p * uz 324 dc = xA**2 + yA**2 - 2 * self._p * zA 325 326 Solution = mgeo.SolverQuadratic(da, db, dc) 327 Solution = mgeo.KeepPositiveSolution(Solution) 328 329 ListPointIntersection = [] 330 for t in Solution: 331 Intersect = Ray.vector * t + Ray.point 332 if self.support._IncludeSupport(Intersect - self.get_centre()): 333 ListPointIntersection.append(Intersect) 334 335 return _IntersectionRayMirror(Ray.point, ListPointIntersection) 336 337 def get_normal(self, Point): 338 """Return the normal unit vector on the paraboloid surface at point Point.""" 339 Gradient = np.zeros(3) 340 Gradient[0] = -Point[0] 341 Gradient[1] = -Point[1] 342 Gradient[2] = self._p 343 return mgeo.Normalize(Gradient) 344 345 def get_centre(self): 346 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 347 return np.array( 348 [ 349 self.feff * np.sin(self.offaxisangle), 350 0, 351 self._p * 0.5 - self.feff * np.cos(self.offaxisangle), 352 ] 353 ) 354 355 def get_grid3D(self, NbPoint, **kwargs): 356 """ 357 Get grid of points on mirror surface. 358 359 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 360 sampling the support in a number NbPoints of points. 361 """ 362 E = "edges" in kwargs and kwargs["edges"] 363 ListCoordXYZ = [] 364 contour = int(round(0.1 * NbPoint)) 365 contours = self.support._Contour_points(contour, **kwargs) 366 if E: 367 contours, contour_edges = contours 368 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 369 xc = self.feff * np.sin(self.offaxisangle) 370 for k in ListCoordXY: 371 z = ((k[0] + xc) ** 2 + k[1] ** 2) / 2 / self._p 372 ListCoordXYZ.append(np.array([k[0] + xc, k[1], z])) 373 if E: 374 return ListCoordXYZ, contour_edges 375 return ListCoordXYZ
Parabolic mirror.
A paraboloid with vertex at the origin [0,0,0] and symmetry axis z, with the center of the support shifted off axis along the x-direction. Its eqn. is therefore $z = \frac{1}{2p}[(x+x_c)^2 + y^2]$ where $p$ is the semi latus rectum, equal to twice the focal lenght of the mother parabola (i.e. off-axis angle $\alpha=0$).
The effective focal length $f_\mathrm{eff}$ is related to the semi latus rectum by $ p = f_\mathrm{eff} (1+\cos\alpha)$, where $\alpha$ is the off-axis angle.
Attributes
offaxisangle : float
Off-axis angle of the parabola. Modifying this also updates p, keeping feff constant.
Attention: The off-axis angle must be *given in degrees*, but is stored and will be *returned in radian* !
feff : float
Effective focal length of the parabola in mm. Modifying this also updates p, keeping offaxisangle constant.
p : float
Semi latus rectum of the parabola in mm. Modifying this also updates feff, keeping offaxisangle constant.
support : ART.ModuleSupport.Support
type : str 'Parabolic Mirror'.
Methods
MirrorParabolic.get_normal(Point)
MirrorParabolic.get_centre()
MirrorParabolic.get_grid3D(NbPoints)
254 def __init__(self, FocalEffective: float, OffAxisAngle: float, Support): 255 """ 256 Initialise an Parabolic mirror. 257 258 Parameters 259 ---------- 260 FocalEffective : float 261 Effective focal length of the parabola in mm. 262 263 OffAxisAngle : float 264 Off-axis angle *in degrees* of the parabola. 265 266 Support : ART.ModuleSupport.Support 267 268 """ 269 self._offaxisangle = np.deg2rad(OffAxisAngle) 270 self.support = Support 271 self.type = "Parabolic Mirror" 272 self._feff = FocalEffective # effective focal length 273 self._p = FocalEffective * ( 274 1 + np.cos(self.offaxisangle) 275 ) # semi latus rectum
Initialise an Parabolic mirror.
Parameters
FocalEffective : float
Effective focal length of the parabola in mm.
OffAxisAngle : float
Off-axis angle *in degrees* of the parabola.
Support : ART.ModuleSupport.Support
337 def get_normal(self, Point): 338 """Return the normal unit vector on the paraboloid surface at point Point.""" 339 Gradient = np.zeros(3) 340 Gradient[0] = -Point[0] 341 Gradient[1] = -Point[1] 342 Gradient[2] = self._p 343 return mgeo.Normalize(Gradient)
Return the normal unit vector on the paraboloid surface at point Point.
345 def get_centre(self): 346 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 347 return np.array( 348 [ 349 self.feff * np.sin(self.offaxisangle), 350 0, 351 self._p * 0.5 - self.feff * np.cos(self.offaxisangle), 352 ] 353 )
Return 3D coordinates of the point on the mirror surface at the center of its support.
355 def get_grid3D(self, NbPoint, **kwargs): 356 """ 357 Get grid of points on mirror surface. 358 359 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 360 sampling the support in a number NbPoints of points. 361 """ 362 E = "edges" in kwargs and kwargs["edges"] 363 ListCoordXYZ = [] 364 contour = int(round(0.1 * NbPoint)) 365 contours = self.support._Contour_points(contour, **kwargs) 366 if E: 367 contours, contour_edges = contours 368 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 369 xc = self.feff * np.sin(self.offaxisangle) 370 for k in ListCoordXY: 371 z = ((k[0] + xc) ** 2 + k[1] ** 2) / 2 / self._p 372 ListCoordXYZ.append(np.array([k[0] + xc, k[1], z])) 373 if E: 374 return ListCoordXYZ, contour_edges 375 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
379class MirrorToroidal: 380 r""" 381 Toroidal mirror surface with eqn.$(\sqrt{x^2+z^2}-R)^2 + y^2 = r^2$ where $R$ and $r$ the major and minor radii. 382 383 ![Illustration of a toroidal mirror.](toroidal.svg) 384 385 Attributes 386 ---------- 387 majorradius : float 388 Major radius of the toroid in mm. 389 390 minorradius : float 391 Minor radius of the toroid in mm. 392 393 support : ART.ModuleSupport.Support 394 395 type : str 'Toroidal Mirror'. 396 397 Methods 398 ------- 399 MirrorToroidal.get_normal(Point) 400 401 MirrorToroidal.get_centre() 402 403 MirrorToroidal.get_grid3D(NbPoints) 404 405 """ 406 407 def __init__(self, MajorRadius, MinorRadius, Support): 408 """ 409 Construct a toroidal mirror. 410 411 Parameters 412 ---------- 413 MajorRadius : float 414 Major radius of the toroid in mm. 415 416 MinorRadius : float 417 Minor radius of the toroid in mm. 418 419 Support : ART.ModuleSupport.Support 420 421 """ 422 self.majorradius = MajorRadius 423 self.minorradius = MinorRadius 424 self.support = Support 425 self.type = "Toroidal Mirror" 426 427 def _get_intersection(self, Ray): 428 """Return the intersection point between Ray and the toroidal mirror surface.""" 429 ux = Ray.vector[0] 430 uz = Ray.vector[2] 431 xA = Ray.point[0] 432 zA = Ray.point[2] 433 434 G = 4.0 * self.majorradius**2 * (ux**2 + uz**2) 435 H = 8.0 * self.majorradius**2 * (ux * xA + uz * zA) 436 I = 4.0 * self.majorradius**2 * (xA**2 + zA**2) 437 J = np.dot(Ray.vector, Ray.vector) 438 K = 2.0 * np.dot(Ray.vector, Ray.point) 439 L = ( 440 np.dot(Ray.point, Ray.point) 441 + self.majorradius**2 442 - self.minorradius**2 443 ) 444 445 a = J**2 446 b = 2 * J * K 447 c = 2 * J * L + K**2 - G 448 d = 2 * K * L - H 449 e = L**2 - I 450 451 Solution = mgeo.SolverQuartic(a, b, c, d, e) 452 Solution = mgeo.KeepPositiveSolution(Solution) 453 454 ListPointIntersection = [] 455 for t in Solution: 456 Intersect = Ray.vector * t + Ray.point 457 if Intersect[2] < -self.majorradius and self.support._IncludeSupport( 458 Intersect 459 ): # For realistic mirror 460 ListPointIntersection.append(Intersect) 461 462 return _IntersectionRayMirror(Ray.point, ListPointIntersection) 463 464 def get_normal(self, Point): 465 """Return the normal unit vector on the toroidal surface at point Point.""" 466 x = Point[0] 467 y = Point[1] 468 z = Point[2] 469 A = self.majorradius**2 - self.minorradius**2 470 471 Gradient = np.zeros(3) 472 Gradient[0] = ( 473 4 * (x**3 + x * y**2 + x * z**2 + x * A) 474 - 8 * x * self.majorradius**2 475 ) 476 Gradient[1] = 4 * (y**3 + y * x**2 + y * z**2 + y * A) 477 Gradient[2] = ( 478 4 * (z**3 + z * x**2 + z * y**2 + z * A) 479 - 8 * z * self.majorradius**2 480 ) 481 482 return mgeo.Normalize(-Gradient) 483 484 def get_centre(self): 485 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 486 return np.array([0, 0, -self.majorradius - self.minorradius]) 487 488 def get_grid3D(self, NbPoint, **kwargs): 489 """ 490 Get grid of points on mirror surface. 491 492 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 493 sampling the support in a number NbPoints of points. 494 """ 495 E = "edges" in kwargs and kwargs["edges"] 496 ListCoordXYZ = [] 497 contour = int(round(0.1 * NbPoint)) 498 contours = self.support._Contour_points(contour, **kwargs) 499 if E: 500 contours, contour_edges = contours 501 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 502 for k in ListCoordXY: 503 z = -np.sqrt( 504 (np.sqrt(self.minorradius**2 - k[1] ** 2) + self.majorradius) 505 ** 2 506 - k[0] ** 2 507 ) 508 ListCoordXYZ.append(np.array([k[0], k[1], z])) 509 if E: 510 return ListCoordXYZ, contour_edges 511 return ListCoordXYZ
Toroidal mirror surface with eqn.$(\sqrt{x^2+z^2}-R)^2 + y^2 = r^2$ where $R$ and $r$ the major and minor radii.
Attributes
majorradius : float
Major radius of the toroid in mm.
minorradius : float
Minor radius of the toroid in mm.
support : ART.ModuleSupport.Support
type : str 'Toroidal Mirror'.
Methods
MirrorToroidal.get_normal(Point)
MirrorToroidal.get_centre()
MirrorToroidal.get_grid3D(NbPoints)
407 def __init__(self, MajorRadius, MinorRadius, Support): 408 """ 409 Construct a toroidal mirror. 410 411 Parameters 412 ---------- 413 MajorRadius : float 414 Major radius of the toroid in mm. 415 416 MinorRadius : float 417 Minor radius of the toroid in mm. 418 419 Support : ART.ModuleSupport.Support 420 421 """ 422 self.majorradius = MajorRadius 423 self.minorradius = MinorRadius 424 self.support = Support 425 self.type = "Toroidal Mirror"
Construct a toroidal mirror.
Parameters
MajorRadius : float
Major radius of the toroid in mm.
MinorRadius : float
Minor radius of the toroid in mm.
Support : ART.ModuleSupport.Support
464 def get_normal(self, Point): 465 """Return the normal unit vector on the toroidal surface at point Point.""" 466 x = Point[0] 467 y = Point[1] 468 z = Point[2] 469 A = self.majorradius**2 - self.minorradius**2 470 471 Gradient = np.zeros(3) 472 Gradient[0] = ( 473 4 * (x**3 + x * y**2 + x * z**2 + x * A) 474 - 8 * x * self.majorradius**2 475 ) 476 Gradient[1] = 4 * (y**3 + y * x**2 + y * z**2 + y * A) 477 Gradient[2] = ( 478 4 * (z**3 + z * x**2 + z * y**2 + z * A) 479 - 8 * z * self.majorradius**2 480 ) 481 482 return mgeo.Normalize(-Gradient)
Return the normal unit vector on the toroidal surface at point Point.
484 def get_centre(self): 485 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 486 return np.array([0, 0, -self.majorradius - self.minorradius])
Return 3D coordinates of the point on the mirror surface at the center of its support.
488 def get_grid3D(self, NbPoint, **kwargs): 489 """ 490 Get grid of points on mirror surface. 491 492 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 493 sampling the support in a number NbPoints of points. 494 """ 495 E = "edges" in kwargs and kwargs["edges"] 496 ListCoordXYZ = [] 497 contour = int(round(0.1 * NbPoint)) 498 contours = self.support._Contour_points(contour, **kwargs) 499 if E: 500 contours, contour_edges = contours 501 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 502 for k in ListCoordXY: 503 z = -np.sqrt( 504 (np.sqrt(self.minorradius**2 - k[1] ** 2) + self.majorradius) 505 ** 2 506 - k[0] ** 2 507 ) 508 ListCoordXYZ.append(np.array([k[0], k[1], z])) 509 if E: 510 return ListCoordXYZ, contour_edges 511 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
517def ReturnOptimalToroidalRadii( 518 Focal: float, AngleIncidence: float 519) -> (float, float): 520 """ 521 Get optimal parameters for a toroidal mirror. 522 523 Useful helper function to get the optimal major and minor radii for a toroidal mirror to achieve a 524 focal length 'Focal' with an angle of incidence 'AngleIncidence' and with vanishing astigmatism. 525 526 Parameters 527 ---------- 528 Focal : float 529 Focal length in mm. 530 531 AngleIncidence : int 532 Angle of incidence in degrees. 533 534 Returns 535 ------- 536 OptimalMajorRadius, OptimalMinorRadius : float, float. 537 """ 538 AngleIncidenceRadian = AngleIncidence * np.pi / 180 539 OptimalMajorRadius = ( 540 2 541 * Focal 542 * (1 / np.cos(AngleIncidenceRadian) - np.cos(AngleIncidenceRadian)) 543 ) 544 OptimalMinorRadius = 2 * Focal * np.cos(AngleIncidenceRadian) 545 return OptimalMajorRadius, OptimalMinorRadius
Get optimal parameters for a toroidal mirror.
Useful helper function to get the optimal major and minor radii for a toroidal mirror to achieve a focal length 'Focal' with an angle of incidence 'AngleIncidence' and with vanishing astigmatism.
Parameters
Focal : float
Focal length in mm.
AngleIncidence : int
Angle of incidence in degrees.
Returns
OptimalMajorRadius, OptimalMinorRadius : float, float.
549class MirrorEllipsoidal: 550 """ 551 Ellipdoidal mirror surface with eqn. $(x/a)^2 + (y/b)^2 + (z/b)^2 = 1$, where $a$ and $b$ are semi major and semi minor axes. 552 553 ![Illustration of a ellipsoidal mirror.](ellipsoid.svg) 554 555 Attributes 556 ---------- 557 a : float 558 Semi major axis of the ellipsoid in mm. 559 560 b : float 561 Semi minor axis of the ellipsoid in mm. 562 563 support : ART.ModuleSupport.Support 564 565 type : str 'Ellipsoidal Mirror'. 566 567 Methods 568 ------- 569 MirrorEllipsoidal.get_normal(Point) 570 571 MirrorEllipsoidal.get_centre() 572 573 MirrorEllipsoidal.get_grid3D(NbPoints) 574 575 """ 576 577 def __init__( 578 self, 579 Support, 580 SemiMajorAxis=None, 581 SemiMinorAxis=None, 582 OffAxisAngle=None, 583 f_object=None, 584 f_image=None, 585 ): 586 """ 587 Generate an ellipsoidal mirror with given parameters. 588 589 Depending on the parameters provided by the vendor, you can either specify: 590 - the Semi Major and Semi Minor axes (default) 591 - The object and image distances 592 You can also specify the Off-Axis angle in degrees. Keep in mind that its value will be stored and returned in radian. 593 594 Parameters 595 ---------- 596 Support : TYPE 597 ART.ModuleSupport.Support. 598 SemiMajorAxis : float 599 Semi major axis of the ellipsoid in mm.. 600 SemiMinorAxis : float 601 Semi minor axis of the ellipsoid in mm.. 602 OffAxisAngle : float 603 Off-axis angle of the mirror in mm. Defined as the angle at the centre of the mirror between the two foci.. 604 f_object : float 605 Object focal distance in mm. 606 f_image : float 607 Image focal distance in mm. 608 """ 609 self.type = "Ellipsoidal Mirror" 610 self.support = Support 611 self.a = None 612 self.b = None 613 self._offaxisangle = None 614 if SemiMajorAxis is not None and SemiMinorAxis is not None: 615 self.a = SemiMajorAxis 616 self.b = SemiMinorAxis 617 if OffAxisAngle is not None: 618 self._offaxisangle = np.deg2rad(OffAxisAngle) 619 if f_object is not None and f_image is not None: 620 f_o = f_object 621 f_i = f_image 622 foci_sq = ( 623 f_o**2 624 + f_i**2 625 - 2 * f_o * f_i * np.cos(self._offaxisangle) 626 ) 627 self.a = (f_i + f_o) / 2 628 self.b = np.sqrt(self.a**2 - foci_sq / 4) 629 else: 630 if f_object is not None and f_image is not None: 631 f_o = f_object 632 f_i = f_image 633 if self.a is not None and self.b is not None: 634 foci = 2 * np.sqrt(self.a**2 - self.b**2) 635 self._offaxisangle = np.arccos( 636 (f_i**2 + f_o**2 - foci**2) / (2 * f_i * f_o) 637 ) 638 639 elif self.a is not None and self.b is not None: 640 foci = 2 * np.sqrt(self.a**2 - self.b**2) 641 f = self.a 642 self._offaxisangle = np.arccos(1 - foci**2 / (2 * f**2)) 643 if self.a is None or self.b is None or self._offaxisangle is None: 644 raise ValueError("Invalid mirror parameters") 645 646 def _get_intersection(self, Ray): 647 """Return the intersection point between Ray and the ellipsoidal mirror surface.""" 648 ux, uy, uz = Ray.vector 649 xA, yA, zA = Ray.point 650 651 da = (uy**2 + uz**2) / self.b**2 + (ux / self.a) ** 2 652 db = 2 * ((uy * yA + uz * zA) / self.b**2 + (ux * xA) / self.a**2) 653 dc = (yA**2 + zA**2) / self.b**2 + (xA / self.a) ** 2 - 1 654 655 Solution = mgeo.SolverQuadratic(da, db, dc) 656 Solution = mgeo.KeepPositiveSolution(Solution) 657 658 ListPointIntersection = [] 659 C = self.get_centre() 660 for t in Solution: 661 Intersect = Ray.vector * t + Ray.point 662 if Intersect[2] < 0 and self.support._IncludeSupport( 663 Intersect - C 664 ): 665 ListPointIntersection.append(Intersect) 666 667 return _IntersectionRayMirror(Ray.point, ListPointIntersection) 668 669 def get_normal(self, Point): 670 """Return the normal unit vector on the ellipsoidal surface at point Point.""" 671 Gradient = np.zeros(3) 672 673 Gradient[0] = -Point[0] / self.a**2 674 Gradient[1] = -Point[1] / self.b**2 675 Gradient[2] = -Point[2] / self.b**2 676 677 return mgeo.Normalize(Gradient) 678 679 def get_centre(self): 680 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 681 foci = 2 * np.sqrt(self.a**2 - self.b**2) 682 h = -foci / 2 / np.tan(self._offaxisangle) 683 R = np.sqrt(foci**2 / 4 + h**2) 684 sign = 1 685 if math.isclose(self._offaxisangle, np.pi / 2): 686 h = 0 687 elif self._offaxisangle > np.pi / 2: 688 h = -h 689 sign = -1 690 a = 1 - self.a**2 / self.b**2 691 b = -2 * h 692 c = self.a**2 + h**2 - R**2 693 z = (-b + sign * np.sqrt(b**2 - 4 * a * c)) / (2 * a) 694 if math.isclose(z**2, self.b**2): 695 return np.array([0, 0, -self.b]) 696 x = self.a * np.sqrt(1 - z**2 / self.b**2) 697 centre = np.array([x, 0, sign * z]) 698 return centre 699 700 def get_grid3D(self, NbPoint, **kwargs): 701 """ 702 Get grid of points on mirror surface. 703 704 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 705 sampling the support in a number NbPoints of points. 706 """ 707 E = "edges" in kwargs and kwargs["edges"] 708 ListCoordXYZ = [] 709 contour = int(round(0.1 * NbPoint)) 710 contours = self.support._Contour_points(contour, **kwargs) 711 if E: 712 contours, contour_edges = contours 713 ListCoordXY = self.support._get_grid(NbPoint - contour) 714 centre = self.get_centre() 715 for i, k in enumerate(ListCoordXY): 716 x = k[0] + centre[0] 717 y = k[1] 718 sideways = (x / self.a) ** 2 + (y / self.b) ** 2 719 if sideways <= 1: 720 z = -self.b * np.sqrt(1 - sideways) 721 ListCoordXYZ.append(np.array([x, y, z])) 722 new_contour_edges = [] 723 for j in contour_edges: 724 new_contour_edges += [[]] 725 for i in j: 726 x = contours[i][0] + centre[0] 727 y = contours[i][1] 728 sideways = (x / self.a) ** 2 + (y / self.b) ** 2 729 if sideways <= 1: 730 z = -self.b * np.sqrt(1 - sideways) 731 ListCoordXYZ.append(np.array([x, y, z])) 732 new_contour_edges[-1] += [len(ListCoordXYZ) - 1] 733 if E: 734 return ListCoordXYZ, new_contour_edges 735 return ListCoordXYZ
Ellipdoidal mirror surface with eqn. $(x/a)^2 + (y/b)^2 + (z/b)^2 = 1$, where $a$ and $b$ are semi major and semi minor axes.
Attributes
a : float
Semi major axis of the ellipsoid in mm.
b : float
Semi minor axis of the ellipsoid in mm.
support : ART.ModuleSupport.Support
type : str 'Ellipsoidal Mirror'.
Methods
MirrorEllipsoidal.get_normal(Point)
MirrorEllipsoidal.get_centre()
MirrorEllipsoidal.get_grid3D(NbPoints)
577 def __init__( 578 self, 579 Support, 580 SemiMajorAxis=None, 581 SemiMinorAxis=None, 582 OffAxisAngle=None, 583 f_object=None, 584 f_image=None, 585 ): 586 """ 587 Generate an ellipsoidal mirror with given parameters. 588 589 Depending on the parameters provided by the vendor, you can either specify: 590 - the Semi Major and Semi Minor axes (default) 591 - The object and image distances 592 You can also specify the Off-Axis angle in degrees. Keep in mind that its value will be stored and returned in radian. 593 594 Parameters 595 ---------- 596 Support : TYPE 597 ART.ModuleSupport.Support. 598 SemiMajorAxis : float 599 Semi major axis of the ellipsoid in mm.. 600 SemiMinorAxis : float 601 Semi minor axis of the ellipsoid in mm.. 602 OffAxisAngle : float 603 Off-axis angle of the mirror in mm. Defined as the angle at the centre of the mirror between the two foci.. 604 f_object : float 605 Object focal distance in mm. 606 f_image : float 607 Image focal distance in mm. 608 """ 609 self.type = "Ellipsoidal Mirror" 610 self.support = Support 611 self.a = None 612 self.b = None 613 self._offaxisangle = None 614 if SemiMajorAxis is not None and SemiMinorAxis is not None: 615 self.a = SemiMajorAxis 616 self.b = SemiMinorAxis 617 if OffAxisAngle is not None: 618 self._offaxisangle = np.deg2rad(OffAxisAngle) 619 if f_object is not None and f_image is not None: 620 f_o = f_object 621 f_i = f_image 622 foci_sq = ( 623 f_o**2 624 + f_i**2 625 - 2 * f_o * f_i * np.cos(self._offaxisangle) 626 ) 627 self.a = (f_i + f_o) / 2 628 self.b = np.sqrt(self.a**2 - foci_sq / 4) 629 else: 630 if f_object is not None and f_image is not None: 631 f_o = f_object 632 f_i = f_image 633 if self.a is not None and self.b is not None: 634 foci = 2 * np.sqrt(self.a**2 - self.b**2) 635 self._offaxisangle = np.arccos( 636 (f_i**2 + f_o**2 - foci**2) / (2 * f_i * f_o) 637 ) 638 639 elif self.a is not None and self.b is not None: 640 foci = 2 * np.sqrt(self.a**2 - self.b**2) 641 f = self.a 642 self._offaxisangle = np.arccos(1 - foci**2 / (2 * f**2)) 643 if self.a is None or self.b is None or self._offaxisangle is None: 644 raise ValueError("Invalid mirror parameters")
Generate an ellipsoidal mirror with given parameters.
Depending on the parameters provided by the vendor, you can either specify: - the Semi Major and Semi Minor axes (default) - The object and image distances You can also specify the Off-Axis angle in degrees. Keep in mind that its value will be stored and returned in radian.
Parameters
Support : TYPE ART.ModuleSupport.Support. SemiMajorAxis : float Semi major axis of the ellipsoid in mm.. SemiMinorAxis : float Semi minor axis of the ellipsoid in mm.. OffAxisAngle : float Off-axis angle of the mirror in mm. Defined as the angle at the centre of the mirror between the two foci.. f_object : float Object focal distance in mm. f_image : float Image focal distance in mm.
669 def get_normal(self, Point): 670 """Return the normal unit vector on the ellipsoidal surface at point Point.""" 671 Gradient = np.zeros(3) 672 673 Gradient[0] = -Point[0] / self.a**2 674 Gradient[1] = -Point[1] / self.b**2 675 Gradient[2] = -Point[2] / self.b**2 676 677 return mgeo.Normalize(Gradient)
Return the normal unit vector on the ellipsoidal surface at point Point.
679 def get_centre(self): 680 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 681 foci = 2 * np.sqrt(self.a**2 - self.b**2) 682 h = -foci / 2 / np.tan(self._offaxisangle) 683 R = np.sqrt(foci**2 / 4 + h**2) 684 sign = 1 685 if math.isclose(self._offaxisangle, np.pi / 2): 686 h = 0 687 elif self._offaxisangle > np.pi / 2: 688 h = -h 689 sign = -1 690 a = 1 - self.a**2 / self.b**2 691 b = -2 * h 692 c = self.a**2 + h**2 - R**2 693 z = (-b + sign * np.sqrt(b**2 - 4 * a * c)) / (2 * a) 694 if math.isclose(z**2, self.b**2): 695 return np.array([0, 0, -self.b]) 696 x = self.a * np.sqrt(1 - z**2 / self.b**2) 697 centre = np.array([x, 0, sign * z]) 698 return centre
Return 3D coordinates of the point on the mirror surface at the center of its support.
700 def get_grid3D(self, NbPoint, **kwargs): 701 """ 702 Get grid of points on mirror surface. 703 704 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 705 sampling the support in a number NbPoints of points. 706 """ 707 E = "edges" in kwargs and kwargs["edges"] 708 ListCoordXYZ = [] 709 contour = int(round(0.1 * NbPoint)) 710 contours = self.support._Contour_points(contour, **kwargs) 711 if E: 712 contours, contour_edges = contours 713 ListCoordXY = self.support._get_grid(NbPoint - contour) 714 centre = self.get_centre() 715 for i, k in enumerate(ListCoordXY): 716 x = k[0] + centre[0] 717 y = k[1] 718 sideways = (x / self.a) ** 2 + (y / self.b) ** 2 719 if sideways <= 1: 720 z = -self.b * np.sqrt(1 - sideways) 721 ListCoordXYZ.append(np.array([x, y, z])) 722 new_contour_edges = [] 723 for j in contour_edges: 724 new_contour_edges += [[]] 725 for i in j: 726 x = contours[i][0] + centre[0] 727 y = contours[i][1] 728 sideways = (x / self.a) ** 2 + (y / self.b) ** 2 729 if sideways <= 1: 730 z = -self.b * np.sqrt(1 - sideways) 731 ListCoordXYZ.append(np.array([x, y, z])) 732 new_contour_edges[-1] += [len(ListCoordXYZ) - 1] 733 if E: 734 return ListCoordXYZ, new_contour_edges 735 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
739def ReturnOptimalEllipsoidalAxes(Focal: float, AngleIncidence: float): 740 """ 741 Get optimal parameters for an ellipsoidal mirror. 742 743 Useful helper function to get the optimal major and minor axes for an ellipsoidal mirror to achieve a 744 focal length 'Focal' with an angle of incidence 'AngleIncidence'. 745 746 Parameters 747 ---------- 748 Focal : float 749 Focal length in mm. 750 751 AngleIncidence : int 752 Angle of incidence in degrees. 753 754 Returns 755 ------- 756 OptimalSemiMajorAxis, OptimalSemiMinorAxis : float, float. 757 """ 758 AngleIncidenceRadian = np.deg2rad(AngleIncidence) 759 OptimalSemiMajorAxis = Focal 760 OptimalSemiMinorAxis = OptimalSemiMajorAxis * np.cos(AngleIncidenceRadian) 761 return OptimalSemiMajorAxis, OptimalSemiMinorAxis
Get optimal parameters for an ellipsoidal mirror.
Useful helper function to get the optimal major and minor axes for an ellipsoidal mirror to achieve a focal length 'Focal' with an angle of incidence 'AngleIncidence'.
Parameters
Focal : float
Focal length in mm.
AngleIncidence : int
Angle of incidence in degrees.
Returns
OptimalSemiMajorAxis, OptimalSemiMinorAxis : float, float.
765class MirrorCylindrical: 766 """ 767 Cylindrical mirror surface with eqn. $y^2 + z^2 = R^2$, where $R$ is the radius. 768 769 Attributes 770 ---------- 771 radius : float 772 Radius of curvature. A postive value for concave mirror, a negative value for a convex mirror. 773 774 support : ART.ModuleSupport.Support 775 776 type : str 'Ellipsoidal Mirror'. 777 778 Methods 779 ------- 780 MirrorCylindrical.get_normal(Point) 781 782 MirrorCylindrical.get_centre() 783 784 MirrorCylindrical.get_grid3D(NbPoints) 785 """ 786 787 def __init__(self, Radius, Support): 788 """ 789 Construct a cylindrical mirror. 790 791 Parameters 792 ---------- 793 Radius : float 794 The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror. 795 796 Support : ART.ModuleSupport.Support 797 798 """ 799 if Radius < 0: 800 self.type = "CylindricalCX Mirror" 801 self.radius = -Radius 802 else: 803 self.type = "CylindricalCC Mirror" 804 self.radius = Radius 805 806 self.support = Support 807 808 def _get_intersection(self, Ray): 809 """Return the intersection point between the Ray and the cylinder.""" 810 uy = Ray.vector[1] 811 uz = Ray.vector[2] 812 yA = Ray.point[1] 813 zA = Ray.point[2] 814 815 a = uy**2 + uz**2 816 b = 2 * (uy * yA + uz * zA) 817 c = yA**2 + zA**2 - self.radius**2 818 819 Solution = mgeo.SolverQuadratic(a, b, c) 820 Solution = mgeo.KeepPositiveSolution(Solution) 821 822 ListPointIntersection = [] 823 for t in Solution: 824 Intersect = Ray.vector * t + Ray.point 825 if Intersect[2] < 0 and self.support._IncludeSupport(Intersect): 826 ListPointIntersection.append(Intersect) 827 828 return _IntersectionRayMirror(Ray.point, ListPointIntersection) 829 830 def get_normal(self, Point): 831 """Return the normal unit vector on the cylinder surface at point P.""" 832 Gradient = np.array([0, -Point[1], -Point[2]]) 833 return mgeo.Normalize(Gradient) 834 835 def get_centre(self): 836 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 837 return np.array([0, 0, -self.radius]) 838 839 def get_grid3D(self, NbPoint, **kwargs): 840 """ 841 Get grid of points on mirror surface. 842 843 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 844 sampling the support in a number NbPoints of points. 845 """ 846 E = "edges" in kwargs and kwargs["edges"] 847 ListCoordXYZ = [] 848 contour = int(round(0.1 * NbPoint)) 849 contours = self.support._Contour_points(contour, **kwargs) 850 if E: 851 contours, contour_edges = contours 852 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 853 for k in ListCoordXY: 854 z = -np.sqrt(self.radius**2 - k[1] ** 2) 855 ListCoordXYZ.append(np.array([k[0], k[1], z])) 856 if E: 857 return ListCoordXYZ, contour_edges 858 return ListCoordXYZ
Cylindrical mirror surface with eqn. $y^2 + z^2 = R^2$, where $R$ is the radius.
Attributes
radius : float
Radius of curvature. A postive value for concave mirror, a negative value for a convex mirror.
support : ART.ModuleSupport.Support
type : str 'Ellipsoidal Mirror'.
Methods
MirrorCylindrical.get_normal(Point)
MirrorCylindrical.get_centre()
MirrorCylindrical.get_grid3D(NbPoints)
787 def __init__(self, Radius, Support): 788 """ 789 Construct a cylindrical mirror. 790 791 Parameters 792 ---------- 793 Radius : float 794 The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror. 795 796 Support : ART.ModuleSupport.Support 797 798 """ 799 if Radius < 0: 800 self.type = "CylindricalCX Mirror" 801 self.radius = -Radius 802 else: 803 self.type = "CylindricalCC Mirror" 804 self.radius = Radius 805 806 self.support = Support
Construct a cylindrical mirror.
Parameters
Radius : float
The radius of curvature in mm. A postive value for concave mirror, a negative value for a convex mirror.
Support : ART.ModuleSupport.Support
830 def get_normal(self, Point): 831 """Return the normal unit vector on the cylinder surface at point P.""" 832 Gradient = np.array([0, -Point[1], -Point[2]]) 833 return mgeo.Normalize(Gradient)
Return the normal unit vector on the cylinder surface at point P.
835 def get_centre(self): 836 """Return 3D coordinates of the point on the mirror surface at the center of its support.""" 837 return np.array([0, 0, -self.radius])
Return 3D coordinates of the point on the mirror surface at the center of its support.
839 def get_grid3D(self, NbPoint, **kwargs): 840 """ 841 Get grid of points on mirror surface. 842 843 Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, 844 sampling the support in a number NbPoints of points. 845 """ 846 E = "edges" in kwargs and kwargs["edges"] 847 ListCoordXYZ = [] 848 contour = int(round(0.1 * NbPoint)) 849 contours = self.support._Contour_points(contour, **kwargs) 850 if E: 851 contours, contour_edges = contours 852 ListCoordXY = contours + self.support._get_grid(NbPoint - contour) 853 for k in ListCoordXY: 854 z = -np.sqrt(self.radius**2 - k[1] ** 2) 855 ListCoordXYZ.append(np.array([k[0], k[1], z])) 856 if E: 857 return ListCoordXYZ, contour_edges 858 return ListCoordXYZ
Get grid of points on mirror surface.
Returns list of numpy-arrays containing the 3D-coordinates of points in the mirror surface, sampling the support in a number NbPoints of points.
896def ReflectionMirrorRayList(Mirror, ListRay): 897 """ 898 Return the the reflected rays according to the law of reflection for the list of incident rays ListRay. 899 900 Rays that do not hit the support are not further propagated. 901 902 Updates the reflected rays' incidence angle and path. 903 904 Parameters 905 ---------- 906 Mirror : Mirror-object 907 908 ListRay : list[Ray-object] 909 910 """ 911 Deformed = type(Mirror) == DeformedMirror 912 ListRayReflected = [] 913 for k in ListRay: 914 PointMirror = Mirror._get_intersection(k) 915 916 if PointMirror is not None: 917 if Deformed and k.number == 0: 918 M = Mirror.Mirror 919 else: 920 M = Mirror 921 RayReflected = _ReflectionMirrorRay(M, PointMirror, k) 922 ListRayReflected.append(RayReflected) 923 return ListRayReflected
Return the the reflected rays according to the law of reflection for the list of incident rays ListRay.
Rays that do not hit the support are not further propagated.
Updates the reflected rays' incidence angle and path.
Parameters
Mirror : Mirror-object
ListRay : list[Ray-object]
929class DeformedMirror: 930 def __init__(self, Mirror, DeformationList): 931 self.Mirror = Mirror 932 self.DeformationList = DeformationList 933 self.type = Mirror.type 934 self.support = self.Mirror.support 935 936 def get_normal(self, PointMirror): 937 base_normal = self.Mirror.get_normal(PointMirror) 938 C = self.get_centre() 939 defects_normals = [ 940 d.get_normal(PointMirror - C) for d in self.DeformationList 941 ] 942 for i in defects_normals: 943 base_normal = normal_add(base_normal, i) 944 base_normal /= np.linalg.norm(base_normal) 945 return base_normal 946 947 def get_centre(self): 948 return self.Mirror.get_centre() 949 950 def get_grid3D(self, NbPoint, **kwargs): 951 return self.Mirror.get_grid3D(NbPoint, **kwargs) 952 953 def _get_intersection(self, Ray): 954 Intersect = self.Mirror._get_intersection(Ray) 955 if Intersect is not None: 956 h = sum( 957 D.get_offset(Intersect - self.get_centre()) 958 for D in self.DeformationList 959 ) 960 alpha = mgeo.AngleBetweenTwoVectors( 961 -Ray.vector, self.Mirror.get_normal(Intersect) 962 ) 963 Intersect -= Ray.vector * h / np.cos(alpha) 964 return Intersect
936 def get_normal(self, PointMirror): 937 base_normal = self.Mirror.get_normal(PointMirror) 938 C = self.get_centre() 939 defects_normals = [ 940 d.get_normal(PointMirror - C) for d in self.DeformationList 941 ] 942 for i in defects_normals: 943 base_normal = normal_add(base_normal, i) 944 base_normal /= np.linalg.norm(base_normal) 945 return base_normal
966def normal_add(N1, N2): 967 normal1 = N1 / np.linalg.norm(N1) 968 normal2 = N2 / np.linalg.norm(N2) 969 grad1X = -normal1[0] / normal1[2] 970 grad1Y = -normal1[1] / normal1[2] 971 grad2X = -normal2[0] / normal2[2] 972 grad2Y = -normal2[1] / normal2[2] 973 gradX = grad1X + grad2X 974 gradY = grad1Y + grad2Y 975 return np.array([-gradX, -gradY, 1])