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 i create a new unit of measure?
dave_cowden
Member, Developers Posts: 475 ✭✭✭
I would like to create a new unit that represents a threadpitch: threads per unit length.
Question 1: How do i do that?
Question 2: If i support threads/inch and threads/meter, how do i ensure these are converted property?
Question 3: how do i link my unit of measure so that when the document defaults are inches, my new threads/inch measure is the default, while if the document units are mm, threads/mm are the default?
Question 4: ( somewhat tangential): having values with units are cool, but why are the units always converted to meter before they are passed into the body of a feature. Is there some reason for this? it would be nice in some cases to know what the unit of measure the user initially supplied ( because for example you could accept dimensionless values connected with another length dimension )
Question 5: ( also somewhat tangential): how do you properly convert units? seems like the conversion is always done for me -- but always from what the user supplied to meter. I can't see where that code is, and/or how to do other types of conversations myself.
Question 1: How do i do that?
Question 2: If i support threads/inch and threads/meter, how do i ensure these are converted property?
Question 3: how do i link my unit of measure so that when the document defaults are inches, my new threads/inch measure is the default, while if the document units are mm, threads/mm are the default?
Question 4: ( somewhat tangential): having values with units are cool, but why are the units always converted to meter before they are passed into the body of a feature. Is there some reason for this? it would be nice in some cases to know what the unit of measure the user initially supplied ( because for example you could accept dimensionless values connected with another length dimension )
Question 5: ( also somewhat tangential): how do you properly convert units? seems like the conversion is always done for me -- but always from what the user supplied to meter. I can't see where that code is, and/or how to do other types of conversations myself.
0
Best Answer
-
kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 5651) If you just want a variable which behaves properly in FS, you can make one by dividing by the proper units, e.g.
var threadSpacing = 25 / inch;
To make such a variable a user input: A generic valueWithUnits input which requires certain dimensions (inverse length, or, say, area, volume, weight, temperature) is on our wishlist, but not currently part of Onshape. Lengths and angles right now get special treatment in how they behave when a user just types "1" without units.
Here's two ways to do it without that feature:
If you want the dimension to be associated with inches always, you can use an isInteger(definition.threadsPerInch) or isReal(definition.threadsPerInch) predicate for the number of threads per inch. Given the standards I'm familiar with, this seems like the more natural choice.
If you want the user to be able to specify their own units, you can use an isAnything(definition.threadSpacing) predicate, which allows the user to type e.g. 25 / in, or 10 / mm. The downside of this is that a user will always need to provide their own units themselves, and you'll have to do your own error handling if they type a bare number, or don't get the units right.
2) For the first case, you'll need to divide the input by inches to get the ValueWithUnits:var threadSpacing = definition.threadsPerInch / inch;
For the second case, you can just use the input directly:var threadSpacing = definition.threadSpacing;
3) Unit inference would happen automatically in the "generic valueWithUnits input" I described above, but won't happen with either of the two methods that work now.
4) It's important that the user shouldn't have to care what units a variable is provided with. If they set a length to 1cm, then change it to 10mm, there should be no change in the geometry. This includes more complex situations using measurements, variables, and (in FS) evaluation functions, where the "units" associated with a value aren't directly given. Units are always implicitly converted to their base units (in Onshape, meters) whenever they are assigned, whether through a user input, or in FS with e.g. 1 * inch.
I actually disagree that it's "nice" to know what units something is defined in. That's a slippery slope that can lead to hard-to-predict, hard-to-generalize behavior. We certainly don't want every FeatureScript writer doing extra coding and testing work just to make sure their feature works in metric. If we're not providing a good experience for features working in every convention, that's our fault, not yours.
5) Clean FS code would be written so that unit conversions aren't necessary – a ValueWithUnits can be thought of as "just" the backing value (with dimensions, not units). For instance, the opHelix function can take in 1 / threadSpacing as the helical pitch. The helix function (whose length is based on a given cylinder) can take in cylinderLength / threadSpacing for the "revolutions" parameter.
If you're asking questions like "Wait, was cylinderLength defined in inches or meters?" the answer should always be "I don't care."
6
Answers
To make such a variable a user input: A generic valueWithUnits input which requires certain dimensions (inverse length, or, say, area, volume, weight, temperature) is on our wishlist, but not currently part of Onshape. Lengths and angles right now get special treatment in how they behave when a user just types "1" without units.
Here's two ways to do it without that feature:
If you want the dimension to be associated with inches always, you can use an isInteger(definition.threadsPerInch) or isReal(definition.threadsPerInch) predicate for the number of threads per inch. Given the standards I'm familiar with, this seems like the more natural choice.
If you want the user to be able to specify their own units, you can use an isAnything(definition.threadSpacing) predicate, which allows the user to type e.g. 25 / in, or 10 / mm. The downside of this is that a user will always need to provide their own units themselves, and you'll have to do your own error handling if they type a bare number, or don't get the units right.
2) For the first case, you'll need to divide the input by inches to get the ValueWithUnits:
For the second case, you can just use the input directly:
3) Unit inference would happen automatically in the "generic valueWithUnits input" I described above, but won't happen with either of the two methods that work now.
4) It's important that the user shouldn't have to care what units a variable is provided with. If they set a length to 1cm, then change it to 10mm, there should be no change in the geometry. This includes more complex situations using measurements, variables, and (in FS) evaluation functions, where the "units" associated with a value aren't directly given. Units are always implicitly converted to their base units (in Onshape, meters) whenever they are assigned, whether through a user input, or in FS with e.g. 1 * inch.
I actually disagree that it's "nice" to know what units something is defined in. That's a slippery slope that can lead to hard-to-predict, hard-to-generalize behavior. We certainly don't want every FeatureScript writer doing extra coding and testing work just to make sure their feature works in metric. If we're not providing a good experience for features working in every convention, that's our fault, not yours.
5) Clean FS code would be written so that unit conversions aren't necessary – a ValueWithUnits can be thought of as "just" the backing value (with dimensions, not units). For instance, the opHelix function can take in 1 / threadSpacing as the helical pitch. The helix function (whose length is based on a given cylinder) can take in cylinderLength / threadSpacing for the "revolutions" parameter.
If you're asking questions like "Wait, was cylinderLength defined in inches or meters?" the answer should always be "I don't care."
Just consider this a "+1" for ability to add a proper, custom UOM. Basically, both of the solutions you suggest in #2 are not nice for the user.
Cheers, Darren.
Values can be multiplied and divided. The preceding values are
1 * kilogram
,90 * degree
, and9.81 * meter / second / second
.Is 'second' built in? auto complete doesn't find it?
Cheers,
Darren
seems to be fine, can we get this in the units.fs?
Cheers,
Darren