]> OCCT Git - occt.git/commitdiff
0033737: Data Exchange, XCAF - Implementing filter tree functionality CR0-Hybrid-780-2024061201 CR0-Hybrid-780_1
authordpasukhi <dmitry.pasukhin@opencascade.com>
Tue, 11 Jun 2024 16:38:29 +0000 (17:38 +0100)
committeroan <oan@opencascade.com>
Tue, 11 Jun 2024 16:38:29 +0000 (17:38 +0100)
Implemented base functionality to filter tree with input label to keep.

src/XCAFDoc/XCAFDoc_Editor.cxx
src/XCAFDoc/XCAFDoc_Editor.hxx
src/XDEDRAW/XDEDRAW_Common.cxx
tests/bugs/xde/bug33737 [new file with mode: 0644]

index e76fcedf4d728ed501a4ca0f3344932495cef2f2..0a7b359be65bfa4f5b494f33b720eb5597b0256d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <BRep_Builder.hxx>
 #include <BRepBuilderAPI_Transform.hxx>
+#include <NCollection_IncAllocator.hxx>
 #include <Message.hxx>
 #include <XCAFDoc.hxx>
 #include <XCAFDimTolObjects_DatumObject.hxx>
@@ -582,12 +583,119 @@ static Standard_Boolean shouldRescaleAndCheckRefLabels(
   return aShouldRescale;
 }
 
+//=======================================================================
+//function : GetDownRelatedShapeLabels
+//purpose  :
+//=======================================================================
+bool XCAFDoc_Editor::GetDownRelatedShapeLabels(const TDF_Label& theLabel,
+                                               TDF_LabelMap& theRelatedLabels)
+{
+  if (theLabel.IsNull() || !XCAFDoc_ShapeTool::IsShape(theLabel))
+  {
+    return false;
+  }
+  if (theRelatedLabels.Contains(theLabel))
+  {
+    return true;
+  }
+  theRelatedLabels.Add(theLabel);
+  if (XCAFDoc_ShapeTool::IsAssembly(theLabel) ||
+      XCAFDoc_ShapeTool::IsSimpleShape(theLabel))
+  {
+    for(TDF_ChildIterator aChildIter(theLabel); aChildIter.More(); aChildIter.Next())
+    {
+      const TDF_Label& aChildLabel = aChildIter.Value();
+      GetDownRelatedShapeLabels(aChildLabel, theRelatedLabels);
+    }
+  }
+  if (XCAFDoc_ShapeTool::IsReference(theLabel))
+  {
+    TDF_Label aRefLabel;
+    XCAFDoc_ShapeTool::GetReferredShape(theLabel, aRefLabel);
+    GetDownRelatedShapeLabels(aRefLabel, theRelatedLabels);
+  }
+  return true;
+}
+
+//=======================================================================
+//function : GetUpRelatedShapeLabels
+//purpose  :
+//=======================================================================
+bool XCAFDoc_Editor::GetUpRelatedShapeLabels(const TDF_Label& theLabel,
+                                             TDF_LabelMap& theRelatedLabels)
+{
+  if (theLabel.IsNull() || !XCAFDoc_ShapeTool::IsShape(theLabel))
+  {
+    return false;
+  }
+  if (theRelatedLabels.Contains(theLabel))
+  {
+    return true;
+  }
+  theRelatedLabels.Add(theLabel);
+  if (XCAFDoc_ShapeTool::IsSubShape(theLabel) ||
+      XCAFDoc_ShapeTool::IsComponent(theLabel))
+  {
+    TDF_Label aFatherLabel = theLabel.Father();
+    GetUpRelatedShapeLabels(aFatherLabel, theRelatedLabels);
+  }
+  else
+  {
+    TDF_LabelSequence aUsers;
+    XCAFDoc_ShapeTool::GetUsers(theLabel, aUsers);
+    if (!aUsers.IsEmpty())
+    {
+      for (TDF_LabelSequence::Iterator aUserIter(aUsers); aUserIter.More(); aUserIter.Next())
+      {
+        const TDF_Label& aUserLabel = aUserIter.Value();
+        GetUpRelatedShapeLabels(aUserLabel, theRelatedLabels);
+      }
+    }
+  }
+  return true;
+}
+
+//=======================================================================
+//function : FilterTree
+//purpose  :
+//=======================================================================
+bool XCAFDoc_Editor::FilterTree(const Handle(XCAFDoc_ShapeTool)& theShapeTool,
+                                const TDF_LabelMap& theLabelsToKeep)
+{
+  if (theLabelsToKeep.IsEmpty())
+  {
+    return false;
+  }
+  Handle(NCollection_BaseAllocator) anAllocator = new NCollection_IncAllocator();
+  TDF_LabelMap aLabelsToKeep (theLabelsToKeep.Size(), anAllocator);
+  for (TDF_LabelMap::Iterator aLabelIter (theLabelsToKeep); aLabelIter.More(); aLabelIter.Next())
+  {
+    GetDownRelatedShapeLabels (aLabelIter.Key(), aLabelsToKeep);
+  }
+  TDF_LabelMap aInternalLabels (1, anAllocator);
+  for (TDF_LabelMap::Iterator aLabelIter (theLabelsToKeep); aLabelIter.More(); aLabelIter.Next())
+  {
+    GetUpRelatedShapeLabels (aLabelIter.Key(), aInternalLabels);
+    aLabelsToKeep.Unite(aInternalLabels);
+    aInternalLabels.Clear(false);
+  }
+  for(TDF_ChildIterator aLabelIter (theShapeTool->Label(), true); aLabelIter.More(); aLabelIter.Next())
+  {
+    const TDF_Label& aLabel = aLabelIter.Value();
+    if (!aLabelsToKeep.Contains (aLabel))
+    {
+      aLabel.ForgetAllAttributes (Standard_False);
+    }
+  }
+  theShapeTool->UpdateAssemblies();
+  return true;
+}
+
 //=======================================================================
 //function : RescaleGeometry
 //purpose  : Applies geometrical scale to all assembly parts, component
 //           locations and related attributes
 //=======================================================================
