The following examples demonstrate how to build, create, modify and redefine Creo features directly from Tcl, including the placement of a UDF – all without compiling a single line of code.
Note: The feature tree structure and its underlying element types are defined by PTC. p-Shell provides a Tcl interface to build, manipulate and maintain a representation of this structure. Before feature creation, the feature tree is temporary. After creation, it is re-parsed from the actual Creo feature tree; when redefining a feature, its feature ID remains unchanged. Selection objects are restored by their original names, provided those names have not been changed.
For clarity and readability, the example scripts omit error handling and focus on the functionality being demonstrated.
More information you will find here: Tcl for Creo
p-Shell provides Tcl representations for several Creo object types. The following three are particularly useful when working with model geometry and assembly structures:
All three types are available as Tcl object commands.
Let’s start with a datum point created at the intersection of an axis and a planar surface. The following example demonstrates how to build and manipulate a Creo feature tree directly from Tcl.
# This example demonstrates how to: # # - Build a feature tree for a Creo datum point. # - Create a feature using user-defined selections. # - Reuse the same feature tree with different selections. # - Modify individual feature tree elements. # - Redefine an existing feature using the modified tree. # # Create a feature tree object for a datum point named 'PSPNT1'. ps_ftree ftObjDtmPnt # on rerun, destroy the tree, '.' is the tree root # if we don't destroy we need to configure # each item path .1 .2 .... ftObjDtmPnt delete . # Get a unique name by increment an counter set n [incr ::PntCounter] # Selection objects are created automatically when referenced # in the feature tree, if they do not already exist. # In this example, two selection objects are used: # ::PS::FTREE::SEL.Axis # ::PS::FTREE::SEL.Surface # # They will hold the references to the axis and surface # used to define the datum point. # # Build the feature tree. # The following structure was extracted from an existing # Creo datum point of the same type using the 'get' subcommand. ftObjDtmPnt insert .1 -type FEATURE_TYPE -map_integer DATUM_POINT ftObjDtmPnt insert .2 -type DPOINT_TYPE -integer -1 ftObjDtmPnt insert .3 -type STD_FEATURE_NAME -wstring PSPNT ftObjDtmPnt insert .4 -type DPOINT_POINTS_ARRAY -array ftObjDtmPnt insert .4.1 -type DPOINT_POINT -compound ftObjDtmPnt insert .4.1.1 -type DPOINT_POINT_NAME -wstring PSPNT$n ftObjDtmPnt insert .4.1.2 -type DPOINT_PLA_CONSTRAINTS -array ftObjDtmPnt insert .4.1.2.1 -type DPOINT_PLA_CONSTRAINT -compound ftObjDtmPnt insert .4.1.2.1.1 -type DPOINT_PLA_CONSTR_REF -selection ::PS::FTREE::SEL.Axis ftObjDtmPnt insert .4.1.2.1.2 -type DPOINT_PLA_CONSTR_TYPE -integer 0 ftObjDtmPnt insert .4.1.2.1.3 -type DPOINT_PLA_CONSTR_VAL -double 0.0 ftObjDtmPnt insert .4.1.2.2 -type DPOINT_PLA_CONSTRAINT -compound ftObjDtmPnt insert .4.1.2.2.1 -type DPOINT_PLA_CONSTR_REF -selection ::PS::FTREE::SEL.Surface ftObjDtmPnt insert .4.1.2.2.2 -type DPOINT_PLA_CONSTR_TYPE -integer 0 ftObjDtmPnt insert .4.1.2.2.3 -type DPOINT_PLA_CONSTR_VAL -double 0.0 ftObjDtmPnt insert .4.1.3 -type DPOINT_DIM_CONSTRAINTS -array # # Ask the user to select the axis and the surface. # # Alternatively, you can configure the selection objects # programmatically and provide the references directly. # # For simplicity, we let the user make the selections here. # # Displays a message in the status line at the bottom of # the Creo window, informing the user what is expected. # The message can optionally be accompanied by an icon # indicating Warning, Error, or Critical. ps_mess “Please select an axis.” ::PS::FTREE::SEL.Axis select axis ps_mess “Please select a planar surface.” ::PS::FTREE::SEL.Surface select surface # Create the datum point. # After creation, pShell reparses the feature tree. ftObjDtmPnt create # Retrieve the ID of the newly created feature. set FID [ftObjDtmPnt cget -id] # # The same feature tree can be reused to create another datum point. # However, each feature requires its own selection objects, # since they are associated with different feature IDs. # # Due to the reparse, we need to retrieve the selection objects # again from the updated tree. # # The tree structure and element order remain unchanged: # .4.1.2.1.1 holds the axis reference. # .4.1.2.2.1 holds the surface reference. # Keep the same axis, but select a different surface. # Retrieve the surface selection object and change its contents. set CurSelSurface [ftObjDtmPnt itemcget .4.1.2.2.1 -value] ps_mess “Please select a planar surface.” $CurSelSurface select surface # Create another datum point using the updated selection. ftObjDtmPnt create # refresh the window ps_wind # # You can also modify individual elements of the feature tree. # Here we change the axis reference to a different selection object. # ftObjDtmPnt itemconfigure .4.1.2.1.1 -selection ::PS::FTREE::SEL.NewAxis # Ask the user to select the new axis. ps_mess “Please select an axis.” ::PS::FTREE::SEL.NewAxis select axis # # Redefine the existing datum point using the new axis. # The same feature tree object is reused. # ftObjDtmPnt redefine # refresh the window ps_wind
The main procedure handles feature creation, while the sketch definition is separated into its own procedure, supported by a helper procedure.
#
# Warning:
# This script deletes all existing
# features in the current model first!
#
# Objective:
# Create the first extrusion in a Creo model
#
proc Create_First_Feature {} {
##
# Shortcut to the Feature Tree Command
##
set f ftree
##
# Get the current model (a Part is assumed)
##
set model [ps_model current]
##
# empty model - this is our FIRST_FEAT
##
ps_feat delete -model $model [ps_feat list -model $model]
##
# Convert the model to a modelitem
# Note: The miObj is created on the fly
# You don't need to call
# ps_modelitem miObj before
##
ps_model to_modelitem -model $model -- miObj
##
# Create a selection object and assign the modelitem.
# The selection object refers to miObj rather than keeping
# an independent copy.
# If miObj changes, selObj is reconfigured and updated
# the next time it is used.
##
ps_sel selObj -modelitem miObj
##
# Create a feature treeObj
# Just for the demo, delete and configure again
# Note: Calling the command twice in row will not raise an error
# ps_ftree TestFTree
# ps_ftree TestFTree
# but calling now
# ps_ftree selObj
# will raise an error, because selObj is a Selection command
# Here ps_obj is introduced, if you want to make sure to have a fresh tree
##
if [ps_obj exists $f] {
ps_obj delete $f
}
ps_ftree $f
##
# Set the model you want to work on
# rather to use the currently active one
##
$f config -selection selObj
##
# Available creation options:
# NONE, DEFINE_MISS_ELEMS, INCOMPLETE_FEAT,
# FIX_MODEL_IF_FAIL and DO_NOT_DISPLAY.
# Specify the desired options as a list.
# The default is NONE.
##
$f config -options INCOMPLETE
##
# Note:
# Before you start, create the feature you want
# and get the tree from the existing feature id
# ps_ftree ftree -id 233
# ftree get -> will now return the tree data
#
# Insert feature incomplete data
# The nodes names are integer values
# On creation you can use your own naming
# like for the widgets and toplevel
# but on 'visit' or 'get', only numerical are used
# and returned
#
##
$f insert .1 -type FEATURE_TYPE -map FIRST_FEAT
$f insert .2 -type FEATURE_FORM -map EXTRUDE
$f insert .3 -type STD_EXT_DEPTH -compound
$f insert .3.1 -type EXT_DEPTH_FROM -compound
$f insert .3.1.1 -type EXT_DEPTH_FROM_TYPE -integer 262144
$f insert .3.1.2 -type EXT_DEPTH_FROM_VALUE -double 120.0
$f insert .3.2 -type EXT_DEPTH_TO -compound
$f insert .3.2.1 -type EXT_DEPTH_TO_TYPE -integer 0
$f insert .3.2.2 -type EXT_DEPTH_TO_VALUE -double 0.0
##
# Create the incomplete feature
# The nodes above may the minimum required
#
# After this call, the underlying tree is updated
# and a handle to the 2D section for sketching is available
# See the complete tree at the bottom of this script documentation
# After this call,
##
set success [$f create]
##
# Retrieve the sketcher section handle from the updated
# feature tree.
# This demonstrates how to get a node/element value
# from an existing feature tree.
##
set HaveSketch [Get_Root_Children_Value_From $f sketcher sketcherObj ]
if { $HaveSketch == 0 } {
return 0
}
##
# Now add items to the sketch
##
Create_Section $sketcherObj
# Configure the creation options
$f config -options none
# Create the feature
# by the redefined tree
# Now after having the full feature tree
# and a Sketch with geometry
# create the first feature
# the workflow is similar to the one
# if you do that in Creo by yourself
$f redefine
# refit the window, rather a simple refresh
#
ps_wind refit $model
set fid [$f cget -id]
return $fid
}
##
# Helper to retrieve a value from a root-level child.
# The proc will not find sub level items/elements
# Walk through all root children and search for the
# specified type.
# Return 1 on success or 0 if the type is not found.
# Store the retrieved value in the variable passed
# by name.
#
# ftree the feature tree
# GetType the requested node type
# from cbr_value, a variable passed by ((Call by) reference
##
proc Get_Root_Children_Value_From {ftree GetType cbr_value} {
# use the root node '.'
set RootChildren [$ftree child .]
# The type values are all in upper
set GETTYPE [string toupper $GetType]
# now search for the given upper string
foreach child $RootChildren {
set ITEMTYPE [$ftree itemcget $child -type]
if { $ITEMTYPE eq $GETTYPE } {
upvar $cbr_value Value
set Value [$ftree itemcget $child -value]
return 1
}
}
return 0
}
##
# Create the sketch entities:
# five lines and an arc.
#
# Both ps_line and ps_arc support the -is_construction option.
# ps_arc also supports the -type option.
# The type can be either ARC or CIRCLE.
#
# For a CIRCLE, the start and end points are ignored.
# For an ARC, the -is_construction flag is ignored.
##
proc Create_Section {sketchObj} {
set width 300
set height 250
set bite_r 20
set bite_h 30
set bhmbr [expr $bite_h - $bite_r]
set bhpbr [expr $bite_h + $bite_r]
for {set i 1 } {$i < 6} {incr i} {
# reuse, no delete here
ps_line l$i
}
l1 2d_values [list 0.0 0.0 $width 0.0 ]
l2 2d_values [list $width 0.0 $width $height ]
l3 2d_values [list $width $height 0.0 $height ]
l4 2d_values [list 0.0 $height 0.0 $bhpbr ]
l5 2d_values [list 0.0 $bhmbr 0.0 0.0 ]
# create the arc
ps_arc a1 -xo 0.0 -yo $bite_h -radius $bite_r -start_angle 270 -end_angle 90
# Add this to the 2D Sketch
foreach item [list l1 l2 l3 l4 l5 a1] {
$sketchObj create [string tolower [$item cget -type]] $item
}
$sketchObj auto_dim
$sketchObj regen
return
}
.1 -type FEATURE_TYPE -map_integer FIRST_FEAT
.2 -type FEATURE_FORM -map_integer EXTRUDE
.3 -type STD_FEATURE_NAME -wstring EXTRUDE_1
.4 -type EXT_SURF_CUT_SOLID_TYPE -integer 917
.5 -type REMOVE_MATERIAL -integer 0
.6 -type BODY -compound
.6.1 -type TARGET_BODY -integer 2
.6.2 -type TOOL_BODIES -selection ::PS::FTREE::SEL.4
.7 -type IS_SMT_CUT -integer 0
.8 -type SMT_CUT_NORMAL_DIR -integer 0
.9 -type SKETCHER -pointer ::PS::FTREE::SKETCH.4
.10 -type STD_SECTION -compound
.10.1 -type STD_SEC_METHOD -integer 0
.10.2 -type SEC_USE_SKETCH -selection {}
.10.3 -type STD_SEC_SELECT -compound
.10.3.1 -type STD_CURVE_COLLECTION_APPL -selection {}
.10.3.2 -type SURF_CHAIN_CMPND -compound
.10.3.2.1 -type SURF_CHAIN_METHOD -integer 0
.10.3.2.2 -type SURF_CHAIN_REF_SURFS -array
.10.3.2.2.1 -type SURF_CHAIN_SURF -compound
.10.3.2.2.1.1 -type SURF_CHAIN_REF -selection {}
.10.3.3 -type STD_SEC_BLN_VERTS -selection {}
.10.4 -type STD_SEC_SETUP_PLANE -compound
.10.4.1 -type STD_SEC_PLANE -selection {}
.10.4.2 -type STD_SEC_PLANE_VIEW_DIR -integer 0
.10.4.3 -type STD_SEC_PLANE_ORIENT_DIR -integer 0
.10.4.4 -type STD_SEC_PLANE_ORIENT_REF -selection {}
.10.5 -type SKETCHER
.11 -type FEAT_FORM_IS_THIN -integer 0
.12 -type STD_MATRLSIDE -integer 0
.13 -type THICKNESS -double 0.0
.14 -type SRF_END_ATTRIBUTES -integer 0
.15 -type TRIM_QUILT -selection {}
.16 -type TRIM_QLT_SIDE -integer 0
.17 -type STD_DIRECTION -integer 0
.18 -type STD_EXT_DEPTH -compound
.18.1 -type EXT_DEPTH_FROM -compound
.18.1.1 -type EXT_DEPTH_FROM_TYPE -integer 0
.18.1.2 -type EXT_DEPTH_FROM_VALUE -double 120.0
.18.1.3 -type EXT_DEPTH_FROM_REF -selection {}
.18.1.4 -type EXT_DEPTH_FROM_REF_TRF -integer 0
.18.1.5 -type EXT_DEPTH_FROM_REF_TRF_VAL -double 0.0
.18.2 -type EXT_DEPTH_TO -compound
.18.2.1 -type EXT_DEPTH_TO_TYPE -integer 0
.18.2.2 -type EXT_DEPTH_TO_VALUE -double 0.0
.18.2.3 -type EXT_DEPTH_TO_REF -selection {}
.18.2.4 -type EXT_DEPTH_TO_REF_TRF -integer 0
.18.2.5 -type EXT_DEPTH_TO_REF_TRF_VAL -double 0.0
.19 -type INT_PARTS
.20 -type PATTERN
.21 -type STD_SMT_THICKNESS -double 0.0
.22 -type STD_SMT_SWAP_DRV_SIDE -integer 0
.23 -type SMT_WALL_SHARPS_TO_BENDS -integer 0
.24 -type SMT_PUNCH_AXIS_PNT -integer 0
.25 -type SMT_FILLETS -compound
.25.1 -type SMT_FILLETS_SIDE -integer 0
.25.2 -type SMT_FILLETS_VALUE -double 0.0
.26 -type SMT_DEV_LEN_CALCULATION -compound
.26.1 -type SMT_DEV_LEN_SOURCE -integer 0
.26.2 -type SMT_DEV_LEN_Y_FACTOR -compound
.26.2.1 -type SMT_DEV_LEN_Y_FACTOR_TYPE -integer 0
.26.2.2 -type SMT_DEV_LEN_Y_FACTOR_VALUE -double 0.0
.26.3 -type SMT_DEV_LEN_BEND_TABLE -integer 0
.27 -type SMT_PUNCH_TOOL_DATA -compound
.27.1 -type SMT_PUNCH_TOOL_ATTR -integer 0
.27.2 -type SMT_PUNCH_TOOL_NAME -wstring
.28 -type SMT_MERGE_DATA -compound
.28.1 -type SMT_MERGE_AUTO -integer 0
.28.2 -type SMT_MERGE_KEEP_LINES -integer 0
.28.3 -type SMT_MERGE_KEEP_BEND_EDGES -integer 0
.29 -type EXT_COMP_DRFT_ANG -compound
.29.1 -type EXT_DRFT_ANG -integer -1
.29.2 -type EXT_DRFT_ANG_VAL -double 0.0
.30 -type FEAT_THIN -compound
.30.1 -type FEAT_THIN_STRT -compound
.30.1.1 -type FEAT_THIN_STRT_OPT -integer 0
.30.1.2 -type FEAT_THIN_STRT_REF -selection {}
.30.2 -type FEAT_THIN_END -compound
.30.2.1 -type FEAT_THIN_END_OPT -integer 0
.30.2.2 -type FEAT_THIN_END_REF -selection {}
ProError CreoFirstFeatureCreate()
{
ProErrorlist errors;
ProMdl model;
ProModelitem model_item;
ProSelection model_sel;
ProFeature feature;
ProFeatureCreateOptions *opts = 0;
ProElempath path;
ProElempathItem path_items[2];
ProSection section;
ProAsmcomppath comp_path;
ProAsmcomppath *p_comp_path = NULL;
ProValue value;
ProValue new_value;
ProElement sketch_element;
ProElement created_elemtree;
ProElement pro_e_feature_tree;
ProElement pro_e_feature_type;
ProElement pro_e_feature_form;
ProElement pro_e_feat_form_is_thin;
ProElement pro_e_thickness;
ProElement pro_e_std_ext_depth;
ProElement pro_e_ext_depth_from;
ProElement pro_e_ext_depth_from_type;
ProElement pro_e_ext_depth_from_value;
ProElement pro_e_ext_depth_to;
ProElement pro_e_ext_depth_to_type;
ProElement pro_e_ext_depth_to_value;
ProElement pro_e_sketcher;
ProError status;
ProValueData value_data;
ProSelection * p_select;
int n_select;
ProStringToWstring ( message_file, "utilities.txt" );
log_file = PTApplsUnicodeFopen ( "ug_sketched_curve.log", "w" );
/*---------------------------------------------------------------*\
Populating root element PRO_E_FEATURE_TREE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_FEATURE_TREE, &pro_e_feature_tree );
/*---------------------------------------------------------------*\
Populating element PRO_E_FEATURE_TYPE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &pro_e_feature_type );
status = ProElementIntegerSet(pro_e_feature_type,PRO_FEAT_FIRST_FEAT);
status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_feature_type );
/*---------------------------------------------------------------*\
Populating element PRO_E_FEATURE_FORM
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_FEATURE_FORM, &pro_e_feature_form );
status = ProElementIntegerSet(pro_e_feature_form,PRO_EXTRUDE);
status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_feature_form );
/*---------------------------------------------------------------*\
Populating compound element PRO_E_STD_EXT_DEPTH
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_STD_EXT_DEPTH, &pro_e_std_ext_depth );
status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_std_ext_depth );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_FROM
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_FROM, &pro_e_ext_depth_from );
status = ProElemtreeElementAdd ( pro_e_std_ext_depth, NULL, pro_e_ext_depth_from );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_FROM
-> PRO_E_EXT_DEPTH_FROM_TYPE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_FROM_TYPE, &pro_e_ext_depth_from_type );
status = ProElementIntegerSet(pro_e_ext_depth_from_type,PRO_EXT_DEPTH_FROM_BLIND);
status = ProElemtreeElementAdd ( pro_e_ext_depth_from, NULL, pro_e_ext_depth_from_type );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_FROM
-> PRO_E_EXT_DEPTH_FROM_VALUE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_FROM_VALUE, &pro_e_ext_depth_from_value );
status = ProElementDecimalsSet( pro_e_ext_depth_from_value,4 );
status = ProElementDoubleSet(pro_e_ext_depth_from_value,120.000000);
status = ProElemtreeElementAdd ( pro_e_ext_depth_from, NULL, pro_e_ext_depth_from_value );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_TO
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_TO, &pro_e_ext_depth_to );
status = ProElemtreeElementAdd ( pro_e_std_ext_depth, NULL, pro_e_ext_depth_to );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_TO
-> PRO_E_EXT_DEPTH_TO_TYPE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_TO_TYPE, &pro_e_ext_depth_to_type );
status = ProElementIntegerSet(pro_e_ext_depth_to_type,PRO_EXT_DEPTH_TO_BLIND);
status = ProElemtreeElementAdd ( pro_e_ext_depth_to, NULL, pro_e_ext_depth_to_type );
/*---------------------------------------------------------------*\
Populating element PRO_E_STD_EXT_DEPTH
-> PRO_E_EXT_DEPTH_TO
-> PRO_E_EXT_DEPTH_TO_VALUE
\*---------------------------------------------------------------*/
status = ProElementAlloc ( PRO_E_EXT_DEPTH_TO_VALUE, &pro_e_ext_depth_to_value );
status = ProElementDecimalsSet( pro_e_ext_depth_to_value,4 );
status = ProElementDoubleSet(pro_e_ext_depth_to_value,0.0);
status = ProElemtreeElementAdd ( pro_e_ext_depth_to, NULL, pro_e_ext_depth_to_value );
/*---------------------------------------------------------------*\
Creating incomplete feature in the current model.
\*---------------------------------------------------------------*/
status = ProMdlCurrentGet (&model);
if ( status != PRO_TK_NO_ERROR ) return ( status );
status = ProMdlToModelitem( model, &model_item );
status = ProSelectionAlloc (p_comp_path, &model_item,
&model_sel);
status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions), 1, (ProArray*)&opts);
opts[0]= PRO_FEAT_CR_INCOMPLETE_FEAT;
status = ProFeatureWithoptionsCreate (model_sel, pro_e_feature_tree, opts, PRO_REGEN_NO_FLAGS, &feature, &errors);
status = ProArrayFree((ProArray*)&opts);
/* Using the element tree from created feature */
status = ProFeatureElemtreeExtract (&feature, NULL, PRO_FEAT_EXTRACT_NO_OPTS, &created_elemtree);
/*---------------------------------------------------------------*\
Getting the initialized section element from the database.
\*---------------------------------------------------------------*/
/* path to PRO_E_SKETCHER element */
path_items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
path_items[0].path_item.elem_id = PRO_E_SKETCHER;
status = ProElempathAlloc (&path);
status = ProElempathDataSet (path, path_items, 1);
status = ProElemtreeElementGet ( created_elemtree, path, &sketch_element);
status = ProElementSpecialvalueGet(sketch_element, NULL, (ProAppData *) §ion);
double section_eps;
status = ProSectionEpsilonGet (section,§ion_eps);
/*---------------------------------------------------------------*\
Creating a 3-D section
\*---------------------------------------------------------------*/
status = UserSectionFirstFeatureBuild (( ProSection * )(§ion) );
/*---------------------------------------------------------------*\
Allocating and assigning new ProValue to sketcher element
:: Wildfire requirement
\*---------------------------------------------------------------*/
status = ProElementSpecialvalueSet(sketch_element, (ProAppData) section);
ProElempathFree (&path);
/*---------------------------------------------------------------*\
Redefining the feature to make it complete.
\*---------------------------------------------------------------*/
status = ProSelectionAsmcomppathGet (model_sel, &comp_path);
status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions), 1, (ProArray*)&opts);
opts[0]= PRO_FEAT_CR_DEFINE_MISS_ELEMS;
status = ProFeatureWithoptionsRedefine (&comp_path, &feature, created_elemtree, opts, PRO_REGEN_NO_FLAGS, &errors);
status = ProArrayFree((ProArray*)&opts);
/*---------------------------------------------------------------*\
Free up the allocated memory.
\*---------------------------------------------------------------*/
status = ProFeatureElemtreeFree (&feature, created_elemtree );
status = ProElementFree (&pro_e_feature_tree );
return (status);
}
ProError UserSectionFirstFeatureBuild ( ProSection * section_here )
{
Pro2dLinedef line;
ProError status;
int line_id[4];
ProName section_name;
ProWSecerror section_errors1;
ProWSecerror section_errors2;
ProWSecerror section_errors3;
int n_sec;
ProMsg error_message;
char error_message_s[100];
int i, error_id;
status = ProSecerrorAlloc ( §ion_errors1 );
status = ProSecerrorAlloc ( §ion_errors2 );
status = ProSecerrorAlloc ( §ion_errors3 );
status = ProSection2DAlloc ( section_here );
ProTKPrintf("The status for ProSection2DAlloc is = %d\n", status );
line.type = PRO_2D_LINE;
line.end1[0] = 0;
line.end1[1] = 0;
line.end2[0] = 100;
line.end2[1] = 0;
status = ProSectionEntityAdd ( *section_here, (Pro2dEntdef*)&line, &line_id[0] ) ;
line.type = PRO_2D_LINE;
line.end1[0] = 100;
line.end1[1] = 0;
line.end2[0] = 100;
line.end2[1] = 100;
status = ProSectionEntityAdd ( *section_here, (Pro2dEntdef*)&line, &line_id[1] ) ;
line.type = PRO_2D_LINE;
line.end1[0] = 100;
line.end1[1] = 100;
line.end2[0] = 0;
line.end2[1] = 100;
status = ProSectionEntityAdd ( *section_here, (Pro2dEntdef*)&line, &line_id[2] ) ;
line.type = PRO_2D_LINE;
line.end1[0] = 0;
line.end1[1] = 100;
line.end2[0] = 0;
line.end2[1] = 0;
status = ProSectionEntityAdd ( *section_here, (Pro2dEntdef*)&line, &line_id[3] ) ;
status = ProSectionEpsilonSet( *section_here, 0.1 );
status = ProSectionAutodim ( *section_here, §ion_errors1 );
if ( status != PRO_TK_NO_ERROR )
{
status = ProSecerrorCount ( §ion_errors1, &n_sec );
ProTKPrintf("The status for ProSecerrorCount is = %d\n", status );
ProTKPrintf("Number of errors in the ProSectionAutodim = %d \n",n_sec );
for ( i = 0; i < n_sec; i++ )
{
status = ProSecerrorMsgGet (section_errors1, i, error_message);
ProTKPrintf("The status for ProSecerrorMsgGet is = %d\n", status );
ProWstringToString (error_message_s, error_message);
status = ProSecerrorItemGet ( section_errors1, i, &error_id);
ProTKPrintf("The status for ProSecerrorMsgGet is = %d\n", status );
ProTKPrintf(" %s : Problem ID : %d \n", error_message_s, error_id );
}
}
status = ProSectionRegenerate ( *section_here, §ion_errors3 );
if ( status != PRO_TK_NO_ERROR )
{
status = ProSecerrorCount ( §ion_errors3, &n_sec );
ProTKPrintf("The status for ProSecerrorCount is = %d\n", status );
ProTKPrintf("Number of errors in ProSectionRegenerate = %d \n",n_sec );
}
return ( status );
}
Note: The UDF definition file simple_round.gph used in this example must be available in the current working environment. This depends on your current config.pro settings. Alternatively, you can configure the file path directly in the udfObj command.
# Simple round on the current solid model using a UDF. # The round uses a fixed radius. # # UDF definition: # Prompt = 'edge' # Selection = EDGE (one reference) # # Create the UDF object and specify the UDF name. ps_udf udfObj -name simple_round # Assign the selection object to the UDF prompt 'edge'. udfObj add_selection edge selObj # Ask the user to select an edge. selObj sel edge # Create and apply the UDF. udfObj create
Creo configuration options, such as pro_group_dir, can be queried and modified at runtime using ps_info:
# Retrieve the current value of a configuration option. set value [ps_info config OptionName] # Set or change a configuration option. ps_info config OptionName NewValue
Changes are applied directly to the running Creo session.
Model items and other pShell objects provide the configure and cget commands to manage and retrieve their properties. configure displays available options and allows writable properties to be modified. cget retrieves the current value of a specific property. Read-only properties are marked with RO in the configure output and can only be retrieved using cget.
A model item is a complex variable representing an item within a Creo model. It references a Creo model, an item type (such as a feature, edge, surface, axis, part, etc.) and the corresponding item ID.
Model items can be used to retrieve information, extract properties and modify the referenced item where supported by the Creo Toolkit.
Like a Tk widget, a model item provides a set of commands to configure the object and retrieve its properties using configure and cget.
A model item can also be linked to Selection objects, allowing changes to be propagated automatically.
Example: Hiding a Creo Feature (if Creo Supports it)
# Create a model item referencing feature ID 238 # in the Creo model box.prt. ps_modelitem miPlane -model box.prt -type Feature -id 238 # Hide the referenced feature. # The effect depends on the type of model item: # A hole feature will remain visible, whereas # a datum feature will be hidden. miPlane hide # For example, hiding a hole feature has no effect, # whereas a datum feature will be hidden.
A component path object identifies where a component is located within a Creo assembly structure and at which level of the assembly hierarchy. It contains the sequence of component feature IDs from the top-level assembly down to the target component. It can be used to identify a specific component occurrence, even when the same part is used multiple times within an assembly.
In short: A component path tells you where a solid component is located.
Accessing Components within the Path
The cpObj provides two commands to retrieve information about individual levels of the assembly hierarchy:
The component path is represented as a list of integer values. You can use integer values to address any level within the component path. Additionally, the Tcl-style indices end and end-1 are supported for addressing levels relative to the end of the path.
For example:
# Get the name of the selected model (bottom level). set modelName [cpObj model_in_level end] # Get the component ID of the selected component. set compId [cpObj compid_in_level end] # Get the name of the parent assembly of ‘modelName’ set parentName [cpObj model_in_level end-1]
A selection object is a complex variable representing a Creo ProSelection. It can be created with ps_sel and then used wherever a selection is required within pShell. A selection object can be configured interactively or programmatically and reused throughout the application. Within the feature tree, the selection objects are identified by name, so keeping their original names allows pShell to restore the references after reparsing.
For example:
# Create two selection objects. ps_sel selAxis ps_sel selSurface # Let the user define their contents. selAxis select axis selSurface select surface # Extract the model item data from each selection object. # The data is copied, no link is established. # The same model item object will be reused. selAxis modelitem miObj set axisId [miObj cget -id] selSurface modelitem miObj set surfaceId [miObj cget -id]
Extract the model item data from the selection object into a model item object.
# Extract selObj modelitem miObj
The model item selection data is copied to the named model item object. The two objects remain independent.
Alternatively, a model item and a component path can be linked directly to a selection object:
# Link selObj configure -modelitem miObj -comppath cpObj
Once linked, the objects automatically keep each other updated:
# Create a selection object linked to a model item. # The model item is created automatically if it does not exist. ps_sel selObj -modelitem miObj # The model item is now linked to the selection object. # Changes to miObj will automatically update selObj. # Select an axis belonging to the model item. selObj select axis # Get the updated information from the linked model item # Retrieve the ID of the selected axis. set axisId [miObj cget -id]
Instead of constructing every feature programmatically, create a deliberately over-complete model in Creo. The model contains all the potential features and geometric alternatives required by the application. The important idea is that the model contains the design intent, while the application controls which parts of that intent are active.
Through TOOLKIT, however, every operation requires explicit programming, including geometry creation, references, feature definitions, regeneration, error handling and model-state management. The difficulty is not simply creating geometry. It is maintaining the complete parametric design intent.
Consider a simple rectangular block.
Now consider a second operation on the opposite face. Which face is the intended one? The application must identify it reliably, not just during initial construction, but after subsequent modifications and regeneration.
Possible identification criteria include:
None of these automatically expresses the designer's intent.
This is an aspect that is easy to overlook. A Creo drawing is not simply a visual representation of the model. It is another structured engineering document with its own information and dependencies. When a drawing is created, additional information must be established.
Direct feature creation through TOOLKIT is technically possible, but technical feasibility is not the same as a sensible development architecture.
Don't use Creo/TOOLKIT to reinvent Creo's modeling capabilities. Use Creo to define the modeling intent and Creo/TOOLKIT to control its execution.