4.2. Base Shapes (Surface, Line, Point)¶
4.2.1. Overview¶
Surfaces, points and lines are the base component for all Element
classes.
They describe a geometrical behavior relative to their center (marked as “x” in the following figures).
They have no absolute position in three-dimensional space,
their actual position is assigned and managed by their owner Element.
All lengths are given in millimeters and angles in degrees.
4.2.2. Point and Line¶
Point
and Line
are the simplest geometry types.
Both types have no extent in z-direction, therefore lie exclusively on a xy-plane.
To create a point write:
P = ot.Point()
A line with radius 2 and an angle of 40 degrees to the x-axis is defined using:
L = ot.Line(r=2, angle=40)
4.2.3. Planar Surfaces¶
Planar surfaces are purely two-dimensional and have no extent in z-direction, therefore being parallel to the xy-plane.
CircularSurfaces
is often used for plan-concave or plan-convex lenses or color filters.
RingSurfaces
and
SlitSurfaces <optrace.tracer.geometry.surface.slit_surface.SlitSurface> are typically found for Apertures,
and RectangularSurfaces
for detectors or object images.
Fig. 4.7 Circle geometry¶ |
Fig. 4.8 Ring geometry¶ |
Fig. 4.9 Rectangle geometry¶ |
Fig. 4.10 Slit geometry¶ |
A circle/disc of radius 3.5 is created by:
Disc = ot.CircularSurface(r=3.5)
When constructing a ring surface an additional inner radius \(0 < r_\text{i} < r\) is required:
Ring = ot.RingSurface(ri=0.2, r=3.5)
The rectangular surface requires a list of two dimensions, that describe the extent in x and y direction. For a side length in x-direction of 4 mm and 5 mm in y-direction we write:
Rect = ot.RectangularSurface(dim=[4.0, 5.0])
The slit surface requires additionally the inner dimensions specified by a parameter dimi
:
Slit = ot.SlitSurface(dim=[4.0, 5.0], dimi=[0.01, 0.1])
4.2.4. Height Surfaces¶
Tilted Surface
A TiltedSurface
has a circular projection in the xy-plane, but has a surface normal
that is not parallel to the optical axis (z-direction).
It can be used for creating prisms or tilted glass plates.
Fig. 4.11 TiltedSurface geometry¶
As for most other surfaces, it is defined by a radius \(r\). Additionally, a normal vector must be provided.
This can either be done in the cartesian form, with 3 elements and parameter normal=[x, y, z]
or using spherical coordinates normal_sph=[theta, phi]
with two elements. theta
describes the angle between the normal and the optical axis (z-axis), while phi
describes the angle in the xy-plane.
The following examples both describe the same surface:
TS = ot.TiltedSurface(r=4, normal=[0.0, 1/np.sqrt(2), 1/np.sqrt(2)])
TS = ot.TiltedSurface(r=4, normal_sph=[45.0, 90.0])
Spherical Surface
A SphericalSurface
is the most common surface type for lenses.
It is defined by a curvature radius \(R\), which is positive when the center of the curvature
circle lies behind the surface and negative otherwise.
This is illustrated in figure Fig. 4.12.
Fig. 4.12 Spherical surface geometry with a positive and negative curvature radius \(R\)¶
Constructing such a surface is done with:
sph = ot.SphericalSurface(r=2.5, R=-12.458)
Conic Surface
A conic surface is defined by the conic section equation:
With the curvature \(\rho = 1/R\) and the conical constant \(k\). Depending on this constant the type of conic section differs:
\(k<-1\) |
hyperbola |
\(k=-1\) |
parabola |
\(-1 < k < 0\) |
prolate ellipse |
\(k=0\) |
circle |
\(k>0\) |
oblate ellipse |
Fig. 4.13 Conic surface geometry with a different conic constant \(k\) signs. An aspheric surface has a small additional rotationally symmetric polynomial added.¶
Compared to the spherical surface, a ConicSurface
takes another parameter, the conical constant k
:
conic = ot.ConicSurface(r=2.5, R=23.8, k=-1)
A visualization of different conical constants can be found in [1].
Aspheric Surface
An aspheric surface is a conic surface with additional \(m\) even order polynomial components \(a_1, ..., a_m\).
An AsphericSurface
has additional polynomial components \(a_0 r^2 + a_1 r^4 + \dots\),
where \(a_0,~a_1,\dots\) are the polynomical coefficients given in powers of millimeters.
For \(a_0 = 0, ~ a_1 = 10^{-5}, ~a_2 = 3.2 \cdot 10^{-7}\) the surface is created by:
asph = ot.AsphericSurface(r=2.5, R=12.37, k=2.03, coeff=[0, 1e-5, 3.2e-7])
4.2.5. User Functions¶
Overview
The FunctionSurface2D
class allows us to define custom surfaces, defined by a mathematical function depending on x and y.
For functions with rotational symmetry we can also use the
FunctionSurface1D
class,
where the values are only dependent on the radial distance r.
Fig. 4.14 Custom function according to \(z_\text{s}(x,~y)\), which can be a symmetric or asymmetric function or a dataset¶
Simplest case
As an example we want to create an axicon surface:
func = ot.FunctionSurface1D(r=3, func=lambda r: r)
The user defined function must take r-values (as numpy array),
return a numpy array and is provided as the func
parameter.
Note that the surface offset at \(r=0\) is irrelevant, as it will be automatically compensated for.
Providing partial derivatives
To speed up tracing and enhance numerical precision we can provide the partial derivatives
of the surface in x and y-direction.
For our axicon the special case \(r=0\) needs to be handled separately.
The derivative function is passed with the deriv_func
-parameter.
def axicon_deriv(r):
dr = np.ones_like(r)
dr[r == 0] = 0
return dr
func = ot.FunctionSurface1D(r=3, func=lambda r: r, deriv_func=axicon_deriv)
Function parameters
The user can provide a dictionary of parameters that will get passed down to the corresponding function.
For the func
argument the matching parameter would be func_args
.
For deriv_func
it is deriv_args
.
def axicon(r, a):
return a*r
def axicon_deriv(r, a):
dr = np.full_like(r, a)
dr[r == 0] = 0
return dr
func = ot.FunctionSurface1D(r=3, func=axicon, func_args=dict(a=-0.3),
deriv_func=axicon_deriv, deriv_args=dict(a=-0.3))
z-Range
When initializing a surface, optrace tries to determine the surface extent in z-direction.
The resulting z_min
and z_max
values are needed to know the surface bounds,
which in turn are needed for tracing of the surface.
While this works automatically in many cases, the user has the option to provide these values manually.
If these values should largely differ from the automatically estimated values a warning or,
for a large deviation, an exception is raised.
For a a=-0.3
and r=3
the z-bounds are [-0.9, 0]
.
This can be provided using:
func = ot.FunctionSurface1D(..., z_min=-0.9, z_max=0)
Radius of Curvature
We can also provide a radius of curvature for the paraxial region. This will be useful for ray transfer matrix analysis in section Section 4.10. Note that this only makes sense for surfaces with rotational symmetry near the center.
func = ot.FunctionSurface1D(..., parax_roc=3.465)
Note that for our axicon example there can be no paraxial radius of curvature defined.
Mask function
When defining custom apertures or filters, the mask_func
-parameter comes in handy.
To define a half circular aperture with radius \(r=0.1\), one can write:
def mask(x, y, r):
return (x > 0) | (x**2 + y**2 > r**2)
func = ot.FunctionSurface2D(r=3, func=lambda x, y: np.zeros_like(x),
mask_func=mask, mask_args=dict(r=0.1))
In this case, the func
-parameter is just a plane.
Note that we need to use the FunctionSurface2D class, as there is no rotational symmetry.
4.2.6. Data Surfaces¶
DataSurface2D
A DataSurface2D
is defined by a height dataset in a square matrix.
This square set is cut into a circular disc after initialization.
Together with this set, the radius of the disc is required.
It is recommended to have 200x200 element or even larger matrices. Values between data cells are interpolated with a polynomial of forth order for smooth curvature changes.
The following example creates a lens with direction-dependent curvature and noise/manufacturing errors added:
r0 = 3
Y, X = np.mgrid[-r0:r0:200j, -r0:r0:200j]
H = 0.1*X**2 + 0.2*Y**2
H += 0.005*np.random.sample(X.shape)
data2d = ot.DataSurface2D(r=r0, data=H)
Note that we can also add the parameters z_min=...
, z_max=
, parax_roc
,
as for the FunctionSurface class.
DataSurface1D
For a surface with rotational symmetry one radial vector is sufficient.
For this we utilize the DataSurface1D
class:
r0 = 3
r = np.linspace(0, r0, 1000)
h = r**2
h[r > 1] = 1
h += 0.005*np.random.sample(1000)
data1d = ot.DataSurface1D(r=r0, data=h)
4.2.7. Geometry Properties¶
All surface/point/line share the following methods and properties.
Position
The position of the surface/point/line is accessed using:
pos = surf.pos
This returns a three element list with x, y, z center coordinates.
Extent
The extent box is the smallest encompassing bounding box that includes the surface/point/line.
The extent property returns a list of coordinate bounds [x0, x1, y0, y1, z0, z1]
.
It is accessed by:
extent = surf.extent
Moving
Moving/setting its initial position of the surface/point/line is handled by its parent object
(typically a subclass of Element
, see Elements (Lens, Ray Source, …)).
Rotation
Using the rotate
function the surface/point/line is rotated by 180 degrees around its
center around the z-axis.
The function takes a rotation angle in degrees:
surf.rotate(15)
Flipping
Flipping the surface rotates it around an axis parallel to the x-axis passing through its center at El.pos
.
surf.flip()
Other
Below you can find some additional geometrical quantities that are useful when moving surfaces, assigning them to lenses or determining the correct thicknesses.
\(z_\text{min}\) and \(z_\text{max}\) describe the minimal and maximal z-position on the surface, while \(z_0\) is the z-position of the center. \(d_\text{s}\) is the difference between \(z_\text{min}\) and \(z_\text{max}\), \(d_\text{p}\) is the difference between \(z_\text{max}\) and \(z_0\) and \(d_\text{n}\) the difference between \(z_0\) and \(z_\text{min}\).
4.2.8. Plotting¶
See Plotting Surfaces.
References