-
 Standard_Boolean XCAFDoc_Editor::RescaleGeometry(const TDF_Label& theLabel,
                                                  const Standard_Real theScaleFactor,
                                                  const Standard_Boolean theForceIfNotRoot)
index 832d522d2d297116c5834f4707f11e07ac38ed8c..9873de31d6f5d79660178aaf8cd7ba6ee1adffc6 100644 (file)
@@ -19,6 +19,7 @@
 #include <TDataStd_Name.hxx>
 #include <TDF_Label.hxx>
 #include <TDF_LabelDataMap.hxx>
+#include <TDF_LabelMap.hxx>
 #include <TDF_LabelSequence.hxx>
 
 class XCAFDoc_VisMaterial;
@@ -95,6 +96,32 @@ public:
                                             const Standard_Boolean theToCopyVisMaterial = Standard_True,
                                             const Standard_Boolean theToCopyAttributes = Standard_True);
 
+  //! Gets shape labels that has down relation with the input label.
+  //! @param[in] theLabel input label
+  //! @param[out] theRelatedLabels output labels
+  //! @return true if labels successfully extracted
+  Standard_EXPORT static bool GetUpRelatedShapeLabels(const TDF_Label& theLabel,
+                                                      TDF_LabelMap& theRelatedLabels);
+
+  //! Gets shape labels that has up relation with the input label.
+  //! @param[in] theLabel input label
+  //! @param[out] theRelatedLabels output labels
+  //! @return true if labels successfully extracted
+  Standard_EXPORT static bool GetDownRelatedShapeLabels(const TDF_Label& theLabel,
+                                                        TDF_LabelMap& theRelatedLabels);
+  //! Filters original shape tree with keeping structure.
+  //! The result will include the full label hierarchy lower then input labels.
+  //! Any higher hierarchy labels will be filtered to keep only necessary labels.
+  //! All not related shape labels with input will be cleared (all attributes will be removed).
+  //!
+  //! The result impact directly into original document and existed shape labels.
+  //!
+  //! @param[in] theShapeTool shape tool to extract from
+  //! @param[in] theLabelsToKeep labels to keep
+  //! @return true if the tree was filtered successfully.
+  Standard_EXPORT static bool FilterTree(const Handle(XCAFDoc_ShapeTool)& theShapeTool,
+                                         const TDF_LabelMap& theLabelsToKeep);
+
   //! Applies geometrical scaling to the following assembly components:
   //! - part geometry
   //! - sub-assembly/part occurrence location
index d4f9e82d99dcd3321175db0201df4e62cc3c65ec..65ff96871900b064d1909817a8bc010377857ae5 100644 (file)
@@ -263,6 +263,53 @@ static Standard_Integer Extract(Draw_Interpretor& theDI,
   return 0;
 }
 
