天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 71|回复: 0

ObjectARX2015 + vs2012选择集

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
在 ObjectARX 开发过程中,经常需要用户和 AutoCAD 之间进行交互操作,除了前面介绍的acedGetXX 系列函数之外,选择集是 AutoCAD 和用户交互操作的重要手段。与 acedEntSel 函数不同,acedEntSel 函数用于提示用户选择一个实体,选择集允许用户同时选择多个图形对象,同时提供了丰富的手段来选择符合特定条件的实体。
        本篇的实例详细介绍了选择集的使用,可以分为以下几个方面:
                 选择集的创建和删除。
                 选择集中对象的增加和删除。
                 对象选择的方法。
                 选择集过滤器的使用。
2. 思路
(1)  选择集的创建和删除
        选择集是 AutoCAD 当前图形中的一组实体,通过图元名进行引用,也就是一个 ads_name 变量。创建选择集可以使用 acedSSAdd 和 acedSSGet 函数,其中 acedSSGet 函数提供了绝大 多数创建选择集的方法:


         提示用户选择实体。
         使用 PICKFIRST 选择集(在未执行命令时用户已经选择的图形集合,也就是 AutoCAD 中的先选择、再输入命令)或者交叉( Crossing )、多变性交叉( Crossing Polygon)、栅栏( Fence )、最后一个( Last )、前一个( Previous )、窗口( Window )、 多边形窗口(Window Polygon )等方式,也可以指定一个点或者一系列点来明确地 限定所要选择的实体。
         指定选择实体所要满足的一系列属性和条件来过滤当前数据库,可以和前面的选择
方式配合使用。


        无论使用 acedSSAdd 还是 acedSSGet 函数,都需要在程序结束之前使用 acedSSFree 函数
释放选择集的内存空间。


(2)  选择集中元素的增加和删除
        这里所说的元素增加和删除,仅指在已经获得对象引用的情况下,使用 acedSSAdd 和 acedSSDel 函数对选择集进行元素的增加和删除。
//acedSSAdd 函数定义为:
int acedSSAdd(const ads_name ename,  //ename 指定要添加到选择集的实体的图元名
              const ads_name sname,  //sname 指定选择集的图元名
              ads_name result);      //result返回被创建或者更新的选择集


// 根据 ename 和 sname 的不同取值,acedSSAdd 有以下几种可能的执行结果:
如果 ename 和 sname 都是空指针,则创建一个未包含任何成员的选择集。
如果 ename 指向一个有效的实体,但 sname 是空指针,则创建一个选择集,该选择集仅包含一个成员 ename。
如果 ename 指向有效的实体,且 sname 指向有效的选择集,则将 ename 所指向的实体添加到 sname 所指向的选择集中。
// acedSSDel 函数定义为:
int acedSSDel(const ads_name ename, //ename 指定了要从选择集中删除的实体
              const ads_name ss);   //ss 指定了所要操作的选择集
(3)  对象选择的方法
        所谓对象选择的方法,就是以某种方式从图形窗口中获得满足某些条件的图形对象。这里要介绍的是使用 acedSSGet 函数所实现的选择对象的方法,该函数被定义为:
/*
//所谓对象选择的方法,就是以某种方式从图形窗口中获得满足某些条件的图形对象,用acedSSGet
int acedSSGet (const char *str,   //str 参数描述了创建选择集的方法,可以使用的参数值参见下表
               const void *pt1,   //pt1 和 pt2 为相关的创建方式提供了点参数,
               const void *pt2,   //如果不需要指定可以输入 NULL 作为参数值;
               const struct resbuf *entmask, //entmask 用于指定选择实体的过滤条件
               ads_name ss);      //ss 则指定了要操作的选择集的图元名
*/




4. 使用选择集过滤器

        在使用各种选择对象的方法时,可以使用过滤器来限定选择的对象。例如,可以指定仅选择图层 0 上的直线对象,也可以指定仅选择蓝色的半径大于 30 的圆,等等。

        如果仅使用一个过滤条件,可以使用下面的代码:
//过滤器例子(一个过滤条件)
struct resbuf rb;
char sbuf[10]; // 存储字符串的缓冲区
ads_name ssname;

