I am trying to copy various object type entities. Some entities are lines, circles, block references and polylines. After some time of searching and manipulating code that I found, I was able to find a copy jig for a single entity. My issue is I need it for an array of entities ...
Take a look at the CopyJig class that works for 1 entity (source😞
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.DatabaseServices
Imports MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application
Imports MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document
Imports AcWindowsNS = Autodesk.AutoCAD.Windows
Public Class CopyJig
Inherits EntityJig
#Region "Fields"
Public mCurJigFactorIndex As Integer = 1
Private mBasePoint As New Point3d()
Private mNewPoint As Point3d
' Factor #1
#End Region
#Region "Constructors"
Public Sub New(ent As Entity, basePoint As Point3d)
MyBase.New(ent)
mNewPoint = InlineAssignHelper(mBasePoint, basePoint.TransformBy(UCS))
End Sub
#End Region
#Region "Properties"
Private ReadOnly Property Editor() As Editor
Get
Return MgdAcApplication.DocumentManager.MdiActiveDocument.Editor
End Get
End Property
Private ReadOnly Property UCS() As Matrix3d
Get
Return Editor.CurrentUserCoordinateSystem
End Get
End Property
#End Region
#Region "Overrides"
Protected Overrides Function Update() As Boolean
Dim mat As Matrix3d = Matrix3d.Displacement(mBasePoint.GetVectorTo(mNewPoint))
Entity.TransformBy(mat)
mBasePoint = mNewPoint
Return True
End Function
Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
Select Case mCurJigFactorIndex
Case 1
Dim prOptions1 As New JigPromptPointOptions(vbLf & "Location:")
prOptions1.UserInputControls = UserInputControls.Accept3dCoordinates Or UserInputControls.GovernedByOrthoMode Or UserInputControls.GovernedByUCSDetect
prOptions1.BasePoint = mBasePoint
prOptions1.UseBasePoint = True
Dim prResult1 As PromptPointResult = prompts.AcquirePoint(prOptions1)
If prResult1.Status = PromptStatus.Cancel Then
Return SamplerStatus.Cancel
End If
If prResult1.Value.Equals(mNewPoint) Then
'Use better comparision method if wanted.
Return SamplerStatus.NoChange
Else
mNewPoint = prResult1.Value
Return SamplerStatus.OK
End If
Case Else
Exit Select
End Select
Return SamplerStatus.OK
End Function
#End Region
#Region "Methods to Call"
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
Public Shared Function Jig(ent As Entity, basePt As Point3d) As Boolean
Dim jigger As CopyJig = Nothing
Try
jigger = New CopyJig(ent, basePt)
Dim pr As PromptResult
Do
pr = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.Drag(jigger)
' Add keyword handling code below
If pr.Status = PromptStatus.Keyword Then
Else
jigger.mCurJigFactorIndex += 1
End If
Loop While pr.Status <> PromptStatus.Cancel AndAlso pr.Status <> PromptStatus.[Error] AndAlso jigger.mCurJigFactorIndex <= 1
If pr.Status = PromptStatus.Cancel OrElse pr.Status = PromptStatus.[Error] Then
If jigger IsNot Nothing AndAlso jigger.Entity IsNot Nothing Then
jigger.Entity.Dispose()
End If
Return False
Else
Return True
End If
Catch
If jigger IsNot Nothing AndAlso jigger.Entity IsNot Nothing Then
jigger.Entity.Dispose()
End If
Return False
End Try
End Function
#End Region
End Class
The following class is called using this code:
<CommandMethod("CopyEntities")> _
Public Sub CopyEntities()
Dim ed As Editor = AcApp.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim rb As ResultBuffer
Dim FoundCorrectXData As Boolean
Dim Lst_ObjId As New List(Of ObjectId)
Dim acBlkTbl As BlockTable
Dim acBlkTblRec As BlockTableRecord
Dim SelSet As SelectionSet = Nothing
Dim entities As Entity()
Try
Dim selRes As PromptEntityResult = ed.GetEntity(vbLf & "Pick an entity:")
Dim ptRes As PromptPointResult = ed.GetPoint(vbLf & "Base Point: ")
If selRes.Status = PromptStatus.OK AndAlso ptRes.Status = PromptStatus.OK Then
Using tr As Transaction = db.TransactionManager.StartTransaction()
'------------------------- START BUILDING THE ARRAY OF ENTITIES---------------------
rb = New ResultBuffer
rb = selRes.ObjectId.GetObject(OpenMode.ForRead).XData()
If IsHunter(rb) Then
MyObject.SetByDataTable(GetPKFromResultBuffer(rb), Project.PK_Project)
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) 'Open the Block table for read
acBlkTblRec = tr.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite) 'Open the Block table record Model space for write
'Go through the Block Table Record and build the collection ID
For Each acObjId As ObjectId In acBlkTblRec
rb = New ResultBuffer
rb = acObjId.GetObject(OpenMode.ForRead).XData()
FoundCorrectXData = False
If Not rb Is Nothing Then
For Each tv As TypedValue In rb
If tv.TypeCode = DxfCode.ExtendedDataRegAppName Then
If tv.Value = "OBJECT_TO_BE_FOUND" Then FoundCorrectXData = True
End If
If FoundCorrectXData And tv.TypeCode = DxfCode.ExtendedDataInteger32 Then
If tv.Value = MyObject.PK_MyObject Then
Lst_ObjId.Add(acObjId)
Exit For
End If
End If
Next
rb.Dispose()
End If
Next
'Create a selection set from the object IDs added to the list
SelSet = SelectionSet.FromObjectIds(Lst_ObjId.ToArray)
entities = New Entity(SelSet.Count - 1) {}
'Create an array of entities
For i As Integer = 0 To SelSet.Count - 1
entities(i) = DirectCast(tr.GetObject(SelSet(i).ObjectId, OpenMode.ForWrite), Entity)
Next
'-----------------------------END OF ENTITY ARRAY BUILD----------------------------------
'Code used to clone a single entity
Dim ent As Entity = TryCast(tr.GetObject(selRes.ObjectId, OpenMode.ForRead), Entity)
If ent IsNot Nothing Then
Dim clone As Entity = TryCast(ent.Clone(), Entity)
If CopyJig.Jig(clone, ptRes.Value) Then
Dim ms As BlockTableRecord = TryCast(tr.GetObject(ent.OwnerId, OpenMode.ForWrite), BlockTableRecord)
If ms IsNot Nothing Then
ms.AppendEntity(clone)
tr.AddNewlyCreatedDBObject(clone, True)
tr.Commit()
End If
Else
tr.Abort()
End If
End If
End If
End Using
End If
Catch ex As System.Exception
ed.WriteMessage(ex.ToString())
End Try
End Sub
The goal is to be able to see where I'm copying my entities and be able to select that point. I cleaned up the code above from my CopyEntities method. It includes an array of entities that contain the perfect selection that I wanted. I've been trying to pass this into the CopyJig class but I keep hitting snags.
My main snag is in the constructor of the CopyJig, I cannot pass an array of entities in there...
I thank you for the help in advance,
Alex