.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Nested Blocks From Selected Subentity

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
christopher
4064 Views, 5 Replies

Nested Blocks From Selected Subentity

I'm attempting to have the user select mText from a nested block within a block and then copy the nested block to model space out of the block. I'm able to change the mText successfully, but when I attempt to get the nested block it is not in the list of GetContainers() it only contains the block in model space and the model space block. The nested block is missing in the list. I'm using AutoCAD Civil 3D 2013. 

 

Here is the code to select the mText object which works correctly.

 

Sub GetNestedMtext()
        ' Have the user select an object. Using the prompt provided.
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
        Dim entopts As New PromptNestedEntityOptions(Environment.NewLine & "Select a mText in block to replace: ")
        entopts.Message = Environment.NewLine & "Select a mText in block to replace: "

        Dim ent As PromptNestedEntityResult = Nothing

        Try
            ent = ed.GetNestedEntity(entopts)
        Catch
            ed.WriteMessage("You did not select a valid entity")

        End Try

        If ent.Status = PromptStatus.OK Then
                CreateDuplicateBlockInModelSpace(ent)
        End If
    End Sub

 

 

Here is the code that attempts to get the nested block which is missing the nested block.

 

    Private Shared Sub CreateDuplicateBlockInModelSpace(ByVal ent As PromptNestedEntityResult)
        Try
            Dim containerObjIds As ObjectId() = ent.GetContainers()
            Dim blkToExtract As BlockReference = DirectCast(containerObjIds(1).GetObject(OpenMode.ForRead), BlockReference)
            Dim blkToPlace As BlockReference = blkToExtract.Clone()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Using tr As Transaction = db.TransactionManager.StartTransaction
                Dim acBlkTbl As BlockTable
                acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim acBlkTblRec As BlockTableRecord
                acBlkTblRec = tr.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                acBlkTblRec.AppendEntity(blkToPlace)
                tr.AddNewlyCreatedDBObject(blkToPlace, True)
                tr.Commit()
            End Using
        Catch ex As System.Exception

        End Try

    End Sub

 Is there another way I can get the parent block object for the nested object? 

5 REPLIES 5
Message 2 of 6
_gile
in reply to: christopher

Hi,

 

The ObjectId array returned by GetContainers() method is 0 based.

 

So, if the selected mtext owns to block 'A' which is nested in block 'B' inserted in model space, GetContainers()(0) returns 'A', GetContainers()(1) returns 'B' and GetContainers()(2) returns the model space ObjectId.

 

In your code, you get the ObjectId at the 1 index (the second item in the array).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 6
christopher
in reply to: _gile

Yes, that is my expectation of how it supposed to work also. Unfortunately when I run the code I only get two objects back in the collection, it's missing the 0 value we are expecting and insteads returns the block the block is inside of and model space. The nested, nested block is missing. 

 

Here is a video showing my experience with it. The block in blue is the nested block with the blue mtext the item the user needs to select. I then want the blue block's ObjectId to copy it from the block into model space so the user can move it and use it elsewhere in the drawing. The red is the block that holds the blue block.

http://screencast.com/t/UJGlQ0OmbOqt

 

I'd prefer the user only clicks once and not have to fake a click for the user, which if it is a bug that I'll have to do.

 

Could it be a version related bug?

Message 4 of 6
_gile
in reply to: christopher

Try this snippet (it works for me).

 

C#

[CommandMethod("Test")]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptNestedEntityResult res = ed.GetNestedEntity("\nSelect a nested entity: ");
            if (res.Status != PromptStatus.OK)
                return;

            ObjectId[] ctnIds = res.GetContainers();
            if (ctnIds.Length == 0)
                return;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockReference br = (BlockReference)tr.GetObject(ctnIds[0], OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                BlockReference clone = (BlockReference)br.Clone();
                ObjectId id = btr.AppendEntity(clone);
                tr.AddNewlyCreatedDBObject(clone, true);
                clone.TransformBy(res.Transform * br.BlockTransform.Inverse());
                ed.SetImpliedSelection(new ObjectId[1] { id });
                tr.Commit();
            }
        }

 

F#

[<CommandMethod("Test")>]
let test () =
    let doc = Application.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor

    let res = ed.GetNestedEntity("\nSelect a nested entity: ")
    if res.Status = PromptStatus.OK then
        let ctnIds = res.GetContainers()
        if ctnIds.Length > 0 then
            use tr = db.TransactionManager.StartTransaction()
            let br = tr.GetObject(ctnIds.[0], OpenMode.ForRead) :?> BlockReference
            let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
            let clone = br.Clone() :?> BlockReference
            let id = btr.AppendEntity(clone)
            tr.AddNewlyCreatedDBObject(clone, true)
            clone.TransformBy(res.Transform * br.BlockTransform.Inverse())
            ed.SetImpliedSelection([| id |])
            tr.Commit()

 

VB

        <CommandMethod("Test")> _
        Public Sub Test()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim res As PromptNestedEntityResult = ed.GetNestedEntity("Select a nested entity: ")
            If res.Status <> PromptStatus.OK Then
                Return
            End If

            Dim ctnIds() As ObjectId = res.GetContainers()
            If ctnIds.Length = 0 Then
                Return
            End If

            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim br As BlockReference = DirectCast(tr.GetObject(ctnIds(0), OpenMode.ForRead), BlockReference)
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
                Dim clone As BlockReference = DirectCast(br.Clone(), BlockReference)
                Dim id As ObjectId = btr.AppendEntity(clone)
                tr.AddNewlyCreatedDBObject(clone, True)
                clone.TransformBy(res.Transform * br.BlockTransform.Inverse())
                ed.SetImpliedSelection(New ObjectId(0) {id})
                tr.Commit()
            End Using

        End Sub


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 6
philippe.leefsma
in reply to: _gile

Hi,

 

You can retrieve the nested block the selected entity belongs to using Entity.BlockName and Entity.BlockId properties.

 

In the attached drawing I have MText inside "Nested" block, which is nested inside topblk. Here is the output of the following code:

 

Select nested entity:
Container: topblk
Container: *Model_Space
Entity: Autodesk.AutoCAD.DatabaseServices.MText
Block: nested

 

[CommandMethod("NestEntSelect")]
public void NestEntSelect()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;

    PromptNestedEntityOptions pneo = new PromptNestedEntityOptions(
        "\nSelect nested entity:");

    PromptNestedEntityResult pner = ed.GetNestedEntity(pneo);

    if (pner.Status != PromptStatus.OK) 
        return;

    using (Transaction Tx = doc.TransactionManager.StartTransaction())
    {
        //Containers
        ObjectId[] containerIds = pner.GetContainers();

        foreach (ObjectId id in containerIds)
        {
            DBObject container = Tx.GetObject(id, OpenMode.ForRead);

            if (container is BlockReference)
            {
                BlockReference bref = container as BlockReference;

                ed.WriteMessage("\nContainer: " + bref.BlockName);
            }
        }

        Entity entity = Tx.GetObject(pner.ObjectId, OpenMode.ForRead) 
            as Entity;

        ed.WriteMessage("\nEntity: " + entity.ToString());

        ed.WriteMessage("\nBlock: " + entity.BlockName);

        BlockTableRecord btr = Tx.GetObject(entity.BlockId, OpenMode.ForRead)
            as BlockTableRecord;

        Tx.Commit();
    }
}

Regards,

Philippe.



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

Message 6 of 6

Thank you both for the help. Same person, different accounts. 

Civil Reminders
http://blog.civil3dreminders.com/
http://www.CivilReminders.com/
Alumni

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost