This investigation was born out of work on calculating stats on running data. The Haversine formula is good for calculating distance along the great circle for two sets of latitude/longitude. The formula however does not account for elevation changes. Other solutions incorporate the Pythagorean Theorem to compensate for the additional elevation changes. For a long enough distance a linear increase in altitude actually follows a curved path known as an Archimedean spiral.
The archimedean spiral is a path that forms where the radius of the spiral increases linearly with $\theta$. This spiral occurs in situations with spooled material such as coiled wire or spools of paper.
In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Goal: Create a function that calculates the distance for a section of an Archimedean spiral.
In [2]:
theta_0 = np.pi / 2 * 3
theta_f = np.pi / 2 * 11
r0 = 1.5
thickness = 2
thetas = np.linspace(theta_0, theta_f, 10000)
drdtheta = thickness / (2 * np.pi)
r = [drdtheta * (theta - theta_0) + r0 for theta in thetas]
pts = [(r*np.cos(theta), r*np.sin(theta)) for r, theta in zip(r, thetas)]
In [3]:
plt.plot(*zip(*pts))
plt.grid()
lim = np.ceil(max(r))
plt.xlim([-lim,lim])
plt.ylim([-lim,lim]);
In [4]:
l_est = 0
last_pt = None
for pt in pts:
if last_pt is not None:
dl = np.sqrt((pt[0] - last_pt[0])**2 + (pt[1] - last_pt[1])**2)
l_est += dl
last_pt = pt
print(l_est)
where
$ a = T / 2 \pi \\ \phi = r / a \\ r = \text{radius} \\ T = \text{change in radius for each full turn} \\ $
In [5]:
T = 2 # Thickness between spirals
r0 = 1.5 # Starting radius
rf = 5.5 # Ending radius
def archimedean_length(r0, rf, T):
def limit(radius, thickness, a):
phi = radius / a
return phi * np.sqrt(1+phi**2)+np.log(phi+np.sqrt(1+phi**2))
a = T / (2 * np.pi)
return a / 2 * (limit(rf, T, a) - limit(r0, T, a))
print(archimedean_length(r0, rf, T))
References:
In [5]: