//=======================================================================
// function:  CommonBlock
// purpose:
//=======================================================================
  NMTTools_CommonBlock& NMTTools_CommonBlockAPI::CommonBlock(const BOPTools_PaveBlock& aPB)const
{
  static NMTTools_CommonBlock aCBTMP;
  //
  NMTTools_ListIteratorOfListOfCommonBlock anItCB;
  BOPTools_ListIteratorOfListOfPaveBlock anItPB;
  //
  NMTTools_ListOfCommonBlock* pLCB=(NMTTools_ListOfCommonBlock*)myListOfCommonBlock;
  //
  anItCB.Initialize(*pLCB);
  for (; anItCB.More(); anItCB.Next()) {
    NMTTools_CommonBlock& aCB=anItCB.ChangeValue();
    //
    const BOPTools_ListOfPaveBlock& aLPB=aCB.PaveBlocks();
    anItPB.Initialize(aLPB);
    for (; anItPB.More(); anItPB.Next()) {
      const BOPTools_PaveBlock& aPBx=anItPB.Value();
      if (aPBx.IsEqual(aPB)) {
        return aCB;
      }
    }
  }
  return aCBTMP;
}
//=======================================================================
// function: UpdateCommonBlocks
// purpose:
//=======================================================================
void NMTTools_PaveFiller::UpdateCommonBlocks()
{
  myIsDone=Standard_False;
  //
  Standard_Integer nE, aNbS,  nSp, nEx, nSpx;
  NMTTools_ListIteratorOfListOfCommonBlock aCBIt;
  BOPTools_ListIteratorOfListOfPaveBlock aPBIt;
  //
  aNbS=myDS->NumberOfShapesOfTheObject();
  //
  for (nE=1; nE<=aNbS; ++nE) {
    if (myDS->GetShapeType(nE)!=TopAbs_EDGE){
      continue;
    }
    if (BRep_Tool::Degenerated(TopoDS::Edge(myDS->Shape(nE)))){
      continue;
    }
    //
    NMTTools_ListOfCommonBlock& aLCB=myCommonBlockPool(myDS->RefEdge(nE));
    /*BOPTools_ListOfPaveBlock& aLPB=*/mySplitShapesPool  (myDS->RefEdge(nE));
    //
    aCBIt.Initialize(aLCB);
    for (; aCBIt.More(); aCBIt.Next()) {
      NMTTools_CommonBlock& aCB=aCBIt.ChangeValue();
      //
      // Among all PBs of aCB the first PB will be one
      // that have max tolerance value
      {
        Standard_Real aTolEx, aTolExMax;
        BOPTools_ListOfPaveBlock *pLPB, aLPBx;
        //
        aTolExMax=-1.;
        pLPB=(BOPTools_ListOfPaveBlock *)&aCB.PaveBlocks();
        aPBIt.Initialize(*pLPB);
        for (; aPBIt.More(); aPBIt.Next()) {
          const BOPTools_PaveBlock& aPBx=aPBIt.Value();
          nEx=aPBx.OriginalEdge();
          const TopoDS_Edge& aEx=TopoDS::Edge(myDS->Shape(nEx));
          aTolEx=BRep_Tool::Tolerance(aEx);
          if (aTolEx>aTolExMax) {
            aTolExMax=aTolEx;
            aLPBx.Prepend(aPBx);
          }
          else{
            aLPBx.Append(aPBx);
          }
        }
        //
        pLPB->Clear();
        *pLPB=aLPBx;
      }
      //
      BOPTools_PaveBlock& aPB=aCB.PaveBlock1(nE);
      nSp=SplitIndex(aPB);
      aPB.SetEdge(nSp);
      //
      const BOPTools_ListOfPaveBlock& aCBLPB=aCB.PaveBlocks();
      aPBIt.Initialize(aCBLPB);
      for (; aPBIt.More(); aPBIt.Next()) {
        BOPTools_PaveBlock& aPBx=aPBIt.Value();
        nEx=aPBx.OriginalEdge();
        if (nEx==nE) {
          continue;
        }
        //
        nSpx=SplitIndex(aPBx);
        aPBx.SetEdge(nSpx);
      }
      //
    }
  }
}
//=======================================================================
// function: FillIn2DParts
// purpose: 
//=======================================================================
  void GEOMAlgo_Builder::FillIn2DParts()
{
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences();
  NMTTools_CommonBlockPool& aCBP=pPF->ChangeCommonBlockPool();
  //
  Standard_Integer  j, nSpIn, nSpSc, aNbCurves;
  Standard_Integer aNbS, nF, aNbCBP, n1, n2, aNbFFs, aNbSpIn;
  TopTools_MapOfShape  aMFence;
  TopTools_ListOfShape aLSpIn;
  TopoDS_Face aF;
  NMTTools_ListIteratorOfListOfCommonBlock aItCB;
  BOPTools_ListIteratorOfListOfPaveBlock aItPB;
  //
  myInParts.Clear();
  //
  aNbFFs=aFFs.Extent();
  aNbCBP=aCBP.Extent();
  //
  aNbS=aDS.NumberOfShapesOfTheObject();
  for (nF=1; nF<=aNbS; ++nF) {
    if (aDS.GetShapeType(nF)!=TopAbs_FACE) {
      continue;
    }
    //
    aF=TopoDS::Face(aDS.Shape(nF));
    //
    aMFence.Clear();
    aLSpIn.Clear();
    //
    // 1. In Parts
    for (j=1; j<=aNbCBP; ++j) {
      NMTTools_ListOfCommonBlock& aLCB=aCBP(j);
      aItCB.Initialize(aLCB);
      for (; aItCB.More(); aItCB.Next()) {
	NMTTools_CommonBlock& aCB=aItCB.Value();
	if (aCB.IsPaveBlockOnFace(nF)) {
	  const BOPTools_PaveBlock& aPB1=aCB.PaveBlock1();
	  nSpIn=aPB1.Edge();
	  const TopoDS_Shape& aSpIn=aDS.Shape(nSpIn);
	  if (aMFence.Add(aSpIn)){
	    aLSpIn.Append(aSpIn);
	  }
	}
      }
    }
    //
    // 2. Section Parts
    for (j=1; j<=aNbFFs; ++j) {
      BOPTools_SSInterference& aFF=aFFs(j);
      aFF.Indices(n1, n2);
      if (!(n1==nF || n2==nF)) {
	continue;
      }
      BOPTools_SequenceOfCurves& aSC=aFF.Curves();
      aNbCurves=aSC.Length();
      if (!aNbCurves) {
	continue;
      }
      //
      const BOPTools_Curve& aBC=aSC(1);
      const BOPTools_ListOfPaveBlock& aLPB=aBC.NewPaveBlocks();
      aItPB.Initialize(aLPB);
      for (; aItPB.More(); aItPB.Next()) {
	const BOPTools_PaveBlock& aPBSc=aItPB.Value();
	nSpSc=aPBSc.Edge();
	const TopoDS_Shape& aSpSc=aDS.Shape(nSpSc);
	if (aMFence.Add(aSpSc)){
	  aLSpIn.Append(aSpSc);
	}
      }
    }
    aNbSpIn=aLSpIn.Extent();
    if (aNbSpIn) {
      myInParts.Add(aF, aLSpIn);
    }
  }//for (nF=1; nF<=aNbS; ++nF) {
}
//=======================================================================
// function: UpdateCommonBlocks
// purpose:
//=======================================================================
void NMTTools_PaveFiller::UpdateCommonBlocks(const Standard_Integer)
{
  Standard_Integer nE, aNbS,  nEx, nEMax, j, aNbPoints, aNbLCB, nF;
  Standard_Real aTolEx, aTolExMax, aTSRMax[2], aTx[2], aTmp;
  TColStd_ListIteratorOfListOfInteger aItLI;
  gp_Pnt aPMax[2];
  TopoDS_Edge aEMax;
  BOPTools_ListIteratorOfListOfPaveBlock aItLPB, aItLPBS;
  NMTTools_ListIteratorOfListOfCommonBlock aItLCB;
  NMTTools_MapOfPaveBlock aMPB;
  //
  myIsDone=Standard_False;
  //
  aNbS=myDS->NumberOfShapesOfTheObject();
  for (nE=1; nE<=aNbS; ++nE) {
    if (myDS->GetShapeType(nE)!=TopAbs_EDGE){
      continue;
    }
    //
    const TopoDS_Edge& aE=*((TopoDS_Edge*)&myDS->Shape(nE));
    if (BRep_Tool::Degenerated(aE)){
      continue;
    }
    //
    NMTTools_ListOfCommonBlock& aLCB=myCommonBlockPool(myDS->RefEdge(nE));
    //modified by NIZNHY-PKV Thu Jan 19 09:03:19 2012f
    aNbLCB=aLCB.Extent();
    if (!aNbLCB) {
      continue;
    }
    // 0
    NMTTools_ListOfCommonBlock aLCBx;
    //
    aItLCB.Initialize(aLCB);
    for (; aItLCB.More(); aItLCB.Next()) {
      NMTTools_CommonBlock aCBx;
      //
      NMTTools_CommonBlock& aCB=aItLCB.ChangeValue();
      const BOPTools_ListOfPaveBlock &aLPB=aCB.PaveBlocks();
      aItLPB.Initialize(aLPB);
      for (; aItLPB.More(); aItLPB.Next()) {
        const BOPTools_PaveBlock& aPBx=aItLPB.Value();
        nEx=aPBx.OriginalEdge();
        BOPTools_ListOfPaveBlock& aLPBS=mySplitShapesPool(myDS->RefEdge(nEx));
        aItLPBS.Initialize(aLPBS);
        for (; aItLPBS.More(); aItLPBS.Next()) {
          const BOPTools_PaveBlock& aPBSx=aItLPBS.Value();
          if (aPBSx.IsEqual(aPBx)) {
            aCBx.AddPaveBlock(aPBSx);
            break;
          }
        }// for (; aItLPBS.More(); aItLPBS.Next()) {
      }// for (; aItLPB.More(); aItLPB.Next()) {
      //
      const TColStd_ListOfInteger& aLI=aCB.Faces();
      aItLI.Initialize(aLI);
      for (; aItLI.More(); aItLI.Next()) {
        nF=aItLI.Value();
        aCBx.AddFace(nF);
      }
      //
      aLCBx.Append(aCBx);
    }//for (; aItLCB.More(); aItLCB.Next()) {
    //
    aLCB.Clear();
    //
    aItLCB.Initialize(aLCBx);
    for (; aItLCB.More(); aItLCB.Next()) {
      NMTTools_CommonBlock& aCBx=aItLCB.ChangeValue();
      aLCB.Append(aCBx);
    }
    //modified by NIZNHY-PKV Thu Jan 19 09:03:30 2012t
    // 1
    aItLCB.Initialize(aLCB);
    for (; aItLCB.More(); aItLCB.Next()) {
      NMTTools_CommonBlock& aCB=aItLCB.ChangeValue();
      //
      BOPTools_PaveBlock aPBMax;
      aTolExMax=-1.;
      const BOPTools_ListOfPaveBlock &aLPB=aCB.PaveBlocks();
      aItLPB.Initialize(aLPB);
      for (; aItLPB.More(); aItLPB.Next()) {
        const BOPTools_PaveBlock& aPBx=aItLPB.Value();
        nEx=aPBx.OriginalEdge();
        const TopoDS_Edge& aEx=*((TopoDS_Edge*)&myDS->Shape(nEx));
        aTolEx=BRep_Tool::Tolerance(aEx);
        if (aTolEx>aTolExMax) {
          aTolExMax=aTolEx;
          aEMax=aEx;
          aPBMax=aPBx;
        }
      }
      //
      // 2
      if (aMPB.Contains(aPBMax)) {
        continue;
      }
      aMPB.Add(aPBMax);
      //
      nEMax=aPBMax.OriginalEdge();
      const IntTools_ShrunkRange& aISRMax=aPBMax.ShrunkRange();
      const IntTools_Range& aSRMax=aISRMax.ShrunkRange();
      const Bnd_Box& aBoxMax=aISRMax.BndBox();
      aSRMax.Range(aTSRMax[0], aTSRMax[1]);
      for (j=0; j<2; ++j) {
        BOPTools_Tools::PointOnEdge(aEMax, aTSRMax[j], aPMax[j]);
      }
      //
      // 3
      aItLPB.Initialize(aLPB);
      for (; aItLPB.More(); aItLPB.Next()) {
        const BOPTools_PaveBlock& aPBx=aItLPB.Value();
        nEx=aPBx.OriginalEdge();
        if (nEx==nEMax) {
          continue;
        }
        //
        const TopoDS_Edge& aEx=*((TopoDS_Edge*)&myDS->Shape(nEx));
        GeomAPI_ProjectPointOnCurve& aPPCx=myContext->ProjPC(aEx);
        //
        for (j=0; j<2; ++j) {
          aPPCx.Perform(aPMax[j]);
          aNbPoints=aPPCx.NbPoints();
          if (!aNbPoints) {
            break;
          }
          aTx[j]=aPPCx.LowerDistanceParameter();
        }
        if (!aNbPoints) {
          // correction the range is impossible due to
          // a projection problem
          continue;
        }
        //
        if (aTx[0]>aTx[1]){
          aTmp=aTx[0];
          aTx[0]=aTx[1];
          aTx[1]=aTmp;
        }
        //
        // 4 Correction
        // 4.1 aPBx
        {
          const IntTools_ShrunkRange& aISRx=aPBx.ShrunkRange();
          IntTools_Range *pSRx=(IntTools_Range *)(&aISRx.ShrunkRange());
          Bnd_Box *pBoxx=(Bnd_Box *)(&aISRx.BndBox());
          //
          pSRx->SetFirst(aTx[0]);
          pSRx->SetLast(aTx[1]);
          *pBoxx=aBoxMax;
        }
        //
        // 4.2 aPBSx
        BOPTools_ListOfPaveBlock& aLPBSx=mySplitShapesPool(myDS->RefEdge(nEx));
        aItLPBS.Initialize(aLPBSx);
        for (; aItLPBS.More(); aItLPBS.Next()) {
          const BOPTools_PaveBlock& aPBSx=aItLPBS.Value();
          if (!aPBSx.IsEqual(aPBx)) {
            continue;
          }
          //
          const IntTools_ShrunkRange& aISRx=aPBSx.ShrunkRange();
          IntTools_Range *pSRx=(IntTools_Range *)(&aISRx.ShrunkRange());
          Bnd_Box *pBoxx=(Bnd_Box *)(&aISRx.BndBox());
          //
          pSRx->SetFirst(aTx[0]);
          pSRx->SetLast(aTx[1]);
          *pBoxx=aBoxMax;
        }
        //
        //
      }//for (; aItLPB.More(); aItLPB.Next()) {
    }//for (; aItLCB.More(); aItLCB.Next()) {
  }//for (nE=1; nE<=aNbS; ++nE) {
}
//=======================================================================
// function: MakePCurves
// purpose:
//=======================================================================
void NMTTools_PaveFiller::MakePCurves()
{
  Standard_Integer i, aNb,  nF1, nF2, nE;
  Standard_Integer aNbCB, aNbF, nSp, nF;
  TopAbs_ShapeEnum aType;
  TopoDS_Face aF1FWD, aF2FWD;
  TColStd_ListIteratorOfListOfInteger aItF;
  BOPTools_ListIteratorOfListOfPaveBlock anIt;
  NMTTools_ListIteratorOfListOfCommonBlock aItCB;
  //
  BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences();
  //
  aNb=aFFs.Extent();
  for (i=1; i<=aNb; i++) {
    BOPTools_SSInterference& aFF=aFFs(i);
    aFF.Indices(nF1, nF2);
    //
    const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv
    const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv
    //
    aF1FWD=aF1;
    aF1FWD.Orientation(TopAbs_FORWARD);
    aF2FWD=aF2;
    aF2FWD.Orientation(TopAbs_FORWARD);
    //
    // In, On parts processing
    const BOPTools_ListOfPaveBlock& aLPBInOn=aFF.PaveBlocks();
    //
    anIt.Initialize(aLPBInOn);
    for (; anIt.More(); anIt.Next()) {
      const BOPTools_PaveBlock& aPB=anIt.Value();
      nE=aPB.Edge();
      const TopoDS_Edge aE=TopoDS::Edge(myDS->Shape(nE));//mpv

      BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aE, aF1FWD);
      BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aE, aF2FWD);
    }
  }
  // Check common blocks between edges and faces
  // Build P-Curves if they were not built in previos block.
  // The main case is :arguments for e.g aEdge, aFace -> no FFs,
  // but p-curves are needed.
  //
  aNb=myDS->NumberOfShapesOfTheObject();
  for (i=1; i<=aNb; ++i) {
    const TopoDS_Shape& aS=myDS->Shape(i);
    aType=aS.ShapeType();
    //
    if (aType!=TopAbs_EDGE) {
      continue;
    }
    const TopoDS_Edge& aE=TopoDS::Edge(aS);
    //
    if (BRep_Tool::Degenerated(aE)) {
      continue;
    }
    //
    const NMTTools_ListOfCommonBlock& aLCB=myCommonBlockPool(myDS->RefEdge(i));
    aNbCB=aLCB.Extent();
    if (!aNbCB) {
      continue;
    }
    //
    aItCB.Initialize(aLCB);
    for (; aItCB.More(); aItCB.Next()) {
      const NMTTools_CommonBlock& aCB=aItCB.Value();
      const BOPTools_PaveBlock &aPB1=aCB.PaveBlock1();
      //
      const TColStd_ListOfInteger& aLF=aCB.Faces();
      aNbF=aLF.Extent();
      if (!aNbF) {
        continue;
      }
      //
      nSp=aPB1.Edge();
      const TopoDS_Edge aSp=TopoDS::Edge(myDS->Shape(nSp));//mpv
      //
      aItF.Initialize(aLF);
      for (; aItF.More(); aItF.Next()) {
        nF=aItF.Value();
        aF1FWD=TopoDS::Face(myDS->Shape(nF));
        aF1FWD.Orientation(TopAbs_FORWARD);
        //
        BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aSp, aF1FWD);
      } // for (; aItCB.More(); aItCB.Next()) {
    }//if (aS.ShapeType()==TopAbs_EDGE) {
  }
}