rb.restype = 0; // 实体名
strcpy(sbuf, "CIRCLE");
rb.resval.rstring = sbuf;
rb.rbnext = NULL; // 不需要设置其他的属性

// 选择图形中所有的圆
acedSSGet("X", NULL, NULL, &rb, ssname);

acedSSFree(ssname);
//上面的代码中虽然使用了结果缓冲区,但是仅是在栈上声明,由编译器自动管理它所使
    //用的内存空间,不需要使用 acutRelRb 函数来手工销毁它。

        如果要指定多个过滤条件,可以使用 acutBuildList 函数来构造结果缓冲区。如果要选择当前图形窗口中位于 0 层上的所有直线,就可以使用下面的方法:
//过滤器例子(多个过滤条件)
struct resbuf *rb; // 结果缓冲区链表
ads_name ssname;

rb = acutBuildList(RTDXF0, "LINE", // 实体类型
                   8, "0", // 图层
                   RTNONE);

// 选择图形中位于0层上的所有直线
acedSSGet("X", NULL, NULL, rb, ssname);

acutRelRb(rb);
acedSSFree(ssname);
//在标准的 DXF 组码中,0 用于表示实体类型,但是在 acutBuildList 函数中 0 也可以用于
    //表示结束链表,因此用 RTDXF0 来代替 0。

        在标准的 DXF 组码中, 0 用于表示实体类型,但是在 acutBuildList 函数中 0 也可以用于表示结束链表,因此用 RTDXF0 来代替 0 。
        过滤器列表由成对的参数组成。第一个参数标识过滤器的类型(例如对象),第二个参数指定要过滤的值(例如圆)。
        过滤器类型是指定使用哪种过滤器的 DXF 组码,下面列出了一些最常用的过滤器类型:


         0 :对象类型(字符串),例如“ Line ”、“ Arc ”等。
         1 :图元的主文字值(字符串),例如文字、属性的字符串内容。
         2 :对象名(字符串),例如属性标记、块名等。
         8:图层名(字符串)。
         10 :主要点(直线或文字图元的起点、圆的圆心等),用三个实数的数组来表示三维点。
         60 :对象可见性(整数), 0 表示可见, 1 表示不可见。
         62 :颜色编号(整数),可取 0 ~ 256 的整数值,其中 0 表示 ByBlock , 256 表示 ByLayer 。
         67 :模型/图纸空间标识符(整数), 0 (默认)表示在模型空间, 1 表示在图纸空间。
         1000 :扩展数据中的 ASCII 字符串,最多可以包含 255 个字节。
         1001 :扩展数据的注册应用程序名,最多可以包含 31 个字节的 ASCII 字符串。
         1003 :扩展数据图层名。


        值得一提的是,在大部分选择模式中均可以使用选择集过滤器,下面的代码提示用户选
择实体的同时使用了选择集过滤器:
acedSSGet(NULL, NULL, NULL, rb, ssname);
3. 步骤

(1) 选择集的创建和删除

    //选择集(Select set)的创建和删除
    static void CreateSSet(); //选择集(Select set)的创建和删除
//选择集(Select set)的创建和删除
void CUserInteraction::CreateSSet()
{
    ads_name sset; // 选择集名称
    // 选择图形数据库中所有的实体
    acedSSGet(_T("A"), NULL, NULL, NULL, sset);
    // 进行其他操作
    acedSSFree(sset);
}
(2)  对象选择的方法
A.  创建一个函数 SelectEnt ,使用多种不同的模式创建选择集
        下边演示了 acedSSGet 函数的几个典型应用。使用 CP 和 WP 选 择模式时,需要用 acutBuildList 函数创建一个包含多边形顶点的结果缓冲区链表, acedSSGet 函数会自动闭合顶点列表,因此不必创建一个首尾顶点相同的结果缓冲区链表。
    //选择对象
    static void SelectEnt();  //选择对象
