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.
|