How to modify a block definition in python?

I want to get an object from a file and add it to the block definitions (I figured out how to do this). Then, I would like to add other obects to the block definition. This is what I’ve got so far (for an example). When I run it, I get an error saying that Breps do not have a Geometry attribute.

#! python3
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino.Geometry as rg
import Rhino
from Rhino import RhinoDoc as rdoc

block_name = rdoc.ActiveDoc.InstanceDefinitions.GetUnusedInstanceDefinitionName("torus")
path = "C:\\Users\\Owner\\Desktop\\torus.3dm"

torus_file = Rhino.FileIO.File3dm().Read(path)
torus = torus_file.Objects.FindByLayer('Default')[0]
index = rdoc.ActiveDoc.InstanceDefinitions.Add(block_name, "", rg.Plane.WorldXY.Origin, torus.Geometry, torus.Attributes)

sphere = rg.Sphere(rg.Plane.WorldXY.Origin, 1.2).ToBrep()
rdoc.ActiveDoc.InstanceDefinitions.ModifyGeometry(index, sphere.Geometry, sphere.Attributes)

# I would like this to have the torus and the sphere combined
sc.doc.Objects.Add(torus.Geometry, torus.Attributes)





insert_block_test.py (801 Bytes)
torus.3dm (55.0 KB)

Please check:

1 Like

Thanks, Nathan. That worked for me.

The script I ended up with was…

#! python3
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino.Geometry as rg
import Rhino
from Rhino import RhinoDoc as rdoc

block_name = rdoc.ActiveDoc.InstanceDefinitions.GetUnusedInstanceDefinitionName("torus")
path = "C:\\Users\\Owner\\Desktop\\torus.3dm"

torus_file = Rhino.FileIO.File3dm().Read(path)
torus = torus_file.Objects.FindByLayer('Default')[0]
index = rdoc.ActiveDoc.InstanceDefinitions.Add(block_name, "", rg.Plane.WorldXY.Origin, torus.Geometry, torus.Attributes)

sphere = rg.Sphere(rg.Plane.WorldXY.Origin, 1.2).ToBrep()

geometry = []
attributes = []
geometry.append(torus.Geometry)
geometry.append(sphere)
attributes.append(torus.Attributes)
attributes.append(sc.doc.CreateDefaultAttributes())


rdoc.ActiveDoc.InstanceDefinitions.ModifyGeometry(index, geometry, attributes)
rdoc.ActiveDoc.InstanceDefinitions.Find(block_name)
idef = rdoc.ActiveDoc.InstanceDefinitions.Find(block_name)

obs = idef.GetObjects()
for ob in obs:
    sc.doc.Objects.Add(ob.Geometry, ob.Attributes)

Not sure why you are adding the objects from your instance definition separately.

You probably just should add a block instance of your definition to the document with ObjectTable.AddInstanceObject Method (Int32, Transform)

With the index you already have after creating the new instance definition:

sc.doc.Objects.AddInstanceObject(index, rg.Plane.WorldXY.Origin)
1 Like

Not sure why you are adding the objects from your instance definition separately.

I did that because I didn’t know about AddInstanceObject(). I’m glad you pointed this out, because this is exactly what I was looking for.

BTW, it takes a transform, not a point3d (I only realized after the Editor complained about it). But, in this case, I didn’t want to transform it. So, I tried to use Rhino.Geometry.Transform.Unset and Rhino.Geometry.Transform.ZeroTransformation. It ran without errors, but it did not actually add the objects to the document. So, I had to make my own dummy transform object. I ended up with this:

xform = rg.Transform.Scale(rg.Plane.WorldXY.Origin, 1)
sc.doc.Objects.AddInstanceObject(index, xform)

Ah yes, my bad. Friday evening brain fart. Use rg.Transform.Identity instead ( Transform.Identity Property ):

sc.doc.Objects.AddInstanceObject(index, rg.Transform.Identity)

1 Like

That worked perfectly! Thanks!!!