//选择对象,演示 acedSSGet 函数的几个典型应用
//使用 CP 和 WP 选择模式时,需要用 acutBuildList 函数创建一个包含多边形顶点的结果缓冲区链表,
//acedSSGet 函数会自动闭合顶点列表,因此不必创建一个首尾顶点相同的结果缓冲区链表。
void CUserInteraction::SelectEnt()
{
    ads_point pt1, pt2, pt3, pt4;
    struct resbuf *pointlist; // 结果缓冲区链表
    ads_name ssname; // 选择集的图元名
    pt1[X] = pt1[Y] = pt1[Z] = 0.0;
    pt2[X] = pt2[Y] = 5.0; pt2[Z] = 0.0;

    // 如果已经选择到了实体,就获得当前的PICKFIRST选择集
    // 否则提示用户选择实体
    acedSSGet(NULL, NULL, NULL, NULL, ssname);

    // 如果存在,就获得当前的PickFirst选择集
    acedSSGet(_T("I"), NULL, NULL, NULL, ssname);

    // 选择最近创建的选择集
    acedSSGet(_T("P"), NULL, NULL, NULL, ssname);

    // 选择最后一次创建的可见实体
    acedSSGet(_T("L"), NULL, NULL, NULL, ssname);

    // 选择通过点(5,5)的所有实体
    acedSSGet(NULL, pt2, NULL, NULL, ssname);

    // 选择位于角点(0,0)和(5,5)组成的窗口内所有的实体
    acedSSGet(_T("W"), pt1, pt2, NULL, ssname);
    // 选择被指定的多边形包围的所有实体
    pt3[X] = 10.0; pt3[Y] = 5.0; pt3[Z] = 0.0;
    pt4[X] = 5.0; pt4[Y] = pt4[Z] = 0.0;
    pointlist = acutBuildList(RTPOINT, pt1, RTPOINT, pt2, RTPOINT, pt3, RTPOINT, pt4, 0);
    acedSSGet(_T("WP"), pointlist, NULL, NULL, ssname);

    // 选择与角点(0,0)和(5,5)组成的区域相交的所有实体
    acedSSGet(_T("C"), pt1, pt2, NULL, ssname);

    // 选择与指定多边形区域相交的所有实体
    acedSSGet(_T("CP"), pointlist, NULL, NULL, ssname);
    acutRelRb(pointlist);

    // 选择与选择栏相交的所有对象
    pt4[Y] = 15.0; pt4[Z] = 0.0;
    pointlist = acutBuildList(RTPOINT, pt1, RTPOINT, pt2, RTPOINT, pt3, RTPOINT, pt4, 0);
    acedSSGet(_T("F"), pointlist, NULL, NULL, ssname);

    acutRelRb(pointlist);
    acedSSFree(ssname);
}

B. 1. 函数参数前面的*&表示该参数是一个指针的引用,使用指
   针的引用作为参数,能够在函数内部对指针的本身的内容进行修改。
2. 首先使用 segType 成员函数来判断多段线某一段的类型,
   如果是直线段就创建一个AcGeLineSeg2d 对象,
   如果是圆弧段则创建一个 AcGeCircArc2d 对象,并将创建的几何类对象添加到一个对象指针数组中。
3. 如果多段线闭合,并且最后的一段是圆弧段,那么还要将终点和起点之间的那一段曲线添加到最终的几何曲线中,
   这样才能保证多段线与对应的几何类曲线形状完全一致。
   如果最后一段是直线段,则不需要添加,其理由将在下一个函数的分析中说明。
4. pArc->setAngles(arc.startAng(), arc.endAng() - (arc.endAng() - arc.startAng()) / 100);
   这句代码将会使最后一段曲线的终点发生一个小的偏移(偏移后仍在原来的圆弧上,但
   不与原来的终点重合),其原因同样会在下一个函数的分析中说明。
5. if (geCurves.length() == 1)
   {
       pGeCurve = (AcGeCurve2d *)geCurves[0];
   }
   else
   {
       pGeCurve = new AcGeCompositeCurve2d(geCurves);
    }
   如果多段线仅包含一段曲线,直接将几何曲线的指针指向新建的几何曲线对象;
   否则根据对象指针数组中的元素创建一个新的复合曲线,并且为其分配相应的内存。
   对应地,当多段线的段数大于 1 时,函数结束前应该用 delete 操作符释放用 new 运算符分配
   所有的几何曲线的存储空间。

    //根据指定的多段线创建对应的几何类曲线, pPline 指定已知的多段线,pGeCurve 参数输出创建的几何曲线
    bool PolyToGeCurve(const AcDbPolyline *pPline, AcGeCurve2d *&pGeCurve);
