特征的基本概念
Pro/E是基于特征的参数化造型系统,在模型树上的每个项目都是特征。如下图所示:
该档案有3个基准面、1个坐标系、1个拉伸、1个孔共6个特征。
我们可以通过配置【树列】选项来查看特征的信息。
特征是对Pro/E模型中几何元素的一层封装。就好比你是负责指挥战争的司令官,你只会下达这样的命令:X师、Y师去攻打敌军的哪个部队,而不会详细到X师、Y师下的具体成员。特征就类似于师的概念,而师下面的每个战士就相当于是几何元素。
因此,我们可以遍历特征下的所有几何元素,Pro/TOOLKIT提供了这样的API:ProFeatureGeomitemVisit()。
特征的定义如下:
typedef struct pro_model_item
{
ProType type;
int id;
ProMdl owner;
}ProFeature;
它和ProModelitem共用相同的数据结构。其中
- type:值为PRO_FEATURE。
- id:特征ID。
- owner:特征所属的模型。
示例
代码如下:
// 实体模型特征访问函数
ProError SolidFeatVisitFunc(ProFeature* p_feature,
ProError status,
ProAppData app_data)
{
ProArrayObjectAdd((ProArray*)app_data, -1, 1, p_feature);
return PRO_TK_NO_ERROR;
}
// 命令响应函数:遍历访问实体档案中的特征
int VisitSolidFeats(uiCmdCmdId command,
uiCmdValue *p_value,
void *p_push_command_data)
{
ProError err;
// 获取当前模型
ProMdl mdlCurr;
err = ProMdlCurrentGet(&mdlCurr);
if (PRO_TK_NO_ERROR != err)
{
return -1;
}
// 定义数组存放特征
ProFeature* featArr;
err = ProArrayAlloc(0, sizeof(ProFeature), 5, (ProArray*)&featArr);
// 遍历访问模型下的所有特征
err = ProSolidFeatVisit((ProSolid)mdlCurr, SolidFeatVisitFunc, NULL, &featArr);
// 输出所有特征的信息
int nSize = 0;
err = ProArraySizeGet(featArr, &nSize);
CStringW cstrSize;
cstrSize.Format(L"当前模型共有%d个特征", nSize);
MessageBoxW(NULL, cstrSize, L"icaxdev: Sample002", MB_OK);
for (int i = 0; i < nSize; ++i)
{
ProName featName;
ProModelitemNameGet(&(featArr[i]), featName);
CStringW cstrFeatInfo;
cstrFeatInfo.Format(L"特征名称为:%s; 特征ID为:%d", featName, featArr[i].id);
MessageBoxW(NULL, cstrFeatInfo, L"icaxdev: Sample002", MB_OK);
}
// 释放数组空间
err = ProArrayFree((ProArray*)&featArr);
return 0;
}
代码说明
ProArray
ProArray是Pro/TOOLKIT中的动态数组,一般的使用步骤如下:
1. 初始化数组:ProArrayAlloc。
2. 往数组中新增或删除元素:ProArrayObjectAdd、ProArrayObjectRemove。
3. 使用完后释放数组空间:ProArrayFree。
ProArrayAlloc:初始化数组,为数组分配内存空间。
ProError ProArrayAlloc(
int n_objs,
int obj_size,
int reallocation_size,
ProArray* p_array);
- n_objs:数组的初始大小。一般传0即可。
- obj_size:数组元素的大小(单位为字节),一般传sizeof(元素类型)。比如数组存放的元素类型为int,传sizeof(int)即可。sizeof操作符会计算出类型占用的字节数。
- reallocation_size:当数组空间大小发生变化时,每次递增或递减的大小。如果你没有深入理解ProArray的内存实现,一般可以传5这个经验值。
- p_array:数组变量的地址。
ProArrayObjectAdd:往数组中添加元素。
ProError ProArrayObjectAdd(
ProArray* p_array,
int index,
int n_objects,
void* p_object);
- p_array:数组的地址。
- index:在何处添加元素,一般传-1,表明在数组最后添加元素。
- n_objects:添加元素的数量。
- p_object:要添加元素的地址。
ProArraySizeGet:获取数组的大小。
ProError ProArraySizeGet(
ProArray array,
int* p_size);
- array:数组。
- p_size:接收数组大小变量的地址。
ProArrayFree:释放数组内存空间。
ProError ProArrayFree(ProArray* p_array);
- p_array:数组的地址。
过滤函数和访问函数
在Pro/TOOLKIT中,如果你想遍历某个对象下的所有子对象,比如遍历实体档案下的所有特征,遍历特征下的所有面等等,需要用到过滤函数和访问函数。过滤函数和访问函数的原型已由Pro/TOOLKIT指定,你需要定义出它们具体的实现,然后将函数指针传递给对应的API。则父对象下的所有子对象都会依次被过滤函数和访问函数调用。如下图所示:
过滤函数就像一个漏斗,其返回值可以决定子对象是否继续被访问函数调用,当其返回值为PRO_TK_CONTINUE时,则不会被访问函数调用。当你只想访问某个对象下的子对象的一个子集时,过滤函数会派上用场。
下面我们以遍历实体模型下的所有特征为例来讲解过滤函数和访问函数。
ProSolidFeatVisit
ProSolidFeatVisit用于访问实体档案中的所有特征。
ProError ProSolidFeatVisit(
ProSolid p_handle,
ProFeatureVisitAction visit_action,
ProFeatureFilterAction filter_action,
ProAppData app_data);
- p_handle:实体模型。
- visit_action:访问函数指针。
- filter_action:过滤函数指针。
- app_data:传递给访问函数和过滤函数的数据。
访问函数的原型:
typedef ProError (*ProFeatureVisitAction)(ProFeature* p_feature,
ProError status,
ProAppData app_data);
- p_feature:被访问特征的指针。
- status:状态值,很少使用。
- app_data:ProSolidFeatVisit传递过来的数据(ProSolidFeatVisit的最后一个参数)。对于本示例程序而言,即为特征数组的指针:&featArr。
在示例程序中,我们定义了访问函数SolidFeatVisitFunc,将被访问的特征添加到数组。
过滤函数的原型:
typedef ProError (*ProFeatureFilterAction)(ProFeature* p_feature,
ProAppData app_data);
- p_feature:被访问特征的指针。
- app_data:ProSolidFeatVisit传递过来的数据(ProSolidFeatVisit的最后一个参数)。对于本示例程序而言,即为特征数组的指针:&featArr。
- 返回值:当返回值为PRO_TK_CONTINUE时,则当前p_feature指向的特征不会经过访问函数。当返回值为其它值时,返回值被传递给访问函数的第二个参数ProError status。
在示例程序中,我们没有定义过滤函数,直接传NULL。
扩展知识
强烈推荐使用C++标准模板库(STL)中的vector、list来替代ProArray。因为vector、list本身负责内存空间的分配与释放,并且使用起来也更方便友善。而使用ProArray的话,你需要手动申请与手动释放内存空间,使用不好很容易出错。
本次示例程序,使用vector替代ProArray的代码如下:
// 实体模型特征访问函数
ProError SolidFeatVisitFunc(ProFeature* p_feature,
ProError status,
ProAppData app_data)
{
vector<ProFeature>* pFeatVec = (vector<ProFeature>*)app_data;
pFeatVec->push_back(*p_feature);
return PRO_TK_NO_ERROR;
}
// 命令响应函数:遍历访问实体档案中的特征
int VisitSolidFeats(uiCmdCmdId command,
uiCmdValue *p_value,
void *p_push_command_data)
{
ProError err;
// 获取当前模型
ProMdl mdlCurr;
err = ProMdlCurrentGet(&mdlCurr);
if (PRO_TK_NO_ERROR != err)
{
return -1;
}
// 遍历访问模型下的所有特征
vector<ProFeature> vecFeat;
err = ProSolidFeatVisit((ProSolid)mdlCurr, SolidFeatVisitFunc, NULL, &vecFeat);
// 输出所有特征的信息
CStringW cstrSize;
cstrSize.Format(L"当前模型共有%d个特征", vecFeat.size());
MessageBoxW(NULL, cstrSize, L"icaxdev: Sample002", MB_OK);
vector<ProFeature>::iterator iterFeat = vecFeat.begin();
for (; iterFeat != vecFeat.end(); ++iterFeat)
{
ProName featName;
ProModelitemNameGet(&(*iterFeat), featName);
CStringW cstrFeatInfo;
cstrFeatInfo.Format(L"特征名称为:%s; 特征ID为:%d", featName, iterFeat->id);
MessageBoxW(NULL, cstrFeatInfo, L"icaxdev: Sample002", MB_OK);
}
return 0;
}