Mechanical Modeler

Modifying Combine's Curve Specifications

How to implement the replace mechanism for a new geometrical feature
Use Case

Abstract

This use case explains how to implement the replace mechanism for a new geometrical feature.

What You Will Learn With This Use Case

Once you have created a new mechanical feature [1], you should integrate it in the V5. The technical article entitled "Integrating a New Mechanical Feature in the V5" [2] lists the main behaviors to take into account and gives all the mandatory and useful interfaces to implement. One of the V5 behavior is the Replace mechanism, in other words the possibility to change for a feature one specification by another one. In the case of a new feature deriving from the GeometricalElement3D StartUp, as it is the case with the Combined Curve [3], the Replace mechanism is fully integrated by implementing:

To implement the CATIReplace interface, this use case explains also the usage of the two following interfaces:

[Top]

The CAAMmrCombinedCurveReplace Use Case

CAAMmrCombinedCurveReplace is a use case of the CAAMechanicalCommands.edu framework that illustrates ObjectSpecsModeler, MechanicalModeler and InteractiveInterfaces frameworks capabilities.

[Top]

What Does CAAMmrCombinedCurveReplace Do

The replace mechanism is strongly related to the notion of history [4]. The goal is to replace in the history of all features a specification by another one.

The basic scenario is:

  1. Select a feature
  2. Click on the right button
  3. Choose the Replace item in the contextual menu
  4. Select an object (a sub-element of a feature in the 3D View ( an edge ) or a feature in the spec tree or in the 3D View)
  5. Choose the orientation of the selected object
  6. Click OK to validate the replacement.

Screen grabs are shown below to illustrate the scenario on a simple case.

Here, two features reference the same line: Line.2.
  1. An extruded feature references Line.2 as its extrusion direction
  2. A combined curve is built using Line.1 and Line.2, as the intersection of the surfaces generated by the extrusion of these lines along their extrusion directions.

The extrusion directions are shown as white arrows. We want to replace this line Line.2 by another line Line.3.

We get into the replace capability, and select Line.2 that we want to replace. The dialog box shows the Line.2 object to replace. Line.3 is not yet selected.
Finally we select Line.3 and click OK. After checking that any feature relying on Line.2 can be rebuilt using Line.3, the replace operation is performed. Both extrusion and combined curve features are impacted by the replace operation that is automatically carried out. Line.2 is no more referenced by any feature that has replaced it by the new line Line.3. (Here the extrusion and the combined curve are the only referencing features.)

There is a need for three different kinds of services:

  1. To filter the selection path and set the level of granularity 
  2. To validate the pre-selection/selection of the object in the selection path
  3. To replace every reference to the former feature by a reference to a new valid feature. 

The CAAMmrCombinedCurveReplace use case explained also two advanced concepts. So for a first implementation of the Replace mechanism you can skip them. 

Some features, as a line, a plane, and so one, have an orientation. It is the orientation of their support. The Replace command enables you to select the feature or its inverse (in selecting the green arrow, see [Fig.2]). The use case explains how to manage the inversion of an input. Note that the Replace command displays always a green arrow, but in some cases the inverse can have no meaning for your input.

In some cases, the input of the feature can be a sub-element: a face, an edge, a vertex. If you want manage those cases, the use case explains how to featurize a selected input.

About the Orientation Flag

To understand the meaning of this flag, consider the following scenario. On the Part below, the purple plane is an offset plane of the blue plane. 

Fig.1: Plane with offset 

The blue plane is selected to be replaced by the yellow plane. The Replace command displays two arrows: a red arrow to indicate the orientation of the input to modify (blue plane), and a green arrow to indicate the orientation of the selected input for the replacement (yellow plane):

Fig.2: The Blue Plane Replaced by the not Inversed Yellow Plane 

 If you don't select the green arrow, the result is the following: the purple plane is over the yellow plane.

Fig.3: The Result

If you select the green arrow, it is inversed,

Fig.4: The Blue Plane Replaced by the Inversed Yellow Plane 

and the result is the following: the purple plane is under the yellow plane.

Fig.5: The Result

If the selection has been inversed, the new input of the feature is a specific feature: the Inverse feature. The next schema explains that for the combined curve:

In this example, for the first direction the Line.1 feature has been selected and the green arrow has been inversed. So the value of the first direction is not Line.1 but the Inverse.1 feature which has a link to the Line.1 feature. 

The CATIOrientationFlag interface is the meaning to know the end user orientation of the selection in the replace code.

About a BRep Selection

The input element, the candidate for the Replace operation, can be a feature as described in the previous scenario, but can be also an object of selection [4].  A such object is often named a BRep object. It implements the CATIBRepAccess interface (MecModInterfaces). This object is not a feature. You retrieve one by selecting a sub-element (an edge, a vertex, a face) of a feature or by creating one thanks to the CATBRepDecode (MechanicalModeler) global function. 

Fig.6: A BRep object as input for the replace

On the picture above, you can notice that one edge of the pad is the second direction of the combined curve. The selected edge has been featurized before becoming  an input of the CombinedCurve.1 feature. It will be done by the ExtractFeature private method of the CATIReplace implementation class. 

[Top]

How to Launch CAAMmrCombinedCurveReplace

See the section entitled "How to Launch the Combined Curve Use Case" in the "Creating a New Geometrical Feature: The Combined Curve" use case for a detailed description of how this use case should be launched. 

Launch CATIA. When the application is ready:

(*) The file is located in the directory CAAMechanicalModeler.edu/InputData

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

[Top]

Where to Find the CAAMmrCombinedCurveReplace Code

The CAAMmrCombineCurveReplace use case is made of three classes named CAAEMmrCombineCurveReplace, CAAEMmrCombineCurveAttrBehavior and CAAEMmrCombineCurveReplaceUI  located in the CAAMmrCombinedCurveReplace.m module of the CAAMechanicalModeler.edu framework:

Windows
InstallRootDirectory\CAAMechanicalModeler.edu\CAAMmrCombinedCurveReplace.m\
Unix
InstallRootDirectory/CAAMechanicalModeler.edu/CAAMmrCombinedCurveReplace.m/

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

[Top]

Step-by-Step

There are three logical steps in CAAMmrCombinedCurveReplace use case:

  1. Implementing the CATIReplace Interface
  2. Implementing the CATIAttrBehavior Interface
  3. Implementing the CATIReplaceUI Interface

[Top]

Implementing the CATIReplace Interface

