Product Synthesis & Knowledgeware

DMU Kinematics Simulator

Creating a Mechanism in a Document

From geometrical lines to mechanism
Use Case

Abstract

This article discusses the CAAKiiCreateMechanism use case. This use case explains how to open a CATProduct document and explore its contents from a Kinematics perspective, down to the basic entities that capture the technology of a mechanism contained in the document.


What You Will You Learn With This Use Case

This use case is intended to help you make your first steps in programming the CATIA Kinematics modeler. Its main intent is to introduce the API of the Kinematics modeler, and ways to use it.

The scenario is based on the creation of a simple mechanism starting from an assembly of two products which each contains a line. One will create the mechanism in the document, then create a joint on the two lines and create a command to control the mechanism. This mechanism will be movable interactively in the Kinematics workbench.

This picture represents a CATProduct document containing lines to create a mechanism.

[Top]

Kinematics Concepts

Before getting to the use case itself, it is important to get an understanding of some of the concepts that are at the heart of the Kinematics, since the use case basically navigates among objects that represent those concepts. They are presented in Kinematics Overview [1].

These concepts are:

[Top]

The CAAKiiCreateMechanism Use Case

CAAKiiCreateMechanism is a use case of the CAAKinematicsInterfaces.edu framework that illustrates KinematicsInterfaces framework capabilities.

[Top]

What Does CAAKiiCreateMechanism Do

The goal of CAAKiiCreateMechanism is to create a mechanism in an assembly using two products as links, and a cylindrical joint that enables a product to translate along a line with respect to the other product that remains fixed in the assembly, thanks to a translation command associated with the mechanism. To do this, CAAKiiCreateMechanism:

[Top]

How to Launch CAAKiiCreateMechanism

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

Launch the use case as follows:

where:

inputDirectory The directory in which inputFile.CATProduct is located
inputFile.CATProduct The file that contains the use case CATProduct document
outputDirectory The directory into which inputFile.CATProduct is stored after the mechanism is created

[Top]

Where to Find the CAAKiiCreateMechanism Code

The CAAKiiCreateMechanism use case is made of a C++ main named CAAKiiCreateMechanism whose source file is located in the CAAKiiCreateMechanism.m module of the CAAKinematicsInterfaces.edu framework:

Windows InstallRootDirectory\CAAKinematicsInterfaces.edu\CAAKiiCreateMechanism.m\
Unix InstallRootDirectory/CAAKinematicsInterfaces.edu/CAAKiiCreateMechanism.m/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed. The CAAKiiCreateMechanism class derives from CATInteractiveApplication. The described code is located in the BeginApplication method.

[Top]

Where to Find the CATProduct sample document for CAAKiiCreateMechanism

You will find a CATProduct sample document in the following directory:

Windows InstallRootDirectory\CAADoc\CAAKinematicsInterfaces.edu\CNext\resources\graphic\
Unix InstallRootDirectory/CAADoc/CAAKinematicsInterfaces.edu/CNext/resources/graphic/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed. The sample is called CAAKiiCreateMechanism.CATProduct.

[Top]

Step-by-Step

There are seven steps in CAAKiiCreateMechanism:
  1. Prolog
  2. Searching Geometries
  3. Creating the Mechanism
  4. Creating the Joint
  5. Creating the Command
  6. Setting the Fixed Product
  7. Epilog

We will now comment each of those sections by looking at the code.

[Top]

Prolog

The use case is the CAAKiiCreateMechanism batch which runs in one shot. The described code is located in the C++ main method. It begins by creating a session, and by opening the use case CATProduct document passed as an argument: pDocument refers to it. This is the usual sequence for creating a document [3].

[Top]

Searching Geometries

The objective of this step is to retrieve the connector associated with the line in each of the two products:

