Add Block Instance into file

Good afternoon sirs!

I’m currently experimenting on how I can exchange information from rhino to python and the other way arround. So I was testing how to write a block instance into a 3dm file.
Here is what I coded so far:

    success, block = check_block_in_file3dm(True, block_name, rhino_file3dm)
    rhino_layer = Rhino.DocObjects.Layer()
    rhino_layer.Name = 'objects'
    rhino_layer.Color = System.Drawing.Color.FromArgb(0, 227, 144)
    file3dm.AllLayers.Add(rhino_layer)
    rhino_object_attributes = Rhino.DocObjects.ObjectAttributes()
    rhino_object_attributes.LayerIndex = rhino_layer.Index
    rhino_object_attributes.Name = block_name
    xform = rg.Transform()
    xform.M03 = 1
    xform.M13 = 1
    xform.M23 = 0
    file3dm.Objects.AddInstanceObject(block.Index, xform, rhino_object_attributes)
    file3dm.Write("test_exports/test-export-to-rhino.3dm", 6)

Where check_block_in_file3dm(True, block_name, rhino_file3dm) is:

def check_block_in_file3dm(prev_success: bool, block_name: str, file3dm):
    success = False
    block = None
    all_blocks = file3dm.AllInstanceDefinitions
    for b in all_blocks:
        if b.Name == block_name:
            success = True
            block = b
    return(success, block)

The ‘block’ variable used is a valid InstanceDefinitionGeometry and the code runs without erros, but the 3dm file created has no objects in it. Any ideia on where the problem is?
I guess that I still don’t understand how to add InstanceObjects into a document.

Thank you.

Hi @thomas.takeuchi,

Do you really need to write an instance definition to a 3dm file? Doing so will cause Rhino to created a nested block upon insertion.

– Dale

Hello @dale, thank you for the reply!

The idea was to have a central file, template, with all needed blocks, like so:

And then, when needed, place one of those blocks into a new, empty, file.
Would there be another way to achieve the same intented objective?

-Thomas

Imo a better way would be to store every block as a single file and just insert each file as you need it. You can script the insert command or do it with rhino common.

Hello rgr,

Thank you for replying. Could you give me an example on how I could do that?
Is there an Insert Method in Rhino Common?

-Thomas

Hi,
Maybe have a look at this thread:

Basicly what you are doing is a) using the RhinoScript Method
oe b) see the link @jeffoulet just posted.

Thank you very much @rgr @jeffoulet!
I’ll definitely try that!

-Thomas

Hello guys, I just now realised that I never gave you a followup to my issue.
Taking your advices, I manage to acomplish what I wanted, wich was to load all blocks from a reference file3dm into a target file3dm.
I’m sure that this will be helpful to someone in the future so here is how I did it:

def explode_block(
file3dm_objects: File3dmObjectTable,
block: InstanceDefinitionGeometry,
) -> IEnumerable:
        """
    Explode a block into its composing elements
        Parameters
        ----------
        file3dm_objects
            A reference file3dm containing the block to be exploded
        block
            A block to explode

        Returns
        -------
        block_elements
            An Enumerable list of composing elements from exploded block
    

        """
        block_elements = List[Rhino.Geometry.GeometryBase]()
        for obj_id in block.GetObjectIds():
            if obj_id is not None:
                obj = file3dm_objects.FindId(obj_id).Geometry
                block_elements.Add(obj)

        return IEnumerable(block_elements)


def load_all_blocks_from_file3dm(
file3dm_src: File3dm,
file3dm_tgt: File3dm,
) -> File3dm:
        """
        Load all blocks form a source File3dm into a target File3dm
        Parameters
        ----------
        file3dm_src
            A source file3dm containing all blocks to be loaded
        file3dm_tgt
            A target file3dm where the blocks will be loaded

        Returns
        -------
        file3dm_tgt
            A modified file3dm with all blocsk loaded from reference file

        Notes
        -----
        For now, it only works with block that are not composed out of
        other blocks
        For that purpose it is necessary to add recurssion to function

        """

        all_blocks_src = file3dm_src.AllInstanceDefinitions
        all_objects_src = file3dm_src.Objects

        for block in all_blocks_src:
            file3dm_tgt.AllInstanceDefinitions.Add(
                block.Name,
                block.Description,
                Plane.WorldXY.Origin,
                explode_block(
                    all_objects_src,
                    block,
                ),
            )

        return file3dm_tgt
1 Like