How to get a RhinoObject not in the document?

Hi

Trying to use this method:

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_DocObjects_Tables_ObjectTable_Replace.htm

I see that the second argument ( RhinoObject ) must not be in the document.

How can I get such an object ?

Thanks

Hi Emilio,

def ReplaceGeometry():
    
    obj_id = rs.GetObject('select object to change geometry from')
    if not obj_id: return

    obj_id_geometry = rs.GetObject('select object with new geometry')
    if not obj_id_geometry: return

    geom = rs.coercegeometry(obj_id_geometry)
    
    scriptcontext.doc.Objects.Replace(obj_id,geom)
    rs.DeleteObject(obj_id_geometry)
    rs.Redraw()

Does this help?
-Willem

Hi Emilio,

The idea behind Replace is to replace an object that exists in the document (has an ID) with a “virtual” RhinoCommon object that hasn’t been written to the document (yet), and at the same time inherit the characteristics of the original (layer, color etc. and most importantly, object ID).

–Mitch

Hi Willem,

I’m trying to replace a block instance.
I’m pretty new to scripting blocks …:confused:
So far I have not been able to replace the instance by the code that you kindly posted.
But I’m going to try to understand something more and do more tests … :slight_smile:

Thanks a lot !

Hi Mitch.

What I’m not able to do is create a new RhinoObject object without adding it to the document using RhinoCommon … :confused:

Any idea about that ? :slight_smile:

Thanks !

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

objID=rs.GetObject("Pick some object")
bb=rs.BoundingBox(objID)
sphere=Rhino.Geometry.Sphere((bb[6]+bb[0])*0.5,25.0)
sph_obj=sphere.ToBrep()
sc.doc.Objects.Replace(objID,sph_obj)
sc.doc.Views.Redraw()

About blocks, I know next to nothing tho…

Yes, me too … :wink:

Your code, as far as I understand, is similar to Willem’s …

I think I’m still confused by the overloads of Replace() …

But I’m learning something new, little by little … :slight_smile:

Thank you !

Can you elaborate on what you want to do exactly?

You have a block instance you want to replace it with:

  • another instance?
  • a newly created block definition?
  • other geometry?

-WIllem

Sorry for not being clear …

I want to replace the instance with a different instance.
Actually I’m trying to mimic Rhino’s ReplaceBlock command, but without having Rhino print text into the command area.
The blocks to replace may be a lot, and they may be replaced more times, so I was curious to see if the script would run faster without using rs.Command().

… I thought that replacing ReplaceBlock would have been easy, but I was too optimistic about that …

Does the following do anything for you?

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_DocObjects_Tables_InstanceDefinitionTable_ModifyGeometry_2.htm

You make objects from Rhino.Geometry, then put them into the document. Generally the structure is (or what I have found to be):

Document -> Geometry
GUID -> Rhino Object / Object Reference -> Geometry Object

Geometry -> Document
Geometry Object -> GUID via document object table Add function

Here is another example:

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

# Make a sphere.  This is now an object not in the document
new_sphere = Rhino.Geometry.Sphere(Rhino.Geometry.Point3d.Origin, 1)
# Make a brep from the sphere
new_sphere_brep = Rhino.Geometry.Brep.CreateFromSphere(new_sphere)

# Add the sphere to the document and keep the returned guid
document_guid_for_sphere = sc.doc.Objects.AddBrep(new_sphere_brep)

# Redraw the viewports to see the sphere
sc.doc.Views.Redraw()

print('Added the sphere with guid {}'.format(document_guid_for_sphere))

# This is just to wait for user to press enter so can control the replacing
rs.GetString('Press enter to continue')

# Make a box.  We need an interval first
interval = Rhino.Geometry.Interval(-1, 1)
# Box will be at origin, from -1 to 1 on each axis
replacement_box = Rhino.Geometry.Box(Rhino.Geometry.Plane.WorldXY, interval, interval, interval)
# Now make a brep from the box
replacement_brep = Rhino.Geometry.Brep.CreateFromBox(replacement_box)

# Now can replace the document sphere with the non-document box brep object
# Note you have to handle any transformations before replacing
sc.doc.Objects.Replace(document_guid_for_sphere, replacement_brep)

# And redraw to see it
sc.doc.Views.Redraw

To replace blocks, you have to deal with the blocks (InstanceObjects) and their definitions and transforms, and also know about the InstanceDefinitionTable in the document. There is a function to add InstanceObjects from the doc objects table that takes an index from the InstanceDefinitionTable (to get the geometry and insertion point), and a transform to apply to that definition.

To replace blocks with another block, here is an example that is working here: (Note I couldn’t get some of the find functions on sc.InstanceDefinitionTable to work but got around it for now.)

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc



# get the replacement block
replacement_block_guid = rs.GetObject('select replacement block')
# we need the instance definition index.  Find functions from table don't seem to work?
replacement_rhino_object = rs.coercerhinoobject(replacement_block_guid)
replacement_instance_definition = replacement_rhino_object.InstanceDefinition
replacement_instance_definition_index = replacement_instance_definition.Index

# get the blocks to replace
block_guids_to_replace = rs.GetObjects('select blocks to replace')
for guid in block_guids_to_replace:
    # get the rhino object
    rhino_object = rs.coercerhinoobject(guid)
    # get the transform for the InstanceDefinition
    instance_xform = rhino_object.InstanceXform
    
    # now we can use the add function from the doc.Objects table
    print(sc.doc.Objects.AddInstanceObject(replacement_instance_definition_index, instance_xform))
    
    # and delete the old instance
    sc.doc.Objects.Delete(rhino_object)

There is not a replace or modify function that I have found for blocks, so this is the most direct method, to replace and delete.

Thanks Mitch

If I understand that correctly, it replaces all the instances of a definition.

I’m trying to replace some instances, individually, with instances of other definitions.
There can be a few different definitions used here to replace the old instances.

What were, say, a hundred instances of the same definition would then become (after running the script) , say, 30 instances of one definition, 20 of another one, and so on …

Thanks Nathan

Yes, I had tried that before, but obviously the Guids are not kept.
This is the reason why I tried to replicate ReplaceBlock’s behaviour …

But I think it’s only a matter of using attributes from the old object and updating the list of Guid’s in the script … :slight_smile:

I think I’ll do it this way.

Thanks again for your very clear samples.

Thank you all for your help !

These things are more clear for me now. :slight_smile:

Best regards.

This specific version of ReplaceObject is pretty rarely used. The only RhinoObjects you can make outside of the document are custom objects.

The ObjectTable.Replace()? Is this a warning?

I don’t understand this question. Was it directed at my post or something else?

Yes, sorry. Why is it pretty rarely used? Is there a better way?

Creating custom Rhino objects is not a common thing to do. Since this overload of ReplaceObject is specific to custom objects, then this function is not typically called.

Ahh, ok I think I understand now. Thanks.