Transform point coordinates

Transform point coordinates

BestFriendCZ
Advocate Advocate
4,284 Views
19 Replies
Message 1 of 20

Transform point coordinates

BestFriendCZ
Advocate
Advocate

Hi

Could somebody help me with the transformation of points? I have point of nested block which have totally different coordinates like in UI. I have some confusion about it. i tested some type of transformation but without success. Thanks for any help 🙂

 

my code

 [CommandMethod("Test", CommandFlags.Session)]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                db.ResolveXrefs(true, false);
                BlockTableRecord mspace =(BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                string blkName = "CP DIGGING HOLE_3";
                if (bt.Has(blkName))
                {
                    BlockTableRecord btr =(BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                    }
                }
                tr.Commit();
            }
        }

Pic 1Pic 1

Pic2Pic2

...
0 Likes
Accepted solutions (1)
4,285 Views
19 Replies
Replies (19)
Message 2 of 20

BestFriendCZ
Advocate
Advocate

Little progress BlockTableRecord does not contains my blocks without explode parent block. Doesn't matter of using COM API or .NET. API. Hmmm this is bad ... It look like there is no possible get coordinates of nested  block without explode parent block... Or am i wrong? 😊

...
0 Likes
Message 3 of 20

_gile
Consultant
Consultant
Accepted solution

Hi,

 

If the block references you're looking for positions are first level nested, you can use tne blockTransform matrix of the parent block reference.

 

        [CommandMethod("Test")]
        public static void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                db.ResolveXrefs(true, false);
                var mspace = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                string blkName = "bloc"; //string blkName = "CP DIGGING HOLE_3";
                if (bt.Has(blkName))
                {
                    var btr = (BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        var owner = (BlockTableRecord)tr.GetObject(br.OwnerId, OpenMode.ForRead);
                        // if the owner is a layout (i.e., the block reference is not nested)
                        if (owner.IsLayout)
                        {
                            ed.WriteMessage("\nPosition: {0}", br.Position);
                        }
                        // else, the owner is a block definition (i.e., the block reference is nested)
                        else
                        {
                            foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                            {
                                var parent = (BlockReference)tr.GetObject(parentId, OpenMode.ForRead);
                                ed.WriteMessage("\nPosition: {0}", br.Position.TransformBy(parent.BlockTransform));
                            }
                        }
                    }
                }
                tr.Commit();
            }
        }

If the refernces may be deeper nested, you have to do this recursively.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 20

BestFriendCZ
Advocate
Advocate

Hi Gile,

thanks for information. I will try make it recursively because my block is on 3.level . BTW: I still learn AutoCAD API and in past i used many your code examples on this forum. Really good job ... newcomers will appreciate it 😊

...
0 Likes
Message 5 of 20

BestFriendCZ
Advocate
Advocate

it's working:) thank for teach me something new

...
0 Likes
Message 6 of 20

kerry_w_brown
Advisor
Advisor

josef,

because you are new to the API and keeping in mind people looking for this solution in the future, it would be a good idea for you to post your solution.

 

Regards,

 

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 7 of 20

BestFriendCZ
Advocate
Advocate

Hi Kdub,

i just only modified sample code for my purpose. Here is current test code

