[Previous]   [Next]   [Contents]   [Index]   [Books]   

FRAME Interface

Frame provides the basis for setting up a CAD/CAE/CIM solution. General facilities for List handling, Error handling, Command decoding, Application module binding, Interactive optical feedback and Mathematical Basics are covered.

Lists

The term lists in this context refers to a sequence of the so-called nodes of a linked list. Each node can hold an object of any size. The nodes are sequentially linked together with pointers (for example, single linked list, one direction). The links between nodes are managed by the AI list routines.

In the recommended way of use, a last-in-first-out (LIFO) concept is used, which means that lists normally grow from the tail towards their head. The head is normally the end where new nodes are added (That's the fastest way). It is also possible to insert new nodes anywhere in the list. The LIFO method is fast and allows coincidence of current element and list head.

All functions and macros of this list-type end with the postfix_list or postfix_node. The type of node and list-head pointers is struct list_node.


Figure 2. An Example of Lists

Related Functions:

Error Handling / Exception Handling

There are two different principles dealing with errors:

Catching Exceptions

The ME_TRY, ME_RECOVER, ME_END_TRY macros allow programmatic trapping of:

General Macro Usage:

 ME_TRY
  <statements>
  ME_RECOVER
  <statements>
  ME_END_TRY

The macros ME_TRY, ME_RECOVERY, and ME_END_TRY are based on calls of setjump. Be careful if you use setjump or these macros together with global optimization switched on during compilation. Due to global optimization, non-volatile variables may have been overwritten if the RECOVER block is entered (by a longjump).

When ME_TRY is executed, certain information about the state of the program is recorded in a marker called the 'environment', which is pushed onto the program's stack. The address of the environment is saved in the global variable me_env_ptr, then the statements following the ME_TRY are executed in sequence. If none of them causes an exception, the ME_RECOVER is reached, its statements are skipped, and the environment is popped off the stack.

But if an exception occurs such as signal received, math error occurred or ME_ESCAPE executed, the stack is restored to the state indicated by the most recent environment. If ME_TRY - ME_RECOVER - ME_END_TRY was itself nested within another one, or within procedures called while a ME_TRY - ME_RECOVER - ME_END_TRY was active, the outer environment becomes active. Then the statements following ME_RECOVER are executed. Thus nesting of ME_TRY - ME_RECOVER - ME_END_TRY is DYNAMIC, according to calling sequence, and not statically structured.


Note
It is not allowed to exit either the ME_TRY or the ME_RECOVER block with return or goto statements.

The recovery process does not 'undo' the computational effects of statements between ME_TRY and ME_RECOVER. The exception simply aborts the computation and the program continues with the 'recover' statements.

When an exception has been caught, the global variable me_errno contains the number of the exception.

Exceptions can be simulated by using the macro ME_ESCAPE(code), which sets the exception code to 'code' and does a longjump.

A well structured example for error handling may look like this:

ME_TRY
{
 statement1;
 statement2;
 .
 .
}
ME_RECOVER
 switch (me_errno)
 {
   case ME_SYS_ERROR:
    recover_statement1;
    recover_statement2;
    .
    .
    break;
   default:
    ME_ESCAPE(me_errno);
    break;
 }
ME_END_TRY

The default branch in the switch statement ensures that unwanted errors are passed on to the next ME_TRY... block, so there should be at least one ME_TRY... where transferred errors are processed !

Related Macros:

Exception Codes

Table 1. Exception Code Table
Symbol Description
ME_NO_EXCEPTION  
ME_SYS_ERROR System Call returned an error; Error code defined in errno
ME_SIGNAL Signal has been received; See me_signalno
ME_MATH_ERROR A math error has occurred; Error code is defined in me_math_error
ME_EX_NOMEM Not enough memory
ME_EX_NILPTR Reference to NIL pointer
ME_GLOBAL_GOTO ESCAPE used for a global goto

Command Decoding

Action Routines

Action routines are C functions executing ME10 user commands and user functions. They are activated when the user types their corresponding keyword, and they usually request input from the user to decide what action to take.

Keywords

Keywords are reserved words within ME10. They start with a letter which may be followed by letters, digits, or the _ character. All letters have to be uppercase.

There are several types of keywords:

The following routines are used to define new keywords. They all return a pointer to an internal data structure describing the keyword. This pointer may be used later to check if some keyword pointer is pointing to the keyword just created.

struct keyword *me_new_command(name, func)
char  *name;
void (*func)();

struct keyword *me_new_function(name, func)
char  *name;
void (*func)();

struct keyword *me_new_qualifier(name)
char  *name;

struct keyword *me_new_arithm_function(name, func)
char  *name;
struct token *func;


Note
The name is the command name at the user interface level and the func is the procedure name at the AI level performing the related command.

Tokens

Processing ME10 input can be split into two parts: character processing and token processing. All logical input devices, such as the keyboard or a screen/tablet menu, send characters to the scanner. The scanner understands the syntax of all token types. It decides by looking at the stream of characters if the token is a point, a string or a number.

Basically a token is an entity of information containing a token type, a value, and a link to next token.

All input from the user is classified, converted, and packaged for easy parsing by action routines. These information packages are called tokens. There are several types of tokens, each carrying a different kind of information:

The information carried by these token types is a pointer to their keyword. Normal action routines will never see PSEUDO_COMMAND or ARITHM_FUNCTION tokens, as these are handled internally. This means those will be processed before being handed over to the action routines.

Table 2. Type of Symbol Tokens
SYM_AMPERSAND 0
SYM_ASTERISK 1
SYM_AT 2
SYM_CARET 3
SYM_COLON 4
SYM_COMMA 5
SYM_DASH 6
SYM_DOLLAR_SIGN 7
SYM_EQUAL 8
SYM_EXCLAMATION_POINT 9
SYM_GRAVE_ACCENT 10
SYM_GREATER 11
SYM_GREATER_EQUAL 12
SYM_LEFT_BRACKET 13
SYM_LEFT_PAREN 14
SYM_LESS 15
SYM_LESS_EQUAL 16
SYM_NOT_EQUAL 17
SYM_PERCENT 18
SYM_PERIOD 19
SYM_PLUS 20
SYM_QUESTION_MARK 21
SYM_RIGHT_BRACKET 22
SYM_RIGHT_PAREN 23
SYM_SEMICOLON 24
SYM_SLASH 25
SYM_TILDE 26
SYM_VERTICAL_BAR 27

The following routines deal with tokens:

int me_token_get(prompt) char *prompt;

me_token_get() is used by action routines to request input from the user. prompt is a prompt string issued by the system. This prompting is suppressed if the input request can be satisfied from an executing macro, input file or from previously buffered user input. All macro and expression handling are done internally.

me_token_get() returns the type of the token read. If the user types a function keyword in response to the input request, the action routine corresponding to this function keyword will be executed. Then this me_token_get() returns to its caller with a token which is executed already. The token type then is NO_TOKEN. This is implemented in this way to give the calling procedure a chance to check for side effects.

void me_token_unget() This routine returns a token, read in by me_token_get(), to the ME10 system. This should be done for all tokens that the current action routine cannot or will not handle.

The following routines are used to retrieve the information associated with the token read by me_token_get(). They will return garbage or cause system errors if they are used with the wrong token type.

struct keyword *me_token_keyword() Contains the keyword pointer from a COMMAND_TOKEN, FUNCTION_TOKEN, QUALIFIER_TOKEN, PSEUDO_COMMAND_TOKEN, or ARITHM_FUNCTION_TOKEN.

int me_token_symbol() Retrieves the symbol type from a SYMBOL_TOKEN.

char *me_token_string() Contains the pointer to the character string of a STRING_TOKEN.

float64 me_token_number() Contains the double-precision number of a NUMBER_TOKEN.

struct fvec2 me_token_pnt2d() Contains the 2D point of a POINT_TOKEN.

Writing Action Routines

The following functions are general support functions for writing action routines:

void me_display_prompt(prompt) char *prompt;

This routine will show the prompt string on the system prompt line.

void me_token_error() This routine should be called if the user has entered an illegal token for an action routine. It clears all input buffers, issues a beep, and then starts error-processing if an ON_ERROR is active.

void me_wait_for_ack() This routine waits for the user to press a key on the keyboard, the mouse or the tablet stylus. It may be used to give the user some time to read a message, before it is overwritten by the next input prompt.

void me_display_error(prompt) char *prompt;

This is a convenient combination of me_token_error(), me_display_prompt() and me_wait_for_ack().

void me_set_default_input(s) char *s;

This routine provides a default for the next user input. This default is put on the input line and may be edited by the user. The default is ignored if the input request can be satisfied from an executing macro, an input file or previously buffered user input.

Example Action Routine:

This is an example where a number_token and a qualifier token takes place. The task it performs is: When the user inputs numbers in a sequence and then finally types in DONE, it prints out the average value.

UNIX-Based Systems:

#include "frame.h"
#include "model2d.h"

static struct keyword *keyword_done;

/*---------------------------------------------*/

static void ai_demo_fnc()
{
  char  buf[1024];
  float64 sum = 0.0;
  int  n = 0;
  for (;;)
   switch (me_token_get("Enter a number or DONE")) {
   case COMMAND_TOKEN:
   case FUNCTION_TOKEN:
    me_token_unget();
    return;
   case QUALIFIER_TOKEN:
    if (me_token_keyword() == keyword_done) {
        if (n) {
          sprintf(buf, "The average of your %d numbers is %.16g", n, sum / n);
          me_display_prompt(buf);
          me_wait_for_ack();
        }
        return;
    }
    me_token_error();
    break;
   case NUMBER_TOKEN:
    sum += me_token_number();
    n+ +;
    break;
   case NO_TOKEN:
    break;
   default:
    me_token_error();
    break;
  }
}

/*----------------------------------------------*/

void ai_initialize()
{
 static int  initialized;
 if (initialized+ +) return;
 me_new_function("AI_DEMO", ai_demo_fnc);
 keyword_done = me_new_qualifier("DONE");
}

Windows-Based Systems:

#include <math.h>
#include <setjmp.h>
#include <stdio.h>
#include <string.h>

#include "../frame.h"
#include "../model2d.h"

struct keyword *keyword_done;

/*---------------------------------------------------------------------------*/

void ai_demo_fnc()
{

  char  buf[1024];
  float64 sum = 0.0;
  int  n = 0;

  for (;;)
    switch (me_token_get("Enter a number or DONE")) {
    case COMMAND_TOKEN:
    case FUNCTION_TOKEN:
      me_token_unget();
      return;
    case QUALIFIER_TOKEN:
      if (me_token_keyword() == keyword_done) {
	if (n) {
	  sprintf(buf, "The average of your %d numbers is %.16g", n, sum / n);
	  me_display_prompt(buf);
	  me_wait_for_ack();
	}
	return;
      }
      me_token_error();
      break;
    case NUMBER_TOKEN:
      sum += me_token_number();
      n+ +;
      break;
    case NO_TOKEN:
      break;
    default:
      me_token_error();
      break;
    }
}

/*---------------------------------------------------------------------------*/

void DllExport init_load_init()
{
  me_new_function("AI_DEMO", ai_demo_fnc);
  keyword_done = me_new_qualifier("DONE");
}

Discussion of the example:

This example shows some aspects of writing action routines. It shows two functions, an initialization routine which is executed at system startup time, and the real action routine, which is called by the system if the user enters the keyword AI_DEMO.

The purpose of the initialization routine is to define two new keywords, the function keyword AI_DEMO, and a qualifier keyword DONE. The keyword pointer returned by me_new_qualifier() is remembered in a static variable, so that the action routine can later check if this keyword was entered.

The action routine itself consists of one endless loop. On top of the loop me_token_get() is used to prompt the user to enter either a number or the keyword DONE. Then the token type returned by me_token_get() is used in a switch statement to execute one of several actions depending on the token type.

case COMMAND_TOKEN:

case FUNCTION_TOKEN:

The user has requested to abort this action routine and to start another one. Therefore the token just read (the command or function) is returned to the system and the action routine is left.

case QUALIFIER_TOKEN:

The keyword pointer of the qualifier is retrieved and compared to see if it is the qualifier DONE. If yes, the real action of the action routine will be taken. The result is then presented to the user until he/she presses any key to leave the routine.

case NUMBER_TOKEN:

The numeric value of the number token is retrieved and processed.

case NO_TOKEN:

As me_token_get() does not return a token, there is nothing for the routine to do, so it loops to reissue the input request to the user.

default:

If the user has entered a token that the action routine cannot handle, it calls the general error routine and then loops to reissue the input request to the user.

Creating Macros

A macro is a named list of one or more tokens. Whenever the user types a macro name in response to an input request from an action routine, this macro name is substituted with its associated token list, and the individual tokens are then presented to the action routine.

Macro names start with an uppercase letter optionally followed by lowercase letters, digits, or the _ character.

The following is a description of routines useful for building the pieces from which macros can be made.

Finding the Pointer to a Keyword

struct keyword *me_search_keyword(name)
char *name;

This routine finds the keyword pointer of the keyword name. It returns NULL if the keyword is not defined.

Finding the Pointer to a Macro

struct macro *me_search_macro(name)
char *name;

This routine finds the macro pointer of the named macro. The macro is created if it does not exist already.

Creating the Token List

struct token *me_append_token(tokenlist, type, valueptr)
struct token *tokenlist;
int type;
void *valueptr;

This routine creates a new token of the specified type and appends it at the end of the specified token list. It returns the updated pointer to the head of the token list.

The following describes the types of tokens that may be created and the value of valueptr:

COMMAND_TOKEN
FUNCTION_TOKEN
QUALIFIER_TOKEN
ARITHM_FUNCTION_TOKEN

valueptr has to be the address of the keyword pointer

SYMBOL_TOKEN valueptr has to be the address of an integer describing the symbol type
MACRO_TOKEN valueptr has to be the address of the macro pointer
STRING_TOKEN valueptr has to be the address of a C string
NUMBER_TOKEN valueptr has to be the address of a double precision number (type float64)
POINT_TOKEN valueptr has to be the address of a 2-dimensional point (type struct fvec2)
POINT_3D_TOKEN valueptr has to be the address of a-3 dimensional point (type struct fvec3)

Create/Delete macro

void me_create_macro(name, tokenlist)
char *name;
struct token *tokenlist;

This associates the given token list with the macro name. After this a macro is defined. This will create the named macro and associate it with the given tokenlist. If a macro with the same name already existed, it will be deleted. This routine may also be used to delete a macro if tokenlist is a NULL pointer.


Note
A macro can be created within an AI routine but it cannot be executed from an AI routine.

Examples:

The following examples show both the interactive way to define macros and the programmatic approach. In each example you will see first the interactive definition (which is shorter). The benefit of the C-written solution is that it executes with higher performance.

Example 1

Macro: LET X1 12.5

C program:

double x1;
x1 = 12.5;
me_create_macro("X1", me_append_token(0, NUMBER_TOKEN, &x1));

Example 2

Macro: LET Mymacro 'Hello, world'

C program:

me_create_macro("Mymacro",me_append_token(0, STRING_TOKEN, "Hello, world"));

In this example, the token list initially is zero.

Example 3

Macro:

DEFINE Makeit
    LINE 0,0 P1
    DIM_LINE 0,0 P1 P2
END_DEFINE

C program:

struct fvec2 zero_point;
struct keyword *keyword_line;
struct keyword *keyword_dim_line;
struct macro *macro_p1;
struct macro *macro_p2;
struct token *tokenlist;

zero_point.x = zero_point.y = 0.0;
keyword_line = me_search_keyword("LINE");
keyword_dim_line = me_search_keyword("DIM_LINE");
macro_p1 = me_search_macro("P1");
macro_p2 = me_search_macro("P2");
tokenlist = (struct token *) 0;

tokenlist = me_append_token(tokenlist, COMMAND_TOKEN, &keyword_line);
tokenlist = me_append_token(tokenlist, POINT_TOKEN, &zero_point);
tokenlist = me_append_token(tokenlist, MACRO_TOKEN, &macro_p1);
tokenlist = me_append_token(tokenlist, COMMAND_TOKEN, &keyword_dim_line);
tokenlist = me_append_token(tokenlist, POINT_TOKEN, &zero_point);
tokenlist = me_append_token(tokenlist, MACRO_TOKEN, &macro_p1);
tokenlist = me_append_token(tokenlist, MACRO_TOKEN, &macro_p2);
me_create_macro("Makeit", tokenlist);

The following examples show how an arithmetic function computes the area of a circle and how a command reads and writes a macro variable.

Example 1

This arithmetic function computes the area of a circle. You can pass parameters to the arithmetic function.

#include  <math.h>
#include  <stdio.h>
#include  <setjmp.h>

#include  "frame.h"
#include  "model2d.h"

static struct token *circle_area()
{
  float64 radius = 0.0;
  struct token *token;

  token = me_eval_factor();
  if (me_type_of_token(token) == NUMBER_TOKEN)
  { radius = me_number_of_token(token);
    radius = radius * radius * me_pi;
  }
  free(token);
  return me_append_token(NULL, NUMBER_TOKEN, 
}

void init_load_init()
{
  me_new_arithm_function("CIRCLE_AREA", circle_area);
}
Windows-Based Systems: Replace void init_load_init() with void DllExport init_load_init().

Example 2

This command reads a macro variable. This is necessary if you want to inquire a macro variable within an AI program.

#include  <math.h>
#include  <stdio.h>
#include  <setjmp.h>

#include  "frame.h"
#include  "model2d.h"

static void read_macro()
{
  float64      n = 0.0;
  char         *message;
  char         variable[1024];
  struct token *token;
  struct macro *macro;

  message = "Enter a macro variable";
  if (me_token_get(message) == STRING_TOKEN)
  { strcpy(variable, me_token_string());
    macro = me_search_macro(variable);

    if (macro)
    { token = me_get_tokenlist_of_macro(macro);
      if (token & me_type_of_token(token) == NUMBER_TOKEN)
      { n = me_number_of_token(token);
        sprintf(variable, "%.15g", n);
        me_display_prompt(variable);
        me_wait_for_ack();
      }
    }
  }
}

void init_load_init()
{
  me_new_command("READ_MACRO", read_macro);
}
Windows-Based Systems: Replace void init_load_init() with void DllExport init_load_init().

Example 3

This command writes a macro variable. This is necessary if you want to overwrite a macro variable within an AI program

#include  <math.h>
#include  <stdio.h>
#include  <setjmp.h>

#include  "frame.h"
#include  "model2d.h"

static void write_macro()
{
  float64      n = 0.0;
  char         *message;
  char         variable[1024];
  struct token *token;
  struct macro *macro;

  message = "Enter a global variable";
  if (me_token_get(message) == STRING_TOKEN)
  { strcpy(variable, me_token_string());
    macro = me_search_macro(variable);

    if (macro)
    { token = me_get_tokenlist_of_macro(macro);
      if (token & me_type_of_token(token) == NUMBER_TOKEN)
      { message = "Enter new value";
        if (me_token_get(message) == NUMBER_TOKEN)
        { n = me_token_number();
          me_set_number_of_token(token, n);
        }
      }
    }
  }
}

void init_load_init()
{
  me_new_command("WRITE_MACRO", write_macro);
}
Windows-Based Systems: Replace void init_load_init() with void DllExport init_load_init().

Application Module Integration

The ME10 AI system is composed of ONE relocatable, pre-linked object code module and several header files which reflect the interface to the sub-modules of the code file.

The ME10 AI product contains the following files:

Table 3. Contents of ME10 AI Product
me10f.lib Import library file
frame.h Frame AI headers
model2d.h 2D AI headers
examples\* Application Module C-program Examples
examples\makefile Makefile for complete application linking
pers ME10F + user interface macros


Note
The optional 2D Hidden Line Removal, Parametric Design, Data Mangement System, Title Block Management, Bill of Materials Processor, the Classification Module and Links are currently NOT supported in the AI products. The same is valid for the dimensioning functionality.

UNIX-Based Systems only:
The ME10 object modules operate together with the personality files (for example, language files *.ms) at run time. This means that there is a complete set of ME10 personality files required to run the ME10 AI version.


Complete Link or Dynamic Link (UNIX-Based Systems)

There are different requirements for integrating a specific application program into ME10. There are questions like "How do I, as an application integrator, offer the application code to the end user?" - OR- "What's the mechanism to activate the application module at the customer's site ?" -OR- "How independent is my application program code from ME10 code ?"

One goal is to offer a mechanism that provides the highest possible degree of flexibility and independence from the ME10 system revisioning process. This goal is reached as follows:

Here we have to distinguish two different phases:

  1. The development phase of an AI application

    During the development phase, there is the requirement to do debugging on the code to be developed. This is possible when the ME10 code is completely linked. The function main() within ME10 is always compiled with debug mode which assures that the completely linked AI application code can be debugged if specified in the appropriate makefile.

  2. The execution/activation phase of an AI application at the customer's site

    In this phase the developed code is assumed to be stable (debugged and tested) and it is possible to integrate the application code into ME10 at runtime of ME10. This process is called Dynamic linking at run time or for short Dynamic link.

Complete Link of an AI Application (UNIX-Based Systems)

The complete link process typically will be used during the development phase of the application.

The process of linking the different relocatable object code files within a makefile results in a completely linked executable code. This is called Complete link.

In the example, the ai_demo.o module is linked together with, for example, me10ai.o, and the resulting executable is mexx. mexx is ready to run.

Within the frame module there is one complete integration hook provided which represents the interface between the CAD system ME10 AND the application module(s) to be integrated.

All the commands, functions, and keywords will be made known to the ME10 system by means of this hook.

Complete Link Command Syntax

The command syntax at the ME10 user interface/macro level is LOAD_MODULE "AI".

The module name "AI" is a reserved name.

The corresponding C function activated by this ME10 LOAD_MODULE "AI" function is ai_initialize

This function ai_initialize has to be provided once within the application program.

The function syntax is as follows:

void ai_initialize()
{
 static int initialized;
 if (initialized+ +) return;  /* inform ME10 about new functions just once*/

 /* specify here all newly to be defined Keywords, Commands and Functions */
 /* the following is an example, see ai_demo.c example file  */

 me_new_function("AI_DEMO", ai_demo_fnc);
 keyword_done = me_new_qualifier("DONE");
}

Dynamic Linking an AI Application (UNIX-Based Systems)

The command syntax of the hook at ME10 user interface/macro level is LOAD_MODULE "Application_module_name.sl"

The Application_module_name.sl is the relocatable object file to be linked. The Application_module_name can be determined by the AI-application-integrator. The ME10 system architecture supports the dynamic loading on the Series 700 with the following specifications:

The corresponding C function activated by this LOAD_MODULE statement is init_load_init

This function init_load_init has to be provided once within the application module to be linked.

The function syntax is as follows:

void init_load_init()
{
  /* provide here ALL functions, commands, keywords which will be
     made known to the system ; an example is:    */
  me_new_function("TEST", test_fnc);
}

Special Considerations for Dynamic Linking (UNIX-Based Systems)

Dynamic linking requires special understanding of some system boundary conditions. One is to satisfy all unresolved references out of libraries.

Typically ME10 has linked-in information which shared libraries are required. Very special library functionality, which an application might require in order to load and run without problems, should be linked in the relocatable dynamic loadable application.sl file. The application module must not be linked together directly with libraries. All libraries already contained in me10ai.o. are accessible for the AI application without additional linking. However, if you get error messages after

LOAD_MODULE "xxxx.sl"
concerning unresolved external references in your AI application module, then go through the following steps.
  1. Find out which external references are still missing
  2. Find the library that fits to the unresolved reference (use ar command)
  3. Extract with ar (archive) the required object file from the library
  4. Link it relocatable (ld -r) to the application.o file, then build a shared library (ld -b -o application.sl application.o).
  5. Try to execute LOAD_MODULE "xxxx.sl" again.

Linking an AI Application (Windows-Based Systems)

The command syntax of the hook at ME10 user interface/macro level is

LOAD_MODULE "Application_module_name.dll"

The Application_module_name.dll is the dynamic-link library (DLL) to be linked.) The Application_module_name can be determined by the AI-application-integrator. On PC-based systems, the ME10 system architecture supports run-time dynamic linking.

The corresponding C function activated by this LOAD_MODULE statement is init_load_init

This function init_load_init has to be provided once within the application module to be linked. The declaration DllExport declares the function for export in the DLL. Alternately, it may be declared during the linking of the DLL.

The function syntax is as follows:

void DllExport init_load_init()
{
  /* provide here ALL functions, commands, keywords which will be
     made known to the system ; an example is:    */
  me_new_function("TEST", test_fnc);
}

Development Steps for Application Set-Up

To write, compile, and link a new application module, the AI integrator has to go through the following steps.

(UNIX-Based Systems: Here it's assumed that during the AI application development the complete link facility is used. Later when the code is thoroughly tested and quality assured the dynamic link facility will be applied and tested).

  1. Specify and design your application
  2. Write an initialization routine (UNIX-Based Systems: ai_initialize) (Windows-Based Systems: init_load_init) which contains the keywords and action routine functions (commands, functions).
  3. Write the action routines which, for example, prompt the user to do further actions and/or call further functions.
  4. The error handling should be set up carefully (see ME_TRY, ME_RECOVER) in order to prevent abnormal system exceptions or terminations.
  5. Configure the makefile appropriately and make sure that ALL required modules and libraries required are linked.
  6. UNIX-Based Systems:
  7. Windows-Based Systems:
  8. Do tests and debug the application.
  9. UNIX-Based Systems:
  10. Windows-Based Systems:
  11. Test the system under specified configuration conditions (such as check RAM and swap space requirements)


Note
The function init_load_init is called during the LOAD_MODULE command. This makes it impossible to set break points in init_load_init before it is called. To debug init_load_init, use LOAD_MODULE CHECK "Application_name.dll" instead. ME10 will pause after loading the library but before calling init_load_init.

Programming Guideline and Tips

If your application uses the functions of the ME10 AI then your application program has to include the AI header files in the following order:

  #include "frame.h"
  #include "model2d.h"

Be sure that the header file include statements appear in the same order as shown above.

Here are some hints in case something goes wrong during program development.

  1. A checklist of what to do if ME10 says your new function is not defined:
    1. Was the module loaded?
    2. Is the module and file in makefile? And up to date?
    3. Check the initialization in source for incorrect syntax or names.
    4. Check the actual code for the function.

  2. UNIX-Based Systems: The most effective (but primitive) way to debug the code is with a liberal application of printf statements, variable values and fflush's.

  3. Upon segmentation violation - check the variables in that area. Make sure all have their memory space declared explicitly. This is a common mistake to forget to save space and just provide a pointer for some routine.

  4. Use normal disciplined software development techniques such as adding comments at suitable points in the program.

Example of the makefile on a Series 400 workstation:

CFLAGS = -g -I. -I/usr/include/X11R4 -I/usr/include/X11 \
                    -Aa -D_HPUX_SOURCE
                    -Dhpux -Dhp9000s300
ME_MODULES = me10ai.o
AI_MODULES = ai_demo.o
LIBS = -L/usr/lib/X11R4\
       -ldld\
       -lXwindow \
       -lsb \
       -lXhp11 \
       -lX11 \
       -L/usr/PE/lib300 -lsi \
       -iI077
       -lF77 \
       -lI77 \
       -lm \
       -ln

mexx_deb: $(AI_MODULES)
        rm -f mexx
        cc -g -q -Wl,-E,-X 16000\
        $(ME_MODULES)\
        $(AI_MODULES)
        $(LIBS)
        /usr/lib/end.o

mexx: $(AI_MODULES)
        rm -f mexx
        cc -g -q -Wl,-E,-X 16000\
        $(ME_MODULES)
        $(AI_MODULES)
        $(LIBS)\
        -o mexx

ai_demo.o: ai_demo.c
        cc -c $(CFLAGS) -o ai_demo.o ai_demo.c

Example of the makefile for Microsoft® Visual C++® Version 1.0:

CC = cl

CFLAGS = /nologo /Zi /D _DEBUG /D __WinNT /D DYN /D WANT_PROTOTYPES
LFLAGS = /nologo /DEBUG:FULL /DEBUGTYPE:cv ..\me10f.lib
AI_HEADER = ..\frame.h ..\model2d.h

ai_demo.dll:	ai_demo.obj
	link $(LFLAGS) ai_demo.obj -DLL -OUT:ai_demo.dll

ai_demo.obj:	ai_demo.c $(AI_HEADER)
	$(CC) $(CFLAGS) /c ai_demo.c

Dynamic Unlink of an AI Application (UNIX-Based Systems)

The command syntax of the hook at ME10 user interface/macro level is UNLOAD_MODULE "Application_module_name.sl".

The Application_module_name.sl is the relocatable object file to be unlinked. The Application_module_name can be determined by the AI-application-integrator. The ME10 system architecture supports the dynamic unloading on the Series 700 with the following specifications:

The corresponding C function activated by this UNLOAD_MODULE statement is init_unload_init.

This function init_unload_init has to be provided once within the application module to be unlinked.

The function syntax is as follows:

int init_unload_init(int *mode,
                     char **product_name,
                     char **partner_key,
                     char **product_key,
                     void *dummy)

If Application_module_name.sl wants to be unloaded this function has to return 1. Otherwise the unlink will be aborted.

The parameters have the following meaning:

  mode              must be set to 1
  product_name      see ME-LS Access Kit, me_access_license_server()
  partner_key       see ME-LS Access Kit, me_access_license_server()
  product_key       see ME-LS Access Kit, me_access_license_server()
  dummy             for future use

Example:

    int init_unload_init(int *mode,
                         char **product_name,
                         char **partner_key,
                         char **product_key,
                         void *dummy)
    {

    /*** [1] free all dynamic data ***/

    /*** [2] unsubscribe from all events ***/

    /*** [3] supply return values ***/

    *mode = 1;
    *product_name = "My_application_1";
    *partner_key =  "1Partnr1";
    *product_key  = "1Prodct1";

    /*** [4] all ok for unload ***/

    return 1;
}

All functions and commands of the loadmodule will automatically be disabled during the unlink. Finally, the system releases the license that has been granted to the loadmodule before with a call of me_access_license_server() (see ME-LS Access Kit) and removes the loadmodule from the memory.

Dynamic Unlink of an AI Application (Windows-Based Systems)

The command syntax of the hook at ME10 user interface/macro level is UNLOAD_MODULE "Application_module_name.dll".

The Application_module_name.dll is the relocatable object file to be unlinked. The Application_module_name can be determined by the AI-application-integrator. The ME10 system architecture supports the dynamic unloading on PC-based systems with the following specification:

The corresponding C function activated by this UNLOAD_MODULE statement is init_unload_init.

This function init_unload_init has to be provided once within the application module to be unlinked.

The function syntax is as follows:

int DllExport init_unload_init(int *mode,
                               char **product_name,
                               char **partner_key,
                               char **product_key,
                               void *dummy)

If Application_module_name.dll wants to be unloaded this function has to return 1. Otherwise the unlink will be aborted.

The parameters have the following meaning:

  mode              must be set to 1
  product_name      see ME-LS Access Kit, me_access_license_server()
  partner_key       see ME-LS Access Kit, me_access_license_server()
  product_key       see ME-LS Access Kit, me_access_license_server()
  dummy             for future use

Example:

    int DllExport init_unload_init(int *mode,
                                   char **product_name,
                                   char **partner_key,
                                   char **product_key,
                                   void *dummy)
    {

    /*** [1] free all dynamic data ***/

    /*** [2] unsubscribe from all events ***/

    /*** [3] supply return values ***/

    *mode = 1;
    *product_name = "My_application_1";
    *partner_key =  "1Partnr1";
    *product_key  = "1Prodct1";

    /*** [4] all ok for unload ***/

    return 1;
}

All functions and commands of the loadmodule will automatically be disabled during the unlink. Finally, the system releases the license that has been granted to the loadmodule before with a call of me_access_license_server() (see ME-LS Access Kit) and removes the loadmodule from the memory.

Housekeeping

There is a function that provides the ME10 revision control string and the ME10 product name. This facility enables the application writer to check if the application fits together with a given ME10 revision at the customer's site.

Feedback

What is Feedback from a user's point of view?

It is a graphical support tool for interactive user input either by a mouse or tablet.

Feedback is all that can be dynamically or statically attached temporarily, for example, to the cursor while setting up or modifying the CAD model interactively.

What is Feedback from an internal system point of view?

Feedback consists of a model containing the graphical data and a procedure that updates the graphical model and draws it on the screen. Feedback model is directly dependent on an action routine. It exists as long as an action routine is active, which means it is owned by an action routine.

Whenever an action routine awaits user input and the cursor steered by the graphic input device changes its position, the feedback update procedure is called with the name of the feedback model of the cursor position as a parameter.

The name of this graphic model is "me_cursor_fdbck_model".

A feedback model consists of an ordered list of sub-models.

An action routine can create feedback sub-models, which are active when the action routine is active. Feedback sub_models, when active, are drawn on the screen and updated. They are inactive, when the action routine is interrupted by another action routine. They are automatically deleted, when the action routine is terminated.

Feedback Sub-Models

The components of a feedback sub-model are :

Feedback Viewport-Lists

The viewport lists specify in which viewports the submodel is to be drawn. There are predefined feedback viewport lists provided by the owners of the viewports, for example, viewports of the 2D model.

Feedback Model Matrix

When a feedback sub-model is drawn on the screen and no model matrix has been specified for the sub-model, the model to screen coordinate mapping set by the owner of the viewport is used.

If the feedback sub-model needs to be specified in a coordinate system other than that set by the viewport owner, the model matrix of the sub-model must be defined. The model matrix is taken to be the transformation from the feedback sub-model to the coordinate system of the viewport owner.

Feedback Points

The feedback points determine the movements of the graphical feedback sub-model. They can reference each other.

There are different types of feedback points :

Fixed points are independent of other feedback points and have a fixed postion on the screen.

Translation points reference two feedback points. Their x and y coordinates have a fixed distance from the x and y coordinates respectively of their reference points.

Rotation points reference three feedback points. The first is the center about which they rotate. The second and the third are the reference points, that determine respectively their polar coordinates r and phi relative to the first point. Coordinate transformation points are needed if a feedback point in another feedback sub-model with a different coordinate system is to be referenced. They perform a coordinate transformation.

There is a special predefined feedback point which represents the cursor position on the screen. It is called "me_cursor_fdbck_pnt" which provides the screen coordinates of the cursor position.

For routines, see FDBCKPNT in ME10 AI Reference.

Feedback Elements

Feedback elements join up feedback points. They are the visible elements on screen and reference feedback points.

Three types of feedback elements are supported:

Maximal Feedback

There is a maximum complexity for a feedback model. This maximum value can be specified interactively in ME10 with the function called "max_feedback". If this maximum value is reached by a feedback model, then no further moving elements or points can be added to a sub-model of "me_cursor_fdbck_model.". However, the feedback tree in "me_cursor_fdbck_model" can still be accessed.

There is no AI routine available to adjust this value. It can be done via the Macro to AI communication.

Related Functions

Mathematical Basics

To support general geometrical calculations, the AI provides some basics for 3D vector and matrix algebra. The 2D modeler is treated as being 3D with the third component set to zero. (You, as a user of AI, should take care of this, especially if you handle 2-dimensional data. In this case the Z- coordinates should be consistently defined to be 3D compatible (Z coordinates should be pre-set to zero).

When using vector and matrix functions, the following boundary conditions should be kept in mind:

  1. Vectors are of type struct fvec3 with
    struct fvec3 {
      float64 x,
              y,
              z;
    }
    

  2. Matrices are packed into objects of type geo_operator_3. In the following, we will refer to this object as geo operator.

  3. Vectors and geo operators are passed by reference in parameter lists of functions. (Pointers to these objects are passed rather than the objects themselves).

  4. All functions returning either vectors or geo operators assume that space for these objects has been allocated by the calling function. Memory allocation is usually done by declaring appropriate variables in the calling program, for example, by malloc.

  5. If a vector or geo operator is returned, the pointer to it is additionally returned as a result of the function to allow nesting with other functions that demand a pointer to a vector or geo operator as input.

Units and Resolution

  1. The standard length unit is millimeter (mm). The standard angle unit is radian(rad).
  2. The maximum possible accuracy of a model is determined by me_resolution if not defined otherwise in the function descriptions.

Vector Algebra

Vector algebra is one of the fundamental concepts for the 2D/3D functionality. For vector algebra functions, no distinction is made between points and vectors. Both have the same data structure, therefore they can be treated in the same manner. Thus, if we talk about a point, we mean a vector from the origin to that point.

Predefined Vectors

Some often used vectors are already predefined:


Related Functions

Matrix Algebra

Matrices are part of geo operators which consist of:


The 4x4 matrix notation is a convenient way to deal with transformations of the type:

General Transformation


When a homogenous 4x4 matrix is used to transform a 3D vector, the vector is first converted into a homogenous vector, second multiplied with the 4x4 matrix, and third reconverted into a 3D vector. That is:

Mapping Homogenous Vectors


with

s' = p__1__x + p__2__y + p__3__z + s

Predefined Matrices

The identity matrix is predefined and is denoted by the symbol me_idn_operator.

Predefined Identity Operator


Related Functions

AI Version Control

To enable an AI application to know the revision of the AI product, a function is available to return the name and the revision of the AI product.

Related Functions


[Previous]   [Next]   [Contents]   [Index]   [Books]