0024667: BRepOffsetAPI_MakePipe::FirstShape() and LastShape() return shapes not from...
[occt.git] / src / BRepFill / BRepFill_Pipe.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 9605033..8620b0e
@@ -1,23 +1,18 @@
 // Created on: 1994-06-07
 // Created by: Bruno DUMORTIER
 // Copyright (c) 1994-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 <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>
@@ -44,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 <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_SequenceOfShape ModEdges;
+      TopoDS_Iterator itw(aWire);
+      for (; itw.More(); itw.Next())
+      {
+        TopoDS_Shape anEdge = itw.Value();
+        if (Emap.Contains(anEdge))
+          ModEdges.Append(anEdge);
+      }
+      aWire.Free(Standard_True);
+      for (Standard_Integer ii = 1; ii <= ModEdges.Length(); ii++)
+      {
+        BB.Remove(aWire, ModEdges(ii));
+        BB.Add(aWire, ModEdges(ii).Reversed());
+      }
+    }
+  }
+}
+
+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  : 
@@ -64,8 +150,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;
 }
 
 
@@ -76,15 +167,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  : 
@@ -92,7 +200,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();
@@ -107,9 +215,21 @@ 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);
@@ -145,9 +265,22 @@ 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);
+    TopLoc_Location theIdentity;
+    NewMyFirst.Location(theIdentity);
+    myFirst = BRepBuilderAPI_Transform(NewMyFirst, theLoc.Transformation());
+  }
+  
   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
 //    try { // Not good, but there are no other means to test SetValues
@@ -160,12 +293,25 @@ 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);
+    TopLoc_Location theIdentity;
+    NewMyLast.Location(theIdentity);
+    myLast = BRepBuilderAPI_Transform(NewMyLast, theLoc.Transformation());
+  }
+  
 #if DRAW
   if (Affich) {
     DBRep::Set("theprof",  TheProf);
@@ -349,7 +495,7 @@ TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
 //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)
 {
  // Postioning 
  gp_Pnt P;
@@ -362,7 +508,9 @@ TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
 
  // 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());
@@ -449,7 +597,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 :
@@ -458,10 +606,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
       explode = Standard_True;
       break;
     }
-#ifndef DEB
   default:
     break;
-#endif    
   }
 
   if (explode) {
@@ -489,8 +635,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 ) {
@@ -499,8 +656,13 @@ 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);
 
       // Labeling of elements
       if (mySections.IsNull()) {
@@ -526,7 +688,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(); 
@@ -535,7 +696,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));   
@@ -554,13 +717,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++) {
@@ -572,6 +744,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));
     }
 
@@ -595,7 +771,6 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
   else {
     return result;
   }
-  return result;
 }
 
 //============================================================================
@@ -644,10 +819,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; 
@@ -712,10 +885,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; 
@@ -771,3 +942,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));
+    }
+  }
+}