Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d6dfeac244 | ||
|
51bb1b8d6d |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 86 KiB |
BIN
dox/user_guides/xde/images/assm_wheel_axle.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
dox/user_guides/xde/images/assm_wheel_axle_root.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
dox/user_guides/xde/images/assm_wheel_axle_sa.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
dox/user_guides/xde/images/xde_as1.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
dox/user_guides/xde/images/xde_as1_bracket_subassembly.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
dox/user_guides/xde/images/xde_as1_bracket_subassembly_graph.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
dox/user_guides/xde/images/xde_as1_part_of_graph.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
dox/user_guides/xde/images/xde_as1_part_of_tree.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
dox/user_guides/xde/images/xde_as1_parts.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
dox/user_guides/xde/images/xde_assembly_design.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
dox/user_guides/xde/images/xde_assembly_ocaf.png
Normal file
After Width: | Height: | Size: 14 KiB |
@@ -5,32 +5,116 @@
|
||||
|
||||
@section occt_xde_1 Introduction
|
||||
|
||||
This manual explains how to use the Extended Data Exchange (XDE). It provides basic documentation on setting up and using XDE. For advanced information on XDE and its applications, see our <a href="http://www.opencascade.com/content/tutorial-learning">E-learning & Training</a> offerings.
|
||||
For hierarchically organizing engineering data, OCCT provides application framework (OCAF). A specialization of OCAF for representing CAD product information is XDE (eXtended Data Exchange) toolset. XDE is capable of associating geometry with metadata (PMI, names, colors, layers, etc.). This framework uses the component-level abstraction of an assembly (see \ref occt_xde_references_ShahMantyla95 "[Shah and Mantyla 1995]" for the overview of possible abstractions). The leaf nodes in the XDE hierarchy are the _part instances_. The interior nodes are the _subassemblies_. The root node represents the _entire assembly_ (several roots are allowed).
|
||||
|
||||
The Extended Data Exchange (XDE) module allows extending the scope of exchange by translating additional data attached to geometric BREP data, thereby improving the interoperability with external software.
|
||||
|
||||
Data types such as colors, layers, assembly descriptions and validation properties (i.e. center of gravity, etc.) are supported. These data are stored together with shapes in an XCAF document. It is also possible to add a new types of data taking the existing tools as prototypes.
|
||||
|
||||
Finally, the XDE provides reader and writer tools for reading and writing the data supported by XCAF to and from IGES and STEP files.
|
||||
|
||||
@figure{/user_guides/xde/images/646_xde_11_400.png,"Shape imported using XDE",240}
|
||||
|
||||
The XDE component requires @ref occt_user_guides__shape_healing "Shape Healing" toolkit for operation.
|
||||
@figure{/user_guides/xde/images/646_xde_11_400.png,"Shape imported using XDE (courtesy of Dave Goetsch via GrabCAD).",240}
|
||||
|
||||
@subsection occt_xde_1_1 Basic terms
|
||||
|
||||
For better understanding of XDE, certain key terms are defined:
|
||||
* **Shape** -- a standalone shape, which does not belong to the assembly structure.
|
||||
* **Instance** -- a replication of another shape with a location that can be the same location or a different one.
|
||||
* **Assembly** -- a construction that is either a root or a sub-assembly.
|
||||
We use the following terminology throughout this documentation:
|
||||
|
||||
* **Assembly:** a hierarchy of elements representing a complex product.
|
||||
|
||||
* **Subassembly:** a group of elements inside an assembly. Typically, a subassembly is a set of components that are physically assembled into a unit and then assembled with other components.
|
||||
|
||||
* **Part:** a piece of data representing a simple individual product.
|
||||
|
||||
* **Instance:** a *usage occurrence* of a part or a subassembly. An instance is usually mounted to a parent component by specifying relative transformation. It should be noted that whenever term "instance" is used, it may refer to either a part or a subassembly. When an individual part is mentioned, we use a more precise "part instance" term.
|
||||
|
||||
* **Assembly item:** any element in the component hierarchy of an assembly. If visualization is employed, an assembly item typically corresponds to an element in a scene graph.
|
||||
|
||||
* **Component:** any *nested* assembly item.
|
||||
|
||||
The key terms are illustrated in the figure below.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_assembly_design.png,"Parts and instances.",240}
|
||||
|
||||
The example above assumes that two parts (a plate and a cylinder) are created independently in some part design system. Then an assembly is constructed by instantiating these parts with some user-defined mutual placements (probably driven by assembly constraints). In this example, the root assembly item "MyAssembly" contains the following components:
|
||||
|
||||
* "Plate" as the only instance of the plate part.
|
||||
* "Cylinders" as the subassembly which includes three instances of a cylinder part.
|
||||
|
||||
A CAD part in a design system has usually no link to other parts in a product unless it is dropped to an assembly structure. To become an assembly component, the part has to be instantiated. An instance is technically a reference to the part with a proper location. The distinction between *parts* and *instances* is one of the fundamental principles in assembly design. A single part may have multiple instances all sharing the same product information (geometry and metadata). It is also valid to associate metadata with the instances themselves, though the latter is not very common (and not fully supported in OCCT).
|
||||
|
||||
\note The important point is the distinction between parts and instances. A part is a single product which may several times occur in an assembly. An instance is a particular occurrence of a part in an assembly.
|
||||
|
||||
@subsection occt_xde_1_2 XDE Organization
|
||||
|
||||
The basis of XDE, called XCAF, is a framework based on OCAF (Open CASCADE Technology Application Framework) and is intended to be used with assemblies and with various kinds of attached data (attributes). Attributes can be Individual attributes for a shape, specifying some characteristics of a shape, or they can be Grouping attributes, specifying that a shape belongs to a given group whose definition is specified apart from the shapes.
|
||||
@subsubsection occt_xde_1_2_1 Assemblies
|
||||
|
||||
XDE works in an OCAF document with a specific organization defined in a dedicated XCAF module. This organization is used by various functions of XDE to exchange standardized data other than shapes and geometry.
|
||||
Assembly components are represented as nodes in a directed graph. The arcs of the graph represent "part-of" relations between the components (read like "component A is part of component B"). The following figure illustrates a conventional assembly from \ref occt_xde_references_cax_if "[CAx-IF STEP Library]" composed of five unique parts.
|
||||
|
||||
The Assembly Structure and attributes assigned to shapes are stored in the OCAF tree. It is possible to obtain TopoDS representation for each level of the assembly in the form of *TopoDS_Compound* or *TopoDS_Shape* using the API.
|
||||
@figure{/user_guides/xde/images/xde_as1.png,"Sample assembly.",240}
|
||||
|
||||
Each part is defined in its local coordinate system and dropped to an assembly with a suitable placement. As such, the bolt has six instances, while a nut is instantiated eight times.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_as1_parts.png,"Parts of sample assembly.",240}
|
||||
|
||||
The "part-of" graph is sketched in the following figure.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_as1_part_of_graph.png,"\"Part-of\" assembly graph.",240}
|
||||
|
||||
There are as many component occurrences in an assembly as many paths exist to each leaf from the root nodes. Starting from the root node "as1", 18 unique ways are giving the total number of part occurrences in the component structure.
|
||||
|
||||
Technically, each node of the graph is represented by a label in the underlying OCAF structure. However, an OCAF label (TDF_Label) cannot be used as an identifier of an assembly item. In general case, one label can be reached from several "directions" of traversal. Thus, to address a single component occurrence unambiguously, one should use a full path to the occurrence in a component graph as an identifier. The following figure illustrates the result of assembly graph traversal which can be represented as a user-friendly tree (scene graph).
|
||||
|
||||
@figure{/user_guides/xde/images/xde_as1_part_of_tree.png,"\"Part-of\" assembly tree.",240}
|
||||
|
||||
Such a tree stands for the hierarchy of the components which can be shown to the user. A child-parent relation has "part-of" meaning. Notice that an individual node in the assembly tree is associated with a unique path to the item in the component graph. The following figure illustrates a simple bracket subassembly which is used twice as a component in the sample model.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_as1_bracket_subassembly.png,"Bracket subassembly instantiated twice in sample model.",240}
|
||||
|
||||
The following figure outlines the component graph for this subassembly.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_as1_bracket_subassembly_graph.png,"\"Part-of\" graph for bracket subassembly.",240}
|
||||
|
||||
Assembly structure is not directly related to any geometry. Therefore, assembly structure gives only a conceptual view of a product. According to \ref occt_xde_references_ShahMantyla95 "[Shah and Mantyla 1995]" (p. 9), many design tasks are not related to geometry at all, but to other characteristics of a product. Some problems involve idealized or simplified geometry, and it often happens that a detailed geometry is not even required (at least during some design phases). At the same time, the geometric model for a subassembly in XDE can be directly accessed at any time in the form of *TopoDS_Compound*.
|
||||
|
||||
XDE defines the specific organization of the assembly content. All elements are stored at sub-labels of label 0:1:1. There can be one or more roots. The hierarchy of labels is always two-levels nested. The first level (direct children of 0:1:1) declares all products within an assembly. The second level determines the "part-of" relations between the assembly elements.
|
||||
|
||||
@figure{/user_guides/xde/images/xde_assembly_ocaf.png,"Internal (OCAF) representation of XDE document.",240}
|
||||
|
||||
@subsubsection occt_xde_1_2_2 How to explore assembly structure
|
||||
|
||||
To explore the assembly structure, you may use a specialized *XCAFDoc_AssemblyGraph* tool. The following code snippet illustrates the construction of explicit assembly graph from XDE document.
|
||||
|
||||
\code
|
||||
Handle(TDocStd_Document) doc = ...; // Your XDE document
|
||||
|
||||
// Prepare assembly graph
|
||||
Handle(XCAFDoc_AssemblyGraph) asmGraph = new XCAFDoc_AssemblyGraph(doc, true);
|
||||
\endcode
|
||||
|
||||
*XCAFDoc_AssemblyGraph* does not contain geometry of the assembly being explored. It is a formal graph structure which makes explicit the "part-of" relations between the assembly components. Each node in a graph is associated with one of the following types:
|
||||
|
||||
* **Root:**
|
||||
* **Subassembly**
|
||||
* **Part occurrence**
|
||||
* **Part**
|
||||
|
||||
A node contains a persistent ID which points to the corresponding OCAF label. The persistent ID is a key to access geometric representations and metadata associated with the corresponding element of assembly.
|
||||
|
||||
@subsubsection occt_xde_1_2_3 Multiple component occurrences
|
||||
|
||||
Consider two parts: wheel and axle shown in the picture below.
|
||||
|
||||
@figure{/user_guides/xde/images/assm_wheel_axle.png,"Two parts: wheel and axle.",240}
|
||||
|
||||
Consider a wheel-axle subassembly composed of one axle and two wheels.
|
||||
|
||||
@figure{/user_guides/xde/images/assm_wheel_axle_sa.png,"Subassembly composed of two wheels and one axle.",240}
|
||||
|
||||
A higher-level chassis assembly is in turn composed of two wheel-axle subassemblies, the front, and the rear.
|
||||
|
||||
@figure{/user_guides/xde/images/assm_wheel_axle_root.png,"Chassis assembly with multiple component occurrences.",240}
|
||||
|
||||
There is a requirement to identify individual components such as the left-front wheel. However, a wheel part has only two instances in the owner wheel-axle subassembly. The necessity to uniquely identify all component occurrences requires introducing a *transient* key for the corresponding assembly item. This key is essentially a path in the component graph which unambiguously addresses the element in question.
|
||||
|
||||
\note As reported by \ref occt_xde_references_Ungerer02 "[Ungerer and Buchanan 2002]", STEP PDM Schema is capable of tracking specific usages of assembly components. However, OCCT makes no assumption on the used STEP schema, so multiple component occurrences should be implemented at the level of XDE-based application.
|
||||
|
||||
\todo mention Grab Instance
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
Basic elements used by XDE are introduced in the XCAF sub-module by the package XCAFDoc. These elements consist in descriptions of commonly used data structures (apart from the shapes themselves) in normalized data exchanges. They are not attached to specific applications and do not bring specific semantics, but are structured according to the use and needs of data exchanges.
|
||||
The Document used by XDE usually starts as a *TDocStd_Document*.
|
||||
@@ -45,9 +129,7 @@ For example, a mechanical assembly can be defined as follows:
|
||||
@figure{/user_guides/xde/images/xde_image004.png,"Assembly View",240}
|
||||
|
||||
|
||||
XDE defines the specific organization of the assembly content. Shapes are stored on sub-labels of label 0:1:1. There can be one or more roots (called free shapes) whether they are true trees or simple shapes. A shape can be considered to be an Assembly (such as AS1 under 0:1:1:1 in Figure1) if it is defined with Components (sub-shapes, located or not).
|
||||
|
||||
*XCAFDoc_ShapeTool* is a tool that allows managing the Shape section of the XCAF document. This tool is implemented as an attribute and located at the root label of the shape section.
|
||||
|
||||
@subsection occt_xde_1_4 Validation Properties
|
||||
Validation properties are geometric characteristics of Shapes (volume, centroid, surface area) written to STEP files by the sending system. These characteristics are read by the receiving system to validate the quality of the translation. This is done by comparing the values computed by the original system with the same values computed by the receiving system on the resulting model.
|
||||
@@ -685,3 +767,14 @@ As a result, if an application works on Assemblies, on Colors or Layers, on Vali
|
||||
|
||||
In addition, if an application has a data structure far from these notions, it can get data (such as Colors and Names on Shapes) according to its needs, but without having to consider the whole.
|
||||
|
||||
@section occt_xde_references References
|
||||
|
||||
-# \anchor occt_xde_references_ShahMantyla95
|
||||
Shah J., Mantyla M. Parametric and Feature Based CAD/CAM. 1995.
|
||||
|
||||
-# \anchor occt_xde_references_cax_if
|
||||
CAx-IF STEP File Library // URL: https://cax-if.org/library/index.html
|
||||
|
||||
-# \anchor occt_xde_references_Ungerer02
|
||||
Ungerer, M. and Buchanan, K. 2002. Usage Guide for the STEP PDM Schema Release 4.3. PDM Implementor Forum, Darmstadt January.
|
||||
|
||||
|
@@ -4,6 +4,8 @@ XCAFDoc.cxx
|
||||
XCAFDoc.hxx
|
||||
XCAFDoc_Area.cxx
|
||||
XCAFDoc_Area.hxx
|
||||
XCAFDoc_AssemblyGraph.cxx
|
||||
XCAFDoc_AssemblyGraph.hxx
|
||||
XCAFDoc_Centroid.cxx
|
||||
XCAFDoc_Centroid.hxx
|
||||
XCAFDoc_ClippingPlaneTool.cxx
|
||||
@@ -40,6 +42,7 @@ XCAFDoc_Material.cxx
|
||||
XCAFDoc_Material.hxx
|
||||
XCAFDoc_MaterialTool.cxx
|
||||
XCAFDoc_MaterialTool.hxx
|
||||
XCAFDoc_ObjectId.hxx
|
||||
XCAFDoc_ShapeMapTool.cxx
|
||||
XCAFDoc_ShapeMapTool.hxx
|
||||
XCAFDoc_ShapeTool.cxx
|
||||
|
259
src/XCAFDoc/XCAFDoc_AssemblyGraph.cxx
Normal file
@@ -0,0 +1,259 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Own include
|
||||
#include <XCAFDoc_AssemblyGraph.hxx>
|
||||
|
||||
// OCCT includes
|
||||
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
|
||||
#include <TDataStd_Name.hxx>
|
||||
#include <TDataStd_TreeNode.hxx>
|
||||
#include <TDF_ChildIterator.hxx>
|
||||
#include <TDF_LabelSequence.hxx>
|
||||
#include <TDF_Tool.hxx>
|
||||
#include <XCAFDoc.hxx>
|
||||
#include <XCAFDoc_DocumentTool.hxx>
|
||||
#include <XCAFDoc_ShapeTool.hxx>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define NodeLetter "N"
|
||||
#define Whitespace " "
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
XCAFDoc_AssemblyGraph::XCAFDoc_AssemblyGraph(const Handle(TDocStd_Document)& M,
|
||||
const bool withParts)
|
||||
: Standard_Transient (),
|
||||
m_model (M),
|
||||
m_bWithParts (withParts)
|
||||
{
|
||||
this->buildGraph();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XCAFDoc_AssemblyGraph::Dump(Standard_OStream& out) const
|
||||
{
|
||||
// Directed graph header
|
||||
out << "digraph core_AssemblyGraph {\n";
|
||||
out << "\n";
|
||||
|
||||
// Dump nodes with attributes
|
||||
const NCollection_IndexedMap<XCAFDoc_ObjectId>& nodes = this->GetNodes();
|
||||
//
|
||||
for ( int n = 1; n <= nodes.Extent(); ++n )
|
||||
{
|
||||
// Get name of persistent object
|
||||
TCollection_ExtendedString name;
|
||||
this->getObjectName(nodes(n), name);
|
||||
|
||||
// Generate label
|
||||
TCollection_AsciiString label(name);
|
||||
label += "\\n"; label += nodes(n);
|
||||
|
||||
// Dump node with label
|
||||
out << Whitespace << NodeLetter << n << " [label=\"" << label.ToCString() << "\"];\n";
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
// Dump arcs
|
||||
for ( t_adjacency::Iterator it(m_arcs); it.More(); it.Next() )
|
||||
{
|
||||
const int parentId = it.Key();
|
||||
const TColStd_PackedMapOfInteger& children = it.Value();
|
||||
|
||||
// Loop over the children
|
||||
for ( TColStd_MapIteratorOfPackedMapOfInteger cit(children); cit.More(); cit.Next() )
|
||||
{
|
||||
const int childId = cit.Key();
|
||||
|
||||
out << Whitespace
|
||||
<< NodeLetter << parentId
|
||||
<< " -> "
|
||||
<< NodeLetter << childId
|
||||
<< ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
out << "}\n";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XCAFDoc_AssemblyGraph::CalculateSummary(int& numRoots,
|
||||
int& numSubassemblies,
|
||||
int& numPartOccurrences,
|
||||
int& numParts) const
|
||||
{
|
||||
numRoots = 0;
|
||||
numSubassemblies = 0;
|
||||
numPartOccurrences = 0;
|
||||
numParts = 0;
|
||||
|
||||
// Loop over the nodes
|
||||
for ( int n = 1; n <= this->GetNodes().Extent(); ++n )
|
||||
{
|
||||
if ( !m_nodeTypes.IsBound(n) ) continue; // This should never happen
|
||||
|
||||
switch ( m_nodeTypes(n) )
|
||||
{
|
||||
case NodeType_Root: ++numRoots; break;
|
||||
case NodeType_Subassembly: ++numSubassemblies; break;
|
||||
case NodeType_PartOccurrence: ++numPartOccurrences; break;
|
||||
case NodeType_Part: ++numParts; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XCAFDoc_AssemblyGraph::buildGraph()
|
||||
{
|
||||
// Get shape tool
|
||||
Handle(XCAFDoc_ShapeTool)
|
||||
shapeTool = XCAFDoc_DocumentTool::ShapeTool( m_model->Main() );
|
||||
|
||||
// We start from those shapes which are "free" in terms of XDE
|
||||
TDF_LabelSequence roots;
|
||||
//
|
||||
shapeTool->GetFreeShapes(roots);
|
||||
//
|
||||
for ( TDF_LabelSequence::Iterator it(roots); it.More(); it.Next() )
|
||||
{
|
||||
const TDF_Label& label = it.Value();
|
||||
|
||||
// Get entry of the current label
|
||||
XCAFDoc_ObjectId objectId;
|
||||
TDF_Tool::Entry(label, objectId);
|
||||
|
||||
// Free shapes are root nodes of the assembly graph
|
||||
const int iObjectId = m_nodes.Add(objectId);
|
||||
|
||||
// Mark as root
|
||||
m_nodeTypes.Bind(iObjectId, NodeType_Root);
|
||||
//
|
||||
m_roots.Add(iObjectId);
|
||||
|
||||
// Add components (the objects nested into the current one)
|
||||
this->addComponents(label, iObjectId);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XCAFDoc_AssemblyGraph::addComponents(const TDF_Label& parent,
|
||||
const int iParentId)
|
||||
{
|
||||
// Get shape tool
|
||||
Handle(XCAFDoc_ShapeTool)
|
||||
shapeTool = XCAFDoc_DocumentTool::ShapeTool( m_model->Main() );
|
||||
|
||||
const bool isSubassembly = shapeTool->IsAssembly(parent);
|
||||
|
||||
// Bind topological type. We check that no attribute is associated to
|
||||
// prevent multiple tagging of the same node from different directions
|
||||
// of traversal.
|
||||
if ( !m_nodeTypes.IsBound(iParentId) )
|
||||
{
|
||||
if ( isSubassembly )
|
||||
m_nodeTypes.Bind(iParentId, NodeType_Subassembly);
|
||||
else
|
||||
{
|
||||
m_nodeTypes.Bind(iParentId, NodeType_PartOccurrence);
|
||||
|
||||
// If parts are requested to participate in the graph, we add more nodes
|
||||
if ( m_bWithParts )
|
||||
{
|
||||
// Get entry of the current label which is the original label
|
||||
XCAFDoc_ObjectId partId;
|
||||
TDF_Tool::Entry(parent, partId);
|
||||
|
||||
// Add node
|
||||
const int iPartId = m_nodes.Add(partId);
|
||||
|
||||
// Add arc
|
||||
if ( !m_arcs.IsBound(iParentId) )
|
||||
m_arcs.Bind( iParentId, TColStd_PackedMapOfInteger() );
|
||||
//
|
||||
m_arcs(iParentId).Add(iPartId);
|
||||
|
||||
// Bind type
|
||||
if ( !m_nodeTypes.IsBound(iPartId) )
|
||||
m_nodeTypes.Bind(iPartId, NodeType_Part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isSubassembly )
|
||||
return; // We have to return here in order to prevent iterating by
|
||||
// sub-labels. For parts, sub-labels are used to encode
|
||||
// metadata which is out of interest in conceptual design
|
||||
// intent represented by assembly graph.
|
||||
|
||||
// Loop over the children (persistent representation of "part-of" relation)
|
||||
for ( TDF_ChildIterator cit(parent); cit.More(); cit.Next() )
|
||||
{
|
||||
TDF_Label child = cit.Value();
|
||||
|
||||
// Get entry of the current label
|
||||
XCAFDoc_ObjectId childId;
|
||||
TDF_Tool::Entry(child, childId);
|
||||
|
||||
// Add node
|
||||
const int iChildId = m_nodes.Add(childId);
|
||||
|
||||
// Add arc
|
||||
if ( !m_arcs.IsBound(iParentId) )
|
||||
m_arcs.Bind( iParentId, TColStd_PackedMapOfInteger() );
|
||||
//
|
||||
m_arcs(iParentId).Add(iChildId);
|
||||
|
||||
// Jump to the referred object (the original)
|
||||
TDF_Label childOriginal;
|
||||
Handle(TDataStd_TreeNode) jumpTreeNode;
|
||||
child.FindAttribute(XCAFDoc::ShapeRefGUID(), jumpTreeNode);
|
||||
//
|
||||
if ( !jumpTreeNode.IsNull() && jumpTreeNode->HasFather() )
|
||||
childOriginal = jumpTreeNode->Father()->Label(); // Declaration-level origin
|
||||
|
||||
// Process children: add components recursively
|
||||
if ( !childOriginal.IsNull() )
|
||||
this->addComponents(childOriginal, iChildId);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool XCAFDoc_AssemblyGraph::getObjectName(const XCAFDoc_ObjectId& id,
|
||||
TCollection_ExtendedString& name) const
|
||||
{
|
||||
// Get label for object ID
|
||||
TDF_Label label;
|
||||
TDF_Tool::Label(m_model->GetData(), id, label);
|
||||
|
||||
// Access name
|
||||
Handle(TDataStd_Name) nameAttr;
|
||||
if ( !label.FindAttribute(TDataStd_Name::GetID(), nameAttr) )
|
||||
{
|
||||
name = "";
|
||||
return false;
|
||||
}
|
||||
//
|
||||
name = nameAttr->Get();
|
||||
return true;
|
||||
}
|
292
src/XCAFDoc/XCAFDoc_AssemblyGraph.hxx
Normal file
@@ -0,0 +1,292 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _XCAFDoc_AssemblyGraph_HeaderFile
|
||||
#define _XCAFDoc_AssemblyGraph_HeaderFile
|
||||
|
||||
// XDE includes
|
||||
#include <XCAFDoc_ObjectId.hxx>
|
||||
|
||||
// Other OCCT includes
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <TColStd_PackedMapOfInteger.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
|
||||
//! \brief Assembly graph.
|
||||
//!
|
||||
//! This tool gives clear OCAF-agnostic interface to
|
||||
//! the assembly structure of a product. A graph is essentially a set of
|
||||
//! nodes {N} and a set of arcs {A} as defined formally.
|
||||
//!
|
||||
//! <pre>
|
||||
//! G = <N, A>
|
||||
//! </pre>
|
||||
//!
|
||||
//! Using this tool, you can map XDE assembly items to a formal graph
|
||||
//! structure. Each node in the graph preserves a link to the data storage
|
||||
//! (OCAF document) by means of \ref XCAFDoc_ObjectId.
|
||||
//!
|
||||
//! \sa XCAFDoc_ObjectId
|
||||
class XCAFDoc_AssemblyGraph : public Standard_Transient
|
||||
{
|
||||
public:
|
||||
|
||||
//! \brief Type of the graph node.
|
||||
enum NodeType
|
||||
{
|
||||
NodeType_UNDEFINED = 0, //!< Undefined node type.
|
||||
//
|
||||
NodeType_Root, //!< Root node (has no entry arcs).
|
||||
NodeType_Subassembly, //!< Intermediate node (non-leaf node which has entry arcs).
|
||||
NodeType_PartOccurrence, //!< Part usage occurrence.
|
||||
NodeType_Part //!< Optional leaf node to represent parts. Note that
|
||||
//!< this node type is activated by a dedicated flag in
|
||||
//!< the constructor. If activated, the part occurrence nodes
|
||||
//!< are not leafs anymore.
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// OCCT RTTI
|
||||
DEFINE_STANDARD_RTTI_INLINE(XCAFDoc_AssemblyGraph, Standard_Transient)
|
||||
|
||||
public:
|
||||
|
||||
//! \brief Graph iterator.
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
|
||||
//! Default ctor.
|
||||
Iterator() : m_iCurrentIndex(0) {}
|
||||
|
||||
//! ctor accepting the assembly graph to iterate.
|
||||
//! \param[in] asmGraph assembly graph to iterate.
|
||||
Iterator(const Handle(XCAFDoc_AssemblyGraph)& asmGraph)
|
||||
{
|
||||
this->Init(asmGraph);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Initializes iterator with assembly graph.
|
||||
//! \param[in] asmGraph assembly graph to iterate.
|
||||
void Init(const Handle(XCAFDoc_AssemblyGraph)& asmGraph)
|
||||
{
|
||||
m_graph = asmGraph;
|
||||
m_iCurrentIndex = 1;
|
||||
}
|
||||
|
||||
//! Checks if there are more graph nodes to iterate.
|
||||
//! \return true/false.
|
||||
bool More() const
|
||||
{
|
||||
return m_iCurrentIndex <= m_graph->GetNodes().Extent();
|
||||
}
|
||||
|
||||
//! \return 1-based ID of the current node.
|
||||
int GetCurrentNode() const
|
||||
{
|
||||
return m_iCurrentIndex;
|
||||
}
|
||||
|
||||
//! Moves iterator to the next position.
|
||||
void Next()
|
||||
{
|
||||
++m_iCurrentIndex;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Handle(XCAFDoc_AssemblyGraph) m_graph; //!< Assembly graph to iterate.
|
||||
int m_iCurrentIndex; //!< Current 1-based node ID.
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//! Type definition for graph adjacency matrix. This is how parent-component
|
||||
//! links are realized in the assembly graph.
|
||||
typedef NCollection_DataMap<int, TColStd_PackedMapOfInteger> t_adjacency;
|
||||
|
||||
public:
|
||||
|
||||
//! \brief Initializes graph from Data Model.
|
||||
//!
|
||||
//! Construction of a formal graph will be done immediately at ctor.
|
||||
//!
|
||||
//! \param[in] M Data Model to iterate.
|
||||
//! \param[in] withParts indicates whether to add nodes representing the
|
||||
//! instanced parts to the assembly graph.
|
||||
Standard_EXPORT
|
||||
XCAFDoc_AssemblyGraph(const Handle(TDocStd_Document)& M,
|
||||
const bool withParts = false);
|
||||
|
||||
public:
|
||||
|
||||
//! \brief Dumps graph structure to output stream.
|
||||
//!
|
||||
//! The output format is DOT. You may use graph rendering tools like
|
||||
//! Graphviz to parse the output.
|
||||
//!
|
||||
//! \param[out] out output stream.
|
||||
Standard_EXPORT void
|
||||
Dump(Standard_OStream& out) const;
|
||||
|
||||
//! \brief Calculates short summary for the assembly.
|
||||
//!
|
||||
//! Short summary gives you the total number of nodes of a particular
|
||||
//! type. Note that the number of parts will be calculated only if parts
|
||||
//! are available in the graph (which is the option by construction).
|
||||
//!
|
||||
//! \param[out] numRoots number of root nodes.
|
||||
//! \param[out] numSubassemblies number of subassembly nodes.
|
||||
//! \param[out] numPartOccurrences number of part usage occurrence nodes.
|
||||
//! \param[out] numParts number of parts (if available).
|
||||
Standard_EXPORT void
|
||||
CalculateSummary(int& numRoots,
|
||||
int& numSubassemblies,
|
||||
int& numPartOccurrences,
|
||||
int& numParts) const;
|
||||
|
||||
public:
|
||||
|
||||
//! \brief Returns IDs of the root nodes.
|
||||
//! \return IDs of the root nodes.
|
||||
const TColStd_PackedMapOfInteger& GetRoots() const
|
||||
{
|
||||
return m_roots;
|
||||
}
|
||||
|
||||
//! \brief Checks whether the assembly graph contains (n1, n2) directed arc.
|
||||
//! \param[in] n1 one-based ID of the first node.
|
||||
//! \param[in] n2 one-based ID of the second node.
|
||||
//! \return true/false.
|
||||
bool HasArc(const int n1, const int n2) const
|
||||
{
|
||||
if ( !this->HasChildren(n1) )
|
||||
return false;
|
||||
|
||||
return this->GetChildren(n1).Contains(n2);
|
||||
}
|
||||
|
||||
//! \brief Checks whether children exist for the given node.
|
||||
//! \param[in] oneBasedNodeId one-based node ID.
|
||||
//! \return true/false.
|
||||
bool HasChildren(const int oneBasedNodeId) const
|
||||
{
|
||||
return m_arcs.IsBound(oneBasedNodeId);
|
||||
}
|
||||
|
||||
//! \brief Returns IDs of child nodes for the given node.
|
||||
//! \param[in] oneBasedNodeId one-based node ID.
|
||||
//! \return set of child IDs.
|
||||
const TColStd_PackedMapOfInteger& GetChildren(const int oneBasedNodeId) const
|
||||
{
|
||||
return m_arcs(oneBasedNodeId);
|
||||
}
|
||||
|
||||
//! \brief Returns the node type from \ref NodeType enum.
|
||||
//! \param[in] oneBasedNodeId one-based node ID.
|
||||
//! \return node type.
|
||||
//! \sa NodeType
|
||||
NodeType GetNodeType(const int oneBasedNodeId) const
|
||||
{
|
||||
if ( !m_nodeTypes.IsBound(oneBasedNodeId) )
|
||||
return NodeType_UNDEFINED;
|
||||
|
||||
return m_nodeTypes(oneBasedNodeId);
|
||||
}
|
||||
|
||||
//! \brief returns object ID by node ID.
|
||||
//! \param[in] oneBasedNodeId one-based node ID.
|
||||
//! \return persistent ID.
|
||||
const XCAFDoc_ObjectId& GetPersistentId(const int oneBasedNodeId) const
|
||||
{
|
||||
return m_nodes(oneBasedNodeId);
|
||||
}
|
||||
|
||||
//! \brief Returns the unordered set of graph nodes.
|
||||
//! \return graph nodes.
|
||||
const NCollection_IndexedMap<XCAFDoc_ObjectId>& GetNodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
//! \brief Returns the number of graph nodes.
|
||||
//! \return number of graph nodes.
|
||||
int GetNumberOfNodes() const
|
||||
{
|
||||
return m_nodes.Extent();
|
||||
}
|
||||
|
||||
//! \brief Returns the collection of graph arcs in form of adjacency matrix.
|
||||
//! \return graph arcs.
|
||||
const t_adjacency& GetArcs() const
|
||||
{
|
||||
return m_arcs;
|
||||
}
|
||||
|
||||
//! \brief Returns the number of graph arcs.
|
||||
//! \return number of graph arcs.
|
||||
int GetNumberOfArcs() const
|
||||
{
|
||||
int numArcs = 0;
|
||||
//
|
||||
for ( t_adjacency::Iterator it(m_arcs); it.More(); it.Next() )
|
||||
numArcs += it.Value().Extent();
|
||||
|
||||
return numArcs;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Builds graph out of OCAF XDE structure.
|
||||
Standard_EXPORT void
|
||||
buildGraph();
|
||||
|
||||
//! Adds components for the given root to the graph structure.
|
||||
//! \param[in] parent OCAF label of the parent object.
|
||||
//! \param[in] iParentId ID of the already registered node
|
||||
//! representing the parent object in the assembly
|
||||
//! graph being populated.
|
||||
Standard_EXPORT void
|
||||
addComponents(const TDF_Label& parent,
|
||||
const int iParentId);
|
||||
|
||||
//! Returns object name for the given persistent ID.
|
||||
//! \param[in] id persistent ID.
|
||||
//! \param[out] name object name.
|
||||
//! \return false if no name is associated with the object or the object
|
||||
//! does not exist.
|
||||
Standard_EXPORT bool
|
||||
getObjectName(const XCAFDoc_ObjectId& id,
|
||||
TCollection_ExtendedString& name) const;
|
||||
|
||||
protected:
|
||||
|
||||
// INPUTS
|
||||
Handle(TDocStd_Document) m_model; //!< Data Model instance.
|
||||
bool m_bWithParts; //!< Indicates whether to include parts to the graph.
|
||||
|
||||
// OUTPUTS
|
||||
TColStd_PackedMapOfInteger m_roots; //!< IDs of the root nodes.
|
||||
NCollection_IndexedMap<XCAFDoc_ObjectId> m_nodes; //!< Graph nodes.
|
||||
t_adjacency m_arcs; //!< "Part-of" relations.
|
||||
NCollection_DataMap<int, NodeType> m_nodeTypes; //!< Node types (cached for efficiency).
|
||||
|
||||
};
|
||||
|
||||
#endif
|
25
src/XCAFDoc/XCAFDoc_ObjectId.hxx
Normal file
@@ -0,0 +1,25 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _XCAFDoc_ObjectId_HeaderFile
|
||||
#define _XCAFDoc_ObjectId_HeaderFile
|
||||
|
||||
// OCCT includes
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
//! Persistent object ID.
|
||||
typedef TCollection_AsciiString XCAFDoc_ObjectId;
|
||||
|
||||
#endif
|
@@ -1,9 +1,13 @@
|
||||
XDEDRAW.cxx
|
||||
XDEDRAW.hxx
|
||||
XDEDRAW_Assemblies.hxx
|
||||
XDEDRAW_Assemblies.cxx
|
||||
XDEDRAW_Colors.cxx
|
||||
XDEDRAW_Colors.hxx
|
||||
XDEDRAW_Common.cxx
|
||||
XDEDRAW_Common.hxx
|
||||
XDEDRAW_DrawableAssemblyGraph.cxx
|
||||
XDEDRAW_DrawableAssemblyGraph.hxx
|
||||
XDEDRAW_Layers.cxx
|
||||
XDEDRAW_Layers.hxx
|
||||
XDEDRAW_Props.cxx
|
||||
|
@@ -80,6 +80,7 @@
|
||||
#include <XCAFPrs.hxx>
|
||||
#include <XCAFPrs_Driver.hxx>
|
||||
#include <XDEDRAW.hxx>
|
||||
#include <XDEDRAW_Assemblies.hxx>
|
||||
#include <XDEDRAW_Colors.hxx>
|
||||
#include <XDEDRAW_Common.hxx>
|
||||
#include <XDEDRAW_Layers.hxx>
|
||||
@@ -1165,6 +1166,7 @@ void XDEDRAW::Init(Draw_Interpretor& di)
|
||||
di.Add ("XTestDoc", "XTestDoc shape", __FILE__, testDoc, g);
|
||||
|
||||
// Specialized commands
|
||||
XDEDRAW_Assemblies::InitCommands ( di );
|
||||
XDEDRAW_Shapes::InitCommands ( di );
|
||||
XDEDRAW_Colors::InitCommands ( di );
|
||||
XDEDRAW_Layers::InitCommands ( di );
|
||||
|
308
src/XDEDRAW/XDEDRAW_Assemblies.cxx
Normal file
@@ -0,0 +1,308 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Own include
|
||||
#include <XDEDRAW_Assemblies.hxx>
|
||||
|
||||
// Other OCCT includes
|
||||
#include <DDocStd.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <NCollection_Vector.hxx>
|
||||
#include <XDEDRAW_DrawableAssemblyGraph.hxx>
|
||||
|
||||
// Standard includes
|
||||
#include <vector>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::vector< std::pair<TCollection_AsciiString, XCAFDoc_AssemblyGraph::NodeType> >
|
||||
XAssembly_NodeTypes = {
|
||||
{"-roots", XCAFDoc_AssemblyGraph::NodeType_Root},
|
||||
{"-subassemblies", XCAFDoc_AssemblyGraph::NodeType_Subassembly},
|
||||
{"-partoccurrences", XCAFDoc_AssemblyGraph::NodeType_PartOccurrence},
|
||||
{"-parts", XCAFDoc_AssemblyGraph::NodeType_Part}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//! Returns true if the passed command line option specifies node type.
|
||||
//! \param[in] opt option to check.
|
||||
//! \return true/false.
|
||||
bool XAssembly_IsKeywordNodeType(const TCollection_AsciiString& opt)
|
||||
{
|
||||
for ( size_t s = 0; s < XAssembly_NodeTypes.size(); ++s )
|
||||
if ( opt == XAssembly_NodeTypes[s].first )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//! Checks if the given graph node is of expected type.
|
||||
//! \param[in] what node to check.
|
||||
//! \param[in] opt expected type.
|
||||
//! \param[in] asmGraph assembly graph.
|
||||
//! \return true/false.
|
||||
bool XAssembly_IsOfExpectedType(const int n,
|
||||
const TCollection_AsciiString& opt,
|
||||
const Handle(XCAFDoc_AssemblyGraph)& asmGraph)
|
||||
{
|
||||
const XCAFDoc_AssemblyGraph::NodeType actualType = asmGraph->GetNodeType(n);
|
||||
|
||||
// Check against registered types
|
||||
TCollection_AsciiString expectedOpt;
|
||||
for ( size_t t = 0; t < XAssembly_NodeTypes.size(); ++t )
|
||||
{
|
||||
if ( actualType == XAssembly_NodeTypes[t].second )
|
||||
{
|
||||
expectedOpt = XAssembly_NodeTypes[t].first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( expectedOpt.IsEmpty() )
|
||||
return false;
|
||||
|
||||
return (expectedOpt == opt);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//! Builds assembly graph for the given model.
|
||||
//! \param[in] di Draw interpreter instance.
|
||||
//! \param[in] argc number of arguments.
|
||||
//! \param[in] argv list of arguments.
|
||||
//! \return execution result.
|
||||
static int XAssemblyGraph(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
// Preliminary checks
|
||||
if ( argc != 4 )
|
||||
{
|
||||
std::cout << "Incorrect number of arguments. Check help for details..." << std::endl;
|
||||
return 1; // Failure
|
||||
}
|
||||
|
||||
// Get document
|
||||
Handle(TDocStd_Document) doc;
|
||||
DDocStd::GetDocument(argv[1], doc);
|
||||
if ( doc.IsNull() )
|
||||
{
|
||||
di << argv[1] << " is not a document\n"; return 1;
|
||||
}
|
||||
|
||||
// Whether to include parts to assembly graph or not
|
||||
const bool withParts = ( atoi(argv[2]) > 0 );
|
||||
|
||||
// Construct assembly graph
|
||||
Handle(XCAFDoc_AssemblyGraph) asmGraph = new XCAFDoc_AssemblyGraph(doc, withParts);
|
||||
|
||||
// Register assembly graph in Draw
|
||||
Draw::Set( argv[3], new XDEDRAW_DrawableAssemblyGraph(asmGraph) );
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//! Checks assembly graph.
|
||||
//! \param[in] di Draw interpreter instance.
|
||||
//! \param[in] argc number of arguments.
|
||||
//! \param[in] argv list of arguments.
|
||||
//! \return execution result.
|
||||
static int XAssemblyGraphCheck(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
// Preliminary checks
|
||||
if ( argc < 3 )
|
||||
{
|
||||
std::cout << "Incorrect number of arguments. Check help for details..." << std::endl;
|
||||
return 1; // Failure
|
||||
}
|
||||
|
||||
// Get assembly graph
|
||||
Handle(XDEDRAW_DrawableAssemblyGraph)
|
||||
DAG = Handle(XDEDRAW_DrawableAssemblyGraph)::DownCast( Draw::Get(argv[1]) );
|
||||
//
|
||||
if ( DAG.IsNull() )
|
||||
{
|
||||
std::cout << "Error: Drawable Assembly Graph is NULL" << std::endl;
|
||||
return 1; // Failure
|
||||
}
|
||||
//
|
||||
Handle(XCAFDoc_AssemblyGraph) asmGraph = DAG->GetGraph();
|
||||
|
||||
// Get summary
|
||||
int numRoots = 0;
|
||||
int numSubassemblies = 0;
|
||||
int numPartInstances = 0;
|
||||
int numParts = 0;
|
||||
//
|
||||
asmGraph->CalculateSummary(numRoots, numSubassemblies, numPartInstances, numParts);
|
||||
|
||||
// Check according to the argument keys
|
||||
for ( int i = 2; i < argc; ++i )
|
||||
{
|
||||
TCollection_AsciiString opt(argv[i]);
|
||||
opt.LowerCase();
|
||||
|
||||
// Check the number of graph nodes
|
||||
if ( opt == "-numnodes" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != asmGraph->GetNumberOfNodes() )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of nodes" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the number of graph arcs
|
||||
else if ( opt == "-numarcs" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != asmGraph->GetNumberOfArcs() )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of arcs" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the number of roots
|
||||
else if ( opt == "-numroots" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != numRoots )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of roots" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the number of subassemblies
|
||||
else if ( opt == "-numsubassemblies" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != numSubassemblies )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of subassemblies" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the number of part occurrences
|
||||
else if ( opt == "-numpartoccurrences" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != numPartInstances )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of part occurrences" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the number of parts
|
||||
else if ( opt == "-numparts" )
|
||||
{
|
||||
const int num = atoi( argv[++i] );
|
||||
//
|
||||
if ( num != numParts )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected number of parts" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check individual arc
|
||||
else if ( opt == "-arc" )
|
||||
{
|
||||
const int n1 = atoi( argv[++i] );
|
||||
const int n2 = atoi( argv[++i] );
|
||||
//
|
||||
if ( !asmGraph->HasArc(n1, n2) )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: arc (" << n1 << ", " << n2 << ") does not exist" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check individual node types
|
||||
else if ( XAssembly_IsKeywordNodeType(opt) )
|
||||
{
|
||||
do
|
||||
{
|
||||
// Get node index
|
||||
const int n = atoi( argv[++i] );
|
||||
|
||||
// Check type
|
||||
if ( !XAssembly_IsOfExpectedType(n, opt, asmGraph) )
|
||||
{
|
||||
di << 0; // FALSE
|
||||
std::cout << "Error: unexpected type for node " << n << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while ( i < (argc - 1) && !XAssembly_IsKeywordNodeType(argv[i + 1]) );
|
||||
}
|
||||
}
|
||||
di << 1; // TRUE
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : InitCommands
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void XDEDRAW_Assemblies::InitCommands(Draw_Interpretor& di)
|
||||
{
|
||||
static Standard_Boolean initactor = Standard_False;
|
||||
if (initactor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
initactor = Standard_True;
|
||||
|
||||
Standard_CString grp = "XDE assembly commands";
|
||||
|
||||
di.Add("XAssemblyGraph", "XAssemblyGraph doc withParts graph",
|
||||
__FILE__, XAssemblyGraph, grp);
|
||||
|
||||
di.Add("XAssemblyGraphCheck", "XAssemblyGraphCheck [-numnodes num] "
|
||||
"[-numarcs num] "
|
||||
"[-numroots num] "
|
||||
"[-numsubassemblies num] "
|
||||
"[-numpartoccurrences num] "
|
||||
"[-numparts num] "
|
||||
"[-arc n1 n2] "
|
||||
"[-arc n2 n3] "
|
||||
" ... "
|
||||
"[-roots n1 n2 ...] "
|
||||
"[-subassemblies n3 n4 ...] "
|
||||
"[-partoccurrences n5 n6 ...] "
|
||||
"[-parts n7 n8 ...] ",
|
||||
__FILE__, XAssemblyGraphCheck, grp);
|
||||
}
|
32
src/XDEDRAW/XDEDRAW_Assemblies.hxx
Normal file
@@ -0,0 +1,32 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _XDEDRAW_Assemblies_HeaderFile
|
||||
#define _XDEDRAW_Assemblies_HeaderFile
|
||||
|
||||
#include <Draw_Interpretor.hxx>
|
||||
|
||||
//! Draw commands for new XDE interface dedicated to assemblies.
|
||||
class XDEDRAW_Assemblies
|
||||
{
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
Standard_EXPORT static void InitCommands(Draw_Interpretor& theCommands);
|
||||
|
||||
};
|
||||
|
||||
#endif // _XDEDRAW_Assemblies_HeaderFile
|
52
src/XDEDRAW/XDEDRAW_DrawableAssemblyGraph.cxx
Normal file
@@ -0,0 +1,52 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Own include
|
||||
#include <XDEDRAW_DrawableAssemblyGraph.hxx>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
XDEDRAW_DrawableAssemblyGraph::XDEDRAW_DrawableAssemblyGraph(const Handle(XCAFDoc_AssemblyGraph)& asmGraph)
|
||||
: Draw_Drawable3D (),
|
||||
m_graph (asmGraph)
|
||||
{}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline const Handle(XCAFDoc_AssemblyGraph)& XDEDRAW_DrawableAssemblyGraph::GetGraph() const
|
||||
{
|
||||
return m_graph;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XDEDRAW_DrawableAssemblyGraph::DrawOn(Draw_Display&) const
|
||||
{
|
||||
this->Dump(std::cout);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XDEDRAW_DrawableAssemblyGraph::Dump(Standard_OStream& out) const
|
||||
{
|
||||
m_graph->Dump(out);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XDEDRAW_DrawableAssemblyGraph::Whatis(Draw_Interpretor& di) const
|
||||
{
|
||||
di << "Assembly graph";
|
||||
}
|
63
src/XDEDRAW/XDEDRAW_DrawableAssemblyGraph.hxx
Normal file
@@ -0,0 +1,63 @@
|
||||
// Created on: 2017-08-22
|
||||
// Created by: Sergey SLYADNEV
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _XDEDRAW_DrawableAssemblyGraph_HeaderFile
|
||||
#define _XDEDRAW_DrawableAssemblyGraph_HeaderFile
|
||||
|
||||
// XDE includes
|
||||
#include <XCAFDoc_AssemblyGraph.hxx>
|
||||
|
||||
// OCCT includes
|
||||
#include <Draw_Drawable3D.hxx>
|
||||
|
||||
//! Drawable container for assembly graph.
|
||||
class XDEDRAW_DrawableAssemblyGraph : public Draw_Drawable3D
|
||||
{
|
||||
public:
|
||||
|
||||
// OCCT RTTI
|
||||
DEFINE_STANDARD_RTTI_INLINE(XDEDRAW_DrawableAssemblyGraph, Draw_Drawable3D)
|
||||
|
||||
public:
|
||||
|
||||
//! Ctor accepting an assembly graph.
|
||||
//! \param[in] asmGraph assembly graph to have as drawable.
|
||||
Standard_EXPORT
|
||||
XDEDRAW_DrawableAssemblyGraph(const Handle(XCAFDoc_AssemblyGraph)& asmGraph);
|
||||
|
||||
public:
|
||||
|
||||
//! \return stored assembly graph.
|
||||
Standard_EXPORT const Handle(XCAFDoc_AssemblyGraph)&
|
||||
GetGraph() const;
|
||||
|
||||
public:
|
||||
|
||||
Standard_EXPORT void
|
||||
DrawOn(Draw_Display& dis) const Standard_OVERRIDE;
|
||||
|
||||
Standard_EXPORT virtual void
|
||||
Dump(Standard_OStream& out) const Standard_OVERRIDE;
|
||||
|
||||
Standard_EXPORT virtual void
|
||||
Whatis(Draw_Interpretor& di) const Standard_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
Handle(XCAFDoc_AssemblyGraph) m_graph; //!< Assembly graph to "draw".
|
||||
|
||||
};
|
||||
|
||||
#endif
|
69
tests/bugs/xde/bug29032_1
Normal file
@@ -0,0 +1,69 @@
|
||||
puts "============"
|
||||
puts "CR29032"
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
pload VISUALIZATION
|
||||
|
||||
##########################################################################
|
||||
# Provide XDE interface for exploration of assembly structure
|
||||
##########################################################################
|
||||
|
||||
ReadStep d [locate_data_file trj3_as1-tc-214.stp]
|
||||
XShow d
|
||||
vfit
|
||||
vsetdispmode 1
|
||||
|
||||
checkview -screenshot -3d -path ${imagedir}/${::casename}_1.png
|
||||
|
||||
# Build assembly graph with parts
|
||||
if { [XAssemblyGraph d 1 DAG] == 0 } {
|
||||
puts "Error: cannot build assembly graph"
|
||||
}
|
||||
|
||||
dump DAG
|
||||
|
||||
# Check assembly graph
|
||||
set ret [XAssemblyGraphCheck DAG \
|
||||
-numnodes 19 \
|
||||
-numarcs 28 \
|
||||
-numroots 1 \
|
||||
-numsubassemblies 6 \
|
||||
-numpartoccurrences 7 \
|
||||
-numparts 5 \
|
||||
-arc 1 2 \
|
||||
-arc 1 12 \
|
||||
-arc 1 14 \
|
||||
-arc 1 15 \
|
||||
-arc 2 3 \
|
||||
-arc 2 5 \
|
||||
-arc 2 10 \
|
||||
-arc 2 11 \
|
||||
-arc 3 4 \
|
||||
-arc 5 6 \
|
||||
-arc 5 8 \
|
||||
-arc 6 7 \
|
||||
-arc 8 9 \
|
||||
-arc 10 6 \
|
||||
-arc 10 8 \
|
||||
-arc 11 6 \
|
||||
-arc 11 8 \
|
||||
-arc 12 13 \
|
||||
-arc 14 3 \
|
||||
-arc 14 5 \
|
||||
-arc 14 10 \
|
||||
-arc 14 11 \
|
||||
-arc 15 16 \
|
||||
-arc 15 18 \
|
||||
-arc 15 19 \
|
||||
-arc 16 17 \
|
||||
-arc 18 7 \
|
||||
-arc 19 7 \
|
||||
-roots 1 \
|
||||
-subassemblies 2 5 10 11 14 15 \
|
||||
-partoccurrences 3 8 6 12 16 18 19 \
|
||||
-parts 4 7 9 13 17]
|
||||
|
||||
if { $ret == 0 } {
|
||||
puts "Error: unexpected contents of assembly graph"
|
||||
}
|
36
tests/bugs/xde/bug29032_2
Normal file
@@ -0,0 +1,36 @@
|
||||
puts "============"
|
||||
puts "CR29032"
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
pload VISUALIZATION
|
||||
|
||||
##########################################################################
|
||||
# Provide XDE interface for exploration of assembly structure
|
||||
##########################################################################
|
||||
|
||||
ReadStep d [locate_data_file OCC137-ANC101-Solid.stp]
|
||||
XShow d
|
||||
vfit
|
||||
vsetdispmode 1
|
||||
|
||||
checkview -screenshot -3d -path ${imagedir}/${::casename}_1.png
|
||||
|
||||
# Build assembly graph with parts
|
||||
if { [XAssemblyGraph d 1 DAG] == 0 } {
|
||||
puts "Error: cannot build assembly graph"
|
||||
}
|
||||
|
||||
dump DAG
|
||||
|
||||
# Check assembly graph
|
||||
set ret [XAssemblyGraphCheck DAG \
|
||||
-numnodes 1 \
|
||||
-numarcs 0 \
|
||||
-numroots 1 \
|
||||
-numsubassemblies 0 \
|
||||
-roots 1]
|
||||
|
||||
if { $ret == 0 } {
|
||||
puts "Error: unexpected contents of assembly graph"
|
||||
}
|