...
  // Search all the roots of the document
  CATIDocRoots* piDocRootsOnDocument = NULL;
  HR = pDocument->QueryInterface(IID_CATIDocRoots, (void**)&piDocRootsOnDocument);
  if (SUCCEEDED(HR))
  {
    CATListValCATBaseUnknown_var* pRootList = piDocRootsOnDocument->GiveDocRoots();
    piDocRootsOnDocument->Release();
    piDocRootsOnDocument = NULL;
    if (NULL != pRootList)
    {
      // Search the root product
      CATIProduct* piProductOnRootProduct = NULL;
      CATIProduct_var spRootProduct = NULL_var;
      for (int j = 1; j <= pRootList->Size() && NULL == piProductOnRootProduct; j++)
      {
        HR = (*pRootList)[j]->QueryInterface(IID_CATIProduct,(void**)&piProductOnRootProduct);
        if (SUCCEEDED(HR)) {spRootProduct = (*pRootList)[j];}
      }
      delete pRootList;
      pRootList = NULL;

      // Get all the products of the root product
      CATListValCATBaseUnknown_var* pProductList = piProductOnRootProduct->GetAllChildren();
      int numberOfProducts = pProductList->Size();
    
      // Search two valid lines in the products
      const int maximumNumberOfConnector = 2;
      CATLISTP(CATBaseUnknown) iConnectorList;
      CATIProduct* piFixedProduct = NULL;
      int numberOfConnector = 0;
      for (int i = 1; numberOfConnector < maximumNumberOfConnector && i <= numberOfProducts; i++)
      {    
        // Search the product
        CATIProduct* piProductOnProduct = NULL;
        if (SUCCEEDED((*pProductList)[i]->QueryInterface(IID_CATIProduct,(void**)&piProductOnProduct)))
        {    
          // retain first product to be set as fixed at the end
          if (i==1) {
            piFixedProduct = piProductOnProduct;
            piFixedProduct->AddRef();
          }
          // Search the link to the shape representation associated with the product
          CATILinkableObject_var spLinkableOnShapeRep = NULL_var;
          if (SUCCEEDED(piProductOnProduct->GetShapeRep(spLinkableOnShapeRep)))  {        
            // Use the link the find the document containing the shape representation
            CATDocument* pShapeDocument = spLinkableOnShapeRep->GetDocument();
            if (NULL != pShapeDocument)
            {   
              // Find the container of the document
              CATIContainerOfDocument* piContainerOfDocumentOnShapeDocument = NULL;
              if (SUCCEEDED(pShapeDocument->QueryInterface(IID_CATIContainerOfDocument,
                                                           (void**)&piContainerOfDocumentOnShapeDocument)))
              {
                // Find the container of the geometry
                CATIContainer* piContainer = NULL;
                piContainerOfDocumentOnShapeDocument->GetSpecContainer(piContainer);
                piContainerOfDocumentOnShapeDocument->Release();
                piContainerOfDocumentOnShapeDocument = NULL;
                if (NULL != piContainer)
                {
                  // List all geometrical entities and search the first line in the document
                  SEQUENCE(CATBaseUnknown_ptr) memberList = piContainer->ListMembers(CATLine::ClassName());
                  CATBaseUnknown* papiUnknownOnLineConnector = NULL;
                  for (int k = 0; NULL == papiUnknownOnLineConnector && k < memberList.length(); k++)
                  {
                    // Filter the line
                    CATLine* piLine = NULL;
                    if (SUCCEEDED(memberList[k]->QueryInterface(IID_CATLine,(void**)&piLine)))
                    {
                      CATILinkableObject_var spLinkableOnLine (memberList[k]);
                      if (NULL_var != spLinkableOnLine)
                      {
                        // Get the connector associated to the line
                        int xCreation = 0;
			
			HR = GetProductConnector(spLinkableOnLine, piProductOnProduct, piProductOnRootProduct, 0, spConnectorOnLine, xCreation);
                        if (NULL_var != spConnectorOnLine)  {
                          // Store the connector as a CATBaseUnknown
                          HR = spConnectorOnLine->QueryInterface(IID_CATBaseUnknown, (void**)&papiUnknownOnLineConnector);
                        }
                      }
                      piLine->Release();
                      piLine = NULL;
                    }
                  }
                  // Store the connector and the product corresponding to the line
                  if (NULL != papiUnknownOnLineConnector)  {
                    iConnectorList.Append(papiUnknownOnLineConnector);
                    numberOfConnector++;
                    papiUnknownOnLineConnector->Release();
                    papiUnknownOnLineConnector = NULL;
                  }
                  piContainer->Release();
                  piContainer = NULL;
               }
	          }
	        }
            piProductOnProduct->Release();
            piProductOnProduct = NULL;
          }
        }
      }
      delete pProductList;
      pProductList = NULL;
      piProductOnRootProduct->Release();
      piProductOnRootProduct = NULL;       
...

A CATProduct document contains many roots accessible thru GiveDocRoots method available on the CATIDocRoots interface of the document. The first root which answer to the interface CATIProduct, is the root of all the products in the document. To get all the products, the sample gets the children of the root product. Then the sample search two lines which belong to the products. It queries the document associated to each product as a shape representation. Having the list of all geometries in this document, it filters the lines and retrieves their connector. This connector and the corresponding product are stored in papiUnknownOnConnector and papiProduct. The sample has to clean the environment and release all resources. The technique is fairly simple: all references to interfaces have to be released using CATBaseUnknown::Release() and nullified.

[Top]

Creating the Mechanism

...
    CATIKinMechanism* piMechanism = NULL;
      CATIKinMechanismFactory* piDocumentAsMechanismFactory = NULL;
      if (SUCCEEDED(pDocument->QueryInterface(IID_CATIKinMechanismFactory, (void**)&piDocumentAsMechanismFactory)))  {
        if (SUCCEEDED(piDocumentAsMechanismFactory->CreateInstance(&piMechanism)))  {
...

The creation of a mechanism in the document is made through the factory method CreateInstance. The factory is obtained thru a QueryInterface on pDocument.

[Top]

Creating the Joint

...
        if (numberOfConnector == maximumNumberOfConnector)
        {
          // Cylindrical joint from connectors
          CATIKinJoint* piJoint = NULL;
          const char* jointType = CATKinCylindricalJoint;
          boolean iCreateConstraintsForJoint = 1;
          if (SUCCEEDED(piMechanism->AddJoint(jointType,&iConnectorList, iCreateConstraintsForJoint, &piJoint)))  {
...

A cylindrical joint is created in the mechanism from the two retrieved connectors using the AddJoint method of the CATIKinMechanism interface, with the connectors stored in iConnectorList.

[Top]

Creating the Command

...  
              CATIKinCmd* piCmd = NULL;
              const char* cmdType = CATKinLengthCmd;
              if (SUCCEEDED(piMechanism->AddCommand(piJoint, cmdType, &piCmd)))  {
                piCmd->Release();
                piCmd = NULL;
              }
              piJoint->Release();
              piJoint = NULL;
            }
          }
...

A translation command is associated with the mechanism to apply to the joint using AddCommand method of the CATIKinMechanism interface.

[Top]

Setting the Fixed Product

...  
          boolean iCreateConstraintsForFixed = 1;
          HR = piMechanism->SetFixedProduct(piFixedProduct,iCreateConstraintsForFixed);
          piFixedProduct->Release();
          piFixedProduct = NULL;
...

To complete the mechanism, the fixed product is defined using SetFixedProduct method of the CATIKinMechanism interface.

[Top]

Epilog

...  
         piMechanism->Release();
          piMechanism = NULL;   
         }
      piDocumentAsMechanismFactory->Release();
      }
...

The pointers to the mechanism and factory are released.

Then, the document is saving using CATDocumentServices::SaveAs static method in the directory passed as the third argument when launching the use case, and with the same name as the input document. After being saved, it is is closed using the remove method of its LifeCycleObject interface. The environment is cleaned, and the session is deleted by the Delete_Session global function, which is passed the same identifier that was used to open it. This is the usual sequence for saving and closing a CATIA document, and for deleting the session [3].

[Top]


In Short

This use case has demonstrated the way to programmatically navigate a CATProduct document, from the document itself down to the entities that hold the mechanism definition.

More specifically, you have learn how to create:

[Top]


References

[1] Kinematics Overview
[2] Building and Launching a CAA V5 Use Case
[3] Creating a New Document
[Top]

History

Version: 1 [Jan 2000] Document created
Version: 2 [Jan 2001] Interface reviewed; exposing only KinematicsInterfaces
Version: 3 [Aug 2002] CATProduct sample document added
[Top]

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