The first interface to implement is CATIReplace. To implement this interface of the ObjectSpecModeler framework, use its adapter class the CATSpecReplaceExt class.  

  1. The header class
  2. The source file
  3. The IsElementValidForReplace method
  4. The Replace method
  5. The ExtractFeature private method
  6. The InvertFeature private method

 

  1. The header class
  2. #include "CATSpecReplaceExt.h"    
    class CATISpecObject_var;        
    
    class CAAEMmrCombineCurveReplace : public CATSpecReplaceExt
    {
       CATDeclareClass;
          
     public :
    
       CAAEMmrCombineCurveReplace();
       virtual ~CAAEMmrCombineCurveReplace();
    
       HRESULT IsElementValidForReplace(const CATUnicodeString  & iNameOfRole,
                                       const CATBaseUnknown_var & ispElement,
                                       CATUnicodeString         & oMessage, 
                                       int                      & oElementValidity,
                                       const CATBaseUnknown_var & ispOldValue=NULL_var);
    
       HRESULT Replace(const CATUnicodeString   & iNameOfRole,
                       CATBaseUnknown_var       & ispNewElement,
                       const CATBaseUnknown_var & ispOldValue=NULL_var);
    
     private:
    
        CAAEMmrCombineCurveReplace(const CAAEMmrCombineCurveReplace &iObjectToCopy);
        CAAEMmrCombineCurveReplace & operator = (const CAAEMmrCombineCurveReplace &iObjectToCopy);
    
        CATISpecObject_var ExtractFeature(const CATBaseUnknown_var& ispSelectedObject);
    
        CATISpecObject_var InvertFeature(const CATBaseUnknown_var& ispSelectedObject,
                                        const CATISpecObject_var& ispCurrentSpec);
    
    };

    The CAAEMmrCombineCurveReplace C++ class derives from CATSpecReplaceExt. This class is the adapter class of the CATIReplace interface. The CATDeclareClass macro declares that the CAAEMmrCombineCurveReplace class belongs to a component. The copy constructor and the "=" operator are set as private to prevent the compiler from automatically creating as public.

    The CATIReplace interface contains two methods:

  3. The source file
  4. The beginning of the CAAEMmrCombineCurveReplace.cpp file is the following.

    ...
    CATImplementClass(CAAEMmrCombineCurveReplace, 
                      DataExtension, 
                      CATIReplace, 
                      CombinedCurve);
    
    CATImplementBOA(CATIReplace, CAAEMmrCombineCurveReplace);
    ...

    The CATImplementClass macro is used in conjunction with the CATDeclareClass macro in the class header file to express that the class is part of a CAA V5 Object Modeler component. Its argument read as follows:

    1. CAAEMmrCombineCurveReplace: the class name
    2. DataExtension: the CAA V5 Object Modeler class type. 
    3. CATIReplace: The name of implemented interface
    4. CombinedCurve : the name of the extended component.

    The CATImplementBOA macro replaces the TIE_CATIReplace macro. Its arguments are the BOA-implemented interface and the extension class name respectively.

    Do no forget to modify the interface dictionary by adding the following line:

    CAAEMmrCombineCurveReplace CATIReplace libCAAMmrCombinedCurveReplace

    Where CAAMmrCombinedCurveReplace is the name of the library which contents the CAAEMmrCombineCurveReplace.cpp class.

  5. The IsElementValidForReplace method
  6. The implementation of the IsElementValidForReplace method is inherited from the adapter class.  The default implementation calls the CATIAttrBehavior on the Feature referencing the object to replace, in order to know if the iElement reference is able to replace the iOldValue object. Below is the signature of IsElementValidForReplace.

    HRESULT
    CAAEMmrCombineCurveReplace::IsElementValidForReplace(const CATUnicodeString& iNameOfRole,
                                                         const CATBaseUnknown_var& iElement,
                                                         CATUnicodeString& oMessage, 
                                                         int& oElementValidity, 
                                                         const CATBaseUnknown_var& iOldValue)
    {
       HRESULT rc = S_OK;
       
       oElementValidity=0;
    
       rc = CATSpecReplaceExt::IsElementValidForReplace(iNameOfRole,
                                                                iElement,
                                                                oMessage,
                                                                oElementValidity,
                                                                iOldValue);
       
       return rc;
    }
  7. The Replace method
  8. The purpose of this method is to set a new object, ispNewElement, in an attribute named iNameOfRole valuated with the former value ispOldValue

    HRESULT CAAEMcaCombineCurveReplace::Replace(const CATUnicodeString   & iNameOfRole,
                                                CATBaseUnknown_var       & ispNewElement,
                                                const CATBaseUnknown_var & ispOldValue)
    {
       CATISpecObject_var spCurrent = this;
       CATISpecObject_var spNewSpec = ispNewElement;
       CATBaseUnknown_var spForReplace = ispNewElement;
    
      ...

    This method can be divided in six parts. But the second part, managing the BRep selection and the third part managing the input orientation, can be skipped for a first implementation of this method.

    The first part of this method consists in to check ispNewElement. There are two kinds of test:

    The second part of the Replace method consists in to transform the input element in a feature if it is not one. In this case the input element is a BRep object, an object of selection. Refer to the section "About BRep Selection" for details about BRep objects. 

    Here, spNewSpec is a CATISpecObject smart pointer on ispNewElement a CATBaseUnknown smart pointer that can be either a feature or a selection object that need to be featurized (that is what ExtractFeature method does). spForReplace is a CATISpecObject smart pointer. If spNewSpec is NULL (i.e., ispNewElement is not a feature), then we call the private method ExtractFeature that will create a feature from a selection object ispNewElement and return it in spElem CATISpecObject smart pointer. 

      ...
      if (NULL_var == spNewSpec)
      {
        CATISpecObject_var spElem = ExtractFeature(ispNewElement);
        spForReplace = spElem;
      }
     
      ...

    The third part consists in to manage the orientation flag of the input. This flag can be available for a feature input or a BRep input. The private method InvertFeature manages the orientation associated with spForReplace.

      ...
      spForReplace = InvertFeature(ispNewElement,spForReplace);
      ...

    The forth part consists in to check that the new feature is a BRep feature. In this case, it must be aggregated by the combined curve. A BRep feature should be aggregated by someone to be delete. If it has already been aggregated by someone, the replace should not be done.

      ...
       CATIMfBRep *pIMfBRep = NULL ;
       rc = spForReplace->QueryInterface(IID_CATIMfBRep, (void**) & pIMfBRep);
       if ( SUCCEEDED(exit) )
       {
           CATISpecObject_var spSpecObjectOnReplace = spForReplace ;
           if (NULL_var != spSpecObjectOnReplace)
           {
              CATISpecObject * pFather = spSpecObjectOnReplace->GetFather() ;
              if ( NULL == pFather )
              {
                 CATIDescendants * pIDescendantsOnCC = NULL ;
                 rc = QueryInterface( IID_CATIDescendants , (void**) &pIDescendantsOnCC );
                                                    
                 if ( SUCCEEDED(rc) )
                 {
                    pIDescendantsOnCC->Append(spForReplace) ;
    
                    pIDescendantsOnCC->Release();
                    pIDescendantsOnCC = NULL ;
                 }
              }else
              {
                 pFather->Release();
                 pFather = NULL ;
                 rc = E_FAIL ;
              }
    
           pIMfBRep->Release();
           pIMfBRep = NULL ;
           
       }else rc = S_OK ;
      ...

    The fifth part consists in to invoke the replacement of the attribute named iNameOfRole by using the Replace method of the adapter class. 

      ...
      rc = CATSpecReplaceExt::Replace(iNameOfRole,spForReplace,ispOldValue);
      ...

    The last part of the Replace method is sending an event to update the graphic representation and the specification tree:

    ...
       CATIRedrawEvent_var spEvent(spCurrent);
       if (NULL_var != spEvent) spEvent->Redraw();
    
    ...

    where spCurrent is the CATISpecObject smart pointer on this. 

  9. The ExtractFeature private method
  10. The goal of this method is to featurize the ispSelectedObject input if it not already a feature. It is done thanks to the CATIFeaturize interface (MechanicalModeler). Refer to the "Options for Featurization" section of the article entitled "Generic Naming overview" [4] for explanations about this interface. 

    ...
    CATISpecObject_var
    CAAEMmrCombineCurveReplace::ExtractFeature(const CATBaseUnknown_var& ispSelectedObject)
    {
       CATISpecObject_var spNewValue = ispSelectedObject;
    
       if (NULL_var == spNewValue)
       {
          CATIFeaturize_var spToFeaturize = ispSelectedObject;
          if (NULL_var != spToFeaturize)
          {
             spNewValue = spToFeaturize->FeaturizeR(MfPermanentBody | 
                                                    MfLastFeatureSupport | 
                                                    MfRelimitedFeaturization);
             
             CATTry
             {
                spNewValue->Update();
             }
             CATCatch(CATError,error)
             {
                 ::Flush(error);
             }
             CATEndTry    
          }
       }
    
       return spNewValue; 
    }      
    ...

    The FeaturizeR method creates a feature that will have the representation (the result) of the selected object that will be a relimited one. After the featurization, the new feature must be updated ( build ) to be used as new input of this.

  11. The InvertFeature private method
  12. The Replace method calls a private method InvertFeature, that has for implementation to create an inversion feature. It could be also to store a flag that models the orientation of the feature. The first argument, ispSelectedObject, is the selection object and the ispCurrentSpec is the feature associated to the selection object.

    ...
    CATISpecObject_var CAAEMmrCombineCurveReplace::InvertFeature
      (const CATBaseUnknown_var& ispSelectedObject, const CATISpecObject_var& ispCurrentSpec)
    {
       CATISpecObject_var spToReturn = ispCurrentSpec;
    
       CATIOrientationFlag_var spInvertFlag = ispSelectedObject;
       if (NULL_var != spInvertFlag && spInvertFlag->IsInversed())
       {
          CATIGSMInverse_var spInverse = ispCurrentSpec;
          if (NULL_var != spInverse)
          {
             spToReturn = spInverse->GetElem();
          }
          else
          {
    ...

    If the selected input, ispSelectedObject is itself a Inverse feature, and that it is inversed, the returned value is the contents of the Inverse feature. In other words, the inverse of the inverse is the feature itself.

    ...
             CATISpecObject_var spSpec(this);
             CATISpecObject_var spInverse = NULL_var;
             CATIContainer_var  spFeatCont= spSpec -> GetFeatContainer();
              
             CATISpecAttrAccess_var spAttrAccessOnCurrentSpec = ispCurrentSpec;
             CATListValCATBaseUnknown_var * pListPointingObject = NULL; 
             pListPointingObject = spAttrAccessOnCurrentSpec->ListPointingObjects(IID_CATIGSMInverse);
             if (NULL != pListPointingObject )
             {
                int size = pListPointingObject -> Size();
                for (int i = 1; i<= size; i++)
                {
                   CATISpecObject_var spOwner = (*pListPointingObject)[i];
                   if ( NULL_var != spOwner )
                   {
                      CATIContainer_var spFeatContForOwner = pOwner->GetFeatContainer() ;
                      if ( spFeatContForOwner == spFeatCont)
                      {
                         spInverse = pOwner;
                         break;
    
    ...

    If there is an Inverse feature which has a link to ispCurrentSpec we used it. Before the V5R15, the code just above used the InverseAttrLink method. It has been replaced by the ListPointingObjects method of the CATISpecAttrAccess interface.

    ...
             if (NULL_var == spInverse)
             {
                CATIGSMFactory * pIFactoryOnFeatCont = NULL ;   
                HRESULT rc = spFeatCont->QueryInterface(IID_CATIGSMFactory,(void**)&pIFactoryOnFeatCont);
                if ( SUCCEEDED(rc) )
                {
                   spInverse = pIFactoryOnFeatCont -> CreateInverse(ispCurrentSpec);
                   ...
     ...
    }
    ...

    Otherwise, the new Inverse feature is created. 

Implementing the CATIAttrBehavior Interface

The second interface to implement is CATIAttrBehavior, that specifies the list of interfaces required to set an object as an attribute thanks to its GetRequestedBehavior method. This is used intensively in the replace capability in order to choose a candidate specification that can replace an existing one referenced by many other specifications. The CAAEMmrCombineCurveAttrBehavior extension class implements CATIAttrBehavior.

  1. The header class
  2. The source file
  3. The GetRequestedBehavior method
  1. The header class
  2. #include "CATBaseUnknown.h"     
    #include "CATBehaviorSpecs.h"
    class CATUnicodeString;       
    
    class CAAEMmrCombineCurveAttrBehavior : public CATBaseUnknown
    {
     public :
       CATDeclareClass;
      
       CAAEMmrCombineCurveAttrBehavior();
       virtual ~CAAEMmrCombineCurveAttrBehavior();
    
       HRESULT GetRequestedBehavior(const CATUnicodeString* ipAttrId, CATBehaviorSpecs** oppBehavior);
    
     private:
        CAAEMmrCombineCurveAttrBehavior(const CAAEMmrCombineCurveAttrBehavior &iObjectToCopy);
        CAAEMmrCombineCurveAttrBehavior & operator = (const CAAEMmrCombineCurveAttrBehavior &iObjectToCopy);
    
    };

    The CAAEMmrCombineCurveAttrBehavior C++ class derives from CATBaseUnknown. The CATDeclareClass macro declares that the CAAEMmrCombineCurveAttrBehavior class belongs to a component. The copy constructor and the "=" operator are set as private to prevent the compiler from automatically creating as public. The GetRequestedBehavior method is the unique method of this interface. 

  3. The source file
  4. ...
    CATImplementClass(CAAEMmrCombineCurveAttrBehavior,CodeExtension,CATBaseUnknown,CombinedCurve);
                     
    #include <TIE_CATIAttrBehavior.h>
    TIE_CATIAttrBehavior(CAAEMmrCombineCurveAttrBehavior);
    ...

    Do no forget to modify the interface dictionary be adding the following line:

    CAAEMmrCombineCurveAttrBehavior CATIAttrBehavior libCAAMmrCombinedCurveReplace

    Where CAAMmrCombinedCurveReplace is the name of the library which contents the CAAEMmrCombineCurveAttrBehavior.cpp class.

  5. The GetRequestedBehavior method
  6. The implementation of the GetRequestedBehavior method is detailed below:

    HRESULT CAAEMmrCombineCurveAttrBehavior::GetRequestedBehavior(
                                      const CATUnicodeString *ipAttrId,
                                      CATBehaviorSpecs      **oppBehavior)
    {
      *oppBehavior = new CATBehaviorSpecs;
      HRESULT exit=S_OK;
      if (2 == ipAttrId->Compare("Curve1") || 2 == ipAttrId->Compare("Curve2"))
      {
        CATListPV* aMyFirstList = new CATListPV;
        aMyFirstList->Append((void*)&IID_CATIMfMonoDimResult);
        (*oppBehavior)->Append(aMyFirstList);
      }
      else if (2 == ipAttrId->Compare("Direction1")
            || 2 == ipAttrId->Compare("Direction2"))
      {
        CATListPV *aMyFirstList = new CATListPV;
        aMyFirstList->Append((void*)&IID_CATLine);
        (*oppBehavior)->Append(aMyFirstList);
      }
      else
      {
        exit = E_FAIL;
      }
      return exit;
    }

    If the input string ipAttrId is equal to "Curve1" or "Curve2" which are the names of two attributes of the CombineCurve feature, then the filter will be IID_CATIMfMonoDimResult. That is to say, we can replace in those two attributes a feature implementing the interface CATIMfMonoDimResult by another one that also implements CATIMfMonoDimResult.

    If the input string ipAttrId is equal to "Direction1" or "Direction2" which are the names of two other attributes of the CombineCurve feature, then the filter will be IID_CATLine. That is to say, we can replace in those two attributes a feature implementing the interface CATLine by another one that also implements CATLine.

Implementing the CATIReplaceUI Interface

The last interface to implement is CATIReplaceUI

  1. The header class
  2. The source file
  3. The FindValidElementForReplace method
  1. The header class
  2. #include "CATBaseUnknown.h"   
    class CATUnicodeString ;
    class CATPathElement;        
    
    class CAAEMmrCombineCurveReplaceUI : public CATBaseUnknown
    {
       CATDeclareClass;
          
     public :
    
       CAAEMmrCombineCurveReplaceUI();
       virtual ~CAAEMmrCombineCurveReplaceUI();
    
       HRESULT FindValidElementForReplace(const CATUnicodeString& iRole,
                                          const CATPathElement* ipSelection,
                                          const CATBaseUnknown* ipOldValue, 
                                          CATBaseUnknown*& opFoundElement);
     private:
        CAAEMmrCombineCurveReplaceUI(const CAAEMmrCombineCurveReplaceUI &iObjectToCopy);
        CAAEMmrCombineCurveReplaceUI & operator = (const CAAEMmrCombineCurveReplaceUI &iObjectToCopy);
    
    };

    The CAAEMmrCombineCurveReplaceUI C++ class derives from CATBaseUnknown. The CATDeclareClass macro declares that the CAAEMmrCombineCurveReplaceUI class belongs to a component. The copy constructor and the "=" operator are set as private to prevent the compiler from automatically creating as public. The FindValidElementForReplace method is the unique method of this interface. 

  3. The source file
  4. ...
    CATImplementClass(CAAEMmrCombineCurveReplaceUI,
                      DataExtension,
                      CATBaseUnknown,
                      CombinedCurve);
    
    #include <TIE_CATIReplaceUI.h>
    TIE_CATIReplaceUI(CAAEMmrCombineCurveReplaceUI);
    ...

    Do no forget to modify the interface dictionary be adding the following line:

    CAAEMmrCombineCurveReplaceUI CATIReplaceUI libCAAMmrCombinedCurveReplace

    Where CAAMmrCombinedCurveReplace is the name of the library which contents the CAAEMmrCombineCurveReplaceUI.cpp class.

  5. The FindValidElementForReplace method
  6. FindValidElementForReplace searches for the opFoundElement object in a CATPathElement ipSelection that can replace a given object ipOldValue for a given role iRole. Here, spFeatParent is a CATISpecObject smart pointer on the pNextParent CATBaseUnknown pointer, spReplace is a CATIReplace smart pointer on this, and pNextParent is a CATBaseUnknown pointer extracted from the CATPathElement ipSelection.

    HRESULT CAAEMmrCombineCurveReplace::FindValidElementForReplace(
                                                const CATUnicodeString & iRole,
                                                const CATPathElement   * ipSelection,
                                                const CATBaseUnknown   * ipOldValue,
                                                CATBaseUnknown        *& opFoundElement)
    {
      ...
      while (NULL != pNextParent)
      {
        spFeatParent = pNextParent;
        if (NULL_var != spFeatParent)
        {
          hr = spReplace -> IsElementValidForReplace(iRole,spFeatParent,message,ElementValidity,spOldValue);
          if (SUCCEEDED(hr) && 1 == ElementValidity)
          {
            opFoundElement = pNextParent;
            opFoundElement->AddRef();
            break;
          }
        }
        pNextParent = pTmp->NextFatherElement();
      }
      ...

    For each object referenced in the CATPathElement ipSelection, we call the IsElementValidForReplace method to know if the current element is valid to replace spOldValue the old value for the iRole attribute. If one is valid, we stop the loop and opFoundElement is valuated. Here, we are looking especially for features referenced in the CATPathElement object.

    At this stage, we can have a opFoundElement that is valuated or not, depending on what objects are in the CATPathElement. Especially if no feature referenced in the CATPathElement object is valid for the given role. We do a second pass, but this time we check that the object are not features. We have done this to replace an object by an existing feature, avoiding to create each time a BRep feature for each replace action done in the model.

      ...
      if (NULL == opFoundElement)
      {
        pTmp->InitToLeafElement();
        pNextParent = pTmp->NextFatherElement();
        while (NULL != pNextParent)
        {
          spFeatParent = pNextParent;
          if (NULL_var == spFeatParent)
          {
            hr = spReplace->IsElementValidForReplace(iRole,pNextParent,message,ElementValidity,spOldValue);
            if (SUCCEEDED(hr) && 1 == ElementValidity)
            {
              opFoundElement = pNextParent;
              opFoundElement->AddRef();
              break;
            }
          }
          pNextParent = pTmp->NextFatherElement();
        }
      }
      ...

    Here, we are doing the same as we have done above, except that we want none feature object, and we call the IsElementValidForReplace method with a selection object at each step.

    In this method we have found a valid element for replace by searching a CATPathElement object.

[Top]


In Short

This use case has demonstrated the way to implement the replace mechanism for a new feature. We illustrate the way interfaces collaborate in an algorithm and the openess that gives these interfaces for the replace mechanism.

[Top]


References

[1] Creating a New StartUp from a Mechanical StartUp
[2] Integrating a New Mechanical Feature in the V5
[3] Creating Combined Curve's Catalog
[4] Generic Naming Overview
[Top]

History

Version: 1 [Mar 2000] Document created
Version: 2 [Jan 2003] Document updated
Version: 3 [Jan 2005] CATImplementBOA usage instead TIE_CATIReplace + InverseAttrLink usage remove
[Top]

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