+//=======================================================================
+//function : Extract
+//purpose  :
+//=======================================================================
+static Standard_Integer Filter(Draw_Interpretor& theDI,
+                                Standard_Integer theNbArgs,
+                                const char** theArgVec)
+{
+  if (theNbArgs < 3)
+  {
+    theDI << "Use: " << theArgVec[0] << "Doc label1 label2 ...\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  DDocStd::GetDocument(theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    theDI << "Error " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+  TDF_LabelMap aSrcShapes;
+  for (Standard_Integer anArgInd = 2; anArgInd < theNbArgs; anArgInd++)
+  {
+    TDF_Label aSrcLabel;
+    TDF_Tool::Label(aDoc->GetData(), theArgVec[anArgInd], aSrcLabel);
+    if (aSrcLabel.IsNull() || !XCAFDoc_ShapeTool::IsShape(aSrcLabel))
+    {
+      theDI << "[" << theArgVec[anArgInd] << "] is not valid shape label\n";
+      return 1;
+    }
+    aSrcShapes.Add(aSrcLabel);
+  }
+  if (aSrcShapes.IsEmpty())
+  {
+    theDI << "Error: No Shapes to keep\n";
+    return 1;
+  }
+  Handle(XCAFDoc_ShapeTool) aShTool = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main());
+  if (!XCAFDoc_Editor::FilterTree(aShTool, aSrcShapes))
+  {
+    theDI << "Error: Cannot filter tree. Document can be corrupted\n";
+    return 1;
+  }
+  return 0;
+}
+
 //=======================================================================
 //function : InitCommands
 //purpose  :
@@ -288,7 +335,9 @@ void XDEDRAW_Common::InitCommands(Draw_Interpretor& theDI)
   theDI.Add("XExtract", "XExtract dstDoc [dstAssmblSh] srcDoc srcLabel1 srcLabel2 ...\t"
             "Extracts given srcLabel1 srcLabel2 ... from srcDoc into given Doc or assembly shape",
             __FILE__, Extract, aGroup);
-
+  theDI.Add("XFilter", "XFilter Doc label1 label2 ...\t"
+            "Removes not related labels with input labels from original document. Hierarchical structure is kept",
+            __FILE__, Filter, aGroup);
   // Load XSDRAW session for pilot activation
   XSDRAW::LoadDraw(theDI);
 }
diff --git a/tests/bugs/xde/bug33737 b/tests/bugs/xde/bug33737
new file mode 100644 (file)
index 0000000..dde1d5f
--- /dev/null
@@ -0,0 +1,61 @@
+puts "========"
+puts " 0033737: Data Exchange, XCAF - Implementing filter tree functionality"
+puts "========"
+
+pload DE OCAF
+
+Close D_orig D_part1 D_part2 D_part3 D_part4 D_part5 -silent
+
+# get original shape
+Close D_orig -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_orig
+XGetOneShape sh_orig D_orig
+
+# any bolt inside assembly
+Close D_orig D_part1 -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_part1
+XFilter D_part1 "0:1:1:7"
+XGetOneShape sh1 D_part1
+
+# rod
+Close D_part1 D_part2 -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_part2
+XFilter D_part2 "0:1:1:2:3"
+XGetOneShape sh2 D_part2
+
+# plate
+Close D_part2 D_part3 -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_part3
+XFilter D_part3 "0:1:1:1:3"
+XGetOneShape sh3 D_part3
+
+# any nuts
+Close D_part3 D_part4 -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_part4
+XFilter D_part4 "0:1:1:3"
+XGetOneShape sh4 D_part4
+
+# any nuts
+Close D_part4 D_part5 -silent
+XOpen [locate_data_file bug28905_as1-oc-214.xbf] D_part5
+XFilter D_part5 "0:1:1:8"
+XGetOneShape sh5 D_part5
+
+Close D_part5 -silent
+
+compound sh1 sh2 sh3 sh4 sh5 comp
+
+set props_orig [vprops sh_orig]
+set props_comp [vprops comp]
+
+checkprops sh_orig -equal comp
+
+if { ![regexp {Center of gravity[^0-9=]+= +([-0-9.+eE]+)[^0-9=]+= +([-0-9.+eE]+)[^0-9=]+= +([-0-9.+eE]+)} $props_orig full x_orig y_orig z_orig] } {
+  puts "Error: Problem with properties calculation"
+}
+if { ![regexp {Center of gravity[^0-9=]+= +([-0-9.+eE]+)[^0-9=]+= +([-0-9.+eE]+)[^0-9=]+= +([-0-9.+eE]+)} $props_comp full x_comp y_comp z_comp] } {
+  puts "Error: Problem with properties calculation"
+}
+if {$x_orig != $x_comp || $y_orig != $y_comp || $z_orig != $z_comp} {
+  puts "Error: Different center of gravity"
+}