Salome HOME
IMP 0021064: correct implementation
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
index 61237649dd99e215c48670bbd212643a859f1fc2..46ce5f9c564d61dfbbf51c50ff108ee0ecc81420 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -18,7 +18,7 @@
 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
+
 #include <Standard_Stream.hxx>
 
 #include <GEOMImpl_IMeasureOperations.hxx>
@@ -59,6 +59,7 @@
 #include <GProp_PrincipalProps.hxx>
 
 #include <TopAbs.hxx>
+#include <TopExp.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
@@ -155,6 +156,14 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
   TopoDS_Shape aShape = aRefShape->GetValue();
   if (aShape.IsNull()) return aKind;
 
+  int geom_type = theShape->GetType();
+
+  // check if it's advanced shape
+  if ( geom_type > ADVANCED_BASE ) {
+    SetErrorCode(OK);
+    return SK_ADVANCED;
+  }
+
   // Call algorithm
   GEOMAlgo_ShapeInfoFiller aSF;
   aSF.SetShape(aShape);
@@ -895,6 +904,60 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
   return aCDG;
 }
 
+//=============================================================================
+/*!
+ *  GetVertexByIndex
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
+                                                (Handle(GEOM_Object) theShape,
+                                                 Standard_Integer theIndex)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull()) return NULL;
+
+  Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+  if (aRefShape.IsNull()) return NULL;
+
+  //Add a new Vertex object
+  Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT);
+
+  //Add a function
+  Handle(GEOM_Function) aFunction =
+    aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
+  if (aFunction.IsNull()) return NULL;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
+
+  GEOMImpl_IMeasure aCI (aFunction);
+  aCI.SetBase(aRefShape);
+  aCI.SetIndex(theIndex);
+
+  //Compute
+  try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Vertex by index 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) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")";
+
+  SetErrorCode(OK);
+  return aVertex;
+}
+
 //=============================================================================
 /*!
  *  GetNormal
@@ -997,9 +1060,9 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha
     theVolume = 0.0;
     if (aShape.ShapeType() < TopAbs_SHELL) {
       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
-       GProp_GProps VProps;
-       BRepGProp::VolumeProperties(Exp.Current(), VProps);
-       theVolume += VProps.Mass();
+        GProp_GProps VProps;
+        BRepGProp::VolumeProperties(Exp.Current(), VProps);
+        theVolume += VProps.Mass();
       }
     }
   }
@@ -1160,25 +1223,25 @@ void GEOMImpl_IMeasureOperations::GetTolerance
       TopoDS_Face Face = TopoDS::Face(ExF.Current());
       T = BRep_Tool::Tolerance(Face);
       if (T > FaceMax)
-       FaceMax = T;
+        FaceMax = T;
       if (T < FaceMin)
-       FaceMin = T;
+        FaceMin = T;
     }
     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
       T = BRep_Tool::Tolerance(Edge);
       if (T > EdgeMax)
-       EdgeMax = T;
+        EdgeMax = T;
       if (T < EdgeMin)
-       EdgeMin = T;
+        EdgeMin = T;
     }
     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
       T = BRep_Tool::Tolerance(Vertex);
       if (T > VertMax)
-       VertMax = T;
+        VertMax = T;
       if (T < VertMin)
-       VertMin = T;
+        VertMin = T;
     }
   }
   catch (Standard_Failure) {
@@ -1236,6 +1299,53 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
   return isValid;
 }
 
+//=============================================================================
+/*!
+ *  IsGoodForSolid
+ */
+//=============================================================================
+TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
+{
+  SetErrorCode(KO);
+
+  TCollection_AsciiString aRes = "";
+
+  if (theShape.IsNull()) {
+    aRes = "WRN_NULL_OBJECT_OR_SHAPE";
+  }
+  else {
+    Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+    if (aRefShape.IsNull()) {
+      aRes = "WRN_NULL_OBJECT_OR_SHAPE";
+    }
+    else {
+      TopoDS_Shape aShape = aRefShape->GetValue();
+      if (aShape.IsNull()) {
+        aRes = "WRN_NULL_OBJECT_OR_SHAPE";
+      }
+      else {
+        if (aShape.ShapeType() == TopAbs_COMPOUND) {
+          TopoDS_Iterator It (aShape, Standard_True, Standard_True);
+          if (It.More()) aShape = It.Value();
+        }
+        if (aShape.ShapeType() == TopAbs_SHELL) {
+          if (!aShape.Closed()) {
+            aRes = "WRN_SHAPE_UNCLOSED";
+          }
+        }
+        else {
+          aRes = "WRN_SHAPE_NOT_SHELL";
+        }
+      }
+    }
+  }
+
+  if (aRes.IsEmpty())
+    SetErrorCode(OK);
+
+  return aRes;
+}
+
 //=============================================================================
 /*!
  *  WhatIs
@@ -1344,10 +1454,13 @@ static double CheckSingularCase(const TopoDS_Shape& aSh1,
       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
         // non solid case
         double U1,U2,V1,V2;
-        S->Bounds(U1,U2,V1,V2);
-        Handle(Geom_RectangularTrimmedSurface) TrS1 = 
+        // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
+        //S->Bounds(U1,U2,V1,V2); changed by
+        ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2);
+        // end of changes for 020677 (dmv)
+        Handle(Geom_RectangularTrimmedSurface) TrS1 =
           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
-        Handle(Geom_RectangularTrimmedSurface) TrS2 = 
+        Handle(Geom_RectangularTrimmedSurface) TrS2 =
           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
         BRep_Builder B;
         TopoDS_Face F1,F2;
@@ -1413,10 +1526,11 @@ static double CheckSingularCase(const TopoDS_Shape& aSh1,
       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
         // non solid case
         double U1,U2,V1,V2;
-        S->Bounds(U1,U2,V1,V2);
-        Handle(Geom_RectangularTrimmedSurface) TrS1 = 
+        //S->Bounds(U1,U2,V1,V2);
+        ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh2),U1,U2,V1,V2);
+        Handle(Geom_RectangularTrimmedSurface) TrS1 =
           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
-        Handle(Geom_RectangularTrimmedSurface) TrS2 = 
+        Handle(Geom_RectangularTrimmedSurface) TrS2 =
           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
         BRep_Builder B;
         TopoDS_Face F1,F2;
@@ -1613,6 +1727,37 @@ static bool CheckSingularCase(const TopoDS_Shape& aSh1,
 */
 
 
