0021762: Integration of new Boolean Operation algorithm to OCCT.
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_8.cxx
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_8.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_8.cxx
new file mode 100644 (file)
index 0000000..17e11f8
--- /dev/null
@@ -0,0 +1,375 @@
+// Created by: Peter KURNEV
+// Copyright (c) 2010-2012 OPEN CASCADE SAS
+// 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
+//
+// 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.
+//
+// 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.
+//
+// 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.
+
+
+#include <BOPAlgo_PaveFiller.ixx>
+
+#include <Precision.hxx>
+
+#include <NCollection_IncAllocator.hxx>
+
+#include <gp_Pnt2d.hxx>
+#include <gp_Lin2d.hxx>
+#include <ElCLib.hxx>
+
+#include <IntRes2d_IntersectionPoint.hxx>
+
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2dInt_GInter.hxx>
+
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#include <BRep_Tool.hxx>
+#include <BRep_Builder.hxx>
+
+#include <BOPCol_ListOfInteger.hxx>
+
+#include <BOPDS_ShapeInfo.hxx>
+#include <BOPDS_DS.hxx>
+#include <BOPDS_FaceInfo.hxx>
+#include <BOPDS_MapOfPaveBlock.hxx>
+#include <BOPDS_PaveBlock.hxx>
+#include <BOPDS_Pave.hxx>
+
+static
+  void MakeSplitEdge1 (const TopoDS_Edge&   aE,
+                       const TopoDS_Face&   aF,
+                       const TopoDS_Vertex& aV1,
+                       const Standard_Real  aP1,
+                       const TopoDS_Vertex& aV2,
+                       const Standard_Real  aP2,
+                       TopoDS_Edge& aNewEdge);
+
+//=======================================================================
+//function : ProcessDE
+//purpose  : 
+//=======================================================================
+  void BOPAlgo_PaveFiller::ProcessDE()
+{
+  Standard_Integer nF, aNb, nE, nV, nVSD, aNbPB;
+  Handle(NCollection_IncAllocator) aAllocator;
+  Handle(BOPDS_PaveBlock) aPBD;
+  BOPCol_ListIteratorOfListOfInteger aItLI;
+  //
+  myErrorStatus=0;
+  //
+  // 1. Find degnerated edges
+  //-----------------------------------------------------scope f
+  //
+  aAllocator=new NCollection_IncAllocator();
+  BOPDS_ListOfPaveBlock aLPBOut(aAllocator);
+  //
+  aNb=myDS->NbSourceShapes();
+  for (nE=0; nE<aNb; ++nE) {
+    const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
+    if (aSIE.ShapeType()==TopAbs_EDGE) {
+      if (aSIE.HasFlag(nF)) {
+        const BOPDS_ShapeInfo& aSIF=myDS->ShapeInfo(nF);
+        nV=aSIE.SubShapes().First();
+        if (myDS->HasShapeSD(nV, nVSD)) {
+          nV=nVSD;
+        }
+        //nV,nE,nF
+        //
+        if (aSIF.ShapeType() == TopAbs_FACE) {
+          // 1. Find PaveBlocks that are go through nV for nF
+          FindPaveBlocks(nV, nF, aLPBOut);
+          aNbPB=aLPBOut.Extent();
+          if (!aNbPB) {
+            continue;
+          }
+          //
+          // 2.
+          BOPDS_ListOfPaveBlock& aLPBD=myDS->ChangePaveBlocks(nE);
+          aPBD=aLPBD.First();
+          //
+          FillPaves(nV, nE, nF, aLPBOut, aPBD);
+          //
+          myDS->UpdatePaveBlock(aPBD);
+          //
+          MakeSplitEdge(nE, nF);
+          //
+          aLPBOut.Clear();
+        }
+        if (aSIF.ShapeType() == TopAbs_EDGE) {
+          Standard_Real aTol=1.e-7;
+          Standard_Integer nEn;
+          BRep_Builder BB;
+          const TopoDS_Edge& aDE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
+          const TopoDS_Vertex& aVn = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
+          //
+          TopoDS_Edge aE=aDE;
+          aE.EmptyCopy();
+          BB.Add(aE, aVn);
+          BB.Degenerated(aE, Standard_True);
+          BB.UpdateEdge(aE, aTol);
+          BOPDS_ShapeInfo aSI;
+          aSI.SetShapeType(TopAbs_EDGE);
+          aSI.SetShape(aE);
+          nEn=myDS->Append(aSI);
+          BOPDS_ListOfPaveBlock& aLPBD=myDS->ChangePaveBlocks(nE);
+          aPBD=aLPBD.First();
+          aPBD->SetEdge(nEn);
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : FindPaveBlocks
+//purpose  : 
+//=======================================================================
+  void BOPAlgo_PaveFiller::FindPaveBlocks(const Standard_Integer nV,
+                                          const Standard_Integer nF,
+                                          BOPDS_ListOfPaveBlock& aLPBOut)
+{
+  Standard_Integer nV1, nV2;
+  BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
+  //
+  const BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
+  // In
+  const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
+  aItMPB.Initialize(aMPBIn);
+  for(; aItMPB.More(); aItMPB.Next()) {
+    const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
+    aPB->Indices(nV1, nV2);
+    if (nV==nV1 || nV==nV2) {
+      aLPBOut.Append(aPB);
+    }
+  }
+  // On
+  const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
+  aItMPB.Initialize(aMPBOn);
+  for(; aItMPB.More(); aItMPB.Next()) {
+    const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
+    aPB->Indices(nV1, nV2);
+    if (nV==nV1 || nV==nV2) {
+      aLPBOut.Append(aPB);
+    }
+  }
+  // Sections
+  const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
+  aItMPB.Initialize(aMPBSc);
+  for(; aItMPB.More(); aItMPB.Next()) {
+    const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
+    aPB->Indices(nV1, nV2);
+    if (nV==nV1 || nV==nV2) {
+      aLPBOut.Append(aPB);
+    }
+  }
+}
+
+//=======================================================================
+//function : MakeSplitEdge
+//purpose  : 
+//=======================================================================
+  void BOPAlgo_PaveFiller::MakeSplitEdge (const Standard_Integer nDE,
+                                          const Standard_Integer nDF)
+{ 
+  Standard_Integer nSp, nV1, nV2, aNbPB;
+  Standard_Real aT1, aT2;
+  TopoDS_Edge aDE, aSp;
+  TopoDS_Vertex aV1, aV2;
+  BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
+  BOPDS_ShapeInfo aSI;
+  //
+  aSI.SetShapeType(TopAbs_EDGE);
+  //
+  aDE=(*(TopoDS_Edge *)(&myDS->Shape(nDE))); 
+  aDE.Orientation(TopAbs_FORWARD);
+  //
+  const TopoDS_Face& aDF=(*(TopoDS_Face *)(&myDS->Shape(nDF)));
+  //
+  BOPDS_ListOfPaveBlock& aLPB=myDS->ChangePaveBlocks(nDE);
+  aNbPB=aLPB.Extent();
+  //
+  aItLPB.Initialize(aLPB);
+  for (; aItLPB.More(); aItLPB.Next()) {
+    Handle(BOPDS_PaveBlock)& aPB=aItLPB.ChangeValue();
+    //
+    const BOPDS_Pave& aPave1=aPB->Pave1();
+    aPave1.Contents(nV1, aT1);
+    //
+    const BOPDS_Pave& aPave2=aPB->Pave2();
+    aPave2.Contents(nV2, aT2);
+    //
+    if (myDS->IsNewShape(nV1) || aNbPB>1) {
+      aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
+      aV1.Orientation(TopAbs_FORWARD); 
+      //
+      aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
+      aV2.Orientation(TopAbs_REVERSED); 
+      //
+      MakeSplitEdge1(aDE, aDF, aV1, aT1, aV2, aT2, aSp); 
+      //
+      aSI.SetShape(aSp);
+      nSp=myDS->Append(aSI);
+      aPB->SetEdge(nSp);
+    }
+    else {
+      //aPB->SetEdge(nDE);
+      aLPB.Clear();
+      break;
+    }
+  }
+}
+
+//=======================================================================
+//function : FillPaves
+//purpose  : 
+//=======================================================================
+  void BOPAlgo_PaveFiller::FillPaves(const Standard_Integer nVD,
+                                     const Standard_Integer nED,
+                                     const Standard_Integer nFD,
+                                     const BOPDS_ListOfPaveBlock& aLPBOut,
+                                     const Handle(BOPDS_PaveBlock)& aPBD)
+{
+  Standard_Boolean bXDir, bIsDone, bReject;
+  Standard_Integer nE, aNbPoints, j;
+  Standard_Real aTD1, aTD2, aT1, aT2, aTolInter, aX, aDT;
+  Standard_Real aTolCmp;
+  gp_Pnt2d aP2d1, aP2d2, aP2D;
+  gp_Lin2d aLDE;
+  Handle(Geom2d_Line) aCLDE;
+  Handle(Geom2d_Curve) aC2DDE1, aC2D;
+  Handle(Geom2d_TrimmedCurve)aC2DDE;
+  BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
+  BOPDS_Pave aPave;
+  //
+  aDT=Precision::PConfusion();
+  //
+  aPave.SetIndex(nVD);
+  //
+  const TopoDS_Edge& aDE=(*(TopoDS_Edge *)(&myDS->Shape(nED)));
+  const TopoDS_Face& aDF=(*(TopoDS_Face *)(&myDS->Shape(nFD)));
+  //aC2DDE
+  aC2DDE1=BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
+  aC2DDE=new Geom2d_TrimmedCurve(aC2DDE1, aTD1, aTD2);
+  //aCLDE
+  Handle(Geom2d_TrimmedCurve) aCLDET1=Handle(Geom2d_TrimmedCurve)::DownCast(aC2DDE1);
+  if (aCLDET1.IsNull()) {
+    aCLDE=Handle(Geom2d_Line)::DownCast(aC2DDE1);
+  }
+  else {
+    Handle(Geom2d_Curve) aBasisCurve=aCLDET1->BasisCurve();
+    aCLDE=Handle(Geom2d_Line)::DownCast(aBasisCurve);
+  }
+  //
+  // Choose direction for degenerated edge
+  aC2DDE->D0(aTD1, aP2d1);
+  aC2DDE->D0(aTD2, aP2d2);
+  //
+  bXDir=Standard_False;
+  if (fabs(aP2d1.Y()-aP2d2.Y()) < aDT){
+    bXDir=!bXDir;
+  }
+  //
+  aItLPB.Initialize(aLPBOut);
+  for (; aItLPB.More(); aItLPB.Next()) {
+    const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
+    nE=aPB->Edge();
+    const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
+    aC2D=BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
+    if (aC2D.IsNull()) {
+      continue;
+    }
+    //
+    // Intersection
+    Geom2dAdaptor_Curve aGAC1, aGAC2;
+    aGAC1.Load(aC2DDE, aTD1, aTD2);
+    //
+    Handle(Geom2d_Line) aL2D= Handle(Geom2d_Line)::DownCast(aC2D);
+    if (!aL2D.IsNull()) {
+      aGAC2.Load(aC2D);
+    }
+    else {
+      aGAC2.Load(aC2D, aT1, aT2);
+    }
+    //
+    aTolInter=0.001;
+    aTolCmp=1.414213562*aTolInter+aDT;
+    Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInter, aTolInter);
+    bIsDone=aGInter.IsDone();
+    if(!bIsDone) {
+      continue;
+    }
+    //
+    aNbPoints=aGInter.NbPoints();
+    if (!aNbPoints){
+      continue;
+    }
+    //
+    for (j=1; j<=aNbPoints; ++j) {
+      aP2D=aGInter.Point(j).Value();
+      aX=aGInter.Point(j).ParamOnFirst();
+      //
+      if (fabs (aX-aTD1) < aTolCmp || fabs (aX-aTD2) < aTolCmp) {
+        continue; 
+      }
+      if (aX < aTD1 || aX > aTD2) {
+        continue; 
+      }
+      //
+      bReject=Standard_False;
+      if (aPBD->ContainsParameter(aX, aDT)) {
+        continue;
+      }
+      aPave.SetParameter(aX);
+      aPBD->AppendExtPave1(aPave);
+    }
+  }//for (; aItLPB.More(); aItLPB.Next()) {
+  //
+  myDS->UpdatePaveBlock(aPBD);
+}
+//=======================================================================
+// function:  MakeSplitEdge1
+// purpose: 
+//=======================================================================
+  void MakeSplitEdge1 (const TopoDS_Edge&   aE,
+                       const TopoDS_Face&   aF,
+                       const TopoDS_Vertex& aV1,
+                       const Standard_Real  aP1,
+                       const TopoDS_Vertex& aV2,
+                       const Standard_Real  aP2,
+                       TopoDS_Edge& aNewEdge)
+{
+  Standard_Real aTol=1.e-7;
+
+  TopoDS_Edge E=aE;
+
+  E.EmptyCopy();
+  BRep_Builder BB;
+  BB.Add  (E, aV1);
+  BB.Add  (E, aV2);
+
+  BB.Range(E, aF, aP1, aP2);
+
+  BB.Degenerated(E, Standard_True);
+
+  BB.UpdateEdge(E, aTol);
+  aNewEdge=E;
+}