0025243: BRepFeat_SplitShape algorithm processes incorrect faces with degenerated...
[occt.git] / src / LocOpe / LocOpe_WiresOnShape.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 4849783..905d616
@@ -1,24 +1,18 @@
 // Created on: 1996-01-11
 // Created by: Jacques GOUSSARD
 // Copyright (c) 1996-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// 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.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <LocOpe_WiresOnShape.ixx>
 
@@ -30,6 +24,7 @@
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>
 #include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <GeomAdaptor_Surface.hxx>
 #include <Geom_Curve.hxx>
@@ -62,6 +57,7 @@
 
 
 static Standard_Boolean Project(const TopoDS_Vertex&,
+                                const gp_Pnt2d&,
                                const TopoDS_Face&,
                                TopoDS_Edge&,
                                Standard_Real&);
@@ -69,6 +65,11 @@ static Standard_Boolean Project(const TopoDS_Vertex&,
 static Standard_Real Project(const TopoDS_Vertex&,
                             const TopoDS_Edge&);
 
+static Standard_Real Project(const TopoDS_Vertex&,
+                             const gp_Pnt2d&,
+                            const TopoDS_Edge&,
+                             const TopoDS_Face&);
+
 
 static void PutPCurve(const TopoDS_Edge&,
                      const TopoDS_Face&);
@@ -90,7 +91,7 @@ static void FindInternalIntersections(const TopoDS_Edge&,
 //=======================================================================
 
 LocOpe_WiresOnShape::LocOpe_WiresOnShape(const TopoDS_Shape& S):
-   myShape(S),myDone(Standard_False)
+  myShape(S),myCheckInterior(Standard_True),myDone(Standard_False)
 {}
 
 
@@ -103,6 +104,7 @@ LocOpe_WiresOnShape::LocOpe_WiresOnShape(const TopoDS_Shape& S):
 void LocOpe_WiresOnShape::Init(const TopoDS_Shape& S)
 {
    myShape = S;
+   myCheckInterior = Standard_True;
    myDone = Standard_False;
    myMap.Clear();
    myMapEF.Clear();
@@ -240,7 +242,8 @@ void LocOpe_WiresOnShape::BindAll()
     if (aPCurve.IsNull())
       continue;
 
-    FindInternalIntersections(edg, fac, Splits, myMap, theMap);
+    if (myCheckInterior)
+      FindInternalIntersections(edg, fac, Splits, myMap, theMap);
   }
 
   for (Ind = 1; Ind <= Splits.Extent(); Ind++)
@@ -278,9 +281,14 @@ void LocOpe_WiresOnShape::BindAll()
       if (theMap.Contains(vtx)) {
        continue;
       }
+      ////
+      Standard_Real vtx_param = BRep_Tool::Parameter(vtx, edg);
+      BRepAdaptor_Curve2d BAcurve2d(edg, fac);
+      gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
+      ////
       TopoDS_Edge Epro;
-      Standard_Real prm;
-      Standard_Boolean ok = Project(vtx,fac,Epro,prm);
+      Standard_Real prm = 0.;
+      Standard_Boolean ok = Project(vtx, p2d, fac, Epro, prm);
       if (ok) {
        for (exp2.Init(Epro,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
          const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
@@ -288,8 +296,13 @@ void LocOpe_WiresOnShape::BindAll()
            break;
          }
          else if (BRepTools::Compare(vtx,vtx2)) {
-           myMap.Bind(vtx,vtx2);
-           break;
+            if (!BRep_Tool::Degenerated(Epro) ||
+                Abs(prm-BAcurve2d.FirstParameter()) <= Precision::PConfusion() ||
+                Abs(prm-BAcurve2d.LastParameter())  <= Precision::PConfusion())
+            {
+              myMap.Bind(vtx,vtx2);
+              break;
+            }
          }
        }
        if (!exp2.More()) {
@@ -412,8 +425,6 @@ Standard_Boolean LocOpe_WiresOnShape::OnVertex(const TopoDS_Vertex& Vw,
 }
 
 
-
-
 //=======================================================================
 //function : OnEdge
 //purpose  : 
@@ -433,6 +444,32 @@ Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
   return Standard_True;
 }
 
+//=======================================================================
+//function : OnEdge
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
+                                             const TopoDS_Edge& EdgeFrom,
+                                             TopoDS_Edge& Ed,
+                                             Standard_Real& prm)
+{
+  if (!myMap.IsBound(V) ||
+      myMap(V).ShapeType() == TopAbs_VERTEX) {
+    return Standard_False;
+  }
+  
+  Ed = TopoDS::Edge(myMap(V));
+  TopoDS_Face theFace = TopoDS::Face(myMapEF.FindFromKey(EdgeFrom));
+  ////
+  Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom);
+  BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, theFace);
+  gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
+  ////
+  prm = Project(V, p2d, Ed, theFace);
+  return Standard_True;
+}
+
 
 //=======================================================================
 //function : Project
