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
piUpdateErrorOnThis
piProcReport
pSoftConfig
piGeomFactory
[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)
piUpdateErrorOnThis
piProcReport
pSoftConfig
piGeomFactory
[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.