Salome HOME
22752: [EDF] Provide explicit feedback on what has been done by Shape Processing...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
index ce0fa360ffcce3ba1cd193ca4d5594eb913f120b..1a7c432055c799963b05d2bf1239cad8642453a0 100644 (file)
 #include "GEOMImpl_VectorDriver.hxx"
 #include "GEOMImpl_ShapeDriver.hxx"
 #include "GEOMImpl_GlueDriver.hxx"
+#include "GEOMImpl_FillingDriver.hxx"
 
 #include "GEOMImpl_IVector.hxx"
 #include "GEOMImpl_IShapes.hxx"
 #include "GEOMImpl_IShapeExtend.hxx"
 #include "GEOMImpl_IGlue.hxx"
+#include "GEOMImpl_IFilling.hxx"
 
 #include "GEOMImpl_Block6Explorer.hxx"
 #include "GEOMImpl_IHealingOperations.hxx"
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
+namespace {
+
+  //================================================================================
+  /*!
+   * \brief Return normal to face at extrema point
+   */
+  //================================================================================
+
+  gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
+  {
+    gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
+    try {
+      // get UV at extrema point
+      Standard_Real u,v, f,l;
+      switch ( extrema.SupportTypeShape2(1) ) {
+      case BRepExtrema_IsInFace: {
+        extrema.ParOnFaceS2(1, u, v );
+        break;
+      }
+      case BRepExtrema_IsOnEdge: {
+        TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
+        Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
+        extrema.ParOnEdgeS2( 1, u );
+        gp_Pnt2d uv = pcurve->Value( u );
+        u = uv.Coord(1);
+        v = uv.Coord(2);
+        break;
+      }
+      case BRepExtrema_IsVertex: return defaultNorm;
+      }
+      // get derivatives
+      BRepAdaptor_Surface surface( face, false );
+      gp_Vec du, dv; gp_Pnt p;
+      surface.D1( u, v, p, du, dv );
+
+      return du ^ dv;
+
+    } catch (Standard_Failure ) {
+    }
+    return defaultNorm;
+  }
+
+  void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
+  {
+    if (S.ShapeType() != TopAbs_COMPOUND) {
+      L.Append(S);
+    }
+    else {
+      TopoDS_Iterator It(S, Standard_True, Standard_True);
+      for (; It.More(); It.Next()) {
+       TopoDS_Shape SS = It.Value();
+       if (M.Add(SS))
+         AddFlatSubShapes(SS, L, M);
+      }
+    }
+  }
+}
 
 //=============================================================================
 /*!
@@ -620,6 +679,107 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
   return aShape;
 }
 
+//=============================================================================
+/*!
+ *  MakeFaceWithConstraints
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
+                             (std::list<Handle(GEOM_Object)> theConstraints)
+{
+  SetErrorCode(KO);
+
+  //Add a new object
+  Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING);
+
+  //Add a new function
+  Handle(GEOM_Function) aFunction =
+    aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
+  if (aFunction.IsNull()) return NULL;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
+
+  GEOMImpl_IFilling aCI (aFunction);
+  Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
+
+  // Shapes
+  std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
+  while (it != theConstraints.end()) {
+    Handle(GEOM_Object) anObject = (*it);
+    if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
+      SetErrorCode("NULL argument edge for the face construction");
+      return NULL;
+    }
+    Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
+    aConstraints->Append(aRefSh);
+    it++;
+    if ( it != theConstraints.end() ) {
+      Handle(GEOM_Object) aFace = (*it);
+      if ( aFace.IsNull() ) {
+        // null constraint face - it is a valid case
+        it++;
+        continue;
+      }
+      if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
+        // constraint face can be omitted - it is a valid case
+        continue;
+      if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
+        // valid constraint
+        aRefSh = aFace->GetLastFunction();
+        aConstraints->Append(aRefSh);
+        it++;
+      }
+      else {
+        // bad constraint
+        SetErrorCode("Face is NULL or not connected to the Edge");
+        return NULL;
+      }
+    }
+  }
+  aCI.SetShapes( aConstraints );
+
+  //Compute the shape
+  Standard_Boolean isWarning = Standard_False;
+  try {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Shape driver failed");
+      return NULL;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+    // to provide warning
+    if (!aFunction->GetValue().IsNull()) {
+      isWarning = Standard_True;
+    } else {
+      return NULL;
+    }
+  }
+
+  //Make a Python command
+  GEOM::TPythonDump pd (aFunction);
+  pd << aShape << " = geompy.MakeFaceWithConstraints([";
+
+  // Constraints
+  it = theConstraints.begin();
+  if (it != theConstraints.end() ) {
+    pd << (*it++);
+    while (it != theConstraints.end()) {
+      Handle(GEOM_Object) anObject = (*it++);
+      if( !anObject.IsNull() )
+        pd << ", " << anObject;
+    }
+  }
+  pd << "])";
+
+  // to provide warning
+  if (!isWarning) SetErrorCode(OK);
+  return aShape;
+}
+
 //=============================================================================
 /*!
  *  MakeShell
@@ -725,6 +885,77 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
   return aShape;
 }
 
+//=============================================================================
+/*!
+ *  MakeSolidFromConnectedFaces
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
+                             (std::list<Handle(GEOM_Object)> theFacesOrShells,
+                              const Standard_Boolean isIntersect)
+{
+  SetErrorCode(KO);
+
+  //Add a new object
+  Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
+
+  //Add a new function
+  Handle(GEOM_Function) aFunction =
+    aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
+  if (aFunction.IsNull()) return NULL;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
+
+  GEOMImpl_IShapes aCI (aFunction);
+
+  Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
+
+  // Shapes
+  std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
+  for (; it != theFacesOrShells.end(); it++) {
+    Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
+    if (aRefSh.IsNull()) {
+      SetErrorCode("NULL argument shape for the shape construction");
+      return NULL;
+    }
+    aShapesSeq->Append(aRefSh);
+  }
+  aCI.SetShapes(aShapesSeq);
+  aCI.SetIsIntersect(isIntersect);
+
+  //Compute the shape
+  try {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Shape driver failed");
+      return NULL;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+    return NULL;
+  }
+
+  //Make a Python command
+  GEOM::TPythonDump pd (aFunction);
+  pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
+
+  // Shapes
+  it = theFacesOrShells.begin();
+  if (it != theFacesOrShells.end()) {
+    pd << (*it++);
+    while (it != theFacesOrShells.end()) {
+      pd << ", " << (*it++);
+    }
+  }
+  pd << "]," << (isIntersect ? "True" : "False") << ")";
+
+  SetErrorCode(OK);
+  return aSolid;
+}
+
 //=============================================================================
 /*!
  *  MakeGlueFaces
@@ -1298,17 +1529,20 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
   TopTools_ListOfShape listShape;
 
   if (aShape.ShapeType() == TopAbs_COMPOUND &&
-      (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
-       TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
-       TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
+      (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
   {
     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
     for (; It.More(); It.Next()) {
-      if (mapShape.Add(It.Value())) {
-        if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
-            TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
-          listShape.Append(It.Value());
+      TopoDS_Shape SS = It.Value();
+      if (mapShape.Add(SS)) {
+       if (theShapeType == TopAbs_FLAT) {
+          AddFlatSubShapes(SS, listShape, mapShape);
+       }
+        else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
+         listShape.Append(SS);
         }
+        // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
+        // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
       }
     }
   }
@@ -1320,7 +1554,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
         listShape.Append(exp.Current());
   }
 
-  if (listShape.IsEmpty()) {
+  if (listShape.IsEmpty()){
     //SetErrorCode("The given shape has no sub-shapes of the requested type");
     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
     return aSeq;
@@ -1364,16 +1598,15 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
       // Put this subshape in the list of sub-shapes of theMainShape
       aMainShape->AddSubShapeReference(aFunction);
     }
-
     if (!anObj.IsNull()) {
-      aSeq->Append(anObj);
+          aSeq->Append(anObj);
 
-      // for python command
-      TDF_Tool::Entry(anObj->GetEntry(), anEntry);
-      anAsciiList += anEntry;
-      anAsciiList += ",";
-    }
-  }
+          // for python command
+          TDF_Tool::Entry(anObj->GetEntry(), anEntry);
+          anAsciiList += anEntry;
+          anAsciiList += ",";
+        }
+      }
 
   //Make a Python command
   anAsciiList.Trunc(anAsciiList.Length() - 1);
@@ -1422,16 +1655,17 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
   TopTools_ListOfShape listShape;
 
   if (aShape.ShapeType() == TopAbs_COMPOUND &&
-      (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
-       TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
-       TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
+      (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
   {
     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
     for (; It.More(); It.Next()) {
-      if (mapShape.Add(It.Value())) {
-        if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
-            TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
-          listShape.Append(It.Value());
+      TopoDS_Shape SS = It.Value();
+      if (mapShape.Add(SS)) {
+       if (theShapeType == TopAbs_FLAT) {
+          AddFlatSubShapes(SS, listShape, mapShape);
+       }
+        else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
+          listShape.Append(SS);
         }
       }
     }
@@ -1809,6 +2043,39 @@ TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(G
   return aTypeName;
 }
 
+//=============================================================================
+/*!
+ *  IsSubShapeBelongsTo
+ */
+//=============================================================================
+Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
+                                                                  const Standard_Integer theSubObjectIndex,
+                                                                  Handle(GEOM_Object) theObject,
+                                                                  const Standard_Integer theObjectIndex)
+{
+  if ( theObject.IsNull() || theSubObject.IsNull() )
+    return false;
+
+  TopoDS_Shape shape    = theObject->GetValue();
+  TopoDS_Shape subShape = theSubObject->GetValue();
+
+  if ( shape.IsNull() || subShape.IsNull() )
+    return false;
+
+  TopTools_IndexedMapOfShape anIndices;
+  if ( theObjectIndex > 0 ) {
+    TopExp::MapShapes( shape, anIndices );
+    shape = anIndices.FindKey(theObjectIndex);
+  }
+  if ( theSubObjectIndex > 0 ) {
+    TopExp::MapShapes( subShape, anIndices );
+    subShape = anIndices.FindKey(theSubObjectIndex);
+  }
+
+  TopExp::MapShapes( shape, anIndices );
+  return anIndices.Contains( subShape );
+}
+
 //=============================================================================
 /*!
  *  NumberOfSubShapes
@@ -1850,33 +2117,41 @@ Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
   */
 
   try {
-    OCC_CATCH_SIGNALS;
-    int iType, nbTypes [TopAbs_SHAPE];
-    for (iType = 0; iType < TopAbs_SHAPE; ++iType)
-      nbTypes[iType] = 0;
-    nbTypes[aShape.ShapeType()]++;
-
-    TopTools_MapOfShape aMapOfShape;
-    aMapOfShape.Add(aShape);
-    TopTools_ListOfShape aListOfShape;
-    aListOfShape.Append(aShape);
-
-    TopTools_ListIteratorOfListOfShape itL (aListOfShape);
-    for (; itL.More(); itL.Next()) {
-      TopoDS_Iterator it (itL.Value());
-      for (; it.More(); it.Next()) {
-        TopoDS_Shape s = it.Value();
-        if (aMapOfShape.Add(s)) {
-          aListOfShape.Append(s);
-          nbTypes[s.ShapeType()]++;
+    if (theShapeType == TopAbs_FLAT) {
+      TopTools_MapOfShape aMapOfShape;
+      TopTools_ListOfShape aListOfShape;
+      AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
+      nbShapes = aListOfShape.Extent();
+    }
+    else {
+      OCC_CATCH_SIGNALS;
+      int iType, nbTypes [TopAbs_SHAPE];
+      for (iType = 0; iType < TopAbs_SHAPE; ++iType)
+        nbTypes[iType] = 0;
+      nbTypes[aShape.ShapeType()]++;
+      
+      TopTools_MapOfShape aMapOfShape;
+      aMapOfShape.Add(aShape);
+      TopTools_ListOfShape aListOfShape;
+      aListOfShape.Append(aShape);
+      
+      TopTools_ListIteratorOfListOfShape itL (aListOfShape);
+      for (; itL.More(); itL.Next()) {
+        TopoDS_Iterator it (itL.Value());
+        for (; it.More(); it.Next()) {
+          TopoDS_Shape s = it.Value();
+          if (aMapOfShape.Add(s)) {
+            aListOfShape.Append(s);
+            nbTypes[s.ShapeType()]++;
+          }
         }
       }
+      
+      if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
+        nbShapes = aMapOfShape.Extent();
+      else
+        nbShapes = nbTypes[theShapeType];
     }
-
-    if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
-      nbShapes = aMapOfShape.Extent();
-    else
-      nbShapes = nbTypes[theShapeType];
   }
   catch (Standard_Failure) {
     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
@@ -3850,49 +4125,6 @@ void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape,
   return;
 }
 
-namespace {
-
-  //================================================================================
-  /*!
-   * \brief Return normal to face at extrema point
-   */
-  //================================================================================
-
-  gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
-  {
-    gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
-    try {
-      // get UV at extrema point
-      Standard_Real u,v, f,l;
-      switch ( extrema.SupportTypeShape2(1) ) {
-      case BRepExtrema_IsInFace: {
-        extrema.ParOnFaceS2(1, u, v );
-        break;
-      }
-      case BRepExtrema_IsOnEdge: {
-        TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
-        Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
-        extrema.ParOnEdgeS2( 1, u );
-        gp_Pnt2d uv = pcurve->Value( u );
-        u = uv.Coord(1);
-        v = uv.Coord(2);
-        break;
-      }
-      case BRepExtrema_IsVertex: return defaultNorm;
-      }
-      // get derivatives
-      BRepAdaptor_Surface surface( face, false );
-      gp_Vec du, dv; gp_Pnt p;
-      surface.D1( u, v, p, du, dv );
-
-      return du ^ dv;
-
-    } catch (Standard_Failure ) {
-    }
-    return defaultNorm;
-  }
-}
-
 //=============================================================================
 /*!
  *  case GetInPlace:
@@ -4921,3 +5153,64 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
 
   return aResFace;
 }
+
+//=======================================================================
+//function : MakeSurfaceFromFace
+//purpose  :
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
+                                      (const Handle(GEOM_Object) &theFace)
+{
+  SetErrorCode(KO);
+
+  if (theFace.IsNull()) {
+    return NULL;
+  }
+
+  //Add a new Face object
+  Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
+
+  //Add a new Vector function
+  Handle(GEOM_Function) aFunction =
+    aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
+    return NULL;
+  }
+
+  GEOMImpl_IShapeExtend aCI (aFunction);
+
+  Handle(GEOM_Function) aFace = theFace->GetLastFunction();
+
+  if (aFace.IsNull()) {
+    return NULL;
+  }
+
+  aCI.SetShape(aFace);
+
+  //Compute the Face value
+  try {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Shape driver failed");
+
+      return NULL;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+
+    return NULL;
+  }
+
+  //Make a Python command
+  GEOM::TPythonDump(aFunction)
+             << aResFace  << " = geompy.MakeSurfaceFromFace("
+             << theFace << ")";
+
+  SetErrorCode(OK);
+
+  return aResFace;
+}