[CommandMethod("GetBlockPosition", CommandFlags.Session)]
        public void GetBlockPosition()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            try
            {
                using (var tr = db.TransactionManager.StartTransaction())
                {
                    var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    string blkName = "bloc"; //string blkName = "CP DIGGING HOLE_3";
                    if (bt.Has(blkName))
                    {
                        var btr = (BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);
                        foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                        {
                            var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                            var owner = (BlockTableRecord)tr.GetObject(br.OwnerId, OpenMode.ForRead);
                            // if the owner is a layout (i.e., the block reference is not nested)
                            if (owner.IsLayout)
                            {
                                ed.WriteMessage("\nPosition: {0}", br.Position);
                            }
                            // else, the owner is a block definition (i.e., the block reference is nested)
                            else
                            {
                                foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                                {
                                    var parent = (BlockReference)tr.GetObject(parentId, OpenMode.ForRead);
                                    ed.WriteMessage("\nPosition: {0}", TransformCordinates(parent, tr, br.Position.TransformBy(parent.BlockTransform)));
                                }
                            }
                        }
                    }
                    tr.Commit();
                }
            }
            catch (Exception e)
            {
                ed.WriteMessage($" Critical error: { e.Message} ");
                return;
            }       
        }
        private Point3d TransformRecursively(BlockReference btr, Transaction tr, Point3d nestedPoint)
        {
            try
            {
                var owner = (BlockTableRecord)tr.GetObject(btr.OwnerId, OpenMode.ForRead);
                BlockReference parent =null;
                foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                {
                    parent = (BlockReference)tr.GetObject(parentId, OpenMode.ForRead);
                    nestedPoint = nestedPoint.TransformBy(parent.BlockTransform);
                    break;
                }
                if (parent != null)
                    TransformRecursively(parent, tr, nestedPoint);
                return nestedPoint;
            }
            catch 
            {
                return new Point3d();
            }          
        }

 

 

...
0 Likes
Message 8 of 20

BestFriendCZ
Advocate
Advocate

Do you think it will be possible ... write something similar without COM API? only using AcadBlockReference and etc..

...
0 Likes
Message 9 of 20

kerry_w_brown
Advisor
Advisor

@BestFriendCZwrote:

Do you think it will be possible ... write something similar without COM API? only using AcadBlockReference and etc..


I can't see any references to COM code in your posted example.

I can't imagine why you would want to use COM code.


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 10 of 20

BestFriendCZ
Advocate
Advocate

meaby i wrong described it.....but this code i can't use in exe application ... and this is my main problem atm...  i need modify one function in large project which is wrote using another API...code work with object like acadblockreference  and not with blockrerefence... if i will use any objects from Acdbmgd or another dll like this so exe app fire error immediately....what i wrote on forum there is no way use this dll in exe app...My plan is change this project to this API but it will takes some time ... so i try to find faster solution

...
0 Likes
Message 11 of 20

BestFriendCZ
Advocate
Advocate

i mean what i read 🙂 sry for my englisch ... if there is way how to use it i would like to know:)

...
0 Likes
Message 12 of 20

norman.yuan
Mentor
Mentor

I am not sure the other post about nested block's coordinate was also from you (using different user name alias?). After all the discussion, and you say you are doing EXE. So, yes, you are correct that AutoCAD .NET API dlls cannot be used with EXE app (at least not directly). While I am not fan of using EXE to control AutoCAD (via AutoCAD COM API), which can hardly be a good business solution in most cases, it is rather simple to do what you want (getting real location/coordinates of a nested block presenting inside a block reference) with COM API. Here is sample code in AutoCAD VBA that just does that (assume only one level of nesting for simplicity):

 

Option Explicit

Public Sub TestNestedBlock()

    Dim ent As AcadEntity
    Dim blk As AcadBlockReference
    Dim pt As Variant
    
    On Error Resume Next
    ThisDrawing.Utility.GetEntity ent, pt, vbCr & "Select a block:"
    
    If ent Is Nothing Then Exit Sub
    If TypeOf ent Is AcadBlockReference Then
        Set blk = ent
        FindNestedBlockLocations blk
    Else
        MsgBox "Selected entity is not a block!"
    End If
    
End Sub

Private Sub FindNestedBlockLocations(bref As AcadBlockReference)
    
    Dim blk As AcadBlock
    Dim ent As AcadEntity
    Dim nestedBlk As AcadBlockReference
    Dim count As Integer
    
    Set blk = ThisDrawing.Blocks(bref.Name)
    For Each ent In blk
        If TypeOf ent Is AcadBlockReference Then
            Set nestedBlk = ent
            GetNestedBlockLocation nestedBlk.InsertionPoint, bref.InsertionPoint
            count = count + 1
        End If
    Next
    
    If count = 0 Then
        MsgBox "Selected block does not have a nested block inside!"
    Else
        MsgBox count & " nested block(s) found!"
    End If

End Sub

