Tcl for Creo – Feature Creation Revisited

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.

Examples

  1. Datum Point – Build, create, reuse, modify and redefine a Creo feature tree.
  2. First Feature – Demonstrate the general mechanism for creating the first sketched feature.
  3. UDF Round – Place a predefined Creo UDF with just four lines of Tcl code.

Tcl Object Commands

p-Shell provides Tcl representations for several Creo object types. The following three are particularly useful when working with model geometry and assembly structures:

  1. Component Path: Identifies where the component is located in the assembly.
  2. Model Item: What is it?
  3. Selection Object: Combines both to identify exactly what is selected.

All three types are available as Tcl object commands.

Datum Point

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

First Feature

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
}

UDF Round

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

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.

Object Configuration: configure and cget

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.

Model Items

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.

Component Path

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:

  • model_in_level – Rturns the model name at the specified level.
  • compid_in_level – Returns the component ID at the specified level.

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.

  • 0 – The root (top-level) assembly.
  • end – The selected component (the target model).
  • end-1 – The parent assembly.

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]

Selection Objects

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]

Selection Object – Extracting and Linking Data

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:

  1. When the selection changes, the linked model item and component path are updated.
  2. When the model item or component path changes, the selection object is updated accordingly on next use.
# 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]