InterOp:Graphical/Importing Graphical Data

From DocR23

Jump to: navigation, search
Showproduct.png



This tutorial provides information necessary for a successful graphical data import using 3D InterOp Graphical.

Contents

Introduction

3D InterOp Graphical allows you to import graphical data for a wide variety of CAD data formats. For some formats, the graphical data is natively extracted from the source file, while other formats provide the graphical data as generated from the imported B-rep model. In either case, the graphical data is accessed via a simple scene graph. With this data, you can populate your own scene graph structures with high-quality graphical data suitable for both rendering and data analysis.

Before you begin working with graphical data for a source file, you must first import the file into a CGMInputProductStructure (refer to Importing a Product Structure). Once you have the product structure, you must then navigate it to identify the specific CGMInputPSReference object associated with the part file you would like to import for rendering or data analysis. From this reference object, obtain its CGMInteropPartDocument. Once you have your CGMInteropPartDocument, you are ready to start importing your graphical data.

Licensing

Before using any 3D InterOp Graphical libraries, you must initialize the component with your 3D InterOp Graphical license key. In this sample, the key string is stored in src/GetLicenseKey.cpp. Edit this file to store your license key.

The call to CGMInteropSystem::Initialize() in main should not be changed; just edit GetLicenseKey as follows:

const char* GetLicenseKey()
{
      static const char* unlock_str =
        "THISISYOURLICENSEKEY0THISISYOURLICENSEKEY0THISISYOURLICENSEKEY"
        "THISISYOURLICENSEKEY0THISISYOURLICENSEKEY0THISISYOURLICENSEKEY"
        "THISISYOURLICENSEKEY0THISISYOURLICENSEKEY";
 
      return unlock_str;
}

Note: For detailed instructions on generating a license file, refer to Licensing and Registration.


Headers

The following headers apply to the sum of the code samples in this tutorial.

#include "CGMInterop.h"
#include "CGMInteropPartVisualization.h"
#include "CATUnicodeString.h"
#include "CATDataType.h"
#include <float.h>

Graphical Data Import

Because the data provided by 3D InterOp Graphical is tuned for data transfer, it is not suitable for rendering or data analysis in its native form. To make use of this data, you will need to extract it from the scene graph and install it in your own data structures that are suited to the particular needs of your own application. This tutorial will show you how to access the various types of data available in the scene graph, but will not attempt to show you how to interpret or utilize the data you find there. Refer to Concepts for a listing of articles that will help you understand the specifics of the types of data available in 3D InterOp Graphical.

All of the data available through the 3D InterOp Graphical set of interfaces is owned and managed by the interfaces themselves. As long as the CGMImputProductStructure and the CGMPartVisualizationImportResult objects associated with your imported data are alive and in scope, the graphical data will be available to your application. Do not attempt to delete any of the information you access from the interfaces and do not attempt to use the data after the managing object has gone out of scope or is otherwise destroyed. If a given interface does not contain a specific type of data, it may return a NULL pointer value. You are cautioned to check all pointers returned by 3D InterOp Graphical before attempting to de-reference them.

At the highest level, this tutorial will show you how to:

  1. Import the graphical information for a part file
  2. Navigate the generated scene graph
  3. Access the graphical data for:
    • Solids
    • Sheets
    • Wires
    • PMI

Note: The code snippets included in this tutorial do not include proper error handling practices. It is important that you enclose your code with try/catch blocks as 3D InterOp Graphical throws exceptions for fatal errors.


Using Iterators

The 3D InterOp Graphical interfaces make use of iterators to access the contents of all data collections. Iterators are simple to use; simply call Next() to move the iterator's cursor to the next item and call Current() to get the current item. All iterators are self-initializing, so there is no need to "prime the pump" before an enumeration. (However, you must call Next() at least once prior to calling Current() to move the iterator cursor to a valid node.) All iterators are also single-use, therefore, to start a new enumeration on any given collection, you will need to obtain a new instance of the iterator.

Using Iterators in 3D InterOp Graphical C++ Example
CGMPartVisualizationNodeIter sceneGraphIter = vizData.GetSceneIterator();
 
// Iterators are self-initializing, so no need to initialize them explicitly.
// Use Next() to move the iterator to the next item, if any. Stop the iteration
// when Next() returns 'false'.
while ( sceneGraphIter.Next())
{
        // Use Current() to get the current item.
	CGMPartVisualizationNode currentNode = sceneGraphIter.Current();
}