Private Sub GetNestedBlockLocation(basePt As Variant, brefPt As Variant)

    Dim location(0 To 2) As Double

    location(0) = brefPt(0) + basePt(0)
    location(1) = brefPt(1) + basePt(1)
    location(2) = brefPt(2) + basePt(2)
    
    MsgBox "Found nested block at: " & vbCr & _
        "X=" & location(0) & vbCr & _
        "Y=" & location(1) & vbCr & _
        "Z=" & location(2)

End Sub

Well, if you go the COM API route, then it would be better to post here.

 

HTH

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 13 of 20

BestFriendCZ
Advocate
Advocate

Hi Norman,
no i write on forum only under my nick. SporadicCoder have totally different level englisch opposite me. To this problem i created only this post:

 

Transform point coordinates
Alternative COM API vs .NET API
Problem about coordinates

 

and reason was becuase i found everytime additional problem. I am not fan using EXE too and i agree with your opinion on it but if you have to modify large project (thousand and thousand line of code) which was created by someone else like exe App so it is problem.
My plan is rewrite complete project like DLL but it takes some time and i am still learn AutoCAD... Thank you for your sample i will test it and i apologize for the inaccurate description of my problem.

...
0 Likes
Message 14 of 20

BestFriendCZ
Advocate
Advocate

I tested sample code and it return the wrong coordinates ...i tryed to make recursively and after only explode parent block and select child block which contains nested block and result was wrong too.. sample code works only on first nested block in base block
I decided to rewrite this part of code to DLL and return result somehow... but now i have problem with rotation all coordinates are good
Parent block have good rotation ... first nested block have good rotation too but second nested block have rotation 0 and good is 1.5.... (90°). I would like to know what is wrong at this code?

 

 

 [CommandMethod("ScanBlocks")]
        public void ScanBlocks()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (DocumentLock acLckDoc = doc.LockDocument())//lock mother window during print
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    RXClass blockReferenceType = RXClass.GetClass(typeof(BlockReference));
                    DBDictionary layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (var lay in layouts)
                    {
                        if (lay.Key.ToLower() == "model")
                        {
                            Layout layout = (Layout)tr.GetObject(lay.Value, OpenMode.ForRead);
                            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == blockReferenceType)
                                {
                                    //get all blocks which are type BlockReference on first level in model layout
                                    BlockReference baseBlock = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                                    //loop through all blocks reference
                                    LoopNestedBlocks(tr, baseBlock,null);
                                }
                            }
                        }
                    }
                }
            }
        }
       private static void LoopNestedBlocks(Transaction trParent, BlockReference brChild, BlockReference brParent)
        {
            BlockTableRecord btr = (BlockTableRecord)trParent.GetObject(brChild.BlockTableRecord, OpenMode.ForRead);
            if (btr != null)
            {
                Point3d bockPosition;
                if (brParent != null)
                {
                    bockPosition = TransformPositionRecursively(brParent, trParent, brChild.Position.TransformBy(brParent.BlockTransform));
                }
                else { bockPosition = brChild.Position; }
                Debug.Print(brChild.Name + "  " + bockPosition.X + "  " + bockPosition.Y + "  " + bockPosition.Z + "  " + brChild.Rotation);
                foreach (ObjectId id in btr)
                {
                    Entity blockEntity = (Entity)trParent.GetObject(id, OpenMode.ForRead);

                    if (blockEntity is BlockReference)
                        LoopNestedBlocks(trParent, (BlockReference)blockEntity, brChild);
                }
            }
        }
        private static Point3d TransformPositionRecursively(BlockReference btr, Transaction trParent, Point3d nestedPoint)
        {
            try
            {
                BlockTableRecord owner = (BlockTableRecord)trParent.GetObject(btr.OwnerId, OpenMode.ForRead);
                BlockReference parent = null;
                foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                {
                    parent = (BlockReference)trParent.GetObject(parentId, OpenMode.ForRead);
                    nestedPoint = nestedPoint.TransformBy(parent.BlockTransform);            
                    break;
                }
                if (parent != null)
                    TransformPositionRecursively(parent, trParent, nestedPoint);
                return nestedPoint;
            }
            catch
            {
                return new Point3d();
            }
        }

  

...
0 Likes
Message 15 of 20

