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.

Showing what's in a query

billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 1,841 PRO
edited February 2016 in FeatureScript
A few questions actually:

1. I suppose this isn't allowed:     
var i, j, k;



2. how do you show what's in your query I'm using:
debug(context, qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.EDGE), 1));

It would be nice to highlight on the model what you've captured.




3. the million dollar question:




So it works for 1 instance


But fails at 2 instances



In my code 
fCylinder(context, id + "cylinder" + cnt, {

and

opDraft(context, id + "draft1" + cnt, {

These should be unique identifiers and it should work.

The math is right because I can manually rotate geometry


What's the red circle, is that the last selection list? If you edit the feature, will it highlight the last query?


If you can't follow this, please let me know how to present a coding problem

Comments

  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 1,841 PRO
    edited February 2016
    Ok, so debug highlighting seems to be working.

    For others trying to figure it out:


    -all this code does is loop through and makes 3 cylinders defined by a variable definition.count. 
    -the highlighted blue code gets the 3 faces by the id of the feature      id + "cylinder" + cnt
    -then I look through this query and pick the 3rd element which is qNthElement(query, 2)
    -then add that to a debug statement

    edit your feature and it highlights all the faces that were queried in the script:
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 1,841 PRO
    edited February 2016
    This might be a better way



    This way uses a point and captures anything that's coincident with the point which should be a very robust query technique.

    The debugged faces using qContainsPoint:


  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 1,841 PRO
    edited January 2016
    ok so if you want to post a code block on this forum format the text as code:



    annotation { "Feature Type Name" : "Star" }
    export const star = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            // Define the parameters of the feature type
            annotation { "Name" : "length" }
            isLength(definition.length, LENGTH_BOUNDS);
            annotation { "Name" : "radius" }
            isLength(definition.radius, LENGTH_BOUNDS);
            annotation { "Name" : "count" }
            isInteger(definition.count, POSITIVE_COUNT_BOUNDS);

        }
        {
            // Define the function's action
            var ang = 360 / definition.count * degree;
            var i;
            var j;
            var k;
            for (var cnt = 1; cnt <= definition.count; cnt += 1)
            {
                i = cos(ang * cnt);
                j = sin(ang * cnt);
                debug(context, ang * cnt / degree);
                fCylinder(context, id + "cylinder" + cnt, {
                            "bottomCenter" : vector(0, 0, 0) * meter,
                            "topCenter" : vector(i, j, 0) * definition.length,
                            "radius" : definition.radius
                        });
                //debug(context, qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), 2));            
                debug(context, (qContainsPoint(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), vector(i, j, 0) * definition.length)));
                          
        
    /*            fillet(context, id + "fillet1" + cnt, {
                            //"entities" : qCreatedBy(id + "cylinder" + cnt, EntityType.EDGE),
                            "entities" : qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.EDGE), 1),
                            "radius" : definition.radius 
                        });

                opDraft(context, id + "draft1" + cnt, {
                        "neutralPlane" : qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), 1),
                        "pullVec" : vector(i, j, 0),
                        "draftFaces" : qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), 0),
                        "angle" : 2*degree
                });*/
            }
        }, { /* default parameters */ });


  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 552
    edited February 2016
    First off, the red circle you see is the result of the debug() function call. debug() will highlight a query (or a Plane, Line, CoordSystem, etc) in the Part Studio in red when that feature's feature dialog is open. This behavior gives you a way of filtering out specific debugged entities when there are multiple instances of a feature in the Part Studio.

    If you just want to display console output (like printing the angles above) you can just use print() or println().

    On diagnosing errors, the most helpful feedback you'll get will be in the FeatureScript notices flyout. Including that flyout with errors in your screenshot will likely contain the most helpful information for others to help you diagnose the problem.

    Your particular error involves something that's definitely not apparent from the documentation: How to manage hierarchical ids.

    Here's a quick summary: When you make an id of the form id + foo + bar, you want "foo" to be the main group of operations, and "bar" to be a smaller, sub-operation. That way, querying for, say qCreatedBy(id + foo) alone will return things created by id + foo + bar, and by id + foo + bar2, etc. There are technical reasons why features and operations cannot currently be added under an existing id after that id has been "closed", i.e. another feature has been created under a different id.

    In your case, you were creating geometry under id + "cylinder", then under id + "draft", then back under id + "cylinder", which throws the error described above. Since you're building each arm of the star individually, a more functional id structure would put the variable cnt first, and build a cylinder, a draft, and a fillet on each arm as part of that id.

    Thus, the fix is to change all instances of <b>id + "cylinder" + cnt</b> to <b>id + cnt + "cylinder"</b> (and the same for draft/fillet).

    I agree that the error we present in this case isn't helpful, which is something we'd like to eventually address.

    Finally, you're spot on about the robustness of queries. qNthElement is hard to rely on in the general case, while qContainsPoint, combined with the qCreatedBy, should give you the right thing every time.
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 1,841 PRO
    edited February 2016
    thanks kevin got it working




    Working code:
    annotation { "Feature Type Name" : "Star" }
    export const star = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            // Define the parameters of the feature type
            annotation { "Name" : "length" }
            isLength(definition.length, LENGTH_BOUNDS);
            annotation { "Name" : "radius" }
            isLength(definition.radius, LENGTH_BOUNDS);
            annotation { "Name" : "count" }
            isInteger(definition.count, POSITIVE_COUNT_BOUNDS);

        }
        {
            // Define the function's action
            var ang = 360 / definition.count * degree;
            var i;
            var j;
            var k;
            //loop through and create both a cylinder and then draft
            for (var cnt = 1; cnt <= definition.count; cnt += 1)
            {
                i = cos(ang * cnt);
                j = sin(ang * cnt);
                println('ang ' ~ ang * cnt / degree);
                fCylinder(context, id + cnt + "cylinder", {
                            "bottomCenter" : vector(0, 0, 0) * meter,
                            "topCenter" : vector(i, j, 0) * definition.length,
                            "radius" : definition.radius
                        });
                //I don't like qNthElement for picking faces
                opDraft(context, id + cnt + "draft1", {
                            "neutralPlane" : qNthElement(qCreatedBy(id + cnt + "cylinder", EntityType.FACE), 1),
                            "pullVec" : vector(i, j, 0),
                            "draftFaces" : qNthElement(qCreatedBy(id + cnt + "cylinder", EntityType.FACE), 0),
                            "angle" : 2 * degree
                        });
                //debug(context, qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), 2));
                //debug(context, (qContainsPoint(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), vector(i, j, 0) * definition.length)));
            }
            /*
               opFillet(context, id, {
               "entities" : qContainsPoint(qCreatedBy(id + "cylinder" + cnt, EntityType.FACE), vector(i, j, 0) * definition.length)),
               "radius" : definition.radius,
               "tangentPropagation" : true
               });
               fillet(context, id + "fillet1" + cnt, {
               //"entities" : qCreatedBy(id + "cylinder" + cnt, EntityType.EDGE),
               "entities" : qNthElement(qCreatedBy(id + "cylinder" + cnt, EntityType.EDGE), 1),
               "radius" : definition.radius
               });

             */
        }, { /* default parameters */ });


Sign In or Register to comment.