Obtaining the Scene Graph

You must import the graphical data for a part before you can access it. First, you must obtain a CGMInteropPartDocument for your part, which is done by accessing the desired reference in the Product Structure, as demonstrated in the tutorial Importing a Product Structure. Once you obtain a CGMInteropPartDocument for the part, you can import its graphical data by creating a CGMPartVisualizationImporter object and passing the CGMInteropPartDocument to its CGMPartVisualizationImporter::Import() method. This will load the part document and build a scene graph from its graphical data. For some formats, this means extracting the native data from the file itself; for other formats, it means loading the B-rep into memory and tessellating the geometry. The import will return a CGMPartVisualizationImportResult object. This result object contains a collection of information about the import operation. To obtain the iterator for the scene graph, you first get the CGMPartVisualizationData object from the result. This data object provides access to the scene graph iterator as well as additional information about the graphical data.

Obtaining the Scene Graph C++ Example
// Use the graphical importer to import the part document obtained from the product structure
CGMPartVisualizationImporter partVizImporter;
CGMPartVisualizationImportResult vizImportResult = partVizImporter.Import( iCGMInteropPartDocument );
 
// Get the visualization data object from the result of the graphical import
CGMPartVisualizationData vizData = vizImportResult.GetVisualizationData();
 
// Get the scene graph node iterator which provides a depth-first enumeration of the scene graph
CGMPartVisualizationNodeIter vizNodeIter = iVizData.GetSceneIterator();

Traversing the Scene Graph

Given a CGMPartVisualizationNodeIter, you can traverse the scene graph and begin extracting the various types of graphical data contained therein. The scene graph iterator performs a depth-first traversal of the scene graph. Each CGMPartVisualizationNode is either a group node or a leaf node. Each group node organizes its children in to categories of information such as Geometry or PMI. Each leaf node provides access to body-level graphical data. Since each node in the scene graph has a string identifier that indicates what kind of data is in that node or its children, you can use this information during scene graph traversal to make choices about what parts of the scene graph you want to process.

Traversing the Scene Graph C++ Example
CGMPartVisualizationNodeIter sceneGraphIter = vizData.GetSceneIterator();
 
// The iterator is self-initializing, so no need to initialize it explicitly.
// Enumerate the nodes in a depth-first traversal. Use Next() to move the
// iterator to the next node, if any. Stop the iteration when Next() returns 'false'.
while ( sceneGraphIter.Next())
{
        // Use Current() to get the current scene graph node.
	CGMPartVisualizationNode currentNode = sceneGraphIter.Current();
 
        // Get the node's type so you can switch your code's behavior based
        // on the type of information in the current node.
	CATUnicodeString nodeType = currentNode.GetType();
        if ( true == currentNode.IsLeaf())
        {
                // In this case, we are ignoring all the group nodes and
                // finding only the leaf nodes that contain geometry or PMI
                // graphical data
	        if ( 1 < nodeType.Compare( CGMPartVisualizationNodeTypes::MESH ))
	        {
		        CGMPartVisualizationMesh mesh = currentNode.GetMesh();
	        }
	        else if ( 1 < nodeType.Compare( CGMPartVisualizationNodeTypes::WIRE ))
	        {
		        CGMPartVisualizationWire wire = currentNode.GetWire();
	        }
	        else if ( 1 < nodeType.Compare( CGMPartVisualizationNodeTypes::POINTSET ))
	        {
		        // Points are not currently supported
	        }
	        else
	        {
		        CGMPartVisualizationPMI pmi = currentNode.GetPMI();
	        }
        }
}

Body-level Graphical Data

Body-level data in the scene graph corresponds to bodies in the part model. So, if the part has a solid or sheet body, its graphical data would be represented in a CGMPartVisualizationMesh object. Similarly, the graphical data for a model's free wire would be in a CGMPartVisualizationWire object and each PMI in the model would have a corresponding CGMPartVisualizationPMI object. Once you have identified a leaf node as containing one of these types of body-level data objects, you need to query the CGMPartVisualizationNode for its body-level data object.

Meshes

A CGMPartVisualizationMesh is comprised of a collection of CGMPartVisualizationFace and CGMPartVisualizationEdge objects that correspond to the model's topological faces and edges. The CGMPartVisualizationFace objects are accessed through the mesh's CGMPartVisualizationFaceIter and the CGMPartVisualizationEdge objects are accessed through its CGMPartVisualizationEdgeIter.

