Exploding nested blocks and getting the right transformation

Hy,

I am having troubles exploding nested blocks and getting the correct transformation to insert the parts again.
So I have this block (lets call it block A, origin = pt1) which is actually consisting of four blocks (the pink part Block B, origin pt1 and three screws block C origins pt2-pt4)

When I place this block with transormation trans1 somewhere in space, explode it and insert the parts again I never get the correct result. When I apply the trans1 again on all parts the screws are placed at pt1 of course.
When I apply the transformation of the transformation array of the explode command the screws are placed somewhere totally different in space.

Here is part of the command and the file

BMU_Test.3dm (771.4 KB)

InstanceDefinition thisBlock;
InstanceObject thisBlockInstance;
Guid thisBlockInstanceID;
RhinoObject blockElements;
ObjectAttributes attributes;
ObjectAttributes att;
Transform transArr;
Transform trans;
Plane thisPlane;
Guid thisBlockID;
InstanceObject tmpBlock;
int gr;

        thisPlane = new Plane(new Point3d(500, 900, 1000), new Point3d(1, 2, 0), new Point3d(5, 6, 2));
        trans = Transform.ChangeBasis(thisPlane, Plane.WorldXY);
        thisBlock = doc.InstanceDefinitions.Find("BMU_TEST", true);
        thisBlockInstanceID = doc.Objects.AddInstanceObject(thisBlock.Index, trans);
        thisBlockInstance = doc.Objects.Find(thisBlockInstanceID) as InstanceObject;

        thisBlockInstance.Explode(false, out blockElements, out attributes, out transArr);

        // loop through the blockelements 
        gr = doc.Groups.Add();
        for (int i = 0; i < blockElements.Length ; i++)
        {
            blockElements[i].Attributes = attributes[i];
            if (blockElements[i].ObjectType == ObjectType.InstanceReference)
            {
                tmpBlock = blockElements[i] as InstanceObject;
                att = attributes[i].Duplicate();
                att.AddToGroup(gr);
                thisBlockID = doc.Objects.AddInstanceObject(tmpBlock.InstanceDefinition.Index, transArr[i], att);
            }
        }


        // loop through the blockelements 
        gr = doc.Groups.Add();
        for (int i = 0; i < blockElements.Length; i++)
        {
            blockElements[i].Attributes = attributes[i];
            if (blockElements[i].ObjectType == ObjectType.InstanceReference)
            {
                tmpBlock = blockElements[i] as InstanceObject;
                att = attributes[i].Duplicate();
                att.AddToGroup(gr);
                thisBlockID = doc.Objects.AddInstanceObject(tmpBlock.InstanceDefinition.Index, trans, att);
            }
        }

        // loop through the blockelements 
        gr = doc.Groups.Add();
        for (int i = 0; i < blockElements.Length; i++)
        {
            blockElements[i].Attributes = attributes[i];
            if (blockElements[i].ObjectType == ObjectType.InstanceReference)
            {
                tmpBlock = blockElements[i] as InstanceObject;
                att = attributes[i].Duplicate();
                att.AddToGroup(gr);
                thisBlockID = doc.Objects.AddInstanceObject(tmpBlock.InstanceDefinition.Index, Transform.Multiply(trans, transArr[i]), att);
            }
        }

        RhinoDoc.ActiveDoc.Objects.Lock(thisBlockInstance, true);

Hi Dominik,

See of this sample is helpful.

https://github.com/dalefugier/SampleCsCommands/blob/master/SampleCsExplodeBlock.cs

– Dale

Hy Dale,

thanks for your reply but unfortunately this is not what I am looking for. This command explodes all nested blocks into breps in the end. I would need more like : Explode first block containing two blocks and some breps.
Take these two blocks - each again containing several other blocks - explode them and place these blocks as blocks and breps… But then somehow the xform gets confused
I just did a small change to your Explode Block Helper function which I thought might work but it did not:

protected bool ExplodeBlockHelper(RhinoDoc doc, InstanceObject iref, Transform xf)
{

        RhinoObject [] objArr;
        Boolean hasNestedBlock;
        if (null == iref)
            return false;

        var idef = iref.InstanceDefinition;
        if (null == idef)
            return false;

        var xform = xf * iref.InstanceXform;
        var do_xform = (xform.IsValid && !xform.Equals(Transform.Identity));

        var atts = iref.Attributes.Duplicate();
        atts.ObjectId = Guid.Empty;

        var objects = idef.GetObjects();
        foreach (var obj in objects)
        {
            if (null == obj)
                continue;

            var iref_obj = obj as InstanceObject;
            if (null != iref_obj)
            {
                // Explode any nested instances...
                //ExplodeBlockHelper(doc, iref_obj, xform);
                objArr = iref_obj.GetSubObjects();
                hasNestedBlock = false;
                for (int i = 0; i < objArr.Length ;i++ )
                {
                    var iref_obj2 = objArr[i] as InstanceObject;
                    if (null != iref_obj2)
                    {
                        hasNestedBlock = true;
                    }
                }
                if(hasNestedBlock )
                {
                    ExplodeBlockHelper(doc, iref_obj, xform);
                }
                else
                {
                    doc.Objects.AddInstanceObject(iref_obj.InstanceDefinition.Index, xform);
                }
                    
                continue;
            }

            var geom = obj.DuplicateGeometry();
            if (do_xform)
            {
                // Check for non-uniform scaling
                if (TransformSimilarityType.NotSimilarity == xform.SimilarityType)
                {
                    if (!geom.MakeDeformable() && geom.ObjectType == ObjectType.Curve)
                    {
                        var crv = geom as Curve;
                        if (null != crv)
                            geom = crv.ToNurbsCurve();
                    }

                }

                if (!geom.Transform(xform))
                    continue;

                if (TransformSimilarityType.OrientationReversing == xform.SimilarityType)
                {
                    if (geom.ObjectType == ObjectType.Brep)
                    {
                        var brep = geom as Brep;
                        if (null != brep)
                            brep.Flip();
                    }
                    else if (geom.ObjectType == ObjectType.Mesh)
                    {
                        var mesh = geom as Mesh;
                        if (null != mesh)
                            mesh.Flip(true, true, true);
                    }
                }
            }

            doc.Objects.Add(geom, atts);
        }

        return true;
    }