For my torchlensmaker project, I need to represent lenses surface shapes parameterically. That is, I need equations that give the X and Y coordinates of the surface, as a function of a parameter, usually called .
The project supports different parametric shapes, but a very popular shape in optics is the arc of circle. So far I had been using the usual polar coordinates parameterization:
This works great, you can represent circles that cross the origin at , and it works for both signs of (the radius) to represent the two possible curvature directions:
import numpy as np import matplotlib.pyplot as plt def half_circle(R, color): t = np.linspace(np.pi/2, 3*np.pi/2, 1000) X = R * np.cos(t) + R Y = R * np.sin(t) plt.plot(X, Y, color=color) plt.gca().set_aspect("equal") half_circle(10, "orange") half_circle(-10, "navy")
However, I want to do numerical optimization to find the best possible shape for lenses. This representation has two problems when used for optimization:
The solution I came up with is double:
Use curvature instead of radius. Curvature is the inverse of the radius: . This means a line is a circle of curvature zero. Brilliant!
Don't use the angle as the parameter, but the Y coordinate directly. This reduces the shapes we can model to only half-circles, but for optics that's not a problem!
So we know that the Y equation is easy: . But what about ? Well, I'll spare you the derivation, but here it is:
And that's a half-circle 🤩! We can also get the derivative with respect to , which is needed when doing collision detection with Newton's method (more on that in a future article maybe!)
import numpy as np import matplotlib.pyplot as plt def half_circle(R, color): t = np.linspace(-10, 10, 1000) K = 1/R X = (K * t**2) / (1 + np.sqrt(1 - t**2 * K**2)) Y = t plt.plot(X, Y, color=color) plt.gca().set_aspect("equal") half_circle(10, "orange") half_circle(-10, "navy")
Interestingly, to get some help because I suck at calculus double check my work, I asked both an LLM and Wolfram Alpha to derive the equation. Wolfram Alpha comes out on top with the final form, while LLM gets stuck and can't simplify all the way. They both show step-by-step derivation (although Wolfram Alpha's is behind a paywall).
ChatGPT4o mini (top, derivation not shown) vs Wolfram Alpha (bottom):