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

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

<p><font face="微软雅黑">AutoCAD 2009新增了Autodesk.AutoCAD.BoundaryRepresentation可以使用BoundaryLoop class 处理边界对象,Kean的一篇Blog也提到了在2011中怎样使用&nbsp; Editor.TraceBoundary() 获得边界对象。</font></p>
<p><font face="微软雅黑">但是,现在的问题是,在AutoCAD 2008中如何提取边界对象?</font></p>
<p><font face="微软雅黑">例如下图所示,四条直线的ObjectId均已知,直线封闭边界内部的某一个点的坐标也已知,怎样提取图中封闭的边界?</font></p>
<p></p>
<p>&nbsp;</p>
<p>注意:这里要问的主要是思路,上图情况采用求交点的方式蛮干还是可以实现的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实际实现的过程中,封闭边界可能是由直线、圆弧等实体组成,亦可能包含孤岛等情况。</p>
<p>&nbsp;</p>
<p><font face="微软雅黑">我有这样的想法:</font></p>
<p><font face="微软雅黑">在AutoCAD中,使用Boundary命令,定义边界内部的一个点,可以创建一个边界的多段线对象。在程序中,创建一个全新的图层并定义为当前图层,然后调用-Boundary命令,这时生成的多段线边界对象便可以提取出来了。</font></p>
<p><font face="微软雅黑">这个方法感觉有点笨。欢迎大家讨论!</font></p>

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

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

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

<p>多谢<font color="#da2549" face="Verdana"><b>lzh741206</b></font>的关注。</p>
<p>还是采用-Boundary命令的方式来实现的,不过没有我在上面说的那么土,要用新图层什么的,哈哈</p>
<p>参考了“ObjectARX编程站”如下帖子(感谢<font style="BACKGROUND-COLOR: #ffffff" face="Verdana">zmkm1234和wz0406</font>):</p>
<p><font style="BACKGROUND-COLOR: #ffffff" face="Verdana"><a href="http://www.objectarx.net/forum.php?mod=viewthread&amp;tid=867&amp;highlight=%B1%DF%BD%E7">http://www.objectarx.net/forum.php?mod=viewthread&amp;tid=867&amp;highlight=%B1%DF%BD%E7</a></font></p>
<p>&nbsp;</p>
<p>我的VB.Net代码如下:</p>
<p>&nbsp; </p>
<p align="left">Public Class ModelSpace</p>
<p align="left">&nbsp;&nbsp;&nbsp; &lt;Runtime.InteropServices.DllImport("acad.exe", SetLastError:=True)&gt; _</p>
<p align="left">&nbsp;&nbsp;&nbsp; Private Shared Function acedCmd(ByVal vlist As System.IntPtr) As Integer</p>
<p align="left">&nbsp;&nbsp;&nbsp; End Function</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp; Public Shared Function GetColsedBoundary(ByVal InnerX As Double, ByVal InnerY As Double) As ObjectId</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim rb As ResultBuffer = New ResultBuffer</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Try</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "._-BOUNDARY"))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rb.Add(New TypedValue(5005, "_AD"))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "_IS"))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If IslandDetection = 1 Then</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "_Y"))&nbsp;&nbsp;&nbsp;&nbsp; 'Y表示启动孤单检测</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "_N"))&nbsp;&nbsp;&nbsp;&nbsp; 'N表示不启动孤单检测</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "_N"))&nbsp;&nbsp;&nbsp;&nbsp; '射线投影类型:默认的Nearest&lt;N&gt;。</p>
<p align="left">'注意:有时会出现点在边界外的问题,所以尽量要启用孤岛检测</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "_OB"))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, "PO"))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, ""))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, (InnerX.ToString + ("," + InnerY.ToString))))</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Add(New TypedValue(5005, ""))</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acedCmd(rb.UnmanagedObject)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim db As Database = GetDB()</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim psr As PromptSelectionResult = ed.SelectLast</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ObjIds As ObjectId() = psr.Value.GetObjectIds</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If ObjIds IsNot Nothing And ObjIds.Length &gt; 0 Then</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ObjId As ObjectId = ObjIds(0)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Using trans As Transaction = db.TransactionManager.StartTransaction</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim obj As DBObject = trans.GetObject(ObjId, OpenMode.ForRead)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If TypeOf (obj) Is Polyline Then</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ObjectPolyPolyline As Polyline = obj</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim msg As String = String.Format("Area = {0} ", ObjectPolyPolyline.Area)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ed.WriteMessage(msg)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return ObjId</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Using</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Catch ex As System.Exception</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MsgBox("Hatch Boundary Error " &amp; ex.Message)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return ObjectId.Null</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Finally</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.Dispose()</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Try</p>
<p align="left">&nbsp;&nbsp;&nbsp; End Function</p>
<p align="left">&nbsp;</p>
<p align="left">End Class</p>

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