bool CUserInteraction::PolyToGeCurve(const AcDbPolyline *pPline, AcGeCurve2d *&pGeCurve)
{
    int nSegs; // 多段线的段数
    AcGeLineSeg2d line, *pLine; // 几何曲线的直线段部分
    AcGeCircArc2d arc, *pArc; // 几何曲线的圆弧部分
    AcGeVoidPointerArray geCurves; // 指向组成几何曲线各分段的指针数组

    nSegs = pPline->numVerts() - 1;

    // 根据多段线创建对应的分段几何曲线
    for (int i = 0; i < nSegs; i++)
    {
        if (pPline->segType(i) == AcDbPolyline::kLine)
        {
            pPline->getLineSegAt(i, line);
            pLine = new AcGeLineSeg2d(line);
            geCurves.append(pLine);
        }
        else if (pPline->segType(i) == AcDbPolyline::kArc)
        {
            pPline->getArcSegAt(i, arc);
            pArc = new AcGeCircArc2d(arc);
            geCurves.append(pArc);
        }
    }

    // 处理闭合多段线最后一段是圆弧的情况
    if (pPline->isClosed() && pPline->segType(nSegs) == AcDbPolyline::kArc)
    {
        pPline->getArcSegAt(nSegs, arc);
        pArc = new AcGeCircArc2d(arc);
        pArc->setAngles(arc.startAng(), arc.endAng() - (arc.endAng() - arc.startAng()) / 100);
        geCurves.append(pArc);
    }

    // 根据分段的几何曲线创建对应的复合曲线
    if (geCurves.length() == 1)
    {
        pGeCurve = (AcGeCurve2d *)geCurves[0];
    }
    else
    {
        pGeCurve = new AcGeCompositeCurve2d(geCurves);
    }


    // 释放动态分配的内存
    if (geCurves.length() > 1)
    {
        for (int i = 0; i < geCurves.length(); i++)
        {
            delete geCurves[i];
        }
    }

    return true;
}

C. 选择指定多段线内部(或者与多段线构成的区域相交)的所有实体
//选择指定多段线内部(或者与多段线构成的区域相交)的所有实体。
    //pPline 指定已知的多段线
    //ObjectIdArray 输出选择到的所有实体的 ObjectId 数组
    //selectMode 指定选择模式(可以输入“CP”或者“WP”)
    //approxEps 指定构造多段线对应几何曲线时的误差。
    bool SelectEntInPoly(AcDbPolyline *pPline, AcDbObjectIdArray &ObjectIdArray, const TCHAR *selectMode, double approxEps);
