An object's parent or children


#1

Hi,

Show me how to find an object’s parent or children, using Python Script in RhinoCommon.


(Dale Fugier) #2

Hi @gootzans,

Rhino objects do not have parents of children.

What problem are you trying to solve?

– Dale


#3

Hi Dale.

I’m sorry.
An object is an object with history.


#4

Hi @gootzans,

you might want to script the commands _SelParent and _SelChildren using rs.Command(). Both require that you have a parent or children selected beforehand.

c.


#5

Hi Dale.

You are right. And I’ve tried it.
But these commands show messeges like “One object is selected” on the command line.

What I’d like to do is,
Whether the object has a history?
If it has a history find parent or children
by accessing some class of RhinoCommon.


#6

@gootzans, i am not Dale :wink:

You can set echo=False to suppress the command messaging or add your own:

import rhinoscriptsyntax as rs
    
def SelChildren():
    parent_id = rs.GetObject("Select Parent object", 0, False, True)
    if not parent_id: return
    
    rc = rs.Command("_SelChildren _Enter", echo=False)
    if rc:
        rs.UnselectObject(parent_id)
        child_ids = rs.SelectedObjects(False, False)
        if not child_ids:
            print "No children found"
        else:
            print "Found {} children".format(len(child_ids))
        
SelChildren()

I think using scripting you have use the command _SelObjectsWithHistory and process the found objects to get the parent ids. Note that only children will be found like this, parents have no history.

c.


#7

I’m sorroy, clement.

Even if you change the parameter to (echo = False), the message “1 surface added to selection.” is showed.
I do not want a message to be showed.


#8

@gootzans, you’re right i was testing in V5 where the built in message is not shown, at least sometimes:

Select Parent object:
Found 1 children

Select Parent object:
1 curve added to selection.
Found 1 children

in the WIP the selection message always seems to show up.

c.


#9

import Rhino
import scriptcontext

children = []

def OneSurf(rhObject, geometry, componentIndex):
b = rhObject.ObjectType == Rhino.DocObjects.ObjectType.Brep
b = b and geometry.Surfaces.Count == 1
b = b and not rhObject.Id in children
return b

def Main():
rhObjects = [None, None]
go = Rhino.Input.Custom.GetObject()
go.SetCustomGeometryFilter(OneSurf)
for i in range(2):
go.SetCommandPrompt("Select surface " + str(i + 1))
go.Get()
if go.CommandResult() != Rhino.Commands.Result.Success:
return go.CommandResult()

    rhObjects[i] = go.Object(0).Object()
    rhObjects[i].Select(False)
    scriptcontext.doc.Views.Redraw()

    if i == 0: children = GetChildren(rhObjects[i])

go.Dispose()

def GetChildren(rhObject):
ids = []

scriptcontext.doc.Objects.Select(rhObject.Id)
if Rhino.RhinoApp.RunScript("_SelChildren", False):
    ids = [rhObj.Id for rhObj in scriptcontext.doc.Objects.GetSelectedObjects(False, False)]
scriptcontext.doc.Objects.UnselectAll()

return ids

if name == “main”:
Main()


#10

I’m sorry.

The previous Reply is not good.
I do not understand how to use the editor well.


#11

I want to change the source code of “def GetChildren ():”.
When the second surface is selected, child objects can not be selected.

import Rhino
import scriptcontext

children = []

def OneSurf(rhObject, geometry, componentIndex):

b = rhObject.ObjectType == Rhino.DocObjects.ObjectType.Brep
b = b and geometry.Surfaces.Count == 1
b = b and not rhObject.Id in children
return b

def Main():

rhObjects = [None, None]
go = Rhino.Input.Custom.GetObject()
go.SetCustomGeometryFilter(OneSurf)
for i in range(2):
    go.SetCommandPrompt("Select surface " + str(i + 1))
    go.Get()
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    rhObjects[i] = go.Object(0).Object()
    rhObjects[i].Select(False)
    scriptcontext.doc.Views.Redraw()
    if i == 0: children = GetChildren(rhObjects[i])
