Geometric Modeler

Geometry

The Management of Foreign Data

How to Put Foreign Data on CGM Objects or Create Own Geometric Curves or Surfaces
Technical Article

Abstract

The geometric attributes are a quick way to add data on CGM objects. Moreover, they are used to introduce foreign surfaces into CGM, that this paper precisely details.


CGM Attributes

Definition

A CGM attribute (CATCGMAttribute class) is an object that can be pointed to by a CGM object (CATICGMObject interface, or its derived interfaces such a CATGeometry, CATSurface, CATCurve for example). It contains data that you want to add to a CGM object, without deriving from the corresponding interface. This is useful:

Depending on your need, you can create temporary or streamable attribute classes, by deriving your own class from the CATCGMAttribute class and CATCGMStreamAttribute class respectively:

Fig. 1: The objects involved in the attribute mechanisms
Foreign0.gif (4919 bytes) An attribute is a CATCGMAttribute object that is referenced by a CATICGMObject.

It can be temporary or streamable

You create your own attribute class by derivation.

All derived object from the CATICGMObject interface obviously owns the attributes management mechanism.

[Top]

Characterization

An attribute is characterized by a class name, an application name and a version number. The application name is a logical name for the physical load module that contains the attribute class. The mapping between the logical and physical names is realized through the static query implementation as precisely described in the Object Modeler documentation. What you need to know here is that you have to create a header that contains the physical name, a source that declares the mapping and a line into a dictionary. The header is as follows :

//-----------------------------------------------------------------------------
//         header XXX.h for the physical load name (XXX)
//-----------------------------------------------------------------------------
#ifdef  _WINDOWS_SOURCE
#ifdef  __XXX
#define ExportedByXXX   __declspec(dllexport)
#else
#define ExportedByXXX   __declspec(dllimport)
#endif
#else
#define ExportedByXXX
#endif

The source is:

//-----------------------------------------------------------------------------
//         source MyApplicationName.cpp for the mapping
//  logical load name (MyApplicationName) - physical load name (XXX)
//  through the dictionary
//-----------------------------------------------------------------------------
#include "AppDef.h"
AppDef(MyApplicationName);

The dictionary MyApplicationName.dico contains the following line:

MyApplicationName        CATICGMDomainBinder        libXXX

Now, you have to declare the mapping in your attribute class by the mean of the macro CATCGMDeclareAttribute, as showed in the header example MyAttributeClass.h below, and the macro CATCGMImplAttribute, as in the code example for a persistent (or streamable) MyAttributeClass.cpp:

#ifndef MyAttributeClass_H
#define MyAttributeClass_H
class CATCGMAttributeDef;
class CATCGMStream;
class CATICGMObject;
class CATCGMContainer;

#include "CATCGMStreamAttribute.h"
#include "XXX.h"

//-----------------------------------------------------------------------------
// case of a streamable attribute
class ExportedByXXX MyAttributeClass : public CATCGMStreamAttribute
{
  CATCGMDeclareAttribute(MyAttributeClass, CATCGMStreamAttribute);
  public :
  virtual void Stream(CATCGMStream & ioStream);
  virtual void UnStream(CATCGMStream & iStream);
// own methods..
  void SetValue(long iVal);
  void GetValue (long & oVal);
  protected :
// useful- returns 1 if TRUE 0 otherwise
    virtual long Compare(const CATCGMAttribute &iOtherAttribute);
};
// useful
ExportedByXXX void CastTo(CATCGMAttribute * iMyAttribute, MyAttributeClass * & oMyAttribute);
#endif

The corresponding source MyAttributeClass.cpp is:

#include "CATCGMAttrId.h"
#include "MyAttributeClass.h"
#include "CATBaseUnknown.h"
#include "CATCGMStream.h"

