由于CAD自带Bo函数,在二次开发时无论使用SendCommand方式,还是TraceBoundary函数,其精度都与视口大小挂钩。测试代码如下:
'测试cad自带bo命令功能
<CommandMethod("bot1")>
Public Sub botest()
Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim acCurDb As Database = acDoc.Database
Dim acDocEd As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
Dim acSSPrompt As PromptSelectionResult
acSSPrompt = acDocEd.GetSelection()
Dim acSSet = acSSPrompt.Value
Dim acpoint = acDocEd.GetPoint("请选择bo点")
Dim point = acpoint.Value
acDocEd.Command("-boundary", "_A", "_B", "_N", acSSet, "", "_O", "_P", "", point, "")
acTrans.Commit()
End Using
End Sub
若图面精准,可通过每次使用bo命令时调整视口范围至需要获取封闭线的区域来实现精度的最大化。即利用acDocEd.GetCurrentView(),acDocEd.SetCurrentView()进行不断的视口调整。
但该方法并不优雅,会导致视口的疯狂乱窜。且当要处理手绘图,封闭线存在小缺口,需要设置一定容差时,利用原生bo功能容易出现错误,导致找漏、找错封闭区域的状况。因此,可以编写单纯通过遍历几何图形寻找bo的函数。本文参考了惊惊大佬cad.net bo边界算法的相关思路,对纯折线情况下寻找封闭区域的算法进行了vb.net的实现,方法如下:
'Entlist为图元构成的集合,bopoint为bo点,tk_max_x是射线法在虚拟射线的最右点,
'可以取消该参数,并通过设置一个极大值的方式进行代替
Public Shared Function boundary(Entlist As ArrayList, bopoint As Point3d, tk_max_x As Double) As Polyline
Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim acCurDb As Database = acDoc.Database
Dim acDocEd As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim FinalBoPline = New Polyline()
Dim NotTrueLine = New Line(bopoint, New Point3d(tk_max_x, bopoint.Y, 0))
Dim cross_dictionary = New Dictionary(Of ObjectId, Dictionary(Of Double, ObjectId))
Dim Linelist = New ArrayList
Using acTrans1 As Transaction = acCurDb.TransactionManager.StartTransaction()
'BlkInt2实现包括自交点在内所有交点全部打断
Linelist = BlkInt2(Entlist, acTrans1)
'构造相交矩阵,使行索引线起点与列索引线相交时,值为0,终点相交时,值为1,不相交时,值为2.
Dim cross_arr = New ArrayList()
For CrNum1 = 0 To Linelist.Count - 1
Dim temp_arr = New ArrayList()
For CrNum2 = 0 To Linelist.Count - 1
temp_arr.Add(2)
Next
cross_arr.Add(temp_arr)
Next
Dim k1 = 0
For Each ent As Curve In Linelist
Dim k2 = 0
For Each ent1 As Curve In Linelist
If k1 < k2 Then
If Math.Abs(ent.StartPoint.DistanceTo(ent1.StartPoint)) <= 0.5 Then
cross_arr.Item(k1).Item(k2) = 0
cross_arr.Item(k2).Item(k1) = 0
ElseIf Math.Abs(ent.StartPoint.DistanceTo(ent1.EndPoint)) <= 0.5 Then
cross_arr.Item(k1).Item(k2) = 0
cross_arr.Item(k2).Item(k1) = 1
ElseIf