Obtaining Face and Edge Iterators from a Mesh Scene Graph Node C++ Example
// Given a CGMPartVisualizationNode of the type CGMPartVisualizationNodeTypes::MESH,
// you can obtain the iterators for its graphical Face and Edge data.
CGMPartVisualizationMesh mesh = currentNode.GetMesh();
CGMPartVisualizationFaceIter meshFaces = iMeshNode.GetFaceIterator();
CGMPartVisualizationEdgeIter meshEdges = iMeshNode.GetEdgeIterator();

Wires

A CGMPartVisualizationWire is made up of a collection of CGMPartVisualizationEdge objects which are managed by a CGMPartVisualizationEdgeIter.

Obtaining the Edge Iterator from a Wire Scene Graph Node C++ Example
// Given a CGMPartVisualizationNode of the type CGMPartVisualizationNodeTypes::WIRE,
// you can obtain the iterator for its graphical Edge data.
CGMPartVisualizationWire wire = currentNode.GetWire();
CGMPartVisualizationEdgeIter wireEdges = wire.GetEdgeIterator();

PMIs

A CGMPartVisualizationPMI is a collection of CGMPartVisualizationEdge and CGMPartVisualizationText objects. The CGMPartVisualizationEdge objects are managed by a CGMPartVisualizationEdgeIter and the CGMPartVisualizationText objects are managed by a CGMPartVisualizationTextIter. The edges in the PMI represent the non-text elements of a PMI such as a leader lined, arrowheads and GD&T cells. The text elements include both plain text and mechanical symbols.

Obtaining Edge and Text Iterators from a PMI Scene Graph Node C++ Example
// Given a CGMPartVisualizationNode of the type CGMPartVisualizationNodeTypes::DATUM or
// CGMPartVisualizationNodeTypes::ANNOTATOION, you can obtain the iterators for its
// graphical Edge and Text data.
CGMPartVisualizationPMI pmi = currentNode.GetPMI();
CGMPartVisualizationEdgeIter pmiEdges = pmi.GetEdgeIterator();
CGMPartVisualizationTextIter pmiTexts = pmi.GetTextIterator();

Topological-level Graphical Data

Topological-level data objects in 3D InterOp Graphical include CGMPartVisualizationFace, CGMPartVisualizationEdge, and CGMPartVisualizationText objects. Body-level objects are built from collections of these topological-level objects.

Faces

CGMPartVisualizationFace objects correspond to faces on a solid or sheet body within the part model. Each CGMPartVisualizationFace is defined by a collection of CGMPartVisualizationPolygon objects, each of which contains a list of indices into a pair of vertex and normal lists supplied by the containing CGMPartVisualizationFace. Each CGMPartVisualizationPolygon describes one of three types of graphic primitives: Triangle, TriStrip, or TriFan.

Since all of the polygon primitives index into the face's vertex and normal lists, you will need to get those lists from the face before interpreting the face's polygon indices as graphical primitives.

Obtaining Face Vertices and Normals C++ Example
// Given a CGMPartVisualizationFace obtained from a CGMPartVisualizationFaceIter,
// you can access the vertex and normal lists. These lists will be referenced
// by the face's CGMPartVisualizationPolygon descriptions.
CGMPartVisualizationFace currentFace = faceIter.Current();
 
const float* pFaceVertices = NULL;
int numVertices = currentFace.GetVertices( pFaceVertices );
 
const float* pFaceNormals = NULL;
int numNormals = currentFace.GetNormals( pFaceNormals );

CGMPartVisualizationPolygon objects can be accessed from a CGMPartVisualizationPolygonIter which can be retrieved from the CGMPartVisualizationFace.

Obtaining the Face Polygon Iterator C++ Example
// Given a CGMPartVisualizationFace obtained from a CGMPartVisualizationFaceIter,
// you can access the polygon definitions that index into the vertex and normal
// lists. 
CGMPartVisualizationFace currentFace = faceIter.Current();
CGMPartVisualizationPolygonIter facePolygons = currentFace.GetPolygonIterator();
Polygons

