1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

Impleneted comand ConvertGTD

Signed-off-by: sshutina <svetlana.shutina@opencascade.com>
This commit is contained in:
dkulikov
2025-06-17 17:52:22 +01:00
committed by sshutina
parent 3c2774ea5d
commit 7b2a67baf6

View File

@@ -31,6 +31,561 @@
#include <XSControl_WorkSession.hxx>
#include <XSDRAW.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelSequence.hxx>
#include <TDF_Tool.hxx>
#include <XCAFDoc_DimTolTool.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_Dimension.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ViewTool.hxx>
#include <XCAFDoc_View.hxx>
#include <XCAFView_Object.hxx>
namespace
{
// Exports GT&D and view data from the document as geometry.
class DataAsGeomExporter
{
public:
// Constructor that initializes the exporter with a document.
// @param theDoc The document to be used for exporting GT&D and view data as geometry.
DataAsGeomExporter(const Handle(TDocStd_Document)& theDoc);
// Performs the export operation.
// @return True if at least one GT&D or view data was successfully exported,
// false if no data were found or exported.
bool Perform();
// Returns the document associated with this exporter.
// @return The document associated with this exporter.
Handle(TDocStd_Document) GetDocument() const { return myDoc; }
private:
// Extracts GT&D presentations from the document.
// @param theDoc The document from which to extract GT&D presentations.
// @return A map containing the GT&D presentations: labels as keys and shapes as values.
NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape> ExtractGTDPresentations() const;
// Converts the indexed data map of presentations to a compound shape.
// @param thePresentations The indexed data map containing labels and shapes.
// @return A compound shape containing all the shapes from the presentations.
static TopoDS_Compound ToCompound(
const NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>& thePresentations);
// Adds GT&D geometry to the document.
// @param theDoc The document to which the GT&D geometry will be added.
// @param aCompound The compound shape containing the GT&D geometry.
// @return The label of the added GT&D geometry, or an empty label if the operation fails.
TDF_Label AddGTDGeometry(const TopoDS_Compound& aCompound);
// Maps the labels of the GT&D presentations to the new geometry labels.
// @param thePresentations The indexed data map containing labels and shapes of the GT&D
// presentations.
// @param theGeometryRoot The root label of the GT&D geometry in the document.
// @return A data map where keys are original labels of the GT&D and values are new labels of
// their respective geometry representations.
static NCollection_DataMap<TDF_Label, TDF_Label> MapLabels(
const NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>& thePresentations,
const TDF_Label& theGeometryRoot);
// Sets the source GT&D entries, reference shape labels, and name attributes in the geometry
// labels.
// @param theDoc The document to which the GT&D geometry is added.
// @param aLabelMap A map of original labels to new labels for GT&D geometry.
void SetSourceGTDAttributes(const NCollection_DataMap<TDF_Label, TDF_Label>& aLabelMap);
// Retrieve or create a named data attribute for a given label.
// @param theLabel The label for which to retrieve or create the named data attribute.
// @return A handle to the named data attribute associated with the label.
static Handle(TDataStd_NamedData) GetNamedDataAttribute(const TDF_Label& theLabel);
// Retuns a string containing the entries of the labels in the sequence.
// The entries are separated by a space.
// @param theLabels The sequence of labels from which to extract entries.
// @return A string containing the entries of the labels, separated by spaces.
// If theLabels is empty or contains only empty labels, returns an empty string.
static TCollection_ExtendedString GetEntriesString(const TDF_LabelSequence& theLabels);
// Sets the label name attribute for a given label.
// If the name attribute does not exist, it creates a new one.
// @param theLabel The label for which to set the name attribute.
// @param theName The name to set in the label's name attribute.
static void SetLabelName(const TDF_Label& theLabel, const TCollection_ExtendedString& theName);
// For each shape in the document, set the entry as a named data attribute.
// This function iterates through all shapes in the document and sets a named data attribute
// containing the entry of each shape.
// @param theDoc The document containing the shapes.
void SetShapeEntriesAsData();
// Creates a shape for views in the document.
// It consists of top-level label containing children labels, one for each non-null view.
// @return A TDF_Label representing the compound of views. If there are no views, returns an empty
// label.
TDF_Label CreateShapeLabelForViews() const;
// Sets views as geometry in the document.
// This function iterates through all views in the document and creates shape labels for them,
// and sets source view data as named data attributes for new shape labels.
bool SetViewsAsGeometry();
private:
Handle(TDocStd_Document) myDoc; //!< The document associated with this exporter.
TDF_Label myMainLabel; //!< The main label of the document.
Handle(XCAFDoc_ShapeTool) myShapeTool; //!< Tool for handling shapes in the document.
Handle(XCAFDoc_DimTolTool) myDimTolTool; //!< Tool for handling GT&D data in the document.
Handle(XCAFDoc_ViewTool) myViewTool; //!< Tool for handling views in the document.
// clang-format off
// Constants for GT&D geometry and attributes.
static constexpr char* GTD_GEOM_NAME = "gtd_geometry"; //!< Name for GT&D geometry top-level label.
static constexpr char* GTD_SRC_ENTRY = "gtd_src_entry"; //!< Named attribute: source entry.
static constexpr char* GTD_DIM_LINK_1 = "gtd_src_dim_link_first"; //!< Named attribute: first GT&D link.
static constexpr char* GTD_DIM_LINK_2 = "gtd_src_dim_link_second"; //!< Named attribute: second GT&D link.
static constexpr char* GTD_SRC_NAME = "gtd_src_name"; //!< Named attribute: source name.
static constexpr char* GTD_SHAPE_SRC_ENTRY = "source_entry"; //!< Named attribute: source entry for shapes.
// Constants for view geometry.
static constexpr char* VIEW_GEOM_NAME = "view_geometry"; //!< Name for view geometry top-level label.
static constexpr char* VIEW_SRC_ENTRY = "view_src_entry"; //!< Named attribute: source entry for views.
static constexpr char* VIEW_REF_SHAPES = "view_ref_shapes"; //!< Named attribute: reference shapes for views.
static constexpr char* VIEW_REF_GTD = "view_ref_gtd"; //!< Named attribute: reference GT&D for views.
static constexpr char* VIEW_CAM_POS = "view_camera_pos"; //!< Named attribute: camera position for views.
static constexpr char* VIEW_CAM_DIR = "view_camera_dir"; //!< Named attribute: camera direction for views.
static constexpr char* VIEW_CAM_UP = "view_camera_up"; //!< Named attribute: camera up vector for views.
// clang-format on
};
//=================================================================================================
DataAsGeomExporter::DataAsGeomExporter(const Handle(TDocStd_Document)& theDoc)
: myDoc(theDoc)
{
if (myDoc.IsNull())
{
return;
}
// Get main document label.
myMainLabel = myDoc->Main();
if (myMainLabel.IsNull())
{
return;
}
// Initialize tools for shape, dimension tolerance, and view.
myShapeTool = XCAFDoc_DocumentTool::ShapeTool(myMainLabel);
myDimTolTool = XCAFDoc_DocumentTool::DimTolTool(myMainLabel);
myViewTool = XCAFDoc_DocumentTool::ViewTool(myMainLabel);
}
//=================================================================================================
bool DataAsGeomExporter::Perform()
{
if (myShapeTool.IsNull())
{
return false;
}
bool isAnyDataExported = false;
if (!myDimTolTool.IsNull())
{
// Extract GT&D data from the document.
const NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape> aPresentations =
ExtractGTDPresentations();
if (!aPresentations.IsEmpty())
{
isAnyDataExported = true;
// Create a compound to hold all GT&D shapes.
const TopoDS_Compound aCompound = ToCompound(aPresentations);
// Add the compound shape to the document.
const TDF_Label aNewRoot = AddGTDGeometry(aCompound);
// Map new labels to original labels based on shape identity.
const NCollection_DataMap<TDF_Label, TDF_Label> aLabelMap =
MapLabels(aPresentations, aNewRoot);
// Set source GT&D entries in the geometry labels.
SetSourceGTDAttributes(aLabelMap);
// Set entries for all shapes in the document.
SetShapeEntriesAsData();
}
}
if (!myViewTool.IsNull())
{
// Set views as geometry.
isAnyDataExported |= SetViewsAsGeometry();
}
return isAnyDataExported;
}
//==================================================================================================
NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape> DataAsGeomExporter::ExtractGTDPresentations()
const
{
NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape> aPresentations;
myDimTolTool->GetGDTPresentations(aPresentations);
return aPresentations;
}
//=================================================================================================
TopoDS_Compound DataAsGeomExporter::ToCompound(
const NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>& thePresentations)
{
if (thePresentations.IsEmpty())
{
return TopoDS_Compound();
}
TopoDS_Compound aCompound;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aCompound);
for (NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>::Iterator aIt(thePresentations);
aIt.More();
aIt.Next())
{
const TopoDS_Shape& aShape = aIt.Value();
if (!aShape.IsNull())
{
aBuilder.Add(aCompound, aShape);
}
}
return aCompound;
}
//=================================================================================================
TDF_Label DataAsGeomExporter::AddGTDGeometry(const TopoDS_Compound& aCompound)
{
if (aCompound.IsNull())
{
return TDF_Label();
}
// Add the compound shape to the document.
TDF_Label aNewRoot = myShapeTool->AddShape(aCompound, true, false);
if (aNewRoot.IsNull())
{
return TDF_Label();
}
SetLabelName(aNewRoot, TCollection_ExtendedString(GTD_GEOM_NAME));
return aNewRoot;
}
//=================================================================================================
NCollection_DataMap<TDF_Label, TDF_Label> DataAsGeomExporter::MapLabels(
const NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>& thePresentations,
const TDF_Label& theGeometryRoot)
{
NCollection_DataMap<TDF_Label, TDF_Label> aLabelMap;
for (TDF_ChildIterator aChildIt(theGeometryRoot); aChildIt.More(); aChildIt.Next())
{
const TDF_Label aNewLabel = aChildIt.Value();
if (aNewLabel.IsNull())
{
continue;
}
const TopoDS_Shape aNewShape = XCAFDoc_ShapeTool::GetShape(aNewLabel);
for (NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape>::Iterator aIt(thePresentations);
aIt.More();
aIt.Next())
{
const TDF_Label& anOriginalLabel = aIt.Key();
const TopoDS_Shape& anOriginalShape = aIt.Value();
if (anOriginalShape.IsPartner(aNewShape))
{
// If the shapes match, map the new label to the original label
aLabelMap.Bind(anOriginalLabel, aNewLabel);
break;
}
}
}
return aLabelMap;
}
//=================================================================================================
Handle(TDataStd_NamedData) DataAsGeomExporter::GetNamedDataAttribute(const TDF_Label& theLabel)
{
Handle(TDataStd_NamedData) aNamedData;
if (!theLabel.FindAttribute(TDataStd_NamedData::GetID(), aNamedData))
{
// If the named data attribute does not exist, create it.
aNamedData = new TDataStd_NamedData();
// If the named data attribute did not exist, add it to the label.
theLabel.AddAttribute(aNamedData);
}
return aNamedData;
}
//=================================================================================================
TCollection_ExtendedString DataAsGeomExporter::GetEntriesString(const TDF_LabelSequence& theLabels)
{
constexpr char* separator = ", ";
TCollection_ExtendedString aResult;
for (const auto& aLabel : theLabels)
{
if (aLabel.IsNull())
{
continue;
}
TCollection_AsciiString anEntry;
TDF_Tool::Entry(aLabel, anEntry);
if (!anEntry.IsEmpty())
{
if (!aResult.IsEmpty())
{
aResult += separator;
}
aResult += TCollection_ExtendedString(anEntry);
}
}
return aResult;
}
//=================================================================================================
void DataAsGeomExporter::SetLabelName(const TDF_Label& theLabel,
const TCollection_ExtendedString& theName)
{
Handle(TDataStd_Name) aNameAttr;
if (!theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttr))
{
aNameAttr = new TDataStd_Name();
theLabel.AddAttribute(aNameAttr);
}
aNameAttr->Set(theName);
}
//=================================================================================================
void DataAsGeomExporter::SetSourceGTDAttributes(
const NCollection_DataMap<TDF_Label, TDF_Label>& theLabelMap)
{
for (NCollection_DataMap<TDF_Label, TDF_Label>::Iterator aIt(theLabelMap); aIt.More(); aIt.Next())
{
const TDF_Label& aOriginalLabel = aIt.Key();
const TDF_Label& aGeometryLabel = aIt.Value();
if (aOriginalLabel.IsNull() || aGeometryLabel.IsNull())
{
continue;
}
Handle(TDataStd_NamedData) aNamedData = GetNamedDataAttribute(aGeometryLabel);
// 1. Set the source entry as named data attribute.
// Get the original label entry.
TCollection_AsciiString anOriginalLabelEntry;
TDF_Tool::Entry(aOriginalLabel, anOriginalLabelEntry);
// Create and set the named data attribute.
aNamedData->SetString(TCollection_ExtendedString(GTD_SRC_ENTRY), anOriginalLabelEntry);
// 2. set the source dimension links as named data attributes.
// Get the reference shapes for the original label.
TDF_LabelSequence aRefShapeLabelsFirst;
TDF_LabelSequence aRefShapeLabelsSecond;
if (myDimTolTool->GetRefShapeLabel(aOriginalLabel, aRefShapeLabelsFirst, aRefShapeLabelsSecond))
{
// Set the first reference shapes as a named data attribute.
if (const TCollection_ExtendedString aRefShapeLabelsFirstStr =
GetEntriesString(aRefShapeLabelsFirst);
!aRefShapeLabelsFirstStr.IsEmpty())
{
aNamedData->SetString(TCollection_ExtendedString(GTD_DIM_LINK_1), aRefShapeLabelsFirstStr);
}
// Set the second reference shapes as a named data attribute.
if (const TCollection_ExtendedString aRefShapeLabelsSecondStr =
GetEntriesString(aRefShapeLabelsSecond);
!aRefShapeLabelsSecondStr.IsEmpty())
{
aNamedData->SetString(TCollection_ExtendedString(GTD_DIM_LINK_2), aRefShapeLabelsSecondStr);
}
}
// 3. Set the source name attribute as a named data attribute.
if (Handle(TDataStd_Name) aSourceNameAttr;
aOriginalLabel.FindAttribute(TDataStd_Name::GetID(), aSourceNameAttr))
{
// If the name attribute exists, set it as a named data attribute.
TCollection_ExtendedString aNameStr = aSourceNameAttr->Get();
if (!aNameStr.IsEmpty())
{
aNamedData->SetString(TCollection_ExtendedString(GTD_SRC_NAME), aNameStr);
}
}
}
}
//=================================================================================================
void DataAsGeomExporter::SetShapeEntriesAsData()
{
for (TDF_ChildIterator aChildIt(myShapeTool->Label(), true); aChildIt.More(); aChildIt.Next())
{
const TDF_Label& aShapeLabel = aChildIt.Value();
if (aShapeLabel.IsNull())
{
continue;
}
// Get label entry.
TCollection_AsciiString anEntry;
TDF_Tool::Entry(aShapeLabel, anEntry);
// Create and set the named data attribute.
// Get NamedData attribute from the label.
Handle(TDataStd_NamedData) aNamedData = GetNamedDataAttribute(aShapeLabel);
aNamedData->SetString(TCollection_ExtendedString(GTD_SHAPE_SRC_ENTRY), anEntry);
}
}
//=================================================================================================
TDF_Label DataAsGeomExporter::CreateShapeLabelForViews() const
{
TDF_ChildIterator aViewIt(myViewTool->Label(), false);
if (!aViewIt.More())
{
return TDF_Label(); // No views to process.
}
// Create a compound to hold all view shapes.
TopoDS_Compound aCompound;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aCompound);
for (; aViewIt.More(); aViewIt.Next())
{
const TDF_Label& aViewLabel = aViewIt.Value();
if (aViewLabel.IsNull())
{
continue; // Skip null labels
}
// Get the shape associated with the view label.
TopoDS_Compound aSubCompound;
aBuilder.MakeCompound(aSubCompound);
// Add the shape to the compound.
aBuilder.Add(aCompound, aSubCompound);
}
const TDF_Label aShapeLabel = myShapeTool->AddShape(aCompound, true, false);
if (!aShapeLabel.IsNull())
{
SetLabelName(aShapeLabel, TCollection_ExtendedString(VIEW_GEOM_NAME));
}
return aShapeLabel;
}
//=================================================================================================
bool DataAsGeomExporter::SetViewsAsGeometry()
{
TDF_Label aShapeLabel = CreateShapeLabelForViews();
if (aShapeLabel.IsNull())
{
return false; // No views to process or create shape label failed.
}
TDF_ChildIterator aViewIt(myViewTool->Label(), false);
TDF_ChildIterator aShapeIt(aShapeLabel, false);
for (; aViewIt.More() && aShapeIt.More(); aViewIt.Next(), aShapeIt.Next())
{
const TDF_Label& aViewLabel = aViewIt.Value();
if (aViewLabel.IsNull())
{
continue;
}
const TDF_Label& aSubShapeLabel = aShapeIt.Value();
Handle(TDataStd_NamedData) aSubShapeNamedData = GetNamedDataAttribute(aSubShapeLabel);
// All label entry.
TCollection_AsciiString anEntry;
TDF_Tool::Entry(aViewLabel, anEntry);
aSubShapeNamedData->SetString(TCollection_ExtendedString(VIEW_SRC_ENTRY), anEntry);
// Add ref shapes entries as named data attributes.
TDF_LabelSequence aRefShapes;
if (myViewTool->GetRefShapeLabel(aViewLabel, aRefShapes))
{
// Set the reference shapes as a named data attribute.
if (const TCollection_ExtendedString aRefShapesStr = GetEntriesString(aRefShapes);
!aRefShapesStr.IsEmpty())
{
aSubShapeNamedData->SetString(TCollection_ExtendedString(VIEW_REF_SHAPES), aRefShapesStr);
}
}
// Add ref GDT labels entries as named data attributes.
TDF_LabelSequence aGDTLabels;
if (myViewTool->GetRefGDTLabel(aViewLabel, aGDTLabels))
{
// Set the GDT labels as a named data attribute.
if (const TCollection_ExtendedString aGDTLabelsStr = GetEntriesString(aGDTLabels);
!aGDTLabelsStr.IsEmpty())
{
aSubShapeNamedData->SetString(TCollection_ExtendedString(VIEW_REF_GTD), aGDTLabelsStr);
}
}
// Add camera position as a named data attribute.
Handle(XCAFDoc_View) aViewAttr;
if (aViewLabel.FindAttribute(XCAFDoc_View::GetID(), aViewAttr))
{
const Handle(XCAFView_Object) aViewObj = aViewAttr->GetObject();
// Position of the camera in the view.
const gp_Pnt aCameraPos = aViewObj->ProjectionPoint();
Handle(TColStd_HArray1OfReal) aCameraPosArray = new TColStd_HArray1OfReal(1, 3);
aCameraPosArray->SetValue(1, aCameraPos.X());
aCameraPosArray->SetValue(2, aCameraPos.Y());
aCameraPosArray->SetValue(3, aCameraPos.Z());
aSubShapeNamedData->SetArrayOfReals(TCollection_ExtendedString(VIEW_CAM_POS),
aCameraPosArray);
// Direction of the camera in the view.
const gp_Dir aCameraDir = aViewObj->ViewDirection();
Handle(TColStd_HArray1OfReal) aCameraDirArray = new TColStd_HArray1OfReal(1, 3);
aCameraDirArray->SetValue(1, aCameraDir.X());
aCameraDirArray->SetValue(2, aCameraDir.Y());
aCameraDirArray->SetValue(3, aCameraDir.Z());
aSubShapeNamedData->SetArrayOfReals(TCollection_ExtendedString(VIEW_CAM_DIR),
aCameraDirArray);
// Up direction of the camera in the view.
const gp_Dir anUpDir = aViewObj->UpDirection();
Handle(TColStd_HArray1OfReal) anUpDirArray = new TColStd_HArray1OfReal(1, 3);
anUpDirArray->SetValue(1, anUpDir.X());
anUpDirArray->SetValue(2, anUpDir.Y());
anUpDirArray->SetValue(3, anUpDir.Z());
aSubShapeNamedData->SetArrayOfReals(TCollection_ExtendedString(VIEW_CAM_UP), anUpDirArray);
}
}
return true;
}
} // namespace
//=================================================================================================
static Standard_Integer DumpConfiguration(Draw_Interpretor& theDI,
@@ -355,6 +910,44 @@ static Standard_Integer WriteFile(Draw_Interpretor& theDI,
//=================================================================================================
static Standard_Integer ConvertGTD(Draw_Interpretor& theDI,
Standard_Integer theNbArgs,
const char** theArgVec)
{
if (theNbArgs != 3)
{
theDI.PrintHelp(theArgVec[0]);
return 1;
}
const TCollection_AsciiString aSourcePath = theArgVec[1];
const TCollection_AsciiString anOutputPath = theArgVec[2];
Handle(TDocStd_Document) aDocument;
DDocStd::GetApplication()->NewDocument(TCollection_ExtendedString("BinXCAF"), aDocument);
if (aDocument.IsNull())
{
return 1;
}
const Handle(DE_Wrapper) aDEWrapper = DE_Wrapper::GlobalWrapper()->Copy();
if (!aDEWrapper->Read(aSourcePath, aDocument))
{
return 1;
}
// Create a DataAsGeomExporter instance to handle GT&D data extraction and geometry creation.
DataAsGeomExporter aExporter(aDocument);
if (aExporter.Perform())
{
aDEWrapper->Write(anOutputPath, aExporter.GetDocument());
}
return 0;
}
//=================================================================================================
void XSDRAWDE::Factory(Draw_Interpretor& theDI)
{
static Standard_Boolean aIsActivated = Standard_False;
@@ -426,6 +1019,16 @@ void XSDRAWDE::Factory(Draw_Interpretor& theDI)
WriteFile,
aGroup);
theDI.Add("ConvertGTD",
"ConvertGTD sourcePath outputPath\n"
"\n\t\t: Reads GT&D presentations from the source file and saves them as a "
"compound shape in the output file."
"\n\t\t: 'sourcePath' - path to the source file containing GT&D presentations"
"\n\t\t: 'outputPath' - path to the output file where GT&D geometry will be saved",
__FILE__,
ConvertGTD,
aGroup);
// Load XSDRAW session for pilot activation
XSDRAW::LoadDraw(theDI);