https://through-the-interface.typepad.com/thro ... 2008/08/getting-a-polyl.html
Public Class Commands
<CommandMethod("RTP")> _
Public Shared Sub RegionToPolyline()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim peo As New PromptEntityOptions(vbLf & "Select a region:")
peo.SetRejectMessage(vbLf & "Must be a region.")
peo.AddAllowedClass(GetType(Region), True)
Dim per As PromptEntityResult = ed.GetEntity(peo)
If per.Status <> PromptStatus.OK Then
Return
End If
Dim tr As Transaction = doc.TransactionManager.StartTransaction()
Using tr
Dim bt As BlockTable = CType(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
Dim btr As BlockTableRecord = CType(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
Dim reg As Region = TryCast(tr.GetObject(per.ObjectId, OpenMode.ForRead), Region)
If reg IsNot Nothing Then
' Explode Region -> collection of Curves
Dim cvs As New DBObjectCollection()
reg.Explode(cvs)
' Create a plane to convert 3D coords
' into Region coord system
Dim pl As New Plane(New Point3d(0, 0, 0), reg.Normal)
' The resulting Polyline
Dim p As New Polyline()
' Set common entity properties from the Region
p.SetPropertiesFrom(reg)
' For initial Curve take the first in the list
Dim cv1 As Curve = TryCast(cvs(0), Curve)
p.AddVertexAt(p.NumberOfVertices, cv1.StartPoint.Convert2d(pl), BulgeFromCurve(cv1, False), 0, 0)
p.AddVertexAt(p.NumberOfVertices, cv1.EndPoint.Convert2d(pl), 0, 0, 0)
cvs.Remove(cv1)
' The next point to look for
Dim nextPt As Point3d = cv1.EndPoint
' Find the line that is connected to
' the next point
' If for some reason the lines returned were not
' connected, we could loop endlessly.
' So we store the previous curve count and assume
' that if this count has not been decreased by
' looping completely through the segments once,
' then we should not continue to loop.
' Hopefully this will never happen, as the curves
' should form a closed loop, but anyway...
' Set the previous count as artificially high,
' so that we loop once, at least.
Dim prevCnt As Integer = cvs.Count + 1
While cvs.Count > 0 AndAlso cvs.Count < prevCnt
prevCnt = cvs.Count
For Each cv As Curve In cvs
' If one end of the curve connects with the
' point we're looking for...
If cv.StartPoint = nextPt OrElse cv.EndPoint = nextPt Then
' Calculate the bulge for the curve and
' set it on the previous vertex
Dim bulge As Double = BulgeFromCurve(cv, cv.EndPoint = nextPt)
p.SetBulgeAt(p.NumberOfVertices - 1, bulge)
' Reverse the points, if needed
If cv.StartPoint = nextPt Then
nextPt = cv.EndPoint
Else
' cv.EndPoint == nextPt
nextPt = cv.StartPoint
End If
' Add out new vertex (bulge will be set next
' time through, as needed)
p.AddVertexAt(p.NumberOfVertices, nextPt.Convert2d(pl), 0, 0, 0)
' Remove our curve from the list, which
' decrements the count, of course
cvs.Remove(cv)
Exit For
End If
Next
End While
If cvs.Count >= prevCnt Then
p.Dispose()
ed.WriteMessage(vbLf & "Error connecting segments.")
Else
' Once we have added all the Polyline's vertices,
' transform it to the original region's plane
p.TransformBy(Matrix3d.PlaneToWorld(pl))
' Append our new Polyline to the database
btr.UpgradeOpen()
btr.AppendEntity(p)
tr.AddNewlyCreatedDBObject(p, True)
' Finally we erase the original region
reg.UpgradeOpen()
reg.[Erase]()
End If
End If
tr.Commit()
End Using
End Sub
' Helper function to calculate the bulge for arcs
Private Shared Function BulgeFromCurve(ByVal cv As Curve, ByVal clockwise As Boolean) As Double
Dim bulge As Double = 0.0
Dim a As Arc = TryCast(cv, Arc)
If a IsNot Nothing Then
Dim newStart As Double
' The start angle is usually greater than the end,
' as arcs are all counter-clockwise.
' (If it isn't it's because the arc crosses the
' 0-degree line, and we can subtract 2PI from the
' start angle.)
If a.StartAngle > a.EndAngle Then
newStart = a.StartAngle - 8 * Math.Atan(1)
Else
newStart = a.StartAngle
End If
' Bulge is defined as the tan of
' one fourth of the included angle
bulge = Math.Tan((a.EndAngle - newStart) / 4)
' If the curve is clockwise, we negate the bulge
If clockwise Then
bulge = -bulge
End If
End If
Return bulge
End Function
End Class