0024840: Exception in BRepOffsetAPI_MakePipe
[occt.git] / src / BRepFill / BRepFill_Pipe.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 9cb8712..5e0dc6c
@@ -1,7 +1,18 @@
-// File:       BRepFill_Pipe.cxx
-// Created:    Tue Jun  7 16:31:15 1994
-// Author:     Bruno DUMORTIER
-//             <dub@fuegox>
+// Created on: 1994-06-07
+// Created by: Bruno DUMORTIER
+// Copyright (c) 1994-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// 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 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.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <BRepFill_Pipe.ixx>
 
 #include <BRep_Builder.hxx>
 #include <BRepClass3d_SolidClassifier.hxx>
 #include <BRepLib_MakeVertex.hxx>
+#include <BRepTools_Substitution.hxx>
 
 #include <GeomFill_CorrectedFrenet.hxx>
+#include <GeomFill_Frenet.hxx>
+#include <GeomFill_DiscreteTrihedron.hxx>
 #include <GeomFill_CurveAndTrihedron.hxx>
 
 #include <BRepFill_SectionPlacement.hxx>
@@ -28,6 +42,9 @@
 #include <TopoDS_Solid.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TColStd_DataMapOfIntegerInteger.hxx>
+#include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
 
 #include <Precision.hxx>
 #include <Standard_NotImplemented.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <Geom_OffsetCurve.hxx>
 #include <Geom_BSplineCurve.hxx>
+#include <BRepBuilderAPI_Transform.hxx>
+#include <BRepBuilderAPI_Copy.hxx>
+#include <TopTools_SequenceOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <BRepLib.hxx>
+
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <Adaptor3d_CurveOnSurface.hxx>
+
+#include <ShapeUpgrade_RemoveLocations.hxx>
 
 #ifdef DRAW
 #include <DBRep.hxx>
 static Standard_Boolean Affich = 0;
 #endif
 
+static void ReverseModifiedEdges(TopoDS_Shape& aShape,
+                                 TopTools_MapOfShape& Emap)
+{
+  TopExp_Explorer Explo(aShape, TopAbs_FACE);
+  BRep_Builder BB;
+  
+  for (; Explo.More(); Explo.Next())
+  {
+    TopoDS_Shape aFace = Explo.Current();
+    TopoDS_Iterator itf(aFace);
+    for (; itf.More(); itf.Next())
+    {
+      TopoDS_Shape aWire = itf.Value();
+      TopTools_ListOfShape Ledges;
+      TopoDS_Iterator itw(aWire);
+      for (; itw.More(); itw.Next())
+        Ledges.Append(itw.Value());
+
+      aWire.Free(Standard_True);
+      TopTools_ListIteratorOfListOfShape itl(Ledges);
+      for (; itl.More(); itl.Next())
+        BB.Remove(aWire, itl.Value());
+        
+      for (itl.Initialize(Ledges); itl.More(); itl.Next())
+      {
+        TopoDS_Shape anEdge = itl.Value();
+        if (Emap.Contains(anEdge))
+          anEdge.Reverse();
+        BB.Add(aWire, anEdge);
+      }
+    }
+  }
+}
+
+static void UpdateTolFromTopOrBottomPCurve(const TopoDS_Face& aFace,
+                                           TopoDS_Edge& anEdge)
+{
+  Standard_Real fpar, lpar;
+  Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, aFace, fpar, lpar);
+  if (aPCurve.IsNull())
+    return;
+
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+  if (aCurve.IsNull())
+    return;
+
+  Handle(Geom2dAdaptor_HCurve) GAHC2d = new Geom2dAdaptor_HCurve(aPCurve, fpar, lpar);
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+  Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(aSurf);
+  Adaptor3d_CurveOnSurface ConS(GAHC2d, GAHS);
+
+  Standard_Real Tol = BRep_Tool::Tolerance(anEdge);
+  Standard_Real InitTol = Tol;
+  Standard_Real TolTol = Tol*Tol;
+  const Standard_Integer NCONTROL = 22;
+  Standard_Real delta = (lpar - fpar)/NCONTROL;
+  for (Standard_Integer i = 0; i <= NCONTROL; i++)
+  {
+    Standard_Real par = fpar + i*delta;
+    gp_Pnt pnt = aCurve->Value(par);
+    gp_Pnt prj = ConS.Value(par);
+    Standard_Real sqdist = pnt.SquareDistance(prj);
+    if (sqdist > TolTol)
+      TolTol = sqdist;
+  }
+  Tol = 1.00005 * Sqrt(TolTol);
+  if (Tol >= InitTol)
+  {
+    BRep_Builder BB;
+    BB.UpdateEdge(anEdge, Tol);
+    TopoDS_Iterator itv(anEdge);
+    for (; itv.More(); itv.Next())
+    {
+      TopoDS_Vertex aVertex = TopoDS::Vertex(itv.Value());
+      BB.UpdateVertex(aVertex, Tol);
+    }
+  }
+}
+
 //=======================================================================
 //function : BRepFill_Pipe
 //purpose  : 