+//=============================================================================
+/*!
+ *  AreCoordsInside
+ */
+//=============================================================================
+std::vector<bool> GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape,
+                                                               const std::vector<double>& coords,
+                                                               double tolerance)
+{
+  std::vector<bool> res;
+  if (!theShape.IsNull()) {
+    Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+    if (!aRefShape.IsNull()) {
+      TopoDS_Shape aShape = aRefShape->GetValue();
+      if (!aShape.IsNull()) {
+        BRepClass3d_SolidClassifier SC(aShape);
+        unsigned int nb_points = coords.size()/3;
+        for (int i = 0; i < nb_points; i++) {
+          double x = coords[3*i];
+          double y = coords[3*i+1];
+          double z = coords[3*i+2];
+          gp_Pnt aPnt(x, y, z);
+          SC.Perform(aPnt, tolerance);
+          res.push_back( ( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ) );
+        }
+      }
+    }
+  }
+  return res;
+}
+
 //=============================================================================
 /*!
  *  GetMinDistance
@@ -1689,12 +1834,12 @@ Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
       gp_Pnt PMin1, PMin2, P1, P2;
 
       for (int i = 1; i <= dst.NbSolution(); i++) {
-       P1 = dst.PointOnShape1(i);
-       P2 = dst.PointOnShape2(i);
+        P1 = dst.PointOnShape1(i);
+        P2 = dst.PointOnShape2(i);
 
-       Standard_Real Dist = P1.Distance(P2);
-       if (MinDist > Dist) {
-         MinDist = Dist;
+        Standard_Real Dist = P1.Distance(P2);
+        if (MinDist > Dist) {
+          MinDist = Dist;
           PMin1 = P1;
           PMin2 = P2;
         }
@@ -1798,7 +1943,7 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine
     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
 
     if ( C1.IsNull() || C2.IsNull() ||
-       !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
+        !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
     {
       SetErrorCode("The edges must be linear");
@@ -1814,6 +1959,72 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine
     anAngle = aLin1.Angle(aLin2);
     anAngle /= PI180; // convert radians into degrees
 
+    if (anAngle > 90.0) {
+      anAngle = 180.0 - anAngle;
+    }
+
+    SetErrorCode(OK);
+  }
+  catch (Standard_Failure)
+  {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+  }
+
+  return anAngle;
+}
+
+//=======================================================================
+/*!
+ *  Compute angle (in degrees) between two vectors
+ */
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
+                                                               Handle(GEOM_Object) theVec2)
+{
+  SetErrorCode(KO);
+
+  Standard_Real anAngle = -1.0;
+
+  if (theVec1.IsNull() || theVec2.IsNull())
+    return anAngle;
+
+  Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
+  Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
+  if (aRefVec1.IsNull() || aRefVec2.IsNull())
+    return anAngle;
+
+  TopoDS_Shape aVec1 = aRefVec1->GetValue();
+  TopoDS_Shape aVec2 = aRefVec2->GetValue();
+  if (aVec1.IsNull() || aVec2.IsNull() ||
+      aVec1.ShapeType() != TopAbs_EDGE ||
+      aVec2.ShapeType() != TopAbs_EDGE)
+  {
+    SetErrorCode("Two edges must be given");
+    return anAngle;
+  }
+
+  try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
+    TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
+    TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
+
+    TopoDS_Vertex aP11, aP12, aP21, aP22;
+    TopExp::Vertices(aE1, aP11, aP12, Standard_True);
+    TopExp::Vertices(aE2, aP21, aP22, Standard_True);
+    if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
+      SetErrorCode("Bad edge given");
+      return anAngle;
+    }
+
+    gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
+    gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
+
+    anAngle = aV1.Angle(aV2);
+    anAngle /= PI180; // convert radians into degrees
+
     SetErrorCode(OK);
   }
   catch (Standard_Failure)
@@ -1859,7 +2070,7 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
     OCC_CATCH_SIGNALS;
 #endif
-    GeomLProp_CLProps Prop = GeomLProp_CLProps 
+    GeomLProp_CLProps Prop = GeomLProp_CLProps
       (aCurve, aP, 2, Precision::Confusion());
     aRes = fabs(Prop.Curvature());
     SetErrorCode(OK);
@@ -1874,7 +2085,7 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
     aRes = 1/aRes;
   else
     aRes = RealLast();
-  
+
   return aRes;
 }
 
@@ -1913,10 +2124,10 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
     OCC_CATCH_SIGNALS;
 #endif
-    GeomAPI_ProjectPointOnCurve PPC(aPoint, aCurve, aFP, aLP);
-    if(PPC.NbPoints()>0) {
-      GeomLProp_CLProps Prop = GeomLProp_CLProps 
-        (aCurve, PPC.LowerDistanceParameter(), 2, Precision::Confusion());
+    GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
+    if(PPCurve.NbPoints()>0) {
+      GeomLProp_CLProps Prop = GeomLProp_CLProps
+        (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
       aRes = fabs(Prop.Curvature());
       SetErrorCode(OK);
     }
@@ -1931,7 +2142,7 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
     aRes = 1/aRes;
   else
     aRes = RealLast();
-  
+
   return aRes;
 }
 
@@ -1956,7 +2167,7 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
     OCC_CATCH_SIGNALS;
 #endif
-    GeomLProp_SLProps Prop = GeomLProp_SLProps 
+    GeomLProp_SLProps Prop = GeomLProp_SLProps
       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
     if(Prop.IsCurvatureDefined()) {
       if(Prop.IsUmbilic()) {
@@ -1985,7 +2196,7 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
     aRes = 1/aRes;
   else
     aRes = RealLast();
-  
+
   return aRes;
 }
 
@@ -2022,7 +2233,7 @@ Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
   Standard_Real U = U1 + (U2-U1)*theUParam;
   Standard_Real V = V1 + (V2-V1)*theVParam;
-  
+
   return getSurfaceCurvatures(aSurf, U, V, true);
 }
 
@@ -2095,7 +2306,7 @@ Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
   Standard_Real U = U1 + (U2-U1)*theUParam;
   Standard_Real V = V1 + (V2-V1)*theVParam;
-  
+
   return getSurfaceCurvatures(aSurf, U, V, false);
 }
 
@@ -2462,14 +2673,14 @@ void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&
 
     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
     for (res->InitContextIterator();
-        res->MoreShapeInContext();
-        res->NextShapeInContext()) {
+         res->MoreShapeInContext();
+         res->NextShapeInContext()) {
       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
-       theMap(sub).Append(theShape);
-       itl.Initialize(res->StatusOnShape());
+        theMap(sub).Append(theShape);
+        itl.Initialize(res->StatusOnShape());
 
-       if (itl.Value() != BRepCheck_NoError) {
-         Standard_Integer ii = 0;
+        if (itl.Value() != BRepCheck_NoError) {
+          Standard_Integer ii = 0;
 
           for (ii = 1; ii <= sl->Length(); ii++)
             if (sl->Value(ii).IsSame(sub)) break;
@@ -2488,8 +2699,8 @@ void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&
             NbProblems->SetValue((Standard_Integer)stat,
                                  NbProblems->Value((Standard_Integer)stat) + 1);
           }
-       }
-       break;
+        }
+        break;
       }
     }
   }