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.
How do you bring numbers in as a precondition
ron_moreland
Member Posts: 99 ✭✭✭
I want to bring a simple unitless number in as a multiplier. I also want to restrict the range and assign a default value.
annotation { "Name" : "Scale" }
isLength(definition.scale, { (inch) : [1, 1.059463, 1.07463] } as LengthBoundSpec);this works, but I think I want this:annotation { "Name" : "Scale" }
isLength(definition.scale, { (unitless) : [1, 1.059463, 1.07463] } as LengthBoundSpec);which doesn't. Should I bring it in as an "inch" then divide by"inch" later?
Tagged:
0
Best Answer
-
annotation { "Name" : "My Number" }isReal(definition.myCount, { (unitless) : [0, 1, 6] } as RealBoundSpec);Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc5
Answers
-
annotation { "Name" : "My Number" }isReal(definition.myCount, { (unitless) : [0, 1, 6] } as RealBoundSpec);Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc5
-
isReal. I tried float, double.. the usual suspects.
Thanks0 -
@ron_moreland, the FeatureScript help page has a wealth of information. OS does a pretty good job on documentation.0
-
I agree the documentation is good. What I find frustrating is a lack of conceptual training. Featurescript operates at a very abstracted level. I'm used to arrays of vertices/connected faces, pretty low-level stuff. Here's an example from evDistance:
EXAMPLE
result = evDistance(context, { "side0" : qEverything(EntityType.VERTEX), "side1" : qEverything(EntityType.VERTEX), "maximum" : true })computes the pair of vertices farthest apart.qNthElement(qEverything(EntityType.VERTEX), result.sides[0].index)queries for one of these vertices.
Everything is queries. Not an array in sight, except "sides[0]", and what the heck is it doing there? For someone with my background, it's very hard to get my head around. It's difficult to know if I'm passing the correct parameters and hard to decipher what came back.0 -
I felt the same way at first and still do to some degree. However, once you wrap your head around the queries, it's a very flexible and powerful way to work. You're not locked into explicitly declared variables or ordered arrays. Everything has context. The second thing you selected isn't just selection[1], it's instead identified by what kind of entity and/or body it is. Getting queries to do what you want can be annoying, but I like it
0 -
Here's another example. I want to use "canBePlane()". Here's the documentation:
canBePlane (value) predicate
Typecheck for
PlaneWhat is "value"? I think I've passed it a plane, or a planar face, but it always fails. Should it be a query? a map? either?
I know featurescript is incredibly powerful, but where I am, I spend most of my time trying to determine if what I'm asking for and getting are correct. Very little time is spent on data manipulation.
0 -
From what I can tell, all of the various canBeX(Y) functions just check to make sure that variable Y is actually of type X. So if you pass it an object of type Plane, canBePlane() will return true. Otherwise, it's false. You can pass whatever you want to canBePlane(), but it will only return true if you're passing it something of datatype Plane (not just a flat surface). Here's the help file for predicates, of which typeChecks are one type.1
-
Hi @ron_moreland
I saw your discussions in this thread and the other thread, and thought it may be useful to clear up some stuff about types in FeatureScript.
For every type <X> in FeatureScript there is a canBe<X>() method, which is the typecheck for that type. You should never need to actually call the canBe<X>() method, its just a construction for declaring types.
Some examples of types in FeatureScript:- Query
- Vector
- Matrix
- Transform
- Line
- Plane
- BoundingBox
- ValueWithUnits (length, angle, volume, etc)
var planeQuery = qNthElement(qGeometry(qEverything(EntityType.FACE), GeometryType.PLANE), 0); var isPlane1 = planeQuery is Plane; // false var isQuery1 = planeQuery is Query; // true var planeEvaluated = evPlane(context, { "face" : planeQuery }); var isPlane2 = planeEvaluated is Plane; // true var isQuery2 = planeEvaluated is Query; // falseIf you look in the documentation, you'll see that evPlane returns a 'Plane':
https://cad.onshape.com/FsDoc/library.html#evPlane-Context-map
And that a 'Plane' is just a special map that contains the mathematical information about a plane in 3D space:
https://cad.onshape.com/FsDoc/library.html#Plane
You can use these 'is <X>' predicates to check whether a variable that you have is of the type that you expect, but you can't use 'is Line' to check if a 'Query' references a linear edge (because 'Query is Query').
You could use 'evLine()' to both check if the edge is linear, and find out the mathematical information about the line:var line = try silent(evLine(context, { "edge" : someQuery })); if (line == undefined) { // This could indicate lots of things. Maybe the query doesn't reference one entity, // or the one entity it references is not an edge, or not a linear edge. throw regenError("someQuery was not a line"); } else { var recievedLineDefinition = line is Line; // true var origin = line.origin; var direction = line.direction; }https://cad.onshape.com/FsDoc/library.html#evLine-Context-map
https://cad.onshape.com/FsDoc/library.html#Line
Or, you could just make sure the user passes linear edges into your feature:annotation { "Feature Type Name" : "Evaluate line" } export const myFeature = defineFeature(function(context is Context, id is Id, definition is map) precondition { annotation { "Name" : "Line", "Filter" : GeometryType.LINE, "MaxNumberOfPicks" : 1 } definition.lineQuery is Query; } { var lineDefinition = evLine(context, { "edge" : definition.lineQuery }); });
Hope this isn't just adding confusion. Let us know if you still have questions.Jake Rosenfeld - Modeling Team0 -
Thanks for taking the time to lay that out. It's very helpful. Some of the problems I get into are syntax related, but these I can run down. The conceptual issues are harder. Your answer is another view into "Featurescript Think". I'm starting to get it.
Thanks.1 -
@Jake_Rosenfeld, so if checking of geometry type is always done with "varX is typeX", what exactly are the canBeX typechecks used for? I get they are used internally for custom types, but for what? From what I can tell canBeX() is redundant since we have "evX() is X"?1
-
They are executed at certain points when monitoring a part studio and warnings are generated if they fail. So if your custom feature does
"this is a string" as Plane
If you monitor a part studio that uses that feature, you'll be warned about a typecheck failure.Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc1 -
@mahir
I may be misunderstanding your question, but 'varX is typeX' cannot be used to check geometry types of queries, it can only be used to check what type a FeatureScript variable is.
To answer the second part of your question in detail, you can't have 'evX() is X' without declaring 'canBeX()'.
Here's an example:export predicate canBeVehicle(value) { value is map; value.numWheels is number; value.color is Color; } export type Vehicle typecheck canBeVehicle; export function vehicle(numWheels is number, color is Color) { return { "numWheels" : numWheels, "color" : color } as Vehicle; } annotation { "Feature Type Name" : "Make vehicles" } export const myFeature = defineFeature(function(context is Context, id is Id, definition is map) precondition { } { // These variables both have type: Vehicle var redCar = vehicle(4, color(1, 0, 0)); var blueMotorcycle = vehicle(2, color(0, 0, 1)); });
You fundamentally can't have 'Vehicle's without 'canBeVehicle()'. You can now check if a variable is a Vehicle with 'someVariable is Vehicle', but only because you wrote out its definition using the 'canBe' predicate.
'canBeVehicle()' is a construction of FeatureScript, and is used internally by the system to make sure that things declared 'as Vehicle' actually qualify for this role.
Another example:var fakeVehicle = { "numWheels" : 5, "color" : color(0, 0, 0) }; var check1 = fakeVehicle is Vehicle; // false. fakeVehicle is a map, it was never declared to be a Vehicle. var check2 = canBeVehicle(fakeVehicle); // true. fakeVehicle follows all the rules of what a vehicle should be. var vehicle = fakeVehicle as Vehicle; // doesn't fail because canBeVehicle() passes. var check3 = vehicle is Vehicle; // true. vehicle was declared as a Vehicle.
In short: you should never need to call 'canBeX()' yourself. It's used by the system to declare variable types.
Coming full circle: It's not really useful to check whether something 'is Plane' or 'is Line' or 'canBePlane' or 'canBeLine'. If you end up with something of these variable types, you'll already know that you have them (because you would have had to call 'evPlane()' or 'evLine()' or similar to get those). To check if some piece of geometry is a plane, you can do:var isPlane = try silent(evPlane(context, { "face" : faceQuery })) != undefined; --- or --- var queryContainsPlane = size(evaluateQuery(context, qGeometry(someQuery, GeometryType.PLANE))) != 0;
Jake Rosenfeld - Modeling Team1 -
Thanks, @Jake_Rosenfeld. That was a great explanation.1
-
This has been a great discussion for me. The original question is bland so I doubt if it will attract much attention. I think a lot of people would benefit from the information shared here.0