CGMPartVisualizationPolygon objects define one of three types of graphic primitives: Triangle, TriStrip, or TriFan. It is vital to know what type of primitive is represented by any given CGMPartVisualizationPolygon object before attempting to interpret its indices relative to the containing CGMPartVisualizationFace's vertex and normal lists. Refer to Graphical Face Data for specific information about how each primitive type is defined.

Obtaining a Face Polygon's Definition and Determining its Type C++ Example
// Given a CGMPartVisualizationPolygon obtained from a CGMPartVisualizationPolygonIter,
// you can retrieve the polygon's definition and its type.
CGMPartVisualizationPolygon currentPolygon = facePolygons.Current();
 
// Get the definition of the polygon in terms of indices into the vertex and normal
// lists obtained from the corresponding face. How the indices are interpreted
// depends on the polygon's type: Triangle, TriStrip, or TriFan.
const int* pPolygonIndices = NULL;
CGMPartVisualizationPolygonType polygonType( CGMPartVisualization_PolygonType_Unknown );
int numPolygonIndices = currentPolygon.GetPolygonIndices( pPolygonIndices, polygonType );
if ( NULL != pPolygonIndices )
{
	switch ( polygonType )
	{
	case CGMPartVisualization_PolygonType_Triangle:
		break;
	case CGMPartVisualization_PolygonType_TriStrip:
		break;
	case CGMPartVisualization_PolygonType_TriFan:
		break;
	case CGMPartVisualization_PolygonType_Unknown:
	default:
		break;
	}
}

Edges

CGMPartVisualizationEdge objects correspond to topological edges on a solid or sheet body or free wire within the part model. They also are used to define non-text elements within a PMI body. CGMPartVisualizationEdge objects are defined as indices into a point list and describe one of three types of graphical primitive: LineStrip, LineLoop, or LineLoopFilled. It is important to know what type of edge you are processing in order to correctly interpret the index data.

As all edges are defined as indices into a point list, you will need to first get the list from the CGMPartVisualizationEdge.

Obtaining Edge Points and Line Definition C++ Example
// Given a CGMPartVisualizationEdge obtained from a CGMPartVisualizationEdgeIter,
// you can access the points list. This list is referenced by the line indices
// to define the edge.
CGMPartVisualizationEdge currentEdge = edgeIter.Current();
 
const float* pEdgePoints = NULL;
int numPoints = currentEdge.GetPoints( pEdgePoints );

Each CGMPartVisualizationEdge provides a list of indices that refer to the point list and includes a type identifier that allows you to know how to interpret the indices. Refer to Graphical Edge Data for details about how to interpret the indices for each edge primitive type.

Obtaining an Edge's Definition and Determining its Type C++ Example
// Given a CGMPartVisualizationEdge obtained from a CGMPartVisualizationEdgeIter,
// you can retrieve the edge's definition and its type.
CGMPartVisualizationEdge currentEdge = edges.Current();
 
// Get the definition of the edge in terms of indices into the point list obtained
// from the corresponding face, wire, or PMI. How the indices are interpreted
// depends on the edge's type: LineStrip, LineLoop, or LineLoopFilled.
const int* pLineIndices = NULL;
CGMPartVisualizationLineType lineType( CGMPartVisualization_LineType_Unknown );
int numLineIndices = currentEdge.GetLineIndices( pLineIndices, lineType );
if ( NULL != pLineIndices )
{
	switch ( lineType )
	{
	case CGMPartVisualization_LineType_LineStrip:
		break;
	case CGMPartVisualization_LineType_LineLoop:
		break;
	case CGMPartVisualization_LineType_LineLoopFilled:
		break;
	default:
		break;
	}
}

Texts

Each text element in a part model's PMI is represented in 3D InterOp Graphical as a CGMPartVisualizationText object which describes the display string along with the necessary information to place and orient the text within the scene. The string value for the text is in Unicode, including the mechanical symbols. For any given string, it is placed within the scene starting at the given anchor point, proceeding along the primary direction and in a display plane with the given normal. Refer to Graphical Text Data for more information about text placement and orientation.

Obtaining a Text's String, Anchor Point, Primary Direction, and Display Plane Normal C++ Example
// Given a CGMPartVisualizationText obtained from a CGMPartVisualizationTextIter,
// you can retrieve the text's string value, anchor point, primary direction and
// display plane normal.
CGMPartVisualizationText currentText = texts.Current();
 
