0028002: Invalid result of Boolean Fuse operation
[occt.git] / src / BRepClass3d / BRepClass3d_SolidExplorer.cxx
index 92085f8..6d8d33d 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
 #define REJECTION 1
 
 //-- To printf on NT
-#include <stdio.h>
 
-#include <BRepClass3d_SolidExplorer.ixx>
-#include <gp.hxx>
-#include <TopoDS.hxx>
+#include <Bnd_Box.hxx>
+#include <BRep_Tool.hxx>
 #include <BRepAdaptor_Curve2d.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
+#include <BRepClass3d_DataMapIteratorOfMapOfInter.hxx>
+#include <BRepClass3d_SolidExplorer.hxx>
+#include <BRepClass_Edge.hxx>
+#include <BRepClass_FaceClassifier.hxx>
+#include <BRepClass_FacePassiveClassifier.hxx>
 #include <BRepTools.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
+#include <ElCLib.hxx>
+#include <Extrema_ExtPS.hxx>
 #include <Geom2d_Curve.hxx>
-#include <gp_Vec2d.hxx>
 #include <GeomAbs_Shape.hxx>
-#include <BRepAdaptor_Surface.hxx>
-#include <BRepClass_FacePassiveClassifier.hxx>
+#include <gp.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <gp_Vec2d.hxx>
+#include <IntCurvesFace_Intersector.hxx>
+#include <Precision.hxx>
 #include <TopAbs_Orientation.hxx>
 #include <TopExp_Explorer.hxx>
-#include <BRepClass_Edge.hxx>
-
-#include <Bnd_Box.hxx>
-#include <BRepBndLib.hxx>
-
-#include <BRepAdaptor_HSurface.hxx>
-
-#include <ElCLib.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopExp.hxx>
 
-#include <BRepClass3d_DataMapIteratorOfMapOfInter.hxx>
-#include <Precision.hxx>
+#include <stdio.h>
 //OCC454(apo)->
-#include <Extrema_ExtPS.hxx>
-#include <BRep_Tool.hxx> 
-#include <BRepClass_FaceClassifier.hxx>
 //<-OCC454(apo)
-#include <BRepTopAdaptor_FClass2d.hxx> 
-
-
 //=======================================================================
 //function : FindAPointInTheFace
 //purpose  : Compute a point P in the face  F. Param is a Real in
 //           ]0,1[ and   is  used to  initialise  the algorithm. For
 //           different values , different points are returned.
 //=======================================================================
-
 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
 (const TopoDS_Face& _face,
  gp_Pnt& APoint_,
@@ -174,7 +176,7 @@ Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
       }
     }
 
-    if (APointExist)
+    while (APointExist)
     { 
       ParamInit *= 0.41234;
       u_ = P.X() + ParamInit* T.X();
@@ -190,7 +192,12 @@ Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
       BRepAdaptor_Surface s;
       s.Initialize (face, Standard_False);
       s.D1 (u_, v_, APoint_, theVecD1U, theVecD1V);
-      return Standard_True;
+
+      if(theVecD1U.CrossMagnitude(theVecD1V) > gp::Resolution())
+        return Standard_True;
+
+      if(ParamInit < Precision::PConfusion())
+        return Standard_False;
     }
   }
   return Standard_False;
@@ -218,6 +225,29 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
                          U1, V1, U2, V2, aVecD1U, aVecD1V);
 }
 
+//=======================================================================
+//function : ClassifyUVPoint
+//purpose  : 
+//=======================================================================
+
+TopAbs_State BRepClass3d_SolidExplorer::ClassifyUVPoint
+                   (const IntCurvesFace_Intersector& theIntersector,
+                    const Handle(BRepAdaptor_HSurface)& theSurf,
+                    const gp_Pnt2d& theP2d) const
+{
+  // first find if the point is near an edge/vertex
+  gp_Pnt aP3d = theSurf->Value(theP2d.X(), theP2d.Y());
+  BRepClass3d_BndBoxTreeSelectorPoint aSelectorPoint(myMapEV);
+  aSelectorPoint.SetCurrentPoint(aP3d);
+  Standard_Integer aSelsVE = myTree.Select(aSelectorPoint);
+  if (aSelsVE > 0)
+  {
+    // The point is inside the tolerance area of vertices/edges => return ON state.
+    return TopAbs_ON;
+  }
+  return theIntersector.ClassifyUVPoint(theP2d);
+}
+
 //=======================================================================
 //function : PointInTheFace
 //purpose  : 
