Salome HOME
NPAL16588: Bug in GetInPlace method. T15881 T32x_16Aug2007_16h00m
authorjfa <jfa@opencascade.com>
Wed, 25 Jul 2007 07:07:07 +0000 (07:07 +0000)
committerjfa <jfa@opencascade.com>
Wed, 25 Jul 2007 07:07:07 +0000 (07:07 +0000)
idl/GEOM_Gen.idl
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
src/GEOM_I/GEOM_IShapesOperations_i.cc
src/GEOM_I/GEOM_IShapesOperations_i.hh
src/GEOM_SWIG/GEOM_TestOthers.py
src/GEOM_SWIG/geompy.py

index bed796e59c3461e80d44e73aa3fbaa1c033c3c37..118971724068050cac991dc835098a36e9c2858d 100644 (file)
@@ -1311,7 +1311,7 @@ module GEOM
                             in shape_state theState);
 
     /*!
-     *  Get sub-shape(s) of theShapeWhere, which are
+     *  Get sub-shape(s) of \a theShapeWhere, which are
      *  coincident with \a theShapeWhat or could be a part of it.
      *  \param theShapeWhere Shape to find sub-shapes of.
      *  \param theShapeWhat Shape, specifying what to find.
@@ -1320,6 +1320,23 @@ module GEOM
     GEOM_Object GetInPlace (in GEOM_Object theShapeWhere,
                            in GEOM_Object theShapeWhat);
 
+    /*!
+     *  Get sub-shape(s) of \a theShapeWhere, which are
+     *  coincident with \a theShapeWhat or could be a part of it.
+     *
+     *  Implementation of this method is based on a saved history of an operation,
+     *  produced \a theShapeWhere. The \a theShapeWhat must be among this operation's
+     *  arguments (an argument shape or a sub-shape of an argument shape).
+     *  The operation could be the Partition or one of boolean operations,
+     *  performed on simple shapes (not on compounds).
+     *
+     *  \param theShapeWhere Shape to find sub-shapes of.
+     *  \param theShapeWhat Shape, specifying what to find.
+     *  \return Group of all found sub-shapes or a single found sub-shape.
+     */
+    GEOM_Object GetInPlaceByHistory (in GEOM_Object theShapeWhere,
+                                    in GEOM_Object theShapeWhat);
+
     /*!
      *  Get sub-shape of theShapeWhere, which are
      *  coincident with \a theShapeWhat that can either SOLID, FACE, EDGE or VERTEX.
index 957c1840add7f47913267f15c7bd0b6cac2953f2..8f698def7504c7579c7ba8b6eb66c69085044dbd 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+// File      : GEOMImpl_IShapesOperations.cxx
+// Created   : 
+// Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
+// Project   : SALOME
+// $Header$
 
 #include <Standard_Stream.hxx>
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
+// Includes added for GetInPlace algorithm improvement
+
+#include <GEOMImpl_MeasureDriver.hxx>
+#include <GEOMImpl_IMeasure.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+
+#include <BRepClass_FaceClassifier.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+#include <Precision.hxx>
+
 //=============================================================================
 /*!
  *   constructor:
@@ -2408,7 +2423,7 @@ Handle(TColStd_HSequenceOfInteger)
 
 //=============================================================================
 /*!
- *  GetInPlace
+ *  GetInPlaceOfShape
  */
 //=============================================================================
 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
@@ -2530,7 +2545,182 @@ static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
   return isFound;
 }
 
-Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
+//=============================================================================
+/*!
+ *  GetShapeProperties
+ */
+//=============================================================================
+
+void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
+                                                     gp_Pnt & aVertex )
+{
+  GProp_GProps SProps, VProps;
+  gp_Pnt aCenterMass;
+  TopoDS_Shape aPntShape;
+  Standard_Real aShapeSize;
+
+  BRepGProp::VolumeProperties(aShape, VProps);
+  aCenterMass = VProps.CentreOfMass();
+  aShapeSize  = VProps.Mass();
+  if (aShape.ShapeType() == TopAbs_FACE) {
+    BRepGProp::SurfaceProperties(aShape, SProps);
+    aCenterMass = SProps.CentreOfMass();
+    aShapeSize  = SProps.Mass();
+  }
+
+  aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
+  aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
+  tab[0] = aVertex.X();
+  tab[1] = aVertex.Y();
+  tab[2] = aVertex.Z();
+  tab[3] = aShapeSize;
+  return;
+}
+
+//=============================================================================
+/*!
+ *  GetInPlace
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
+                                                            Handle(GEOM_Object) theShapeWhat)
+{
+  SetErrorCode(KO);
+
+  if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
+
+  TopoDS_Shape aWhere = theShapeWhere->GetValue();
+  TopoDS_Shape aWhat  = theShapeWhat->GetValue();
+
+  if (aWhere.IsNull() || aWhat.IsNull()) {
+    SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
+    return NULL;
+  }
+
+  Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
+  if (aWhereFunction.IsNull()) {
+    SetErrorCode("Error: aWhereFunction is Null.");
+    return NULL;
+  }
+
+  TopTools_IndexedMapOfShape aWhereIndices;
+  TopExp::MapShapes(aWhere, aWhereIndices);
+
+  TColStd_ListOfInteger aModifiedList;
+  Standard_Integer aWhereIndex;
+  Handle(TColStd_HArray1OfInteger) aModifiedArray;
+  Handle(GEOM_Object) aResult;
+
+  bool isFound = false;
+  Standard_Integer iType = TopAbs_SOLID;
+  Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
+  Standard_Real    tab_aWhat[4],    tab_aWhere[4];
+  Standard_Real    dl_l = 1e-3;
+  Standard_Real    min_l, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
+  gp_Pnt           aPnt, aPnt_aWhat;
+  GProp_GProps     aProps;
+
+  // 2D or 3D shapes
+  if ( aWhat.ShapeType() == TopAbs_COMPOUND  ||
+       aWhat.ShapeType() == TopAbs_SHELL     ||
+       aWhat.ShapeType() == TopAbs_COMPSOLID ) {
+    TopExp_Explorer Exp( aWhat, TopAbs_ShapeEnum( iType ) );
+    if ( ! Exp.More() ) iType = TopAbs_FACE;
+  }
+  else if ( aWhat.ShapeType() == TopAbs_FACE )
+    iType = TopAbs_FACE;
+
+  TopExp_Explorer Exp_aWhat( aWhat,   TopAbs_ShapeEnum( iType ) );
+  TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
+  TopExp_Explorer Exp_Edge( aWhere,   TopAbs_EDGE );
+
+  // Find the shortest edge in theShapeWhere shape
+  for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
+    BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
+    if ( ! nbEdge ) min_l = aProps.Mass();
+    if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
+  }
+
+  // Compute tolerances
+  Tol_1D = dl_l * min_l;
+  Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
+  Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
+
+  Tol_Mass = Tol_3D;
+  if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
+
+  // Compute the ShapeWhat Mass
+  for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
+    if      ( iType == TopAbs_SOLID ) BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps);
+    else if ( iType == TopAbs_FACE )  BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
+    aWhat_Mass += aProps.Mass();
+  }
+
+  // Finding the Sub-ShapeWhere
+  for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
+    GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
+    for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
+      GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
+      if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
+        isFound = true;
+      else if ( tab_aWhat[3] - ( tab_aWhere[3] > Tol_Mass) ) {
+        BRepClass3d_SolidClassifier SC_aWhere (Exp_aWhere.Current(), aPnt, Precision::Confusion());
+        BRepClass3d_SolidClassifier SC_aWhat  (Exp_aWhat.Current(),  aPnt, Precision::Confusion());
+        // Block construction 3D
+        if      ( SC_aWhere.State() == TopAbs_IN && SC_aWhat.State() == TopAbs_IN ) isFound = true;
+        // Block construction 2D
+        else if ( SC_aWhere.State() == TopAbs_ON && SC_aWhat.State() == TopAbs_ON ) isFound = true;
+      }
+      if ( isFound ) {
+        aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
+        aModifiedList.Append(aWhereIndex);
+        aWhere_Mass += tab_aWhere[3];
+        isFound = false;
+        break;
+      }
+    }
+    if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
+  }
+
+  aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
+  TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
+  for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
+    aModifiedArray->SetValue(imod, anIterModif.Value());
+
+  //Add a new object
+  aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
+  if (aResult.IsNull()) {
+    SetErrorCode("Error in algorithm: result found, but cannot be returned.");
+    return NULL;
+  }
+
+  if (aModifiedArray->Length() > 1) {
+    //Set a GROUP type
+    aResult->SetType(GEOM_GROUP);
+
+    //Set a sub shape type
+    TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
+    TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
+
+    TDF_Label aFreeLabel = aResult->GetFreeLabel();
+    TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
+  }
+
+  //Make a Python command
+  Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
+
+  GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
+    << theShapeWhere << ", " << theShapeWhat << ")";
+
+  SetErrorCode(OK);
+  return aResult;
+}
+
+//=======================================================================
+//function : GetInPlaceByHistory
+//purpose  :
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
                                           (Handle(GEOM_Object) theShapeWhere,
                                            Handle(GEOM_Object) theShapeWhat)
 {
index b345677552a4efe7fc9e42bafd5348f3d89cb4af..1e8cdc2c80a992099dbfac4be5e73e5cf41eae12 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
+//=============================================================================
+// File      : GEOMImpl_IShapesOperations.hxx
+// Created   : 
+// Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
+// Project   : SALOME
+// Copyright : CEA 2003
+// $Header$
+//=============================================================================
 #ifndef _GEOMImpl_IShapesOperations_HXX_
 #define _GEOMImpl_IShapesOperations_HXX_
 
@@ -32,6 +39,8 @@
 #include <list>
 #include <Handle_Geom_Surface.hxx>
 
+#include <gp_Pnt.hxx>
+
 class GEOM_Engine;
 class Handle(GEOM_Object);
 class Handle(TColStd_HArray1OfInteger);
@@ -206,9 +215,14 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
                                             Handle(GEOM_Object)    theCenter,
                                             const Standard_Real    theRadius);
 
+  void GetShapeProperties(const TopoDS_Shape aShape, Standard_Real propertiesArray[], gp_Pnt & aPnt);
+
   Standard_EXPORT Handle(GEOM_Object) GetInPlace (Handle(GEOM_Object) theShapeWhere,
                                                   Handle(GEOM_Object) theShapeWhat);
 
+  Standard_EXPORT Handle(GEOM_Object) GetInPlaceByHistory (Handle(GEOM_Object) theShapeWhere,
+                                                           Handle(GEOM_Object) theShapeWhat);
+
   /*!
    * \brief Searches a shape equal to theWhat in the context of theWhere
    * \param theShapeWhere - a context shap
index 7e022a0c31e155993476d8351cf9af55515540fa..32dd0f0236dd5498b79ef4ea19e026269cf48615 100644 (file)
@@ -1325,6 +1325,41 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlace
   return GetObject(anObject);
 }
 
+//=============================================================================
+/*!
+ *  GetInPlaceByHistory
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlaceByHistory
+                                          (GEOM::GEOM_Object_ptr theShapeWhere,
+                                          GEOM::GEOM_Object_ptr theShapeWhat)
+{
+  GEOM::GEOM_Object_var aGEOMObject;
+
+  //Set a not done flag
+  GetOperations()->SetNotDone();
+
+  if (theShapeWhere == NULL ||
+      theShapeWhat == NULL) return aGEOMObject._retn();
+
+  //Get the reference objects
+  Handle(GEOM_Object) aShapeWhere = GetOperations()->GetEngine()->GetObject
+    (theShapeWhere->GetStudyID(), theShapeWhere->GetEntry());
+  Handle(GEOM_Object) aShapeWhat = GetOperations()->GetEngine()->GetObject
+    (theShapeWhat->GetStudyID(), theShapeWhat->GetEntry());
+
+  if (aShapeWhere.IsNull() ||
+      aShapeWhat.IsNull()) return aGEOMObject._retn();
+
+  //Get Shapes in place of aShapeWhat
+  Handle(GEOM_Object) anObject =
+    GetOperations()->GetInPlaceByHistory(aShapeWhere, aShapeWhat);
+  if (!GetOperations()->IsDone() || anObject.IsNull())
+    return aGEOMObject._retn();
+
+  return GetObject(anObject);
+}
+
 //=============================================================================
 /*!
  *  GetSame
index 036603b7f5566519fd1e39e88f26cc6c4d189936..81c2ad8da781fd37cf31da34bde6362d51da2899 100644 (file)
@@ -176,6 +176,9 @@ class GEOM_IShapesOperations_i :
   GEOM::GEOM_Object_ptr GetInPlace (GEOM::GEOM_Object_ptr theShapeWhere,
                                    GEOM::GEOM_Object_ptr theShapeWhat);
 
+  GEOM::GEOM_Object_ptr GetInPlaceByHistory (GEOM::GEOM_Object_ptr theShapeWhere,
+                                            GEOM::GEOM_Object_ptr theShapeWhat);
+
   GEOM::GEOM_Object_ptr GetSame (GEOM::GEOM_Object_ptr theShapeWhere,
                                 GEOM::GEOM_Object_ptr theShapeWhat);
 
index a530c3433f29db0f0780e7e86505788cd97320b4..899553a35790678368e5dd670d3d29052522c19b 100644 (file)
@@ -524,24 +524,72 @@ def TestOtherOperations (geompy, math):
   geompy.UnionIDs(vertices_on_quad, vertices_on_quad_ids)
   geompy.addToStudy(vertices_on_quad, "Group of vertices on Quadrangle F12")
 
-  # GetInPlace(theShapeWhere, theShapeWhat)
+  # Prepare arguments for GetInPlace and GetInPlaceByHistory
   box5 = geompy.MakeBoxDXDYDZ(100, 100, 100)
   box6 = geompy.MakeTranslation(box5, 50, 50, 0)
 
+  geompy.addToStudy(box5, "Box 5")
+  geompy.addToStudy(box6, "Box 6")
+
+  part = geompy.MakePartition([box5], [box6])
+  geompy.addToStudy(part, "Partitioned")
+
+  box5_faces = geompy.SubShapeAll(box5, geompy.ShapeType["FACE"])
+  box6_faces = geompy.SubShapeAll(box6, geompy.ShapeType["FACE"])
+
+  ifa = 1
+  for aface in box5_faces:
+    geompy.addToStudyInFather(box5, aface, "Face" + `ifa`)
+    ifa = ifa + 1
+
+  ifa = 1
+  for aface in box6_faces:
+    geompy.addToStudyInFather(box6, aface, "Face" + `ifa`)
+    ifa = ifa + 1
+
+  # GetInPlace(theShapeWhere, theShapeWhat)
+  ibb = 5
+  faces_list = [box5_faces, box6_faces]
+  for afaces in faces_list:
+    ifa = 1
+    for aface in afaces:
+      if ibb == 6 and (ifa == 2 or ifa == 4):
+        # use IDL interface directly to avoid error message appearence in Python console
+        refl_box_face = geompy.ShapesOp.GetInPlace(part, aface)
+        if refl_box_face is not None:
+          geompy.addToStudyInFather(part, refl_box_face,
+                                    "Reflection of face " + `ifa` + " of box " + `ibb`)
+          error = "Result of GetInPlace must be NULL for face " + `ifa` + " of box " + `ibb`
+          raise RuntimeError, error
+      else:
+        # use geompy interface
+        refl_box_face = geompy.GetInPlace(part, aface)
+        geompy.addToStudyInFather(part, refl_box_face,
+                                  "Reflection of face " + `ifa` + " of box " + `ibb`)
+      ifa = ifa + 1
+    ibb = ibb + 1
+
+  # GetInPlaceByHistory(theShapeWhere, theShapeWhat)
   part = geompy.MakePartition([box5], [box6])
   geompy.addToStudy(part, "Partitioned")
 
   ibb = 5
-  box_list = [box5, box6]
-  for abox in box_list:
-    geompy.addToStudy(abox, "Box " + `ibb`)
-    box_faces = geompy.SubShapeAll(abox, geompy.ShapeType["FACE"])
+  faces_list = [box5_faces, box6_faces]
+  for afaces in faces_list:
     ifa = 1
-    for aface in box_faces:
-      geompy.addToStudyInFather(abox, aface, "Face" + `ifa`)
-      refl_box_face = geompy.GetInPlace(part, aface)
-      if refl_box_face is not None:
+    for aface in afaces:
+      if ibb == 6 and (ifa == 2 or ifa == 4):
+        # use IDL interface directly to avoid error message appearence in Python console
+        refl_box_face = geompy.ShapesOp.GetInPlaceByHistory(part, aface)
+        if refl_box_face is not None:
+          geompy.addToStudyInFather(part, refl_box_face,
+                                    "Reflection of face " + `ifa` + " of box " + `ibb` + " (by history)")
+          error = "Result of GetInPlaceByHistory must be NULL for face " + `ifa` + " of box " + `ibb`
+          raise RuntimeError, error
+      else:
+        # use geompy interface
+        refl_box_face = geompy.GetInPlaceByHistory(part, aface)
         geompy.addToStudyInFather(part, refl_box_face,
-                                  "Reflection of Face " + `ifa` + " of box " + `ibb`)
+                                  "Reflection of face " + `ifa` + " of box " + `ibb` + " (by history)")
       ifa = ifa + 1
     ibb = ibb + 1
index 36db1cc3ea8df14dc4190c5496a4f86ab377f117..cf5a61fcfb79149d4d2c1343607064f1627085a1 100644 (file)
@@ -1097,6 +1097,27 @@ def GetInPlace(theShapeWhere, theShapeWhat):
       print "GetInPlace : ", ShapesOp.GetErrorCode()
     return anObj
 
+## Get sub-shape(s) of \a theShapeWhere, which are
+#  coincident with \a theShapeWhat or could be a part of it.
+#
+#  Implementation of this method is based on a saved history of an operation,
+#  produced \a theShapeWhere. The \a theShapeWhat must be among this operation's
+#  arguments (an argument shape or a sub-shape of an argument shape).
+#  The operation could be the Partition or one of boolean operations,
+#  performed on simple shapes (not on compounds).
+#
+#  @param theShapeWhere Shape to find sub-shapes of.
+#  @param theShapeWhat Shape, specifying what to find (must be in the
+#                      building history of the ShapeWhere).
+#  @return Group of all found sub-shapes or a single found sub-shape.
+#
+#  Example: see GEOM_TestOthers.py
+def GetInPlaceByHistory(theShapeWhere, theShapeWhat):
+    anObj = ShapesOp.GetInPlaceByHistory(theShapeWhere, theShapeWhat)
+    if ShapesOp.IsDone() == 0:
+      print "GetInPlace : ", ShapesOp.GetErrorCode()
+    return anObj
+
 ## Get sub-shape of theShapeWhere, which is
 #  equal to \a theShapeWhat.
 #  @param theShapeWhere Shape to find sub-shape of.