Geometric Modeler |
Tessellation |
Browsing the Geometric ContainerThe application to visualize geometry and topology |
Use Case |
AbstractIn all the CATIA Geometric Modeler use cases, a CATGeoFactory container, creating and containing the geometric objects, is created and can be stored in a .NCGM file. The purpose of the CAAGemBrowser use case is to create an application and a document allowing you to visualize the created objects of a CATGeoFactory container. |
This use case explains a means to visualize geometric objects:
First an application and a document are defined, following the same way as in
the CAAVisBase
use case. Then, the visualization of the objects are
computed. Hence, you will learn:
CATCellOperator
to
tessellate a cell, CATCurveTessellator
to tessellate a curve
and CATSurfaceTessellator
to tessellate a surface.[Top]
CAAGemBrowser is a use case of the CAAGemBrowser.edu framework that illustrates Tessellation framework capabilities.
[Top]
This use case:
This use case is a proposal of geometry visualization. Its intent is not to be a full graphic application. In particular, the color or the selection are not managed here.
In the picture above, the CAAGemBrowser use case displays the result of the CAATopJournal use case. This result was saved in the directory
Windows | InstallRootDirectory\intel_a\CNext\resources\graphic\CAATopJournal.NCGM |
Unix | InstallRootDirectory/OS_a/CNext/resources/graphic/CAATopJournal.NCGM
(OS depends on the system [1] ) |
to allows you to visualize an example without processing any other use case. To visualize the model, simply select the menu File and the item Open. Then select the file.
[Top]
To launch CAAGemBrowser, you will need to set up the build time environment, then compile CAAGemBrowser.m along with its prerequisites, set up the run time environment, and then execute the use case [1].
This use case is an interactive application. To visualize a .NCGM document (for example, the model saved at the last step of the CAATopJournal, CAATopOverview, CAAGobCreation, CAAGobNurbs, CAATesBody, or CAAGopIntersect use cases ), click the File+Open menu and select the file you want to display.
[Top]
The CAAGemBrowser use case is made of three classes
The sources (CAAGemBrowserApplication.cpp, CAAGemBrowserDocument.cpp, CAAGemRep.cpp) are located in the CAAGemBrowser.m module of the CAATessellation.edu framework.
The corresponding headers (CAAGemBrowserApplication.h, CAAGemBrowserDocument.h, CAAGemRep.h) are located in the LocalInterfaces directory of the CAAGemBrowser.m module.
Windows | InstallRootDirectory\CAATessellation.edu\CAAAGemBrowser.m\ |
Unix | InstallRootDirectory/CAATessellation.edu/CAAAGemBrowser.m/ |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
[Top]
CAAGemBrowser is divided into the following steps:
[Top]
Thanks to an interactive application, the CAAGemBrowserDocument can be displayed and run as a standalone application. This interactive application is made of the class CAAGemBrowserApplication that derives from CATInteractiveApplication. Its header file is as follows.
#include "CATInteractiveApplication.h" // To derive from class CAAGemBrowserApplication : public CATInteractiveApplication { public: CAAGemBrowserApplication(const CATString & iApplicationId); virtual ~CAAGemBrowserApplication(); virtual void BeginApplication(); virtual int EndApplication(); private: CAAGemBrowserApplication(); CAAGemBrowserApplication(const CAAGemBrowserApplication &iObjectToCopy); }; |
In addition to the constructor and destructor, this interactive application class redefines two methods of CATInteractiveApplication:
BeginApplication
, called by the system just after the
application constructor. This method is dedicated to create the different
objects managed by the application, namely here the document window
EndApplication
, called by the system when the application
destruction is requested. This method is dedicated to deallocate objects or
close files.The document window is created in the BeginApplication
method,
and in this use case, the EndApplication
has nothing to deallocate
since it is automatically deleted when the application is deleted.
... void CAAGemBrowserApplication::BeginApplication() { cout << "CAAGemBrowserApplication::BeginApplication" << endl; // This window is deleted when the application is deleted. // The application is deleted by the Destroy Method called in the // CAAGemBrowserDocument::Exit method. // CAAGemBrowserDocument * pMainWindow =NULL; pMainWindow = new CAAGemBrowserDocument(this); // Constructs all Dialog objects of the window pMainWindow->Build(); pMainWindow->SetVisibility(CATDlgShow); } int CAAGemBrowserApplication::EndApplication() { return 0; } |
Note that the document window is first instantiated, then initialized using
its Build
method, and finally set as visible. The constructor
parameter is the dialog box parent in the command tree structure, set as the
application itself.
The application is simply instantiated as follows.
... CAAGemBrowserApplication ApplicationInstance("CAAGemBrowserApplicationInstance"); |
The main program is created from this instance.
[Top]
The file CAAGemBrowserDocument.h contains the following:
#ifndef CAAGemBrowserDocument_h #define CAAGemBrowserDocument_h #include "CATDlgDocument.h" // To derive from class CATInteractiveApplication; // Application kept in data member class CATDlgFile; class CAT3DBagRep ; // Data member class forward declaration class CATNavigation3DViewer; class CATGeoFactory; class CAAGemBrowserDocument : public CATDlgDocument { DeclareResource(CAAGemBrowserDocument, CATDlgDocument) public: CAAGemBrowserDocument(CATInteractiveApplication * iParentCommand); virtual ~CAAGemBrowserDocument(); void Build(); private: ... // Creates the model representation, ie _pTheModelToDisplay void CreateModelRepresentation(); // Creates the Menubar which is reduced to a File/Open-Close-Exit option void CreateMenuBar(); // Creates the Dialog object to see the model void CreateViewer(); // Attaches the model representation in the 3D Viewer to see it and // asks a draw model void VisualizeModel(); // Default constructor, not implemented // Set as private to prevent from compiler automatic creation as public. CAAGemBrowserDocument (); // Copy constructor, not implemented // Set as private to prevent from compiler automatic creation as public. CAAGemBrowserDocument(const CAAGemBrowserDocument &iObjectToCopy); private: //The parent widget (a CATInteractiveApplication instance) CATInteractiveApplication * _pApplication; // The Top of the representation tree CAT3DBagRep * _pTheModelToDisplay ; // The Dialog object to display the model CATNavigation3DViewer * _p3DViewer ; // The "file selection" window CATDlgFile * _pFileSelector; // The geometry factory that is visualized CATGeoFactory * _piGeomFactory; }; #endif |
The DeclareResource
macro enables the class and all its dialog
objects to use the automatic resource assignment. The first parameter is the
class name, and the resource files must use this class name as file name, such
as CAAGemBrowserDocument.CATNls for the file containing the texts and messages.
The class has a constructor, a destructor, and a Build
method.
Additional private methods create the menu bar, the dialog object to see the
model, the object containing all the representations and visualize the model.
Pointers to the different dialog objects are then declared as data members.
The remaining part of this file deals with the callback method declaration.
// Callback on the exit button item of the menubar void Exit (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData); // Callback on the open button item of the menubar void Open (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData); // Callback on the OK button item of the file window void OpenOK (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData); // Callback on the cancel button item of the file window void Cancel (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData); // Callback on the close button item of the menubar void Close (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData); |
[Top]
Let's have a look at the beginning of CAAGemBrowserDocument.cpp:
CAAGemBrowserDocument::CAAGemBrowserDocument(CATInteractiveApplication * iParentCommand) : CATDlgDocument(iParentCommand, "CAAGemBrowserRepWindowId"), _pApplication(iParentCommand),_pTheModelToDisplay(NULL), _p3DViewer(NULL), _piGeomFactory(NULL),_pFileSelector(NULL) { cout << "CAAGemBrowserDocument::CAAGemBrowserDocument" << endl; // Do not construct any Dialog object child in the constructor // Use the Build Method to do this. } void CAAGemBrowserDocument::Build() { cout << "CAAGemBrowserDocument::Build" << endl; CreateMenuBar(); CreateViewer(); } |
The constructor is empty, but calls the base class CATDlgDocument
constructor, and sets the parent command of the window as the interactive
application itself. The Build
method calls for the creation of the
menu bar and for the creation of the viewer that allows the user to do 3D
manipulations.
[Top]
void CAAGemBrowserDocument::CreateMenuBar() { CATDlgBarMenu* pMainMenu = NULL; pMainMenu = new CATDlgBarMenu(this,"MainMenu"); CATDlgSubMenu* pFileMenu = NULL; pFileMenu = new CATDlgSubMenu(pMainMenu,"File"); CATDlgPushItem* pOpenItem = NULL; pOpenItem = new CATDlgPushItem(pFileMenu,"Open"); AddAnalyseNotificationCB(pOpenItem, pOpenItem->GetMenuIActivateNotification(), (CATCommandMethod)&CAAGemBrowserDocument::Open, NULL); CATDlgPushItem* pCloseItem=NULL; pCloseItem = new CATDlgPushItem(pFileMenu,"Close"); AddAnalyseNotificationCB(pCloseItem, pCloseItem->GetMenuIActivateNotification(), (CATCommandMethod)&CAAGemBrowserDocument::Close, NULL); CATDlgPushItem * pExitItem =NULL; pExitItem = new CATDlgPushItem(pFileMenu,"Exit"); AddAnalyseNotificationCB(pExitItem, pExitItem->GetMenuIActivateNotification(), (CATCommandMethod)&CAAGemBrowserDocument::Exit, NULL); AddAnalyseNotificationCB(this, GetWindCloseNotification(), (CATCommandMethod)&CAAGemBrowserDocument::Exit, NULL); } |
The CreateMenuBar
method creates the menu and menu items. Since
the declaration of an external resource file has been made in the header, the
items will be displayed according to the chosen language.
Moreover, this method sets the callbacks to trigger the appropriate method when a specific control is activated.
[Top]
The 3D navigation viewer is an instance of the CATNavigation3DViewer class.
It is created in the CreateViewer
method of the
CAAGemBrowserDocument class that is called when the application is launched.
void CAAGemBrowserDocument::CreateViewer() { // The window contains a 3DViewer which allows the user to do 3D Manipulations _p3DViewer = new CATNavigation3DViewer( this, "3DViewerId",CATDlgFraNoTitle, 800, 450); // Changes the color of the background _p3DViewer->SetBackgroundColor(0.2f,0.2f,0.6f); // The Viewer is attached to the 4 sides of the Window Attach4Sides( _p3DViewer); } |
The _pViewer
pointer to the 3D navigation viewer is kept as a
data member of the CAAGemBrowserDocument class. The Attach4Sides
method attaches the four sides of the viewer to those of the window. This makes
the viewer occupy the whole window space.
[Top]
Once the user clicks on the File/Open item, the following callback is triggered:
void CAAGemBrowserDocument::Open (CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData) { // Creates a File box _pFileSelector = new CATDlgFile(this,"FileBox",NULL); _pFileSelector->SetVisibility(CATDlgShow); // Sets the authorized types CATUnicodeString nameExtension = CATUnicodeString("NCGM files"); CATString filterExtension = CATString("*.NCGM"); _pFileSelector->SetFilterStrings(&nameExtension, &filterExtension, 1); // callbacks on the FileBox interactions AddAnalyseNotificationCB(_pFileSelector, _pFileSelector->GetDiaCANCELNotification(), (CATCommandMethod)&CAAGemBrowserDocument::Cancel, NULL); int iTypeOfInput = 0; AddAnalyseNotificationCB(_pFileSelector, _pFileSelector->GetDiaOKNotification(), (CATCommandMethod)&CAAGemBrowserDocument::OpenOK, &iTypeOfInput); } |
This method creates a File Box to select the file to display. The authorized
type of file extension is *NCGM
. Once again, callbacks are set to
trigger methods when a specific control is activated. In particular, the OpenOK
method opens the file and visualizes the created objects of the CATGeoFactory
container.
[Top]
The OpenOK
callback:
GetSelection
CATGeoFactory
: CATLoadCGMContainer
CreateModelRepresentation
VisualizeModel
.The CreateModelRepresentation
method begins by creating the
representation bag to attach to the viewer.
Then, it defines the CAAGemRep
object to compute the
representations of the geometric objects. The CATGeoFactory
is
scanned by the Next
method in order to retrieve the objects to
visualize. The representation of an object is created by the CreateRep
method of CATGemRep
, and added (AddChild
) to the
representation bag.
The visualization is done by the VisualizeModel
method.
void CAAGemBrowserDocument::VisualizeModel() { if ( (NULL != _p3DViewer) && ( NULL != _pTheModelToDisplay) ) { // Attaches the bag to the viewer _p3DViewer->AddRep((CAT3DRep*)_pTheModelToDisplay); // Reframes on the current bounding sphere const CAT3DBoundingSphere boundingSphere = _pTheModelToDisplay->GetBoundingElement(); _p3DViewer->ReframeOn(boundingSphere); // Instruction to do at each representation modification _p3DViewer->Draw(); } } |
[Top]
CAAGemRep is the class dedicated to the creation of the representations.
... // GeometricObjects forward declarations ... // Tessellation forward declarations class CAT3DRep; #include "CATBoolean.h" class CAAGemRep { public: CAAGemRep(CATGeoFactory * ipiGeomFactory, float iSag); ~CAAGemRep(); // Creates the representation of a geometric object void CreateRep(CATGeometry * ipiToView, CAT3DRep *& iopRep); // Creates the representation of a body void CreateBodyRep(CATBody * ipiBody, CAT3DRep *& iopRep); // Creates the representation of a face // The arguments are the output of the tessellation cell or body operators void CreateSurfaceRep(CATBoolean iPlane, CATSide iSide, CATTessPointIter * iPoints, CATTessStripeIter * iStrips, CATTessFanIter * iFans, CATTessPolyIter * iPolygons, CATTessTrianIter * iTriangles, CAT3DRep *& iopRep); // Creates the representation of a plane void CreatePlaneRep(CATPlane *piPlane, CAT3DRep *& iopRep); // Creates the representation of an edge // The arguments are the output of the tessellation cell or body operator void CreateEdgeRep (CATEdge * ipiEdge, long & ioNumOfPoints, float * oaPoints, CAT3DRep *& iopRep); // Creates the representation of a curve // The arguments are the output of CATCurveTessellator void CreateCurveRep (long & ioNumOfPoints, float * oaPoints, CAT3DRep *& iopRep); // Creates the representation of a line void CreateLineRep(CATLine *piLine, CAT3DRep *& iopRep); // Creates the representation of a point void CreatePointRep (CATMathPoint & point,CAT3DRep *& iopRep); private: CAAGemRep (); CAAGemRep(const CAAGemRep &iObjectToCopy); CATGeoFactory * _piGeomFactory; // The geometry factory that is visualized float _sag; // The tessellation sag }; |
CreateRep
directs the creation of different kinds of
representations, according to the different types of objectsCreateBodyRep
tessellates a body and creates the
corresponding representationCreateSurfaceRep
creates the representation of a surface from
the results of a tessellation operatorCreateEdgeRep
creates the representation of a curve from the
results of a tessellation operatorCreateCurveRep
creates the representation of a curve (that is
not a line) from the results of a tessellation operatorCreateLineRep
directly creates the representation of a lineCreatePlaneRep
directly creates the representation of a planeCreatePointRep
directly creates the representation of a
point.The private data are the pointer to the CATGeoFactory
container
that is visualized, and the sag used to define the tessellation [2].
The structure of the CreateRep method is as follows:
void CAAGemRep::CreateRep(CATGeometry * ipiToView, CAT3DRep *& iopRep) { if (NULL!= ipiToView) { // ------ Body visualization if (0!=ipiToView->IsATypeOf(CATBodyType)) { CATBody * piBody=(CATBody * )ipiToView; CreateBodyRep(piBody,iopRep); } // ------ Curve visualization else if (0!=ipiToView->IsATypeOf(CATCurveType)) { if (0== ipiToView->GetUseCount()) // to only visualize alone curves { // ------ Line if (0!=ipiToView->IsATypeOf(CATLineType)) { CATLine * piLine=(CATLine*)ipiToView; CreateLineRep(piLine,iopRep); } else // ------ other curves { ... --> use a CATCurveTessellator } } } // ------ Surface else if (0!=ipiToView->IsATypeOf(CATSurfaceType)) { CATSurface * piSurface = (CATSurface * )ipiToView; if (0== ipiToView->GetUseCount()) // only visualizes surfaces that are not pointed to { // ----- Plane if(ipiToView->IsATypeOf(CATPlaneType)) { CATPlane * piPlane=(CATPlane*)ipiToView; CreatePlaneRep(piPlane,iopRep); } else // Other surfaces { ... --> use CATSurfaceTessellator } } } // Point else if (0!=ipiToView->IsATypeOf(CATPointType)) { if (0== ipiToView->GetUseCount()) { CATPoint * piPoint = (CATPoint*)ipiToView; CATMathPoint point; piPoint->GetMathPoint(point); CreatePointRep(point,iopRep); } } } } |
The creation of the representations is managed according to the type of the
geometric object, retrieved with the CATICGMContainer::IsATypeOf
method. In case of surfaces, curves, or points, the choice of the use case is to
visualize only objects that are not pointed to by any other object. Hence the CATICGMObject::GetUseCount
returns if an object is pointed to or not.
We now examine in detail all the type of geometry: point, line, curve, plane, surface and body.
[Top]
The coordinates of the point are directly passed to the constructor of the representation.
void CAAGemRep::CreatePointRep (CATMathPoint & point,CAT3DRep *& iopRep) { // Gets the coordinates of the point double ioFirstCoord,ioSecondCoord,ioThirdCoord; point.GetCoord(ioFirstCoord,ioSecondCoord,ioThirdCoord); float aCoord[3]; aCoord[0]= (float)ioFirstCoord; aCoord[1]= (float)ioSecondCoord; aCoord[2]= (float)ioThirdCoord; // Creates the rep CAT3DPointRep *rep = new CAT3DPointRep(aCoord,FULLCIRCLE); // Returns the rep iopRep = rep; } |
[Top]
The lines have a specific treatment: they do not need to be discretized. Two
cases are considered: finite (or trimmed) and infinite lines. To know if a line
is infinite, the model size of the CATGeoFactory
container is
retrieved (GetModelSize
). The model size defines the maximum
bounding box of the model [3] and one tests whether
this maximum bounding box includes the extremities of the curve.
In case of a finite line, a CAT3DLineRep instance is modified to be trimmed by the start and end limits of the line, thus defining the representation of the line.
In case of an infinite line, an arrow is visualized: a CAT3DFixedArrowGP is created at the origin of the line, along its direction. The total arrow length is 40 millimeters, and the head height is 2 millimeters.
[Top]
We are here in the CreateRep
method of CAAGemRep. We describe
now the code under the other curves comment.
In case of a curve, the program first checks that the curve is not
degenerated. The bounding box of the current limits is first retrieved with the CATCurve::GetBox
method, the length of its diagonal is then computed. If this length is
CATGeoFactory::GetResolution
),
the representation of a point is created. The point is evaluated with CATCurve::Eval
.CATCurveTessellator
operator computes the data used to create the representation of a curve. The
representation itself is created in the CreateCurveRep
method
that is later detailed.To use the CATCurveTessellator
operator:
The tessellation results are used by the method CreateCurveRep
of CAAGemRep
to create the representation as follows.
void CAAGemRep::CreateCurveRep (long & ioNumOfPoints, float * oaPoints, CAT3DRep *& iopRep) { CAT3DCurveRep* pCurveRep = NULL; // Creates the rep CAT3DPolylineGP* polylineGP = new CAT3DPolylineGP(oaPoints, ioNumOfPoints, 1); pCurveRep = new CAT3DCurveRep(); pCurveRep->AddWireframeLOD(0,polylineGP, _sag); // Defines the bounding box float xmin=1.e+10,ymin=1.e+10,zmin=1.e+10,xmax=-1.e+10,ymax=-1.e+10,zmax=-1.e+10; for (int j=0, curj=0; j<ioNumOfPoints; j++, curj+=3) { if(oaPoints[curj+0] < xmin) xmin=oaPoints[curj+0]; if(oaPoints[curj+1] < ymin) ymin=oaPoints[curj+1]; if(oaPoints[curj+2] < zmin) zmin=oaPoints[curj+2]; if(oaPoints[curj+0] > xmax) xmax=oaPoints[curj+0]; if(oaPoints[curj+1] > ymax) ymax=oaPoints[curj+1]; if(oaPoints[curj+2] > zmax) zmax=oaPoints[curj+2]; } CATMathPointf center((float) (xmin+xmax)/2.f, (float) (ymin+ymax)/2.f, (float) (zmin+zmax)/2.f); double radius= sqrt((xmax-xmin)*(xmax-xmin)+ (ymax-ymin)*(ymax-ymin)+ (zmax-zmin)*(zmax-zmin))/2.f; pCurveRep->SetBoundingElement(CAT3DBoundingSphere(center, (float)radius)); // Returns the rep iopRep = pCurveRep; } |
The representation of a curve is a collection of graphic polylines CAT3DPolylineGP
,
each one representing a level of detail (LOD). Here, one LOD is added to the
curve representation (AddWireframeLOD
), with a level a detail
having _sag
as the corresponding sag value. Finally, the bounding
box is computed from the tessellation results and set to the curve
representation.
[Top]
The origin and the axes of the plane are directly passed to the constructor of the representation. As the plane is infinite, a given size is fixed. The associated bounding sphere is also set to the representation.
void CAAGemRep::CreatePlaneRep(CATPlane *piPlane, CAT3DRep *& iopRep) { CATMathPlane plane; // Gets the mathematical definition piPlane->GetAxis(plane); CATMathPoint center = plane.GetOrigin(); CATMathDirection vAxis = plane.GetSecondDirection(); CATMathDirection uAxis = plane.GetFirstDirection(); CATMathPointf origin((float) center.GetX(), (float) center.GetY(), (float) center.GetZ()); CATMathDirectionf u((float) uAxis.GetX(), (float) uAxis.GetY(), (float) uAxis.GetZ()); CATMathDirectionf v((float) vAxis.GetX(), (float) vAxis.GetY(), (float) vAxis.GetZ()); float size = 20.f; float radius = 15.f; // Creates the rep CAT3DPlanRep *pRep = new CAT3DPlanRep(origin,u,v,size); CAT3DBoundingSphere *pBe = new CAT3DBoundingSphere(origin,0.f,radius); pRep->SetBoundingElement(*pBe); delete pBe; pBe=NULL; // Returns the rep iopRep = pRep; } |
[Top]
We are here in the CreateRep
method of CAAGemRep. We describe
now the code under the other surfaces comment.
The surface is first tessellated with CATSurfaceTessellator
.
// piSurface is the pointer to the surface to visualize CATSurLimits limits; piSurface->GetLimits(limits); CATSurfaceTessellator * pSurfTess = new CATSurfaceTessellator(_sag); if (NULL!=pSurfTess) { pSurfTess -> AddSurface(piSurface, limits); pSurfTess -> Run(); CATBoolean isPlanar; CATTessPointIter * pPoints = NULL; CATTessStripeIter * pStrips = NULL; CATTessFanIter * pFans = NULL; CATTessPolyIter * pPolygons = NULL; CATTessTrianIter * pTriangles = NULL; pSurfTess -> GetSurface(piSurface,isPlanar, &pPoints,&pStrips,&pFans,&pPolygons,&pTriangles); CATSide side=CATSideUnknown; CreateSurfaceRep(isPlanar,side, pPoints, pStrips,pFans, pPolygons, pTriangles,iopRep); delete pSurfTess; pSurfTess=NULL; } |
To use the CATSurfaceTessellator
operator:
The tessellation results are used by the method CreateSurfaceRep
of CAAGemRep
to create the representation as follows:
CATTessTrianIter
CATTessStripeIter
We now detail the use of the point iterator to retrieve the normals in case of a non-planar surface.
CATTessPointIterator::GetNbPoints
outputs the number of points
computed by the tessellation. Now, the iterator is used as follows:
The IsExhauted
method declares whether the end is reached.
If there is no points anymore, it returns 0
.
The GetPointXyz
returns the current point. The coordinates
of this point are then put in the array that will be passed to the graphic
primitive creation.
The GetPointNor
returns the normal to the surface at the
current point. The coordinates of this normal are also put in an array to be
later used.
The GoToNext
method skips to the next point of the iterator.
Now, the isolated triangles are read with the CATTessTrianIter
iterator created by the tessellator. Its use is similar to the use of a CATTessPointIter
.
long numberOfTriangles = ipTriangles->GetNbTrian(); if ( NULL!= numberOfTriangles ) { triangleIndice = new int [3 * numberOfTriangles] ; i = 0 ; while ( ipTriangles->IsExhausted()==0 ) { ipTriangles->GetTrianNuPts(NuPts); if (ori <0) { // triangles must be inverted triangleIndice[i] = NuPts[2]*3 ; triangleIndice[i+1] = NuPts[1]*3 ; triangleIndice[i+2] = NuPts[0]*3 ; } else { triangleIndice[i] = NuPts[0]*3 ; triangleIndice[i+1] = NuPts[1]*3 ; triangleIndice[i+2] = NuPts[2]*3 ; } i += 3 ; ipTriangles->GoToNext(); } } |
As this method is also used to create the representation of a face, the
relative orientation of the face and the surface is taken into account here by
the ori
value, initialized with the corresponding output of the
tessellator. In the same way, the strips of triangles are retrieved.
long TotalPointNb=0; long numberOfStrips = ipStrips->GetNbStri(TotalPointNb) ; if ( numberOfStrips ) { nbVertexPerTriangleStrip = new int [numberOfStrips] ; triangleStripIndice = new int [TotalPointNb] ; i = 0 ; j = 0 ; while ( ipStrips->IsExhausted()==0 ) { nbVertexPerTriangleStrip[i] = ipStrips->GetStriNbPts(); ipStrips ->GetStriNuPts( &(triangleStripIndice[j]) ) ; for ( k=0 ; k < nbVertexPerTriangleStrip[i] ; k++ ) { triangleStripIndice[j+k] *= 3 ; } if (ori <0) { // Inverts to strip: Swap 2 by 2 int m=0 ; for ( int l=0; l<(nbVertexPerTriangleStrip[i])/2 ;l++) { int i1 = triangleStripIndice[j+m]; triangleStripIndice[j+m] = triangleStripIndice[j+m+1]; triangleStripIndice[j+m+1] = i1 ; m +=2 ; } } j += nbVertexPerTriangleStrip[i] ; i += 1; ipStrips->GoToNext(); } } |
Now, the representation can be created.
CAT3DFaceGP * faceGP = NULL; if ( iPlane ) faceGP = new CAT3DPlanarFaceGP(vertices,verticesArraySize, normals, triangleIndice,numberOfTriangles, triangleStripIndice, numberOfStrips, nbVertexPerTriangleStrip, triangleFanIndice, numberOfFans, nbVertexPerTriangleFan); else faceGP = new CAT3DFaceGP(vertices,verticesArraySize, normals,normalsArraySize, triangleIndice,numberOfTriangles, triangleStripIndice, numberOfStrips, nbVertexPerTriangleStrip, triangleFanIndice,numberOfFans,nbVertexPerTriangleFan); if (NULL!=vertices) delete [] vertices; if (NULL!=normals) delete [] normals; if (NULL!=triangleIndice) delete [] triangleIndice ; if (NULL!=triangleStripIndice) delete [] triangleStripIndice ; if (NULL!=nbVertexPerTriangleStrip) delete [] nbVertexPerTriangleStrip ; if (NULL!=triangleFanIndice ) delete [] triangleFanIndice ; if (NULL!=nbVertexPerTriangleFan ) delete [] nbVertexPerTriangleFan ; CAT3DCustomRep * pSurfacicRep = new CAT3DCustomRep(); CATGraphicAttributeSet ag ; ag.SetType(2); pSurfacicRep->AddGP(faceGP,ag); // Gets the bounding box CATMathPointf Center(float((xmin+xmax)/2.), float((ymin+ymax)/2.), float((zmin+zmax)/2.)); double BoundingSphereRadius= sqrt((xmax-xmin)*(xmax-xmin)+ (ymax-ymin)*(ymax-ymin)+ (zmax-zmin)*(zmax-zmin))/2.; CAT3DBoundingSphere BoundingSphere( Center, float(BoundingSphereRadius)); pSurfacicRep->SetBoundingElement(BoundingSphere); |
The graphic primitive is first created: it is a CAT3DPlanarFaceGP for a
planar surface or a CAT3DFaceGP for a non-planar surface. This primitive is
added to a new CAT3DCustomRep. The computed bounding box is set with the SetBoundingElement
method, thus ending the construction of the surface representation.
[Top]
All the previous methods are used to create the representation of a body. CATCellTessellator
is used to create data needed by the CreateSurfaceRep
and CreateCurveRep
methods. The faces, edges of wire domains, and vertices in volume are
tessellated. In particular, neither the edges of the face, nor the vertices of
the edges are represented.
void CAAGemRep::CreateBodyRep(CATBody * ipiBody, CAT3DRep *& iopRep) { iopRep=NULL; CAT3DBagRep* pBagRep = NULL; pBagRep = new CAT3DBagRep(); CATCellTessellator * pTessellator = new CATCellTessellator(_sag); //-------------------------------------------------- // Tessellates the faces //-------------------------------------------------- if (NULL!=pTessellator) { // Retrieves all the faces CATLISTP(CATCell) cells; ipiBody->GetAllCells( cells,2); // 2 for retrieving the faces int numberOfCells = cells.Size(); for (int ifa=1 ; ifa<=numberOfCells ; ifa++) { pTessellator->AddFace((CATFace *)(cells[ifa])); } pTessellator -> Run(); // for each face, retrieve the tessellation results for (ifa=1 ; ifa<=numberOfCells ; ifa++) { CATFace * piFace = (CATFace*) cells[ifa]; // a special visualization for infinite face if (TRUE== piFace->GetInfinite()) { CATOrientation ori; CATGeometry* piGeom= piFace->GetGeometry(&ori); if (NULL!= piGeom && piGeom->IsATypeOf(CATPlaneType) ) { CATPlane * piPlane = (CATPlane *)piGeom; CAT3DRep* pRep=NULL; CreatePlaneRep(piPlane,pRep); if (NULL!=pRep) { if (NULL== pBagRep) pBagRep = new CAT3DBagRep(); pBagRep->AddChild(*pRep); } } } else { CATBoolean isPlanar; CATTessPointIter * pPoints = NULL; CATTessStripeIter * pStrips = NULL; CATTessFanIter * pFans = NULL; CATTessPolyIter * pPolygons = NULL; CATTessTrianIter * pTriangles = NULL; short side; pTessellator -> GetFace(piFace,isPlanar,&pPoints,&pStrips,&pFans,&pPolygons,&pTriangles,&side); CAT3DRep * pRep=NULL; CreateSurfaceRep(isPlanar, side, pPoints, pStrips,pFans, pPolygons, pTriangles,pRep); if (NULL!=pRep) { if (NULL== pBagRep) pBagRep = new CAT3DBagRep(); pBagRep->AddChild(*pRep); } } } delete pTessellator; pTessellator = NULL; } //-------------------------------------------------- // Now tessellate the wire domains (not the edges of faces) //-------------------------------------------------- // ...... // Returns the rep iopRep=pBagRep; } |
All the faces of the body are retrieved in one shot with the GetAllCells
method of the CATTopology interface from which the body derives. The 2 value is
the dimension for the faces. All these faces are Add
ed to CATCellTessellator
,
that is then Run
. Now, for each face, the results are retrieved:
If the face is infinite, the representation of a plane is created, if the associated geometry is a plane
Otherwise, the GetFace
method of the CATCellTesselator
returns all the data that is needed to create the representation of a
surface.
The tessellator is deleted after use.
The way to create the representation of the vertices in volume and the edges of the wires is very similar.
We first loop on all the domains of the body. GetDomain
returns
the pointer to the i-th domain.
If the domain is a wire
all the edges of this wire are retrieved: GetAllCells
is
called with 1
They are Add
ed to the created CATCellTessellator
The tessellator is Run
For each edge, the tessellation results are retrieved: GetEdge
These results are passed to CreateEdgeRep
that created
the representation
The tessellator is deleted after use.
If the domain is a vertex in volume
The unique cell of this domain is retrieved
The representation of the corresponding point is created.
[Top]
The representation is created in a very similar way as in the curve case. They only differ by the process of the degenerated elements
void CAAGemRep::CreateEdgeRep (CATEdge * ipiEdge, long & ioNumOfPoints, float * oaPoints, CAT3DRep *& iopRep) { CAT3DRep *pRep = NULL; CATMathBox boundingBox; CATMathPoint low,high; ipiEdge->GetBoundingBox(boundingBox); boundingBox.GetLow(low); boundingBox.GetHigh(high); CATMathVector diagonal=high-low; double diagonalLength= diagonal.Norm(); if ( diagonalLength > _piGeomFactory->GetResolution() ) { CreateCurveRep (ioNumOfPoints,oaPoints,pRep); } // The edge is a point else { //Gets the coordinates of a point CATPointOnEdgeCurve *piStartPoec=NULL; ipiEdge->GetVerticesPointsOnEdgeCurve(&piStartPoec,NULL ); CATMathPoint pt; piStartPoec->GetMathPoint(pt); CreatePointRep(pt,pRep); } // Returns the rep iopRep = pRep; } |
If the edge has a length greater than the factory resolution, the representation of a curve is created.
Otherwise, one point of the edge is recovered, and a representation of this
point is created. Notice that to get the points extremities of an edge, the CATEdge::GetVerticesPointsOnEdgeCurve
method can be used.
[Top]
This use case offers the programmer a way to visualize the geometry and topology created by the CATGeoFactory. Meanwhile, it illustrates how to tessellate geometric objects.
[Top]
[1] | Building and Launching a CAA V5 Use Case |
[2] | Tessellation |
[3] | The Management of Tolerances |
[Top] |
Version: 1.1 [Nov 2000] | Use of CAT3DCustomRep for the graphic representation of faces and surfaces |
Version: 1 [Jun 2000] | Document created |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.