(31)ObjectARX2015 + vs2012选择集
1. 说明
//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 指定了所要操作的选择集
/*
//所谓对象选择的方法,就是以某种方式从图形窗口中获得满足某些条件的图形对象,用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 函数来手工销毁它。
//过滤器例子(多个过滤条件)
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。
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);
}
//选择对象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;
}
//选择指定多段线内部(或者与多段线构成的区域相交)的所有实体。//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;
}
void getSamplePoints( double fromParam, //fromParam是开始处的参数double toParam, //toParam是结束处的参数double approxEps, //approxEps是弦高误差AcGePoint3dArray& pointArray, //pointArray输出曲线上位于开始参数fromParam和AcGeDoubleArray& paramArray) const; //终止参数toParam之间的所有点的数组// paramArray输出与数组pointArray中的点相对应的参数数组。
// 这里所说的“参数”,是一个与长度有关的值,其具体含义Autodesk并未公开。
对一条多段线取样本点,能够得到类似下图所示的结果:
接下来的代码根据样本点创建结果缓冲区链表,在此之前,需要确保样本点数组中首尾两点不重合,其中的原因在前面已经介绍,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);
}
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);
}
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);
}
E. 创建过滤扩展数据的过滤器,使用过滤器过滤扩展数据。添加新函数 Filter5()
rb = acutBuildList(1000, "Road", // 扩展数据中的ASCII字符串RTNONE);
(31)ObjectARX2015 + vs2012选择集相关推荐
- (9)ObjectARX2015 + vs2012创建面域
提示:看之前的博客(1)和(4),那里已经分析了创建一个图形对象的基本过程,在之前的基础上本节开始就要将着眼点放在创建实体的参数上. (1)ObjectARX2015 + vs2012创建直线_qq_ ...
- (14)ObjectARX2015 + vs2012创建和编辑对象时的动态拖动技术
提示:看之前的博客(1)(4)和(12),那里已经分析了创建一个图形对象的基本过程,在之前的基础上本节开始就要将着眼点放在创建实体的参数上. (1)ObjectARX2015 + vs2012创建直线 ...
- CAD开发——AcadSelectionSet 选择集
1. 定义一个永不重复的时间变量 Private Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMT ...
- SAP QM初阶事务代码QA11对检验批做UD时出现很多UD Code的选择集?
SAP QM初阶事务代码QA11对检验批做UD时出现很多UD Code的选择集? 1,检验批890000000105,检验类型是89,它是一个使用QA01创建的检验批. 2, 执行事务代码QA11对该 ...
- SAP QM 执行事务代码QS51维护使用决策的选择集,系统报错 – Transaction no longer valid for catalog ‘3’ -
SAP QM 执行事务代码QS51维护使用决策的选择集,系统报错 – Transaction no longer valid for catalog '3' - 执行事务代码QS51,试图为工厂NMD ...
- [译] D3.js 嵌套选择集 (Nested Selection)
译者注: 原文: Mike Bostock (D3.js 作者) -- Nested Selections 译者: ssthouse 本文讲解的是关于 D3.js 中 d3-selection 的使用 ...
- 5 QM配置-质量计划配置-编辑缺陷类型的选择集
业务背景:编辑缺陷类型的选择集 事务码:QS51 SPRO路径:SPRO->质量管理->质量计划->基本信息->目录->编辑检验特征目录->编辑选择集 第1步,SP ...
- 3 QM配置-质量计划配置-编辑特性属性的选择集
业务背景:编辑特性属性的选择集 事务码:QS51 SPRO路径:SPRO->质量管理->质量计划->基本信息->目录->编辑检验特征目录->编辑选择集 第1步,SP ...
- jQuery——入门基础(获取元素、样式、属性,选择集、过滤器、样式类)
目录 Jquery的加载方法 获取元素 操作样式和属性 选择集和过滤器 选择集转移 绑定常用事件 操作样式类名 Jquery的加载方法 (1)$(document).ready(function(){ ...
最新文章
- java如何读取excel文件
- [翻译] NMock 简介
- $(@:_config=)的意思
- boost::geometry::detail::calculate_point_order用法的测试程序
- 如何在SAP Cloud for Customer页面嵌入自定义UI
- LeetCode 1169. 查询无效交易
- Redis 持久化——AOF
- 使用InstallShield下部署ASP.NET网站和MySQL,目标机为Win7——(二)使用InstallShield部署非安装版MySQL...
- node ajax配置文件,如何存储Node.js部署设置/配置文件?
- php逻辑难是难在sql,[实验吧] 所有web writeup
- 复杂sql 查询编写方法_学习SQL:如何编写复杂的SELECT查询
- python selenium自动化获取oracle_Python+selenium2 自动化测试登录
- 在Hadoop集群实施成功后再次格式化名称节点,datanode无法加入集群的处理办法...
- DHTML【3】--HTML
- [POJ3020]Antenna Placement(二分图最大匹配,最小边覆盖)
- 辣椒app软件测试,testflight辣椒视频
- AD19快速制作多管脚元件符号
- 数学——Lipschitz连续
- 什么叫UG编程?UG编程是干什么的?
- funcode实验--海底世界(c++实现)
热门文章
- CAD教程:CAD软件中怎么将图块改层?
- P4417 [COCI2006-2007#2] STOL
- 微信小程序 基本认识
- 读完这篇文章,颠覆你之前对硬盘开盘的认知!
- Google(谷歌)走了我们该用什么呢?
- TYVJ-P1035 棋盘覆盖
- 2012服务器系统显示这台电脑,两台windows server 2012 R2 服务器 故障:计算机已经从检测错误后重新启动。请问如何解决?...
- 【漫画】分享16张程序员高端漫画~
- ubuntu和windows之间实现复制粘贴
- redis为什么选择了跳跃表而不是红黑树