在应用开发中,遍历特征树是常见需求,通过遍历特征结构树,可以获取大量信息。这里给出一个遍历函数,供参考。
函数采用递归算法,从给出的特征出发,遍历以该特征为根的特征树,如果根是零部件, 遍历整个零部件特征。
适当修改,即可完成特定特征对象的搜索。
这里有两个函数,第一个GetRootObject()可以获取根特征,这里根特征可以是Part和Product。
参数CATDocument *pDoc可以根据之前的方法获取。
第二个函数:void NavigateSpecTree(CATISpecObject_var spObject,CATUnicodeString path)的第一个参数由函数1获取,
第二个参数为初始值为“”。这个参数是为了在递归调用时,记录特征的路径。
CATISpecObject_var GetRootObject(CATDocument *pDoc)
{
HRESULT rc;
CATISpecObject_var spRoot;
if (pDoc==NULL)
{
CATUnicodeString hint="GetDocument Failed";
MessageBox(NULL ,hint,_T("提醒" ), MB_OK);
return NULL_var ;
}
CATUnicodeString type;
type=pDoc->GetType();
if (type=="CATProduct")
{
CATIDocRoots* piDocRootsOnDoc=NULL;
rc=pDoc->QueryInterface(IID_CATIDocRoots,(void**)&piDocRootsOnDoc);
if (FAILED(rc)||piDocRootsOnDoc==NULL) return NULL_var;
CATListValCATBaseUnknown_var *pRootProducts;
pRootProducts=piDocRootsOnDoc->GiveDocRoots();
piDocRootsOnDoc->Release();
piDocRootsOnDoc=NULL;
if (pRootProducts==NULL) return NULL_var;
CATIProduct_var spRootProduct=NULL_var;
spRootProduct=(*pRootProducts)[1];
CATIProduct *piProductOnRoot=NULL;
rc=spRootProduct->QueryInterface(IID_CATIProduct,(void**)&piProductOnRoot);
if (FAILED(rc)||piProductOnRoot==NULL) return NULL_var;
spRoot=piProductOnRoot;
}
else {
CATInit *pDocAsInit = NULL ;
rc = pDoc->QueryInterface(IID_CATInit, (void**)&pDocAsInit);
if ( FAILED(rc) )
{
CATUnicodeString hint="CATInit Failed";
MessageBox(NULL ,hint,_T("提醒" ), MB_OK);
return NULL_var ;
}
CATIPrtContainer *pSpecContainer = NULL ;
pSpecContainer = (CATIPrtContainer*)pDocAsInit->GetRootContainer("CATIPrtContainer");
if ( NULL == pSpecContainer )
{
CATUnicodeString hint="Get CATIPrtContainer Failed";
MessageBox(NULL ,hint,_T("提醒" ), MB_OK);
return NULL_var ;
}
pDocAsInit->Release();
pDocAsInit = NULL ;
spRoot = pSpecContainer->GetPart() ;
if ( NULL_var == spRoot )
{
CATUnicodeString hint="GetPart Failed";
MessageBox(NULL ,hint,_T("提醒" ), MB_OK);
return NULL_var ;
}
pSpecContainer->Release();
pSpecContainer = NULL ;
}
return spRoot;
}
void NavigateSpecTree(CATISpecObject_var spObject,CATUnicodeString path)
{
if (spObject==NULL_var)
return;
else {
CATIDescendants_var spDescendants=spObject;
CATListValCATISpecObject_var spDescendantsList;
CATUnicodeString title,type="",disName;
disName=spObject->GetName();
type=spObject->GetType();
if (type=="MechanicalPart") path="";
if (path.GetLengthInChar()>1) path.Append("\\");
path.Append(disName);
if (type=="ASMPRODUCT")
{
cout<<"ASMPRODUCT"<<endl;
CATIProduct_var spProductOnRoot=spObject;
CATListValCATBaseUnknown_var *childrenList=spProductOnRoot->GetChildren();
//piProductOnRoot->Release();
//piProductOnRoot=NULL;
if (childrenList==NULL)
{
CATUnicodeString hint1="当前文档没有Part或Product";
MessageBox(NULL ,hint1,_T("提醒" ), MB_OK);
return;
}
int size=childrenList->Size();
CATIProduct_var spChild;
CATUnicodeString nm;
for (int i=1;i<=size;i++)
{
spChild=(*childrenList)[i];
spChild->GetPrdInstanceName(nm);
CATIProduct_var pRef;
pRef=spChild->GetReferenceProduct();
CATILinkableObject *pLink=NULL;
pRef->QueryInterface(IID_CATILinkableObject,(void**)&pLink);
CATDocument *pDoc1;
pDoc1=pLink->GetDocument();
pLink->Release();
pLink=NULL;
if (pDoc1==NULL) return;
CATISpecObject_var spPart=GetRootObject(pDoc1);
path.Append("\\");path.Append(nm);
NavigateSpecTree(spPart,path);
}
}
else {
if (type!=NULL&&disName!=NULL)
cout<<path.ConvertToChar()<<" Type:"<<type.ConvertToChar()<<" Name:"<<disName.ConvertToChar()<<endl;
if (spDescendants!=NULL)
{
spDescendants->GetDirectChildren("CATISpecObject",spDescendantsList);
if (spDescendantsList!=NULL)
for (int i=1;i<=spDescendantsList.Size();i++) {
NavigateSpecTree(spDescendantsList[i],path);
}
else {
//cout<<"spDescendantsList is Null"<<endl;
CATILinkableObject *pLinkable;
CATDocument *pDoc;
spDescendants->QueryInterface(IID_CATILinkableObject,(void**)&pLinkable);
pDoc=pLinkable->GetDocument();
//cout<<"Doc:"<<pDoc->DisplayName()<<endl;
}
} //else cout<<"spDescendants is Null"<<endl;
}
}
}
通过这两个函数,就可以遍历整个零件或产品文档。
执行结果,输出特征的名称、类型的信息。程序在CATIA V5 CAA 2012上调试通过。