Mechanical Modeler

Part Design

Implementing a Mechanical Design Feature Building

Implementing the CATIBuild and CATIBuildShape interfaces
Use Case

Abstract

This article discusses the CAAPriUserPad use case. This use case explains how to implement the CATIBuild and CATIBuildShape interfaces for mechanical design features. A simplified pad feature is used as a mechanical feature as example. A knowledge of the Mechanical Modeler [1] is strongly recommended. 


What You Will Learn With This Use Case

This use case is intended to help you make your first steps in programming with Part Design. Its main intent is to introduce important concepts about the way to implement the CATIBuild and CATIBuildShape interfaces of Mechanical Design feature. Specifically, you will learn how to:

Before getting to this use case itself, refer to the article "Integrating a New Geometrical Feature in the Update Mechanism" [2] which explains in details how to implement the CATIBuild and CATIBuildShape interfaces.

[Top]

The CAAPriBuildUserPad Use Case

CAAPriBuildUserPad is a use case of the CAAPartInterfaces.edu framework that illustrates the PartInterfaces and MechanicalModeler frameworks capabilities.

[Top]

What Does CAAPriBuildUserPad Do

The goal of CAAPriBuildUserPad is to show how to implement the CATIBuild and CATIBuildShape interfaces on a given form feature, namely a user pad. The user pad already exists as a StartUp in the CAAPriFormFeature catalog and has the type CAAPriUserPad. It is a form feature, in other words the CAAPriUserPad StartUp derives from the MechanicalFormFeature StartUp [3].

Fig.1 The hierarchy of StartUps

The CAAPriBuildUserPadMain.m module contains a main program that creates a Part document, instantiates the CAAPriUserPad StartUp, calls its Build method, saves the resulting Part document Fig.2, instantiates again the CAAPriUserPad StartUp with a new sketch, calls its Build method, and saves the resulting Part in a second Part document Fig.3.

Fig.2 The First Saved Pad
Fig.3 The Second Saved Pad

The Build in Details

Build a feature consists in to create a result. A result is:

The following schema explains in details the construction of a form feature. A form feature is a solid feature (in opposite to a surfacic feature) which is a chain link. These links are chained together by the ResultIN and ResultOUT attributes. The ResultIN attribute of a solid feature references the ResultOUT attribute of the previous feature in the chain. Refer to the article entitled "Specification/Result Mechanism Applied to Mechanical Feature" [5] for complete details about the ResultIN and ResultOUT attributes.

Fig.4: Form Feature Build

[Top]

How to Launch CAAPriBuildUserPad

To launch CAAPriBuildUserPad, you will need to set up the build time environment, then compile CAAPriBuildUserPad along with its prerequisites, set up the run time environment, and then execute the use case [6].

Launch the use case as follows:

where:

outputDirectory The directory into which CAAUserPad1.CATPart and CAAUserPad2.CATPart will be stored
CAAUserPad1.CATPart The file that contains the pad created
CAAUserPad2.CATPart The file that contains the pad after it is modified

[Top]

Where to Find the CAAPriBuildUserPadMain Code

The CAAPriBuildUserPadMain use case is made of a main program named CAAPriBuildUserPad and located in the CAAPriBuildUserPadMain.m module of the CAAPartInterfaces.edu framework. The CATIBuild and CATIBuildShape interface implementations are located in the CAAPriBuildUserPad.m module of the same framework.

Windows
InstallRootDirectory\CAAPartInterfaces.edu\CAAPriBuildUserPad.m\
InstallRootDirectory\CAAPartInterfaces.edu\CAAPriBuildUserPadMain.m\
Unix
InstallRootDirectory/CAAPartInterfaces.edu/CAAPriBuildUserPad.m/
InstallRootDirectory/CAAPartInterfaces.edu/CAAPriBuildUserPadMain.m/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed.

[Top]

CATIBuild Implementation Step-by-Step

CATIBuild is implemented using a class named CAAPriEBuild class that is a code extension of the late type CAAPriUserPadBuild, the unique method of this interface has always this structure:

...
HRESULT CAAPriEBuild::Build ()
{
   HRESULT rc = E_FAIL ;
   
   Declaring the Useful Pointers
   
   CATTry
   {
      Computing the Form of the Feature 
      Removing all Possible Update Errors
      Retrieving Data for the Procedural Report
      Creating the Procedural Report
      Running the Topological Operators 
      Storing the Procedural Report
      Cleaning the Useless Data
   }
   
   // Managing the Errors
   
   CATCatch(CATMfErrUpdate , pUpdateError)  
   {
      Managing the CATMfErrUpdate Error
   }
   CATCatch(CATError , pError)
   {
      Managing the CATError Error
   }
   
   CATEndTry
   
   return rc ;
}
...

This method contains a CATTry and CATCatch sections because some methods can throw an error [7].

[Top]

Declaring the Useful Pointers

Before the CATTry section you declare all the pointers:

...
    CATIUpdateError          * piUpdateErrorOnThis             = NULL;
    CATIBuildShape           * piBuildShape                    = NULL;

    CATIMfProcReport         * piProcReport                    = NULL;
    CATGeoFactory            * piGeomFactory                   = NULL;
    CATDynBoolean            * pOperatorBool                   = NULL;

    CATSoftwareConfiguration * pSoftConfig                     = NULL ;
    
    rc = QueryInterface( IID_CATIUpdateError , (void**) &piUpdateErrorOnThis);
    if ( FAILED(rc) ) return rc ;
...

All this pointers will be explained in the next sections. 

[Top]

Computing the Form of the Feature

Before to compute the final result of the feature, its form is necessary. It is computed thanks to the BuildShape method. 

...
       CATIBuildShape * piBuildShape = NULL;
       rc = QueryInterface(IID_CATIBuildShape,(void**)&piBuildShape);
       if ( SUCCEEDED(rc) )
       {
           int val = piBuildShape->BuildShape();
           if ( 0 == val )
           {
              rc = E_FAIL ;
           }
           piBuildShape->Release();
           piBuildShape = NULL ;
       }
...

The BuildShape method can throw an error or return an error. 

[Top]

Removing all Possible Update Errors

It is safer to remove all possible update error that may be associated to the current User Pad feature. To do so, use the UnsetUpdateError of the CATIUpdateError interface. Refer to the article entitled "A Description of Update Errors" [8] for details on this interface.

...
       rc = QueryInterface( IID_CATIUpdateError , (void**) &piUpdateErrorOnThis);
       if ( SUCCEEDED(rc) )
       {
          piUpdateErrorOnThis->UnsetUpdateError();
       }
...

The implementation of CATIUpdateError interface for the User Pad is provided by an extension of late type MechanicalFeature. Since UserPad late type derives from MechanicalFeature late type, see the Fig.1, you automatically benefit from this implementation. 

[Top]

Retrieving the Data for the Procedural Report

This step consists in three sub-steps which are :

Retrieving the ResultIN feature
...
       CATIShapeFeatureBody * pIShapeFeatureBodyOnThis = NULL ;
       if ( SUCCEEDED(rc) )
       {
          rc = QueryInterface( IID_CATIShapeFeatureBody,(void**) &pIShapeFeatureBodyOnThis);
       }
       
       CATISpecObject_var  spResultIn ;
       if ( SUCCEEDED(rc) )
       {
             CATListValCATISpecAttribute_var *pListSpecAttribute = NULL ;
             pListSpecAttribute = pIShapeFeatureBodyOnThis->GetBodyINAttributes();
             
             if ( NULL != pListSpecAttribute )
             {
                CATISpecAttribute_var spSpecAttribute = (*pListSpecAttribute)[1];

                if ( NULL_var != spSpecAttribute )
                {
                   spResultIn = spSpecAttribute->GetSpecObject();
                }
                ...
             }
       }
...

The form feature implements the CATIShapeFeatureBody (MechanicalModeler) interface. This interface enables you to retrieve the ResultIN attribute associated with the feature. This attribute, spSpecAttribute, is always the first element of the list returned by the GetBodyINAttributes method. As usual, to retrieve the feature referenced by the attribute use the GetSpecObject method of the CATISpecAttribute (ObjectSpecsModeler) interface. spResultIn will be one of the two elements following by the procedural report. The second is this.