void CastTo(CATCGMAttribute * curattr, MyAttributeClass * & retour)
{
  retour =NULL;
  if (curattr ->IsATypeOf(UAIDPtr(MyAttributeClass)))
    retour = (MyAttributeClass *) curattr;
}
// declaration of the class, the application and the version.
CATCGMImplAttribute(MyAttributeClass,CATCGMStreamAttribute,MyApplication,1);

void MyAttributeClass::Stream(CATCGMStream & Str)
{Str.WriteLong(streamedvalue);}

void MyAttributeClass::UnStream(CATCGMStream & Str)
{Str.ReadLong(streamedvalue);}

void MyAttributeClass::SetValue(long val)
{ streamedvalue=val;}

void MyAttributeClass::GetValue (long & val)
{ val = streamedvalue;}

long MyAttributeClass::Compare(const CATCGMAttribute & NewAttr)
{
  long idef = 0;
  MyAttributeClass * newattr;
  CastTo((MyAttributeClass *)&NewAttr, newattr);
  if (streamedvalue== newattr->streamedvalue)
    idef=1;
  return idef;
}

[Top]

Management

Once defined, an attribute can be used by a CATICGMObject. Hence, the CATICGMObject::PutAttribute method allows a CATICGMObject to point to an attribute.

Now, the attributes can be read (CATICGMObject::GetAttribute) or released (CATICGMObject::ReleasedAttribute). If a CATICGMObject releases an attribute that is no more used, the attribute is deleted.

A CATICGMObject may point several attributes of different classes; conversely, an attribute may be pointed by several CATICGMObjects of the same container (a container is a set that contains objects). If a CATICGMObject is deleted, the attribute(s) that it points is(are) also deleted if this(these) attribute(s) is(are) no more pointed by any other CATICGMObjects.

[Top]

Stream and Unstream

The stream and unstream mechanisms allow you to translate a (persistent) object into a sequence of bytes and vice et versa. To unstream a file (at the File/Read operation for example), the unstream process uses the mapping between the application name and the load module name to load the right physical load module. If the load module is not found during the unstream process, the attribute is copied and referenced by the the CATICGMObject, but not seen, so that the model can be read and the data are not lost, but not usable too.

To write the stream and unstream methods for your own attribute, take into account that:

[Top]

Non Persistent Attribute: Sample

First described the application name through the dictionary and the corresponding header file.

The header of a new attribute class can be as as follows:

#ifndef UserNonPersistentAttr_H_
#define UserNonPersistentAttr_H_
#include "XXX.h"
#include "CATCGMAttribute.h"

class ExportedByXXX UserNonPersistentAttr : public CATCGMAttribute
{
public :
CATCGMDeclareAttribute(UserNonPersistentAttr,CATCGMAttribute);
UserNonPersistentAttr();
UserNonPersistentAttr(const UserNonPersistentAttr&);
UserNonPersistentAttr& operator=(const UserNonPersistentAttr&);
virtual ~UserNonPersistentAttr();

};
#endif

The source file is then:

#include "UserNonPersistentAttr.h"
CATCGMImplAttribute(UserNonPersistentAttr,CATCGMAttribute,NoAppDef,1);
//
UserNonPersistentAttr::UserNonPersistentAttr() :
CATCGMAttribute()
{
}
//
UserNonPersistentAttr::UserNonPersistentAttr(const UserNonPersistentAttr&)
{
}
//
UserNonPersistentAttr& UserNonPersistentAttr::operator=(const UserNonPersistentAttr&)
{
return *this;
}
//
UserNonPersistentAttr::~UserNonPersistentAttr()
{
}

To use it:

//Creates a UserNonPersistentAttr
UserNonPersistentAttr * pMyAttr=new UserNonPersistentAttr();
//
// Puts it on a line
piLine->PutAttribute(pMyAttr);
//
// Gets it from the line
UserNonPersistentAttr * pRetrievedAttr=
    (UserNonPersistentAttr*) piLine->GetAttribute(UAIDPtr(UserNonPersistentAttr))
// 
//Releases it from the line if no more needed
piLine->ReleaseAttribute(pRetrievedAttr);

[Top]

The Introduction of a Foreign Surface Class

CATIA Geometric Modeler offers a large variety of surfaces (CATSurface interface) from elementary surfaces to Nurbs surfaces, and from sampled surfaces to procedural surfaces. All the capabilities of these surfaces are described in the [2] paper.

You may need to introduce your own surface classes, either you want to have a special interface for existing CATSurfaces (for example, you want to have a class for Bezier surface, that is a specific case of CATNurbsSurface), or you have developed own methods that are optimized for a given type of surfaces.

This section describes the way to introduce foreign surfaces in CGM. Once introduced, they can be handled as any CATSurface: thus, they can be used, for example, by the geometric operators or as the geometric support of topological faces as any CATSurface. All CATSurface must be C2 continuous (at least twice differentiable). So does your own surfaces.

[Top]

Base Principle

The base principle is to involve an attribute class called CATForeignSurfaceData and the interface CATIForeignSurface in a bi-directional relashionship: the CATIForeignSurface is a void shell, that is filled by the CATForeignSurfaceData, as attribute of CATIForeignSurface.

You only have to derive your own attribute class from CATForeignSurfaceData, and overload the pure virtual (at least) methods.

Fig. 2: The mechanism of introduction of a foreign surface
Foreign2.gif (5772 bytes) CGM offers two objects that are bi-directionally linked. CATIForeignSurface and CATForeignSurfaceData.

To introduce your own surface object, you have to derive CATForeignSurfaceData , and overload the methods to fit the properties of your object.

Then, a CATIForeignSurface object that have a MySurfaceData object as data is handled as any CATSurface by CGM, and with the behavior you have given it.

CATForeignSurfaceData is a CATCGMStreamAttribute. Hence, it globally owns the same properties as its father, except that:

Once described the general mechanism, we detail now the methods of CATForeignGeometryData and CATForeignSurfaceData, that must or may be written for taking into account the properties of your own surface.

[Top]

CATForeignGeometryData

This class handles the common behavior of all the foreign geometric objects. It is the counterpart of the CATGeometry interface. We find here

If you compare the methods that are requested for your object with the CATGeometry and CATICGMObject methods, you can notice that nothing maps the GetLinks method. Indeed, if your object refers to an other one, that is foreign or CGM, this forward linked object would not be taken into account in any CGM processes up to now.

[Top]

CATForeignSurfaceData

This class handles the behavior of the foreign surfaces. It is the counterpart of the CATSurface interface. Let us first remind some important CATSurface properties:

Hence, the main methods of the CATForeignSurfaceData are:

[Top]

CATMathFunctionXY

This class manages the evaluators that are used by the surface evaluators. There are already CATMathLinearXY, CATMathFunctionXY, CATMathPolynomXY are kind of CATMathFunctionXY that are already provided in CGM.

If needed however, you may derive your own class of function to fit your object behavior, and overload at least the evaluator Eval of the value of the function.

The evaluation of the first and second derivatives may be approximated by default. So do the interval evaluators. It is however strongly recommended to overload the first derivatives evaluation, the best being to also write the second derivatives evaluation. If you overload the interval evaluators you will increase the CPU performances.

[Top]

How to Proceed

This section summarizes the steps for the integration of your own surface class.

[Top]


In Short

Attribute Pointed by Streamable
CATCGMAttribute one or more CATICGMObject no
CATCGMStreamAttribute one or more CATICGMObject of the same container yes
A file is readable, even if the attribute class load module is not found
CATForeignSurfaceData only one CATIForeignSurface, that points only one CATForeignSurfaceData yes
A file is not readable if the attribute class load module is not found

[Top]


References

[1] The Curves of CATIA Geometric Modeler
[2] The Surfaces of CATIA Geometric Modeler
[Top]

History

Version: 1 [Mar 2000] Document created
[Top]

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