3D PLM PPR Hub Open Gateway

Product Modeler

Working With Rigid/Flexible Sub-Products

Using the CATIBlockMovable interface

Use Case

Abstract

This article presents  the CAAPstBlockMovable use case which illustrates how to work with flexible sub-products.


What You Will Learn With This Use Case

Using the CATIBlockMovable interface, a sub-product can be made flexible or rigid.

[Top]

The CAAPstBlockMovable Use Case

CAAPstBlockMovable is a use case of the CAAProductStructure.edu framework that illustrates the ProductStructure framework capabilities.

[Top]

What Does CAAPstBlockMovable Do

The goal of CAAPstBlockMovable is to demonstrate the CATIBlockMovable interface. It performs the following steps:

Below  is the Product document that will be loaded in the use case. It can be found in

InstallRoot/CAAProductStructure.edu/CNext/resources/graphic/CAAPstBlockMovable_document.CATProduct

If link.1 is moved (by dropping the compass on the part and then dragging it), it is the whole chain.1 that will move and not only link.1. This is because chain.1 is rigid.

The code in the use case will make chain.1 flexible and then move link.1. The resulting document will show that only link.1 has moved. Moreover, link.1 and link.2 can now be moved separately using the compass.

[Top]

How to Launch CAAPstBlockMovable

To launch CAAPstBlockMovable:

  1. Set the current directory to InstallRoot/CAAProductStructure.edu
  2. Set up  the build time environment and build the CAAPstBlockMovable.m module (see reference [2])
  3. Execute the following command:

    mkrun -c "CAAPstBlockMovable input.CATProduct output.CATProduct link.1 0 50 0"

In the resulting document, only link.1 has moved because chain.1 has been made flexible

[Top]

Where to Find the CAAPstBlockMovable Code

CAAPstBlockMovable code is located in the CAAPstBlockMovable.m module of the CAAProductStructure.edu framework. There are two source files:

[Top]

Step-by-Step

There are six logical steps in CAAPstBlockMovable:

  1. Creating a session to load a Product document
  2. Retrieving the document's Root Product
  3. Finding a part and its parent
  4. Checking whether a sub-product is rigid and making it flexible
  5. Moving the part
  6. Saving the Product Document

We will now detail  each of those sections:

[Top]

Loading a Product Document

Generally, the first thing that is necessary in a batch program is the creation of a new session. This is done using the Create_Session global function. It is important not to forget to delete the session when the program exits. Once the session is created, a Product document can be loaded with CATDocumentServices::Open.

        //
        // Start session and load a Product
        //
        rc = ::Create_Session((char *) _sessionName, _pSession);
...
        rc = CATDocumentServices::Open(inputFilename, _pDocument);

[Top]

Retrieving the Document's Root Product

In order to work with a product structure within the Product document, it is necessary to access the root product. This is done using the GiveDocRoots method of CATIDocRoots which returns a list of all of the roots within the document, the first one being the root product we are looking for. From this root product, we can get a CATIProduct handle which will be needed later in order to find a part.

        //
        // Get Root Product
        //
        CATIDocRoots* piDocRootsOnDoc = NULL;
        rc = _pDocument->QueryInterface(IID_CATIDocRoots,
                                        (void**) &piDocRootsOnDoc);
