Mechanical Modeler |
Building Combined CurvesImplementing CATIBuild |
|
| Use Case | ||
| Creating a New Geometrical Feature : The Combined Curve > Building Combined Curves | ||
AbstractThis article explains how to build the result of the combined curve. |
This use case demonstrates how to build the result of a geometrical feature which is a wireframe feature. The build is done by the update mechanism through the CATIBuild interface. The article entitled "Integrating a New Geometrical Feature in the Update Mechanism" [1] explains in details this interface and how to implement it.
From V5R15, the use case has been enriched to build or not the result, a choice managed by the CATIMechanicalProperties interface [8].
[Top]
CAAMmrCombinedCurve is a use case of the CAAMechanicalModeler.edu framework that illustrates Mechanical Modeler frameworks capabilities.
[Top]
This article explains how the Combined Curves implements the CATIBuild
interface. This interface is called whenever someone wants to update an
object. The Build method, the unique method of this interface
produces:
Build method constructs an object which manages the access
stability of the CATCell of the CATBody. This object is
a scope created by the procedural report
of the Combined Curve. Build method
retrieves the software level (SoftwareConfiguration) which will be used to
compute Built result. On the first Build call, the
AlgorithmConfiguration is set on the feature instance to keep this
information.The following picture explains the process of the Build method in the case of
a surfacic (wireframe) feature:
![]() |
All the inputs specifications of the feature will be followed by the procedural report. The CATIMechanicalImport interface will be used to check if the result must be built of not.
The final part of the Use Case describes how to manage any potential error that may occur during the Combined Curve building .
[Top]
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, follow the scenario described below:
The following picture shows the CAACombinedCurve.CATPart, on left when the result of the combined curve is computed, and on right otherwise.
![]() ![]() |
On right note that the icon of the combined curve shows that the geometrical
feature is deactivated:![]()
(*) The file is located in the directory
CAAMechanicalModeler.edu/InputData
InstallRootDirectory/CAAMechanicalModeler.edu/InputData
InstallRootDirectory\CAAMechanicalModeler.edu\InputData
where InstallRootDirectory is the directory where the CAA CD-ROM
is installed.
[Top]
The CAAMmrCombinedCurve use case is made one class,CAAEMmrCombinedCurveBuild, located in the CAAMmrCombinedCurve.m module of the CAAMechanicalModeler.edu framework:
| Windows | InstallRootDirectory\CAAMechanicalModeler.edu\CAAMmrCombinedCurve.m\ |
| Unix | InstallRootDirectory/CAAMechanicalModeler.edu/CAAMmrCombinedCurve.m/ |
where InstallRootDirectory is the directory where the CAA CD-ROM
is installed.
[Top]
By implementing the CATIBuild interface, you will define how a Combined Curve
is build, i.e. how to compute the two extruded surfaces and their intersection,
and how to integrate these operations in the procedural journal. This interface
contains one method, the Build method, whose the contents is the
following:
...
HRESULT CAAEMmrCombinedCurveBuild::Build ()
{
HRESULT rc = E_FAIL ;
Declaring the Useful Pointers
CATTry
{
Checking the build activation
if ( DeactivateState == 0 )
{
Removing all Possible Update Errors Associated with the Combined Curve
Retrieving Data for the Procedural Report
Creating the Procedural Report
Running the Topological Operators
Storing the Procedural Report and the Algorithm Configuration
Cleaning the Useless Data
}
}
// Managing the Errors
CATCatch(CATMfErrUpdate , pUpdateError)
{
Managing the CATMfErrUpdate Error
}
CATCatch(CATError , pError)
{
Managing the CATError Error
}
CATEndTry
return rc ;
}
...
|
This method contains a CATTry and CATCatch sections
because some methods can throw an error. [3]
At last, the Implementing the CATIBuild Interface section describes how to create the new data extension for the Combined Curve feature.
Before the CATTry section you declare all the pointers:
CATTry and CATCatch sections: such
as piUpdateErrorOnThis the CATIUpdateError interface
pointer on the combined curve.CATTry section and not released before the
call of a method which can throw an error
...
CATIUpdateError * piUpdateErrorOnThis = NULL;
CATTopPrism * pCurve1Extrude = NULL;
CATTopPrism * pCurve2Extrude = NULL;
CATHybOperator * pIntersect = NULL;
CATBody * pCurve1ExtrudeBody = NULL ;
CATBody * pCurve2ExtrudeBody = NULL ;
CATIMfProcReport * piProcReport = NULL;
CATGeoFactory * piGeomFactory = NULL;
CATSoftwareConfiguration * pSoftConfig = NULL;
int IsConfigToStore = NULL;
...
|
All this pointers will be explained in the next sections.
[Top]
This part consists in to check the status of the combined curve in term of build's activation. This information is managed by the CATIMechanicalProperties interface [8].
...
int DeactivateState = 0 ;
CATIMechanicalProperties *pMechProp = NULL ;
rc = QueryInterface(IID_CATIMechanicalProperties,(void **) & pMechProp);
DeactivateState = pMechProp->IsInactive();
if ( 1 == DeactivateState )
{
QueryInterface(IID_CATIMfProcReport,(void**) &piProcReport );
rc = piProcReport->InactivateResult();
piProcReport->Release();
piProcReport = NULL ;
...
|
If the geometrical feature is deactivated, the InactivateResult
method of the
CATIMfProcReport interface must be used. This interface,
CATIMfProcReport,
is natively implemented by a geometrical feature.
Once the procedural report is
deactivated, you can leave the CATTry section. But before you
must release piProcReport, the
CATIMfProcReport interface pointer. It is
the only one pointer declared in the
Declaring the Useful Pointers
section, and valuated in this section.
This check
about the deactivation must be done in the CATTry section because the
InactivateResult method of the CATIMfProcReport can through an
error. In this case, piProcReport will be released in the CATCatch
section.
[Top]
It is safer to remove all possible
update error that may be associated with the current Combined Curve feature. To do
so, use the UnsetUpdateError of the
CATIUpdateError interface.
...
rc = QueryInterface( IID_CATIUpdateError , (void**) &piUpdateErrorOnThis);
if ( SUCCEEDED(rc) )
{
piUpdateErrorOnThis->UnsetUpdateError();
}
...
|
The implementation of CATIUpdateError interface for Combined Curve is provided by an extension of late type MechanicalFeature. Since CombinedCurve late type derives from MechanicalFeature late type [4], you automatically benefit from this implementation.
[Top]
This step consists in three sub-steps which are :
With the CAAIMmrCombinedCurve interface [5] it is easy to retrieve the Combined Curve input curves and directions.
...
CATISpecObject *piSpecOnCurve1 = NULL;
CATISpecObject *piSpecOnCurve2 = NULL;
CATISpecObject *piSpecOnDirection1 = NULL;
CATISpecObject *piSpecOnDirection2 = NULL;
CAAIMmrCombinedCurve *piCombinedCurve = NULL;
rc = QueryInterface( IID_CAAIMmrCombinedCurve , (void**) &piCombinedCurve );
if ( SUCCEEDED(rc) )
{
// Retrieves curves and directions
rc = piCombinedCurve->GetCurve ( 1 , &piSpecOnCurve1 );
if ( SUCCEEDED(rc) )
rc = piCombinedCurve->GetDirection( 1 , &piSpecOnDirection1 );
if ( SUCCEEDED(rc) )
rc = piCombinedCurve->GetCurve ( 2 , &piSpecOnCurve2 );
if ( SUCCEEDED(rc) )
rc = piCombinedCurve->GetDirection( 2 , &piSpecOnDirection2 );
...
|
Once the inputs are retrieved, you can generate an error if one of them are not valid.
...
if ( FAILED(rc) )
{
if ( NULL != piSpecOnCurve1 )
{
piSpecOnCurve1->Release();
piSpecOnCurve1 = NULL;
}
if ( NULL != piSpecOnCurve2 )
{
piSpecOnCurve2->Release();
piSpecOnCurve2 = NULL;
}
if ( NULL != piSpecOnDirection1 )
{
piSpecOnDirection1->Release();
piSpecOnDirection1 = NULL;
}
if ( NULL != piSpecOnDirection2 )
{
piSpecOnDirection2->Release();
piSpecOnDirection2 = NULL;
}
CATMfErrUpdate *pErrorNoValidInput = new CATMfErrUpdate();
CATUnicodeString Diagnostic("Invalid inputs.");
pErrorNoValidInput->SetDiagnostic(1,Diagnostic);
CATThrow(pErrorNoValidInput);
}
}
...
|
pErrorNoValidInput is a CATMfErrUpdate error. Before to
throw the error, all the none-null pointers declared in the CATTry
section, in other words the inputs of the Combined Curve, are released.
Note: In the use case we have chosen to generate an update error if the inputs of the combined curve are wrong. You can also considerer that it is an internal error, so do not generate an error but only use the HRESULT mechanism. In this last case, the "Update Diagnosis" dialog box will not appear in case of error. Refer to the "A Description of Update Errors" article [6] for details about the update errors.
Retrieving the geometrical directions of the two input directions is even easier. You just have to get a pointer on CATLine from the input direction, and then ask this CATLine for its mathematical direction.
...
CATMathDirection MathDirection1,MathDirection2 ;
if ( SUCCEEDED(rc) )
{
CATLine *piLine1 = NULL;
rc = piSpecOnDirection1->QueryInterface( IID_CATLine , ( void**) &piLine1 );
if ( SUCCEEDED(rc) )
{
piLine1->GetDirection(MathDirection1);
...
}
}
if ( SUCCEEDED(rc) )
{
CATLine *piLine2 = NULL;
rc = piSpecOnDirection2->QueryInterface( IID_CATLine , ( void**) &piLine2 );
if ( SUCCEEDED(rc) )
{
piLine2->GetDirection(MathDirection2);
...
}
}
...
|
These input curves and directions will be now asked to give their geometry so that you can compute the two extruded surfaces.
A method of CATIGeometricalElement retrieves the CATBody corresponding to a feature.
...
CATBody_var spiBodyOfCurve1,spiBodyOfCurve2 ;
if ( SUCCEEDED(rc) )
{
CATIGeometricalElement *piGeometricalElementOnCurve1 = NULL;
rc = piSpecOnCurve1->QueryInterface ( IID_CATIGeometricalElement ,
(void**) &piGeometricalElementOnCurve1 );
if ( SUCCEEDED(rc) )
{
spiBodyOfCurve1 = piGeometricalElementOnCurve1->GetBodyResult();
...
}
}
if ( SUCCEEDED(rc) )
{
CATIGeometricalElement *piGeometricalElementOnCurve2 = NULL;
rc = piSpecOnCurve2->QueryInterface ( IID_CATIGeometricalElement ,
(void**) &piGeometricalElementOnCurve2 );
if ( SUCCEEDED(rc) )
{
spiBodyOfCurve2 = piGeometricalElementOnCurve2->GetBodyResult();
...
}
}
...
|
Once again, you do not have to worry about the implementation of CATIGeometricalElement for your Combined Curve or input curves. For example, the parent late type GeometricalElement3D [4] of CombinedCurve has an extension that provides the implementation for CATIGeometricalElement.
[Top]
The procedural report is the means to generate the scope of the feature by using the topological report to generate the name of the following cells. The procedural report is managed by the CATIMfProcReport interface.
The first thing is to declare the following cells by the procedural journal during the Build operation. In general, in the case of a surfacic feature, all the input specifications are followed:
...
CATLISTV(CATBaseUnknown_var) ListSpec;
CATListOfCATUnicodeString ListKeys;
if ( SUCCEEDED(rc) )
{
ListSpec.Append( piSpecOnCurve1 );
ListKeys.Append( MfKeyNone );
ListSpec.Append( piSpecOnDirection1 );
ListKeys.Append( MfKeyNone );
ListSpec.Append( piSpecOnCurve2 );
ListKeys.Append( MfKeyNone );
ListSpec.Append( piSpecOnDirection2 );
ListKeys.Append( MfKeyNone );
}
...
|
ListSpec is the list of specifications to follow, and ListKeys
is the list of associated keys. These two lists have the same size. The default
value of a key is MfKeyNone. A different key value will indicate
that the historical relationship of a node should be replaced with a user
information. The value of the key must be in relationship with the
information given by the topological report.
...
if ( SUCCEEDED(rc) )
{
rc = QueryInterface( IID_CATIMfProcReport , (void**) &piProcReport );
if ( SUCCEEDED(rc) )
{
int BoolOper = 0;
piProcReport->CreateProcReport(ListSpec,ListKeys,BoolOper);
}
}
...
|
Once the CATIMfProcReport interface pointer on the combined curve is
retrieved, piProcReport, you can create the procedural report
thanks to the CreateProcReport method. The last argument of this
method is 0, the default value, because the result ( the scope )
will be affected to the feature itself [Fig.1]. Note that
piProcReport is declared at the top of the Build method because it
can be released in a CATCatch section.
[Top]
This step consists in three sub-steps which are always:
The geometrical factory is handled by the CATGeoFactory interface. This interface is implemented by the geometrical container of the Part document [7]. You retrieve this container thanks to the CATIContainerOfDocument interface implemented on the Part document. The CATILinkableObject interface is the means for each feature to retrieve its containing document.
...
if ( SUCCEEDED(rc) )
{
CATILinkableObject *piLinkableObjectOnCombinedCurve = NULL;
rc = QueryInterface( IID_CATILinkableObject,
(void**)& piLinkableObjectOnCombinedCurve );
if ( SUCCEEDED(rc) )
{
CATDocument * pDocument = NULL ;
pDocument = piLinkableObjectOnCombinedCurve->GetDocument();
if ( NULL != pDocument )
{
CATIContainerOfDocument * pIContainerOfDocument = NULL ;
rc = pDocument->QueryInterface(IID_CATIContainerOfDocument,
(void**)& pIContainerOfDocument );
if ( SUCCEEDED(rc) )
{
CATIContainer * pIContainerOnGeomContainer = NULL ;
rc = pIContainerOfDocument->GetResultContainer
(pIContainerOnGeomContainer);
if ( SUCCEEDED(rc) )
{
rc = pIContainerOnGeomContainer->QueryInterface( IID_CATGeoFactory ,
(void**) &piGeomFactory );
...
}
...
|
The GetResultContainer is the method of the CATIContainerOfDocument
to retrieve the geometrical container. piGeomFactory is the pointer
on the geometrical factory interface. This pointer is declared at the beginning
of the Build
method because it can be released in a CATCatch section.
The procedural report then provides a pointer on a new topological journal that will log all topological operations.
...
CATTopData TopData ;
if ( SUCCEEDED(rc) )
{
CATCGMJournalList *pCGMJournalList = piProcReport->GetCGMJournalList();
TopData.SetJournal(pCGMJournalList) ;
...
|
pCGMJournalList is the pointer on the topological journal. This
pointer must not be released. pSoftConfig is a pointer declared
at the beginning of the Build
method because it can be released in a CATCatch section.
The "CATSoftwareConfiguration" pointer (pSoftConfig) is needed to get the version of the Combined Curve feature [9]. This information is used to determine which type of algorithm will be used to compute the result.
This Software Configuration is stored on the feature instance and has to be retrieved using "CATMmrAlgoConfigServices::GetConfiguration".
If your feature has not been built yet, "IsConfigToStore = 1". Then, the value set by "TopData.SetSoftwareConfiguration" has to be stored using CATMmrAlgoConfigServices::StoreConfiguration at the end of build process of the feature.
... rc = QueryInterface(IID_CATISpecObject,(void **) & pSOCombinedCurve);
if(SUCCEEDED(rc)&&pSOCombinedCurve != NULL)
{
rc = CATMmrAlgoConfigServices::GetConfiguration(pSOCombinedCurve ,pSoftConfig ,IsConfigToStore);
if(SUCCEEDED(rc))
{
// SetSoftwareConfig
TopData.SetSoftwareConfiguration(pSoftConfig) ;
// release pSoftConfig after the procedural report ending
}
}
...
|
Note that "pSoftConfig" and "IsConfigToStore" are declared
at the beginning of the Build
method because they will be useful at its end and because pSoftConfig can be released in a CATCatch section.
The combined curve geometry is computed thanks three operations:
The first surface is created by a CATTopPrism
operator. pCurve1Extrude is a CATTopPrism interface pointer
declared at the top of the Build method.
...
if ( SUCCEEDED(rc) )
{
CATLength StartOffset = 1000;
CATLength EndOffset = -StartOffset;
pCurve1Extrude = ::CATCreateTopPrism ( piGeomFactory ,
&TopData ,
spiBodyOfCurve1 ,
&MathDirection1 ,
StartOffset ,
EndOffset);
if ( NULL != pCurve1Extrude)
{
pCurve1Extrude->Run();
pCurve1ExtrudeBody = pCurve1Extrude->GetResult();
}
...
}
...
|
pCurve1ExtrudeBody is an intermediary CATBody corresponding to
the first surface. It is also declared at the top of the Build
method. Once the combined curve body will be computed, pCurve1ExtrudeBody
should be removed from the geometric container.
The second surface is also created by a CATTopPrism
operator. pCurve2Extrude is a CATTopPrism interface pointer
declared at the top of the Build method.
...
pCurve2Extrude = ::CATCreateTopPrism ( piGeomFactory ,
&TopData,
spiBodyOfCurve2 ,
&MathDirection2 ,
StartOffset ,
EndOffset);
if ( NULL != pCurve2Extrude)
{
pCurve2Extrude->Run();
pCurve2ExtrudeBody = pCurve2Extrude->GetResult ();
}
}
...
|
pCurve2ExtrudeBody is an intermediary CATBody corresponding to
the first surface. It is also declared at the top
of the Build
method. Once the combined curve body will be computed, pCurve2ExtrudeBody
should be removed from the geometric container.
At last, the final result is created
by a CATHybOperator operator. pIntersect is a CATHybOperator
interface pointer declared at the top
of the Build method. pResultBody
is the resulting topology.
...
CATBody *pResultBody = NULL ;
if ( SUCCEEDED(rc) && (NULL!=pCurve2ExtrudeBody) && (NULL!=pCurve1ExtrudeBody) )
{
pIntersect = ::CATCreateTopIntersect ( piGeomFactory ,
&TopData ,
pCurve1ExtrudeBody ,
pCurve2ExtrudeBody );
if ( NULL != pIntersect )
{
pIntersect->Run();
pResultBody= pIntersect->GetResult ();
}
}
...
|
Note that pResultBody is not declared at the top of the
method. It is not necessary once its lifecycle is managed by the DeletedProcReport
method in the CATCatch sections.
[Top]
It is now high time to store (fill) the procedural report corresponding to
the creation of the geometric result of the Combined Curve. That's the job of
the CATIMfProcReport::StoreProcReport method.
In addition, it is also time to store the Algorithm Configuration, if it is
needed...
In deed, when the software configuration is retrieved, an integer (IsConfigToStore)
determines if it is needed to store this data on the feature
instance.
This configuration, used to version the feature, has to be stored, at least, on
the first Build Time.[9]
The storage of this data on the feature instance is done thanks to
CATMmrAlgoConfigServices::StoreConfiguration method.
...
if ( SUCCEEDED(rc) )
{
if ( NULL != pResultBody )
{
int BoolOper = 0 ;
piProcReport->StoreProcReport(pResultBody,NoCopy,BoolOper);
if(IsConfigToStore == 1)
{
CATMmrAlgoConfigServices::StoreConfiguration(pSOCombinedCurve ,pSoftConfig);
}
}
else
{
CATMfErrUpdate *pErrorNoIntersection = new CATMfErrUpdate();
CATUnicodeString Diagnostic("The two extruded curves do not intersect.");
pErrorNoIntersection->SetDiagnostic(1,Diagnostic);
CATThrow(pErrorNoIntersection);
}
}
...
|
The last argument of the StoreProcReport method, BoolOper,
is the same as the value in the CreateProcReport method.
[Top]
In this last part of the CATTry section, you clean the data
declared in the first section entitled "Declaring
the Useful Pointers" and not released/deleted during the CATTry
section.
pCurve1ExtrudeBody and pCurve2ExtrudeBody All the objects not yet deleted, it means the topological operators: pCurve1Extrude, pCurve2Extrude
and pIntersect
piUpdateErrorOnThispiProcReportpSoftConfigpiGeomFactory
[Top]
Some errors may be thrown during these previous operations, the CATTry
bloc catches them and the CATCatch blocks treats the error. There
are two kinds of
errors:
Each CATCatch section processes the error and cleans
the pointers declared at the top of the Build method.
The highest-level errors are of CATMfErrUpdate type. The error is re-thrown without modification.
...
CATCatch ( CATMfErrUpdate , pUpdateError)
{
if(NULL != piUpdateErrorOnThis)
{
piUpdateErrorOnThis->SetUpdateError(pUpdateError);
piUpdateErrorOnThis->Release();
piUpdateErrorOnThis = NULL ;
}
// Here the pointers declared at the top of the
|
All other types of errors derive from CATError. The following code associates the diagnostic and the error with the Combined Curve:
...
CATCatch ( CATError , pError)
{
CATMfErrUpdate *pErrorToThrow = new CATMfErrUpdate();
pErrorToThrow->SetDiagnostic(1,pError->GetNLSMessage());
::Flush(pError);
if(NULL != piUpdateErrorOnThis)
{
piUpdateErrorOnThis->SetUpdateError(pErrorToThrow);
piUpdateErrorOnThis->Release();
piUpdateErrorOnThis = NULL ;
}
// Here the pointers declared at the top of the
|
A new CATMfErrUpdate is created. pError, the CATError,
must be released. The Flush global function do
that.
In the two CATCatch sections it is important to :
DeleteProcReport
method.and for the data declared in the first section entitled "Declaring the Useful Pointers":
pCurve1ExtrudeBody and pCurve2ExtrudeBody Delete the topological operators: pCurve1Extrude, pCurve2Extrude
and pIntersect
CATTry section: ( You should always have,
at least, these
four pointers)
piUpdateErrorOnThispiProcReportpSoftConfigpiGeomFactory
[Top]
To implement the CATIBuild interface, you just have to create a new extension of Combined Curve. Its class name is CAAEMmrCombinedCurveBuild.
This part of CAAEMmrCombinedCurveBuild.cpp aims at declaring this new extension.
...
CATImplementClass(CAAEMmrCombinedCurveBuild,
DataExtension,
CATBaseUnknown,
CombinedCurve);
#include "TIE_CATIBuild.h"
TIE_CATIBuild( CAAEMmrCombinedCurveBuild);
...
|
Do not forget to update your dictionary to declare CombinedCurve has been extended to implement CATIBuild.
[Top]
This paper demonstrates a complete implementation of the CATIBuild interface for the Combined Curve mechanical feature, that can now take part in the update of a Part document.
[Top]
| Version: 1 [Apr 2000] | Document created |
| Version: 2 [Jan 2003] | Document updated |
| Version: 3 [Jan 2005] | Document updated for build deactivation integration |
| Version: 4 [Jan 2007] | Document updated for Algorithm Configuration Services |
| [Top] | |
Copyright © 2000, Dassault Systèmes. All rights reserved.