Mechanical Modeler

Instantiating a User Feature Reference

Using CATIUdfFactory and CATIUdfInstantiate
Use Case

Abstract

This article shows how to instantiate a User Feature reference.


What You Will Learn With This Use Case

Thanks to the use case "Creating a User Feature Reference"  [1], you have learned to successfully create a User Feature reference. With this article you will learn how to instantiate it. An instantiation follows a strict process whose depends its success. 

Before reading this article, see the technical article about Power Copy and User Feature [2].

[Top]

The CAAMcaUdfInstantiation Use Case

CAAMcaUdfInstantiation is a use case of the CAAMechanicalCommands.edu framework that illustrates MechanicalCommands framework capabilities.

[Top]

What Does CAAMcaUdfInstantiation Do

In the CAAUdfLoft Part document we have a User Feature reference CAAUserFeatureSample created by the  "Creating a User Feature Reference"  use case [1]. It is a loft which needs two inputs (two green points) for each instantiation.

Fig.1: The CAAUdfLoft Part Document

This User Feature reference is a surfacic features set which implements CATIUdfInstantiate. Thanks to this interface it is possible to instantiate it.

In this use case we describe two instantiations. These two instantiations are set in the CAAUdfModel Part document. This Part contains at the beginning three points which will be used as input (Point.1, Point.2, Point.3).

Fig.2: The CAAUdfModel Part Document

The first instantiation is a feature named CAAUserFeatureSample.1. For the first input we have chosen the point Point.3 and for the second the point Point.1.

The second instantiation is a feature where we have explicitly given a name: TheLoftWithPoint2and3. For the first input we have chosen the point Point.3. For the second input we have used the UseIdenticalName method of CATIUdfInstantiate to valuate it. At last, for this new User Feature, we have changed the value of each circle's radius. Each radius is a published parameter. (See  the step "Publishing Parameters" in the "Creating a User Feature Reference"  use case [1] )

The Part, with these two instantiations, is saved as CAAUdfModelWithInstances Part document. In green is the CAAUserFeatureSample.1 and in pink the TheLoftWithPoint2and3.

Fig.3: The CAAUdfModelWithInstances Part Document: the Part with the two New Instances of User Features

[Top]

The interactive scenario:

Launch CATIA. When the application is ready:

How to Launch CAAMcaUdfInstantiation

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

mkrun -c CAAMcaUdfInstantiation InputPath [OutputPath]

  1. InputPath:  The path of the CAAUdfLoft.CATPart and CAAUdfModel.CATPart files included in the directory CAAMechanicalCommands.edu/InputData
  2. OutputPath: The path to write the output file CAAUdfModelWithInstances.CATPart. If this path is empty, the output file is created in the current directory.

[Top]

Where to Find the CAAMcaUdfInstantiation Code

The CAAMcaUdfInstantiation use case is made of one main located in the CAAMcaUdfInstantiation.m module of the CAAMechanicalCommands.edu framework:

Windows InstallRootDirectory\CAAMechanicalCommands.edu\CAAMcaUdfInstantiation.m\
Unix InstallRootDirectory/CAAMechanicalCommands.edu/CAAMcaUdfInstantiation.m/

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

In the CAAMcaUtilities.m module of the same framework, there is a global function to retrieve data from the input Part, named CAAMcaGetGeometry. It is located in CAAMcaGetGeometry.cpp. The header of this function, CAAMcaGetGeometry.h, is set in the PrivateInterfaces directory of the framework. 

[Top]

Step-by-Step