本帖最后由 作者 于 2010-8-29 14:05:03 编辑 <br /><br /> <p><font face="微软雅黑 "><font size="4">实际上,这样做有一个问题,如果边界内部含有孤岛的话,-Boundary命令可以检测出来,也会在CAD上提示检测到,但是使用上面的代码却是无法提取孤岛边界多段线的。</font></font><br/><font face="微软雅黑 "><font size="4">假如:有外部边界和内部孤岛边界时,-Boundary检测并创建两个封闭的多段线边界,但在</font></font></p>
<p><font face="微软雅黑 "><font size="4">Dim psr As PromptSelectionResult = ed.SelectLast </font></font></p>
<p><font face="微软雅黑 "><font size="4">Dim ObjIds As ObjectId() = psr.Value.GetObjectIds</font></font></p>
<p><font face="微软雅黑 "><font size="4">执行后,objIds的长度只有1,也就是只能提取外部边界对象,内部孤岛边界对象是无法提取的。</font></font></p>
<p><font size="4" face="微软雅黑"></font>&nbsp;</p>
<p><font size="4" face="微软雅黑">怎样才能将内部孤岛的多段线对象也提取出来呢?</font></p>
<p>&nbsp;</p>
<p><font size="4" face="微软雅黑">另:有人使用ARX命令<font style="BACKGROUND-COLOR: #ffffff"><font color="#993366">acdbEntLast</font>和<font color="#993366">acdbEntNext</font>可以实现,在ObjectARX .NET里面这两个函数的对应函数分别是什么?</font><br/></font></p>

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

<p><font size="4" face="微软雅黑">.NET里面这两个函数的对应函数:Utils.EntLast/Next</font></p>
<p><font size="4" face="微软雅黑">内部孤岛:</font></p>
<p><font face="Verdana">命令: -Boundary<br/>指定内部点或 [高级选项(A)]: a<br/>输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]: i<br/>是否需要孤岛检测?[是(Y)/否(N)] &lt;Y&gt;: y<br/>输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]: o<br/>输入边界对象类型 [面域(R)/多段线(P)] &lt;多段线&gt;: p<br/>输入选项 [边界集(B)/孤岛检测(I)/对象类型(O)]:<br/>指定内部点或 [高级选项(A)]: 正在选择所有对象...<br/>正在选择所有可见对象...<br/>正在分析所选数据...</font></p>
<p><font face="Verdana">正在分析内部孤岛...</font></p>
<p><font face="Verdana">指定内部点或 [高级选项(A)]:<br/>BOUNDARY 已创建 2 个多段线</font></p>

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

<p>不过如果内部点选择错误的话,<font face="Verdana">-Boundary命令会出问题的,要考虑这个问题</font></p>
<p>&nbsp;</p>

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

<p><font size="4">AutoCAD2010版本的acmgd.dll才有Utils.EntLast/Next函数。</font></p>
<p><font size="4" face="微软雅黑">在AutoCAD2008,acmgdinternal.dll有Utils,但是没有上面的两个函数。</font></p>
<p><font size="4" face="微软雅黑">好遗憾啊!</font></p>

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

<p><font size="4" face="微软雅黑">多谢<font color="#da2549" face="Verdana"><b>lzh741206</b></font>的提醒!</font></p>
<p><font size="4" face="微软雅黑"></font>&nbsp;</p>
<p><font size="4" face="微软雅黑">经过不懈的努力,终于搞定了。</font></p>
<p><font size="4" face="微软雅黑">具体思路为:</font></p>
<p><font size="4" face="微软雅黑">在ObjectARX .Net程序中同时使用COM编程,在调用-Boundary命令之前和之后分别使用</font></p>
<p><font style="BACKGROUND-COLOR: #ffffff" size="4" face="微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThisDrawing.ModelSpace.Count</font></p>
<p><font size="4" face="微软雅黑">得到各个状态模型空间的实体总个数,然后在两个实体总个数差异值的区间内使用</font></p>
<p><font style="BACKGROUND-COLOR: #ffffff" size="4" face="微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ent As AcadEntity = ThisDrawing.ModelSpace.Item(i)</font></p>
<p><font size="4" face="微软雅黑">得到外部边界与内部边界多段线对象。</font></p>
<p><font size="4" face="微软雅黑">----------------------------------------------------------------------------------------</font></p>
<p><font size="4" face="微软雅黑">实际上,在此之前,我也使用了在调用-Boundary命令之前新建图层并设为当前图层,</font></p>
<p><font size="4" face="微软雅黑">在调用-Boundary命令之后再使用ed.SelectAll()选择当前图层上的所有对象这一思路。</font></p>
<p><font size="4" face="微软雅黑">代码如下:</font></p>
<p><font style="BACKGROUND-COLOR: #ffffff" size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '定义过滤条件<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim value1 As TypedValue = New TypedValue(DxfCode.LayerName, TempLayerName)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim value2 As TypedValue = New TypedValue(DxfCode.Start, "Polyline")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim Values() As TypedValue = {value1, value2}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim sf As New SelectionFilter(Values)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '执行选择<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim psr As PromptSelectionResult = ed.SelectAll(sf)<br/></font></p>
<p><font size="4" face="微软雅黑">但是执行到上面最后一条语句时报错,不知道怎么回事。</font></p>
<p><font size="4" face="微软雅黑">望指教!</font></p>

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

<p>多段线是"LWPolyline“吧?</p>

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

lzh741206发表于2010-8-30 16:55:00static/image/common/back.gif多段线是\"LWPolyline“吧?


<p><font face="微软雅黑">正解!就是这个的问题!换成LWPolyline就没有问题了!</font></p>
<p><font face="微软雅黑">佩服!感谢!</font></p>
<p><font face="微软雅黑"></font>&nbsp;</p>
<p><font face="微软雅黑">顺着这个思路,重新复习了一下DXF参考手册,有收获啊!</font></p>
页: [1]
查看完整版本: [讨论]如何在ObjectARX 2008中获得边界对象