How to select all objects in file and move them using a script

Hello,
I’m new to Rhino. I have several .3dm files containing groups of objects, and I’m trying to combine them together to one .3dm file using python script.
I need to load each file’s group of objects into a certain location in the combined file, and I’m not sure how to do it.
I have a function that imports several .3dm files into one file, and I know how to select all the objects in the activeDoc, but I am not sure how to proceed.
Any help will be appriciated!
thanks

p.s. I can either move the object groups in the imported files and then import them or import the object group to a certain location in the combined file. I prefer the second option but the first one also will do.

Hi @Hanna_Keller,

Here is a sample that works with a single file. Perhaps this is a good starting place for a script that works with multiple files.

import Rhino
import scriptcontext as sc

# This example demonstrates how to retrieve the objects that
# were created by scripting a Rhino command.

def test_import_file():
    # Prompt the user to select a 3dm file
    fd = Rhino.UI.OpenFileDialog()
    fd.Filter = 'Rhino 3D Models|*.3dm||'
    if not fd.ShowOpenDialog(): 
        return
    
    # Surround path with double-quotes (in case it contains spaces)
    path = chr(34) + fd.FileName + chr(34)
    
    # Get the starting object runtime serial number
    start_sn = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    
    # Script the Import command
    cmd = '_-Import {0} _Enter'.format(path)
    Rhino.RhinoApp.RunScript(cmd, False)
    
    # Get the ending object runtime serial number
    end_sn = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    
    # If the scripted command completed successfully and new objects were
    # added to the document, end_sn will be greater than start_sn. So all
    # that's left to do is find the newly added objects.
    rh_objects = []
    for sn in range(start_sn, end_sn):
        rh_obj = sc.doc.Objects.Find(sn)
        if rh_obj:
          rh_objects.append(rh_obj)
    
    # Move the newly added objects (example)
    dir = Rhino.Geometry.Vector3d(10.0, 10.0, 0.0)
    xform = Rhino.Geometry.Transform.Translation(dir)
    for rh_obj in rh_objects:
        sc.doc.Objects.Transform(rh_obj, xform, True)
    
    # Done!
    sc.doc.Views.Redraw()
    
if __name__ == "__main__":
    test_import_file()

test_import_file.py (1.5 KB)

– Dale

1 Like

Thanks! I combined your code with my previous script for importing multiple .3dm files and it worked like a charm :slight_smile:
Follow up question: I have an example of a 3dm file, and a 3dm file with the same group of objects in some arbitrary different location. I want to move the group of objects in the second file exactly to the place they are in the example file, using script. With your help I can import the object to wherever I want :slight_smile:
The question: how do I find the location of the object groups in the example file? I tried moving (with the translate from your script) all the objects to the volume centroid of the group in the example file, but it obviously didn’t work.
Thanks!

P.S. I don’t have to use script to find the location of the original objects. I can do it manually in rhino - I just don’t know how.

Hi @Hanna_Keller,

Determining which group of objects are the same might be challenging. I’ll leave that to you.

Once you have figured out which groups of objects are the same, I’d calculate the bounding box of each group, using RhinoObject.GetTightBoundingBox. Then just create a vector between the two box centers, create a translation transformation, and do it.

Some pseudo-code:

var group0 = List<RhinoObject>();
// TODO: Fill in group0
var group0 = List<RhinoObject>();
// TODO: Fill in group1

var bbox0 = RhinoDoc.GetTightBoundingBox(group0)
var bbox1 = RhinoDoc.GetTightBoundingBox(group1)

var dir = bbox1.Center - bbox0.Center;
var xform = Transform.Translation(dir);

foreach (var rhobj in group0)
  doc.Objects.Transform(rhobj, xform, true);

doc.Views.Redraw();

– Dale

Thanks for the detailed answer!
I tried to implement your suggested psudo code and encountered strange behavior:

I wanted to move the center of the bbox of the group of objects to
wanted location: [-0.054,-1.631,35.005]
I calculated the center of the bbox of the group of objects in the original file (before moving):
m_bbox.Center: [-0.0549563848703185,12.5509077503052,35.0059236223493]
And the dir, to move all the objects by:
dir: [0.000956384870318509,-14.1819077503052,-0.000923622349283448]
It looks alright. But when I transformed all the objects along the dir and calculated the center of the new bbox, the new center was suprisingly at:
new m_bbox.Center: [-0.0549563848703185,5.45995387515261,35.0059236223493].
I used this function to move the object group:

def moveLetterToPoint(path, location,sett):
    # Get the starting object runtime serial number
    start_sn = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    # Script the Import command
    comm_str="_-Import "+chr(34)+path+chr(34)+sett+" _Enter"
    rs.Command (comm_str, False)
    if rs.LastCommandResult()==0: print("success!")
    # Get the ending object runtime serial number
    end_sn = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    rh_objects = []
    for sn in range(start_sn, end_sn):
        rh_obj = sc.doc.Objects.Find(sn)
        if rh_obj:
          rh_objects.append(rh_obj)
    m_bbox = Rhino.Geometry.BoundingBox()
    for object in rh_objects:
        rc, bbox = Rhino.DocObjects.RhinoObject.GetTightBoundingBox([object])
        if rc:
           m_bbox.Union(bbox)
    # Move the newly added objects
    dir =  m_bbox.Center - Rhino.Geometry.Point3d(location);
    xform = Rhino.Geometry.Transform.Translation(-dir);
    for rh_obj in rh_objects:
        sc.doc.Objects.Transform(rh_obj, xform, True)
    sc.doc.Views.Redraw()

What am I doing wrong?