Improved numerical accuarcy of catenary calculations.
This commit is contained in:
parent
1255e71271
commit
a7803b1efb
|
@ -5268,7 +5268,7 @@ The coordinates of the lowest point on the curve can be retrieved by calling ```
|
|||
|:--- |:--- |
|
||||
| ```catenary(t, a)``` | Parametric catenary function linear along the length of the curve. |
|
||||
| ```catenary_ds_by_da(d, a)``` | First derivative of the length with respect to ```a```. |
|
||||
| ```catenary_find_a(d, l, a = 1)``` | Find the catenary constant ```a```, given half the horizontal span and the length. |
|
||||
| ```catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1)``` | Find the catenary constant ```a```, given half the horizontal span and the length. |
|
||||
| ```catenary_points(l, x, y, steps = 100)``` | Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```. |
|
||||
| ```catenary_s(d, a)``` | Length of a symmetric catenary with width ```2d```. |
|
||||
|
||||
|
|
|
@ -33,21 +33,20 @@ function catenary(t, a) = let(u = argsinh(t)) a * [u, cosh(u)]; //! Parametric c
|
|||
function catenary_s(d, a) = 2 * a * sinh(d / a); //! Length of a symmetric catenary with width ```2d```.
|
||||
function catenary_ds_by_da(d, a) = 2 * sinh(d / a) - 2 * d / a * cosh(d / a); //! First derivative of the length with respect to ```a```.
|
||||
|
||||
function catenary_find_a(d, l, a = 1) = //! Find the catenary constant ```a```, given half the horizontal span and the length.
|
||||
assert(l > 2 * d, "Not long enough to span the gap") assert(d)
|
||||
abs(catenary_s(d, a) - l) < 0.0001 ? a
|
||||
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), 0.001));
|
||||
function catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1) = //! Find the catenary constant ```a```, given half the horizontal span and the length.
|
||||
assert(l > 2 * d, "Not long enough to span the gap") assert(d) let(error = abs(catenary_s(d, a) - l))
|
||||
error >= best_e && error < 0.0001 ? /*echo(best=best_e, a = best_a)*/ best_a
|
||||
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), d / argsinh(1e99)), error, a);
|
||||
|
||||
function catenary_points(l, x, y, steps = 100) = //! Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```.
|
||||
let(
|
||||
d = x / 2,
|
||||
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y)), d / 2), // Find a to get the correct length
|
||||
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y))), // Find a to get the correct length
|
||||
offset = argsinh(y / catenary_s(d, a)),
|
||||
t0 = sinh(-d / a + offset),
|
||||
t1 = sinh( d / a + offset),
|
||||
h = a * cosh(-d / a + offset) - a,
|
||||
lowest = offset > d / a ? [0, 0] : offset < -d / a ? [x, y] : [d - offset * a, -h],
|
||||
//dummy = echo(l = l, d = d, a = a, t0=t0, t1=t1, sinh(d / a), s = catenary_s(d, a), offset = offset * a, h = h),
|
||||
p0 = catenary(t0, a)
|
||||
)
|
||||
steps ? [for(t = [t0 : (t1 - t0) / steps : t1]) catenary(t, a) - p0] : lowest;
|
||||
|
|
Loading…
Reference in New Issue