Has anyone had success in using WBlockCloneObjects() on polylines?
Essentially I am copying polylines from an XREF and using WBlockCloneObjects() to place in the host database. This works fine. However, if I then manually explode the polylines, all of the subentities disappear. What am I doing wrong?
I'm basically using this code, just on polyline object.
http://docs.autodesk.com/ACD/2011/ESP/filesMDG/WS1a9193826455f5ff2566ffd511ff6f8c7ca-3f78.htm
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
Solved! Go to Solution.
Solved by Jeff_M. Go to Solution.
A good amount of views but no takers... Ok, I'll post some code. Here's what I'm doing.
Selected nested linework, returns an ObjectIdCollection. I'm only allowing for Lines, Arcs, Polylines, Polyline2D, and Polyline3D
Public Shared Function SelectNestedLinework() As ObjectIdCollection
Dim db As Database = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database
Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim retLinework As New ObjectIdCollection
Dim contPick As Boolean = True
Dim tsManager As aGr.TransientManager = aGr.TransientManager.CurrentTransientManager
While contPick = True
Dim PrNestOps As New PromptNestedEntityOptions("Select nested curb linework: ")
PrNestOps.AllowNone = False
PrNestOps.UseNonInteractivePickPoint = False
Dim pner As PromptNestedEntityResult = ed.GetNestedEntity(PrNestOps)
If pner.Status = PromptStatus.OK Then
Dim nestedID As ObjectId = pner.ObjectId
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim ent As Entity = tr.GetObject(nestedID, OpenMode.ForRead)
tsManager.AddTransient(ent, aGr.TransientDrawingMode.Highlight, 128, New IntegerCollection())
If ent.GetType() = GetType(Line) Or ent.GetType() = GetType(Arc) Or ent.GetType() = GetType(Polyline) Or ent.GetType() = GetType(Polyline2d) Or ent.GetType() = GetType(Polyline3d) Then
retLinework.Add(nestedID)
Else
ed.WriteMessage(vbLf & "Entity type of: " & ent.GetType().ToString & " is not allowed, select again... ")
End If
End Using
Else
Using tr As Transaction = db.TransactionManager.StartTransaction()
For Each id As ObjectId In retLinework
Dim ent As Entity = tr.GetObject(id, OpenMode.ForRead)
tsManager.EraseTransient(ent, New IntegerCollection())
Next
End Using
contPick = False
End If
End While
Return retLinework
End Function
Next, I take that selected collection and pass it to an NCOPY function. I've tried a couple of different ways of doing this. Both work until I explode a polyline.
Method 1: Return ObjectIdCollection from IdMapping
Public Shared Function PerformNCOPY(ByVal destDoc As Document, ByVal destEd As Editor, ByVal destDb As Database) As ObjectIdCollection
Dim selObjIds As New ObjectIdCollection
selObjIds = ModuleSelections.SelectNestedCurbLinework()
Dim retObjIds As New ObjectIdCollection
Dim idMap As IdMapping = New IdMapping()
Using docLock As DocumentLock = destDoc.LockDocument
Using tr As Transaction = destDb.TransactionManager.StartTransaction()
Try
tr.TransactionManager.QueueForGraphicsFlush()
destDb.WblockCloneObjects(selObjIds, destDb.CurrentSpaceId, idMap, DuplicateRecordCloning.Replace, False)
For Each id As ObjectId In selObjIds
Dim idPair As IdPair = idMap.Lookup(id)
If idPair.IsCloned = True Then
retObjIds.Add(idPair.Value)
End If
Next
tr.Commit()
Catch ex As System.Exception
destEd.WriteMessage(vbLf & "Error during NCOPY: " & ex.Message)
End Try
End Using
End Using
Return retObjIds
End Function
Method 2: Loop through selected objects, make a new collection and perform the WBlockConeObjects, then Select the last created entity. NOTE: I only tried this because I was exploding the polyline programmatically after it was cloned to current database and upon doing that I was getting a 'eWrongDatabase' error. I was thinking the IDMapping was returning the wrong ObjectID... both methods return this error when I explode the polyline.
Public Shared Function PerformNCOPYReturnLast(ByVal destDoc As Document, ByVal destEd As Editor, ByVal destDb As Database, ByVal cloneIds As ObjectIdCollection) As ObjectIdCollection
Dim retObjIds As New ObjectIdCollection
Dim idMap As IdMapping = New IdMapping()
For Each cloneId In cloneIds
Dim newCloneColl As New ObjectIdCollection
newCloneColl.Add(cloneId)
Using docLock As DocumentLock = destDoc.LockDocument
Using tr As Transaction = destDb.TransactionManager.StartTransaction()
Try
tr.TransactionManager.QueueForGraphicsFlush()
destDb.WblockCloneObjects(newCloneColl, destDb.CurrentSpaceId, idMap, DuplicateRecordCloning.Ignore, False)
tr.Commit()
Catch ex As System.Exception
destEd.WriteMessage(vbLf & "Error during NCOPY: " & ex.Message)
End Try
End Using
End Using
Using docLock As DocumentLock = destDoc.LockDocument
Using tr As Transaction = destDb.TransactionManager.StartTransaction()
Try
Dim lastPst As PromptSelectionResult = destEd.SelectLast()
Dim ss As SelectionSet = lastPst.Value
Dim objColl As ObjectId() = ss.GetObjectIds()
For i = 0 To objColl.Length - 1
''Move linework as a test
''Dim pt As New Point3d(0, 0, 0)
''Dim endPt As New Point3d(5, 5, 5)
''Dim disp As Vector3d = pt.GetVectorTo(endPt)
''Dim mat As Matrix3d = Matrix3d.Displacement(disp)
''Dim ent As Entity = TryCast(objColl(i).GetObject(OpenMode.ForWrite), Entity)
''ent.TransformBy(mat)
retObjIds.Add(objColl(i))
Next
tr.Commit()
Catch ex As System.Exception
destEd.WriteMessage(vbLf & "Error during select last: " & ex.Message)
End Try
End Using
End Using
Next
Return retObjIds
End Function
Lastly, explode the polylines to get the segments. This iterates through the entire selection skipping lines and arcs and exploding any polyline type. I probably don't need to check the entity type and could just explode any object type, but alas, this is my function.... eWrongDatabase happens here when exploding.
If I skip this function and manually explode in AutoCAD after the WBlockCloneObjects, all polyline segments disappear.
Public Shared Function explodePolys(ByVal doc As Document, ByVal ed As Editor, ByVal db As Database, ByVal selObjIdColl As ObjectIdCollection) As ObjectIdCollection
Dim addLineworkIdColl As New ObjectIdCollection
Using tr As Transaction = db.TransactionManager.StartTransaction()
For i = 1 To selObjIdColl.Count - 2
Dim ent As Entity = TryCast(selObjIdColl.Item(i).GetObject(OpenMode.ForWrite), Entity)
Select Case ent.GetType
Case GetType(Line)
''skip
Case GetType(Arc)
''skip
Case GetType(Polyline)
Dim objs As DBObjectCollection = New DBObjectCollection
ent.Explode(objs)
Dim explodedPolyColl As New ObjectIdCollection
Dim btr As BlockTableRecord = CType(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
For Each obj As DBObject In objs
Dim expEnt As Entity = CType(obj, Entity)
btr.AppendEntity(expEnt)
tr.AddNewlyCreatedDBObject(expEnt, True)
explodedPolyColl.Add(expEnt.ObjectId)
Next
For Each id As ObjectId In explodedPolyColl
addLineworkIdColl.Add(id)
Next
Case GetType(Polyline2d)
Dim objs As DBObjectCollection = New DBObjectCollection
ent.Explode(objs)
Dim explodedPolyColl As New ObjectIdCollection
Dim btr As BlockTableRecord = CType(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
For Each obj As DBObject In objs
Dim expEnt As Entity = CType(obj, Entity)
btr.AppendEntity(expEnt)
tr.AddNewlyCreatedDBObject(expEnt, True)
explodedPolyColl.Add(expEnt.ObjectId)
Next
For Each id As ObjectId In explodedPolyColl
addLineworkIdColl.Add(id)
Next
Case GetType(Polyline3d)
Dim objs As DBObjectCollection = New DBObjectCollection
ent.Explode(objs)
Dim explodedPolyColl As New ObjectIdCollection
Dim btr As BlockTableRecord = CType(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
For Each obj As DBObject In objs
Dim expEnt As Entity = CType(obj, Entity)
btr.AppendEntity(expEnt)
tr.AddNewlyCreatedDBObject(expEnt, True)
explodedPolyColl.Add(expEnt.ObjectId)
Next
For Each id As ObjectId In explodedPolyColl
addLineworkIdColl.Add(id)
Next
End Select
Next
tr.Commit()
End Using
Return addLineworkIdColl
End Function
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
Hi,
Here's a simple example which seems to work.
[CommandMethod("TEST")]
public static void Test()
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
ObjectId id;
var options = new PromptNestedEntityOptions("\nSelect nested curb linework: ");
PromptNestedEntityResult result;
while (true)
{
result = ed.GetNestedEntity(options);
if (result.Status != PromptStatus.OK)
return;
id = result.ObjectId;
if (id.ObjectClass == RXObject.GetClass(typeof(Line)) ||
id.ObjectClass != RXObject.GetClass(typeof(Arc)) ||
id.ObjectClass != RXObject.GetClass(typeof(Polyline)) ||
id.ObjectClass != RXObject.GetClass(typeof(Polyline2d)) ||
id.ObjectClass != RXObject.GetClass(typeof(Polyline3d)))
{
if (id.Database == db)
ed.WriteMessage("\nSelected entitiy is not from an external reference.");
else
break;
}
else
{
ed.WriteMessage($"\nEntity type of: {result.ObjectId.ObjectClass.Name} is not allowed, select again... ");
}
}
var mapping = new IdMapping();
var ids = new ObjectIdCollection();
ids.Add(id);
using (var sourceDb = id.Database)
{
sourceDb.WblockCloneObjects(ids, db.CurrentSpaceId, mapping, DuplicateRecordCloning.Ignore, false);
}
if (mapping[id].IsCloned)
{
using (var tr = db.TransactionManager.StartTransaction())
{
var br = (BlockReference)tr.GetObject(result.GetContainers()[0], OpenMode.ForRead);
var clone = (Entity)tr.GetObject(mapping[id].Value, OpenMode.ForWrite);
clone.TransformBy(br.BlockTransform);
clone.ColorIndex = 1;
tr.Commit();
}
}
}
Thanks @_gile . I'll give that a try.
I see you're calling WblockCloneObjects on the source database... perhaps that's my problem. I called it on the destination database and still put the object in the destination database. Weird thing is it works... lines, arcs, and polylines (until exploded). I'll give this a test. Appreciate the help
sourceDb.WblockCloneObjects
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
@_gile that doesn't work.... did you explode the polyline after doing it? If you explode it, the polyline disappears. See my video running your code.
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
@_gile Following up on this, I found more detail on how it's behaving...
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
@_gile not to bother you too much - I really do appreciate your help. This is just so bizzare.
I found another post with some of your code here on copying a 3D polyline from an XREF and tested it. SAME RESULTS! If you then keep the XREF attached and explode the 3D Polyline, it disappears!
https://forums.autodesk.com/t5/net/clone-a-3d-polyline/m-p/3870996/highlight/true#M34572
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.
Wow. Thanks so much @Jeff_M ! That works. I don't know why I couldn't figure that out - just didn't cross my mind to check the layer. There isn't a single example out there, even by Autodesk, showing to set the layer after doing the clone. It was one of those issues that I guess I got hung up on other aspects than checking something so simple.
Really appreciate the help!
Steve Hill
Civil Designer / .NET Developer
AutoCAD Certified Professional
AutoCAD Civil 3D Certified Professional
http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn
Please select the Accept this solution button if my post solves your issue or answers your question.