Mimic the SelDup command

If I have a curve without the GUID, how do I mimic the SelDup command but only find duplicates for that specific curve? Is there an method that allows me to do this or do I need to iterate through all the document’s objects and do a lengthy comparison of the all the object’s properties?

Anything that inherits from GeometryBase, such as Curve, does not have a GUID. Rhino objects, objects that inherit from RhinoObject, have GUIDs.

The SelDup command works by iterating the document’s object table, essentially calling GeometryBase.GeometryEquals. You should be able to do the same.

– Dale

1 Like

Thanks for the help Dale. I’m am able to compare the objects using GeometryEquals just fine, but now I want to know without using the GUID how to know if the current object is equal to the same object in a for loop. I tried using the GeometryBase.Equals, however, it is not working as expected. I must be missing something here. Can you give me some light on why I am not able to use the Equals method to compare objects to determine if the two objects are the exact same object?

Here is the code I’m using in Python script. In a new file can you draw a line, copy it in place, draw another line somewhere else, and run the code? This is just sample code to show you what I’m trying to do. The actual code is totally different.

import Rhino
import Rhino.Geometry as rg
import scriptcontext as sc

filter = Rhino.DocObjects.ObjectType.Curve
rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", True, filter)

co = objref.Curve()

numObjFound = 0
objNbr = 0
for obj in sc.doc.ActiveDoc.Objects:
    o = obj.Geometry
    objNbr += 1
    print 'Object # ' + str(objNbr) + ' is a ' + str(o)
    
    #if rg.GeometryBase.Equals(co, o):
    if co.Equals(o):
        print 'This is the selected object.'
    
    if rg.GeometryBase.GeometryEquals(co, o):
        numObjFound += 1

print
print 'Number of times curve found that are the same as the selected curve including the selected curve itself: ' + str(numObjFound)

Also, when using the Variables tab in the debugger, how do I access the base property show in the screenshot? In the code above right now I am getting the following:

<Rhino.Geometry.LineCurve object at 0x00000000000000BB [Rhino.Geometry.LineCurve]>

All I want is Rhino.Geometry.LineCurve just like it’s shown in the variables tab. Is there a direct way to access that without parsing what I’m currently getting?

Hi @Mike24,

Does this help?

import Rhino
import scriptcontext as sc

def test_sel_dup():
    filter = Rhino.DocObjects.ObjectType.Curve
    rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", False, filter)
    if not objref or rc != Rhino.Commands.Result.Success: 
        return
    
    srcId = objref.ObjectId 
    srcGeometry = objref.Geometry()
    if not srcGeometry:
        return
    
    sc.doc.Objects.UnselectAll()
    
    numDuplicates = 0
    for rhObj in sc.doc.ActiveDoc.Objects:
        if srcId != rhObj.Id:
            if Rhino.Geometry.GeometryBase.GeometryEquals(srcGeometry, rhObj.Geometry):
                numDuplicates += 1
                rhObj.Select(True, True)
    
    if numDuplicates > 0:
        sc.doc.Views.Redraw()
    
    if numDuplicates == 1:
        print("1 duplicate found.")
    else:
        print("{0} duplicates found.".format(numDuplicates))

if __name__ == "__main__":
    test_sel_dup()

– Dale

Hey @dale -

I think there is a misunderstanding. I appreciate the code you posted but as I stated in the previous post I am able to use the GeometryEquals method just fine. I would like to know what the Equals method is used for. It appeared in the documentation it is to compare two objects to see if they are the exact same object (without using the GUID), yet I am getting False returned when comparing the exact same object.

Also can you comment on the 2nd issue where I am trying to get ‘Rhino.Geometry.LineCurve’ returned without having to parse ‘<Rhino.Geometry.LineCurve object at 0x00000000000000BB [Rhino.Geometry.LineCurve]>’?

Thanks!

I think we need some context here…why do you have a curve with no GUID? Did you make it and not add it to the document?

You asked for SelDup and Dale gave you that, so what are you actually trying to do? Are you trying to see if some curve object you have is identical to another, or to see if two variables are referring to literally the same instance of an object, which is more of a Python question than a Rhino one?

More on Object.Equals.

This method is returning False because the .NET objects are not the same. The .NET objects do reference the same Rhino object, however.

This slightly modified example illustrates this:

import Rhino
import scriptcontext as sc

def test_sel_dup():
    filter = Rhino.DocObjects.ObjectType.Curve
    rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", False, filter)
    if not objref or rc != Rhino.Commands.Result.Success: 
        return
    
    srcId = objref.ObjectId 
    srcGeometry = objref.Geometry()
    if not srcGeometry:
        return
    
    sc.doc.Objects.UnselectAll()
    
    print("Selected id: {0}, hash: {1}".format(srcId, srcGeometry.GetHashCode()))
    numDuplicates = 0
    for rhObj in sc.doc.ActiveDoc.Objects:
        if srcId != rhObj.Id:
            print("Object id: {0}, hash: {1}".format(rhObj.Id, rhObj.Geometry.GetHashCode()))
            if Rhino.Geometry.GeometryBase.GeometryEquals(srcGeometry, rhObj.Geometry):
                numDuplicates += 1
                rhObj.Select(True, True)
    
    if numDuplicates > 0:
        sc.doc.Views.Redraw()
    
    if numDuplicates == 1:
        print("1 duplicate found.")
    else:
        print("{0} duplicates found.".format(numDuplicates))

if __name__ == "__main__":
    test_sel_dup()

– Dale

Use isinstance.

import Rhino
import scriptcontext as sc

def test():
    filter = Rhino.DocObjects.ObjectType.Curve
    rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", False, filter)
    if not objref or rc != Rhino.Commands.Result.Success: 
        return
    
    geometry = objref.Geometry()
    if not geometry:
        return
    
    if isinstance(geometry, Rhino.Geometry.LineCurve):
        print("Line curve, length: {0}".format(geometry.Line.Length))

if __name__ == "__main__":
    test()

– Dale

1 Like

@Dale - Ok thanks. I have used isinstance many times before. I was hoping there was a direct way to print the object type since the variables tab of the debugger displays it. Thanks for the input.

@JimCarruthers - The code that I have been given to modify has 100k objects where the GUIDs were not kept so I was hoping if I had a specific object that could easily find any duplicates without having to go back and modify the code to keep track of the GUIDs. I realize having the GUIDs makes it easy but that’s not what I’m dealing with in the current version of the code I am having to work with. Hence, that is why I presented the question in such a way where I didn’t have the GUID but wanted to find any duplicates out there.

@dale - Ok thanks for this. I didn’t know about the GetHashCode method and that makes sense since the hashcode is different for every object. I took this a step further and examined the hashcode for the selected object and also printed the hashcode for every object and the selected object’s hashcode is even different than ALL of the objects in the document including the one with the same GUID. So even the selected object’s hashcode is different than the same object that is in the document. So what this is telling me is that the ONLY way to know if a selected object is the same as one of the objects when iterating through the document’s objects is to compare GUIDs. There is no other way to know if the objects are the same object except for comparing GUIDs. Is this correct?

Yes.

– Dale

@dale - Ok thank you.