@@ -48,8 +155,13 @@ static Standard_Boolean Affich = 0;
 
 BRepFill_Pipe::BRepFill_Pipe()
 {
-  myDegmax = 10;
+  myDegmax = 11;
   mySegmax = 100;
+  myContinuity = GeomAbs_C2;
+  myMode = GeomFill_IsCorrectedFrenet;
+  myForceApproxC1 = Standard_False;
+
+  myCurIndexOfSectionEdge = 1;
 }
 
 
@@ -60,15 +172,32 @@ BRepFill_Pipe::BRepFill_Pipe()
 
 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
                             const TopoDS_Shape& Profile,
+                             const GeomFill_Trihedron aMode,
+                             const Standard_Boolean ForceApproxC1,
                             const Standard_Boolean KPart)
+                             
 {
-  myDegmax = 10;
+  myDegmax = 11;
   mySegmax = 100;
+  
+  myMode = GeomFill_IsCorrectedFrenet;
+  if (aMode == GeomFill_IsFrenet ||
+      aMode == GeomFill_IsCorrectedFrenet ||
+      aMode == GeomFill_IsDiscreteTrihedron)
+    myMode = aMode;
+
+  myContinuity = GeomAbs_C2;
+  if (myMode == GeomFill_IsDiscreteTrihedron)
+    myContinuity = GeomAbs_C0;
+  
+  myForceApproxC1 = ForceApproxC1;
+
+  myCurIndexOfSectionEdge = 1;
+  
   Perform(Spine, Profile, KPart);
 }
 
 
-
 //=======================================================================
 //function : Perform
 //purpose  : 
@@ -76,7 +205,7 @@ BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
 
 void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
                            const TopoDS_Shape& Profile,