@@ -241,11 +271,29 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
   Standard_Real v,dv = (V2-V1)/6.0;
   if(du<1e-12) du=1e-12;
   if(dv<1e-12) dv=1e-12;
+  Standard_Boolean IsNotUper = !surf->IsUPeriodic(), IsNotVper = !surf->IsVPeriodic();
   Standard_Integer NbPntCalc=0;
   if(myMapOfInter.IsBound(Face)) { 
     void *ptr = (void*)(myMapOfInter.Find(Face));
+    Standard_Boolean IsInside = Standard_True;
+    if(IsNotUper)
+    {
+      IsInside = (u_ >= U1) && (u_ <= U2);
+    }
+    if(IsNotVper)
+    {
+      IsInside &= (v_ >= V1) && (v_ <= V2);
+    }
     if(ptr) { 
       const IntCurvesFace_Intersector& TheIntersector = (*((IntCurvesFace_Intersector *)ptr));
+      // Check if the point is already in the face
+      if (IsInside && (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u_, v_)) == TopAbs_IN)) {
+        gp_Pnt aPnt;
+        surf->D1(u_, v_, aPnt, theVecD1U, theVecD1V);
+        if (aPnt.SquareDistance(APoint_) < Precision::Confusion() * Precision::Confusion())
+          return Standard_True;
+      }
+
       //-- Take 4 points in each Quarter of surface
       //-- -> Index : 1 -> 16
       //-- 
@@ -255,7 +303,7 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
       for(u=du+(U1+U2)*0.5; u<U2; u+=du) {          //--  0  X    u increases
         for(v=dv+(V1+V2)*0.5; v<V2; v+=dv) {        //--  0  0    v increases
           if(++NbPntCalc>=IndexPoint) { 
-            if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
+            if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
               u_=u; v_=v;
               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
               IndexPoint = NbPntCalc;
@@ -264,42 +312,42 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
           }
         }
       }
-         
+          
       for(u=-du+(U1+U2)*0.5; u>U1; u-=du) {         //--  0  0    u decreases
-       for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {       //--  X  0    v decreases
-         if(++NbPntCalc>=IndexPoint) {
-           if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
-             u_=u; v_=v;
-             surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
-             IndexPoint = NbPntCalc;
-             return(Standard_True);
-           }
-         }
-       }
+        for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {       //--  X  0    v decreases
+          if(++NbPntCalc>=IndexPoint) {
+            if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
+              u_=u; v_=v;
+              surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
+              IndexPoint = NbPntCalc;
+              return(Standard_True);
+            }
+          }
+        }
       }
       for(u=-du+(U1+U2)*0.5; u>U1; u-=du) {         //--  X  0    u decreases
-       for(v=dv+(V1+V2)*0.5; v<V2; v+=dv) {        //--  0  0    v increases
-         if(++NbPntCalc>=IndexPoint) { 
-           if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
-             u_=u; v_=v;
-             surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
-             IndexPoint = NbPntCalc;
-             return(Standard_True);
-           }
-         }
-       }
+        for(v=dv+(V1+V2)*0.5; v<V2; v+=dv) {        //--  0  0    v increases
+          if(++NbPntCalc>=IndexPoint) { 
+            if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
+              u_=u; v_=v;
+              surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
+              IndexPoint = NbPntCalc;
+              return(Standard_True);
+            }
+          }
+        }
       }
       for(u=du+(U1+U2)*0.5; u<U2; u+=du) {         //--  0  0     u increases
-       for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {      //--  0  X     v decreases
-         if(++NbPntCalc>=IndexPoint) {
-           if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
-             u_=u; v_=v;
-             surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
-             IndexPoint = NbPntCalc;
-             return(Standard_True);
-           }
-         }
-       }
+        for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {      //--  0  X     v decreases
+          if(++NbPntCalc>=IndexPoint) {
+            if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
+              u_=u; v_=v;
+              surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
+              IndexPoint = NbPntCalc;
+              return(Standard_True);
+            }
+          }
+        }
       }
       //-- the remainder
       du = (U2-U1)/37.0;
