Skip to main content
1-Visitor
November 5, 2021
Question

Get all ProCsys in an assembly

  • November 5, 2021
  • 4 replies
  • 17252 views

In an assembly I want to visit all the ProCsys with a certain name and then get there coordinates. I have tried several examples which use ProSolidCsysVisit(), including the ProUtilCollectSolidCsys() and ProUtilCsysFind() functions. I know how to get the coordinates with the ProSelection typ by selecting a Csys with ProSelect() but now I have to use the ProCsys typ. But I also think I am not using the functions ProUtilCollectSolidCsys() and ProUtilCsysFind() correctly because I don´t get a list of ProCsys, only one value.

Can someone help me to understand this? There are also some things I didn´t find any explanation, like what is the "handle to the solid" or what does "PRO_TK_E_NOT_FOUND" mean?

 

Thanks a lot!
Tim

4 replies

17-Peridot
November 8, 2021

@Tim_1996,

 

Please use below APIs:

  1. Use API ProSolidCsysVisit() - To visit all CSYS features in model
  2. Use APIs ProCsysToGeomitem() and ProModelitemNameGet() in filter function of above API and visit only those CSYS features based on specific name of CSYS.
  3. Use API ProCsysDataGet() to get ProGeomitemdata csys_data. Extract origin of CSYS using csys_data->data.p_csys_data->origin

Answers to your additional questions:

1. What is 'handle to the solid'?

Ans.: Handle to solid is pointer to solid i.e. ProSolid

2. What does PRO_TK_E_NOT_FOUND means?

Ans.: If any API returns error PRO_TK_E_NOT_FOUND then, it means that API found 0 objects which that API is supposed to look for in specified model.

Tim_19961-VisitorAuthor
1-Visitor
November 8, 2021

Thank you very much, I will try it!

Maybe a stupid question but what exactly is a solid? 

17-Peridot
November 8, 2021

@Tim_1996,

 

Solid is nothing but, the solid model in Creo Parametric. Please read Toolkit User's Guide to understand more in detail about Creo Parametric Toolkit.

 

Also, please open separate threads or cases for each query so that individual questions would be addressed separately in different threads. 

21-Topaz I
November 8, 2021

Hi @Tim_1996 ,

because I did nothing the last 5 years with Toolkit possibly I do not remember accurately  but so far I remember .

You meant you can select the coordinate system with ProSelect . In this case to understand where is the CSYS you can check selection with ProSelectionAsmcomppathGet()  to get the Asmcomppath and print it to see  the direct assembly component level.

- is the CSYS an assembly feature or it is a feature in some part which has specific asmcomppath. The mentioned workflow by @rghadge    should work pretty good when the  csys feature is an assembly feature or you know that it is in part or subassembly and you have the handle of the mdl /solid

But let say if it is inside a component or subassembly ->in this case so far I remember what I did in the past something like this:

I did first call ProSolidFeatVisit  and  used a filter to check if  the feature is form type PRO_FEAT_COMPONENT 

IF yes then I will then

-check the workflow suggested by @rghadge   to find if the CSYS is inside of the current visited model. If not yes found and  stop - if not found yet  then continue with :

-check if the model is an assembly and call recursively the ProSolidFeatVisit . So  this  is one of the workflows what could be used when we search a specific CSYS feature in the assembly but we do not    not know where is it -> in Top assembly or in some part /subassembly component on some specific component level depth.

OK let remember a name of a feature could be not unique. Means we could have in different components / part a feature with the same name.

So  when I know the component path so I could e.g. take directly the part by ProAsmcomppathMdlGet() and then used the suggested workflow by  

@rghadge 

PS - the question what is ProSolid.

It is simple  casted ProMdl object handle to ProSolid .... some thing like      ....ProMdl mdl;      (ProSolid) mdl....    - but, please,  pay attention you can do this  cast only if you are sure that the ProMdl type is PRO_ASSEMBLY or PRO_PART (othewise such casting  do not make any sense)- so means before you will cast  ProMdl handle to ProSolid you can check the ProMdl type e.g. by the fucntion ProMdlTypeGet()

Tim_19961-VisitorAuthor
1-Visitor
November 10, 2021

I tried this way and it kind of worked but not the way I wanted. It visit some csys but only a few and I can't even find those csys in my Creo model. I think I have to go recursively in deeper subsystems, but I'm not sure. Here is what I have:

 

ProError FilterFunction(ProCsys p_csys, ProAppData app_data) {

 ProModelitem r_geom_item;
 ProName csysName;
 ProSolid model = ((UserCsysAppData*)app_data)->model;
 ProCsysToGeomitem(model, p_csys, &r_geom_item);
 ProModelitemNameGet(&r_geom_item, csysName);
 strcpy(((UserCsysAppData*)app_data)->csys_name, csysName);

 if(strcmp(csysName,"ENTRY")){
 return(PRO_TK_CONTINUE);
 }
 else {
 return(PRO_TK_NO_ERROR);
 }
}