//pPline 指定已知的多段线
//ObjectIdArray 输出选择到的所有实体的 ObjectId 数组
//selectMode 指定选择模式(可以输入“CP”或者“WP”)
//approxEps 指定构造多段线对应几何曲线时的误差。
bool CUserInteraction::SelectEntInPoly(AcDbPolyline *pPline,
                                       AcDbObjectIdArray &ObjectIdArray,
                                       const TCHAR *selectMode,
                                       double approxEps)
{
    // 判断selectMode的有效性
    if (_tcscmp(selectMode, _T("CP")) != 0 && _tcscmp(selectMode, _T("WP")) != 0)
    {
        acedAlert(_T("函数SelectEntInPline中,指定了无效的选择模式!"));
        return false;
    }
    // 清除数组中所有的ObjectId
    for (int i = 0; i < ObjectIdArray.length(); i++)
    {
        ObjectIdArray.removeAt(i);
    }
    AcGeCurve2d *pGeCurve; // 多段线对应的几何曲线
    Adesk::Boolean bClosed = pPline->isClosed(); // 多段线是否闭合
    if (bClosed != Adesk::kTrue) // 确保多段线作为选择边界时是闭合的
    {
        pPline->setClosed(!bClosed);
    }
    // 创建对应的几何类曲线
    CUserInteraction::PolyToGeCurve(pPline, pGeCurve);
    // 获得几何曲线的样本点
    AcGePoint2dArray SamplePtArray; // 存储曲线的样本点
    AcGeDoubleArray ParamArray; // 存储样本点对应的参数值
    AcGePoint2d ptStart, ptEnd; // 几何曲线的起点和终点
    Adesk::Boolean bRet = pGeCurve->hasStartPoint(ptStart);
    bRet = pGeCurve->hasEndPoint(ptEnd);
    double valueSt = pGeCurve->paramOf(ptStart);
    double valueEn = pGeCurve->paramOf(ptEnd);
    pGeCurve->getSamplePoints(valueSt, valueEn, approxEps, SamplePtArray, ParamArray);

    delete pGeCurve; // 在函数PolyToGeCurve中分配了内存
    // 确保样本点的起点和终点不重合
    AcGeTol tol;
    tol.setEqualPoint(0.01);
    AcGePoint2d ptFirst = SamplePtArray[0];
    AcGePoint2d ptLast = SamplePtArray[SamplePtArray.length() - 1];
    if (ptFirst.isEqualTo(ptLast))
    {
        SamplePtArray.removeLast();
    }

    // 根据样本点创建结果缓冲区链表
    struct resbuf *rb;
    rb = CUserInteraction::BuildRbFromPtArray(SamplePtArray);
    // 使用acedSSGet函数创建选择集
    ads_name ssName; // 选择集名称
    int rt = acedSSGet(selectMode, rb, NULL, NULL, ssName);
    if (rt != RTNORM)
    {
        acutRelRb(rb); // 释放结果缓冲区链表
        return false;
    }
    // 将选择集中所有的对象添加到ObjectIdArray
    long length;
    acedSSLength(ssName, &length);
    for (int i = 0; i < length; i++)
    {
        // 获得指定元素的ObjectId
        ads_name ent;
        acedSSName(ssName, i, ent);
        AcDbObjectId objId;
        acdbGetObjectId(objId, ent);
        // 获得指向当前元素的指针
        AcDbEntity *pEnt;
        Acad::ErrorStatus es = acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
        // 选择到作为边界的多段线了,直接跳过该次循环
        if (es == Acad::eWasOpenForWrite)
        {
            continue;
        }
        ObjectIdArray.append(pEnt->objectId());
        pEnt->close();
    }
    // 释放内存
    acutRelRb(rb); // 释放结果缓冲区链表
    acedSSFree(ssName); // 删除选择集
    return true;
}

        首先判断 selectMode 参数的有效性,清空 ObjectIdArray 的所有元素(引用类型传递的参 数,防止该参数在函数外的修改影响该函数执行的结果),然后使用 PolyToGeCurve 函数创建与指定多段线对应的几何类曲线。
        此后,使用 AcGeCurve2d 类的 getSamplePoints 函数来获得多段线的样本点。为什么不直
接用数据库实体类 AcDbPolyline 来获得多段线的顶点来作为样本点呢?样本点是用于描述曲线形状的一组点,获得多段线的形状,可以使用两种方法:
         等距获得样本点。输入一个固定的长度值,从起点开始,每到这个固定的长度就在曲线上取一个样本点,最后得到的样本点是等间距的。
         按照弦切距的误差极限来获得样本点,这种方法可以控制样本点的精度。要根据一定的精度来获得几何类对象的样本点,
        必须深入理解几何类的getSamplePoints函数
void getSamplePoints(
    double fromParam, //fromParam是开始处的参数
    double toParam,   //toParam是结束处的参数
    double approxEps, //approxEps是弦高误差
    AcGePoint3dArray& pointArray,       //pointArray输出曲线上位于开始参数fromParam和
    AcGeDoubleArray& paramArray) const; //终止参数toParam之间的所有点的数组

//    paramArray输出与数组pointArray中的点相对应的参数数组。
//    这里所说的“参数”,是一个与长度有关的值,其具体含义Autodesk并未公开。
弦高误差的含义如图 所示:

对一条多段线取样本点,能够得到类似下图所示的结果:





多段线的顶点 A 、 B 、C、 D 仍然会是样本点。从图中可以看出,样本点很好地描述了多段线的形状,而仅由顶点组成的多边形根本无法描述带有圆弧段的多段线形状。


        接下来的代码根据样本点创建结果缓冲区链表,在此之前,需要确保样本点数组中首尾两点不重合,其中的原因在前面已经介绍,acedSSGet 函数会自动闭合顶点列表。创建结果缓冲区链表使用了一个自定义函数 BuildRbFromPtArray,该函数的定义将在下面的步骤中介绍。

        创建选择集之后,遍历选择集,将选择到的实体添加到 ObjectId 数组中,但是有时候作为边界的多段线也被添加到选择集中,在添加 ObjectId 的时候就要将其排除。此时多段线还没有被关闭,因此使用 acdbOpenAcDbEntity 函数打开时会返回 Acad::eWasOpenForWrite,可以此作为辨别边界多段线的依据。

        在函数的最后,不能忘记释放结果缓冲区链表和选择集。