go.Dispose()

def GetChildren(rhObject):

ids = []
scriptcontext.doc.Objects.Select(rhObject.Id)
if Rhino.RhinoApp.RunScript("_SelChildren", False):
    ids = [rhObj.Id for rhObj in scriptcontext.doc.Objects.GetSelectedObjects(False, False)]
scriptcontext.doc.Objects.UnselectAll()
return ids

if name == “main”:
Main()


#12

@gootzans,

try below to limit the selection to objects without a history record. Note that this works using Rhino WIP only.

# Rhino WIP only, limit selection to objects without history
    
import Rhino
import scriptcontext
import rhinoscriptsyntax as rs
    
def myfilter(rhObject, geometry, componentIndex):
    log =  Rhino.FileIO.TextLog()
    Rhino.DocObjects.RhinoObject.Description(rhObject, log)
    if not "Record index:" in log.ToString():
        return True
    return False

def CustomGetObjWithoutHistory():
    id = rs.GetObject(None, 0, True, False, myfilter)
    if not id: return
    
CustomGetObjWithoutHistory()

c.


#13

Thank you, clement.

So then in Rhinoceros5 do I mean I can not do what I want to do?


#14

@gootzans,

above script uses:

Rhino.DocObjects.RhinoObject.Description

which is not available in Rhino 5. Basically it returns the content of the _What command which is then searched for the Record id. To get this in Rhino 5 you could use the clipboard to store the text like described here.

The problem is, you’ll have to do this before asking for a selection and limit your selection to objects which do not have a record id, so the myfilter function could not be used. Instead you would have to select possible objects, run the _What command , store the content in the clipboard, search for the record id of every object and limit the selection to allowed objects using GetObjectEx() like below:

import rhinoscriptsyntax as rs

def CustomGetObjWithoutHistory():
    
    rs.EnableRedraw(False)
    all_objs = rs.AllObjects(True, False, False, False)
    rc = rs.Command("_-What _Clipboard _Enter", False)
    result = rs.ClipboardText() if rc else None
    rs.ClipboardText("")
    rs.UnselectAllObjects()
    rs.EnableRedraw(True)
    
    if result:
        descriptions = result.split("\n\n")
        searchlist = zip(all_objs, descriptions)
        allowed_objs = [n[0] for n in searchlist if not "Record id:" in n[1]]
    else:
        allowed_objs = rs.NormalObjects(False, False)
    
    id = rs.GetObjectEx("Select", 0, False, True, allowed_objs)
    if not id: return
    
CustomGetObjWithoutHistory()

This works in V5, but has a 4 drawbacks, it is ugly, may be slow with many objects, clears the clipboard and it does not allow for a preselection.

c.


#15

Thank you, clement.

But the purpose is different.
Instead of letting users can not select objects with history, they can not select the children of the first object selected.


#16

@gootzans, my 3 examples shown above show how you could find the child or parent of an object using scripted commands and how to find out which object has history. As far as i understand from your posts you’re trying to setup a GetObject prompt which does not allow to select child objects:[quote=“gootzans, post:11, topic:45626”]
When the second surface is selected, child objects can not be selected.
[/quote]

This does not require _SelChild, as all you have to know is if an object has history and exclude it from the selection. Maybe you should give a detailed description of what you’re trying to do and which object types are involved. I am sure it’s possible somehow :wink:

c.


#17

Hi, in RhinoScript there are some history methods:
ObjectHasHistory
IsObjectChild
IsObjectParent
ObjectChildren
ObjectParents
It would be possible to use it from python, but that’s a bit of a hack…


#18

clement.

Thank you for teaching me a lot.
I have never used the Rhino.FileIO.TextLog () method.
I will try to use it with RhinoWIP.


#19

Thank you, Jess.

I can solve it by using the methods you showed.
I could not find them in Rhinoscript’s help but …


#20

@gootzans, the suggestion @Jess made is referring to RhinoScript (vbScript). As far as i can see, those methods are not yet available in Python.

c.