@@ -308,26 +356,26 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
       if(dv<1e-12) dv=1e-12;
       
       for(u=du+U1; u<U2; u+=du) { 
-       for(v=dv+V1; v<V2; v+=dv) {
-         if(++NbPntCalc>=IndexPoint) {
-           if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
-             u_=u; v_=v;
-             surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
-             IndexPoint = NbPntCalc;
-             return(Standard_True);
-           }
-         }
-       }
+        for(v=dv+V1; v<V2; v+=dv) {
+          if(++NbPntCalc>=IndexPoint) {
+            if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
+              u_=u; v_=v;
+              surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
+              IndexPoint = NbPntCalc;
+              return(Standard_True);
+            }
+          }
+        }
       }
       u=(U1+U2)*0.5;
       v=(V1+V2)*0.5;
       if(++NbPntCalc>=IndexPoint) {
-       if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
-         u_=u; v_=v;
-         surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
-         IndexPoint = NbPntCalc;
-         return(Standard_True);
-       }
+        if (ClassifyUVPoint(TheIntersector, surf, gp_Pnt2d(u, v)) == TopAbs_IN) {
+          u_=u; v_=v;
+          surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
+          IndexPoint = NbPntCalc;
+          return(Standard_True);
+        }
       }
     }
     IndexPoint = NbPntCalc;