D. 创建一个新的成员函数 BuildRbFromPtArray,用于根据指定的一组点创建一个结果缓冲区链表,它接受一个参数 arrPoints,该参数指定一组点,而函数返回创建的结果缓冲区链表。该函数的实现代码为:

    //根据指定的一组点创建一个结果缓冲区链表
    struct resbuf* BuildRbFromPtArray(const AcGePoint2dArray &arrPoints);//根据指定的一组点创建一个结果缓冲区链表
//根据指定的一组点创建一个结果缓冲区链表
struct resbuf* CUserInteraction::BuildRbFromPtArray(const AcGePoint2dArray &arrPoints)
{
    struct resbuf *retRb = NULL;
    int count = arrPoints.length();
    if (count <= 1)
    {
        acedAlert(_T("函数BuildBbFromPtArray中,点数组包含元素个数不足!"));
            return retRb;
    }

    // 使用第一个点来构建结果缓冲区链表的头节点
    ads_point adsPt;
    adsPt[X] = arrPoints[0].x;
    adsPt[Y] = arrPoints[0].y;
    retRb = acutBuildList(RTPOINT, adsPt, RTNONE);

    struct resbuf *nextRb = retRb; // 辅助指针

    for (int i = 1; i < count; i++) // 注意:不考虑第一个元素,因此i从1开始
    {
        adsPt[X] = arrPoints[i].x;
        adsPt[Y] = arrPoints[i].y;
        // 动态创建新的节点,并将其链接到原来的链表尾部
        nextRb->rbnext = acutBuildList(RTPOINT, adsPt, RTNONE);
        nextRb = nextRb->rbnext;
    }

    return retRb;
}

(3) 使用选择集过滤器

A. 创建一个带有通配符的过滤器, 在过滤器中使用通配符。添加函数 Filter1()

    //创建一个带有通配符的过滤器, 在过滤器中使用通配符。
    void Filter1();
//创建一个带有通配符的过滤器, 在过滤器中使用通配符。
void CUserInteraction::Filter1()
{
    struct resbuf *rb; // 结果缓冲区链表
    ads_name ssname;

    rb = acutBuildList(RTDXF0, _T("TEXT"), // 实体类型
        8, _T("0,图层1"), // 图层
        1, _T("*cadhelp*"), // 包含的字符串
        RTNONE);

    // 选择复合要求的文字
    acedSSGet(_T("X"), NULL, NULL, rb, ssname);
    long length;
    acedSSLength(ssname, &length);
    acutPrintf(_T("\n实体数:%d"), length);

    acutRelRb(rb);
    acedSSFree(ssname);
}

        上面的代码构建的过滤器,能够获得位于图层“0 ”或者“图层 1 ”中、字符串内容包含 cadhelp 的所有文字对象。其中,“ 0, 图层 1 ”中的逗号(,)是一个通配符,用于分隔两个模式,表示两种情况均可;“*mjtd* ”中的星号(*)是一个通配符,用于匹配任意的字符序列,表示任何包含 cadhelp 的字符串均可.
关于 AutoCAD 能够识别的通配符及其含义


B.  创建包含逻辑运算符的过滤器, 在过滤器中使用逻辑运算符。添加新函数 Filter2()

    //创建包含逻辑运算符的过滤器, 在过滤器中使用逻辑运算符
    void Filter2();
