STEP export: Use TDocStd_XLinkTool to copy model with colors instead of our DIY routine.
Now supports older OCCT versions. Also puts components at a higher level in the hierarchy. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17549
This commit is contained in:
parent
a4583fdbc1
commit
2179685dd2
|
@ -218,6 +218,7 @@ set( PCBNEW_EXPORTERS
|
||||||
exporters/export_svg.cpp
|
exporters/export_svg.cpp
|
||||||
exporters/step/exporter_step.cpp
|
exporters/step/exporter_step.cpp
|
||||||
exporters/step/step_pcb_model.cpp
|
exporters/step/step_pcb_model.cpp
|
||||||
|
exporters/step/KI_XCAFDoc_AssemblyGraph.cxx
|
||||||
exporters/exporter_vrml.cpp
|
exporters/exporter_vrml.cpp
|
||||||
exporters/place_file_exporter.cpp
|
exporters/place_file_exporter.cpp
|
||||||
exporters/gen_drill_report_files.cpp
|
exporters/gen_drill_report_files.cpp
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
// Created on: 2022-05-11
|
||||||
|
// Copyright (c) 2022 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.
|
||||||
|
|
||||||
|
#include <Standard_NullObject.hxx>
|
||||||
|
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
|
||||||
|
#include <TDataStd_TreeNode.hxx>
|
||||||
|
#include <TDF_ChildIterator.hxx>
|
||||||
|
#include <TDF_Tool.hxx>
|
||||||
|
#include <TDocStd_Document.hxx>
|
||||||
|
#include <XCAFDoc.hxx>
|
||||||
|
#include "KI_XCAFDoc_AssemblyGraph.hxx"
|
||||||
|
#include <XCAFDoc_DocumentTool.hxx>
|
||||||
|
#include <XCAFDoc_ShapeTool.hxx>
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : KI_XCAFDoc_AssemblyGraph constructor
|
||||||
|
// purpose : Builds an assembly graph from the OCAF document
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
KI_XCAFDoc_AssemblyGraph::KI_XCAFDoc_AssemblyGraph(const Handle(TDocStd_Document)& theDoc)
|
||||||
|
{
|
||||||
|
Standard_NullObject_Raise_if(theDoc.IsNull(), "Null document!");
|
||||||
|
|
||||||
|
myShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
|
||||||
|
Standard_NoSuchObject_Raise_if(myShapeTool.IsNull(), "No XCAFDoc_ShapeTool attribute!");
|
||||||
|
|
||||||
|
TDF_Label aDummy;
|
||||||
|
buildGraph(aDummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : KI_XCAFDoc_AssemblyGraph constructor
|
||||||
|
// purpose : Builds an assembly graph from the OCAF label
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
KI_XCAFDoc_AssemblyGraph::KI_XCAFDoc_AssemblyGraph(const TDF_Label& theLabel)
|
||||||
|
{
|
||||||
|
Standard_NullObject_Raise_if(theLabel.IsNull(), "Null label!");
|
||||||
|
|
||||||
|
myShapeTool = XCAFDoc_DocumentTool::ShapeTool(theLabel);
|
||||||
|
Standard_NoSuchObject_Raise_if(myShapeTool.IsNull(), "No XCAFDoc_ShapeTool attribute!");
|
||||||
|
|
||||||
|
buildGraph(theLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : IsDirectLink
|
||||||
|
// purpose : Checks if one node is the direct child of other one
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
Standard_Boolean KI_XCAFDoc_AssemblyGraph::IsDirectLink(const Standard_Integer theNode1,
|
||||||
|
const Standard_Integer theNode2) const
|
||||||
|
{
|
||||||
|
if (!HasChildren(theNode1))
|
||||||
|
return Standard_False;
|
||||||
|
|
||||||
|
return GetChildren(theNode1).Contains(theNode2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : GetNodeType
|
||||||
|
// purpose : Returns node type
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
KI_XCAFDoc_AssemblyGraph::NodeType
|
||||||
|
KI_XCAFDoc_AssemblyGraph::GetNodeType(const Standard_Integer theNode) const
|
||||||
|
{
|
||||||
|
const NodeType* typePtr = myNodeTypes.Seek(theNode);
|
||||||
|
if (typePtr == NULL)
|
||||||
|
return NodeType_UNDEFINED;
|
||||||
|
|
||||||
|
return (*typePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : NbLinks
|
||||||
|
// purpose : Calculates and returns the number of links
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
Standard_Integer KI_XCAFDoc_AssemblyGraph::NbLinks() const
|
||||||
|
{
|
||||||
|
Standard_Integer aNumLinks = 0;
|
||||||
|
for (AdjacencyMap::Iterator it(myAdjacencyMap); it.More(); it.Next())
|
||||||
|
{
|
||||||
|
aNumLinks += it.Value().Extent();
|
||||||
|
}
|
||||||
|
return aNumLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : GetUsageOccurrenceQuantity
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
Standard_Integer KI_XCAFDoc_AssemblyGraph::NbOccurrences(const Standard_Integer theNode) const
|
||||||
|
{
|
||||||
|
const Standard_Integer* aUsageOQPtr = myUsages.Seek(theNode);
|
||||||
|
if (aUsageOQPtr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (*aUsageOQPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : buildGraph
|
||||||
|
// purpose : Builds an assembly graph from the OCAF document
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
void KI_XCAFDoc_AssemblyGraph::buildGraph(const TDF_Label& theLabel)
|
||||||
|
{
|
||||||
|
// We start from those shapes which are "free" in terms of XDE.
|
||||||
|
TDF_LabelSequence aRoots;
|
||||||
|
if (theLabel.IsNull() || (myShapeTool->Label() == theLabel))
|
||||||
|
myShapeTool->GetFreeShapes(aRoots);
|
||||||
|
else
|
||||||
|
aRoots.Append(theLabel);
|
||||||
|
|
||||||
|
for (TDF_LabelSequence::Iterator it(aRoots); it.More(); it.Next())
|
||||||
|
{
|
||||||
|
TDF_Label aLabel = it.Value();
|
||||||
|
|
||||||
|
TDF_Label anOriginal;
|
||||||
|
if (!myShapeTool->GetReferredShape(aLabel, anOriginal))
|
||||||
|
anOriginal = aLabel;
|
||||||
|
|
||||||
|
const Standard_Integer aRootId = addNode(anOriginal, 0);
|
||||||
|
if (aRootId == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
myRoots.Add(aRootId);
|
||||||
|
|
||||||
|
// Add components (the objects nested into the current one).
|
||||||
|
if (myShapeTool->IsAssembly(anOriginal))
|
||||||
|
addComponents(anOriginal, aRootId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : addComponents
|
||||||
|
// purpose : Adds components for the given parent to the graph structure
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
void KI_XCAFDoc_AssemblyGraph::addComponents(const TDF_Label& theParent,
|
||||||
|
const Standard_Integer theParentId)
|
||||||
|
{
|
||||||
|
if (!myShapeTool->IsShape(theParent))
|
||||||
|
{
|
||||||
|
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 anIt(theParent); anIt.More(); anIt.Next())
|
||||||
|
{
|
||||||
|
TDF_Label aComponent = anIt.Value();
|
||||||
|
|
||||||
|
// Add component
|
||||||
|
const Standard_Integer aComponentId = addNode(aComponent, theParentId);
|
||||||
|
if (aComponentId == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Protection against deleted empty labels (after expand compounds, for example).
|
||||||
|
Handle(TDataStd_TreeNode) aJumpNode;
|
||||||
|
if (!aComponent.FindAttribute(XCAFDoc::ShapeRefGUID(), aJumpNode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Jump to the referred object (the original).
|
||||||
|
TDF_Label aChildOriginal;
|
||||||
|
if (!aJumpNode.IsNull() && aJumpNode->HasFather())
|
||||||
|
aChildOriginal = aJumpNode->Father()->Label(); // Declaration-level origin.
|
||||||
|
|
||||||
|
if (aChildOriginal.IsNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Add child
|
||||||
|
const Standard_Integer aChildId = addNode(aChildOriginal, aComponentId);
|
||||||
|
if (aChildId == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Process children: add components recursively.
|
||||||
|
addComponents(aChildOriginal, aChildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : addNode
|
||||||
|
// purpose : Adds node into the graph
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
Standard_Integer KI_XCAFDoc_AssemblyGraph::addNode(const TDF_Label& theLabel,
|
||||||
|
const Standard_Integer theParentId)
|
||||||
|
{
|
||||||
|
NodeType aNodeType = NodeType_UNDEFINED;
|
||||||
|
if (myShapeTool->IsAssembly(theLabel))
|
||||||
|
{
|
||||||
|
if (myShapeTool->IsFree(theLabel))
|
||||||
|
aNodeType = NodeType_AssemblyRoot;
|
||||||
|
else
|
||||||
|
aNodeType = NodeType_Subassembly;
|
||||||
|
}
|
||||||
|
else if (myShapeTool->IsComponent(theLabel))
|
||||||
|
{
|
||||||
|
aNodeType = NodeType_Occurrence;
|
||||||
|
}
|
||||||
|
else if (myShapeTool->IsSubShape(theLabel))
|
||||||
|
{
|
||||||
|
aNodeType = NodeType_Subshape;
|
||||||
|
}
|
||||||
|
else if (myShapeTool->IsSimpleShape(theLabel))
|
||||||
|
{
|
||||||
|
aNodeType = NodeType_Part;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aNodeType == NodeType_UNDEFINED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Get ID of the insertion-level node in the abstract assembly graph.
|
||||||
|
const Standard_Integer aChildId = myNodes.Add(theLabel);
|
||||||
|
myNodeTypes.Bind(aChildId, aNodeType);
|
||||||
|
|
||||||
|
if (aNodeType != NodeType_Occurrence)
|
||||||
|
{
|
||||||
|
// Bind usage occurrences.
|
||||||
|
Standard_Integer* aUsageOQPtr = myUsages.ChangeSeek(aChildId);
|
||||||
|
if (aUsageOQPtr == NULL)
|
||||||
|
aUsageOQPtr = myUsages.Bound(aChildId, 1);
|
||||||
|
else
|
||||||
|
++(*aUsageOQPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theParentId > 0)
|
||||||
|
{
|
||||||
|
// Add link
|
||||||
|
TColStd_PackedMapOfInteger* aMapPtr = myAdjacencyMap.ChangeSeek(theParentId);
|
||||||
|
if (aMapPtr == NULL)
|
||||||
|
aMapPtr = myAdjacencyMap.Bound(theParentId, TColStd_PackedMapOfInteger());
|
||||||
|
|
||||||
|
(*aMapPtr).Add(aChildId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aChildId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : Iterator constructor
|
||||||
|
// purpose : Iteration starts from the specifid node.
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
KI_XCAFDoc_AssemblyGraph::Iterator::Iterator(const Handle(KI_XCAFDoc_AssemblyGraph)& theGraph,
|
||||||
|
const Standard_Integer theNode)
|
||||||
|
{
|
||||||
|
Standard_NullObject_Raise_if(theGraph.IsNull(), "Null assembly graph!");
|
||||||
|
Standard_NullObject_Raise_if(theNode < 1, "Node ID must be positive one-based integer!");
|
||||||
|
|
||||||
|
myGraph = theGraph;
|
||||||
|
myCurrentIndex = theNode;
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
// Created on: 2022-05-11
|
||||||
|
// Copyright (c) 2022 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 _KI_XCAFDoc_AssemblyGraph_HeaderFile
|
||||||
|
#define _KI_XCAFDoc_AssemblyGraph_HeaderFile
|
||||||
|
|
||||||
|
#include <NCollection_DataMap.hxx>
|
||||||
|
#include <NCollection_IndexedMap.hxx>
|
||||||
|
#include <Standard.hxx>
|
||||||
|
#include <Standard_Type.hxx>
|
||||||
|
#include <TCollection_AsciiString.hxx>
|
||||||
|
#include <TColStd_PackedMapOfInteger.hxx>
|
||||||
|
#include <TDF_LabelIndexedMap.hxx>
|
||||||
|
|
||||||
|
class TDF_Label;
|
||||||
|
class TDocStd_Document;
|
||||||
|
class XCAFDoc_ShapeTool;
|
||||||
|
|
||||||
|
class KI_XCAFDoc_AssemblyGraph;
|
||||||
|
DEFINE_STANDARD_HANDLE(KI_XCAFDoc_AssemblyGraph, Standard_Transient)
|
||||||
|
|
||||||
|
// Assembly graph.
|
||||||
|
class KI_XCAFDoc_AssemblyGraph : public Standard_Transient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! \brief Type of the graph node.
|
||||||
|
enum NodeType
|
||||||
|
{
|
||||||
|
NodeType_UNDEFINED = 0, //!< Undefined node type.
|
||||||
|
NodeType_AssemblyRoot, //!< Root node.
|
||||||
|
NodeType_Subassembly, //!< Intermediate node.
|
||||||
|
NodeType_Occurrence, //!< Assembly/part occurrence node.
|
||||||
|
NodeType_Part, //!< Leaf node to represent parts.
|
||||||
|
NodeType_Subshape //!< Subshape node.
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief Type definition for graph adjacency matrix.
|
||||||
|
//! This is how parent-component links are realized in the assembly graph.
|
||||||
|
typedef NCollection_DataMap<Standard_Integer, TColStd_PackedMapOfInteger> AdjacencyMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! \brief Graph iterator.
|
||||||
|
class Iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! \brief Accepting the assembly graph and starting node to iterate.
|
||||||
|
//! Iteration starts from the specified node.
|
||||||
|
//! \param [in] theGraph - assembly graph to iterate.
|
||||||
|
//! \param [in] theNode - graph node ID.
|
||||||
|
Standard_EXPORT Iterator(const Handle(KI_XCAFDoc_AssemblyGraph)& theGraph,
|
||||||
|
const Standard_Integer theNode = 1);
|
||||||
|
|
||||||
|
//! Checks if there are more graph nodes to iterate.
|
||||||
|
//! \return true/false.
|
||||||
|
Standard_Boolean More() const
|
||||||
|
{
|
||||||
|
return myCurrentIndex <= myGraph->NbNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \return 1-based ID of the current node.
|
||||||
|
Standard_Integer Current() const
|
||||||
|
{
|
||||||
|
return myCurrentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Moves iterator to the next position.
|
||||||
|
void Next()
|
||||||
|
{
|
||||||
|
++myCurrentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Handle(KI_XCAFDoc_AssemblyGraph) myGraph; //!< Assembly graph to iterate.
|
||||||
|
Standard_Integer myCurrentIndex; //!< Current 1-based node ID.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! \brief Constructs graph from XCAF document.
|
||||||
|
//! Construction of a formal graph will be done immediately.
|
||||||
|
//! \param [in] theDoc - document to iterate.
|
||||||
|
Standard_EXPORT KI_XCAFDoc_AssemblyGraph(const Handle(TDocStd_Document)& theDoc);
|
||||||
|
|
||||||
|
//! \brief Constructs graph from XCAF label.
|
||||||
|
//! Construction of a formal graph will be done immediately. The specified
|
||||||
|
//! label is used as a starting position.
|
||||||
|
//! \param [in] theDoc - document to iterate.
|
||||||
|
//! \param [in] theLabel - starting position.
|
||||||
|
Standard_EXPORT KI_XCAFDoc_AssemblyGraph(const TDF_Label& theLabel);
|
||||||
|
|
||||||
|
//! \return Document shape tool.
|
||||||
|
const Handle(XCAFDoc_ShapeTool)& GetShapeTool() const
|
||||||
|
{
|
||||||
|
return myShapeTool;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns IDs of the root nodes.
|
||||||
|
//! \return IDs of the root nodes.
|
||||||
|
const TColStd_PackedMapOfInteger& GetRoots() const
|
||||||
|
{
|
||||||
|
return myRoots;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Checks whether the assembly graph contains (n1, n2) directed link.
|
||||||
|
//! \param [in] theNode1 - one-based ID of the first node.
|
||||||
|
//! \param [in] theNode2 - one-based ID of the second node.
|
||||||
|
//! \return true/false.
|
||||||
|
Standard_EXPORT Standard_Boolean IsDirectLink(const Standard_Integer theNode1,
|
||||||
|
const Standard_Integer theNode2) const;
|
||||||
|
|
||||||
|
//! \brief Checks whether direct children exist for the given node.
|
||||||
|
//! \param [in] theNode - one-based node ID.
|
||||||
|
//! \return true/false.
|
||||||
|
Standard_Boolean HasChildren(const Standard_Integer theNode) const
|
||||||
|
{
|
||||||
|
return myAdjacencyMap.IsBound(theNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns IDs of child nodes for the given node.
|
||||||
|
//! \param [in] theNode - one-based node ID.
|
||||||
|
//! \return set of child IDs.
|
||||||
|
const TColStd_PackedMapOfInteger& GetChildren(const Standard_Integer theNode) const
|
||||||
|
{
|
||||||
|
return myAdjacencyMap(theNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns the node type from \ref NodeType enum.
|
||||||
|
//! \param [in] theNode - one-based node ID.
|
||||||
|
//! \return node type.
|
||||||
|
//! \sa NodeType
|
||||||
|
Standard_EXPORT NodeType GetNodeType(const Standard_Integer theNode) const;
|
||||||
|
|
||||||
|
//! \brief returns object ID by node ID.
|
||||||
|
//! \param [in] theNode - one-based node ID.
|
||||||
|
//! \return persistent ID.
|
||||||
|
const TDF_Label& GetNode(const Standard_Integer theNode) const
|
||||||
|
{
|
||||||
|
return myNodes(theNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns the unordered set of graph nodes.
|
||||||
|
//! \return graph nodes.
|
||||||
|
const TDF_LabelIndexedMap& GetNodes() const
|
||||||
|
{
|
||||||
|
return myNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns the number of graph nodes.
|
||||||
|
//! \return number of graph nodes.
|
||||||
|
Standard_Integer NbNodes() const
|
||||||
|
{
|
||||||
|
return myNodes.Extent();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns the collection of graph links in the form of adjacency matrix.
|
||||||
|
//! \return graph links.
|
||||||
|
const AdjacencyMap& GetLinks() const
|
||||||
|
{
|
||||||
|
return myAdjacencyMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Returns the number of graph links.
|
||||||
|
//! \return number of graph links.
|
||||||
|
Standard_EXPORT Standard_Integer NbLinks() const;
|
||||||
|
|
||||||
|
//! Returns quantity of part usage occurrences.
|
||||||
|
//! \param [in] theNode - one-based part ID.
|
||||||
|
//! \return usage occurrence quantity.
|
||||||
|
Standard_EXPORT Standard_Integer NbOccurrences(const Standard_Integer theNode) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! Builds graph out of OCAF XDE structure.
|
||||||
|
//! \param [in] theLabel - optional starting position.
|
||||||
|
Standard_EXPORT void buildGraph(const TDF_Label& theLabel);
|
||||||
|
|
||||||
|
//! Adds components for the given parent to the graph structure.
|
||||||
|
//! \param [in] theParent - OCAF label of the parent object.
|
||||||
|
//! \param [in] theParentId - ID of the already registered node representing
|
||||||
|
//! the parent object in the assembly graph
|
||||||
|
//! being populated.
|
||||||
|
Standard_EXPORT void addComponents(const TDF_Label& theParent,
|
||||||
|
const Standard_Integer theParentId);
|
||||||
|
|
||||||
|
//! Adds node into the graph.
|
||||||
|
//! \param [in] theLabel - label at insertion level.
|
||||||
|
//! \param [in] theParentId - parent one-based node IDS.
|
||||||
|
//! \return one-based internal ID of the node.
|
||||||
|
Standard_EXPORT Standard_Integer addNode(const TDF_Label& theLabel,
|
||||||
|
const Standard_Integer theParentId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Handle(XCAFDoc_ShapeTool) myShapeTool; //!< Document shape tool.
|
||||||
|
TColStd_PackedMapOfInteger myRoots; //!< IDs of the root nodes.
|
||||||
|
TDF_LabelIndexedMap myNodes; //!< Maps assembly/part entries to graph node IDs.
|
||||||
|
AdjacencyMap myAdjacencyMap; //!< "Part-of" relations.
|
||||||
|
NCollection_DataMap<Standard_Integer, NodeType> myNodeTypes; //!< Node types.
|
||||||
|
NCollection_DataMap<Standard_Integer,
|
||||||
|
Standard_Integer> myUsages; //!< Occurrences usage.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _KI_XCAFDoc_AssemblyGraph_HeaderFile
|
|
@ -66,10 +66,11 @@
|
||||||
#include <Standard_Version.hxx>
|
#include <Standard_Version.hxx>
|
||||||
#include <TCollection_ExtendedString.hxx>
|
#include <TCollection_ExtendedString.hxx>
|
||||||
#include <TDocStd_Document.hxx>
|
#include <TDocStd_Document.hxx>
|
||||||
|
#include <TDocStd_XLinkTool.hxx>
|
||||||
#include <TDataStd_Name.hxx>
|
#include <TDataStd_Name.hxx>
|
||||||
#include <TDataStd_TreeNode.hxx>
|
#include <TDataStd_TreeNode.hxx>
|
||||||
#include <TDF_LabelSequence.hxx>
|
#include <TDF_LabelSequence.hxx>
|
||||||
#include <TDF_ChildIterator.hxx>
|
#include <TDF_Tool.hxx>
|
||||||
#include <TopExp_Explorer.hxx>
|
#include <TopExp_Explorer.hxx>
|
||||||
#include <TopoDS.hxx>
|
#include <TopoDS.hxx>
|
||||||
#include <XCAFApp_Application.hxx>
|
#include <XCAFApp_Application.hxx>
|
||||||
|
@ -77,6 +78,12 @@
|
||||||
#include <XCAFDoc_DocumentTool.hxx>
|
#include <XCAFDoc_DocumentTool.hxx>
|
||||||
#include <XCAFDoc_ColorTool.hxx>
|
#include <XCAFDoc_ColorTool.hxx>
|
||||||
#include <XCAFDoc_ShapeTool.hxx>
|
#include <XCAFDoc_ShapeTool.hxx>
|
||||||
|
#include <XCAFDoc_Area.hxx>
|
||||||
|
#include <XCAFDoc_Centroid.hxx>
|
||||||
|
#include <XCAFDoc_Location.hxx>
|
||||||
|
#include <XCAFDoc_Volume.hxx>
|
||||||
|
|
||||||
|
#include "KI_XCAFDoc_AssemblyGraph.hxx"
|
||||||
|
|
||||||
#include <BRep_Tool.hxx>
|
#include <BRep_Tool.hxx>
|
||||||
#include <BRepMesh_IncrementalMesh.hxx>
|
#include <BRepMesh_IncrementalMesh.hxx>
|
||||||
|
@ -478,6 +485,113 @@ static TopoDS_Shape getOneShape( Handle( XCAFDoc_ShapeTool ) aShapeTool )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Apply scaling to shapes within theLabel.
|
||||||
|
// Based on XCAFDoc_Editor::RescaleGeometry
|
||||||
|
static Standard_Boolean rescaleShapes( const TDF_Label& theLabel, const gp_XYZ& aScale )
|
||||||
|
{
|
||||||
|
if( theLabel.IsNull() )
|
||||||
|
{
|
||||||
|
Message::SendFail( "Null label." );
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Abs( aScale.X() ) <= gp::Resolution() || Abs( aScale.Y() ) <= gp::Resolution()
|
||||||
|
|| Abs( aScale.Z() ) <= gp::Resolution() )
|
||||||
|
{
|
||||||
|
Message::SendFail( "Scale factor is too small." );
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle( XCAFDoc_ShapeTool ) aShapeTool = XCAFDoc_DocumentTool::ShapeTool( theLabel );
|
||||||
|
if( aShapeTool.IsNull() )
|
||||||
|
{
|
||||||
|
Message::SendFail( "Couldn't find XCAFDoc_ShapeTool attribute." );
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle( KI_XCAFDoc_AssemblyGraph ) aG = new KI_XCAFDoc_AssemblyGraph( theLabel );
|
||||||
|
if( aG.IsNull() )
|
||||||
|
{
|
||||||
|
Message::SendFail( "Couldn't create assembly graph." );
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
Standard_Boolean anIsDone = Standard_True;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
gp_GTrsf aGTrsf;
|
||||||
|
aGTrsf.SetVectorialPart( gp_Mat( aScale.X(), 0, 0,
|
||||||
|
0, aScale.Y(), 0,
|
||||||
|
0, 0, aScale.Z() ) );
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
BRepBuilderAPI_GTransform aBRepTrsf( aGTrsf );
|
||||||
|
|
||||||
|
for( Standard_Integer idx = 1; idx <= aG->NbNodes(); idx++ )
|
||||||
|
{
|
||||||
|
const KI_XCAFDoc_AssemblyGraph::NodeType aNodeType = aG->GetNodeType( idx );
|
||||||
|
|
||||||
|
if( ( aNodeType != KI_XCAFDoc_AssemblyGraph::NodeType_Part )
|
||||||
|
&& ( aNodeType != KI_XCAFDoc_AssemblyGraph::NodeType_Occurrence ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TDF_Label& aLabel = aG->GetNode( idx );
|
||||||
|
|
||||||
|
if( aNodeType == KI_XCAFDoc_AssemblyGraph::NodeType_Part )
|
||||||
|
{
|
||||||
|
const TopoDS_Shape aShape = aShapeTool->GetShape( aLabel );
|
||||||
|
aBRepTrsf.Perform( aShape, Standard_True );
|
||||||
|
if( !aBRepTrsf.IsDone() )
|
||||||
|
{
|
||||||
|
Standard_SStream aSS;
|
||||||
|
TCollection_AsciiString anEntry;
|
||||||
|
TDF_Tool::Entry( aLabel, anEntry );
|
||||||
|
aSS << "Shape " << anEntry << " is not scaled!";
|
||||||
|
Message::SendFail( aSS.str().c_str() );
|
||||||
|
anIsDone = Standard_False;
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
TopoDS_Shape aScaledShape = aBRepTrsf.Shape();
|
||||||
|
aShapeTool->SetShape( aLabel, aScaledShape );
|
||||||
|
|
||||||
|
// Update sub-shapes
|
||||||
|
TDF_LabelSequence aSubshapes;
|
||||||
|
aShapeTool->GetSubShapes( aLabel, aSubshapes );
|
||||||
|
for( TDF_LabelSequence::Iterator anItSs( aSubshapes ); anItSs.More(); anItSs.Next() )
|
||||||
|
{
|
||||||
|
const TDF_Label& aLSs = anItSs.Value();
|
||||||
|
const TopoDS_Shape aSs = aShapeTool->GetShape( aLSs );
|
||||||
|
const TopoDS_Shape aSs1 = aBRepTrsf.ModifiedShape( aSs );
|
||||||
|
aShapeTool->SetShape( aLSs, aSs1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// These attributes will be recomputed eventually, but clear them just in case
|
||||||
|
aLabel.ForgetAttribute( XCAFDoc_Area::GetID() );
|
||||||
|
aLabel.ForgetAttribute( XCAFDoc_Centroid::GetID() );
|
||||||
|
aLabel.ForgetAttribute( XCAFDoc_Volume::GetID() );
|
||||||
|
}
|
||||||
|
else if( aNodeType == KI_XCAFDoc_AssemblyGraph::NodeType_Occurrence )
|
||||||
|
{
|
||||||
|
TopLoc_Location aLoc = aShapeTool->GetLocation( aLabel );
|
||||||
|
gp_Trsf aTrsf = aLoc.Transformation();
|
||||||
|
aTrsf.SetTranslationPart( aTrsf.TranslationPart().Multiplied( aScale ) );
|
||||||
|
XCAFDoc_Location::Set( aLabel, aTrsf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !anIsDone )
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
aShapeTool->UpdateAssemblies();
|
||||||
|
|
||||||
|
return anIsDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
STEP_PCB_MODEL::STEP_PCB_MODEL( const wxString& aPcbName )
|
STEP_PCB_MODEL::STEP_PCB_MODEL( const wxString& aPcbName )
|
||||||
{
|
{
|
||||||
m_app = XCAFApp_Application::GetApplication();
|
m_app = XCAFApp_Application::GetApplication();
|
||||||
|
@ -2510,141 +2624,46 @@ bool STEP_PCB_MODEL::readSTEP( Handle( TDocStd_Document )& doc, const char* fnam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document )& source,
|
TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document ) & source,
|
||||||
Handle( TDocStd_Document )& dest, VECTOR3D aScale )
|
Handle( TDocStd_Document ) & dest, VECTOR3D aScale )
|
||||||
{
|
{
|
||||||
// transfer data from Source into a top level component of Dest
|
// transfer data from Source into a top level component of Dest
|
||||||
gp_GTrsf scale_transform;
|
|
||||||
scale_transform.SetVectorialPart( gp_Mat( aScale.x, 0, 0,
|
|
||||||
0, aScale.y, 0,
|
|
||||||
0, 0, aScale.z ) );
|
|
||||||
BRepBuilderAPI_GTransform brep( scale_transform );
|
|
||||||
|
|
||||||
// s_assy = shape tool for the source
|
// s_assy = shape tool for the source
|
||||||
Handle(XCAFDoc_ShapeTool) s_assy = XCAFDoc_DocumentTool::ShapeTool( source->Main() );
|
Handle( XCAFDoc_ShapeTool ) s_assy = XCAFDoc_DocumentTool::ShapeTool( source->Main() );
|
||||||
|
|
||||||
// retrieve all free shapes within the assembly
|
// retrieve all free shapes within the assembly
|
||||||
TDF_LabelSequence frshapes;
|
TDF_LabelSequence frshapes;
|
||||||
s_assy->GetFreeShapes( frshapes );
|
s_assy->GetFreeShapes( frshapes );
|
||||||
|
|
||||||
// d_assy = shape tool for the destination
|
// d_assy = shape tool for the destination
|
||||||
Handle( XCAFDoc_ShapeTool ) d_assy = XCAFDoc_DocumentTool::ShapeTool ( dest->Main() );
|
Handle( XCAFDoc_ShapeTool ) d_assy = XCAFDoc_DocumentTool::ShapeTool( dest->Main() );
|
||||||
|
|
||||||
// create a new shape within the destination and set the assembly tool to point to it
|
// create a new shape within the destination and set the assembly tool to point to it
|
||||||
TDF_Label component = d_assy->NewShape();
|
TDF_Label d_targetLabel = d_assy->NewShape();
|
||||||
|
|
||||||
int nshapes = frshapes.Length();
|
if( frshapes.Size() == 1 )
|
||||||
int id = 1;
|
|
||||||
Handle( XCAFDoc_ColorTool ) scolor = XCAFDoc_DocumentTool::ColorTool( source->Main() );
|
|
||||||
Handle( XCAFDoc_ColorTool ) dcolor = XCAFDoc_DocumentTool::ColorTool( dest->Main() );
|
|
||||||
TopExp_Explorer dtop;
|
|
||||||
TopExp_Explorer stop;
|
|
||||||
|
|
||||||
while( id <= nshapes )
|
|
||||||
{
|
{
|
||||||
const TDF_Label& s_shapeLabel = frshapes.Value( id );
|
TDocStd_XLinkTool link;
|
||||||
TopoDS_Shape shape = s_assy->GetShape( s_shapeLabel );
|
link.Copy( d_targetLabel, frshapes.First() );
|
||||||
|
}
|
||||||
if( !shape.IsNull() )
|
else
|
||||||
|
{
|
||||||
|
// Rare case
|
||||||
|
for( TDF_Label& s_shapeLabel : frshapes )
|
||||||
{
|
{
|
||||||
Handle( TDataStd_Name ) s_nameAttr;
|
TDF_Label d_component = d_assy->NewShape();
|
||||||
s_shapeLabel.FindAttribute( TDataStd_Name::GetID(), s_nameAttr );
|
|
||||||
|
|
||||||
TCollection_ExtendedString s_labelName =
|
TDocStd_XLinkTool link;
|
||||||
s_nameAttr ? s_nameAttr->Get() : TCollection_ExtendedString();
|
link.Copy( d_component, s_shapeLabel );
|
||||||
|
|
||||||
TopoDS_Shape scaled_shape( shape );
|
d_assy->AddComponent( d_targetLabel, d_component, TopLoc_Location() );
|
||||||
|
|
||||||
if( aScale.x != 1.0 || aScale.y != 1.0 || aScale.z != 1.0 )
|
|
||||||
{
|
|
||||||
brep.Perform( shape, Standard_False );
|
|
||||||
|
|
||||||
if( brep.IsDone() )
|
|
||||||
{
|
|
||||||
scaled_shape = brep.Shape();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ReportMessage( wxT( " * transfertModel(): failed to scale model\n" ) );
|
|
||||||
|
|
||||||
scaled_shape = shape;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TDF_Label d_shapeLabel = d_assy->AddShape( scaled_shape, Standard_False );
|
|
||||||
|
|
||||||
if( s_labelName.Length() > 0 )
|
|
||||||
TDataStd_Name::Set( d_shapeLabel, s_labelName );
|
|
||||||
|
|
||||||
TDF_Label niulab = d_assy->AddComponent( component, d_shapeLabel, TopLoc_Location() );
|
|
||||||
|
|
||||||
// check for per-surface colors
|
|
||||||
stop.Init( shape, TopAbs_FACE );
|
|
||||||
dtop.Init( d_assy->GetShape( niulab ), TopAbs_FACE );
|
|
||||||
|
|
||||||
while( stop.More() && dtop.More() )
|
|
||||||
{
|
|
||||||
Quantity_Color face_color;
|
|
||||||
|
|
||||||
TDF_Label tl;
|
|
||||||
|
|
||||||
// give priority to the base shape's color
|
|
||||||
if( s_assy->FindShape( stop.Current(), tl ) )
|
|
||||||
{
|
|
||||||
if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
|
|
||||||
|| scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
|
|
||||||
|| scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
|
|
||||||
{
|
|
||||||
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
|
|
||||||
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
|
|
||||||
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
|
|
||||||
{
|
|
||||||
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
|
|
||||||
}
|
|
||||||
|
|
||||||
stop.Next();
|
|
||||||
dtop.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for per-solid colors
|
|
||||||
stop.Init( shape, TopAbs_SOLID );
|
|
||||||
dtop.Init( d_assy->GetShape( niulab ), TopAbs_SOLID, TopAbs_FACE );
|
|
||||||
|
|
||||||
while( stop.More() && dtop.More() )
|
|
||||||
{
|
|
||||||
Quantity_Color face_color;
|
|
||||||
|
|
||||||
TDF_Label tl;
|
|
||||||
|
|
||||||
// give priority to the base shape's color
|
|
||||||
if( s_assy->FindShape( stop.Current(), tl ) )
|
|
||||||
{
|
|
||||||
if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
|
|
||||||
|| scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
|
|
||||||
|| scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
|
|
||||||
{
|
|
||||||
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorGen );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
|
|
||||||
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
|
|
||||||
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
|
|
||||||
{
|
|
||||||
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
|
|
||||||
}
|
|
||||||
|
|
||||||
stop.Next();
|
|
||||||
dtop.Next();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++id;
|
if( aScale.x != 1.0 || aScale.y != 1.0 || aScale.z != 1.0 )
|
||||||
};
|
rescaleShapes( d_targetLabel, gp_XYZ( aScale.x, aScale.y, aScale.z ) );
|
||||||
|
|
||||||
return component;
|
return d_targetLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue