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

Test for duplicate handles

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
matt.worland
1801 Views, 6 Replies

Test for duplicate handles

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

If my reply was helpful, please give a "Thumbs Up" or "Accept as Solution"
6 REPLIES 6
Message 2 of 7
_gile
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
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 7
matt.worland
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
If my reply was helpful, please give a "Thumbs Up" or "Accept as Solution"
Message 4 of 7
Balaji_Ram
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

Message 5 of 7
matt.worland
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

If my reply was helpful, please give a "Thumbs Up" or "Accept as Solution"
Message 6 of 7
Balaji_Ram
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

Message 7 of 7
matt.worland
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

If my reply was helpful, please give a "Thumbs Up" or "Accept as Solution"

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