-                           const Standard_Boolean KPart)
+                           const Standard_Boolean /*KPart*/)
 
 {
   mySections.Nullify();
@@ -91,16 +220,28 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
   BRepTools_WireExplorer wexp;
   TopoDS_Shape TheProf; 
 
-
- Handle(GeomFill_CorrectedFrenet) TLaw = 
-   new (GeomFill_CorrectedFrenet) ();
+  Handle(GeomFill_TrihedronLaw) TLaw;
+  switch (myMode)
+  {
+  case GeomFill_IsFrenet:
+    TLaw = new GeomFill_Frenet();
+    break;
+  case GeomFill_IsCorrectedFrenet:
+    TLaw = new GeomFill_CorrectedFrenet();
+    break;
+  case GeomFill_IsDiscreteTrihedron:
+    TLaw = new GeomFill_DiscreteTrihedron();
+    break;
+  default:
+    break;
+  }
   Handle(GeomFill_CurveAndTrihedron) Loc = 
     new (GeomFill_CurveAndTrihedron) (TLaw);
   myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
   if (myLoc->NbLaw() == 0) {
-    return; // Cas degenere
+    return; // Degenerated case
   }
-  myLoc->TransformInG0Law(); // Mise en continuite
+  myLoc->TransformInG0Law(); // Set into continuity
     
   BRepFill_SectionPlacement Place(myLoc, Profile);
   myTrsf = Place.Transformation();
@@ -111,7 +252,7 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
   TheProf =  myProfile;
   TheProf.Location(Loc2.Multiplied(Loc1));
  
-  // Construit les Shape First && Last
+  // Construct First && Last Shape
   Handle(GeomFill_LocationLaw) law;
 
   gp_Mat M;
@@ -129,12 +270,27 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
   TopLoc_Location LocFirst(fila);
   myFirst = myProfile;
   if ( ! LocFirst.IsIdentity()) {
-    myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
+    //myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
+    myFirst = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
   }
 
+  ShapeUpgrade_RemoveLocations RemLoc;
+  RemLoc.Remove(myFirst);
+  myFirst = RemLoc.GetResult();
+  TopLoc_Location theLoc = myFirst.Location();
+  if (!theLoc.IsIdentity())
+  {
+    TopoDS_Shape NewMyFirst = BRepBuilderAPI_Copy(myFirst);
+    RemLoc.Remove(NewMyFirst);
+    NewMyFirst = RemLoc.GetResult();
+    TopLoc_Location theIdentity;
+    NewMyFirst.Location(theIdentity);
+    myFirst = BRepBuilderAPI_Transform(NewMyFirst, theLoc.Transformation(), Standard_True);
+  }
+  
   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
-//    try { // Pas joli mais il n'y as pas d'autre moyens de tester SetValues
+//    try { // Not good, but there are no other means to test SetValues
   fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
                 M(2,1), M(2,2), M(2,3), V.Y(),
                 M(3,1), M(3,2), M(3,3), V.Z(),
@@ -144,12 +300,27 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
   if (! myLoc->IsClosed() || LocFirst != LocLast) {
     myLast = myProfile;
     if ( ! LocLast.IsIdentity()) {
-      myLast.Location(LocLast.Multiplied(myProfile.Location()) );
+      //myLast.Location(LocLast.Multiplied(myProfile.Location()) );
+      myLast = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
     }
   }
   else {
     myLast = myFirst;
   }
+
+  RemLoc.Remove(myLast);
+  myLast = RemLoc.GetResult();
+  theLoc = myLast.Location();
+  if (!theLoc.IsIdentity())
+  {
+    TopoDS_Shape NewMyLast = BRepBuilderAPI_Copy(myLast);
+    RemLoc.Remove(NewMyLast);
+    NewMyLast = RemLoc.GetResult();
+    TopLoc_Location theIdentity;
+    NewMyLast.Location(theIdentity);
+    myLast = BRepBuilderAPI_Transform(NewMyLast, theLoc.Transformation(), Standard_True);
+  }
+  
 #if DRAW
   if (Affich) {
     DBRep::Set("theprof",  TheProf);
@@ -330,12 +501,12 @@ TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
 
 //=======================================================================
 //function : PipeLine
-//purpose  : Construit un wire par balayage d'un point
+//purpose  : Construct a wire by sweeping of a point
 //=======================================================================
 
-TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
+TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point)
 {
- // Postionnement
+ // Postioning 
  gp_Pnt P;
  P = Point;
  P.Transform(myTrsf);
@@ -344,9 +515,11 @@ TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
  Handle(BRepFill_ShapeLaw) Section = 
        new (BRepFill_ShapeLaw) (MkV.Vertex());
 
- // Balayage
+ // Sweeping
  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
- MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+ MkSw.SetForceApproxC1(myForceApproxC1);
+ MkSw.Build( myReversedEdges, myTapes,
+             BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
  TopoDS_Shape aLocalShape = MkSw.Shape();
  return TopoDS::Wire(aLocalShape);
 // return TopoDS::Wire(MkSw.Shape());
@@ -433,7 +606,7 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
 
   case TopAbs_SOLID :
   case TopAbs_COMPSOLID :
-    Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
+    Standard_DomainError::Raise("BRepFill_Pipe::profile contains solids");
     break;
 
   case TopAbs_COMPOUND :
@@ -442,10 +615,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
       explode = Standard_True;
       break;
     }
-#ifndef DEB
   default:
     break;
-#endif    
   }
 
   if (explode) {
@@ -473,8 +644,19 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
      Handle(BRepFill_ShapeLaw) Section = 
        new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
-      MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+      MkSw.SetForceApproxC1(myForceApproxC1);
+      MkSw.Build( myReversedEdges, myTapes,
+                  BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
       result = MkSw.Shape();
+
+      Handle(TopTools_HArray2OfShape) aSections = MkSw.Sections();
+
+      if (aSections.IsNull() == Standard_False) {
+        const Standard_Integer aVLast = aSections->UpperCol();
+
+        myFirst = aSections->Value(1, 1);
+        myLast  = aSections->Value(1, aVLast);
+      }
     }
 
     if (TheS.ShapeType() == TopAbs_WIRE ) {
@@ -483,10 +665,15 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
                     TopoDS::Wire(TheLast));
-      MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+      MkSw.SetForceApproxC1(myForceApproxC1);
+      MkSw.Build( myReversedEdges, myTapes,
+                  BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
       result = MkSw.Shape();
+      //Correct <myFirst> and <myLast>
+      ReverseModifiedEdges(myFirst, myReversedEdges);
+      ReverseModifiedEdges(myLast, myReversedEdges);
 
-      // Reperage des elements
+      // Labeling of elements
       if (mySections.IsNull()) {
        myFaces    = MkSw.SubShape();
        mySections = MkSw.Sections();
@@ -510,7 +697,6 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
            Somme->SetValue(ii, jj, Aux->Value(kk, jj));
        }
        myFaces = Somme;    
-       
 
        Aux = MkSw.Sections();
        length = Aux->ColLength() + mySections->ColLength(); 
@@ -519,7 +705,9 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
        for (jj=1; jj<=mySections->RowLength(); jj++) {
          for (ii=1; ii<=mySections->ColLength(); ii++)
            Somme->SetValue(ii, jj, mySections->Value(ii, jj));
+
+          myCurIndexOfSectionEdge = mySections->ColLength()+1;
+          
          for (kk=1, ii=mySections->ColLength()+1; 
               kk <=Aux->ColLength(); kk++, ii++)
            Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
@@ -538,13 +726,22 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
               kk <=Aux->ColLength(); kk++, ii++)
            Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
        }
-       myEdges = Somme;               
+
+       myEdges = Somme;
       }
     }
   }
       
   if ( TheS.ShapeType() == TopAbs_FACE ) {
     Standard_Integer ii, jj;
+    //jgv
+    TopExp_Explorer Explo(result, TopAbs_FACE);
+    for (; Explo.More(); Explo.Next())
+    {
+      TopoDS_Shape aFace = Explo.Current();
+      RebuildTopOrBottomFace(aFace.Reversed(), Standard_True); //top face was reversed
+    }
+    /////
     TopoDS_Face F;
     for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
       for (jj=1; jj<=myFaces->RowLength(); jj++) {
@@ -556,6 +753,10 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
     if ( !mySpine.Closed()) {
       // if Spine is not closed 
       // add the last face of the solid
+
+      //jgv
+      RebuildTopOrBottomFace(TheLast, Standard_False); //bottom face
+      /////
       B.Add(result, TopoDS::Face(TheLast));
     }
 
@@ -579,14 +780,12 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
   else {
     return result;
   }
-  return result;
 }
 
-//=======================================================================
+//============================================================================
 //function : FindEdge
-//purpose  : Recherche le numero de bande correspondant a une edge du
-//           profil.
-//=======================================================================
+//purpose  : Find the number of edge corresponding to the edge of the profile.
+//============================================================================
 
 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
                                         const TopoDS_Edge& E,
@@ -629,10 +828,8 @@ Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
   case TopAbs_COMPSOLID :
     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
     break;
-#ifndef DEB
   default:
     break;
-#endif
   }
 
   return result; 
