home - about - advertise     
 
 
Sponsors
Navigation
Partners

 
Pro/ENGINEERTutorial

Pro/TOOLKIT: Learning to Walk

By Vojin Jovanović, February 12, 2004

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: The First Steps Are the Hardest, which will provide a foundation to help you continue exploring Pro/TOOLKIT in this article.

Menus

Before you do anything with Pro/TOOLKIT you need to make sure that you can access your functions from within Pro/ENGINEER. The way to do that is to set up menu files which load when Pro/E or Pro/TOOLKIT applications start (synchronous mode). The new menu buttons then appear in Pro/E which imitate your functions. In fact this, most likely, is going to be your primary way of making applications for your users. The other method is using asynchronous mode, where your code runs outside of Pro/E. This approach allows remote connection to Pro/E and some other tricks which I like to use, but we’ll talk about that when we learn some more about Pro/TOOLKIT.

Let us first set up a complete simple application with menus and buttons so that we can do some meaningful work.

First create a text file part.aux which contains the following in the box. Note: don’t include <blank space> in that file as shown below. That is only a reminder to put a blank space at that line.

 


PART
<blank space>
<blank space>
Develop
Develop your code.
<blank space>

With this we are telling Pro/E to add another button to its part menu when the main menu gets loaded into the memory. We’ll see how that is done in the code.

Second create a text file develop.mnu which contains the following in the box.

 


Develop
<blank space>
<blank space>
Evaluate
Test the code.
#
Quit#Develop
Quit
#
#
 

This is going to be what that menu will contain. Note that ‘Quit#Develop’ contain ‘#’ for space field designation.

Then create a text file develop_msg.txt which contains the following in the box.

 


USER %0s
%0s
#
#
 

This is going to be our generic way to write messages to the Message area in Pro/E. I’ll explain that shortly in the code that follows.

Then create a text file protknt.dat with the following in the box

 


NAME develop
STARTUP dll
EXEC_FILE C:\vjfolder\PTK\PTKDEVEL\CADDIGEST\Debug\develop.dll
TEXT_DIR C:\vjfolder\PTK\PTKDEVEL\CADDIGEST\text
allow_stop TRUE
REVISION Wildfire
END
 

Finally, create a file user_init.cpp that contains the following code:

 

extern "C"{  // extern directive because I want to work with C++

                                                 //        since Pro/TOOLKIT stuff is all written in C it

                                                 // must be designated as C code

#include <ProToolkit.h>

#include <ProUtil.h>

#include <ProMenu.h>

#include <ProMessage.h>

 

// these 2 function must always be declared and

// defined in your Pro/TOOLKIT dll application

int user_initialize(int argc,char ** argv);

void user_terminate();

 

}

 

int user_evaluate();  // declare these functions

int user_create_develop_menu();

 

static ProName dev_msg;

// this macro will be a time saver

#define MSGFILE  ProStringToWstring(dev_msg,"develop_msg.txt")

 

 

// this function gets called when you load your application

int user_initialize(int argc,char ** argv)

{

 

    int menuId;

                // tell Pro/E to load its own menus

                // and extend them with our stuff as

                // specified in part.aux

    ProMenuFileRegister("MAIN","main.mnu", &menuId);

    ProMenuFileRegister("PART","part.mnu", &menuId);

    ProMenuAuxfileRegister("PART","part.aux", &menuId);

 

                // designated Develop button that will initiate

                // our menu creating function (note that there are no passing of arguments

                // to that function therefore NULL and 0)

    ProMenubuttonActionSet("PART", "Develop",

                    (ProMenubuttonAction)user_create_develop_menu, NULL, 0);

    return(0);

}

 

// this function gets called when your application stops

void user_terminate()

{

                // clean up here if necessary

     return;

}

 

 

// this function gets called when a user clicks on the Develop button

int user_create_develop_menu(){

 

                int action,menuId;

 

                // lets register our menu file

    ProMenuFileRegister ("Develop", "develop.mnu", &menuId);

                // and set up a function that will be called on clicking Evaluate

    ProMenubuttonActionSet ("Develop", "Evaluate", (ProMenubuttonAction)user_evaluate,NULL, 0);

                // also allow the user to quit so that menu will close itself

    ProMenubuttonActionSet ("Develop", "Quit Develop",

        (ProMenubuttonAction)ProMenuDelete, NULL, 0);

    ProMenubuttonActionSet("Develop", "Develop",

        (ProMenubuttonAction)ProMenuDelete, NULL, 0);

 

                // create the menu

    ProMenuCreate (PROMENUTYPE_MAIN, "Develop", &menuId);

                // and make it active

    ProMenuProcess ("", &action);

                return 0;

}

 

// this function gets called when a user clicks on the button Evaluate

int user_evaluate()

{

                // just display a message for now

                ProMessageDisplay( MSGFILE, "USER %0s", "Testing." );

                // and scroll one line

                ProMessageClear();

                return 0;

}

The comments in the above code should be enough to help you understand what is going on. In short, we instruct Pro/E to load its own menus and then extend them with our own content. Additionally we set up some buttons to initiate our own code and do some work.

The above us a pretty standard way to add your code to mode specific menus. The other approach is using Pro/E menu bar. Examples of that you can find on my website.

To use the above just put in your config.pro line ...

