.NET

Reply
Active Contributor
matt.worland
Posts: 34
Registered: ‎11-13-2006
Message 1 of 7 (486 Views)
Accepted Solution

Test for duplicate handles

486 Views, 6 Replies
12-03-2013 05:09 PM

How would I test for duplicate handles in a file. If I select a cirlce from an xref and it has a handle of "E6" Then I select another circle from a different xref that has the same handle. When I use GetObjectId how do I specify which handle? Is there a way to give a handle and a file path and have it point to the correct entity or would I need to cycle through all entities and check for matching handle and file name?

 

In the end I would like to select an object, then store that data in a file and then recall that exact same object later.

 

Thanks,

matt

matt worland
*Expert Elite*
_gile
Posts: 2,077
Registered: ‎04-29-2006
Message 2 of 7 (460 Views)

Re : Test for duplicate handles

12-03-2013 10:00 PM in reply to: matt.worland

Hi,

 

The GetObjectId (or TryGetObjectId) method searches an ObjectId in the Database instance the method applies to.

If you want to search in a xref, you have to call GetObjectId (or TryGetObjectId) on the xref Database:

- create a new Database instance,

- call Database ReadDwgFile() on this new instance with the xref filename

- call GetObjectId (or TryGetObjectId) on this instance.

Gilles Chanteau
Active Contributor
matt.worland
Posts: 34
Registered: ‎11-13-2006
Message 3 of 7 (361 Views)

Re : Test for duplicate handles

12-13-2013 10:20 AM in reply to: _gile
Thank you for the quick response. I apologize for my slow response. Im trying to get back in a rhythm after attending AU. Now that I think through this a bit more, is there a way to store just the object handle and parent handle? Then with the parent handle, find the path to use with GetObjectID.

Thank you again for your time.
matt
matt worland
ADN Support Specialist
Balaji_Ram
Posts: 666
Registered: ‎03-21-2011
Message 4 of 7 (322 Views)

Re : Test for duplicate handles

12-16-2013 11:13 PM in reply to: matt.worland

Hi Matt,

 

Nested entity selection works very similar to what you have described. To uniquely identify the entity the container handles are also provided. Please try this code to know the container handles during nested entity selection. I think this can provide some clues on what handles to store in your application.

 

private static List<ObjectId> _objIds = new List<ObjectId>();
private static Point3d _pickedPt = Point3d.Origin;

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

    _objIds.Clear();
    ObjectId selId = ObjectId.Null;

    PromptNestedEntityOptions pneo = new PromptNestedEntityOptions("\nSelect nested entity: ");
    PromptNestedEntityResult pner = ed.GetNestedEntity(pneo);
    if (pner.Status == PromptStatus.OK)
    {
        selId = pner.ObjectId;
        ed.WriteMessage(String.Format("{0}Selected Handle {1}", Environment.NewLine, selId.Handle.ToString()));

        _pickedPt = pner.PickedPoint;

        FullSubentityPath path = FullSubentityPath.Null;
                
        _objIds = new List<ObjectId>(pner.GetContainers());
        int i = 0;
        foreach (ObjectId id in _objIds)
        {
            ed.WriteMessage(String.Format("{0}Container[{1}] Handle {2}", Environment.NewLine, i, id.Handle.ToString()));
            i++;
        }

        _objIds.Reverse();
        _objIds.Add(selId);
    }
}

 For an entity in Xref, one of the container handle is that of a BlockReference. The BlockTableRecord of the BlockReference can provide access to the external database through the "GetXrefDatabase".

 

Regards,

Balaji



Balaji
Developer Technical Services
Autodesk Developer Network

Active Contributor
matt.worland
Posts: 34
Registered: ‎11-13-2006
Message 5 of 7 (301 Views)

Re : Test for duplicate handles

12-18-2013 10:41 AM in reply to: Balaji_Ram

Thank you for your patience and help. Im trying to figure out .NET coming from a lisp world.


So I can store the handle of the object and the handle of the container so I know the object and where the object is coming from. I think I am understanding that part now.

 

The next part I think I am understanding, but Im not sure of the most efficient way to go about it.

 

If I store those handles, I will need to convert them to an ObjectID.?.

 

The only way I see to do that is using GetObjectID (thank you _gile). To use that I need to know which database to look in. (Is my assumption correct that each xref in the drawing is a separate database?)

 

Now if all I have is the handle, how do I know which xref database to look in, so I can use GetObjectId?

 

Thank you again for your patience and time, Its much appreciated.

 

matt

matt worland
ADN Support Specialist
Balaji_Ram
Posts: 666
Registered: ‎03-21-2011
Message 6 of 7 (252 Views)

Re: Test for duplicate handles

12-22-2013 08:32 AM in reply to: matt.worland

Hi Matt,

 

Sorry for the delay.

 

Your understanding that each xref in the drawing is a separate database is right. But it is also important to note that each Xref that you see in the host drawing is a block reference. The BlockTableRecord of the BlockReference provides access to that external database.

 

The sample code that I posted earlier will displays the container ids. For an entity in Xref, one of the container handle is that of a BlockReference.

 

The BlockTableRecord of the BlockReference can provide access to the external database. For this you will need the "BlockTableRecord.GetXrefDatabase" method.

 

After you have the Xref database, you may open it for accessing its entities or use it to get the object id.

 

The ArxDbg snoop tool can help you understand the structure. I have attached a screenshot. In this the ArxDbg snoop displays a drawing (2.dwg) which has an external reference to 1.dwg. The drawing 1.dwg has a block named "Test".

 