//创建包含逻辑运算符的过滤器, 在过滤器中使用逻辑运算符
void CUserInteraction::Filter2()
{
    struct resbuf *rb; //结果缓冲区链表
    ads_name ssname;

    rb = acutBuildList(-4, _T("<OR"),  //逻辑运算符开始
        RTDXF0, _T("TEXT"),            //一个条件
        RTDXF0, _T("MTEXT"),           //另一个条件
        -4, _T("OR<"),                 //逻辑运算符结束
        RTNONE);

    //选择符合要求的文字
    acedSSGet(_T("X"), NULL, NULL, rb, ssname);
    long length;
    acedSSLength(ssname, (Adesk::Int32 *)&length);
    acutPrintf(_T("\n实体数:%d"), length);

    acutRelRb(rb);
    acedSSFree(ssname);
}

        上面构建的过滤器,能够选择图形中所有的文字和多行文字。过滤器列表中的逻辑运算符用DXF组码-4 来指示。逻辑运算符是字符串但必须成对出现,运算符以小于号开始(<), 以大于号结束(>)。图 5.13列出了可以在选择集过滤中使用的逻辑运算符






C. 创建包含关系运算符的过滤器, 在过滤器中使用关系运算符。添加新函数 Filter3()

    //创建包含关系运算符的过滤器, 在过滤器中使用关系运算符
    void Filter3();
//创建包含关系运算符的过滤器, 在过滤器中使用关系运算符
void CUserInteraction::Filter3()
{
    struct resbuf *rb; //结果缓冲区链表
    ads_name ssname;

    //选择图形中半径大于或等于30的所有圆
    rb = acutBuildList(RTDXF0, _T("CIRCLE"), //实体类型
        -4, _T(">="),  //关系运算符;组码-4指示过滤器列表中的关系运算符
        40, 30,   //半径;组码40用于指定圆的半径
        RTNONE);  

    //选择符合要求的圆
    acedSSGet(_T("X"), NULL, NULL, rb, ssname);
    long length;
    acedSSLength(ssname, (Adesk::Int32 *)&length);
    acutPrintf(_T("\n实体数:%d"), length);

    acutRelRb(rb);
}

        上面构建的过滤器,能够选择图形中半径大于或等于 30 的所有圆,其中的组码 40 用于指定圆的半径。过滤器列表中的关系运算符以DXF 组码- 4 来指示,用字符串来表示关系运算符。


D. 结合使用通配符和关系运算符,创建更为复杂的过滤器,添加新函数 Filter4()

    //结合使用通配符和关系运算符,创建更为复杂的过滤器
    void Filter4();
//结合使用通配符和关系运算符,创建更为复杂的过滤器
//选择图形中圆心在 pt1 和 pt2 两点构成的矩形内的圆,其中的组码 10 用于指定圆的圆心。
void CUserInteraction::Filter4()
{
    struct resbuf *rb; //结果缓冲区链表
    ads_name ssname;
    ads_point pt1 = { 0,0,0 };
    ads_point pt2 = { 100,100,0 };

    //选择图形中圆心在pt1和pt2两点构成的矩形内的圆
    rb = acutBuildList(RTDXF0,TEXT("CIRCLE"),//实体类型
        -4,_T(">,>,*"),  //关系运算符和通配符
        10,pt1,     //圆心;组码10用于指定圆的圆心
        -4,_T("<,<,*"),  //关系运算符和通配符
        10,pt2,  //圆心
        RTNONE);

    acedSSGet(_T("X"), NULL, NULL, rb, ssname);
    long length;
    acedSSLength(ssname, (Adesk::Int32 *)&length);
    acutPrintf(_T("\n实体数:%d"), length);

    acutRelRb(rb);
}

        上面构建的过滤器,能够选择图形中圆心在 pt1 和 pt2 两点构成的矩形内的圆,其中的
组码 10 用于指定圆的圆心。
E. 创建过滤扩展数据的过滤器,使用过滤器过滤扩展数据。添加新函数 Filter5()



        上面构建的过滤器,能够选择图形中所有包含“Xdata ”应用程序扩展数据的图元。令人遗憾的是,除轻量多段线之外,其他的实体都不支持扩展数据内容的过滤,也就是说,如果使用下面的代码:
rb = acutBuildList(1000,
                   "Road", // 扩展数据中的ASCII字符串
                   RTNONE);
        上面的过滤器仅能选择到图形中所有包含字符串“Road ”扩展数据的轻量多段线,其他类型的实体不起作用。
        讲到这里,相信你一定感觉在创建选择集过滤器时,如何获得所需要的组码是一个令人头疼的问题。

 

 

 

 

ObjectARX2015 + vs2012选择集
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 11:29 , Processed in 0.187541 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表