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
Solved! Go to Solution.
Solved by matt.worland. Go to Solution.
Solved by Balaji_Ram. Go to Solution.
Solved by _gile. Go to Solution.
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.
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
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
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
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
Can't find what you're looking for? Ask the community or share your knowledge.