cobalt 发表于 2010-8-28 21:28:00

[讨论]如何在ObjectARX 2008中获得边界对象

2009新增了Autodesk.AutoCAD.BoundaryRepresentation可以使用BoundaryLoop class 处理边界对象,Kean的一篇Blog也提到了在2011中怎样使用Editor.TraceBoundary() 获得边界对象。
但是,现在的问题是,在AutoCAD 2008中如何提取边界对象?
例如下图所示,四条直线的ObjectId均已知,直线封闭边界内部的某一个点的坐标也已知,怎样提取图中封闭的边界?





注意:这里要问的主要是思路,上图情况采用求交点的方式蛮干还是可以实现的。
         实际实现的过程中,封闭边界可能是由直线、圆弧等实体组成,亦可能包含孤岛等情况。

我有这样的想法:
在AutoCAD中,使用Boundary命令,定义边界内部的一个点,可以创建一个边界的多段线对象。在程序中,创建一个全新的图层并定义为当前图层,然后调用-Boundary命令,这时生成的多段线边界对象便可以提取出来了。
这个方法感觉有点笨。欢迎大家讨论!

雪山飞狐_lzh 发表于 2010-8-28 21:39:00

用命令还是比较简单的,但必须要让区域在视口中可见
自己实现的话,现成的算法应该是有的,google下看看?

cobalt 发表于 2010-8-29 00:06:00

多谢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

cobalt 发表于 2010-8-29 11:58:00


实际上,这样做有一个问题,如果边界内部含有孤岛的话,-Boundary命令可以检测出来,也会在CAD上提示检测到,但是使用上面的代码却是无法提取孤岛边界多段线的。
假如:有外部边界和内部孤岛边界时,-Boundary检测并创建两个封闭的多段线边界,但在
Dim psr As PromptSelectionResult = ed.SelectLast
Dim ObjIds As ObjectId() = psr.Value.GetObjectIds
执行后,objIds的长度只有1,也就是只能提取外部边界对象,内部孤岛边界对象是无法提取的。

怎样才能将内部孤岛的多段线对象也提取出来呢?

另:有人使用ARX命令acdbEntLast和acdbEntNext可以实现,在ObjectARX .NET里面这两个函数的对应函数分别是什么?

雪山飞狐_lzh 发表于 2010-8-29 17:34:00

.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 个多段线

雪山飞狐_lzh 发表于 2010-8-29 17:36:00

不过如果内部点选择错误的话,-Boundary命令会出问题的,要考虑这个问题

cobalt 发表于 2010-8-29 20:48:00

AutoCAD2010版本的acmgd.dll才有Utils.EntLast/Next函数。
在AutoCAD2008,acmgdinternal.dll有Utils,但是没有上面的两个函数。
好遗憾啊!

cobalt 发表于 2010-8-30 00:04:00

多谢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)

但是执行到上面最后一条语句时报错,不知道怎么回事。
望指教!

雪山飞狐_lzh 发表于 2010-8-30 16:55:00

多段线是"LWPolyline“吧?

cobalt 发表于 2010-8-31 10:52:00

正解!就是这个的问题!换成LWPolyline就没有问题了!
佩服!感谢!

顺着这个思路,重新复习了一下DXF参考手册,有收获啊!
页: [1]
查看完整版本: [讨论]如何在ObjectARX 2008中获得边界对象