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.

How to I evaluate a query and store one of the resulting entities?

tim268tim268 Member, Developers Posts: 3 PRO
edited October 2017 in FeatureScript
Hello,

I am hoping you can help me.

I would like to find the 2 largest Cylindrical surfaces on a part by surface area.

I can do this, but I think there must be a better method? I am used to object oriented programming in java where I could store this sort of thing using an object.

I havn't put the full code (as it long and may confuse things) but the basic method I am using at the moment:


// Query the all cylindrical faces
var cyls = qGeometry(qOwnedByBody(part, EntityType.FACE), GeometryType.CYLINDER);

var counter = 0;
var cylOneIndex = 0;
var cylTwoIndex = 0;

// Loop through the cylindrical faces
for (var cyl in evaluateQuery(context, cyls))
{

                var cylArea = evArea(context, {
                        "entities" : cyl
                    });

                // If the surface is largest by area - store it's array position/index
                cylOneIndex = counter;

                // If the surface is second largest by area  - store it's array position/index
                cylTwoIndex = counter;

counter += 1;

}


Then, if I want to use either of the 2 largest surfaces later on, I use Query Nth element (because I now know the  position/index):

qNthElement(cyls, cylOneIndex);

or

qNthElement(cyls, cylTwoIndex);


Is there a better way of doing this? Is it possible to evaluate a query and store one of the resulting entities? For example:


// Query the all cylindrical faces
var cyls = qGeometry(qOwnedByBody(part, EntityType.FACE), GeometryType.CYLINDER);

// Initialise the Cylinders as undefined??
var cylOne is Cylinder = undefined;
var cylTwo is Cylinder = undefined;

// Loop through the cylindrical faces
for (var cyl in evaluateQuery(context, cyls))
{

                var cylArea = evArea(context, {
                        "entities" : cyl
                    });

                // If the surface is largest by area - store the Cylinder
                cylOne = cyl;

                // If the surface is second largest by area  - store the Cylinder
                cylTwo = cyl;

}

Then, if I want to use either of the 2 largest surfaces later on, I just used the cylOne or cylTwo variables? For example:

cylOne.radius;

or

cylTwo.radius;


My concerns with my current method are:
  • I am evaluating the query twice. I assume this is poor on performance?
  • What if the index/position of the entities changes in the array?
  • There must be a better way of doing this?

Any help would be appreciated! Thank you

Tim


Comments

  • konstantin_shiriazdanovkonstantin_shiriazdanov Member Posts: 1,221 ✭✭✭✭✭
    after you got the query of cylindrical faces by
    var cyls = qGeometry(qOwnedByBody(part, EntityType.FACE), GeometryType.CYLINDER);
    i would reccomend to make a list of map structures for each face like {"query": cylFaceQuery,"area":cylFaceArea}
    and sort that list with sort() function. the compare function should be: function(cyl1, cyl2) {return cyl2.area-cyl1.area}
    the two first elements of resulting list will contain the query and the area of two largest by area cylinders
  • tim268tim268 Member, Developers Posts: 3 PRO
    Hello Konstantin,

    Thank you for your quick response.

    Would you be able to explain how I make a list of map structures?
    Do I define an empty var? Loop through and add the maps to the var?

    // Query the all cylindrical faces
    var cyls = qGeometry(qOwnedByBody(part, EntityType.FACE), GeometryType.CYLINDER);

    //Define Empty var?
    var cylList;

    // Loop through the cylindrical faces
    for (var cyl in evaluateQuery(context, cyls))
    {

                    var cylArea = evArea(context, {
                            "entities" : cyl
                        });

                    // Add a map to the array??
                    cylList + {"query": cyl,"area":cylArea};

    }

    sort(cylList ,function(cyl1, cyl2) {return cyl2.area-cyl1.area;});


    I will try and work this out. But again any help would be appreciated. Thank you!

    Tim








  • konstantin_shiriazdanovkonstantin_shiriazdanov Member Posts: 1,221 ✭✭✭✭✭
    edited October 2017
    something like this - define an empty list and append it with newly calculated values in the loop

    var cylList=[];

    // Loop through the cylindrical faces
    for (var cyl in evaluateQuery(context, cyls))
    {
                    var cylArea = evArea(context, { "entities" : cyl });

                    cylList = append(cylList, {"query": cyl,"area":cylArea});
    }
  • tim268tim268 Member, Developers Posts: 3 PRO
    Got it!

    Thank you so much. I couldn't work out how to init an empty array and then append to it!

    I've been trying:

    var cylList = null;
    var cylList = undefined;
    var cylList[5];
    etc. etc.

    And:

    cylList[counter] = {"query": cyl,"area":cylArea};
    cylList += {"query": cyl,"area":cylArea};
    cylList.set(counter) = {"query": cyl,"area":cylArea};
    etc. etc.


    Seems stupid when you know  how!

    Thank you very much.

    Tim



  • konstantin_shiriazdanovkonstantin_shiriazdanov Member Posts: 1,221 ✭✭✭✭✭
    yep, featurescript doesn't pamper us by too big amount of syntax sugar :) so if you going to perform some standart operation to data structure you should likely search a function for this in its standart library
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,211
    There are qLargest and qSmallest queries that you can use for this.  To get the second largest face, you can do something like:
    var largestQuery = qLargest(faces);
    var secondLargest = qLargest(qSubtraction(faces, largestQuery));
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
Sign In or Register to comment.