AutoCAD.NET 技术交流-吴锋


专注AutoCAD.net,GIS
posts - 113, comments - 500, trackbacks - 15, articles - 4
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

AutoCAD.net:有条件选择AutoCAD实体

Posted on 2008-08-08 13:23 无锋不起浪 阅读(147) 评论(2)  编辑 收藏 所属分类: AutoCAD.net

引自http://through-the-interface.typepad.com/through_the_interface/2008/07/conditional-sel.html 

这篇文章有感自之前的 一篇文章 ,在那篇文章中我们可以找到选择指定层上的所有实体的代码。这儿我们关注的是如何更好的选择多个层中的实体:AutoCAD的选择过滤机理使得这个选择起来实现起来很容易,同时还能实现跟实体的各个属性相关的复合性选择。

This post was inspired by a comment on this previous post, where we looked at some code to select entities on a specific layer. The question was regarding how best to select entities from multiple layers: the selection filtering mechanism inside AutoCAD makes this very easy, and can cope with composition of conditions related to various entity properties. 

基本的思路就是添加你所想要过滤的实体特性的标签,标签标明了过滤条件:条件"or",添加"<or"与">or";条件"and",添加"<and"与">and"。

The basic concept is to enclose sets of entity properties for which you wish to filter with tags indicating the composition of the conditions: for "or" you enclose the conditions with "<or" and "or>" and for "and" you use "<and" and "and>". Wow: I can safely say that that's probably the only sentence I've ever written that has 6 of the last 10 words being "and". :-) 

让我们看一个实例:我们想要选择层0上的所有直线和所有直径大于10的圆,该如何组合条件呢?

Let's take a concrete example: let's say we want to select all lines on on layer 0 and all the circles with radii greater than 10.'s how we would compose the conditions, in pseudo-code:

  • <or
    • <and
      • Layer == "0"
      • Entity type == "LINE"
    • and>
    • <and
      • Entity type == "CIRCLE"
      • Radius >= 10.0
    • and>
  • or>

转换为c#如下代码:为清楚起见,此处我把指定的属性/值以硬编码的形式实现,另如果需要应该直接由用户从数据库中进行选择。

This translates into the following C# code - for clarity I've left the specific properties/values hard-coded, but clearly it would be straightforward to ask the user or pick them out of a database, as needed. 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

namespace EntitySelection
{
    
public class Commands
    
{
        [CommandMethod(
"SEWP")]
        
public static void SelectEntitiesWithProperties()
        
{
            Document doc 
= Application.DocumentManager.MdiActiveDocument;
            Editor ed 
= doc.Editor;

            
// Build a conditional filter list so that only
            
// entities with the specified properties are
            
// selected
            TypedValue[] tvs = new TypedValue[] 
            
{
                
new TypedValue((int)DxfCode.Operator, "<or"),
                
new TypedValue((int)DxfCode.Operator, "<and"),
                
new TypedValue((int)DxfCode.LayerName, "0"),
                
new TypedValue((int)DxfCode.Start, "LINE"),
                
new TypedValue((int)DxfCode.Operator, "and>"),
                
new TypedValue((int)DxfCode.Operator, "<and"),
                
new TypedValue((int)DxfCode.Start, "CIRCLE"),
                
new TypedValue((int)DxfCode.Operator, ">="),
                
new TypedValue((int)DxfCode.Real, 10.0),// Circle Radius
                new TypedValue((int)DxfCode.Operator, "and>"),
                
new TypedValue((int)DxfCode.Operator, "or>")
            }
;

            SelectionFilter sf 
= new SelectionFilter(tvs);
            PromptSelectionResult psr 
= ed.SelectAll(sf);
            
if (psr.Status == PromptStatus.OK)
            
{
                SelectionSet SS 
= psr.Value;
                ObjectId[] idArray 
= SS.GetObjectIds();
                
for (int i = 0; i < idArray.Length; i++)
                
{
                    Entity ent 
= (Entity)Tools.GetDBObject(idArray[i]);
                    ent.Highlight();
                    Tools.WriteMessage(i 
+ ":" + ent.ObjectId.ToString() + "," + ent.GetType().Name);
                }

            }


        }


    }
//end class
}


另外,你也可以使用"<xor"与"xor>"进行一个高级"or"选择的测试。

By the way - you can also choose to perform an "exclusive or" test by using "<xor" and "xor>".

To try out this code, draw a number of lines in a blank drawing, and run the SEWP command. This simply tells you how many entities met the selection criteria - it doesn't leave them selected for use by further commands. You can then see how drawing circles of varying radii changes the number of entities selected by the command.

On a final note... SelectionFilters can be used either non-interactively (as in this example, via the SelectAll() method) or interactively (via GetSelection(), SelectWindow(), SelectCrossingPolygon(), SelectFence(), etc.). I've shown simple uses of SelectionFilters in previous posts, but it's also possible to use quite complicated groupings of conditions - as we've scratched the surface of in this post.

Feedback

#1楼 [楼主]   回复  引用  查看    

2008-08-11 11:31 by 无锋不起浪      
TypedValue[] tv = { new TypedValue(1001, "MyEntity") };
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult pr = ed.SelectAll(sf);
这个选择集中包括所有的扩展数据中的注册程序名称为“MyEntity”的实体。1001对应DXF编码中扩展数据的注册应用程序名称。

