From RhinoObject to Instance Object container

Hello,

How, having a RhinoObject, can I know the InstanceObject that contains it ?
(I’m in the BlockEdit command)

jmv

Hello,

I know my question is very short, but I don’t see how to have a more complex question.
maybe clearer.

The user modifies a block.
How to know the InstanceObject of this selected Mesh?

Outside the Block Edit command, it is easy to iterate the descending hierarchy.
(But the Block Edit command changes all sub-objects, like IDs of the objects displayed in the viewport.)
In this case, I have to traverse the ascending hierarchy.
(I suppose)
but I don’t see how to do this with the Rhino API. I also searched in the managed code of “BlockEdit.rhp”, without success.


For 2 days I have solved many needs with “bad” alternatives.
But currently I need to know the complete transformation of an object.
Inside the previous image, it would look like this:

completeTransform = blockA.InstanceXForm * blockB.InstanceXForm;

I am trying to contribute to the RhineBridge project, I hope you can help me.

jmv

The selected mesh, shown by BlockEdit is part of an instance definition, not an instance object.

Or am I confused what you are asking?

– Dale

Hello @dale.

Well actually, neither of the two.

The BlockEdit command duplicates block objects.
What we select in the viewport is the duplicate RhinoObject.
BlockEdit UI explode the block and toggle “locked” attribute copies.
BlockEdit doesn’t have a public API so I only have a RhinoObject as a starting point.

Yes, of couse.

What is it, exactly, what you want to do and why?

– Dale

Hello @dale

Here’s what happens.
I have a block with a Brep and 4 sub-blocks.
The master block and the sub-blocks have a origin at 0,0,0.
The master block is translated relative to the origin of the scene.
Sub-blocks are translated/rotated inside the master block.
When I edit a block to dynamically change the mesh.
The process regenerates the mesh and I need to know the full transformation matrix to reposition the new geometry in the correct place.

It’s not clear ?

I’m surprised I’m the only one who tried to override the geometry while running the BlockEdit command.
I am all the more surprised that after 6 days, I have had no useful response.
Not even an “I don’t know” or “not possible”.
Don’t waste your time with this subject, I manage.
Thanks me.

static List <RO.InstanceObject> GetInstanceHierarchy (RH.RhinoDoc doc)
{
    var instances = new List <RO.InstanceObject> ();

    // var editor = BlockEdit.Editor.TryGet (doc);

    var ass = typeof (BlockEdit.BlockEditPlugIn).Assembly;
    var Editor_t = ass.GetType ("BlockEdit.Editor", throwOnError: false, ignoreCase: false);
    if (Editor_t == null) return instances;

    var TryGet_t = Editor_t.GetMethod ("TryGet", new Type[] { typeof (RH.RhinoDoc) });
    if (TryGet_t == null) return instances;
    var editor = TryGet_t.Invoke (null, new object[] { doc });
    if (editor == null) return instances;

    // var collection = editor.Collection

    var Collection_t = Editor_t.GetProperty ("Collection");
    if (Collection_t == null) return instances;
    var collection = Collection_t.GetValue (editor);
    if (collection == null) return instances;

    // var rootItem = collection.RootItem;

    var RootItem_t = Collection_t.PropertyType.GetProperty ("RootItem");
    if (RootItem_t == null) return instances;
    var rootItem = RootItem_t.GetValue (collection);
    if (rootItem == null) return instances;

    // var editItem = collection.EditItem;

    var EditItem_t = Collection_t.PropertyType.GetProperty ("EditItem");
    if (EditItem_t == null) return instances;
    var editItem = EditItem_t.GetValue (collection);
    if (editItem == null) return instances;

    // rootId = rootItem.ReferenceId
    // editId = editItem.ReferenceId

    var ReferenceId_t = EditItem_t.PropertyType.GetProperty ("ReferenceId");
    if (ReferenceId_t == null) return instances;
    var root = ReferenceId_t.GetValue (rootItem);
    if (root is not Guid rootId || rootId == Guid.Empty) return instances;
    var edit = ReferenceId_t.GetValue (editItem);
    if (edit is not Guid editId || editId == Guid.Empty) return instances;

    if (doc.Objects.FindId (rootId) is not RO.InstanceObject rootObj ||
        doc.Objects.FindId (editId) is not RO.InstanceObject editObj
    ) return instances;

    //

    if (rootId == editId) {
        instances.Add (rootObj);
        return instances;
    }

    if (_Compute (rootObj, editObj, instances)) {
        instances.Reverse ();
        instances.Insert (0, rootObj);
        instances.Add (editObj);
    } else { 
        instances.Clear ();
    }

    var indent = "  ";
    foreach (var inst in instances)
    {
        RH.RhinoApp.WriteLine (indent + inst.InstanceDefinition.Name);
        indent += "  ";
    }

    return instances;

    static bool _Compute (RO.InstanceObject block, RO.InstanceObject target, List <RO.InstanceObject> instances)
    {
        foreach (var o in block.InstanceDefinition.GetObjects ())
        {
            if (o is RO.InstanceObject subBlock)
            {
                if (subBlock.Id == target.Id) return true;
                if (_Compute (subBlock, target, instances))
                {
                    instances.Add (subBlock);
                    return true;
                }
            }
        }
        return false;
    }
}