@@ -345,9 +393,9 @@ Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
 //purpose  : Limit infinite parameters
 //=======================================================================
 static void LimitInfiniteUV (Standard_Real& U1,
-                            Standard_Real& V1,
-                            Standard_Real& U2,
-                            Standard_Real& V2)
+                             Standard_Real& V1,
+                             Standard_Real& U2,
+                             Standard_Real& V2)
 {
   Standard_Boolean
     infU1 = Precision::IsNegativeInfinite(U1),
@@ -365,9 +413,9 @@ static void LimitInfiniteUV (Standard_Real& U1,
 //purpose  : 
 //=======================================================================
 static Standard_Integer IsInfiniteUV (Standard_Real& U1, 
-                                     Standard_Real& V1,
-                                     Standard_Real& U2, 
-                                     Standard_Real& V2) 
+                                      Standard_Real& V1,
+                                      Standard_Real& U2, 
+                                      Standard_Real& V2) 
 {
   Standard_Integer aVal = 0;
 
@@ -398,8 +446,8 @@ static Standard_Integer IsInfiniteUV (Standard_Real& U1,
 //           and so on. 
 //=======================================================================
 Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P, 
-                                                        gp_Lin& L, 
-                                                        Standard_Real& _Par) 
+                                                         gp_Lin& L, 
+                                                         Standard_Real& _Par) 
 {
   const Standard_Real TolU = Precision::PConfusion();
   const Standard_Real TolV = TolU;
@@ -415,6 +463,8 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
   Standard_Integer IndexPoint=0;
   Standard_Integer NbPointsOK=0;
   Standard_Integer NbFacesInSolid=0;
+  Standard_Boolean aRestr = Standard_True;
+  Standard_Boolean aTestInvert = Standard_False;
 
   for(;;) { 
     myFirstFace++; 
@@ -422,6 +472,7 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
     // look for point on face starting from myFirstFace
 //  Modified by skv - Thu Sep  4 14:31:12 2003 OCC578 Begin
 //     while (faceexplorer.More()) {
+    NbFacesInSolid = 0;
     for (; faceexplorer.More(); faceexplorer.Next()) {
 //  Modified by skv - Thu Sep  4 14:31:12 2003 OCC578 End
       NbFacesInSolid++;
@@ -429,7 +480,26 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
       face = TopoDS::Face(faceexplorer.Current());
 
       Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
-      surf->ChangeSurface().Initialize(face);
+      if(aTestInvert)
+      {
+        BRepTopAdaptor_FClass2d aClass(face, Precision::Confusion());
+        if(aClass.PerformInfinitePoint() == TopAbs_IN)
+        {
+          aRestr = Standard_False;
+          if(myMapOfInter.IsBound(face))
+          {
+            myMapOfInter.UnBind(face);
+            void *ptr = (void *)(new IntCurvesFace_Intersector(face, Precision::Confusion(),
+                                                               aRestr, Standard_False));
+            myMapOfInter.Bind(face,ptr);
+          }
+        }
+        else
+        {
+          aRestr = Standard_True;
+        }
+      }
+      surf->ChangeSurface().Initialize(face, aRestr);
       Standard_Real U1,V1,U2,V2;
       U1 = surf->FirstUParameter();
       V1 = surf->FirstVParameter();
@@ -438,73 +508,84 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
       face.Orientation(TopAbs_FORWARD);
       //
       //avoid process faces from uncorrected shells
-      if( Abs (U2 - U1) < 1.e-12 || Abs(V2 - V1) < 1.e-12) {
-       return 2;
+      const Standard_Real eps = Precision::PConfusion();
+      Standard_Real epsU = Max(eps * Max(Abs(U2), Abs(U1)), eps);
+      Standard_Real epsV = Max(eps * Max(Abs(V2), Abs(V1)), eps);
+      if( Abs (U2 - U1) < epsU || Abs(V2 - V1) < epsV) {
+        return 2;
       }
       //
       Standard_Real svmyparam=myParamOnEdge;
       //
       // Check if the point is on the face or the face is infinite.
       Standard_Integer anInfFlag = IsInfiniteUV(U1,V1,U2,V2);
+      // default values
+      _u = (U1 + U2) * 0.5;
+      _v = (V1 + V2) * 0.5;
 
       GeomAdaptor_Surface GA(BRep_Tool::Surface(face));
       Extrema_ExtPS Ext(P, GA, TolU, TolV);
       //
       if (Ext.IsDone() && Ext.NbExt() > 0) {
-       Standard_Integer i, iNear,  iEnd;
-       Standard_Real  aUx, aVx, Dist2, Dist2Min;
-       Extrema_POnSurf aPx;
-       //
-       iNear = 1;
-       Dist2Min = Ext.SquareDistance(1);
-       iEnd = Ext.NbExt();
-       for (i = 2; i <= iEnd; i++) {
-         aPx=Ext.Point(i);
-         aPx.Parameter(aUx, aVx);
-         if (aUx>=U1 && aUx<=U2 && aVx>=V1 && aVx<=V2) {
-           Dist2 = Ext.SquareDistance(i);
-           if (Dist2 < Dist2Min) {
-             Dist2Min = Dist2; 
-             iNear = i;
-           }
-         }
-       }
-       //
-       Standard_Real aDist2Tresh=1.e-24;
-       //
-       if (Dist2Min<aDist2Tresh) {
-         if (anInfFlag) {
-           return 1;
-         } 
-         else {
-           BRepClass_FaceClassifier classifier2d;
-           Standard_Real            aU;
-           Standard_Real            aV;
-
-           (Ext.Point(iNear)).Parameter(aU, aV);
-
-           gp_Pnt2d aPuv(aU, aV);
-
-           classifier2d.Perform(face,aPuv,Precision::PConfusion());
-
-           TopAbs_State aState = classifier2d.State();
-
-           if (aState == TopAbs_IN || aState == TopAbs_ON) {
-             return 1;
-           }
-           else {
-             return 3; // skv - the point is on surface but outside face.
-           }
-         }
-       }
-       if (anInfFlag) {
-         APoint = (Ext.Point(iNear)).Value();
-         gp_Vec V(P,APoint);
-         _Par = V.Magnitude(); 
-         L = gp_Lin(P,V);
-         ptfound=Standard_True;
-         return 0;
-       }
+        Standard_Integer i, iNear,  iEnd;
+        Standard_Real  aUx, aVx, Dist2, Dist2Min;
+        Extrema_POnSurf aPx;
+        //
+        iNear = 1;
+        Dist2Min = Ext.SquareDistance(1);
+        iEnd = Ext.NbExt();
+        for (i = 2; i <= iEnd; i++) {
+          aPx=Ext.Point(i);
+          aPx.Parameter(aUx, aVx);
+          if (aUx>=U1 && aUx<=U2 && aVx>=V1 && aVx<=V2) {
+            Dist2 = Ext.SquareDistance(i);
+            if (Dist2 < Dist2Min) {
+              Dist2Min = Dist2; 
+              iNear = i;
+            }
+          }
+        }
+        //
+        Standard_Real aDist2Tresh=1.e-24;
+        //
+        if (Dist2Min<aDist2Tresh) {
+          if (anInfFlag) {
+            return 1;
+          } 
+          else {
+            BRepClass_FaceClassifier classifier2d;
+            Standard_Real            aU;
+            Standard_Real            aV;
+
+            (Ext.Point(iNear)).Parameter(aU, aV);
+
+            gp_Pnt2d aPuv(aU, aV);
+
+            classifier2d.Perform(face,aPuv,Precision::PConfusion());
+
+            TopAbs_State aState = classifier2d.State();
+
+            if (aState == TopAbs_IN || aState == TopAbs_ON) {
+              return 1;
+            }
+            else {
+              return 3; // skv - the point is on surface but outside face.
+            }
+          }
+        }
+        if (anInfFlag) {
+          APoint = (Ext.Point(iNear)).Value();
+          gp_Vec V(P,APoint);
+          _Par = V.Magnitude(); 
+          L = gp_Lin(P,V);
+          ptfound=Standard_True;
+          return 0;
+        }
+
+        // set the parameters found by extrema
+        aPx = Ext.Point(iNear);
+        aPx.Parameter(_u, _v);
+        APoint = aPx.Value();
       }
       //The point is not ON the face or surface. The face is restricted.
       // find point in a face not too far from a projection of P on face
@@ -516,7 +597,9 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
           ++NbPointsOK;
           gp_Vec V (P, APoint);
           Par = V.Magnitude();
-          if (Par > gp::Resolution())
+          if (Par > gp::Resolution() &&
+              aVecD1U.Magnitude() > gp::Resolution() &&
+              aVecD1V.Magnitude() > gp::Resolution())
           {
             gp_Vec Norm = aVecD1U.Crossed (aVecD1V);
             Standard_Real tt = Norm.Magnitude();
@@ -539,8 +622,8 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
       while(IndexPoint<200 && NbPointsOK<16);
 
       myParamOnEdge=svmyparam;
-      if(maxscal>0.2) {                  
-       return 0;
+      if(maxscal>0.2) {                  
+        return 0;
       }
 
 
@@ -552,23 +635,23 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
 
       Standard_Boolean encoreuneface = faceexplorer.More();
       if(ptfound==Standard_False && encoreuneface==Standard_False) { 
-       if(myParamOnEdge < 0.0001) { 
-         //-- This case takes place when the point is on the solid
-         //-- and this solid is reduced to a face 
-         gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
-         gp_Vec V(P,PBidon);
-         Par= 1.0;
-         _Par=Par;
-         L  = gp_Lin(P,V);
-         return 0;
-       }
+        if(myParamOnEdge < 0.0001) { 
+          //-- This case takes place when the point is on the solid
+          //-- and this solid is reduced to a face 
+          gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
+          gp_Vec V(P,PBidon);
+          Par= 1.0;
+          _Par=Par;
+          L  = gp_Lin(P,V);
+          return 0;
+        }
       }
     } //-- Exploration of the faces   
 
     if(NbFacesInSolid==0) { 
       _Par=0.0;
       myReject=Standard_True;
-#if DEB
+#ifdef OCCT_DEBUG
       cout<<"\nWARNING : BRepClass3d_SolidExplorer.cxx  (Solid without face)"<<endl;
 #endif  
       return 0;
@@ -590,14 +673,15 @@ Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P,
     else {
       myParamOnEdge*=0.5;  
       if(myParamOnEdge < 0.0001) { 
-       gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
-       gp_Vec V(P,PBidon);
-       Par= 1.0;
-       _Par=Par;
-       L  = gp_Lin(P,V);
-       return 0;
+        gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
+        gp_Vec V(P,PBidon);
+        Par= 1.0;
+        _Par=Par;
+        L  = gp_Lin(P,V);
+        return 0;
       }
     }
+    aTestInvert = Standard_True;
   } //-- for(;;) { ...  } 
 }
 
@@ -711,11 +795,11 @@ BRepClass3d_SolidExplorer::BRepClass3d_SolidExplorer(const TopoDS_Shape& S)
 }
 
 //=======================================================================
-//function : Delete
-//purpose  : 
+//function : ~BRepClass3d_SolidExplorer
+//purpose  :
 //=======================================================================
 
-void BRepClass3d_SolidExplorer::Delete()
+BRepClass3d_SolidExplorer::~BRepClass3d_SolidExplorer()
 {
  Destroy() ;
 }
@@ -744,6 +828,9 @@ void BRepClass3d_SolidExplorer::Destroy() {
 
 void BRepClass3d_SolidExplorer::InitShape(const TopoDS_Shape& S)
 {
+  myMapEV.Clear();
+  myTree.Clear();
+
   myShape = S;
   myFirstFace = 0;
   myParamOnEdge = 0.512345;
@@ -768,20 +855,61 @@ void BRepClass3d_SolidExplorer::InitShape(const TopoDS_Shape& S)
       Expl.More();
       Expl.Next()) { 
     const TopoDS_Face Face = TopoDS::Face(Expl.Current());
-    void *ptr = (void *)(new IntCurvesFace_Intersector(Face,Precision::Confusion()));
+    void *ptr = (void *)(new IntCurvesFace_Intersector(Face,Precision::Confusion(),Standard_True, Standard_False));
     myMapOfInter.Bind(Face,ptr);
     myReject=Standard_False;  //-- at least one face in the solid 
   }
   
-#if DEB
+#ifdef OCCT_DEBUG
   if(myReject) { 
     cout<<"\nWARNING : BRepClass3d_SolidExplorer.cxx  (Solid without face)"<<endl;
   }
-#endif      
+#endif
 
 #if REJECTION
   BRepBndLib::Add(myShape,myBox);
 #endif
+
+  // since the internal/external parts should be avoided in tree filler,
+  // there is no need to add these parts in the EV map as well
+  TopExp_Explorer aExpF(myShape, TopAbs_FACE);
+  for (; aExpF.More(); aExpF.Next()) {
+    const TopoDS_Shape& aF = aExpF.Current();
+    //
+    TopAbs_Orientation anOrF = aF.Orientation();
+    if (anOrF == TopAbs_INTERNAL || anOrF == TopAbs_EXTERNAL) {
+      continue;
+    }
+    //
+    TopExp_Explorer aExpE(aF, TopAbs_EDGE);
+    for (; aExpE.More(); aExpE.Next()) {
+      const TopoDS_Shape& aE = aExpE.Current();
+      //
+      TopAbs_Orientation anOrE = aE.Orientation();
+      if (anOrE == TopAbs_INTERNAL || anOrE == TopAbs_EXTERNAL) {
+        continue;
+      }
+      //
+      if (BRep_Tool::Degenerated(TopoDS::Edge(aE))) {
+        continue;
+      }
+      //
+      TopExp::MapShapes(aE, myMapEV);
+    }
+  }
+  //
+  // Fill mapEV with vertices and edges from shape
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (myTree);
+  //
+  Standard_Integer i, aNbEV = myMapEV.Extent();
+  for (i = 1; i <= aNbEV; ++i) {
+    const TopoDS_Shape& aS = myMapEV(i);
+    //
+    Bnd_Box aBox;
+    BRepBndLib::Add(aS, aBox);
+    aTreeFiller.Add(i, aBox);
+  }
+  aTreeFiller.Fill();
 }
 
 //=======================================================================
@@ -895,7 +1023,7 @@ Standard_Boolean BRepClass3d_SolidExplorer::RejectFace(const gp_Lin& ) const
   return(Standard_False); 
 }
 
-#ifdef DEB
+#ifdef OCCT_DEBUG
 #include <TopAbs_State.hxx>
 #endif
 
@@ -906,8 +1034,8 @@ Standard_Boolean BRepClass3d_SolidExplorer::RejectFace(const gp_Lin& ) const
 //           compute  intersections. 
 //=======================================================================
 Standard_Integer  BRepClass3d_SolidExplorer::Segment(const gp_Pnt& P, 
-                                                    gp_Lin& L, 
-                                                    Standard_Real& Par)  
+                                                     gp_Lin& L, 
+                                                     Standard_Real& Par)  
 {
   Standard_Integer bRetFlag;
   myFirstFace = 0;
@@ -941,11 +1069,16 @@ const Bnd_Box& BRepClass3d_SolidExplorer::Box() const {
 //=======================================================================
 
 void BRepClass3d_SolidExplorer::DumpSegment(const gp_Pnt&,
-                                           const gp_Lin&,
-                                           const Standard_Real,
-                                           const TopAbs_State) const
+                                            const gp_Lin&,
+                                            const Standard_Real,
+                                            const TopAbs_State) const
 {
-#ifdef DEB
+#ifdef OCCT_DEBUG
  
 #endif
 }
+
+const TopoDS_Shape& BRepClass3d_SolidExplorer::GetShape() const 
+{ 
+  return(myShape);
+}