Retrieving the two CATBody  (of ResultIN and this) 

The first is those associated with the ResultIN feature. In the Fig.4, it is the CATBody named TopoA. You always use the CATIShapeFeatureBody (MechanicalModeler) interface. The first element of the list returned by the GetBodyIN method is the CATBody of the ResultIN feature, spCATBodyOnResultIn.

...
       CATBody_var spCATBodyOnResultIn  ; 
       if ( SUCCEEDED(rc) )
       {
          CATListValCATBaseUnknown_var *pListBodyIn = NULL ;
          pListBodyIn = pIShapeFeatureBodyOnThis->GetBodyIN("CATBody");

          if ( NULL != pListBodyIn )
          {
             spCATBodyOnResultIn = (*pListBodyIn)[1];
             ...
          }
       }
...

The second is those associated with this. It is the form computed by the BuildShape method. In the Fig.4, it is the CATBody named TopoC. You always use the CATIShapeFeatureBody (MechanicalModeler) interface. The first element of the list returned by the GetShape method is the CATBody of this, spCATBodyOnThis.

...
       CATBody_var  spCATBodyOnThis ;
       if ( SUCCEEDED(rc) )
       {
          CATListValCATBaseUnknown_var *pListBody = NULL ;
          pListBody = pIShapeFeatureBodyOnThis->GetShape("CATBody");

          if ( NULL != pListBody )
          {
             spCATBodyOnThis = (*pListBody)[1];
             ...
          }
       }
...

Checking the Data

If the ResultIN feature does not exist and the form exists, the form feature is the first of the chain, so the build operation is done. The "Creating the Procedural Report", "Run the Topological Operators" and "Storing the Procedural Report" sections are skipped. 

If the form does not exist, it is an error, the returned code of the Build method will be E_FAIL. 

[Top]

Creating the Procedural Report

The procedural report is the means to generate the scope of the feature by using the topological report to generate the name of the following cells. The procedural report is managed by the CATIMfProcReport interface. 

The first thing is to declare the following cells by the procedural journal during the Build operation. In the case of a form feature, the specifications to follow are always this, and if the the body exists for ResultIN, ResultIN too.  

...
          CATLISTV(CATBaseUnknown_var) ListSpec;
          CATListOfCATUnicodeString    ListKeys;
          
          ListSpec.Append( this ); 
          ListKeys.Append( MfKeyNone  );
          if (NULL_var != spCATBodyOnResultIn)
          {
                ListSpec.Append( spResultIn); 
                ListKeys.Append( MfKeyNone );
          }
...

ListSpec is the list of specifications to follow, and ListKeys is the list of associated keys. These two lists have the same size. The default value of a key is MfKeyNone. A different key value will indicate that the historical relationship of a node should be replaced with a user information. The value of the key must be in relationship with the information given by the topological report.

...
       if ( SUCCEEDED(rc) )
       {
          rc = QueryInterface( IID_CATIMfProcReport , (void**) &piProcReport );
          if ( SUCCEEDED(rc) )
          {
             int BoolOper = 1;
             piProcReport->CreateProcReport(ListSpec,ListKeys,BoolOper); 
          }
       }
...

Once the CATIMfProcReport interface pointer on the User Pad is retrieved, piProcReport, you can create the procedural report thanks to the CreateProcReport method. The last argument of this method is 1 because the result ( the scope ) will be affected to the solid feature and not the user pad itself. On the Fig.4 this solid feature is named SolidB. Note that piProcReport is declared at the top of the Build method because it can be released in a CATCatch section.

[Top]

Running the Topological Operators

This step consists in three sub-steps which are always:

Retrieving the Geometrical Factory Interface

The geometrical factory is handled by the CATGeoFactory interface. This interface is implemented by the geometrical container of the Part document [9]. You retrieve this container thanks to the CATIContainerOfDocument interface implemented on the Part document. The CATILinkableObject interface is the means for each feature to retrieve its containing document.

