From 7b2a67baf6fa06bfd97bb7446ef30004fc3d7e7b Mon Sep 17 00:00:00 2001 From: dkulikov Date: Tue, 17 Jun 2025 17:52:22 +0100 Subject: [PATCH] Impleneted comand ConvertGTD Signed-off-by: sshutina --- src/Draw/TKXSDRAWDE/XSDRAWDE/XSDRAWDE.cxx | 603 ++++++++++++++++++++++ 1 file changed, 603 insertions(+) diff --git a/src/Draw/TKXSDRAWDE/XSDRAWDE/XSDRAWDE.cxx b/src/Draw/TKXSDRAWDE/XSDRAWDE/XSDRAWDE.cxx index 1d3ed8f6ba..601455092e 100644 --- a/src/Draw/TKXSDRAWDE/XSDRAWDE/XSDRAWDE.cxx +++ b/src/Draw/TKXSDRAWDE/XSDRAWDE/XSDRAWDE.cxx @@ -31,6 +31,561 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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& 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 MapLabels( + const NCollection_IndexedDataMap& 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& 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 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 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 DataAsGeomExporter::ExtractGTDPresentations() + const +{ + NCollection_IndexedDataMap aPresentations; + myDimTolTool->GetGDTPresentations(aPresentations); + return aPresentations; +} + +//================================================================================================= + +TopoDS_Compound DataAsGeomExporter::ToCompound( + const NCollection_IndexedDataMap& thePresentations) +{ + if (thePresentations.IsEmpty()) + { + return TopoDS_Compound(); + } + + TopoDS_Compound aCompound; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + for (NCollection_IndexedDataMap::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 DataAsGeomExporter::MapLabels( + const NCollection_IndexedDataMap& thePresentations, + const TDF_Label& theGeometryRoot) +{ + NCollection_DataMap 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::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& theLabelMap) +{ + for (NCollection_DataMap::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); -- 2.39.5