@@ -184,15 +184,12 @@ function Lens(
184184
185185 # Initialize remaining cylindrical section length.
186186 l0 = center_thickness
187-
188187 # Front Surface
189188 front = sdf (front_surface, ForwardOrientation ())
190189 l0 -= isnothing (front) ? zero (l0) : thickness (front)
191-
192190 # Back Surface
193191 back = sdf (back_surface, BackwardOrientation ())
194192 l0 -= isnothing (back) ? zero (l0) : thickness (back)
195-
196193 # Use MeniscusLensSDF if cylinder length is non-positive
197194 if l0 ≤ 0
198195 if sign (radius (front_surface)) == sign (radius (back_surface))
@@ -222,39 +219,89 @@ function Lens(
222219 end
223220 shape = mid
224221
225- # Add mechanical ring if md_mid > d_mid
226- if md_mid > d_mid
227- ring_thickness = thickness (mid)
228- ring_center = position (mid)[2 ] + ring_thickness / 2
229- if front != = nothing
230- s = edge_sag (front_surface, front)
231- ring_thickness -= s
232- ring_center += s / 2
222+ d_front = diameter (front_surface)
223+ d_back = diameter (back_surface)
224+ d_min = min (d_front, d_back)
225+ d_max = max (d_front, d_back)
226+
227+ if md_mid < d_min
228+ @warn " Mechanical diameter is less than clear aperture; parameter md has been ignored."
229+ else
230+ # add leveling ring if there is a step between front and back clear apertures
231+ if d_front != d_back
232+ if d_back > d_front
233+ # Step exists on the front side: level front to match back.
234+ leveling_thickness = l0
235+ if front != = nothing
236+ s_front = edge_sag (front_surface, front)
237+ if s_front < 0
238+ # edge curves towards negative so it is a concave type shape,
239+ # which has to be covered by the ring
240+ leveling_thickness += abs (s_front) + thickness (front)
241+ end
242+ end
243+
244+ ring = RingSDF (d_front / 2 , (d_back - d_front) / 2 , leveling_thickness)
245+ translate3d! (ring, [0 , edge_sag (front_surface, front) + leveling_thickness / 2 , 0 ])
246+ shape += ring
247+ else # d_front > d_back
248+ # Step exists on the back side: level back to match front.
249+ leveling_thickness = l0
250+ if back != = nothing
251+ s_back = edge_sag (back_surface, back)
252+ if (s_back - thickness (back)) > 0
253+ # edge curves towards positive so it is a concave type shape,
254+ # which has to be covered by the ring
255+ leveling_thickness += abs (s_back) + thickness (back)
256+ end
257+ end
258+ leveling_center = position (mid)[2 ] +
259+ (l0/ 2 + (back != = nothing ? edge_sag (back_surface, back) : 0 ))
260+ if back != = nothing
261+ leveling_center += s_back / 2
262+ end
263+ ring = RingSDF (d_back / 2 , (d_front - d_back) / 2 , leveling_thickness)
264+ translate3d! (ring, [0 , thickness (front) + leveling_thickness/ 2 , 0 ])
265+ shape += ring
266+ end
233267 end
234- if back != = nothing
235- s = edge_sag (back_surface, back)
236- ring_thickness += s
237- ring_center += s / 2
268+
269+ # add outer ring if the mechanical diameter exceeds the larger clear aperture.
270+ if md_mid > d_max
271+ outer_thickness = thickness (mid)
272+ outer_center = position (mid)[2 ] + outer_thickness / 2
273+ if front != = nothing
274+ s_front = edge_sag (front_surface, front)
275+ outer_thickness -= s_front
276+ outer_center += s_front / 2
277+ end
278+ if back != = nothing
279+ s_back = edge_sag (back_surface, back)
280+ outer_thickness += s_back
281+ outer_center += s_back / 2
282+ end
283+ ring = RingSDF (d_max / 2 , (md_mid - d_max) / 2 , outer_thickness)
284+ translate3d! (ring, [0 , outer_center, 0 ])
285+ shape += ring
238286 end
239- ring = RingSDF (d_mid / 2 , (md_mid - d_mid) / 2 , ring_thickness)
240- translate3d! (ring, [0 , ring_center, 0 ])
241- shape += ring
242- elseif md_mid < d_mid
243- @warn " Mechanical diameter is less than clear aperture; parameter md has been ignored."
244287 end
245288 end
246289
247290 return Lens (shape, n)
248291end
249292
250- Lens (front_surface:: AbstractRotationallySymmetricSurface , center_thickness:: Real , n:: RefractiveIndex ) = Lens (
251- front_surface,
252- CircularFlatSurface (diameter (front_surface)),
253- center_thickness,
254- n
255- )
293+ function Lens (front_surface:: AbstractRotationallySymmetricSurface ,
294+ center_thickness:: Real , n:: RefractiveIndex )
295+ Lens (
296+ front_surface,
297+ CircularFlatSurface (diameter (front_surface)),
298+ center_thickness,
299+ n
300+ )
301+ end
256302
257- function Lens (front_surface:: CircularFlatSurface , back_surface:: CircularFlatSurface , center_thickness:: Real , n:: RefractiveIndex )
303+ function Lens (front_surface:: CircularFlatSurface , back_surface:: CircularFlatSurface ,
304+ center_thickness:: Real , n:: RefractiveIndex )
258305 d_mid = min (diameter (front_surface), diameter (back_surface))
259306
260307 return Lens (
@@ -306,7 +353,7 @@ function Lens(
306353 else
307354 # Construct central box and add front/back surfaces
308355 mid = BoxSDF (h, l0, d_mid)
309- translate3d! (mid, [0 , l0/ 2 , 0 ])
356+ translate3d! (mid, [0 , l0 / 2 , 0 ])
310357 if front != = nothing
311358 translate3d! (mid, [0 , thickness (front), 0 ])
312359 mid += front
@@ -342,15 +389,20 @@ function Lens(
342389 return Lens (shape, n)
343390end
344391
345- Lens (front_surface:: AbstractCylindricalSurface , center_thickness:: Real , n:: RefractiveIndex ) = Lens (
346- front_surface,
347- RectangularFlatSurface (diameter (front_surface)),
348- center_thickness,
349- n
350- )
392+ function Lens (front_surface:: AbstractCylindricalSurface ,
393+ center_thickness:: Real , n:: RefractiveIndex )
394+ Lens (
395+ front_surface,
396+ RectangularFlatSurface (diameter (front_surface)),
397+ center_thickness,
398+ n
399+ )
400+ end
351401
352- function cylindric_lens_outer_parameters (f:: AbstractCylindricalSurface , b:: AbstractCylindricalSurface )
353- height (f) != height (b) && throw (ArgumentError (" height of front and back surface have to match for cylindric lenses" ))
402+ function cylindric_lens_outer_parameters (
403+ f:: AbstractCylindricalSurface , b:: AbstractCylindricalSurface )
404+ height (f) != height (b) &&
405+ throw (ArgumentError (" height of front and back surface have to match for cylindric lenses" ))
354406
355407 d_mid = min (diameter (f), diameter (b))
356408 md_mid = max (mechanical_diameter (f), mechanical_diameter (b))
@@ -359,27 +411,33 @@ function cylindric_lens_outer_parameters(f::AbstractCylindricalSurface, b::Abstr
359411 return d_mid, md_mid, h
360412end
361413
362- function cylindric_lens_outer_parameters (f:: AbstractCylindricalSurface , :: RectangularFlatSurface )
414+ function cylindric_lens_outer_parameters (
415+ f:: AbstractCylindricalSurface , :: RectangularFlatSurface )
363416 d_mid = diameter (f)
364417 md_mid = mechanical_diameter (f)
365418 h = height (f)
366419
367420 return d_mid, md_mid, h
368421end
369422
370- cylindric_lens_outer_parameters (f:: RectangularFlatSurface , b:: AbstractCylindricalSurface ) = cylindric_lens_outer_parameters (b, f)
423+ function cylindric_lens_outer_parameters (
424+ f:: RectangularFlatSurface , b:: AbstractCylindricalSurface )
425+ cylindric_lens_outer_parameters (b, f)
426+ end
371427
372- function cylindric_lens_outer_parameters (f:: RectangularFlatSurface , b:: RectangularFlatSurface )
428+ function cylindric_lens_outer_parameters (
429+ f:: RectangularFlatSurface , b:: RectangularFlatSurface )
373430 d_mid = diameter (f)
374431 md_mid = mechanical_diameter (f)
375432
376433 return d_mid, md_mid, d_mid
377434end
378435
379- function Lens (front_surface:: RectangularFlatSurface , back_surface:: RectangularFlatSurface , center_thickness:: Real , n:: RefractiveIndex )
436+ function Lens (front_surface:: RectangularFlatSurface , back_surface:: RectangularFlatSurface ,
437+ center_thickness:: Real , n:: RefractiveIndex )
380438 d_mid = min (diameter (front_surface), diameter (back_surface))
381439 mid = BoxSDF (d_mid, center_thickness, d_mid)
382- translate3d! (mid, [0 , center_thickness/ 2 , 0 ])
440+ translate3d! (mid, [0 , center_thickness / 2 , 0 ])
383441
384442 return Lens (
385443 mid,
0 commit comments