Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

How to create a Natural Spline / Minimal-Energy Spline

sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
I'm working on a new FeatureScript to quickly create hose routings:

In the FeatureScript I can select a start, end and midpoints. A fitspline is going through all points.
  • Now I would like to know how to create a "Natural Spline / Minimal-Energy Spline" This means that the spline should behave like a bend hose/wire.
  • Can I define a minimal bend radius? This is necessary for pneumatic hoses.
  • Is there a way to type in the length of the spline and fix that value?
  • Does anyone know what the parameters in the fitspline command do and how they are used?


Thanks :smile:

Comments

  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    @sebastian_glanzner

    The documentation there seems to be saying that you can specify an explicit parameterization for each point of the spline.

    An example:

    • points = [A, B, C]
    • parameters = [0, .9, 1]
    A spline will be created passing through A, B, and C.  90% of the length of the spline will be between A and B.  10% will be between B and C.

    I'm turning your actual question over in my head but I don't have a great answer yet.  I'll ask around.
    Jake Rosenfeld - Modeling Team
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,173
    The parameterization specified is not length, but rather the "natural" spline parameterization (if omitted, centripetal is used, which means proportional to the square root of the chord length).

    The answer to the original question is that the requirements you describe (minimum bending energy, at least given bend radius, fixed length) all require nonlinear optimization -- there is no easy answer.

    For shapes such as what you're looking for, I'd start by not having any intermediate points and just optimizing over start and end derivatives.  You won't get great answers, but you'll get simple curves that work reasonably.  If you actually do try more complete optimization (which I would not recommend if your goal is to do something relatively quickly), opCreateBSplineCurve will probably be better, as at least the derivative matrix of positions as a function of control points is sparse.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
    @Jake_Rosenfeld
    Thanks for the explanation of the parameters!

    @ilya_baran
    Thanks for your suggestions! I'm now using splines with two points and startDerivative and endDerivative, it looks quite good!

    I create 4 splines for each segment (one for each combination of normal-directions) and select only the shortest spline for the sweep.
    This way the user does not have to select the correct directions :)



  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    @sebastian_glanzner

    If you want to avoid doing four geometric operations and then deleting 3 of them, consider the following algorithm for each side:
    1. Consider one profile "current" and the other profile as "other"
    2. Pick an arbitrary point on the current profile
    3. Pick an arbitrary point on the other profile
    4. Subtract the current point from the other point and normalize to get a vector that points in the direction from current to other.
    5. Consider the two options of normal directions that you have at the current profile.  If you take their dot product with the current->other vector, the normal that points "towards" the other profile will have a positive dot product.  The normal that points "away from" the other profile will have a negative dot product.  Use the normal that points towards.
    6. Repeat with the other profile! 
    Jake Rosenfeld - Modeling Team
  • sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
    @Jake_Rosenfeld
    Thank you very much! This was exactly what I needed!

    I will release a public version as soon as I cleaned up the code and tested it.
  • romeograhamromeograham Member Posts: 656 PRO
    This looks like an awesome FS. Looking forward to trying it out when it's available.
  • owen_sparksowen_sparks Member, Developers Posts: 2,660 PRO
    This looks like an awesome FS. Looking forward to trying it out when it's available.
    Likewise :+1:
    Owen S.
    Business Systems and Configuration Controller
    HWM-Water Ltd
  • sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
    The FS is almost complete. I ran into a special case which my FS could not handle.

    If a spline starts and ends in the same plane I get an "S" Shaped spline as result.
    So I tried to create two alternative spline with the end normal switched:


    Now I have get Onshape to select the correct spline automatically. Unfortunately I can't select the shortest spline, because that would be the "S".
    But the Curvature shows which is the "better" spline:



    So I used evEdgeCurvatures() to get the curvature along the spline at multiple points. Then I search for the max curvature, compare it with the max curvature of the other spline and select the curve with the lowest value.

    But I have to do this for at least 20 points along the curve and this cost a lot of time. 

            var parameterCurvature = [];
            var indexCurvature = [];
    
            for (var i = 0; i < 21; i += 1)
            {
                parameterCurvature = append(parameterCurvature, roundToPrecision(1 / 20 * i, 2));
                indexCurvature = append(indexCurvature, i);
            }
    
            var curvatureAlternativeA = 0;
            var curvatureMaxAlternativeA = 0;
    
            var currentCurvature;
    
            curvatureAlternativeA = evEdgeCurvatures(context, {
                "edge" : qCreatedBy(id + ("splineA" ~ i), EntityType.EDGE),
                "arcLengthParameterization" : true,
                "parameters" : parameterCurvature
            });
    
            for (var i = 0; i < size(indexCurvature); i += 1)
            {
                currentCurvature = abs(curvatureAlternativeA[i].curvature * meter);
                if (currentCurvature > curvatureMaxAlternativeA)
                {
                     curvatureMaxAlternativeA = currentCurvature;
                }
            }        

    Does anyone know how I can get the max curvature of a spline without this iteration?
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 2,034 EDU
    Could you check if the planes are coplanar and make the directions the same if they are?
    mb - draftsman - also FS author: View FeatureScripts
    IR for AS/NZS 1100
  • sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
    Interesting idea!
    I will have to try that, thanks  :)

    I could also check if the next point is exactly in the normal direction of the first point.
    If true, this segment can be a line instead of a spline :)
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 2,034 EDU
    Also, if they are coplanar, you will want a "Flip direction" option.
    mb - draftsman - also FS author: View FeatureScripts
    IR for AS/NZS 1100
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    @sebastian_glanzner @MBartlett21

    One of the tricks we use internally is that we would make a feature like this take only sketch points, and then use the normal of `evOwnerSketchPlane` as the normal of each point.  Flips could be applied to this if necessary, but in the ambiguous case, just trust the user's sketch plane (and they can select a different plane if its wrong)
    Jake Rosenfeld - Modeling Team
  • owen_sparksowen_sparks Member, Developers Posts: 2,660 PRO
    I was hoping the point of this FS was to not have to create many many sketch points.  Instead the user would be selecting circular edges or faces?
    Business Systems and Configuration Controller
    HWM-Water Ltd
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    @owen_sparks

    Circular face does not define a center point, just a center axis.
    Circular edge is nice because it probably has a circular or cone face coming off one side of the edge, and a plane or similar coming off the other side of the edge (assuming the body is solid, which implies there are two faces attached to the edge).  In a case like that it seems (from the given examples) that the edge wants to go away from the circular face.

    Another thing that could be done is that the selection could be an array parameter, each of whose inputs has a selection and a direction flip, which would override the original heuristic that is being applied.
    Jake Rosenfeld - Modeling Team
  • owen_sparksowen_sparks Member, Developers Posts: 2,660 PRO
    @Jake_Rosenfeld Sounds sensible, thanks for the explanation

    @sebastian_glanzner Could you have it evaluate the length of the part created and stick it in a custom part property?  For example I have a property called "Raw_Material_Length" within my company, so the BOM can call for a specific length of material to be cut for each run.

    @Jake_Rosenfeld my BOM length idea falls over as a custom property is only for one company.  Is there an easy way around this?  Presumably even if a pair of companies sets custom properties with the same "friendly text name" the internal ID will be different so it'll still fall over?

    Cheers,
    Owen .
    Business Systems and Configuration Controller
    HWM-Water Ltd
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    edited February 2019
    I think the naive solution would be to just take the internal id as an optional parameter, and then have another featurescript that sets a variable to that internal parameter automatically, so you'd just have to press a button to add the variable to your PS, and then pass in `#mat_len_id` variable into this other fs.

    A long term solution might be that your company could own their own branch of this FS, which incorporates an additional small piece of code to mark that property as desired.  But as it currently stands you would need to copy the FS, and incorporate it, which maintains no associativity to the original FS.  Internally we are always thinking about stuff like being able to keep your own "fork" of a FeatureScript and pull updates from the master while keeping your own company changes private, but I think the solutions others have been using right now is to create a repository on GitHub for the feature, and maintain a fork there.  The project to improve these kinds of workflows is more on the horizon than knocking on the door.
    Jake Rosenfeld - Modeling Team
  • owen_sparksowen_sparks Member, Developers Posts: 2,660 PRO
    Sounds good to me, thanks!
    Owen S.
    Business Systems and Configuration Controller
    HWM-Water Ltd
  • owen_sparksowen_sparks Member, Developers Posts: 2,660 PRO
    @Jake_Rosenfeld Hmm thinking about this further...  How about the original FS could trying writing to a number of parameter ID's.  Then providing one of the tries completes the feature could be declare itself happy.  We as users could submit our ID's to the original author and only need one copy of the script to be maintained.  Presumably it failing to write to a parameter would be pretty quick, so it wouldn't slow the regen much?

    @sebastian_glanzner - Sorry for the thread hijack.
    Business Systems and Configuration Controller
    HWM-Water Ltd
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    edited February 2019
    @owen_sparks

    I think the regen would be fine, but it seems like it's making a company-specific change to a geometric feature that is otherwise completely general.

    Also, it would expose the internal ids of your company to the public eye, which isn't the worst thing in the world but probably not ideal?  

    I do think that your idea would work functionally, and feel free to move forward with it if Sebastian agrees, but I don't think it's a great design decision.


    I think a better design from the FS designer point of view would be to introduce a "keep curve" option which would keep the original curve around in the curve list on the left.  Then it would be super easy to write an additional FeatureScript which takes the curve, measures its length, and sets whatever properties you want on another selected body (it could even then take charge and delete those curves if you want).

    In FS curves are called "wire bodies".  I have called them curves above ^ because it is very ambiguous what I mean when I say "wire body" in a thread about making solid bodies to represent wiring :):)
    Jake Rosenfeld - Modeling Team
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 2,034 EDU
    Or you could have an input for the company's parameter's id
    mb - draftsman - also FS author: View FeatureScripts
    IR for AS/NZS 1100
  • sebastian_glanznersebastian_glanzner Member, Developers Posts: 398 PRO
Sign In or Register to comment.