[讨论]如何在ObjectARX 2008中获得边界对象
2009新增了Autodesk.AutoCAD.BoundaryRepresentation可以使用BoundaryLoop class 处理边界对象,Kean的一篇Blog也提到了在2011中怎样使用Editor.TraceBoundary() 获得边界对象。但是,现在的问题是,在AutoCAD 2008中如何提取边界对象?
例如下图所示,四条直线的ObjectId均已知,直线封闭边界内部的某一个点的坐标也已知,怎样提取图中封闭的边界?
注意:这里要问的主要是思路,上图情况采用求交点的方式蛮干还是可以实现的。
实际实现的过程中,封闭边界可能是由直线、圆弧等实体组成,亦可能包含孤岛等情况。
我有这样的想法:
在AutoCAD中,使用Boundary命令,定义边界内部的一个点,可以创建一个边界的多段线对象。在程序中,创建一个全新的图层并定义为当前图层,然后调用-Boundary命令,这时生成的多段线边界对象便可以提取出来了。
这个方法感觉有点笨。欢迎大家讨论!
用命令还是比较简单的,但必须要让区域在视口中可见
自己实现的话,现成的算法应该是有的,google下看看?
多谢lzh741206的关注。
还是采用-Boundary命令的方式来实现的,不过没有我在上面说的那么土,要用新图层什么的,哈哈
参考了“ObjectARX编程站”如下帖子(感谢zmkm1234和wz0406):
http://www.objectarx.net/forum.php?mod=viewthread&tid=867&highlight=%B1%DF%BD%E7
我的VB.Net代码如下:
Public Class ModelSpace
_
Private Shared Function acedCmd(ByVal vlist As System.IntPtr) As Integer
End Function
Public Shared Function GetColsedBoundary(ByVal InnerX As Double, ByVal InnerY As Double) As ObjectId
Dim rb As ResultBuffer = New ResultBuffer
Try
rb.Add(New TypedValue(5005, "._-BOUNDARY"))
rb.Add(New TypedValue(5005, "_AD"))
rb.Add(New TypedValue(5005, "_IS"))
If IslandDetection = 1 Then
rb.Add(New TypedValue(5005, "_Y")) 'Y表示启动孤单检测
Else
rb.Add(New TypedValue(5005, "_N")) 'N表示不启动孤单检测
rb.Add(New TypedValue(5005, "_N")) '射线投影类型:默认的Nearest。
'注意:有时会出现点在边界外的问题,所以尽量要启用孤岛检测
End If
rb.Add(New TypedValue(5005, "_OB"))
rb.Add(New TypedValue(5005, "PO"))
rb.Add(New TypedValue(5005, ""))
rb.Add(New TypedValue(5005, (InnerX.ToString + ("," + InnerY.ToString))))
rb.Add(New TypedValue(5005, ""))
acedCmd(rb.UnmanagedObject)
Dim db As Database = GetDB()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim psr As PromptSelectionResult = ed.SelectLast
Dim ObjIds As ObjectId() = psr.Value.GetObjectIds
If ObjIds IsNot Nothing And ObjIds.Length > 0 Then
Dim ObjId As ObjectId = ObjIds(0)
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim obj As DBObject = trans.GetObject(ObjId, OpenMode.ForRead)
If TypeOf (obj) Is Polyline Then
Dim ObjectPolyPolyline As Polyline = obj
Dim msg As String = String.Format("Area = {0} ", ObjectPolyPolyline.Area)
ed.WriteMessage(msg)
Return ObjId
End If
End Using
End If
Catch ex As System.Exception
MsgBox("Hatch Boundary Error " & ex.Message)
Return ObjectId.Null
Finally
rb.Dispose()
End Try
End Function
End Class
实际上,这样做有一个问题,如果边界内部含有孤岛的话,-Boundary命令可以检测出来,也会在CAD上提示检测到,但是使用上面的代码却是无法提取孤岛边界多段线的。
假如:有外部边界和内部孤岛边界时,-Boundary检测并创建两个封闭的多段线边界,但在
Dim psr As PromptSelectionResult = ed.SelectLast
Dim ObjIds As ObjectId() = psr.Value.GetObjectIds
执行后,objIds的长度只有1,也就是只能提取外部边界对象,内部孤岛边界对象是无法提取的。
怎样才能将内部孤岛的多段线对象也提取出来呢?
另:有人使用ARX命令acdbEntLast和acdbEntNext可以实现,在ObjectARX .NET里面这两个函数的对应函数分别是什么?
.NET里面这两个函数的对应函数:Utils.EntLast/Next
内部孤岛:
命令: -Boundary
指定内部点或 [高级选项(A)]: a
输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]: i
是否需要孤岛检测?[是(Y)/否(N)] : y
输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]: o
输入边界对象类型 [面域(R)/多段线(P)] : p
输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]:
指定内部点或 [高级选项(A)]: 正在选择所有对象...
正在选择所有可见对象...
正在分析所选数据...
正在分析内部孤岛...
指定内部点或 [高级选项(A)]:
BOUNDARY 已创建 2 个多段线
不过如果内部点选择错误的话,-Boundary命令会出问题的,要考虑这个问题
AutoCAD2010版本的acmgd.dll才有Utils.EntLast/Next函数。
在AutoCAD2008,acmgdinternal.dll有Utils,但是没有上面的两个函数。
好遗憾啊!
多谢lzh741206的提醒!
经过不懈的努力,终于搞定了。
具体思路为:
在ObjectARX .Net程序中同时使用COM编程,在调用-Boundary命令之前和之后分别使用
ThisDrawing.ModelSpace.Count
得到各个状态模型空间的实体总个数,然后在两个实体总个数差异值的区间内使用
Dim ent As AcadEntity = ThisDrawing.ModelSpace.Item(i)
得到外部边界与内部边界多段线对象。
----------------------------------------------------------------------------------------
实际上,在此之前,我也使用了在调用-Boundary命令之前新建图层并设为当前图层,
在调用-Boundary命令之后再使用ed.SelectAll()选择当前图层上的所有对象这一思路。
代码如下:
'定义过滤条件
Dim value1 As TypedValue = New TypedValue(DxfCode.LayerName, TempLayerName)
Dim value2 As TypedValue = New TypedValue(DxfCode.Start, "Polyline")
Dim Values() As TypedValue = {value1, value2}
Dim sf As New SelectionFilter(Values)
'执行选择
Dim psr As PromptSelectionResult = ed.SelectAll(sf)
但是执行到上面最后一条语句时报错,不知道怎么回事。
望指教!
多段线是"LWPolyline“吧?
正解!就是这个的问题!换成LWPolyline就没有问题了!
佩服!感谢!
顺着这个思路,重新复习了一下DXF参考手册,有收获啊!
页:
[1]