
1234

>However, I don't believe the shape of a bent physical strip in a general setting may be modeled by a cubic arc.
Yes that seems to be the case despite computer splines having their origin in physical splines. I am surprised there isn't an off the shelf solution for a uniform strip because I don't think the shape depends on anything other than the length and the endpoint position and orientation. I.e. I don't think it depends on its stiffness.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


If the ends are not "close" doesn't a catenary come very near to the actual solution? I agree it goes out the window if the two ends are close. On Sunday, December 24, 2017, nop head < [hidden email]> wrote: >However, I don't believe the shape of a bent physical strip in a general setting may be modeled by a cubic arc.
Yes that seems to be the case despite computer splines having their origin in physical splines. I am surprised there isn't an off the shelf solution for a uniform strip because I don't think the shape depends on anything other than the length and the endpoint position and orientation. I.e. I don't think it depends on its stiffness.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


I don't think so. A catenary forms under gravity with an infinitely flexible cord. It is all about tension along the tangent rather than curvature causing stress forces. The equation is a simple integral we did at school. I don't think the minimum energy curve has a simple mathematical formula.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


Here is the code of my atempts to find the cubic with minimum energy.
First note that AdjustBezier() finds the cubic with the desired length keeping the balance between the norms of the cubic endpoint derivatives. The strategy I used in the code was to change this balance in order to reduce the cubic energy.
// for any cubic bz, it holds bz == balance(bz, 0.5) bz[0] + 2*s*(bz[1]bz[0]), bz[3] + 2*(1s)*(bz[2]bz[3]),
For each balance, the cubic is adjusted to the target length by AdjustBezier() and its energy is calculated.
function BalancedEnergy(bz, s, l, eps) = BzEnergy(AdjustBezier(balance(bz,s), l, eps));
To find the balance that leads to the minimum energy is objective of an iterative search. The search for the cubic with minimum energy is done iteratively narrowing an interval (s1,s2) of balances that contains the best balance.
// Minimum energy Bezier arc with a given length l // and given tangent directions at its ends function BestBz(bz, l, eps=1e3) = let( bz2 = [ bz[0], // normalize end derivatives en1 = BalancedEnergy(bz, s1, l, eps), en2 = BalancedEnergy(bz, 1s1, l, eps), s = _bestS(bz2, l, s1, 1s1, en1, en2, eps) ) AdjustBezier(balance(bz2,s), l); function _bestS(bz, l, s1, s2, e1, e2, eps=1e3, n=15) = e12 = BalancedEnergy(bz, s12, l, eps)) //echo("in",s1=s1,s2=s2,s12=s12,e1=e1,e2=e2,e12=e12) abs(e12(e1+e2)/2)/e12< eps ? let( s3 = max(min(parabMin(s1,s12,s2,e1,e12,e2),1eps),eps) ) //echo(s1=s1,s3=s3,s2=s2,e1=e1,e12=e12,e2=e2,n=n) abs(s3s1)<eps  abs(s3s2)<eps  n==0 ? let( e3 = BalancedEnergy(bz, s3, l, eps) ) _bestS(bz,l,s1,s12,e1,e12,eps,n1) _bestS(bz,l,s12,s2,e12,e2,eps,n1) _bestS(bz,l,s3,s2,e3,e2,eps,n1) _bestS(bz,l,s1,s3,e1,e3,eps,n1);
The full code is annexed.
In the experiments I have done with the code, the plot of the cubic energy against the balance parameter s has the shape of an U with an almost horizontal bottom. This shows that the effect of mediumsized changes of the optimal balance does not produce significant changes of the cubic energy. In special, in your case of a strip going down from a fixed pole to a moving table clamped point, the optimal balance will change slowly from 0.5 (when the two end points are level) to 1 (when the strip is fully stretched). That means the balance of the cubic endpoint derivatives in the optimal solution is slightly favorable to the fixed point if the strip is never fully stretched. So, your assumption that "keeping the two inner control points level" would do the trick is not confirmed by my results.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


