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.

NEED HELP ON FS

papawopapawo Member, Developers Posts: 206 PRO
Tagged:

Comments

  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    edited December 2017
    A few ideas here:

    If this entire process is happening in FeatureScript, I would just sketch the rectangle in the position you actually want it rather than trying to move it around.  You could also accomplish this entire case with "fCuboid" but I assume this is just a simplified version of something more generic.

    The best way to do exactly what you want to do would be the following:
    1. Use opExtractSurface to turn the sketch face into a surface.
    2. Find the Plane at the center of the surface using evFaceTangentPlane with a parameter of (0.5, 0.5)
    3. Find the point and direction at the end of the edge using evEdgeTangentLine (*see node below)
    4. Change the found tangent line into a plane using Plane(tangentLine.origin, tangentLine.direction)
    5. Construct your transform using transform(faceTangentPlane, edgeEndPlane)
    6. Transform the surface using opTransform(...)
    7. Sweep using opSweep
    * Note on how to find the tangent line:
    You may need to take in a helper point for the end of the line you care about and do something like the following to figure out which parameter to use:
    const tangentLines = evEdgeTangentLines(context, "edge" : definition.sweepEdge, "parameters" : [0, 1]);
    const helperPoint = evVertexPoint(context, {"vertex" : definition.vertexToStartSweep});
    
    var edgeEndPlane;
    const zeroLengthSq = TOLERANCE.zeroLength * TOLERANCE.zeroLength;
    // Find whether the "0" or "1" end of the sweep edge is the selected start point
    if (squaredNorm(tangentLines[0].origin - helperPoint) < zeroLengthSq)
    {
        edgeEndPlane = Plane(tangentLines[0].origin, tangentLines[0].direction);
    }
    else if (squaredNorm(tangentLines[1].origin - helperPoint) < zeroLengthSq)
    {
        edgeEndPlane = Plane(tangentLines[1].origin, tangentLines[1].direction);
    }
    else
    {
        throw "Selected start point did not lie on the sweep edge";
    }
    ^ There are a number of different ways to do something like this, this was just the first that came to mind.


    This was a pretty high level explanation, and I'm not sure of your programming experience in FS.  Please let me know if you'd like a more detailed explanation or have any specific questions.

    Jake Rosenfeld - Modeling Team
  • papawopapawo Member, Developers Posts: 206 PRO
    Yes, this is advanced for me. I'm a newbie in FS. Im learning FS thru the samples and here  in forum. The rectangle has to be move to either end and it has to be in the front plane with the straight line at first. can you please code it in a simplier way as Im am learning the basic first. Thanks for your response.
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    edited December 2017
    Hi @Nan_Cp ,

    I'm not sure there's a simpler way to do this, but I can try to make the process clearer.  Would you prefer if I write a custom feature that does this for you so you can use it as a sample to learn from, or would you prefer that I write a more detailed description so that you can try to do it yourself?
    Jake Rosenfeld - Modeling Team
  • papawopapawo Member, Developers Posts: 206 PRO
    edited December 2017
    i have a FS that I modified to work for my particular problem but im stuck in where i am supposed to sweep the transformed sketch.. a sample and a detailed description would be good. or i can give you a link of my prob.
    https://cad.onshape.com/documents/57ffe78b4a526810dcbb1fc9/w/b5546fa462ee9ea8409fb580/e/9ffafc49f03e2e027ce54c34
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    Hi @Nan_Cp !

    I've made a custom feature for this, and hopefully the code itself, the comments in the code, and my initial explanation will be enough to piece together a picture of how to do this.

    https://cad.onshape.com/documents/33258f05b113f6aad79dc7f9/w/7bbd4ad8c1b9d6d2dee33a83/e/1116aeea70b5188e5859cb93

    In the provided document, I've made two features: "Transform sweep - simple" and "Transform sweep - advanced".
    Simple is useful as a learning tool to see the basic MVP (minimum viable product) for something like this.  As in my initial explanation it does the following:
    1. Copy the desired sketch as a surface
    2. Collect information about where the sketch is and where the line is
    3. Transform the surface to be at the start of the line
    4. Sweep the surface over the line
    5. Delete the helper surface (so as not to have a random surface hanging around in the part studio)
    The code is pretty simple for this, I think if you take a look, it'll be straightforward to see what's going on.  This simple version can be found in the feature studio called "simple".

    To augment this, "Transform sweep - advanced" can be found in the feature studio called "advanced".  This feature augments the original feature such that:
    1. It can take in multiple profile faces (instead of just one) as long as they are all coplanar and touching.
    2. The angle that the profile meets the sweep edge can be adjusted (this angle is not well defined in "simple", any angle of the profile on the sweep edge could satisfy your original problem statement, but it's nice to give the user some control over this)
    3. The path can be multiple connected edges instead of just one edge.

    As always, happy to answer any questions you may have after seeing this.
    Jake Rosenfeld - Modeling Team
  • papawopapawo Member, Developers Posts: 206 PRO
    Thank you so much. This is perfect!. You're simple and advance is a great tool for me to refresh what I have learn last year . 
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    No problem! Happy to help.
    Jake Rosenfeld - Modeling Team
  • papawopapawo Member, Developers Posts: 206 PRO
    Jake,
    In your "Transform sweep - simple", instead of filtering  entitytype:face , how can I change it to select featureList? 
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    edited January 2018
    @Nan_Cp
    You can replace the two lines with in the precondition for definition.profile with the following:
    annotation { "Name" : "Profile to sweep" }
            definition.profile is FeatureList;
            
    Then, like the feature discussed in this thread, add that qCreatedBy function to the bottom of the Feature Studio, and add the following line to the top of your feature.
    const profileEntities = qCreatedBy(definition.profile);
    Finally, for every place that previously referred to "definition.profile" , change that to "profileEntities" so the new full query will be used.


  • papawopapawo Member, Developers Posts: 206 PRO
    I like to replace this using the featurelist as this is simple for me to digest
    but replacing it doesnt work. can you point me what is wrong.
    ___________
    annotation { "Feature Type Name" : "Test-using profile" }
    export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            
            annotation { "Name" : "Profile to sweep" }
            definition.profile is FeatureList;
            
            annotation { "Name" : "Edge to sweep along", "Filter" : EntityType.EDGE, "MaxNumberOfPicks" : 1 }
            definition.path is Query;


        }
        {
            const profileEntities = qCreatedBy(definition.features);  //i have error on this line saying no matching function
            
            opExtractSurface(context, id + "extract", {
                        "faces" : profileEntities
                    });
            const surface = qCreatedBy(id + "extract", EntityType.BODY);

         
            const facePlane = evFaceTangentPlane(context, {
                        "face" : profileEntities,
                        "parameter" : vector(0.5, 0.5)
                    });
            const edgeTangent = evEdgeTangentLine(context, {
                        "edge" : definition.path,
                        "parameter" : 0
                    });
            const edgePlane = plane(edgeTangent.origin, edgeTangent.direction);

           
            opTransform(context, id + "transform", {
                        "bodies" : surface,
                        "transform" : transform(facePlane, edgePlane)
                    });
                    
             opSweep(context, id + "sweep", {
                    "profiles" : qOwnedByBody(surface, EntityType.FACE),
                    "path" : definition.path
            });


            opDeleteBodies(context, id + "deleteSurface", {
                    "entities" : surface
            });
        });
        
            
    export  function qCreatedBy(features is FeatureList) returns Query
    {    
        
        var query = [];
        for (var feature in features)
            query = append(query, qCreatedBy(feature.key));
        return qUnion(query);
    }
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    My apologies. I had an error in an earlier version of the post. The line you commented on should be
     const profileEntities = qCreatedBy(definition.profile);
    This line uses the "definition.profile" defined above in the feature. If that name doesn't match the parameter name, it will have no value (that is, it will be "undefined"), which causes the error you saw.


  • lanalana Onshape Employees Posts: 689
    const profileEntities = qCreatedBy(definition.profile);
    Will not quite work either.
    It should be 
    var faceQueryArr = [];<br>for (featureEntry in definition.profile)<br>{<br>&nbsp; &nbsp; &nbsp;faceQueryArr = append(faceQueryArr,&nbsp;qCreatedBy(featureEntry.key, EntityType.FACE));<br>}<br>const profileFaces = qUnion(faceQueryArr);


  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    @lana In the other thread (and Nancy's code above) we defined that exact code as a function overload. Perhaps it's a good candidate for us to add to the standard library :smile:
  • lanalana Onshape Employees Posts: 689
    Sorry, missed that part of the discussion. Agree, about adding it to the std.
  • papawopapawo Member, Developers Posts: 206 PRO
    @lana do I have to replace the function qcreatedBy with your code? if so, i tried it and doesnt work.
  • lanalana Onshape Employees Posts: 689
    @Nan_Cp No need to replace qCreatedBy call, if you have the implementation of qCreatedBy(FeatureList) from the other thread
  • papawopapawo Member, Developers Posts: 206 PRO
    so I should replace ---------const profileEntities = qCreatedBy(definition.profile);
    with your code, if so its still doesnt work
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    edited January 2018
    @Nan_Cp

    The only thing you need to change from the code you pasted above is that:
    const profileEntities = qCreatedBy(definition.features);
    should be:
    const profileEntities = qCreatedBy(definition.profile);
    Because the input variable in your feature is defined as 'definition.profile', not 'definition.features'.  The qCreatedBy function that you've defined at the bottom of your file will take care of what Lana is telling you to do.

    Calling it this way will give you everything created by the feature list that you take in.  That means it will give you all the vertices, edges, faces, and bodies created by the selected features. You can see that this is the case if you add the line "debug(context, profileEntities);", which will print out for you the contents of the "profileEntities" query.

    Once you make that change, you'll most likely have a new error on "opExtractSurface"! This is because you're then trying to pass these "profileEntities" (which currently include vertices, edges, faces, and bodies) into "opExtractSurface", but "opExtractSurface" only takes faces.  This wasn't a problem in your old code because definition.profile was explicitly only taking faces.  What you'll want to do to fix this is replace the line we're working on with:
    const profileEntities = qEntityFilter(qCreatedBy(definition.profile), EntityType.FACE);
    which gets all the entities created by the selected features, and then filters out everything that isn't a face.

    Now if you do "debug(context, profileEntities)", you will see that that query only refers to the created faces of the selected features.


    After you make this small change, please comment if there are more errors!
    Jake Rosenfeld - Modeling Team
  • papawopapawo Member, Developers Posts: 206 PRO
    edited January 2018
    @Jake_Rosenfeld
    No more error. :smile:
    Thank you so much!! your explanation helps a lot! 
Sign In or Register to comment.