How to Import Instance Definitions from a 3dm file C#

Hello,

I have a question about the best workflow to do the following:

I have a 3dm file with some blocks and nested blocks, as shown in the image.

I want to use the File3dm class, and import all of the objects from the file into my Rhino document, and eventually wrap them into an InstanceDefinition.

The catch is that the Instance Definitions A,B,C from the 3dm file should also “pass-through” into the document.

At the moment I am simply iterating through the objects in the File3dm and getting their geometries.

foreach (var obj in file.Objects)

One of them is a block instance and i can see it identified it as InstanceReferenceGeometry. Of course, when I use its obj.Geometry it simply takes the geometry that is “inside” the block. If I have nested blocks, again, only the geometries from those blocks are extracted.

How do I take the instance definitions from the file as well and add them to the document so that all block instances from the file are imported as block instances, and not geometries?

Thanks
Milos

to get all infos about the instance Definitions look at
https://developer.rhino3d.com/api/rhinocommon/rhino.fileio.file3dminstancedefinitiontable

and/or

https://developer.rhino3d.com/api/rhinocommon/rhino.docobjects.tables.instancedefinitiontable

Thanks @Tom_P ,

but still did not manage to resolve it until the end.

Step1: Inside the File3dm I go through the InstanceDefinitionGeometrys in the File3dmInstanceDefinitionTable. I copy those “blocks” into my Rhino document…I do it “manually”, by creating a new InstanceDefinition with the same name, description and the same geometries and attributes…I don’t think there is another way…?

Now I need to recognize the block instances inside File3md and bring them over to my active document.

Step2: I iterate through the file3dm.Objects and have to recognize which of them are blocks…the only way I found is this: if (obj.Geometry is InstanceReferenceGeometry irg). Is this correct? Because I did not find any other way…if(obj is instanceObject) and similar, does not work for the File3dm.

Step3: Once I do recognize it as InstanceReferenceGeometry, how do I now “copy” that block to my document. If I try to get the position of this InstanceReferenceGeometry using XForm I keep getting 0,0,0…that is the piece of puzzle I am missing at the moment.

I thought I could recognize the position of the block in the file3dm and then create a new instance of the same block (that I previously recreated) at that position…but I am not sure how to get the proper position…

Thanks

something like this ?
just an code snippet - modified from another context and not tested much

            if (obj.Geometry is InstanceReferenceGeometry irg)
            {
                Transform xform = irg.Xform;
                Guid id = irg.ParentIdefId;
                Rhino.Geometry.InstanceDefinitionGeometry instDgeo = file3dm.AllInstanceDefinitions.FindId(id);
                string idgeoname = instDgeo.Name;
                InstanceDefinition docInstD = doc.InstanceDefinitions.Find(idgeoname);
                if (docInstD != null)
                {
                    ObjectAttributes attrs = obj.Attributes;
                    doc.Objects.AddInstanceObject(docInstD.Index,xform);
                }
            }

somehow it feels crazy that there is not a simpler method to import blocks from a file…
if you manage - would be nice to share a working sample.

Hi @dimcic,

Any reason you don’t just import the 3dm file?

– Dale

Hi @dale ,

I would like better control over the import. Once it gets imported into the document, I want to wrap everything up in another block. Also, I need to manipulate the attributes before I add them to the document…for example, I am moving all the imported objects into one layer.

I could use the “manual” import and track what geometries and InstanceDefinitions existed before the import and which ones are new, and use that to distinguish them…then move them to a different layer, purge layers, pack them into an InstanceDefinition, etc…but that seems a bit “hacky”…not so clean…

The best workflow for me would be to recognize that an Object from the File3dm is an InstanceObject, then copy (or recreate) the InstanceDefinition in the document, and then copy that InstanceObject to the same place it was in the File3dm. Of course, if blocks are nested (as in the original question) they should end up exactly like that in the document as well…

I am trying to first recreate all the InstanceDefinitions from File3dm in the document, and in that case, the nesting should (theoretically) not be a problem…I am currently “stuck” on copying the object from the File3dm to the document as a block instance…only the geometry from within the block gets copied…even after me recreating the InstanceDefinitions, the block instance from File3dm (from file.Objects) comes as geometry.

Here is what I realized so far: if I have a 3dm file with three boxes wrapped in a single Block, in the debugging process I can see that file.Objects has 4 elements. Three Extrusions (boxes) and one InstanceReferenceGeometry. That is the first problem because if objects are wrapped in a block instance I only want the instance. Second…if I try to limit the import to only the InstanceReferenceGeometry, even after I recreate the same InstanceDefinition with the same name, nothing gets drawn…there is no Geometry associated with the InstanceReferenceGeometry. That is the step I am missing.

Greetings,
Milos