Select all objects of the same type in rhino

Hello

I want to select all objects of the same type
For example: squares, circles, closed curves …

Is there any way?

1 Like

Native Rhino has a number of these… Including SelOpenCrv and SelClosedCrv. It also has some more specific object type selection such as SelLine, SelPolyline, etc. However it does not have all such cases, for example no native SelCircle or SelEllipse. Type Sel… at the command line to see what is natively available.

Anything else can be very easily scripted though and then it can be pretty much as granular and specific as you want to make it…

Here are a few of my common “specials”

SelArc.py (466 Bytes)

SelCircle.py (472 Bytes)

SelEllipse.py (474 Bytes)

SelPolycurve.py (403 Bytes)

And for fun, I just added a “SelSquare and SelRectangle”:

SelSquare.py (1.4 KB)

SelRectangle.py (1.6 KB)

(SelRectangle specifically excludes squares)

4 Likes

This can also be done via native grasshopper components or plugin components.

1 Like

Thank you. I tested it perfectly
Can these commands search for objects of the same size?

That can be scripted, of course - one can add a size criteria to the search process. There are many different ‘size’ criteria however - length, perimeter, area, volume etc…

1 Like

@Helvetosaur
You have previously shared this code.

It only applies to the object circle

How to apply with other shapes

 Option Explicit
    'Script written by Mitch
    'Script version Monday, October 25, 2010

    Call SelSameRadCircles()
    Sub SelSameRadCircles()

    	dim strcirc,dblRad,arrAllCrvs,strCrv,dblTol
    	strCirc=Rhino.GetObject("Select circle to match radius",4,True)
    	If IsNull(strCirc) Then Exit Sub
    	dblTol=Rhino.UnitAbsoluteTolerance
    	
    	If Rhino.IsCircle(strCirc) Then
    		dblRad=Rhino.CircleRadius(strCirc)
    		arrAllCrvs=Rhino.ObjectsByType(4)
    		For each strCrv in arrAllCrvs
    			If Rhino.IsCircle(strCrv) Then
    				If Abs(Rhino.CircleRadius(strCrv)-dblRad)<dbltol Then
    					Call Rhino.SelectObject(strCrv)
    				End If				
    			End If		
    		Next	
    	End If	
    End Sub

Depends on the shape. A circle is a specifically defined type of geometry object, a generic “shape” probably isn’t. Therefore you will have to define all the criteria necessary to make that shape uniquely distinguishable from other, similar shapes. This can be a combination of length, area, curve/surface degree, number of control points, etc. - the list is pretty large. Once the criteria have been found that uniquely define your shape, the easy part is to simply check all the objects and see which conform to all of the criteria.

1 Like

This problem is really hard for me

Well, it’s not really difficult, its simply a bit complex. As I said, the main thing is figuring out a logic that will find only the objects you want. That means testing each object for one or probably multiple characteristics that make that object unique. The more complex the object, the more tests will likely be required.

As each of these tests take some time, if you have many objects and many tests, it could also be slow. So another consideration is to put the tests in order of how fast they are to execute, and at the first one that fails, stop testing that object immediately for the rest and move on to the next object. Properties of an object are generally fast to access, whereas something like having to calculate an area or a volume might take longer.

Let’s see how I did the square test in the SelSquare script above. The “SquareTest” definition is the part of the script that checks an object to see if it’s a square. It is written using RhinoCommon, but the principle can also be applied using rhinoscriptsyntax. Here’s the whole thing:

def SquareTest(crvID,tol):
    crv=rs.coercecurve(crvID)
    if crv.IsPlanar(tol):
        rc,pl=crv.TryGetPolyline()
        if rc:
            if pl.IsClosed and pl.Count==5:
                sl=pl[0].DistanceTo(pl[1])
                if rm.EpsilonEquals(sl,pl[1].DistanceTo(pl[2]),tol):
                    if rm.EpsilonEquals(sl,pl[2].DistanceTo(pl[3]),tol):
                        if rm.EpsilonEquals(sl,pl[3].DistanceTo(pl[0]),tol):
                            dl=pl[0].DistanceTo(pl[2])
                            if rm.EpsilonEquals(dl,pl[1].DistanceTo(pl[3]),tol):
                                return True
    return False

Let’s break it down. The first thing is the object ID is passed to the function, as well as the tolerance value to be used in checking.

Then the base geometry - a curve object - is gotten from the object ID
crv=rs.coercecurve(crvID)
crv is the base curve geometry from which we will continue

if crv.IsPlanar(tol):
First we check for planarity within tolerance. A square is planar. So only if the curve is planar do we continue.

rc,pl=crv.TryGetPolyline()
This is a RhinoCommon method which tries to convert the curve into a polyline object. If it fails, rc will be False, otherwise rc will be True and the polyline object will be returned and referenced to pl

if rc:
We only will continue if the curve can actually be converted into a polyline object.

if pl.IsClosed and pl.Count==5:
We will only continue if the polyline is closed and has 5 control points (the start and end both count as one) Polyline objects in RhinoCommon are really just a list of 3d points (the vertices). All the points can be referenced in order like you get elements from a normal python list.

sl=pl[0].DistanceTo(pl[1])
We get the distance from the start point to the next point in the polyline, and store that value in the variable sl. That will be the side length of the square - all the other lengths must be equal.

if rm.EpsilonEquals(sl,pl[1].DistanceTo(pl[2]),tol):
EpsilonEquals is a RhinoCommon method for comparing values within tolerance. The above tests the second side - distance between polyline points [1] and [2] - to see if it is the same length as the first side within the given tolerance tol you could also write it without using EpsilonEquals like this:

if abs(sl - pl[1].DistanceTo(pl[2]))<tol:
(if the absolute value of a-b is less than tolerance, a and b are equal to within that tolerance)
Only if the second side is the same length as the first, do we continue. The same principle applies for the other two sides.

if rm.EpsilonEquals(sl,pl[2].DistanceTo(pl[3]),tol):
    if rm.EpsilonEquals(sl,pl[3].DistanceTo(pl[0]),tol):

So now we have a four sided polyline with all equal lengths. On a square, all four sides are equal lengths. But that is not a unique identifier. A parallelogram could have four equal sides as well. How do we differentiate between them?

A square will have four 90 degree angles. So we could test for those. Instead, I chose a different method which I found simpler - the two diagonals will be equal only when the object is a square. So I continue like this:

dl=pl[0].DistanceTo(pl[2])
Get the first diagonal length…

if rm.EpsilonEquals(dl,pl[1].DistanceTo(pl[3]),tol):
    return True

Compare the first diagonal length to the second. Only if they are equal length do we return True (object is a square). If not, by default, at any exit point the function returns False (not a square)

OK, that was a pretty long explanation - I hope it is understandable. Now, try and imagine a further selection criteria - say only squares that have a specific side length. Or, perhaps something quite different, like a pentagon… :stuck_out_tongue_winking_eye:

5 Likes

Thank you. Yes, very clear, concise response :+1:.
The Teacher returns; get him a new mouse pad.
Happy Holidays, Mitch @Helvetosaur

1 Like

Thanks Fred! —M

1 Like

can run on python okay

You are very good, thank you