Background
Math SE's HNQ How to straighten a parabola? has 4,000+ views, ~60 up votes, 16 bookmarks and six answers so far and has a related companion HNQ in Mathematica SE How to straighten a curve? which includes a second part asking to move a point cloud along with the curve that we can ignore here.
From the Math SE question:
Consider the function \$f(x)=a_0x^2\$ for some \$a_0\in \mathbb{R}^+\$. Take \$x_0\in\mathbb{R}^+\$ so that the arc length \$L\$ between \$(0,0)\$ and \$(x_0,f(x_0))\$ is fixed. Given a different arbitrary \$a_1\$, how does one find the point \$(x_1,y_1)\$ so that the arc length is the same?
Schematically,
In other words, I'm looking for a function \$g:\mathbb{R}^3\to\mathbb{R}\$, \$g(a_0,a_1,x_0)\$, that takes an initial fixed quadratic coefficient \$a_0\$ and point and returns the corresponding point after "straightening" via the new coefficient \$a_1\$, keeping the arc length with respect to \$(0,0)\$. Note that the \$y\$ coordinates are simply given by \$y_0=f(x_0)\$ and \$y_1=a_1x_1^2\$.
Problem
Given a positive integer n and values a0 and a1 defining the original and new parabolas:
- Generate \$n\$ equally spaced values for \$x_0\$ from 0 to 1 and corresponding \$y_0\$ values.
- Calculate the new \$x_1\$ and \$y_1\$ such that their path distances along the new parabola are equal to their old distances.
- Output the \$x_0\$, \$x_1\$ and \$y_1\$ lists so that a user could plot the two parabolas.
note: The basis of the calculation can come from any of the answers to either linked question or something totally different. If you choose to use a numerical rather than analytical solution an error of \$1 \times 10^{-3}\$ would be sufficient for the user to make their plot.
Regular Code Golf; goal is shortest answer.
Example
This is quite a bit late but here is an example calculation and results. I chose the same numbers as in Eta's answer in order to check my math.
s0: [0.00000, 0.13589, 0.32491, 0.59085, 0.94211, 1.38218, 1.91278, 2.53486, 3.24903]
x0: [0.00000, 0.12500, 0.25000, 0.37500, 0.50000, 0.62500, 0.75000, 0.87500, 1.00000]
x1: [0.00000, 0.13248, 0.29124, 0.46652, 0.64682, 0.82802, 1.00900, 1.18950, 1.36954]
script:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import root
def get_lengths(x, a): # https://www.wolframalpha.com/input?i=integrate+sqrt%281%2B4+a%5E2x%5E2%29+x%3D0+to+1
return 0.5 * x * np.sqrt(4 * a**2 * x**2 + 1) + (np.arcsinh(2 * a * x)) / (4 * a)
def mini_me(x, a, targets):
return get_lengths(x, a) - targets
a0, a1 = 3, 1.5
x0 = np.arange(9)/8
lengths_0 = get_lengths(x0, a0)
wow = root(mini_me, x0.copy(), args=(a1, lengths_0))
x1 = wow.x
fig, ax = plt.subplots(1, 1)
y0, y1 = a0 * x0**2, a1 * x1**2
ax.plot(x0, y0, '-')
ax.plot(x0, y0, 'ok')
ax.plot(x1, y1, '-')
ax.plot(x1, y1, 'ok')
np.set_printoptions(precision=5, floatmode='fixed')
things = [str(q).replace(' ', ', ') for q in (lengths_0, x0, x1)]
names = [q + ': ' for q in ('s0', 'x0', 'x1')]
for name, thing in zip(names, things):
print(' ' + name + thing)
_, ymax = ax.get_ylim()
xmin, _ = ax.get_xlim()
ax.text(x0[-1:]+0.03, y0[-1:]-0.1, str(a0) + 'x²')
ax.text(x1[-1:]-0.04, y1[-1:]-0.1, str(a1) + 'x²', horizontalalignment='right')
title = '\n'.join([name + thing for (name, thing) in zip(names, things)])
ax.set_title(title, fontsize=9)
plt.show()