We do not explain step by step the first instantiation and next the second instantiation. We have chosen to show step by step how to instantiate a User Feature reference. In each  section we detail the part concerning the first and/or the second instantiation. With this presentation you can see the main methods to succeed an instantiation and mainly the order of each step. Each instantiation begins from the step "Setting the Destination Path" until the step "Ending the Instantiation" .

  1. Opening Documents
  2. Retrieving the Mechanical Part of CAAUdfModel and the Root Container of CAAUdfLoft
  3. Retrieving the User Feature Reference to Instantiate
  4. Setting the Destination Path
  5. Valuating the Inputs
  6. Changing Parameter Values
  7. Instantiating the User Feature Reference
  8. Changing the Name of the New Instance
  9. Ending the Instantiation
  10. Updating the New Instantiations
  11. Closing Documents

[Top

Opening Documents

First document to open, CAAUdfModel.CATPart which contains three points:

  ...
  CATString InputData = iArgv[1] ;
  CATDocument *pCAAUdfModel = NULL;
  CATString CAAUdfModelDocName =InputData + Slash + "CAAUdfModel.CATPart"

  rc = CATDocumentServices::Open(CAAUdfModelDocName.CastToCharPtr(), pCAAUdfModel);   
  ...

Second document to open, CAAUdfLoft.CATPart which contains the User Feature reference CAAUserFeatureSample to instantiate:

  ...
  CATDocument *pCAAUdfLoft = NULL;
  CATString CAAUdfLoftDocName =InputData + Slash + "CAAUdfLoft.CATPart";

  rc = CATDocumentServices::Open(CAAUdfLoftDocName.CastToCharPtr(), pCAAUdfLoft);

  if (SUCCEEDED(rc) )
  {
     ::CATLockDocument(*pCAAUdfLoft);
     ...
  }  
  ...

We have detailed these opening operations to show the lock of the second document. CATLockDocument enables to increase the count of references of a document, and CATUnLockDocument decreases this counter.

In this case the lock is mandatory because as soon as the first instantiation  of CAAUserFeatureSample in CAAUdfModel is done, a link from CAAUdfModel to CAAUdfLoft is set. (this link is temporary). So when CAAUdfModel is closed all models linked with it are closed too. So if you do not lock CAAUdfLoft, the attempt to close it will fail.

See the opposite operation "Closing Documents".

Note: If you write a code for an interactive command, the CATLockDocument call is necessary only if your command keeps a pointer to the model which contains the User Feature to instantiate. Otherwise, you open it and after the instantiation you close it, using the Remove method.

[Top

Retrieving the Mechanical Part of CAAUdfModel and the Root Container of CAAUdfLoft

For CAAUdfModel we need the Mechanical Part which contains the surfacic features set with three points:

  ...
  CATInit *pInitOnDoc = NULL ;
  rc = pCAAUdfModel->QueryInterface(IID_CATInit,(void **) &pInitOnDoc);
  if ( FAILED(rc) )return 1 ;

  CATIPrtContainer *pIPrtContOnCAAUdfModel= NULL ;
  pIPrtContOnCAAUdfModel= (CATIPrtContainer*)pInitOnDoc->GetRootContainer("CATIPrtContainer");
  if ( NULL == pIPrtContOnCAAUdfModel) return 1 ;
  
  pInitOnDoc->Release();
  pInitOnDoc = NULL ;
  
  CATISpecObject_var spSpecObjectCAAUdfModelPart = pIPrtContOnCAAUdfModel->GetPart();

  CATBaseUnknown_var spCAAUdfModelPart = spSpecObjectCAAUdfModelPart ;
  CATBaseUnknown* pCAAUdfModelPart= (CATBaseUnknown*)spCAAUdfModelPart;
 
  pIPrtContOnCAAUdfModel->Release();
  pIPrtContOnCAAUdfModel = NULL ;
  ...

pCAAUdfModelPart is a pointer on the CAAUdfModel Mechanical Part.

For CAAUdfLoft, only the root container is necessary:

  ...
  rc = pCAAUdfLoft->QueryInterface(IID_CATInit,(void **) &pInitOnDoc);
  if ( FAILED(rc) )return 1 ;

  CATIPrtContainer *pIPrtContOnCAAUdfLoft = NULL ;
  pIPrtContOnCAAUdfLoft = (CATIPrtContainer*)pInitOnDoc->GetRootContainer("CATIPrtContainer");
  if ( NULL == pIPrtContOnCAAUdfLoft ) return 1 ;
  
  pInitOnDoc->Release();
  pInitOnDoc = NULL ;
  ...

[Top]

Retrieving the User Feature Reference to Instantiate

First, we retrieve a pointer to CATIUdfFactory implemented by the root container of the CAAUdfLoft document:

  ...
  CATIUdfFactory *pIUdfFactory = NULL ;
  rc = pIPrtContOnCAAUdfLoft->QueryInterface(IID_CATIUdfFactory,(void **) &pIUdfFactory);
  if ( FAILED(rc) )  return 1 ;

  pIPrtContOnCAAUdfLoft->Release();
  pIPrtContOnCAAUdfLoft = NULL ;
  ...

Now, we can retrieve the User Feature reference, the only one, of this Part:

  ...  
  CATIUdfInstantiate * pIUdfInstantiate = NULL ;      
  CATListValCATISpecObject_var * pListUserFeature = NULL ;
  pListUserFeature = pIUdfFactory->GetUserFeatureList();

  if  ( (NULL != pListUserFeature) && (pListUserFeature->Size() ==1 ) &&
	    (NULL_var != (*pListUserFeature)[1]) )
  {
     rc = (*pListUserFeature)[1]->QueryInterface(IID_CATIUdfInstantiate,(void **)&pIUdfInstantiate);
     if ( FAILED(rc) ) return 1 ;
     ...
  }

  pIUdfFactory->Release();
  pIUdfFactory = NULL ;
  ...

GetUserFeatureList returns the list of all User Feature references existing in the User Feature Set. Each User Feature reference implements CATIUdfInstantiate.

Now we can begin the instantiation steps.

[Top]

Setting the Destination Path

  ...
  CATPathElement PathFirstInstantiate1(pCAAUdfModelPart); 
  CATPathElement * FirstUIactiveObject1 = NULL ;
  CATBaseUnknown_var FirstDest1 = NULL_var ; 

  rc = pIUdfInstantiate->SetDestinationPath(&PathFirstInstantiate1,
                                             FirstUIactiveObject1,FirstDest1); 
  if ( FAILED(rc) ) return 1;
  ...

This piece of code is common for the two instantiations. The source  ended by 1 for the first instantiation and ended by 2 for the second one.

The first role of this method is to initialize the instantiation process. Each instantiation must begin by this call. The second role of this method is to give the Part where the instantiation will be set.

The first argument of SetDestinationPath is PathFirstInstantiate. It is the complete path of the CAAUdfModel Part. The second and third (outputs) arguments are not used in this use case.

Note: When the first argument of SetDestinationPath is the complete path of a Part, the two last output arguments remain to NULL. When the path is the complete path of a product, a part is automatically created. The second argument is the path of the UI object to activate, to use in an interactive command, and the last argument returns a pointer to this new part. 

[Top]

Valuating the Inputs

For the first instantiation, we set the point Point.3 and the point Point.1 for the first and second input respectively:

  ...
  CATBaseUnknown * pInput1 = NULL ;
  rc = ::CAAMcaGetGeometry(spSpecObjectCAAUdfModelPart,"Point.3",&pInput1);
  if ( FAILED(rc) )return 1 ;

  CATPathElement * pPathFirstInput1 = new CATPathElement(pInput1);
  rc = pIUdfInstantiate->SetNewInput(1,pPathFirstInput1);
  if ( FAILED(rc) )return 1 ;

  ...

  rc = ::CAAMcaGetGeometry(spSpecObjectCAAUdfModelPart,"Point.1",&pInput1);
  if ( FAILED(rc) ) return 1 ;
 
  CATPathElement * pPathSecondInput1 = new CATPathElement(pInput1);
  rc = pIUdfInstantiate->SetNewInput(2,pPathSecondInput1);
  if ( FAILED(rc) ) return 1 ;
 
  ...

CAAMcaGetGeometry is a global function which retrieves in a Part given in first argument, a feature whose CATIAlias name is the same as the second argument. So the returned feature is associated with the input thanks to the SetNewInput method.

For the second instantiation, at first the UserIdenticalName method is used to valuate the inputs. The role of this method is to find for each input a feature whose CATIAlias name is equal to the role of the input. The features are searched for from a root given as argument of the method. In this case the root is spCAAUdfModelPart, the pointer to the CAAUdfModel Part.

  ...
  rc = pIUdfInstantiate->UseIdenticalName(spCAAUdfModelPart);
  if ( FAILED(rc) ) return 1 ;     
  ...

After calling  UseIdenticalName, it is necessary to check that all inputs are valuated because the search can fail. Even if  UseIdenticalName returns  S_OK  you must use the GetNewInput method for each input. If the returned value is NULL_var the input is not valuated.

In this case, for the first input, we have a failure, spOnFirstInput2 is NULL_var. It is normal. The role of this input is "The top point of the loft", and in the CAAUdfModel, no point has a such CATIAlias name.

But for the second input, spOnSecondInput2 is not NULL_var. The role of the second input is Point.2, so we have found the feature Point.2.

  ...
  CATBaseUnknown_var spOnFirstInput2 = pIUdfInstantiate->GetNewInput(1);
  if ( NULL_var != spOnFirstInput2 )
  {     
     return 1 ;
  }

  CATBaseUnknown_var spOnSecondInput2 = pIUdfInstantiate->GetNewInput(2);
  if (  NULL_var == spOnSecondInput2 )
  {
     return 1 ;
  }
  ...

Note: The GetOldInputs method, not used here, returns the input's list of the User Feature reference, so the size of this list gives you the count of input to valuate, and returns the role for each input.

So now, we valuate the first input explicitly with the Point.3.

  ... 
  CATBaseUnknown * pInput2 = NULL ;
  rc = ::CAAMcaGetGeometry(spSpecObjectCAAUdfModelPart,"Point.3",&pInput2);
  if ( FAILED(rc) )  return 1 ;
  
  CATPathElement * pPathFirstInput2 = new CATPathElement(pInput2);
  rc = pIUdfInstantiate->SetNewInput(1,pPathFirstInput2);
  if ( FAILED(rc) )  return 1 ;

  pPathFirstInput2->Release();
  pPathFirstInput2 = NULL ;

  pInput2->Release();
  pInput2 = NULL ;  
  ...

Note: It is strongly recommended to valuate the inputs during the instantiation. You can nevertheless change them after the instantiation thanks to the CATIUdfFeatureInstance interface. 

[Top]

Changing Parameter Values

For this use case, we have just done it for the second instantiation.

The User Feature reference CAAUserFeatureSample contains a lot of parameters. Only two have been published. You can modify only the published parameters. In the following picture you can see the two published parameters:  the radius of the top circle and the radius of the bottom circle.

Fig.4: The Published Parameters Displayed in the Specifications Tree

  ...
  CATListValCATBaseUnknown_var * pListParam = NULL ;
  CATListOfCATUnicodeString    * pListParamRole = NULL ;
  rc = pIUdfInstantiate->GetParameters(pListParam,pListParamRole);

  if ( SUCCEEDED(rc) && ( NULL != pListParam) && ( NULL != pListParamRole ) )
  {
     int nbparam = pListParam->Size();
     if ( 2 == nbparam )
     {
         for ( int i=1 ; i <= 2 ; i++ )
        {
           CATICkeParm_var spCkeParm = (*pListParam)[i] ;
           if ( NULL_var != spCkeParm)
           {
              ...
              spCkeParm->Valuate(i*0.010f);
              ...
           }
     }
   ...
  }  
  ...

The GetParameters returns the published parameters, pListParam, and their respectical role pListParamRole. These two list have the same size. With the CATICkeParm interface (LiteralFeatures Framework), the value of the parameters are changed. In this case, each radius is divided by 100.

[Top]

Instantiating the User Feature Reference

This piece of code is the same for the two instantiations:

   ...  
  rc = pIUdfInstantiate->Instantiate(NULL_var);
  if ( FAILED(rc) ) return 1 ;
  
  CATBaseUnknown_var spFirstInstance = NULL_var ;
  spFirstInstance = pIUdfInstantiate->GetInstantiated(pIUdfInstantiate);
  if ( NULL_var == spFirstInstance )  return 1 ;
  ...

Thanks to the Instantiate method, the new instance is created in the current surfacic features set of the Part specified by the SetDestinationPath method. So the argument of the Instantiate method can be NULL_var.

We can have a pointer to this instance thanks to the GetInstantiated method. spFirstInstance is the smart pointer for the first instantiation. The argument of this method is the User Feature reference itself.

But caution, after the Instantiate call, it is not possible to modify the inputs and the parameters. When the instantiation process will be totally ended, you can use the CATIUdfFeatureInstance interface to edit it [4].

[Top]

Changing the Name of the New Instance

Before ending the instantiation process, and after the instance creation, it is possible to change the default name of the new instance. The default name is the name of the User Feature reference to which an index is appended.

For the first instance, the name is thus:  "CAAUserFeatureSample.1". For the second instance, we change it to "The Loft With Point2 and Point3".

 ...    
  CATUnicodeString NewName = "The Loft With Point2 and Point3""
  rc = pIUdfInstantiate->SetDisplayName(NewName);
  if ( FAILED(rc) ) return 1 ;
  ...

You can see the result in Fig.3

Note: The GetDisplayName method, not used here, returns the name of the User Feature reference, so after SetDisplayName, the result of GetDisplayName is always "CAAUserFeatureSample"

[Top]

Ending the Instantiation

This piece of code is the same for the two instantiations:

  ...
  rc = pIUdfInstantiate->EndInstantiate();
  if ( FAILED(rc) )  return 1 ;
  ...

The instantiation process is ended. To restart a new instantiation, you must go to the "Setting The Destination Path" step.

[Top]

Updating the New Instantiations

The goal of this step is to update the new instances. In batch like here, the CATISpecObject interface must be used. If your instantiation is inside an interactive command, it is better to use the CATPrtUpdateCom class  [5] .

The code for the first instance is:

  ...
  CATISpecObject_var spSpecObj1= spFirstInstance ;
  CATTry
  {
     spSpecObj1->Update();
  }
  CATCatch(CATError,error)
  {
     ...
  	 return 1 ;
  }
  CATEndTry 
  ...

spFirstInstance is a pointer to the first instance. We retrieved it using the GetInstantiated method. Refer to the Instantiating the User Feature Reference step.

[Top]

Closing Documents

  ... 
  rc = CATDocumentServices::Remove(*pCAAUdfModel);
  if (FAILED(rc)) return 1
  pCAAUdfModel = NULL ; 

  rc = ::CATUnLockDocument(*pCAAUdfLoft);
  if (FAILED(rc)) return 1
  pCAAUdfLoft = NULL ; 
  ...

The CAAUdfModel model is removed from the current session using the Remove method. This also closes the CAAUdfModel and decreases the count of references on CAAUdfLoft. CATUnLockDocument decreases the counter too, and closes the document because the counter is now zero.

[Top]


In Short

This use case has demonstrated how to instantiate a User Feature reference:

[Top]


References

[1] Creating a User Feature Reference
[2] Power Copy and User Features Overview
[3] Building and Launching a CAA V5 Use Case
[4] Editing a User Feature
[5] Editing Combined Curves
[Top]

History

Version: 1 [Nov 2001] Document created
[Top]

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