Author Topic: Best way to obtain entities in an xref  (Read 1959 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 601
Best way to obtain entities in an xref
« on: June 11, 2015, 09:53:16 AM »
I have a problem where I need to select all entities in a drawing that have certain XData on them.  Normally I would do something like this:

Code - Visual Basic: [Select]
  1. Dim entities = New ObjectIdCollection()
  2. Dim typedValues As TypedValue() = {New TypedValue(DxfCode.ExtendedDataRegAppName, "AppName")}
  3. Dim selectionFilter = New SelectionFilter(typedValues)
  4. Dim result As PromptSelectionResult = Active.Editor.SelectAll(selectionFilter)
  5.  
  6. If result.Status = PromptStatus.OK Then
  7.     entities = New ObjectIdCollection(result.Value.GetObjectIds())
  8. End If

However this will not go and get any nested entities in xrefs or blocks.  What is the best way to accomplish this?  Would it be to check for a block reference and then explode the items and rinse and repeat?

Does anyone have any boilerplate code where they have accomplished this already?  It seems like something that would need to be done quite a bit.


** Edit **  I need to do this without any user interaction otherwise I would just use one of the GetNestedEntity routines.
« Last Edit: June 11, 2015, 10:21:02 AM by Keith Brown »
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Best way to obtain entities in an xref
« Reply #1 on: June 11, 2015, 01:11:54 PM »
You could use the Editor.SelectionAdded event and filter through BlockReferences for enitites that contain the XData you're looking for.
Revit 2019, AMEP 2019 64bit Win 10

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Best way to obtain entities in an xref
« Reply #2 on: June 11, 2015, 02:06:17 PM »
Here is the solution that I came up with to just get the unique objectIds of each entity in modelspace that contains the required XData.  I apologize for the VB but I am required to use it for my job.  I go home each night and scrub myself down in a hot shower just to get the stink of it off of me afterwards.  Just kidding but i do think that C# is a much more elegant language.

Code - Visual Basic: [Select]
  1. Private Function GetXDataEntities() As ObjectIdCollection
  2.  
  3.         Dim entitiesId = New ObjectIdCollection()
  4.         Dim database = Active.Database
  5.  
  6.         Try
  7.                 Using transaction = Active.Database.TransactionManager.StartTransaction()
  8.                         Dim blockTable = TryCast(transaction.GetObject(database.BlockTableId, OpenMode.ForRead), BlockTable)
  9.                         If blockTable IsNot Nothing Then
  10.                                 Dim modelspace = TryCast(transaction.GetObject(blockTable(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
  11.                                 If modelspace IsNot Nothing Then
  12.                                         EntityWalker(modelspace, entitiesId, transaction)
  13.                                 End If
  14.                         End If
  15.                 End Using
  16.  
  17.         Catch exception As System.Exception
  18.                 Log.Logger.Error(exception, "GetLineEntities: Error getting entity objectId")
  19.         End Try
  20.  
  21.         Return entitiesId
  22.  
  23. End Function
  24.  
  25. Private Sub EntityWalker(blockTableRecord As BlockTableRecord, ByRef entitiesId As ObjectIdCollection, transaction As Transaction)
  26.  
  27.         Try
  28.                 Dim rxc As RXClass = RXClass.GetClass(GetType(BlockReference))
  29.                 For Each entityId As ObjectId In blockTableRecord
  30.                         Dim entity = TryCast(transaction.GetObject(entityId, OpenMode.ForRead, False, True), Entity)
  31.                         If entity IsNot Nothing Then
  32.                                 If entityId.ObjectClass = rxc Then
  33.                                         Dim blockReference = TryCast(transaction.GetObject(entityId, OpenMode.ForRead), BlockReference)
  34.                                         If blockReference IsNot Nothing Then
  35.                                                 Dim blockTableRecord2 = TryCast(transaction.GetObject(blockReference.BlockTableRecord, OpenMode.ForRead, False, True), BlockTableRecord)
  36.                                                 If blockTableRecord2 IsNot Nothing Then
  37.                                                         EntityWalker(blockTableRecord2, entitiesId, transaction)
  38.                                                 End If
  39.                                         End If
  40.                                 Else
  41.                                         If XData.CheckXDataExists(entity, _AppName) Then
  42.                                                 If Not entitiesId.Contains(entity.ObjectId) Then
  43.                                                         entitiesId.Add(entity.ObjectId)
  44.                                                 End If
  45.                                         End If
  46.                                 End If
  47.                         End If
  48.                 Next
  49.  
  50.         Catch exception As Exception
  51.                 Log.Logger.Error(exception, "EntityWalker: Error getting entity objectId")
  52.         End Try
  53.  
  54. End Sub
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

kaefer

  • Guest
Re: Best way to obtain entities in an xref
« Reply #3 on: June 11, 2015, 03:13:13 PM »
Code - vb.net: [Select]
  1.                         Dim entity = TryCast(transaction.GetObject(entityId, OpenMode.ForRead, False, True), Entity)
  2.                         If entity IsNot Nothing Then
  3.                                 If entityId.ObjectClass = rxc Then
  4.                                         Dim blockReference = TryCast(transaction.GetObject(entityId, OpenMode.ForRead), BlockReference)
  5.                                         If blockReference IsNot Nothing Then
  6.                                                 ...
I hope that using vb.net doesn't have a detrimental influence on the program logic. Is it just me, or are you opening the same ObjectId twice, and also performing basically the same tests on RXClass and .net object type?

Your code would possibly benefit from the TypeOf Operator (Visual Basic)

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Best way to obtain entities in an xref
« Reply #4 on: June 11, 2015, 03:31:49 PM »
I noticed that after I posted the code.  I had already changed the TryCast and removed the transaction to just DirectCast the entity to the BlockReference like this. 


Code - Visual Basic: [Select]
  1. If entityId.ObjectClass = rxc Then
  2.         Dim blockReference = DirectCast(entity, BlockReference)
  3.         Dim blockTableRecord2 = TryCast(transaction.GetObject(blockReference.BlockTableRecord, OpenMode.ForRead, False, True), BlockTableRecord)
  4.         ...



I will check out the TypeOf operator.  All of my code could definitely benefit from a code review.  As it is I spend alot of time each night reviewing the code and studying program courses learning as much as I can.  I am not formerly trained so I get things done as best as I can.



Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013