ProError VisitActionFunction(ProCsys p_csys, ProError filter_return, ProAppData app_data) {

 if (filter_return == PRO_TK_NO_ERROR) {
 ProGeomitemdata* csys_data;
 ProCsysDataGet(p_csys, &csys_data); // get data
 int coor[3];
 coor[0] = csys_data->data.p_csys_data->origin[0];
 coor[1] = csys_data->data.p_csys_data->origin[1];
 coor[2] = csys_data->data.p_csys_data->origin[2];

 // write data
 FILE* fp;
 fp = fopen("Csys_data1.txt", "a");
 ProName csysName;
 strcpy(csysName, ((UserCsysAppData*)app_data)->csys_name);
 char* csysName2 = (char*)calloc(100, sizeof(char));
 ProWstringToString(csysName2, csysName);
 fprintf(fp, "%s\t\t%d\t%d\t%d\n", csysName2, coor[0], coor[1], coor[2]);
 fclose(fp);

 return(PRO_TK_NO_ERROR);
 }
}


ProMdl model;
UserCsysAppData	app_data;
status = ProMdlCurrentGet(&model);
app_data.model = model;
status = ProSolidCsysVisit((ProSolid)model, (ProCsysVisitAction)VisitActionFunction, (ProCsysFilterAction)FilterFunction, (ProAppData)&app_data);

 

If I understand it correctly, ProSolidCsysVisit() gets the first Csys possible and then calls the filter function. The filter decides if the action function does something with that csys or not. What I don't understand is how ProSolidCsysVisit() navigates through the different Csys and where I need to do a recursive action to get ALL the Csys in the assembly.

RPN
18-Opal
November 9, 2021

PRO_TK_E_NOT_FOUND will be returned if the call was successfully but no data was found.

SOLID, I would say a solid is everything where the Creo file extension is either '.PRT' (model type PRO_PART) or '.ASM' (model type PRO_ASSEMBLY)

Tcl Code less than 30 lines (in a colored image, after that clear uncolored code) follows, C logic is very similar > 30 lines 😀, even if you use your own filter function

GetCsysByNames.png

 

 

 

 

# Side effects
# Each component is checked 
# and the point data is not transformed
# to the top level assembly
#
# Function Input:
# FP	: The handle to the open file
# MDL	: The Name of the Solid Model
# Pat	: The pattern to match, e.g A* match ACSYS
proc Get_Csys_Match {FP MDL PAT} {
	foreach GEOM_ID [ps_visit csys -model $MDL] {
		# Get the Feature ID for this geom id
		set FEAT_ID [ps_geom to_feat_ids -model $MDL -- CSYS $GEOM_ID]
		# Get the Feature Name
		set FEAT_NAME [ps_feat name -model $MDL -- $FEAT_ID]
		# Now the Match check
		# Here do a match of the csys name by the given pattern
		# if not match, continue
		if {![string match -nocase $PAT $FEAT_NAME]} {
			continue
		}
		# Prepare the Output
		set Record [list $MDL $FEAT_NAME]
		# Get the Csys Data to an csysObj 
		ps_data csys -model $MDL -- $GEOM_ID CsysData 
		# extract each vector, skip origin and other data
		foreach vector [list xvector yvector zvector origin] {
			# from the csysObj extract the 3D point data to an pointObj 
			CsysData $vector Point
			# lappend the 3D Values by expanding to the output record list
			lappend Record {*}[Point 3d_values]
		}
		# write the data in our file, use ',' as an seperator
		puts $FP [join $Record ,]
	}
}

# Function Input:
# FP	: The handle to the open file
# ASM	: The Name of the Assembly
# Pat	: The pattern to match, e.g A* match ACSYS
proc Get_Assy_Csys_Match {FP ASM PAT} {
	# Get it for the assembyl as well
	Get_Csys_Match	$FP $ASM $PAT
	# Vist the given assembly, get all feature IDs 
	# where the feature type is a component
	foreach FID [ps_visit type -model $ASM -- COMPONENT] {
		# Get the model name from this feature ID
		set MDL [ps_assy component_name -model $ASM -- $FID ]
		# Now get all Geom ID from each CSYS in this Solid
		# No filter for sub types like skeleton, ... 
		Get_Csys_Match	$FP $MDL $PAT
		# Recursive Call
		# If the model is an assembly, 
		# search in this assembly as well
		if { [ps_model is_assembly -model $MDL]} {
			Get_Assy_Csys_Match	$FP $MDL $PAT
		}

	}
	# Done and return
	return
}

proc CSYS_Test {} {
	# The Pattern to search for
	set PAT	A*
	# use the current active Model
	set MODEL [ps_model cur]
	# Prepare the filename
	set outname [format "%s_csys_data.csv" $MODEL]
	# open the file
	set FP [open $outname w]
	# write the header, use ',' as an seperator
	puts $FP [join [list Model CsysName xvecx xvecy xvecz yvecx yvecy yvecz zvecx zvecy zvecz ovecx ovecy ovecz] ,]
	# get the data
	Get_Assy_Csys_Match $FP $MODEL $PAT
	# close the file
	close $FP
	# Done and return
	return
}
# just call it
CSYS_Test

 

 

 

 

Sample Out

 

SampleOut.png

 

Have fun 😇