polyline轉polygon不同情況buffer的實現方法
做一個運輸署的project時需要實現一個線轉面(polyline to polygon)的函數,有點像buffer,有個buffer distance, 但是在頭尾兩邊不能是圓弧,而是直線.(確實夠搞得...)參考了一下網上的資料,將幾種類似的buffer做了一下,效果如下圖。
(左上角為polyline,用它生成其他3種buffer.注意三個polygon紅色框框位置的差別 )
先說最簡單的,直接利用ITopologicalOperator.Buffer,設定一個buffer distance就
能得到左下角的polygon, 生成的polygon在結點位置都是圓弧.
Private Function ConvertPolylineToPolygon(pPolyline As IPolyline, pDist As Double) As IPolygon
Dim pPolygon As IPolygon
Set pPolygon = New Polygon
Dim pTopo As ITopologicalOperator
Set pTopo = pPolyline
Set pPolygon = pTopo.Buffer(pDist)
pPolygon.Densify pPolygon.Length, 360
Set ConvertPolylineToPolygon = pPolygon
End Function
Dim pPolygon As IPolygon
Set pPolygon = New Polygon
Dim pTopo As ITopologicalOperator
Set pTopo = pPolyline
Set pPolygon = pTopo.Buffer(pDist)
pPolygon.Densify pPolygon.Length, 360
Set ConvertPolylineToPolygon = pPolygon
End Function
如果希望首尾兩點位置上是squre buffer,則可以用下面的函數操作
Public Function TrySquareBufferByDifference(pPolyline As IPolyline, bufDist As Double) As IPolygon
Dim pResult As IPolygon
Dim pTopoIn As ITopologicalOperator
Set pTopoIn = pPolyline
Set pResult = pTopoIn.Buffer(bufDist)
Dim pTopoOut As ITopologicalOperator
Set pTopoOut = pResult
Dim pNorm1 As ILine, pNorm2 As ILine, pNorm3 As ILine, pNorm4 As ILine
Dim pCloser As ILine
Dim pDiffSegs As ISegmentCollection
Dim pDiffer As IPolygon
Dim pDiffTopo As ITopologicalOperator
Set pNorm1 = New Line
Set pNorm2 = New Line
Set pNorm3 = New Line
Set pNorm4 = New Line
Set pCloser = New Line
pPolyline.QueryNormal esriNoExtension, 0, True, bufDist, pNorm1
pPolyline.QueryNormal esriNoExtension, 0, True, -bufDist, pNorm2
'on the next two lines, you may need to reverse the signs of the "length" arguments
pNorm1.QueryNormal esriNoExtension, 1, True, bufDist, pNorm3
pNorm2.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm4
pCloser.PutCoords pNorm3.ToPoint, pNorm4.ToPoint
Set pDiffer = New Polygon
Set pDiffSegs = pDiffer
Set pDiffTopo = pDiffer
Set pDiffer.SpatialReference = pPolyline.SpatialReference
pDiffSegs.AddSegment pNorm1
pDiffSegs.AddSegment pNorm2
pDiffSegs.AddSegment pNorm3
pDiffSegs.AddSegment pNorm4
pDiffSegs.AddSegment pCloser
pDiffTopo.Simplify
Dim pTemp As IGeometry
Set pTemp = pTopoOut.Difference(pDiffer)
Set pTopoOut = pTemp
Set pNorm1 = New Line
Set pNorm2 = New Line
Set pNorm3 = New Line
Set pNorm4 = New Line
Set pCloser = New Line
pPolyline.QueryNormal esriNoExtension, 1, True, bufDist, pNorm1
pPolyline.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm2
'on the next two lines, you may need to reverse the signs of the "length" arguments
pNorm1.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm3
pNorm2.QueryNormal esriNoExtension, 1, True, bufDist, pNorm4
pCloser.PutCoords pNorm3.ToPoint, pNorm4.ToPoint
Set pDiffer = New Polygon
Set pDiffSegs = pDiffer
Set pDiffTopo = pDiffer
Set pDiffer.SpatialReference = pPolyline.SpatialReference
pDiffSegs.AddSegment pNorm1
pDiffSegs.AddSegment pNorm2
pDiffSegs.AddSegment pNorm3
pDiffSegs.AddSegment pNorm4
pDiffSegs.AddSegment pCloser
pDiffTopo.Simplify
Set TrySquareBufferByDifference = pTopoOut.Difference(pDiffer)
End Function
Dim pResult As IPolygon
Dim pTopoIn As ITopologicalOperator
Set pTopoIn = pPolyline
Set pResult = pTopoIn.Buffer(bufDist)
Dim pTopoOut As ITopologicalOperator
Set pTopoOut = pResult
Dim pNorm1 As ILine, pNorm2 As ILine, pNorm3 As ILine, pNorm4 As ILine
Dim pCloser As ILine
Dim pDiffSegs As ISegmentCollection
Dim pDiffer As IPolygon
Dim pDiffTopo As ITopologicalOperator
Set pNorm1 = New Line
Set pNorm2 = New Line
Set pNorm3 = New Line
Set pNorm4 = New Line
Set pCloser = New Line
pPolyline.QueryNormal esriNoExtension, 0, True, bufDist, pNorm1
pPolyline.QueryNormal esriNoExtension, 0, True, -bufDist, pNorm2
'on the next two lines, you may need to reverse the signs of the "length" arguments
pNorm1.QueryNormal esriNoExtension, 1, True, bufDist, pNorm3
pNorm2.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm4
pCloser.PutCoords pNorm3.ToPoint, pNorm4.ToPoint
Set pDiffer = New Polygon
Set pDiffSegs = pDiffer
Set pDiffTopo = pDiffer
Set pDiffer.SpatialReference = pPolyline.SpatialReference
pDiffSegs.AddSegment pNorm1
pDiffSegs.AddSegment pNorm2
pDiffSegs.AddSegment pNorm3
pDiffSegs.AddSegment pNorm4
pDiffSegs.AddSegment pCloser
pDiffTopo.Simplify
Dim pTemp As IGeometry
Set pTemp = pTopoOut.Difference(pDiffer)
Set pTopoOut = pTemp
Set pNorm1 = New Line
Set pNorm2 = New Line
Set pNorm3 = New Line
Set pNorm4 = New Line
Set pCloser = New Line
pPolyline.QueryNormal esriNoExtension, 1, True, bufDist, pNorm1
pPolyline.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm2
'on the next two lines, you may need to reverse the signs of the "length" arguments
pNorm1.QueryNormal esriNoExtension, 1, True, -bufDist, pNorm3
pNorm2.QueryNormal esriNoExtension, 1, True, bufDist, pNorm4
pCloser.PutCoords pNorm3.ToPoint, pNorm4.ToPoint
Set pDiffer = New Polygon
Set pDiffSegs = pDiffer
Set pDiffTopo = pDiffer
Set pDiffer.SpatialReference = pPolyline.SpatialReference
pDiffSegs.AddSegment pNorm1
pDiffSegs.AddSegment pNorm2
pDiffSegs.AddSegment pNorm3
pDiffSegs.AddSegment pNorm4
pDiffSegs.AddSegment pCloser
pDiffTopo.Simplify
Set TrySquareBufferByDifference = pTopoOut.Difference(pDiffer)
End Function
如果希望節點位置不出現圓弧,可以用以下的方法
Public Function TrySquareBufferByOffset(pPolyline As IPolyline, bufDist As Double) As IPolygon
Dim pOffset1 As IConstructCurve, pOffset2 As IConstructCurve
Set pOffset1 = New Polyline
Set pOffset2 = New Polyline
Dim pOffCurve1 As ICurve, pOffCurve2 As ICurve
Set pOffCurve1 = pOffset1
Set pOffCurve2 = pOffset2
pOffset1.ConstructOffset pPolyline, bufDist, esriConstructOffsetSimple
pOffset2.ConstructOffset pPolyline, -bufDist, esriConstructOffsetSimple
Dim pLine1 As ILine, pLine2 As ILine
Set pLine1 = New Line
Set pLine2 = New Line
pLine1.PutCoords pOffCurve1.FromPoint, pOffCurve2.FromPoint
pLine2.PutCoords pOffCurve1.ToPoint, pOffCurve2.ToPoint
Dim pResult As IPolygon
Set pResult = New Polygon
Set pResult.SpatialReference = pPolyline.SpatialReference
Dim pSegCol As ISegmentCollection
Set pSegCol = pResult
pSegCol.AddSegment pLine1
pSegCol.AddSegment pLine2
pSegCol.AddSegmentCollection pOffset1
pSegCol.AddSegmentCollection pOffset2
pResult.SimplifyPreserveFromTo
Set TrySquareBufferByOffset = pResult
End Function
Dim pOffset1 As IConstructCurve, pOffset2 As IConstructCurve
Set pOffset1 = New Polyline
Set pOffset2 = New Polyline
Dim pOffCurve1 As ICurve, pOffCurve2 As ICurve
Set pOffCurve1 = pOffset1
Set pOffCurve2 = pOffset2
pOffset1.ConstructOffset pPolyline, bufDist, esriConstructOffsetSimple
pOffset2.ConstructOffset pPolyline, -bufDist, esriConstructOffsetSimple
Dim pLine1 As ILine, pLine2 As ILine
Set pLine1 = New Line
Set pLine2 = New Line
pLine1.PutCoords pOffCurve1.FromPoint, pOffCurve2.FromPoint
pLine2.PutCoords pOffCurve1.ToPoint, pOffCurve2.ToPoint
Dim pResult As IPolygon
Set pResult = New Polygon
Set pResult.SpatialReference = pPolyline.SpatialReference
Dim pSegCol As ISegmentCollection
Set pSegCol = pResult
pSegCol.AddSegment pLine1
pSegCol.AddSegment pLine2
pSegCol.AddSegmentCollection pOffset1
pSegCol.AddSegmentCollection pOffset2
pResult.SimplifyPreserveFromTo
Set TrySquareBufferByOffset = pResult
End Function
-----------------------------------------------------------
佛对我说:你心里有尘。我用力的拭擦。