@@ -440,36 +477,32 @@ Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
 //=======================================================================
 
 Standard_Boolean Project(const TopoDS_Vertex& V,
+                         const gp_Pnt2d& p2d,
                         const TopoDS_Face& F,
                         TopoDS_Edge& theEdge,
                         Standard_Real& param)
 {
-  Handle(Geom_Curve) C;
-  TopLoc_Location Loc;
+  Handle(Geom2d_Curve) PC;
+  //TopLoc_Location Loc;
   Standard_Real f,l;
 
   Standard_Real dmin = RealLast();
-  gp_Pnt toproj(BRep_Tool::Pnt(V));
+  //gp_Pnt toproj(BRep_Tool::Pnt(V));
   Standard_Boolean valret = Standard_False;
-  GeomAPI_ProjectPointOnCurve proj;
+  Geom2dAPI_ProjectPointOnCurve proj;
 
   for (TopExp_Explorer exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
        exp.More(); exp.Next()) {
     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
-    if (!BRep_Tool::Degenerated(edg)) {
-      C = BRep_Tool::Curve(edg,Loc,f,l);
-      if (!Loc.IsIdentity()) {
-       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
-       C = *((Handle(Geom_Curve)*)&GG);
-      }
-      proj.Init(toproj,C,f,l);
-      if (proj.NbPoints() > 0) {
-       if (proj.LowerDistance() < dmin) {
-         theEdge = edg;
-         theEdge.Orientation(edg.Orientation());
-         dmin = proj.LowerDistance();
-         param = proj.LowerDistanceParameter();
-       }
+    //C = BRep_Tool::Curve(edg,Loc,f,l);
+    PC = BRep_Tool::CurveOnSurface(edg, F, f, l);
+    proj.Init(p2d, PC, f, l);
+    if (proj.NbPoints() > 0) {
+      if (proj.LowerDistance() < dmin) {
+        theEdge = edg;
+        theEdge.Orientation(edg.Orientation());
+        dmin = proj.LowerDistance();
+        param = proj.LowerDistanceParameter();
       }
     }
   }
@@ -518,6 +551,35 @@ Standard_Real Project(const TopoDS_Vertex& V,
   return proj.LowerDistanceParameter();
 }
 
+//=======================================================================
+//function : Project
+//purpose  : 
+//=======================================================================
+
+Standard_Real Project(const TopoDS_Vertex&,
+                      const gp_Pnt2d&      p2d,
+                     const TopoDS_Edge& theEdge,
+                      const TopoDS_Face& theFace)
+{
+  //Handle(Geom_Curve) C;
+  Handle(Geom2d_Curve) PC;
+  //TopLoc_Location Loc;
+  Standard_Real f,l;
+
+  Geom2dAPI_ProjectPointOnCurve proj;
+
+  PC = BRep_Tool::CurveOnSurface(theEdge, theFace, f, l);
+  /*
+  if (!Loc.IsIdentity()) {
+    Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
+    C = *((Handle(Geom_Curve)*)&GG);
+  }
+  */
+  proj.Init(p2d, PC, f, l);
+
+  return proj.LowerDistanceParameter();
+}
+
 
 //=======================================================================
 //function : PutPCurve
@@ -948,7 +1010,13 @@ void PutPCurves(const TopoDS_Edge& Efrom,
 
     C->D1(f,pt,d1f);
 
-    Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),Eto);
+    ////
+    TopoDS_Vertex FirstVertex = TopExp::FirstVertex(Efrom);
+    Standard_Real vtx_param = BRep_Tool::Parameter(FirstVertex, Efrom);
+    BRepAdaptor_Curve2d BAcurve2d(Efrom, Fac);
+    gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
+    ////
+    Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),p2d,Eto,Fac);
     
     C = BRep_Tool::Curve(Eto,Loc,f,l);
     if (!Loc.IsIdentity()) {
@@ -1082,11 +1150,6 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
   
   TopoDS_Vertex theVertices [2];
   TopExp::Vertices(theEdge, theVertices[0], theVertices[1]);
-  if (theEdge.Orientation() == TopAbs_REVERSED)
-  {
-    theVertices[0].Reverse();
-    theVertices[1].Reverse();
-  }
   gp_Pnt thePnt [2];
   thePnt[0] = BRep_Tool::Pnt(theVertices[0]);
   thePnt[1] = BRep_Tool::Pnt(theVertices[1]);
@@ -1162,7 +1225,7 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
           }
         }
       }
-      if (!IntersFound) //intersection is inside "theEdge" => split
+      if (!IntersFound && aDist <= Precision::Confusion()) //intersection is inside "theEdge" => split
       {
         gp_Pnt aPoint = aCurve->Value(anIntPar);
         if (aPoint.Distance(thePnt[0]) > BRep_Tool::Tolerance(theVertices[0]) &&
@@ -1221,11 +1284,13 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
     LastVertex.Orientation(TopAbs_REVERSED);
     
     TopoDS_Shape aLocalShape = theEdge.EmptyCopied();
+    TopAbs_Orientation anOrient = aLocalShape.Orientation();
+    aLocalShape.Orientation(TopAbs_FORWARD);
     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
     BB.Range(NewEdge, FirstPar, LastPar);
     BB.Add(NewEdge, FirstVertex);
     BB.Add(NewEdge, LastVertex);
-
+    NewEdge.Orientation(anOrient);
     NewEdges.Append(NewEdge);
     FirstVertex = LastVertex;
     FirstPar = LastPar;