BestFriendCZ
Advocate
Advocate

ok i found another bug in sampe code up... will be long night:(. i stopped focus on my block and tryed to test function on large structure and position are wrong atleast some of them.
reason is because this row returns colection parent of blockreference and me need only one right parent blockreference for my child blockreference.

BlockTableRecord owner = (BlockTableRecord)trParent.GetObject(btr.OwnerId, OpenMode.ForRead);

...
0 Likes
Message 16 of 20

BestFriendCZ
Advocate
Advocate

i tried modify function but without success.Is there some way how to indetify parent blockreference?
because every parent block contains reference to child block with same name, ID,BlockID but in different position.
Is there a way how to find that right? BTW i use this way because i try to keep the block list as in the old application

  private static Point3d TransformPositionRecursively(BlockReference btr, Transaction trParent, Point3d nestedPoint)
        {
            try
            {
                Point3d point3D;
                BlockTableRecord owner = (BlockTableRecord)trParent.GetObject(btr.OwnerId, OpenMode.ForRead);
                BlockReference parent = null;
                foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                {
                    parent = (BlockReference)trParent.GetObject(parentId, OpenMode.ForRead);

                    BlockTableRecord btr2 = (BlockTableRecord)trParent.GetObject(parent.BlockTableRecord, OpenMode.ForRead);
                    if (btr2 != null)
                    {
                        foreach (ObjectId id in btr2)
                        {
                            Entity blockEntity = (Entity)trParent.GetObject(id, OpenMode.ForRead);
                            if (blockEntity is BlockReference)
                            {
                                BlockReference testBlocRef = (BlockReference)blockEntity;
                                if (testBlocRef.Id == btr.Id)
                                {
                                    point3D = nestedPoint.TransformBy(parent.BlockTransform);
                                    break;
                                }
                            }
                        }
                    }
                }
                if (parent != null)
                    TransformPositionRecursively(parent, trParent, nestedPoint);
                return nestedPoint;
            }
            catch ()
            {
                return new Point3d();
            }
        }
...
0 Likes
Message 17 of 20

_gile
Consultant
Consultant

Try this one:

 

        [CommandMethod("Test")]
        public static void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                db.ResolveXrefs(true, false);
                var mspace = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                string blkName = "CP DIGGING HOLE_3";
                if (bt.Has(blkName))
                {
                    var btr = (BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);
                    foreach (Point3d pt in GetNestedPositions(btr, Point3d.Origin, tr))
                    {
                        ed.WriteMessage($"\n{pt}");
                    }
                }
                tr.Commit();
            }
        }

        private static List<Point3d> GetNestedPositions(BlockTableRecord btr, Point3d position, Transaction tr)
        {
            List<Point3d> positions = new List<Point3d>();
            foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
            {
                var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                var owner = (BlockTableRecord)tr.GetObject(br.OwnerId, OpenMode.ForRead);
                if (owner.IsLayout)
                {
                    positions.Add(position.TransformBy(br.BlockTransform));
                }
                else
                {
                    positions.AddRange(GetNestedPositions(owner, position.TransformBy(br.BlockTransform), tr));
                }
            }
            return positions;
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 18 of 20

BestFriendCZ
Advocate
Advocate

Hi Gile,

thank you for your sample but i know about this but this is not exactly what i need. I try to explain on the picture.  I have DWG which contains many block like CP130100-07 and these blocks contains for example nested block CP DIGGING HOLE_1. Function returns list of block CP DIGGING HOLE_1 with corect coordination but how can i identify right parent block reference for populate list of block like is on picture. This list contains complete list of block with specific order.

 

pic3.png

 

 

this list is result similar functions as this

    [CommandMethod("ScanBlocks")]
        public void ScanBlocks()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (DocumentLock acLckDoc = doc.LockDocument())//lock mother window during print
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    RXClass blockReferenceType = RXClass.GetClass(typeof(BlockReference));
                    DBDictionary layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (var lay in layouts)
                    {
                        if (lay.Key.ToLower() == "model")
                        {
                            Layout layout = (Layout)tr.GetObject(lay.Value, OpenMode.ForRead);
                            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == blockReferenceType)
                                {
                                    BlockReference baseBlock = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                                    LoopNestedBlocks( tr, baseBlock);
                                }
                            }
                        }
                    }
                }
            }
        }
        private static void LoopNestedBlocks(Transaction trParent, BlockReference brCurrent)
        {
            BlockTableRecord btr = (BlockTableRecord)trParent.GetObject(brCurrent.BlockTableRecord, OpenMode.ForRead);
            if (btr != null)
            {
                Debug.Print(brCurrent.Name);
                foreach (ObjectId id in btr)
                {
                    Entity childEntity = (Entity)trParent.GetObject(id, OpenMode.ForRead);
                    if (childEntity is BlockReference)
                        LoopNestedBlocks(trParent, (BlockReference)childEntity);
                }
            }
        }