...
       if ( SUCCEEDED(rc) )
       {
          CATILinkableObject *piLinkableObjectOnUserPad= NULL;
          rc = QueryInterface( IID_CATILinkableObject, 
                               (void**)& piLinkableObjectOnUserPad);
          
          if ( SUCCEEDED(rc) )
          {
             CATDocument * pDocument = NULL ;
             pDocument = piLinkableObjectOnUserPad->GetDocument();
   
             if ( NULL != pDocument )
             {
                CATIContainerOfDocument * pIContainerOfDocument = NULL ;
                rc = pDocument->QueryInterface(IID_CATIContainerOfDocument, 
                                                   (void**)& pIContainerOfDocument );
                if ( SUCCEEDED(rc) )
                {
                   CATIContainer * pIContainerOnGeomContainer = NULL ;
                   rc = pIContainerOfDocument->GetResultContainer
                                                          (pIContainerOnGeomContainer);
                   if ( SUCCEEDED(rc) )
                   {

                      rc = pIContainerOnGeomContainer->QueryInterface( IID_CATGeoFactory , 
                                                               (void**) &piGeomFactory );
                      ...
       }
...

The GetResultContainer is the method of the CATIContainerOfDocument to retrieve the geometrical container. piGeomFactory is the pointer on the geometrical factory interface. This pointer is declared at the beginning of the Build method because it can be released in a CATCatch section.

Retrieving the Topological Journal

The procedural report then provides a pointer on a new topological journal that will log all topological operations.

...
       CATTopData TopData ;
       if ( SUCCEEDED(rc) )
       {
          CATCGMJournalList *pCGMJournalList = piProcReport->GetCGMJournalList();  
          TopData.SetJournal(pCGMJournalList) ;

          pSoftConfig = new CATSoftwareConfiguration();
          TopData.SetSoftwareConfiguration(pSoftConfig) ;
       }
...

pCGMJournalList is the pointer on the topological journal. This pointer must not be released. pSoftConfig is a pointer declared at the beginning of the Build method because it can be released in a CATCatch section.

Creating the Resulting Geometry

This section consists in to valuate, pResultBody, a CATBody instance. This pointer is declared locally, and is not declared at the top of the method. It is not necessary since its lifecycle is managed by the DeletedProcReport method in the CATCatch sections.

...
          CATBody   *pResultBody = NULL ;

          ....
...

There are two cases two consider:

  1. The user Pad is not the first solid feature of the set

    spCATBodyOnResultIn is the CATBody associated with the ResultIN feature, if this smart pointer is not null, the user pad has a RESULTIN , so it is not the first solid feature of the body feature.

    ...
                 if (NULL_var != spCATBodyOnResultIn)
                 {
                 CATDynBooleanType internalOperType = CATBoolUnion;
       
                 pOperatorBool = ::CATCreateDynBoolean(piGeomFactory,
                                                    &TopData,
                                                    internalOperType,
                                                    spCATBodyOnResultIn,
                                                    spCATBodyOnThis);
    
                 if ( NULL != pOperatorBool )
                 {
                    pOperatorBool->Run();
                    pResultBody = pOperatorBool->GetResult();
                 }
              }
    ...

    A boolean operation is performed between the User Pad feature shape (spCATBodyOnThis) and the topological result of the previous feature (spCATBodyOnResultIn). The topological journal which is the second argument of the CATDynCreateBoolean global function is also updated. pOperatorBool is a CATDynBoolean interface pointer declared at the top of the Build method. pResultBody is the resulting topology, the CATBody named TopoB on the Fig.4

  2. The User Pad is the first solid feature in the set
  3. The body associated with the result is the body created by the CATIBuildShape interface. But since a topological result can only be associated with an unique geometrical feature, a new CATBody is created. Nevertheless, if a CATBody is unique for a geometrical feature, cells can be shared between two CATBody. So the resulting CATBody will be created using the cells (the domains) of the body created by  the CATIBuildShape interface.

    ...
              pResultBody = piGeomFactory->CreateBody();
              if ( NULL != pResultBody )
              {
                 CATDomain *Domain = NULL;
                 int NbDomain = spCATBodyOnThis->GetNbDomains();
    
                 for (int i = 1; i <= NbDomain; i++)
                 {
                    Domain = spCATBodyOnThis->GetDomain(i);
                    pResultBody->AddDomain(Domain);
                  }
              }
    ...

    spCATBodyOnThis is the smart pointer on the CATBody created by the CATIBuildShape interface. The valuation of this pointer has been done in the Retrieving the two CATBody  (of ResultIN and this  section.

[Top]

Storing the Procedural Report

It is now high time to store (fill) the procedural report corresponding to the creation of the geometric result of the User Pad. That's the job of the CATIMfProcReport::StoreProcReport method.

  ...
          if ( SUCCEEDED(rc) )
          {
             if ( NULL != pResultBody )
             {
                int BoolOper = 1 ;  
                piProcReport->StoreProcReport(pResultBody,Copy, BoolOper); 
             }
             else
             {
                CATMfErrUpdate *pErrorNoIntersection = new CATMfErrUpdate();
                CATUnicodeString Diagnostic("Error during boolean operation.");
                pErrorNoIntersection->SetDiagnostic(1,Diagnostic);

                CATThrow(pErrorNoIntersection);
             }
          }
       }
  ...

The last argument of the StoreProcReport method, BoolOper, is the same as the value in the CreateProcReport method. 

[Top]

Cleaning the Useless Data

In this last part of the CATTry section, you clean the data declared in the first section entitled "Declaring the Useful Pointers" and not released/deleted during the CATTry section. For example, the piBuildShape pointer is not released here, once if the BuildShape method do not throw an error, the pointer is released just after the BuildShape call. See the "Computing the Form of the Feature" section.

Generally, you have to consider: 

Managing the Error

Some errors may be thrown during these previous operations, the CATTry bloc catches them. The CATCatch blocks treats the error. There are two kinds of errors:

Each CATCatch section processes the error and cleans the pointers declared at the top of the Build method.

Managing the CATMfErrUpdate Error

The highest-level errors are of type CATMfErrUpdate. The error is re-thrown without modification.

...
    CATCatch ( CATMfErrUpdate , pUpdateError)
    {
        if(NULL != piUpdateErrorOnThis) 
        {
            piUpdateErrorOnThis->SetUpdateError(pUpdateError);

            piUpdateErrorOnThis->Release();
            piUpdateErrorOnThis = NULL ;
        }

        // Here the pointers declared at the top of the Build method are cleaned
        
        CATRethrow ;
     }
...
Managing the CATError Error

All other types of errors derive from CATError. The following code associates the diagnostic and the error.

...
    CATCatch ( CATError , pError) 
    {

        CATMfErrUpdate *pErrorToThrow = new CATMfErrUpdate();
        pErrorToThrow->SetDiagnostic(1,pError->GetNLSMessage());

        ::Flush(pError);

        if(NULL != piUpdateErrorOnThis) 
        {
            piUpdateErrorOnThis->SetUpdateError(pErrorToThrow);

            piUpdateErrorOnThis->Release();
            piUpdateErrorOnThis = NULL ;
        }

        // Here the pointers declared at the top of the Build method are cleaned

        CATThrow(pErrorToThrow);
    }   
    ...

A new CATMfErrUpdate is created. pError, the CATError, must be released in the error process. The Flush global function do that.

Cleaning the Pointers

In the two CATCatch sections it is important to :

and for the data declared in the first section entitled "Declaring the Useful Pointers":

[Top]

CATIBuildShape Implementation Step-by-Step

CATIBuildShape is implemented using a class named CAAPriEBuildShape class that is a data extension of the late type CAAPriUserPadBuildShape, the unique method of this interface has always this structure:

...
int CAAPriEBuildShape::BuildShape ()
{
   int rcode = 1 ; //OK
   HRESULT rc = E_FAILD;
   
   Declaring the Useful Pointers
   
   CATTry
   {
      Removing all Possible Update Errors
      Retrieving Data for the Procedural Report
      Creating the Procedural Report
      Running the Topological Operator
      Storing the Procedural Report
      Cleaning the Useless Data
   }
   
   // Managing the Errors
   
   CATCatch(CATMfErrUpdate , pUpdateError)  
   {
      Managing the CATMfErrUpdate Error
   }
   CATCatch(CATError , pError)
   {
      Managing the CATError Error
   }
   
   CATEndTry
   
   if ( FAILED(rc) )
   {
       rcode = 0 ;
   }

   return rcode ;
}
...      

This method contains a CATTry and CATCatch sections because some methods can throw an error [7].

[Top]

Declaring the Useful Pointers

Before the CATTry section you declare all the pointers:

...
    CATIUpdateError          * piUpdateErrorOnThis        = NULL;

    CATTopPrism              * pOperatorPrism             = NULL;
    CATIPrtProfile           * pPrtProfile                = NULL;

    CATIMfProcReport         * piProcReport               = NULL;
    CATGeoFactory            * piGeomFactory              = NULL;
    CATSoftwareConfiguration * pSoftConfig                = NULL ;

    CATBody_var                spBodyOnProfile ;
...

All this pointers will be explained in the next sections.

[Top]

Removing all Possible Update Errors

It is safer to remove all possible update error that may be associated to the current user pad feature. To do so, use the UnsetUpdateError of the CATIUpdateError interface.

...
       rc = QueryInterface( IID_CATIUpdateError , (void**) &piUpdateErrorOnThis);
       if ( SUCCEEDED(rc) )
       {
          piUpdateErrorOnThis->UnsetUpdateError();
       }
...

[Top]

Retrieving the Data for the Procedural Report

This step consists in three sub-steps which are:

Retrieving the Profile 

The profile is an attribute of the UserPad feature and referenced in the "Profile" string. 

...
       CATMathDirection   ExtrusionDirection ;
       CATISpecObject_var spSpecObjectOnProfileElt;

       if ( SUCCEEDED(rc) )
       {
          CATISpecObject  * pSpecObjectOnThis = NULL;
          rc = QueryInterface( IID_CATISpecObject , (void**) &pSpecObjectOnThis );
          if ( SUCCEEDED(rc) )
          {
              CATUnicodeString strProfile = "Profile";
              CATISpecAttribute * pProfileAtt = NULL ;
              pProfileAtt = pSpecObjectOnThis->GetAttribute(strProfile);

              pSpecObjectOnThis->Release();
              pSpecObjectOnThis = NULL ;

              if ( NULL != pProfileAtt )
              {
                 CATISpecObject  * pSpecObjectOnProfileAtt = NULL;
                 pSpecObjectOnProfileAtt = pProfileAtt->GetSpecObject();

...

pProfileAtt is the "profile" attribute of the User Pad. pSpecObjectOnProfileAtt is the feature associated with this attribute. The CATIPrtProfile interface applied to pSpecObjectOnProfileAtt enables you to retrieve the direction of extrusion, ExtrusionDirection and the profile itself, spSpecObjectOnProfileElt. 

...
                 if ( NULL != pSpecObjectOnProfileAtt )
                 {
                    rc = pSpecObjectOnProfileAtt->QueryInterface( IID_CATIPrtProfile , 
                                                           (void**) &pPrtProfile );

                    pSpecObjectOnProfileAtt->Release();
                    pSpecObjectOnProfileAtt = NULL ;
                    
                    if ( SUCCEEDED(rc) )
                    {
                       CATMathPlane SketchPlane ;
                       rc = pPrtProfile->GetPlane(SketchPlane) ;
                       if ( SUCCEEDED(rc) )
                       {  
                          CATMathVector normalDir;
                          
                          SketchPlane.GetNormal(normalDir);
                          ExtrusionDirection = normalDir ;

                          if ( SUCCEEDED(rc) )
                          {
                              pPrtProfile->GetElement(1,spSpecObjectOnProfileElt) ;                       
...

The Pad direction, ExtrusionDirection, has been defined normal to the sketch plane. The profile, spSpecObjectOnProfileElt, retrieved by the GetElement method of the CATIPrtProfile interface will be the feature followed by the procedural report.

To be complete, if spSpecObjectOnProfileElt, pSpecObjectOnProfileAtt or  pProfileAtt are NULL or NULL_var, an update error [8] is thrown like this: 

...
     CATMfErrUpdate *pError = new CATMfErrUpdate();
     CATUnicodeString Diagnostic("xxxxx");
     pError ->SetDiagnostic(1,Diagnostic);
   
     CATThrow(pError );
...

In this case the CATTry section in interrupted. 

Retrieving and Checking the CATBody associated with the Profile

pPrtProfile is the CATIPrtProfile interface pointer on the feature referenced by the Profile attribute of the User Pad. This part consists in to compute the CATBody forming the profile to extrude, spBodyOnProfile. But previously some checks are necessary to validate the profile.

...
       if ( SUCCEEDED(rc) )
       {
          int nbContour = pPrtProfile->GetContourCount();
          if (nbContour == 1)
          {	
              CATBody_var LocalBody ;
              pPrtProfile->GetBody(0,LocalBody);

              CATDomain * pDomain = LocalBody->GetDomain(1);
              CATWire_var spWireOnDomain(pDomain);
              if (spWireOnDomain != NULL_var)
              {
                 CATBoolean isClosed = spWireOnDomain->IsClosed();
                 if(TRUE != isClosed) 
                 {
                    CATMfErrUpdate *pErrorNotClosedProfile = new CATMfErrUpdate();
                    CATUnicodeString Diagnostic("The associated profile is not closed");
                    pErrorNotClosedProfile->SetDiagnostic(1,Diagnostic);

                    CATThrow(pErrorNotClosedProfile);
                 } 
...

If the profile is wrong an error, pErrorNotClosedProfile, is generated and thrown to interrupt the process.

Once the Profile is validated, spBodyOnProfile is computed by the GetBody method of the CATIPrtProfile interface. This CATBody should be removed from the topological container at the end of the method.

...
                    pPrtProfile->GetBody(1,spBodyOnProfile);

                    if ( NULL_var == spBodyOnProfile )
                    {
                       CATMfErrUpdate *pErrorNoProfileToExtrude = new CATMfErrUpdate();
                       CATUnicodeString Diagnostic("No elt to extrude");
                       pErrorNoProfileToExtrude->SetDiagnostic(1,Diagnostic);
   
                       CATThrow(pErrorNoProfileToExtrude);
...

[Top]

Creating the Procedural Report

The procedural report is the means to generate the scope of the feature by using the topological report to generate the name of the following cells. The procedural report is managed by the CATIMfProcReport interface. The first thing is to declare the following cells by the procedural journal during the Build operation. 

...
       CATLISTV(CATBaseUnknown_var) ListSpec;
       CATListOfCATUnicodeString    ListKeys;
       if ( SUCCEEDED(rc) )
       {
             ListSpec.Append( spSpecObjectOnProfileElt ); 
             ListKeys.Append( MfKeyExtrudedFrom  );
       }
...

ListSpec is the list of specifications to follow, and ListKeys is the list of associated keys. There is only one specification, the profile, spSpecObjectOnProfileElt and the associated keyword is valuated to MfKeyExtrudedFrom .

...
       if ( SUCCEEDED(rc) )
       {
          rc = QueryInterface( IID_CATIMfProcReport , (void**) &piProcReport );
          if ( SUCCEEDED(rc) )
          {
             int BoolOper = 0;
             piProcReport->CreateProcReport(ListSpec,ListKeys,BoolOper); 
          }
       }
...

Once the CATIMfProcReport interface pointer on the User Pad is retrieved, piProcReport, you can create the procedural report thanks to the CreateProcReport method. The last argument of this method is 0, the default value, because the result ( the scope ) will be affected to the feature itself [Fig.1]. Note that piProcReport is declared at the top of the Build method because it can be released in a CATCatch section.

[Top]

Running the Topological Operators

This step consists in three sub-steps which are always:

Retrieving the Geometrical Factory

See the "Retrieving the Geometrical Factory Interface" section in the Build implementation. 

Retrieving the Topological Journal

See the "Retrieving the Topological Journal" section in the Build implementation. 

Creating the Prism Operator

The prism operator is created with the following arguments:

...
      CATBody   *pResultBody = NULL ;

       if ( SUCCEEDED(rc) )
       {
          CATLength endOffset = 30.;
          CATLength startOffset = 0.;
    
          pOperatorPrism = CATCreateTopPrism(piGeomFactory,
                                       &TopData,
                                       spBodyOnProfile, 
                                       &ExtrusionDirection, 
                                       startOffset, 
                                       endOffset);

...

The pad operation creates a positive shape (negative in pocket case) and the CatBoolUnion argument is used to characterize the operation. The two SetLimit methods applied allow first and last limits to be defined.

         if ( NULL != pOperatorPrism )
          {
             pOperatorPrism->SetOperation(CatBoolUnion);
		
	    CATTopLimitType startLimitType = CatLimOffsetFromProfile;   
             CATTopPropagationType startPropagType = CatPropagSingle;

             // Defines the first limit for the operator
             pOperatorPrism->SetLimit(CatLimStart, 
                             startLimitType,
                             1, 
                             startOffset, 
                             NULL, 
                             CATBody_var(NULL_var), 
                             startPropagType,
                             FALSE);
	
             // Defines the second limit for the operator
             CATTopLimitType endLimitType = CatLimOffsetFromProfile;
             CATTopPropagationType endPropagType = CatPropagSingle;

             pOperatorPrism->SetLimit(CatLimEnd,
                             endLimitType,
                             0, 
                             endOffset, 
                             NULL, 
                             CATBody_var(NULL_var),
                             endPropagType,
                             FALSE);
                             
            // Performs the operation
            pOperatorPrism->Run();
	
            // Retrieves the performed body
            pResultBody = pOperatorPrism->GetResult();
...

pResultBody is the CATBody named TopoC on the figure [Fig.1] associated with the form of the User Pad. Note that pResultBody  is not declared at the top of the method. It is not necessary once its lifecycle is managed by the DeletedProcReport method in the CATCatch sections

[Top]

Storing the Procedural Report

It is now high time to store (fill) the procedural report corresponding to the creation of the geometric result of the User Pad. That's the job of the CATIMfProcReport::StoreProcReport method.

...
       if ( SUCCEEDED(rc) )
       {
          if ( NULL != pResultBody )
          {
             int BoolOper = 0 ; 
             piProcReport->StoreProcReport(pResultBody,NoCopy,BoolOper); 
          }
          else
          {
             CATMfErrUpdate *pErrorBuildShape = new CATMfErrUpdate();
             CATUnicodeString Diagnostic("Error during BuildShape operation");
             pErrorBuildShape->SetDiagnostic(1,Diagnostic);

             CATThrow(pErrorBuildShape);
          }
       }
...

The last argument of the StoreProcReport method, BoolOper, is the same as the value in the CreateProcReport method. 

[Top]

Cleaning the Useless Data

In this last part of the CATTry section, you clean the data declared in the first section entitled "Declaring the Useful Pointers" and not released/deleted during the CATTry section. For example, the pPrtProfile pointer is not released here, once it has been safer released in the CATTry section (not described in this article, refer to the code) 

Managing the Error

This section is identical to the "Managing Error" section of the Build method. Depending on the data used during the method, only the "cleaning useless data" section is different. In the two CATCatch sections of the BuildShape method it is important to:

and for the data declared in the first section entitled "Declaring the Useful Pointers":

[Top]


In Short

This use case has demonstrated the way to manage the build of a form feature.

[Top]


References

[1] Mechanical Modeler Overview
[2] Integrating a New Geometrical Feature in the Update Mechanism
[3] Creating a New StartUp Deriving from a Mechanical StartUp
[4] Generic Naming Overview
[5] Specification/Result Mechanism Applied to Mechanical Feature
[6] Building and Launching a CAA V5 Use Case
[7] Managing Errors Using Exceptions
[8] A Description of Update Errors
[9] The Structure of the Part Document
[Top]

History

Version: 1 [Apr 2000] Document created
Version: 2 [Jan 2003] Document updated
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.