So, the Xref appear in the host drawing (2.dwg) as a BlockTableRecord and is can be identified as an Xref.

 

Regards,

Balaji

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Active Contributor
matt.worland
Posts: 34
Registered: ‎11-13-2006
Message 7 of 7 (210 Views)

Re: Test for duplicate handles

01-06-2014 09:09 AM in reply to: Balaji_Ram

Thank you Baliji and Giles, I think I am understanding this a bit better. I believe I have a working example.

 

Much of this code was found on the net and compiled into what is seen below. Is there anything in this that could have been done more efficient or any fatal flaws?

 

 <CommandMethod("GrabPreviousEnt")> _
    Public Sub GrabPreviousEnt()
        Dim myDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim myDb As Database = myDoc.Database
        Dim myEd As Editor = myDoc.Editor
        Using myTr As Transaction = myDb.TransactionManager.StartTransaction
            Dim mycwPEO As New PromptNestedEntityOptions("Select to annotate:")
            Dim mycwPER As PromptNestedEntityResult = myEd.GetNestedEntity(mycwPEO)
            Select Case mycwPER.Status
                Case Autodesk.AutoCAD.EditorInput.PromptStatus.OK
                    Dim myEnt2 As Entity = mycwPER.ObjectId.GetObject(OpenMode.ForRead)
                    Dim myHandle As String = myEnt2.Handle.ToString
                    'find out xref handle/modelspace handle
                    Dim myOwnerHandle As String = ""
                    Dim mycontainer() As ObjectId = mycwPER.GetContainers
                    If mycontainer.Length > 0 Then
                        Dim objid As ObjectId = mycontainer.First
                        Dim acBlkRef As BlockReference = myTr.GetObject(objid, OpenMode.ForRead)
                        Dim bl As BlockTableRecord = myTr.GetObject(acBlkRef.BlockTableRecord, OpenMode.ForRead)
                        myOwnerHandle = bl.Handle.ToString
                    Else
                        myOwnerHandle = myEnt2.OwnerId.Handle.ToString
                    End If

                    Dim SelectedEnt As ObjectId = HandleToOID(myDb, myHandle, myOwnerHandle)

                    '3:
                    'Dim SelectedEnt As ObjectId = HandleToOID(myDb, "A1", "1236")
                    '2:
                    'Dim SelectedEnt As ObjectId = HandleToOID(myDb, "D3", "1233")
                    '1:
                    'Dim SelectedEnt As ObjectId = HandleToOID(myDb, "26D", "1DC")
                    '0:
                    'Dim SelectedEnt As ObjectId = HandleToOID(myDb, "126B", "1F")


            End Select
        End Using
    End Sub


    Public Shared Function HandleToOID(myDB As Database, myHandle As String, myOwnerHandle As String) As ObjectId
        Dim myOwnerHdllng As Long = Convert.ToInt64(myOwnerHandle, 16)
        Dim myOwnerHNDL As Handle = New Handle(myOwnerHdllng)
        Dim myHdllng As Long = Convert.ToInt64(myHandle, 16)
        Dim myHNDL As Handle = New Handle(myHdllng)
        Using Tx As Transaction = myDB.TransactionManager.StartTransaction()
            'Check if owner handle is xref or not
            Try
                Dim my_EntOid As ObjectId = myDB.GetObjectId(False, myHNDL, 0)
                MsgBox(my_EntOid.ObjectClass.Name & vbCr & my_EntOid.Handle.ToString & vbCr & my_EntOid.ToString)
            Catch myex As System.Exception
                Select Case myex.Message
                    Case "eUnknownHandle"
                        myDB.ResolveXrefs(False, False)
                        Dim xg As XrefGraph = myDB.GetHostDwgXrefGraph(True)
                        Dim my_EntOid As New ObjectId
                        Dim root As GraphNode = xg.RootNode
                        ChildrenGet(root, Tx, myHNDL, myOwnerHNDL)
                        Return my_EntOid
                    Case Else
                        MsgBox(myex.Message)
                End Select
            End Try
        End Using
    End Function

    ' Recursively grabs ObjectIDs of xrefs
    ' used by HandleToOID
    Private Shared Function ChildrenGet(i_root As GraphNode, i_Tx As Transaction, myHNDL As Handle, myOwnerHNDL As Handle) As ObjectId
        For o As Integer = 0 To i_root.NumOut - 1
            Dim child As XrefGraphNode = TryCast(i_root.Out(o), XrefGraphNode)
            If child.XrefStatus = XrefStatus.Resolved Then
                Dim bl As BlockTableRecord = TryCast(i_Tx.GetObject(child.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)
                If bl.Handle = myOwnerHNDL Then
                    'we found the parent object, now find myHandle 
                    Dim myXrefDB As Database = bl.GetXrefDatabase(False) ' check for example on what the number means
                    Using XTrans As Transaction = myXrefDB.TransactionManager.StartTransaction
                        Try
                            Dim myEntOID As ObjectId = myXrefDB.GetObjectId(False, myHNDL, 0)
                            MsgBox(myEntOID.ObjectClass.Name & vbCr & bl.Handle.ToString & vbCr & myEntOID.ToString)
                            Return myEntOID
                        Catch myex As System.Exception
                            MsgBox(myex.Message)
                        End Try
                    End Using
                    Exit For
                Else
                    ChildrenGet(child, i_Tx, myHNDL, myOwnerHNDL)
                End If
            End If
        Next
    End Function

 Thanks again,

matt

matt worland

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community