...
0 Likes
Message 19 of 20

BestFriendCZ
Advocate
Advocate

i tried use another way transform coordinates from parent to child but nested coordinate are wrong and from child to parent i don't know have how identify parent reference for my sample. I'm getting a little desperate 🙂

 

 [CommandMethod("ScanBlocks")]
        public void ScanBlocks()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (DocumentLock acLckDoc = doc.LockDocument())//lock mother window during print
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    RXClass blockReferenceType = RXClass.GetClass(typeof(BlockReference));
                    DBDictionary layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (var lay in layouts)
                    {
                        if (lay.Key.ToLower() == "model")
                        {
                            Layout layout = (Layout)tr.GetObject(lay.Value, OpenMode.ForRead);
                            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == blockReferenceType)
                                {
                                    BlockReference baseBlock = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                                    List<DrawingElement> test = new List<DrawingElement>();
                                    LoopNestedBlocks(test, tr, baseBlock, new PointTransformed());

                                    foreach (DrawingElement item in test)
                                    {
                                        //roration is 0 in second level nested block?
                                        Debug.Print(item.BlocName + " " + item.Cordinate.Position.X + " " + item.Cordinate.Position.Y + " " + item.Cordinate.Position.Z + " " + item.Cordinate.Rotation);
                                    }


                                }
                            }
                        }
                    }
                }
            }
        }
        class DrawingElement
        {
            public string BlocName { get; set; }
            public PointTransformed Cordinate { get; set; }
        }
        class PointTransformed
        {
            public Point3d Position { get; set; }
            public Boolean IsNull { get; set; } = true;
            public double Rotation { get; set; }
        }
        private static List<DrawingElement> LoopNestedBlocks(List<DrawingElement> currentList, Transaction trParent, BlockReference brCurrent, PointTransformed pointParent)
        {
            BlockTableRecord btr = (BlockTableRecord)trParent.GetObject(brCurrent.BlockTableRecord, OpenMode.ForRead);
            if (btr != null)
            {
                PointTransformed pointCurrent;
                if (!pointParent.IsNull)
                {
                    pointCurrent = new PointTransformed()
                    {
                        Position = pointParent.Position.TransformBy(brCurrent.BlockTransform),
                        IsNull = false
                    };
                }
                else
                {
                    pointCurrent = pointCurrent = new PointTransformed()
                    {
                        Position = brCurrent.Position,
                        IsNull = false
                    };
                }
                DrawingElement currentElement = new DrawingElement();
                currentElement.Cordinate = pointCurrent;
                currentElement.BlocName = brCurrent.Name;
                currentElement.Cordinate.Rotation = brCurrent.Rotation;
                currentList.Add(currentElement);

                foreach (ObjectId id in btr)
                {
                    Entity childEntity = (Entity)trParent.GetObject(id, OpenMode.ForRead);
                    if (childEntity is BlockReference)
                        LoopNestedBlocks(currentList, trParent, (BlockReference)childEntity, pointCurrent);
                }
            }
            return currentList;
        }
...
0 Likes
Message 20 of 20

BestFriendCZ
Advocate
Advocate