Here is my curve in red and its control points in blue alongside yours with my actual geometry. Your BzEnergy function returns 12 times the energy for mine which is hard to believe because mine has a more distributed curvature. A strip held against the screen follows mine, not yours, so I think there must be a bug in your energy function.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


The starting point is:
bzcp=[[0, 0, 0], [0, 0, 125.85], [0, 79.721, 125.85], [0, 79.721, 108.35]]; length=180;
After I adjust the control points for length I get [[0, 0, 0], [0, 0, 139.685], [0, 79.721, 139.685], [0, 79.721, 108.35]]
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


You are right. The energy function was wrong. At some point, I have made some change in it.
The correct (I hope) energy function should be:
function BzEnergy(b, n=8) = let( bs = subdivBezier3(b, n) ) [for(i=[0:3:len(bs)1]) pow(curvature(bs,i),2)] *[for(i=[0:3:len(bs)1]) 1]/pow(2,n1);
With this function, the plot of the cubic energy as a function of the balance s has a sharper minimum what is more reasonable.
I will try your data and compare.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


With the new function they are so close it is hard to tell. They match exactly when the ends are level, drift out about 3.5% on energy half way up and then get close again at the top. If I was to call it I think yours is the most accurate to the strip but mine is accurate enough at the end points, which is only case that needs to be accurate for the BOM. Particularly as the critical prediction is the length to get the correct minimum Z. The minimum z is only 0.2mm different.
It is very odd that they converge exactly just before my end point and then diverge rapidly again. With this h= 108*$t; bzcp=[[0,0,0],[0,0,50],[78,0,50h],[78,0,h]]; bzcp=[[0, 0, 0], [0, 0, 125.85], [0, 79.721, 125.85], [0, 79.721, h]]; They converge around about t = 0.945. Very odd.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


It is not odd to me. It was a coincidence that you get an almost level inner control points at the table lower position with the given length you have chosen. The factor that changes the bending energy for a given length is the balance between the two endpoint derivative and not the inner point positions. Along the table path from top to bottom the balance goes from 0.5 to 0.798 and that is what maters.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


Although your s value covers that range your control points are
never far from level and the curves are never much different in shape or
minimum z over the full movement. What I find odd is both versions
exactly match at three points. No surprise they match in the middle.
For my code to work I need to start with the control points level because I adjust them as follows
function adjust_bezier(v, r) = let(extension = (v[1]  v[0]) * (r  1)) [v[0], v[1] + extension, v[2] + extension, v[3]];
Your
code works with my control points. If I give it control points that
have equal endpoint lengths like your original code then it produces a
slightly different result that actually has higher energy at the end
point than mine.
E.g. bzcp=[[0, 0, 0], [0, 0, 125.85], [0, 79.721, 125.85 + h], [0, 79.721, h]]; bzcp2=[[0, 0, 0], [0, 0, 125.85], [0, 79.721, 125.85], [0, 79.721, h]];
It gives a slightly lower energy result staring with bzcp2 when h = 108. Probably a numerical accuracy issue.
I made a video and that seems to show some numerical instability. https://youtu.be/6t8Taul_4Rw
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