...
        //
        // The root product is the first element of root elements
        //
        CATListValCATBaseUnknown_var* pRootProducts = 
                piDocRootsOnDoc->GiveDocRoots();
        CATIProduct_var spRootProduct = NULL_var;

        if (pRootProducts && pRootProducts->Size()) { 
                spRootProduct = (*pRootProducts)[1];
...

        //
        // Get CATIProduct handle on the root product.
        //
        CATIProduct *piProductOnRoot = NULL;
        rc = spRootProduct->QueryInterface(IID_CATIProduct,
                                           (void**) &piProductOnRoot);

[Top]

Finding a part and its parent

Finding a part with a given instance name is implemented by the FindPart method: it walks though the children list of the root product until the name matches with an instance's.

CATIProduct_var CAAPstBlockMovable::FindPart(CATUnicodeString& ipartName,
                                             CATIProduct *ipiProductOnRoot)
{
        CATIProduct_var ospPart = NULL_var;

...
        CATListValCATBaseUnknown_var* childrenList =
                ipiProductOnRoot->GetAllChildren();
...
        int childrenCount = childrenList->Size();
        CATIProduct_var spChild = NULL_var;
        CATUnicodeString instanceName;
        for (int i=1; i <= childrenCount; i++) {
                spChild = (*childrenList)[i];
                if (NULL_var == spChild)
                        break;
                HRESULT rc = spChild->GetPrdInstanceName(instanceName);
                if (FAILED(rc))
                        break;
                if (instanceName == ipartName) {
                        ospPart = spChild;
                        break;
                }
        }
...
        return ospPart;
}

Once the part is found, getting its parent product is done by calling GetFatherProduct

        //
        // Retrieve the part with specified name
        //
        CATIProduct_var spPart = FindPart(partName, piProductOnRoot);
...
        if ( NULL_var == spPart) {
                cout << partName.ConvertToChar() << " not found" << endl;
                ERROR_RETURN(S_PartNotFound);
        }

        //
        // Retrieve the parent product of the part
        //
        CATIProduct_var spParentProduct = spPart->GetFatherProduct();
        if (NULL_var == spParentProduct) {
                cout << "Can't find parent product of " << partName.ConvertToChar() << endl;
                ERROR_RETURN(S_ParentNotFound);
        }

[Top]

Checking whether a sub-product is rigid and making it flexible

The next thing to do is to get the CATIBlockMovalbe interface of the parent product. Using this interface, the parent product rigidity is tested with IsSoft and is made flexible only if it is necessary with MakeSoftAssembly.

        //
        // Get the CATIBlockMovable interface on the parent product
        //
        CATIBlockMovable *piBlockMovable = NULL;
        rc = spParentProduct->QueryInterface(IID_CATIBlockMovable,
                                             (void **) &piBlockMovable);
...
        //
        // Check whether the rigid/flexible modification needs to be applied to
        // the parent product
        //
        int isFlexibleFlag = piBlockMovable->IsSoft();
        CATUnicodeString parentName;
        spParentProduct->GetPrdInstanceName(parentName);
        cout << parentName.ConvertToChar();
        if (isFlexibleFlag)
                cout << " is already flexible" << endl;
        else {
                cout << " is rigid, making it flexible" << endl;
                piBlockMovable->MakeSoftAssembly(); 
        }

[Top]

Moving the part

Now that the parent product is flexible, the part can be moved using the CATIMovable interface. (see reference [3])

        isFlexibleFlag = piBlockMovable->IsSoft();
...

        //
        // If the parent product is flexible then move the part:
        // Get the CATIMovable Interface and move the part on the Y axis
        //
        if (isFlexibleFlag) {
                CATIMovable *piMovable = NULL;
                rc = spPart->QueryInterface(IID_CATIMovable, 
                                            (void **) &piMovable);
...
                CATMathTransformation position;
                rc = piMovable->GetAbsPosition(position);
...
                double array[12];
                position.GetCoef(array, sizeof(array)/sizeof(array[0]));
                //
                // move the part 20mm in the Y axis
                //
                array[9]  += double(deltaX);
                array[10] += double(deltaY);
                array[11] += double(deltaZ);
                position.SetCoef(array);
                rc = piMovable->SetAbsPosition(position);

[Top]

Saving the modified Product Document

The modified document can now be saved. Finally the session is delete and the loaded Product document is removed.

        //
        // All done. save the modified document into the specified output file
        //
        rc = CATDocumentServices::SaveAs(*_pDocument, outputFilename);
...

        //
        // Remove the opened document and close the session
        //
        CleanUp();

[Top]


In Short

This use case has demonstrated how to make a sub-product flexible so that one of its parts can be moved:

[Top]


References

[1] The Product Structure Model
[2] Building and Launching a CAA V5 Use Case
[3] Positioning Products Use Case
[Top]

History

Version: 1.1 [Aug 2004] Document revised
Version: 1 [Aug 2003] Document created
[Top]

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