float anchorPt[ 3 ] = { CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED };
float direction[ 3 ] = { CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED };
float normal[ 3 ] = { CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED, CGM_VIZ_FLT_UNDEFINED };
CATUnicodeString stringValue = currentText.GetTextString( anchorPt, direction, normal );

Attributes

Attributes in 3D InterOp Graphical modify certain display characteristics of the graphical data. Each CGMPartVisualizationNode can have a CGMPartVisualizationAttributes object attached to it that describes the modifications that apply to that node and all of its children. If a specific attribute is set lower in the scene graph than a previously defined attribute, then the lowest definition overrides all previous ones.

Not all attributes are set for any given CGMPartVisualizationAttibutes object. For example, the RGB color channel may be set for the whole scene graph, but the alpha channel is only set for a specific face in the scene. Some attributes, such as color, can be set anywhere in the scene from its root node to one of its topological-level data objects, while other attributes can only be set on scene graph nodes.

Obtaining Attributes from a Scene Graph Node C++ Example
// Given a CGMPartVisualizationNode obtained from a CGMPartVisualizationNodeIter,
// you can retrieve the node's attributes.
CGMPartVisualizationNode currentNode = nodes.Current();
CGMPartVisualizationAttributes currentAttributes = currentNode.GetAttributes();

Fonts

A CGMPartVisualizationFont describes certain display characteristics used in rendering CGMPartVisualizationText elements for graphical PMI data. CGMPartVisualizationFont objects can be retrieved from a CGMPartVisualizationAttributes object. If the font was not set for a specific instance of CGMPartVisualizationAttributes, then the CGMPartVisualizationAttributes::GetFont() method will return false indicating that a font is not available for that attribute set. Refer to Graphical Text Data for details about how the various font properties influence the display of text within a scene.

Obtaining the Font from a Scene Graph Node's Attributes C++ Example
// Given a CGMPartVisualizationAttributes obtained from a CGMPartVisualizationNode,
// you can retrieve the attribute's CGMPartVisualizationFont.
CGMPartVisualizationAttributes currentAttributes = currentNode.GetAttributes();
 
CGMPartVisualizationFont currentFont;
bool gotFont = currentAttributes.GetFont( currentFont );

Color - RGB

The RGB color can appear anywhere in the scene graph hierarchy or on any body-level or topological-level data object. Any RGB color that appears lower in the scene graph overrides the RGB color that appears above it. Each channel in the RGB color is defined as a number between 0 and 255. If the color is not set at a given level, then the query function returns false to indicate that the color is not available.

Obtaining the RGB Color Values C++ Example
// Given a CGMPartVisualizationAttributes obtained from a CGMPartVisualizationNode,
// you can retrieve the attribute's RGB color values.
CGMPartVisualizationAttributes currentAttributes = currentNode.GetAttributes();
 
// The value of each color channel ranges from 0-255
CATLONG32 red = CGM_VIZ_COLOR_UNDEFINED;
CATLONG32 green = CGM_VIZ_COLOR_UNDEFINED;
CATLONG32 blue = CGM_VIZ_COLOR_UNDEFINED;
bool gotRGBColor = currentAttributes.GetRGBColor( red, green, blue );

Color - Alpha

The Alpha color can appear anywhere in the scene graph hierarchy or on any body-level or topological-level data object. Any Alpha color that appears lower in the scene graph overrides the Alpha color that appears above it. The Alpha channel is given as a number between 0 and 255. If a query for the Alpha color returns false, then the Alpha channel is not available at that level.

Obtaining the Alpha Color Values C++ Example
// Given a CGMPartVisualizationAttributes obtained from a CGMPartVisualizationNode,
// you can retrieve the attribute's alpha color values.
CGMPartVisualizationAttributes currentAttributes = currentNode.GetAttributes();
 
// The value of the alpha color channel ranges from 0-255
CATLONG32 alpha = CGM_VIZ_COLOR_UNDEFINED;
bool gotAlphaColor = currentAttributes.GetAlphaColor( alpha );

Using the Sample Code

3D InterOp Graphical includes source code for a sample application. The sample performs a full scene graph traversal and formats the graphical data for output to the console. The sample is provided as a debugging utility and is not intended to demonstrate how you should prepare the scene graph data for rendering in your own application. The sample application executable is also included, so you can quickly start learning about how to import graphical data using actual data from a source model. Refer to CGMPartVisualization Sample Application for details on using the sample application.

Personal tools