Pro/TOOLKIT: The First Steps Are the Hardest
An Application Programmers Interface
(API), Pro/TOOLKIT allows Pro/ENGINEER functionality to be
augmented and/or customized to meet the specific needs of PTC's
customer base using the "C" programming language. Specifically,
Pro/TOOLKIT provides the ability to customize the standard
Pro/ENGINEER user interface, automate processes involving
repetitive steps, integrate proprietary or other external
applications with Pro/ENGINEER and develop customized end-user
application for model creation, design rule verification and
drawing automation.
Unfortunately, Pro/TOOLKIT deservingly
gained a reputation of being hard to work with. This state of
the affairs is the result of PTC's current vision, which
dictates where and how this product ought to augment the
functionality of Pro/ENGINEER. This vision, as the series of the
articles to follow will show, is by no means offers the ideal
toolkit users would hope for; rather, it leaves quite a few
features to be desired. In these articles we will explore what
it takes to work with Pro/TOOLKIT and how to go beyond what PTC
supports today.
Note: If you haven't yet, please read (or read
again) my article,
Pro/TOOLKIT: Setting Up Your Environment in VC++ .NET, which
will prepare you for what follows.
Getting Started
If you know how to write C programs you
are already on your way to success with Pro/TOOLKIT. Although
you don’t need to possess any C++ knowledge, it might be useful.
Pro/TOOLKIT was written in C a long time ago and its sheer size
and internal complexity, in my opinion, is the main reason why
PTC did not make it an objects-oriented tool. This situation
seems likely to persist given PTC's silence on the issue.
You don’t need to be an expert in C
either, although you should understand the "pointers" business.
You’ll use them often as you transfer your data from one
function to another.
The main tool you’ll use is the API
browser, which contains over 2000 functions and is
cross-referenced with example code and user guide. So make sure
that you install it properly with the required Java plug-in. It
may take some time to set everything up, but don’t get
discouraged.
In addition, if you're going to work with
geometry (which happens to be my area of expertise), you’ll need
a decent understanding of vectors and be able to imagine how
things are oriented.
Finally, once you get going it will
probably take about one month of work (at 40 hours per week) to
get comfortable with Pro/TOOLKIT. To speed things up you may
want to consider attending one of the 5-day Pro/TOOLKIT classes
given by PTC.
Overall Organization
Since all of Pro/TOOLKIT is written in C,
each object is represented with a structure. Which object needs
to be used, and how you derive them from various structures, is
an art in itself. (This is due to the mixing of some objects
before Pro/TOOLKIT’s time, which were used in Pro/DEVELOP - Pro/TOOLKIT’s
predecessor).
In order to work with structures you need
to have the means to access them. Pro/TOOLKIT provides a number
of “typedefs”; you will eventually develop a sense how to use
them. The typedefs are nothing but disguised pointers to
internal Pro/E structures. For example:
typedef struct entity* ProPoint;
typedef struct sld_part* ProSolid;
These are also called OHandles (from
Opaque handles) and they directly access the memory locations of
objects in Pro/E. Since that can be dangerous in some cases, PTC
provides another type of structure that contains only minimal
information about items stored in Pro/E’s internal database. The
structure (labeled DHandle from data handle) is of a generic
type and contains the type of the object, its ID and its owner.
A lot of designed words are associated with this structure as
you can see below:
typedef struct
pro_model_item
{
ProType type;
int id;
ProMdl owner;
} ProModelitem, ProGeomitem, ProExtobj, ProFeature, ProProcstep,
ProSimprep, ProExpldstate, ProLayer, ProDimension, ProDtlnote,
ProDtlsyminst, ProGtol, ProCompdisp, ProDwgtable;
If you are planning to work on geometry
problems, you’ll mostly use ProModelitem, ProGeomitem and
ProFeature. ProModelitem is the most generic type of object and
it can represent objects other than geometry items.
ProType in DHandle structure is enumerated
typedef with a large number of keywords. Once you receive an
object from a function or search for it in some contour, for
example, you’ll often have a need to check what type it is.
The first thing you will notice when
looking at the browser is that Pro/TOOLKIT function names are
chosen based on what objects they usually work with. For
example, any function that starts with ProSolid has the input
argument ProSolid.
A very important class of functions that
you’ll have to learn how to work with is the visiting functions.
These functions contain the word “Visit” in their name. The
functions provide a way to search through complex Pro/E internal
structures. They always take as an input argument a pointer to
your own user-defined action function, which does some work at
each structure found.
The above may seem overwhelming at first
but as you go along I promise that things will fall into place.
Don’t worry if you're a little unsure about what I've said so
far. The best way to counteract the confusion is to try to make
some concrete functions in Pro/TOOLKIT, which are provided
below.
The first steps
One of the first functions that you need
to know about is ProMdlCurrentGet(). The beginning of its
description in API Browser is shown below.
Description
Initializes the p_handle with the current Pro/ENGINEER object.
Synopsis
#include <ProMdl.h>
ProError ProMdlCurrentGet (
ProMdl *p_handle
/* (Out)
The model handle
*/
)
The function takes one argument, a pointer
to ProMdl typedef and you use it like this:
ProMdl mdlhandle;
ProMdlCurrentGet(&mdlhandle);
mdlhandle is OHandle and in this case it
is OK to use it because this handle will persist as long as your
part (or whatever it is) remains in the session. Now, what can
you do with this object? A lot of things. For example, you can
make a call with ProMdlDataGet() and get some initial
information about this model.
ProMdldata mdldata;
ProMdlDataGet (mdlhandle, &mdldata);
mdldata is a simple structure that
contains name, type, path and other info about the model. Let’s
print the type of the model.
The most members of the structure are
declared as wide characters so you cannot just go ahead and do
printf(“%s\n”,mdldata.type);. You have to translate the type to
a regular character array with ProWstringToString() as shown
below:
char type_in_c[PRO_TYPE_SIZE]; /* uses
predefined Pro/T constants like PRO_TYPE_SIZE */
ProWstringToString (type_in_c, mdldata.type);
printf(“%s\n”,type_in_c);
Note how the names of Pro/TOOLKIT
functions are chosen by PTC. Also note in this case that input
and output to the function may not be what you would expect. The
first argument is the output, while the second is the input.
Now let’s print the name of the model. You
could do the same as above and extract the name from mdldata
structure; instead try a different, more convenient method:
ProName current_name;
char current_name_in_c[PRO_NAME_SIZE];
ProMdlNameGet(mdlhandle, current_name);
ProWstringToString(current_name_in_c,current_name);
printf(“%s\n”, current_name_in_c);
How about printing the features that are
contained in the model? First, you need to initialize a model
item handle and supply it to ProModelitemInit(). You will need
to do this often. In fact, what all of the functions that
contain Init in their name do is initialize handles. Please note
that in some situations, since you know that most of the handles
are structures, you may want to circumvent the process and fill
up those handles yourself; for example: mdlhandle.name = “a
name”. But avoid this, because doing somay lead to unpredictable
behavior and you’ll wind up spending a lot of time chasing
errors. Therefore, always use Init functions for this kind of
job.
Here is how to do it properly:
ProName current_name;
char current_name_in_c[PRO_NAME_SIZE];
ProError err;
ProModelitem mdlitem;
long mdlhandle;
int id;
id = 38: /* change this number to be a number for a feature in
your feature tree, ideally you should ask the user to enter a
number, but we are not ready to do that here yet*/
ProModelitemInit(mdlhandle,id,PRO_FEATURE,&mdlitem);
err=ProModelitemNameGet(&mdlitem,current_name);
if(err == PRO_TK_E_NOT_FOUND) /* in some cases the feature may
be odd so we’ll check for that*/
ProFeatureTypenameGet(&mdlitem,current_name);
ProWstringToString(current_name_in_c,current_name);
printf(“%s\n”, current_name_in_c);
Note that in Init function you specify
PRO_FEATURE, which indicates what type of object you want to
initialize.
Visiting Functions
Next, let's look at visiting functions, an
important topic related to collecting items from a model.
As you can imagine, the model may consist
of a large number of objects that can contain many sub-objects.
Since you don’t know a priori the number of those, you need to
be able to somehow collect the objects you are looking for. For
that type of need PTC provides visiting functions.
In previous versions of Pro/TOOLKIT
(called Pro/DEVELOP), PTC provided different functionality where
you could, with one function call, obtain a list of needed
objects. But with the coming of Pro/TOOLKIT a shift was made
toward visiting objects, and previous Pro/DEVELOP functionality
was dropped. Visitation process obviously has its advantages, as
you’ll see, and while visiting it is possible to do all kinds of
actions to visited objects. In my opinion, however, this was
better accomplished the way Pro/DEVELOP managed it.
The visitation process consists of 2
components. One is the PTC’s visitation action call itself and
the other is the supplied user’s function that should work on
every object visited. Let's look at a simple example.
Suppose that you want to visit all of the
features contained in a model and collect their ids. The
function to do this (which you will use often) is
ProSolidFeatVisit(). The function takes 4 arguments: ProSolid
handle, a vesting function pointer, a filtering function pointer
and a pointer to an arbitrary structure. The purpose of the
filtering function is to be able to filter access to particular
objects, but I find that cumbersome and do filtering on my own
within the visiting function itself. The final input argument,
the pointer to an arbitrary structure, provides a way to store
the collected data and use it at the top level before the
visitation call is made.
If the above confuses you don’t worry.
It's not difficult as it may sound.
Let's look at an example where everything
will fall into place. Note that I like to use STL for its
convenience and I suggest that, if you still have not done it,
you get familiar with STL’s objects. It will save you a lot of
time.
// action function, note the layout it is
always the same
static ProError user_action_get_feat_ids(
ProFeature *feature,
ProError status,
ProAppData appdata)
{
ProBoolean visible;
vector<int> *fids = (vector<int> *)appdata;
ProFeatureVisibilityGet(feature,&visible); /* we’ll only work
with visible features */
if(visible == PRO_B_TRUE){ // and collect their ids
fids->push_back(feature->id);
}
return(PRO_TK_NO_ERROR); /* always return this constant unless
you want to stop visiting for some reason */
}
vector<int> feat_ids; // STL vector
object, a very useful one
// the main Pro/TOOLKIT call
ProSolidFeatVisit((ProSolid)
mdlhandle,(ProFeatureVisitAction)user_action_get_feat_ids,NULL,(ProAppData)
&feat_ids); /* you’ll need to cast the pointers if you don’t
want the warnings */
Note the use of mdlhandle that I used
before and note that ProMdl and ProSolid can be interchanged in
function calls. You can use ProMdl object where ProSolid is
needed. Also note that I put NULL for the filtering function
since I don’t want to use it.
Now you obtained a list of ids in feat_ids
and you can do with them anything you want. For example print
them out.
for(unsigned int i=0; i<feat_ids.size(); i++){
cout<<feat_ids[i]<<endl;
}
I’ll stop here to let you absorb things so
far. Pro/TOOLKIT may seem a bit overwhelming at first, but in
time you'll get the knack of it.
Conclusion
Above I have presented the most fundamental and most-used
concepts that you’ll need to learn. I suggest that you study
those examples and experiment with their variations. Consult the
large number of example functions that come with the
installation, which are cross-referenced in the Pro/TOOLKIT API
browser.
And stay tuned - soon we’ll try to make some more steps with
Pro/TOOLKIT!
About the Author
Vojin Jovanović is an independent consultant with 5 years of
experience developing Pro/TOOLKIT applications in the area of
design optimization and automation as well as over 10 years of
experience in developing scientific numerical applications. He
has published in international journals and presented at various
conferences. His area of expertise is in computational geometry
related to MCAD and in development of financial applications.
You can reach him at
fractal97@hotmail.com and visit his website at: <http://attila.stevens-tech.edu/~vjovanov/index.htm>.Related Articles
Pro/TOOLKIT: The First Steps are the Hardest - Jovanovic Pro/TOOLKIT: Setting up your environment in VC++ .NET - Jovanovic.
|