protkdat C:\vjfolder\prodevexe\protknt.dat
(Of course substitute your own location for that the .dat file.)

… and start Pro/E. Once you load a part or create a new one, a menu ‘Develop’ will appear on the right side.

Features and Geometry

Pro/E is a feature-based parametric tool where all geometry is a result of creating features. As a consequence you’ll see quite a number of feature-dedicated functions if you look in the user guide. Getting familiar with features and Pro/E geometry objects is quite essential. Let us use what we developed above and try to get some information on the objects in a part.

We’ll make a function that will ask the user to select a surface object on the part and we’ll then extract some info from it. With this we’ll learn how to select the objects on the screen and access the internal geometry of the parts. Just for fun we’ll draw some stuff in order to practice vector geometry.

To make a selection from the code you need to use ProSelect().This function has quite a few input arguments but fortunately you can specify only a few to get a job done in most cases.

Bear minimum of usage is the following. For complete declaration syntax consult the user guide.

ProSelection *sel = NULL;
int n_sel;
ProSelect("surface", -1, NULL, NULL, NULL, NULL, &sel, &n_sel);

Here we force a user to make only one pick (-1) and only pick a “surface” object. Other possibilities can also be specified such as “point”, “edge”, “curve”, “axis”, etc. The result of this operation is that the pointer ‘sel’ points to the picked structure, ProSelection object. This object is quite general and can contain all kinds of stuff; therefore you must know what you are looking for. In this case we know that we are getting a surface. Before we extract anything from this object we need to turn it to modelitem/geoitem. These objects are used quite often and you’ll find yourself doing this kind of stuff often.

ProModelitem mdlitem;
ProSelectionModelitemGet(*sel, & mdlitem);

Now that we have a model item we can get a particular surface object with …

ProSurface surface;
ProGeomitemToSurface(&mdlitem,&surface);

Sometimes you’ll notice that the PTC’s functions take pointers as in-arguments even though they are not filled-up on the way out of the function. For example in the above case mdlitem is supplied with & but it unchanged argument after ProGeomitemToSurface() returns. Pay attention to these kind of requirements, it will save you time.

Now we can test if the surface is planar and report if it is not.

ProSrftype p_srf_type;
ProSurfaceTypeGet(surface,&p_srf_type);

if(PRO_SRF_PLANE != p_srf_type){
ProMessageDisplay(MSGFILE,"USER %0s","Surface is not plannar, try again.");
ProMessageClear();
return -1;
}

Now we come to a complicated structure that you would need to get familiar with and that is a Geomitemdata object. If you look in the browser you’ll see that this object contains quite a few references. The references branch to different structures depending what kind of geometry Geomitemdata object is representing. To learn how to access the particular pieces of that geometry you’ll need to browse through its types and see whether they can be accessed through ‘->’ or ‘.’ notation. But let’s first get the object itself.

ProGeomitemdata *p_data_ptr;
ProSurfaceDataGet(surface,&p_data_ptr);

Notice that the last function allocates the memory and we’ll need to free it otherwise your code will leak.

Ok, here is how to get to the relevant vectors for the picked surface

double *_org=p_data_ptr->data.p_surface_data->srf_shape.plane.origin;
double *_e1=p_data_ptr->data.p_surface_data->srf_shape.plane.e1;
double *_e2=p_data_ptr->data.p_surface_data->srf_shape.plane.e2;
double *_e3=p_data_ptr->data.p_surface_data->srf_shape.plane.e3;

Notice ‘->’ and ‘.’ operators and go over the structure in the documentation. Unfortunatelly, VS inteli-sense does not sense with Pro/TOOLKIT to help you out in figuring out what the next parameter is, due to complicated statements in PTC’s include files.

Just for fun let us draw some arrows (you’ll find the complete code in this file).

double surface_area;
ProSurfaceAreaEval(surface,&surface_area);
double lenght = sqrt(surface_area)/3.;

I first scale the arrows to correspond to the size of the surface and then draw them.

DrawArrow(_org,_e3,_e1,lenght);
DrawArrow(_org,_e1,_e3,lenght);
DrawArrow(_org,_e2,_e3,lenght);

Finally, we need to free the structure and return

ProGeomitemdataFree(&p_data_ptr);
return 0;

To use the code shown above place it into user_evaluate(), compile, make a part with planar surfaces and start selecting them through the Develop menu.

You’ll notice some (funny) looking arrows that show up indicating the coordinate systems of the surfaces that you picked. Here is a picture for you to know what you should get.

Play around with the above code and start adding your own stuff. There is much more to geometry than we did here and you’ll have to go through it yourself.

Conclusion

We've covered some ground related to geometry. It may seem a bit overwhelming in the beginning, but with practice you’ll get used to it. Try to make a good use of API browser and installation examples. Install pd_examples, pt_examples, and user_guide toolkit applications. There is a lot of useful stuff there and you should try to use it and learn from it.

And stay tuned - soon we’ll try to make some more steps with Pro/TOOLKIT, and in some not too distant future add some Pro/INTRALINK Toolkit to all of this.

About the Author

Vojin Jovanović is an independent consultant with over 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://www.purplerose.biz/Vin>.

Related Articles

 
CADdigest Weekly
Email (required) *

A week's worth of articles will be emailed to you. See latest issue .