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

WBlockCloneObjects() on polylines works until polylines are exploded... then linework disappears

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
stevenh0616
795 Views, 8 Replies

WBlockCloneObjects() on polylines works until polylines are exploded... then linework disappears

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.

8 REPLIES 8
Message 2 of 9
stevenh0616
in reply to: stevenh0616

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.

Message 3 of 9
_gile
in reply to: stevenh0616

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();
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 9
stevenh0616
in reply to: _gile

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.

Message 5 of 9
stevenh0616
in reply to: _gile

@_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.

 

https://autode.sk/32OKD5C



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.

Message 6 of 9
stevenh0616
in reply to: _gile

@_gile Following up on this, I found more detail on how it's behaving...

 

If the XREF remains or is unloaded, the polyline disappears after exploding.
 
If the XREF is detached and no longer part of the file and explode the polyline, it works as expected.

 

https://autode.sk/3jC47jT



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.

Message 7 of 9
stevenh0616
in reply to: _gile

@_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.

Message 8 of 9
Jeff_M
in reply to: stevenh0616

Steve, the cloned polyline is being placed on the same layer as it is coming from. A database resident object cannot reside on an Xref layer. Change the layer of the cloned object and all is well.

Jeff_M, also a frequent Swamper
EESignature
Message 9 of 9
stevenh0616
in reply to: Jeff_M

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.

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