Insert file as block in RhinoCommon (not via CommandLine)

Hello there,

right now I am using the command line to insert external files as a block and I have to admit it is a bit bulky.

Is there any way of doing that in RhinoCommon?
I found some documentation on FileIO, but I have to admit that I can’t see how to possibly achieve that.

Thanks in adavance,
T.

1 Like

Hi @tobias.stoltmann,

You could try to first create a block with a dummy object (probably a Point3d at the origin). And then modify the source archive of that newly created block to the file you want to insert. This should bring your file to your document…

string myNewBlockName = "MyBlock";
string myNewBlockFilePath = @"C:\Users\.........\MyBlock.3dm";

List<GeometryBase> dummyInitialObjects = new List<GeometryBase>() { new Point(Plane.WorldXY.Origin) };
List<ObjectAttributes> dummyInitialAttributes = new List<ObjectAttributes>() { new ObjectAttributes() };
int indexOfAddedBlock = RhinoDoc.ActiveDoc.InstanceDefinitions.Add(myNewBlockName, "", Plane.WorldXY.Origin,
                    dummyInitialObjects , dummyInitialAttributes);


bool modified = RhinoDoc.ActiveDoc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock,
                    Rhino.FileIO.FileReference.CreateFromFullPath(myNewBlockFilePath), InstanceDefinitionUpdateType.LinkedAndEmbedded, true);
2 Likes

@Darryl_Menezes, fine. Thanks first tof all.
I am not so good in C# though and will try to rewrite that code in Python.
Or would you be so kind as to help he with this one?

Same code in python would be something like this

import Rhino as Rh


myNewBlockName = "MyBlock"
myNewBlockFilePath = "C:\\Users\\.........\\MyBlock.3dm"

dummyInitialObjects = [Rh.Geometry.Point(Rh.Geometry.Plane.WorldXY.Origin)]  
dummyInitialAttributes = [Rh.DocObjects.ObjectAttributes()]
indexOfAddedBlock = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.Add(myNewBlockName, "", Rh.Geometry.Plane.WorldXY.Origin,dummyInitialObjects , dummyInitialAttributes)


modified = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock,Rh.FileIO.FileReference.CreateFromFullPath(myNewBlockFilePath), Rh.DocObjects.InstanceDefinitionUpdateType.LinkedAndEmbedded, True)
Rh.RhinoDoc.ActiveDoc.Objects.AddInstanceObject(indexOfAddedBlock,Rh.Geometry.Transform.Identity)
1 Like

Perfect! Thanks, @Darryl_Menezes

@Darryl_Menezes, one last question.
Right now, the block is linked and embedded.
Is there any option to chose embedded only?

You have to change the InstanceDefinitionUpdateType to static

1 Like

@Darryl_Menezes, somehow this does not work. It only creates a point at the insertion point.

@tobias.stoltmann,
The code was just an example on how to insert file as a block. What it does is, it creates a block with just a point, and then updates its link (source archive), to the file which you want to link it. If the link isnt valid, then it wont be updated.
So you could add a few statements to the code to check if the file path is valid, and also modified is False, then delete the created block (because then it only has a Point)

@Darryl_Menezes, I am aware that this was an example only.
I implemented the code and for the linked and embedded version it works perfectly fine.
But when I try to use the “Static” argument instead of the LinkedAndEmbedded one, it only inserts the point.
So I checked:
Path is valid and file is there True
modified prints a True as well

The only thing I did is to replace this line:
modified = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock,Rh.FileIO.FileReference.CreateFromFullPath(location), Rh.DocObjects.InstanceDefinitionUpdateType.LinkedAndEmbedded, True)

with this one:

modified = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock,Rh.FileIO.FileReference.CreateFromFullPath(location), Rh.DocObjects.InstanceDefinitionUpdateType.Static, True)

Oh, then in this case you could use “LinkedAndEmbedded”, and later embed them using DestroySourceArchive()

modified = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock,Rh.FileIO.FileReference.CreateFromFullPath(location), Rh.DocObjects.InstanceDefinitionUpdateType.LinkedAndEmbedded, True)
addedBlock = Rh.RhinoDoc.ActiveDoc.InstanceDefinitions[indexOfAddedBlock]
Rh.RhinoDoc.ActiveDoc.InstanceDefinitions.DestroySourceArchive(addedBlock,True)

Okay, I already tried that, that works fine.
THANKS once again, @Darryl_Menezes . :slight_smile:

I’m sorry everyone to re-open this old post, but I’m in the same situation and there’s something that doesn’t work and I don’t understand what it is!

I’m creating a plugin that, among other things, programmatically tries insert a 3dm survey file (mostly lines and hatches) inside the current document as a block.
Something like this normal behaviour of Rhino, but automated basically:

I’ve been looking in the APIs for the Insert command but couldn’t find anything. It was then confirmed by this post Add Objects from dxf via Rhino.FileIO.FileReference with their original attributes - #3 by tobias.stoltmann (not sure if there are news @dale )

I’ve tried to follow the code in this thread at hand and once I run it, if I open the Block Manager I can see my survey file is there, but no elements and/or layers shows up in the model!

My plugin is written in C# and this is what I’m doing:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
    RhinoDoc surveyDoc = RhinoDoc.OpenHeadless(surveyFilePath);

    ObjectTable objects = surveyDoc.Objects;

    List<GeometryBase> geoms = new List<GeometryBase>();
    foreach (var obj in objects)
    {
        geoms.Add(obj.Geometry);
    }

    List<ObjectAttributes> dummyInitialAttributes = new List<ObjectAttributes>() { new ObjectAttributes() };

    int indexOfAddedBlock = doc.InstanceDefinitions.Add("Test", "", Plane.WorldXY.Origin,  geoms, dummyInitialAttributes);

    bool modified = doc.InstanceDefinitions.ModifySourceArchive(indexOfAddedBlock, FileReference.CreateFromFullPath(surveyFilePath), InstanceDefinitionUpdateType.Static, true);
}

I really don’t understand why I see the block in the manager but no objects in the model.
Any ideas??

Thanks!

Hi @Andrea_Tassera ,
you could script the Insert command like this. This will insert the block as Embedded at WorldXY origin, with scale 1, and rotation 0.

RhinoApp.RunScript($"_-Insert F \"{surveyFilePath}\" B 0 1 0 ", false);

If you want it as LinkedAndEmbedded,
RhinoApp.RunScript($"_-Insert F L m \"{surveyFilePath}\" B 0 1 0 ", false);

basically you can type the _-Insert command in the command line, and look at the options in each step, to get an idea what script to run to get what result you want

1 Like

Thanks @Darryl_Menezes

I was hoping to find a way to do it through the APIs, but this will do for now!

Thanks for the help!