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.

a simpler way to define length parameter defaults

adamohernadamohern Member, OS Professional Posts: 216 PRO
export const US_THICKNESS_BOUNDS =
{
            "min" : -TOLERANCE.zeroLength * meter,
            "max" : 500 * meter,
            (meter) : [1e-5, .01905, 500],
            (centimeter) : 1.905,
            (millimeter) : 19.05,
            (inch) : .75,
            (foot) : 0.0625,
            (yard) : 0.02083333
        } as LengthBoundSpec;

I don't understand LengthBoundSpec maps. All I want to do is set a default value for a field and, usually, allow it to be zero. 

1) Why are min and max included as separate if they are also required in the (meter) value range? It seems redundant.

2) This seems like a lot of code for simply setting a default parameter. If I have to do this for every single input in my feature, I end up with tons of these things taking up the top 100+ lines of code, most of it fluff. Is there a cleaner way?

Comments

  • traveler_hauptmantraveler_hauptman Member, OS Professional, Mentor, Developers Posts: 419 PRO
    edited April 2016
    My approach would be a constructor/factory function to handle the case when the default is the same for all units, and using templates when only a couple things change.

    //mapArray with parameters
    export function mapArrayParam(arr is array, mapFunction is function, parameters is map) returns array
    {
    const size = @size(arr);
    for (var i = 0; i < size; i = i + 1) {
    arr[i] = mapFunction(arr[i],parameters);
    }
    return arr;
    }
    //convert units
    const convert = function(value,params){
    return value.value/params.u.value;
    };

    function LSfactory(mn is ValueWithUnits, dv is array, mx is ValueWithUnits)
    {
    return {
    "min" : mn,
    "max" : mx,
    (meter) : mapArrayParam(dv,convert,{u: meter}),
    (centimeter) : mapArrayParam(dv,convert,{u: centimeter}),
    (millimeter) : mapArrayParam(dv,convert,{u: millimeter}),
    (inch) : mapArrayParam(dv,convert,{u: inch}),
    (foot) : mapArrayParam(dv,convert,{u: foot}),
    (yard) : mapArrayParam(dv,convert,{u: yard})
    } as LengthBoundSpec;
    }

    function LSfactory(mn is ValueWithUnits, dv is ValueWithUnits, mx is ValueWithUnits)
    {
    return {
    "min" : mn,
    "max" : mx,
    (meter) : convert(dv,{u:meter}),
    (centimeter) : convert(dv,{u:centimeter}),
    (millimeter) :convert(dv,{u:millimeter}),
    (inch) : convert(dv,{u:inch}),
    (foot) : convert(dv,{u:foot}),
    (yard) : convert(dv,{u:yard})
    } as LengthBoundSpec;
    }

    export const CustSpec = LSfactory(0.0001*meter, 20*millimeter, 10*meter);
    const TemplateSpec = LSfactory(0.0001*meter, [0.1*millimeter,1*millimeter, 20*millimeter], 10*meter);

    //Change only the (inch) default from the template
    export const CustSpec2 = mergeMaps(TemplateSpec, {(inch): 1});

    This was done quickly, it's possible that I don't need to convert units...




  • leon_pootleon_poot Member, Developers Posts: 87 ✭✭✭
    @traveler_hauptman, quick question: I tried the exact code you provided and I get the warning "Expected bounds to be a map" when applying any of the CustSpecs or TemplateSpec to a parameter... causing the feature to stop functioning. It looks like a map to me... Which version did you write this in?
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools." - Douglas Adams, Mostly Harmless
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    @leon_poot
    @traveler_hauptman's example is hypothetical, and doesn't work in FeatureScript. The reason it doesn't work (and may not ever work) is that we don't execute arbitrary FeatureScript code when extracting the parameters you want in your feature dialog. What is done is called "precondition analysis", where we look at your feature's precondition, resolve symbols where necessary, and expect those symbols to be defined in a standard way. A function call to Traveler's LSfactory is simply not one of those defined ways.

    The result of LSfactory, if run, would be of a format that isLength would be fine with at runtime, which is why Traveler suggested it. Unfortunately, his code will never be executed at this phase. As soon as we see the unrecognized format, we fail to extract a specification of the feature dialog.

    But there's good news!

    We've changed the behavior of the length bound spec a bit, and when Onshape 1.54 comes out (our next release), you'll be able to set the min, max, and default for all units more concisely, even right in the parameter 
            annotation { "Name" : "Length 1" }<br>        isLength(definition.length1, { (inch) : [0, 0.1, 1e5] } as LengthBoundSpec);

  • traveler_hauptmantraveler_hauptman Member, OS Professional, Mentor, Developers Posts: 419 PRO
    @leon_poot At the time I made a wrong assumption that imports and top-level function calls would be executed before precondition analysis. I was using print statements in a function body to verify my functions were creating things correctly and once the map was correct did not test further.

Sign In or Register to comment.