TheSwamp
Code Red => .NET => Topic started by: Proctor on October 27, 2010, 02:21:50 PM
-
Hello: I have code that converts objects to polylines (e.g. 2d to poly, spline to poly).
When my code converts most of the objects, the object still appears the same as what it did before; however,
a user allerted me of a few 2d polys that once converted, looked way different (see attached pic).
Here's my code for converting - it's fairly staight forward:
Private Shared Function ConvertToPolylines(ByVal ids() As ObjectId, ByVal tr As Transaction) As List(Of Polyline)
Dim polyList As New List(Of Polyline)
Dim blockTable As BlockTable = tr.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead)
Dim modelSpace As BlockTableRecord = tr.GetObject(blockTable(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
Dim sLayerName As String = "'"
Try
For Each id As ObjectId In ids
Dim ent As Entity = tr.GetObject(id, OpenMode.ForWrite)
If TypeOf ent Is Polyline Then
' there is nothing to do
polyList.Add(ent)
ElseIf TypeOf ent Is Polyline2d Then
Dim oldPoly As Polyline2d = ent
Dim newPoly As New Polyline
newPoly.SetDatabaseDefaults()
For Each vertId As ObjectId In oldPoly
Dim vert As Vertex2d = tr.GetObject(vertId, OpenMode.ForRead)
newPoly.AddVertexAt(newPoly.NumberOfVertices, New GE.Point2d(vert.Position.X, vert.Position.Y), 0, 0, 0)
Next
newPoly.Closed = oldPoly.Closed
Dim lLength As Double = newPoly.Length
Dim aArea As Double = newPoly.Area
' add new object
modelSpace.AppendEntity(newPoly)
tr.AddNewlyCreatedDBObject(newPoly, True)
' delete old one
oldPoly.Erase()
polyList.Add(newPoly)
ElseIf TypeOf ent Is Ellipse Or TypeOf ent Is Circle Or TypeOf ent Is Spline Then
Dim curve As Curve = ent
Dim length As Double = AenLoop.GetCurveLength(ent)
Dim segmentNumber As Integer = length / kPolysegmentLength + 1
Dim newPoly As New Polyline
newPoly.SetDatabaseDefaults()
For i As Integer = 0 To segmentNumber
Dim param As Double = curve.StartParam + ((curve.EndParam - curve.StartParam) * i / segmentNumber)
Dim pt As GE.Point3d = curve.GetPointAtParameter(param)
newPoly.AddVertexAt(newPoly.NumberOfVertices, New GE.Point2d(pt.X, pt.Y), 0, 0, 0)
Next
' it it is circle or ellipse then it is closed
newPoly.Closed = TypeOf ent Is Ellipse Or TypeOf ent Is Circle
' add new object
modelSpace.AppendEntity(newPoly)
tr.AddNewlyCreatedDBObject(newPoly, True)
' delete old one
curve.Erase()
polyList.Add(newPoly)
End If
Next
Return polyList
Catch ex As Autodesk.AutoCAD.Runtime.Exception
MsgBox("ConvertToPolylines error: " & ex.Message)
tr.Abort()
Finally
End Try
End Function
Is there a way to have the object retain it's original shape when converting? Thanks,
Proctor
-
For a 2dPoly you can try this.
It creates a new PolyLine then uses the PolyLine.ConvertFrom()
Here is info from the docs instead trying to sound smart and putting in my own words
This fills the Polyline with data from the Polyline2d pointed to by entity. entity must point to a SimplePoly or FitCurvePoly type of Polyline2d object in a database. This function should be called from an Polyline that is not yet database-resident.
If transferId is true, the calling Polyline will become database-resident. The calling Polyline will assume the ObjectId and handle, plus any extended entity data (except data on vertices), the extension dictionary, and reactors of the Polyline2d entity entity. entity will then be deleted and set to NULL.
If transferId is false, entity will remain in the database as is and the caller must close it. The resulting Polyline will not be database-resident, and if not appended to a database, should be deleted.
I tried setting the transferId to true but AutoCad hung up.
I also commented out to erase the the original PolyLine2d so you could compare.
<CommandMethod("PolyConvert")> _
Public Sub PolyConvert()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Using trx As Transaction = db.TransactionManager.StartTransaction()
Dim btrMs As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)
For Each objId As ObjectId In btrMs
Dim ent As Entity = objId.GetObject(OpenMode.ForRead)
If TypeOf ent Is Polyline2d Then
ent.UpgradeOpen()
btrMs.UpgradeOpen()
Dim polyLne As New Polyline
polyLne.ConvertFrom(ent, False)
ed.WriteMessage(vbCrLf & "Converted")
'ent.Erase()
btrMs.AppendEntity(polyLne)
trx.AddNewlyCreatedDBObject(polyLne, True)
End If
Next
trx.Commit()
End Using
End Sub
Also you might want look at Polyline2d.ConvertToPolyType() since there was no mention of SplineFit in docs
And PLINETYPE system variable.
-
I tried setting the transferId to true but AutoCad hung up.
You might want to look up the DBObject.HandOverTo() Method, where it is written:
Note
This method is not allowed on objects that are transaction resident. If the object on which the method is called is transaction resident, then no handOverTo operation is performed and Acad::eInvalidContext is returned.
This leads me to suspect that something along those lines also should apply to Polyline.ConvertFrom().
Cf.
[<CommandMethod "MyPolyConvert">]
let polyConvert() =
let doc = acApp.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
let btrMs = (SymbolUtilityServices.GetBlockModelSpaceId db).Open(OpenMode.ForWrite, false) :?> BlockTableRecord
let n = ref 0
for objId in btrMs do
if typeof<Polyline2d> |> RXClass.GetClass |> objId.ObjectClass.IsDerivedFrom then
let pl2d = objId.Open(OpenMode.ForWrite, false) :?> Polyline2d
let polyLne = new Polyline()
polyLne.ConvertFrom(pl2d, true)
polyLne.Close()
incr n
btrMs.Close()
ed.WriteMessage("\n{0} converted", !n)