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.

convert units?

adamohernadamohern Member, OS Professional Posts: 216 PRO
Silly question. I have a length parameter expressed internally as meters. I would like to know the same value in inches. How can I get the length map's value converted to inches?

Comments

  • cody_armstrongcody_armstrong Moderator, Onshape Employees, Developers Posts: 208
    @adamohern  You should just be able to multiply it by "inch".  
    var inchUnits = value * inch;


  • adamohernadamohern Member, OS Professional Posts: 216 PRO
    As in:
    var inches = definition.myLength.value * inch;
    That doesn't give me the proper value, nor would I expect it to.
  • adamohernadamohern Member, OS Professional Posts: 216 PRO
    If it helps to clarify my meaning, here's what I'm currently using as a workaround:

    // To use formula, we need to start with Inches (not meters)
    var mercury_planet_dia_inches = definition.mercury_planet_dia.value * 39.37007874;

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,123
    edited May 2017
    You divide by inches, not multiply by them.  Dividing a length by a length gives a number.
    var inches is number = definition.myLength / inch;
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • cody_armstrongcody_armstrong Moderator, Onshape Employees, Developers Posts: 208
    Ah I misunderstood, what about just multiplying everything by a conversion factor? 

    var inchConvert = 39.3701<br>var inches = value * inchConvert
  • adamohernadamohern Member, OS Professional Posts: 216 PRO
    Ilya nailed it, as usual. I find the unit conversions in FS confusing. (I'm sure they make sense to a math person.)

  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 552
    edited May 2017
    @adamohern There's definitely a bit of a zen to units in FS: One should think of a length as "just a length" and not really having units. If I have a length variable (of type ValueWithUnits), it does not matter whether that variable was originally entered by some user in inches, or created in FS via &nbsp;* centimeter, or gotten from evDistance, or calculated by dividing "just a volume" by "just an area". All these are just lengths. I can take one length, subtract another length from it, pass the result into a function that expects a length, all without caring about units.

    The flip side of this is: if you find yourself wanting to create a variable like "numberOfInches", it's worth thinking about why. That variable does have a bias about its own units, and once you create it, those units will need to be considered for the whole lifetime of that variable. numberOfInches can't be added to other FeatureScript lengths, nor can it be passed into functions expecting FeatureScript length. So, you're going to be paying the cost of maintaining such a variable every time it interacts with something else in FS.

    You can instead write code which takes advantage of FS units in formulas, like:

    const mercury_planet_density = 5.43 * gram / (centimeter^3);
    const mercury_planet_radius = definition.diameter / 2;
    const mercury_planet_volume = (4 / 3) * PI * mercury_planet_radius ^ 3;
    const mercury_planet_mass = mercury_planet_volume * mercury_planet_density;

    The result, mercury_planet_mass, is "just a mass". By default, a ValueWithUnits will print in SI units (in this case, "3.3031834839597105e+23 kilogram"). You can see that value with different units by dividing out the units before printing, like println("Mass: " ~ mercury_planet_mass&nbsp;/ pound ~ " pounds");

  • adamohernadamohern Member, OS Professional Posts: 216 PRO
    Thanks, Kevin. I understand the principle, and as a rule I do exactly what you describe. I had two problems that were forcing me (as far as I could tell) to use an inch-specific number: 1) I inherited a formula from an engineer that for some reason only worked with inches, and 2) I was having trouble raising distances to decimal powers (root). Not sure why #2, but I found that working with real numbers (as opposed to distances) fixed the problem.
  • patrick_farleypatrick_farley Member Posts: 37 ✭✭
    i have almost the same issues and dividing by / inch does not seams to work?
    Here is a snipet of my code:


    This works but give me a some decimal at the end

     //var inches = definition.myLength.value / inch;
            if (definition.size == Size.X204)
                {
                var sketch01 = newSketch(context, id + "sketch01", { "sketchPlane" : qCreatedBy(makeId("Top"), EntityType.FACE) });
                skRectangle(sketch01, "rectangle01", { "firstCorner" : vector(0, 0)* inch,"secondCorner" : vector(3.5, 1.5) * inch} );
                skSolve(sketch01);
                extrude(context, id + "extrude01", { "entities" : qSketchRegion(id + "sketch01"), "endBound" : BoundingType.BLIND, "depth" : definition.myLength });
                //setProperty (context is Context, definition is map)
                 setProperty(context, {
                        "entities" : qCreatedBy(id + "extrude01", EntityType.BODY),
                        "propertyType" : PropertyType.PART_NUMBER,
                        "value" : ("2\" x 4\" x "~(definition.myLength.value * 39.37007875))
                });
                



    but if i divide by inch
    i get :

            if (definition.size == Size.X204)
                {
                var sketch01 = newSketch(context, id + "sketch01", { "sketchPlane" : qCreatedBy(makeId("Top"), EntityType.FACE) });
                skRectangle(sketch01, "rectangle01", { "firstCorner" : vector(0, 0)* inch,"secondCorner" : vector(3.5, 1.5) * inch} );
                skSolve(sketch01);
                extrude(context, id + "extrude01", { "entities" : qSketchRegion(id + "sketch01"), "endBound" : BoundingType.BLIND, "depth" : definition.myLength });
                //setProperty (context is Context, definition is map)
                 setProperty(context, {
                        "entities" : qCreatedBy(id + "extrude01", EntityType.BODY),
                        "propertyType" : PropertyType.PART_NUMBER,
                        "value" : ("2\" x 4\" x "~(definition.myLength.value / inch))
                });





    i did enter the lenght in INCH at the interface,



    Any idea?
    Thanks

    Pat Farley


  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 4,397
    Try it with just "value" : ("2\" x 4\" x "~(definition.myLength / inch))

    You were dividing a number by a "ValueWithUnits"
    Director, Technical Services, EMEAI
  • patrick_farleypatrick_farley Member Posts: 37 ✭✭
    Thanks,
    now i have inches but the other issues is , it is not rounded to the value i enter (32 inches)

    i don't think that i could ask the builder to cut a 2x4 at 31.9999 inch ;-)

    i will problably have to round it to the nearest 1/16.
    i did not search for this function yet, is there anything that could do the job?

    Thanks for your help guys

    Pat Farley




  • patrick_farleypatrick_farley Member Posts: 37 ✭✭
    Thanks i just found the round() function
    i am trying this
    i will let you know my find

    Pat F

  • patrick_farleypatrick_farley Member Posts: 37 ✭✭
    Perfect
    it now works with round(

                 setProperty(context, {
                        "entities" : qCreatedBy(id + "extrude01", EntityType.BODY),
                        "propertyType" : PropertyType.PART_NUMBER,
                        "value" : ("2\" x 4\" x "~(round(definition.myLength / inch, 0.0625))~"\"")
     
    Pat Farley

  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 4,397
    Glad you got it sorted
    Director, Technical Services, EMEAI
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 552
    FYI to future users, the round function also takes a precision, if desired. You can use the function either with units: round(length, millimeter) or without: round(number, 0.01), depending on what units the original value has.

    There's a few examples of printing values with units in a sane way at the top of the units module.
  • MichaelPascoeMichaelPascoe Member Posts: 929 PRO
    edited May 2021
    The feature I'm working on will be used in both metric and english part studios.

    @kevin_o_toole_1
    This may have already been answered and I missed it.
    Is there a way to query the units that are on a number? Or perhaps a way to round with whatever units are already on the number?

    Here is my current code, which only works if your studio is english.
    roundToPrecision( result / inch, 1);

  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 552
    edited May 2021
    @MichaelPascoe
    ValuesWithUnits are agnostic to the unit type (they can more correctly be thought of as values with dimensions e.g. length, not units e.g. inches).

    So no, there is no difference between setting a parameter value to "1 in" vs. setting it to "2.54 cm".

    Sounds like you want code that does do different things for those two values, which smells a bit off. For instance, if you're trying to get two different units to compare equal, tolerantEquals() is definitely preferable to rounding both.

    Granted, if you're interested in an end user output, correct units are definitely good. There's a couple ways to display values with units natively in Onshape:
    - If you're trying to inform the user of an output value, you can use a READ_ONLY parameter to display it
    - If you want many such outputs, a custom table can display those

    And if you really do just need such a thing in the code, there is also a sneaky workaround where you can capture the default units of the workspace (at the time a feature was created) with an ALWAYS_HIDDEN length parameter with known defaults for each unit type.
  • MichaelPascoeMichaelPascoe Member Posts: 929 PRO
    edited May 2021
    @kevin_o_toole_1
    Thank you for the explanation and examples. This is very helpful!

    Ah, I like the work around.
  • MichaelPascoeMichaelPascoe Member Posts: 929 PRO
    edited May 2021
    For anyone who may need this work around for rounding, I used what @kevin_o_toole_1 showed me and implemented it into my feature with a few changes.
     Variable (Advanced)

    Like Kevin said, this will capture the default units of the workspace at the time a feature was created. 

    precondition
    {
            annotation { "Name" : "Rounding / Precision", "Default" : RoundingPrecision.ONE_THOUSANDTH }
            definition.roundingPrecision is RoundingPrecision;
            
            //Get work space units work around. Reference kevin_o_toole_1
            //https://forum.onshape.com/discussion/comment/43969#Comment_43969
    
            annotation { "Name" : "Invisible length", "UIHint" : UIHint.ALWAYS_HIDDEN }
            isLength(definition.invisibleLength, { (inch) : [-10000, /* min (inclusive) */
                                    1.0, /* default */
                                    10000 /* max (inclusive) */],
                            (meter) : 1,
                            (centimeter) : 1,
                            (millimeter) : 1,
                            (foot) : 1,
                            (yard) : 1 } as LengthBoundSpec);
        }
        {
            const units = definition.invisibleLength;
    
                var unitMultiplyer = switch (units) {
                        (inch) : inch,
                        (meter) : meter,
                        (centimeter) : centimeter,
                        (millimeter) : millimeter,
                        (foot) : foot,
                        (yard) : yard,
                    };
    
            var unitlessValue = definition.value / unitMultiplyer;
            var value = roundToPrecision(unitlessValue, 2);
            
            value = value * unitMultiplyer;
            
            setVariable(context, definition.name, value);
            setFeatureComputedParameter(context, id, { "name" : "d", "value" : value });
        });
    


     
  • Evan_ReeseEvan_Reese Member Posts: 1,489 PRO
    Thanks for the writeup Kevin. I've been following along because I still get hung up on units stuff sometimes.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
Sign In or Register to comment.