对于过滤集,SelectionFilter来说,不是所有的东西都可以用于过滤条件的,例如dxf编码为5的handle就不能用于过滤,如果你构造一个过滤集为:
TypedValue[] tv = { new TypedValue(5, "15C") };
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult pr = ed.SelectAll(sf);
也就是说,你想过滤Handle为“15C”的对象,但是,这里是不行的,pr.status肯定是Error。因为,Handle是不能用于过滤的。根据Lisp中的提示,有很多dxfcode能用于过滤的,Lisp中的说明如下:

"The ssget function recognizes all group codes except entity names
(group -1), handles (group 5), and xdata codes (groups greater than 1000).
If an invalid group code is used in a filter-list, it is ignored by ssget. "

他里面说,dxfcode大于1000的不行,但是,我在ObjectARX2008下测试是可以的,也许,改进了吧。但是,-1和5还是不行。

但确实有很多情况想根据Handle来得到图中的实体,那么可以用这种方式,首先根据Handle得到ObjectId,然后根据ObjectId从Database得到实体,例如:
ObjectId entId = db.GetObjectId(false, entHandle, 0);
Entity ent = (Entity)tr.GetObject(entId, OpenMode.ForWrite);

#2楼 [楼主]   回复  引用  查看    

2008-09-19 16:44 by 无锋不起浪      
3.10.1   选择集的过滤
为了使用选择集过滤模式,参数str必须指定为“X”。选择集过滤模式允许依据特性选择实体。过滤参数是一个结果缓冲区表,在这里给acedSSGet()函数详细说明了要使用的实体种类和特性种类。如果过滤参数是NULL,并且参数str为“X”,则选择集ss将包含当前AutoCAD图形中的每一
个实体,而不考虑实体是否在冻结的层上。函数调用如下:
现在选择集ss将包含当前AutoCAD图形中的每一个实体。那么我们怎样选择数据库中所有的圆实体呢?为了有效地使用选择集,必须知道DXF组码。首先我们必须构造一个结果缓冲区,但因为我们只寻找一种实体,所以我们可以使用acutNewRb()函数来创建该结果缓冲区。下面是一段代码实
例:
下面的程序代码实例生成由某一图层上所有的实体组成的选择集。图层的DXF组码是8。
好了,下面我们举一个稍微复杂一点的例子,假定我们要选择“parts”层上的所有圆。这是一个利用acutBuildList()函数构造结果缓冲区表后再传给acedSSGet()函数的实例。

3.10.2   选择集的关系过滤
在选择集中可以使用关系运算符。例如:我们要选取“parts”图层上半径大于等于2.0的所有圆。在缺省情况下,acedSSGet()函数选取满足过滤表中所有条件的实体。过滤时每两个项之间的隐含关系是“相等(equals)”。对于数值型组码(整数、实数、点和向量),借助在结果缓冲区中包
含一个说明关系运算符的特殊组码“-4”可以指定其他的关系运算。该运算符应用于紧跟其后的结果缓冲区项。关系运算符由字符串指定。表3-8列出了所有的关系运算符。
关系运算符可以用实例来很好地说明,继续我们所举的例子:选取“parts”图层上半径大于等于2.0的所有圆。其程序代码如下:
表3-8   选择集过滤表的关系运算符
关系运算符 说      明
“*” 任意(始终为真)
“=” 等于
“!=” 不等于(C/C++)
“/=” 不等于(AutoLISP)
“<>” 不等于
“<” 小于
“<=” 小于或等于
“>” 大于
“>=” 大于或等于
“&” 按位“与”(只用于整数组码)
“&=” 按位等于(只用于整数组码)


3.10.3   选择集的条件过滤
除关系测试外,我们还可以使用条件运算符。表3-9列出了所有的选择集条件运算符。
表3-9   选择集过滤表的条件运算符
起始运算符 中间内容 终止运算符
“<AND” 一个或多个操作对象 “AND>”
“<OR” 一个或多个操作对象 “OR>”
“<XOR” 两个操作对象 “XOR>”
“<NOT” 一个操作对象 “NOT>”
选择集的条件运算符允许我们执行像选择图形中半径为1.0的所有圆和“parts”图层上的所有直线这一类的选择集操作。编程后代码如下:
本例有助于掌握选择集的关系过滤和条件过滤。


3.10.4   选择集的扩展实体数据过滤
从R11版本起,AutoCAD就有了一个为实体添加数据的机制,称为扩展实体数据(xdata)。我不准备深入讨论扩展实体数据,因为从AutoCAD R13 c4a起,在AutoCAD R14和以后的版本中引入了一种新的机制称为XRecords,这在后面的章节中将会加以讨论。扩展实体数据通常是由外部应用程序附加到一个对象上的文本串、数值、3D点、距离、层名或其他数据。扩展数据的大小是每个实体16KB。注意XRecords是不附加于任何实体的,因此XRecords的存在并不需要实体的存在。借助在过滤表中使用-3组码标记指定应用程序名,就可以检索扩展数据。acedSSGet()函数返回登记有特定名称的扩展数据的实体集合,acedSSGet()函数并不检索单个扩展数据项(组码范围为1000~2000)。
下面为选择所有实体的代码段,所有实体均有以其应用程序ID号为“APPNAME”注册的扩展数据:在ADSRX文档中,有关扩展实体数据的信息还有很多,但由于AutoCAD R14和以后的版本使用XRecords,因此,在后面的章节中我们将详细讨论XRecords。


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-08-08 13:25 编辑过


相关链接: