Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- 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
papawo
Member, Developers Posts: 206 PRO
Comments
-
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:- Use opExtractSurface to turn the sketch face into a surface.
- Find the Plane at the center of the surface using evFaceTangentPlane with a parameter of (0.5, 0.5)
- Find the point and direction at the end of the edge using evEdgeTangentLine (*see node below)
- Change the found tangent line into a plane using Plane(tangentLine.origin, tangentLine.direction)
- Construct your transform using transform(faceTangentPlane, edgeEndPlane)
- Transform the surface using opTransform(...)
- Sweep using opSweep
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 Team1 -
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.0
-
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 Team2 -
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
0 -
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:- Copy the desired sketch as a surface
- Collect information about where the sketch is and where the line is
- Transform the surface to be at the start of the line
- Sweep the surface over the line
- Delete the helper surface (so as not to have a random surface hanging around in the part studio)
To augment this, "Transform sweep - advanced" can be found in the feature studio called "advanced". This feature augments the original feature such that:- It can take in multiple profile faces (instead of just one) as long as they are all coplanar and touching.
- 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)
- 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 Team1 -
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 .1
-
No problem! Happy to help.Jake Rosenfeld - Modeling Team0
-
Jake,
In your "Transform sweep - simple", instead of filtering entitytype:face , how can I change it to select featureList?0 -
@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.
0 -
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 functionopExtractSurface(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);}0 -
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.
0 -
const profileEntities = qCreatedBy(definition.profile);Will not quite work either.
It should bevar faceQueryArr = [];<br>for (featureEntry in definition.profile)<br>{<br> faceQueryArr = append(faceQueryArr, qCreatedBy(featureEntry.key, EntityType.FACE));<br>}<br>const profileFaces = qUnion(faceQueryArr);
0 -
@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

0 -
Sorry, missed that part of the discussion. Agree, about adding it to the std.0
-
@Nan_Cp No need to replace qCreatedBy call, if you have the implementation of qCreatedBy(FeatureList) from the other thread0
-
so I should replace ---------const profileEntities = qCreatedBy(definition.profile);
with your code, if so its still doesnt work0 -
@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 Team1 -
1