I think subdivBezier3 may have a bug in it. It seems to produce a path that has segments with zero curvature. I.e. subtracting adjacent tangents produces zero. E.g. path = subdivBezier3(bezier, 4); for(i = [1 : len(path) 2]) echo(path[i+1]path[2]  (path[i]path[i1])); ECHO: [0, 0.31141, 0.258989]
ECHO: [0, 0.31141, 0.258989]
ECHO: [0, 0.272484, 0.272173]
ECHO: [0, 0, 3.55271e015]
ECHO: [0, 0.272484, 0.272173]
ECHO: [0, 0.233558, 0.285357]
ECHO: [0, 0, 0]
ECHO: [0, 0.233558, 0.285357]
ECHO: [0, 0.194631, 0.29854]
ECHO: [0, 0, 0]
ECHO: [0, 0.194631, 0.29854]
ECHO: [0, 0.155705, 0.311724]
ECHO: [0, 0, 7.10543e015]
ECHO: [0, 0.155705, 0.311724]
ECHO: [0, 0.116779, 0.324907]
ECHO: [0, 3.55271e015, 7.10543e015]
ECHO: [0, 0.116779, 0.324907]
ECHO: [0, 0.0778525, 0.338091]
ECHO: [0, 3.55271e015, 0]
ECHO: [0, 0.0778525, 0.338091]
ECHO: [0, 0.0389263, 0.351274]
ECHO: [0, 7.10543e015, 0]
ECHO: [0, 0.0389263, 0.351274]
ECHO: [0, 0, 0.364458]
ECHO: [0, 0, 0]
ECHO: [0, 0, 0.364458]
ECHO: [0, 0.0389263, 0.377642]
ECHO: [0, 7.10543e015, 0]
ECHO: [0, 0.0389263, 0.377642]
ECHO: [0, 0.0778525, 0.390825]
ECHO: [0, 0, 7.10543e015]
ECHO: [0, 0.0778525, 0.390825]
ECHO: [0, 0.116779, 0.404009]
ECHO: [0, 7.10543e015, 0]
ECHO: [0, 0.116779, 0.404009]
ECHO: [0, 0.155705, 0.417192]
ECHO: [0, 1.42109e014, 1.77636e015]
ECHO: [0, 0.155705, 0.417192]
ECHO: [0, 0.194631, 0.430376]
ECHO: [0, 0, 1.77636e015]
ECHO: [0, 0.194631, 0.430376]
ECHO: [0, 0.233558, 0.44356]
ECHO: [0, 0, 0]
ECHO: [0, 0.233558, 0.44356]
ECHO: [0, 0.272484, 0.456743]
ECHO: [0, 0, 7.10543e015]
ECHO: [0, 0.272484, 0.456743]
ECHO: [0, 0.31141, 0.469927]
ECHO: [0, 0.31141, 0.469927]
There shouldn't be any zero curvature sections in this curve.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


There is a small typo in your last code. Anyway, the output of subdivBezier3() should be fully understood in order to compute the curvature correctly.
ShowBezier(bzcp,t=0.5); ShowPolygonal(bzcp,t=0.7); sbz = subdivBezier3(bzcp,n=2); for(i=[0:len(sbz)1]) translate(sbz[i]) if(i%3) color("red") sphere(1.5); else color("blue") sphere(1.5);
The dots are the points of the sequence generated by subdivBezier3(). The four dots between (and including) two subsequent blue dots are the control points of the arc going from one to the other. The curvature at each blue dot may be computed either by considering the two subsequent red dots or the two previous ones. If you take a blue dot, one before and one after, a zero curvature would result because those three points are always colinear. I don't see any bug there.
The numerical instability may be in the _bestS() code, the method of finding the energy minimizing curve. I am looking for a bug there.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


Yes there is an erroneous 2 in my code but the output I posted was correct.
The confusing thing is you draw the Bezier curve with the results from subdivBezier3 but its output isn't a Bezier curve. To speed up drawing I passed it to my Frenet sweep and it choked.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


The result of subdivBezier3() is not a sequence of points in the curve. It is a sequence of control points of partial arcs of the incoming curve. So, just a third of its points are actually on the curve. You will have troubles computing Frenet frame for the sequence because there are many subsequences of 3 colinear points in it. The sequence generated by subdivBezier3(bz,n) is a polygonal that approximates the curve. The greater the value of n the better is the approximation. The sequence length grows exponentially with n, though. It is faster to subdivide than to evaluate an equal number of points points in the curve and the convergence rate is better.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

1234