@@ -640,8 +837,7 @@ Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
 
 //=======================================================================
 //function : FindVertex
-//purpose  : Recherche le numero de bande correspondant a une edge du
-//           profil.
+//purpose  : Find the number of edge corresponding to an edge of the profile.
 //=======================================================================
 
 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
@@ -698,10 +894,8 @@ Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
   case TopAbs_COMPSOLID :
     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
     break;
-#ifndef DEB
   default:
     break;
-#endif
   }
 
   return result; 
@@ -757,3 +951,48 @@ void BRepFill_Pipe::DefineRealSegmax()
   if (mySegmax < RealSegmax)
     mySegmax = RealSegmax;
 }
+
+//=======================================================================
+//function : RebuildTopOrBottomFace
+//purpose  : Correct orientation of v-iso edges
+//           according to new 3d and 2d curves taken from swept surfaces
+//=======================================================================
+
+void BRepFill_Pipe::RebuildTopOrBottomFace(const TopoDS_Shape& aFace,
+                                           const Standard_Boolean IsTop) const
+{
+  Standard_Integer IndexOfSection =
+    (IsTop)? 1 : mySections->RowLength();
+
+  Standard_Integer ii;
+  BRep_Builder BB;
+  TopoDS_Iterator itf(aFace);
+  for (; itf.More(); itf.Next())
+  {
+    TopoDS_Shape aWire = itf.Value();
+    TopTools_SequenceOfShape InitEdges;
+    TopTools_SequenceOfShape ResEdges;
+    TopoDS_Iterator itw(aWire);
+    for (; itw.More(); itw.Next())
+    {
+      TopoDS_Shape anEdge = itw.Value();
+      for (ii = myCurIndexOfSectionEdge; ii <= mySections->ColLength(); ii++)
+      {
+        TopoDS_Shape aVisoEdge = mySections->Value(ii, IndexOfSection);
+        if (anEdge.IsSame(aVisoEdge))
+        {
+          InitEdges.Append(anEdge);
+          ResEdges.Append(aVisoEdge);
+          break;
+        }
+      }
+    }
+    aWire.Free(Standard_True);
+    for (ii = 1; ii <= InitEdges.Length(); ii++)
+    {
+      BB.Remove(aWire, InitEdges(ii));
+      UpdateTolFromTopOrBottomPCurve(TopoDS::Face(aFace), TopoDS::Edge(ResEdges(ii)));
+      BB.Add(aWire, ResEdges(ii));
+    }
+  }
+}