Looks like it works ... i checked on few DWG and it works correct...last problem are rotations. Does anybody know how to get rotation from nested block? because blockreference rotation doesn't have property TransformBy

 

 [CommandMethod("ScanBlocks")]
        public void ScanBlocks()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (DocumentLock acLckDoc = doc.LockDocument())//lock mother window
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    RXClass blockReferenceType = RXClass.GetClass(typeof(BlockReference));
                    DBDictionary layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (var lay in layouts)
                    {
                        if (lay.Key.ToLower() == "model")
                        {
                            Layout layout = (Layout)tr.GetObject(lay.Value, OpenMode.ForRead);
                            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == blockReferenceType)
                                {
                                    BlockReference baseBlock = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                                    List<DrawingElement> test = new List<DrawingElement>();
                                    List<BlockReference> parentReferenceList = new List<BlockReference>();
                                    int level = 0;
                                    LoopNestedBlocks(test, tr, baseBlock, parentReferenceList, ref level);
                                    if (baseBlock.Name == "BaseBlock") /*A$C70C23CFC*/
                                    {
                                        foreach (DrawingElement item in test)
                                        {
                                            Debug.Print(item.BlocName + " " + item.Cordinate.Position.X + " " + item.Cordinate.Position.Y + " " + item.Cordinate.Position.Z);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        class DrawingElement
        {
            public string BlocName { get; set; }
            public PointTransformed Cordinate { get; set; }
        }
        class PointTransformed
        {
            public Point3d Position { get; set; }
            public Boolean IsNull { get; set; } = true;
            public double Rotation { get; set; }
        }

        private static void LoopNestedBlocks(List<DrawingElement> currentList, Transaction trParent, BlockReference brCurrent, List<BlockReference> parentReferenceList, ref int parentLevel)
        {
            try
            {
                BlockTableRecord btr = (BlockTableRecord)trParent.GetObject(brCurrent.BlockTableRecord, OpenMode.ForRead);
                if (btr != null)
                {
                    List<DrawingElement> subList = new List<DrawingElement>();
                    int currentBlockLevel = 0;
                    GetCurrentLevel(brCurrent, trParent, ref currentBlockLevel, parentReferenceList);
                    if (currentBlockLevel != parentReferenceList.Count)
                        parentReferenceList.RemoveRange(currentBlockLevel, parentReferenceList.Count - currentBlockLevel);
                    Point3d currentBlockPosition = brCurrent.Position;
                    for (int i = parentReferenceList.Count; i > 0; i--)
                    {
                        BlockReference parentBlockRef = parentReferenceList[i - 1];
                        currentBlockPosition = currentBlockPosition.TransformBy(parentBlockRef.BlockTransform);
                    }
                    PointTransformed pointCurrent;
                    pointCurrent = new PointTransformed()
                    {
                        Position = currentBlockPosition,
                        IsNull = false
                    };
                    DrawingElement currentElement = new DrawingElement()
                    {
                        Cordinate = pointCurrent,
                        BlocName = brCurrent.Name
                    };
                    currentList.Add(currentElement);
                    parentReferenceList.Add(brCurrent);
                    parentLevel = currentBlockLevel;
                    foreach (ObjectId id in btr)
                    {
                        Entity childEntity = (Entity)trParent.GetObject(id, OpenMode.ForRead);
                        if (childEntity is BlockReference)
                            LoopNestedBlocks(currentList, trParent, (BlockReference)childEntity, parentReferenceList, ref parentLevel);
                    }
                }
            }
            catch { }
        }
        private static void GetCurrentLevel(BlockReference btr, Transaction trParent, ref int currentLevel, List<BlockReference> parentReferenceList)
        {
            try
            {
                BlockReference parent = null;
                BlockTableRecord owner = (BlockTableRecord)trParent.GetObject(btr.OwnerId, OpenMode.ForRead);
                foreach (ObjectId parentId in owner.GetBlockReferenceIds(true, false))
                {
                    parent = (BlockReference)trParent.GetObject(parentId, OpenMode.ForRead);
                    if (parentReferenceList.Contains(parent))
                    {
                        break;
                    }
                }
                if (parent != null)
                {
                    currentLevel++;
                    GetCurrentLevel(parent, trParent, ref currentLevel, parentReferenceList);
                }
            }
            catch { }
        }
...
0 Likes