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/step/exporter_step.cpp
|
||||
exporters/step/step_pcb_model.cpp
|
||||
exporters/step/KI_XCAFDoc_AssemblyGraph.cxx
|
||||
exporters/exporter_vrml.cpp
|
||||
exporters/place_file_exporter.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 <TCollection_ExtendedString.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <TDocStd_XLinkTool.hxx>
|
||||
#include <TDataStd_Name.hxx>
|
||||
#include <TDataStd_TreeNode.hxx>
|
||||
#include <TDF_LabelSequence.hxx>
|
||||
#include <TDF_ChildIterator.hxx>
|
||||
#include <TDF_Tool.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <XCAFApp_Application.hxx>
|
||||
|
@ -77,6 +78,12 @@
|
|||
#include <XCAFDoc_DocumentTool.hxx>
|
||||
#include <XCAFDoc_ColorTool.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 <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 )
|
||||
{
|
||||
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,
|
||||
Handle( TDocStd_Document )& dest, VECTOR3D aScale )
|
||||
TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document ) & source,
|
||||
Handle( TDocStd_Document ) & dest, VECTOR3D aScale )
|
||||
{
|
||||
// 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
|
||||
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
|
||||
TDF_LabelSequence frshapes;
|
||||
s_assy->GetFreeShapes( frshapes );
|
||||
|
||||
// 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
|
||||
TDF_Label component = d_assy->NewShape();
|
||||
TDF_Label d_targetLabel = d_assy->NewShape();
|
||||
|
||||
int nshapes = frshapes.Length();
|
||||
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 )
|
||||
if( frshapes.Size() == 1 )
|
||||
{
|
||||
const TDF_Label& s_shapeLabel = frshapes.Value( id );
|
||||
TopoDS_Shape shape = s_assy->GetShape( s_shapeLabel );
|
||||
|
||||
if( !shape.IsNull() )
|
||||
{
|
||||
Handle( TDataStd_Name ) s_nameAttr;
|
||||
s_shapeLabel.FindAttribute( TDataStd_Name::GetID(), s_nameAttr );
|
||||
|
||||
TCollection_ExtendedString s_labelName =
|
||||
s_nameAttr ? s_nameAttr->Get() : TCollection_ExtendedString();
|
||||
|
||||
TopoDS_Shape scaled_shape( shape );
|
||||
|
||||
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();
|
||||
TDocStd_XLinkTool link;
|
||||
link.Copy( d_targetLabel, frshapes.First() );
|
||||
}
|
||||
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() )
|
||||
// Rare case
|
||||
for( TDF_Label& s_shapeLabel : frshapes )
|
||||
{
|
||||
Quantity_Color face_color;
|
||||
TDF_Label d_component = d_assy->NewShape();
|
||||
|
||||
TDF_Label tl;
|
||||
TDocStd_XLinkTool link;
|
||||
link.Copy( d_component, s_shapeLabel );
|
||||
|
||||
// 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();
|
||||
d_assy->AddComponent( d_targetLabel, d_component, TopLoc_Location() );
|
||||
}
|
||||
}
|
||||
|
||||
++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