//=======================================================================
// function: CheckFacePaves
// purpose: 
//=======================================================================
  Standard_Integer NMTTools_PaveFiller::CheckFacePaves 
    (const TopoDS_Vertex& aNewVertex,
     const Standard_Integer nF)
{
  Standard_Integer nEF, nVF, iFlag, i, aNbV, iRet;
  BOPTools_ListIteratorOfListOfPave anIt;
  TColStd_IndexedMapOfInteger aMVF;
  //
  iRet=0; 
  //
  BooleanOperations_OnceExplorer aExp(*myDS);
  aExp.Init(nF, TopAbs_EDGE);
  for (; aExp.More(); aExp.Next()) {
    nEF=aExp.Current();
    BOPTools_PaveSet& aPaveSet=myPavePool(myDS->RefEdge(nEF));
    const BOPTools_ListOfPave& aLP=aPaveSet.Set();
    anIt.Initialize(aLP);
    for (; anIt.More(); anIt.Next()) {
      const BOPTools_Pave& aPave=anIt.Value();
      nVF=aPave.Index();
      aMVF.Add(nVF);
    }
  }
  //
  aNbV=aMVF.Extent();
  for (i=1; i<=aNbV; ++i) {
    nVF=aMVF(i);
    const TopoDS_Vertex aVF=TopoDS::Vertex(myDS->Shape(nVF));
    iFlag=IntTools_Tools::ComputeVV(aNewVertex, aVF);
    if (!iFlag) {
      return nVF;
    }
  }
  return iRet;
}
Standard_Boolean ShHealOper_FillHoles::Fill()
{
  ShapeAnalysis_FreeBounds sab(myInitShape);
  TopoDS_Compound aCompClosed = sab.GetClosedWires();
  TopoDS_Compound aCompOpen = sab.GetOpenWires();
  TopTools_SequenceOfShape aFillWires;
  if(!aCompClosed.IsNull()) {
    TopoDS_Iterator aIt(aCompClosed);

    for( ; aIt.More(); aIt.Next()) 
      aFillWires.Append(aIt.Value());
  }
  if(!aCompOpen.IsNull()) {
    TopoDS_Iterator aIt(aCompOpen);
    for(  ; aIt.More(); aIt.Next()) 
      aFillWires.Append(aIt.Value());
  }
  
  TopExp_Explorer aExp(myInitShape,TopAbs_EDGE,TopAbs_FACE);
  
  for( ; aExp.More(); aExp.Next())
    aFillWires.Append(aExp.Current());

  return Fill(aFillWires);
}
//=======================================================================
//function : IsManifold
//purpose  : function for definition manifold shell
//=======================================================================
Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
{
  Standard_Boolean IsManifold = Standard_True;
  TopExp_Explorer aExp(aShell,TopAbs_EDGE);
  for( ; aExp.More() && IsManifold; aExp.Next()) {
    const TopTools_ListOfShape& als = myMapEdgesFace.FindFromKey(aExp.Current());
    IsManifold = (als.Extent() <=2 ); 
  }
  return IsManifold;
}
Standard_Boolean ShHealOper_Sewing::sewing(const TopTools_SequenceOfShape& theSeqShapes)
{
  myDone = Standard_False;
  myErrorStatus = ShHealOper_NotError;
  if(myInitShape.IsNull()) {
    myErrorStatus = ShHealOper_InvalidParameters;
    return myDone;
  }
  //sewing shape
  Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
  aSewing->Load(myInitShape);
  aSewing->SetTolerance(myTolerance);
  aSewing->SetFaceMode(myFacesMode);
  aSewing->SetFloatingEdgesMode(myEdgesMode);
  aSewing->SetNonManifoldMode(myNonManifoldMode);
  Standard_Integer j =1;
  for( ; j <= theSeqShapes.Length();j++)
    aSewing->Add(theSeqShapes.Value(j));

  aSewing->Perform();
  const TopoDS_Shape aSewShape = aSewing->SewedShape();
  if(aSewShape.IsNull()) {
    myErrorStatus = ShHealOper_ErrorExecution;
    return myDone;
  }
  if(aSewShape.IsSame(myInitShape))
    return myDone;

  //analysis either sewing was made by changing number of shells
  myDone = isSewed(aSewShape);

  //keep modification of the subshapes in the Context.
  TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
  for( ; aExp.More(); aExp.Next())
    myDone = (getModifications( aExp.Current(),aSewing) || myDone);

  TopoDS_Shape aTempShape = myContext->Apply(aSewShape);
  //obtained shells with fixed orientation for manifold and nonmanifold shells
  if(myFacesMode) 
    myDone = getShells(aTempShape) || myDone;

  //obtained manifold wires if sewing edges was performed.
  if(myEdgesMode) 
    myDone = getWires(aTempShape) || myDone;
  
  if(myDone)
    myResultShape = myContext->Apply(aTempShape);
    
  return myDone;
}
//=======================================================================
//function : MakeInternalWires
//purpose  : 
//=======================================================================
void MakeInternalWires(const TopTools_MapOfShape& theME,
		       TopTools_ListOfShape& theWires)
{
  TopTools_MapIteratorOfMapOfShape aItM;
  TopTools_MapOfShape aAddedMap;
  TopTools_ListIteratorOfListOfShape aItE;
  TopTools_IndexedDataMapOfShapeListOfShape aMVE;
  BRep_Builder aBB;
  //
  aItM.Initialize(theME);
  for (; aItM.More(); aItM.Next()) {
    const TopoDS_Shape& aE=aItM.Key();
    TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
  }
  //
  aItM.Initialize(theME);
  for (; aItM.More(); aItM.Next()) {
    TopoDS_Shape aEE=aItM.Key();
    if (!aAddedMap.Add(aEE)) {
      continue;
    }
    //
    // make a new shell
    TopoDS_Wire aW;
    aBB.MakeWire(aW);    
    aEE.Orientation(TopAbs_INTERNAL);
    aBB.Add(aW, aEE);
    //
    TopoDS_Iterator aItAdded (aW);
    for (; aItAdded.More(); aItAdded.Next()) {
      const TopoDS_Shape& aE =aItAdded.Value();
      //
      TopExp_Explorer aExp(aE, TopAbs_VERTEX);
      for (; aExp.More(); aExp.Next()) {
        const TopoDS_Shape& aV =aExp.Current();
	const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
	aItE.Initialize(aLE);
	for (; aItE.More(); aItE.Next()) { 
	  TopoDS_Shape aEL=aItE.Value();
	  if (aAddedMap.Add(aEL)){
	    aEL.Orientation(TopAbs_INTERNAL);
	    aBB.Add(aW, aEL);
	  }
	}
      }
    }
    theWires.Append(aW);
  }
}
Standard_Boolean ShHealOper_RemoveFace::Perform()
{
  myDone = Standard_False;
  myErrorStatus = ShHealOper_NotError;
  if(myInitShape.IsNull()) {
    myErrorStatus = ShHealOper_InvalidParameters;
    return myDone;
  }
  TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
  for( ; aExp.More(); aExp.Next()) {
    removePCurve(TopoDS::Face(aExp.Current()));
    myContext->Remove(aExp.Current());
    myDone = Standard_True;
  }
  if(myDone) {
    TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
    isReplace(aNewShape,myResultShape);
    myContext->Replace(aNewShape,myResultShape);
  }
  return myDone;
}
//modified by NIZNHY-PKV Thu Feb 16 12:25:16 2012f
//=======================================================================
//function : IsClosed
//purpose  :
//=======================================================================
Standard_Boolean IsClosed(const TopoDS_Edge& aE,
			  const TopoDS_Face& aF)
{
  Standard_Boolean bRet;
  //
  bRet=BRep_Tool::IsClosed(aE, aF);
  if (bRet) {
    TopTools_MapOfShape aM;
    TopExp_Explorer aExp(aF, TopAbs_EDGE);
    for (; aExp.More(); aExp.Next()) {
      const TopoDS_Shape& aEx=aExp.Current();
      //
      if (aM.Add(aEx)) {
	bRet=aEx.IsSame(aE);
	if (bRet) {
	  break;
	}
      }
    }
  }
  return bRet;
}
//=======================================================================
// function: FillInternalVertices
// purpose:
//=======================================================================
void GEOMAlgo_Builder::FillInternalVertices()
{
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  const Handle(IntTools_Context)& aCtx= pPF->Context();
  //
  BOPTools_CArray1OfVSInterference& aVFs=pIP->VSInterferences();
  BOPTools_CArray1OfESInterference& aEFs=pIP->ESInterferences();
  const NMTTools_IndexedDataMapOfIndexedMapOfInteger& aMAV=pPF->AloneVertices();
  //
  Standard_Boolean bHasImage;
  Standard_Integer i, j, nF, aNbS, nV, nVSD, n1, n2, iFlag;
  Standard_Integer aNbVFs, aNbAVF, aNbEFs, aNbVC, aNbE, aNbV;
  Standard_Real aU1, aU2, aTol;
  NMTTools_IndexedDataMapOfIndexedMapOfInteger aMFMV;
  TopTools_MapOfShape aMFence;
  TopTools_ListIteratorOfListOfShape aIt, aItV;
  BRep_Builder aBB;
  //
  // 1. Collect face-vertex candidates [aMFMV]
  //
  // 1.1. VFs
  aNbVFs=aVFs.Extent();
  for (i=1; i<=aNbVFs; ++i) {
    const BOPTools_VSInterference& aVS=aVFs(i);
    aVS.Indices(n1, n2);
    nF=n2;
    nV=n1;
    if (aDS.Shape(n1).ShapeType()==TopAbs_FACE) {
      nF=n1;
      nV=n2;
    }
    nVSD=pPF->FindSDVertex(nV);
    if (nVSD) {
      nV=nVSD;
    }
    //
    UpdateCandidates(nF, nV, aMFMV);
  }
  //
  // 1.2 EFs
  aNbEFs=aEFs.Extent();
  for (i=1; i<=aNbEFs; ++i) {
    const BOPTools_ESInterference& aEF=aEFs(i);
    aEF.Indices(n1, n2);
    nV=aEF.NewShape();
    if (!nV) {
      continue;
    }
    const TopoDS_Shape& aSnew=aDS.Shape(nV);
    if (aSnew.ShapeType()!=TopAbs_VERTEX) {
      continue;
    }
    //
    nF=(aDS.Shape(n1).ShapeType()==TopAbs_FACE) ? n1 : n2;
    nVSD=pPF->FindSDVertex(nV);
    if (nVSD) {
      nV=nVSD;
    }
    UpdateCandidates(nF, nV, aMFMV);
  }
  //
  aNbS=aDS.NumberOfShapesOfTheObject();
  for (nF=1; nF<=aNbS; ++nF) {
    const TopoDS_Shape& aF=aDS.Shape(nF);
    //
    if (aF.ShapeType()!=TopAbs_FACE) {
      continue;
    }
    if (!aMFence.Add(aF)) {
      continue;
    }
    //
    const TopoDS_Face& aFF=TopoDS::Face(aF);
    aTol=BRep_Tool::Tolerance(aFF);
    //
    // 1.3 FFs
    if (aMAV.Contains(nF)) {
      const TColStd_IndexedMapOfInteger& aMAVF=aMAV.FindFromKey(nF);
      aNbAVF=aMAVF.Extent();
      for (j=1; j<=aNbAVF; ++j) {
        nV=aMAVF(j);
        nVSD=pPF->FindSDVertex(nV);
        if (nVSD) {
          nV=nVSD;
        }
        //
        UpdateCandidates(nF, nV, aMFMV);
      }
    }
    //
    // 1.4 Internal vertices of the face nF
    BooleanOperations_OnceExplorer aExp(aDS);
    aExp.Init(nF, TopAbs_VERTEX);
    for (; aExp.More(); aExp.Next()) {
      nV=aExp.Current();
      const TopoDS_Shape& aV=aDS.Shape(nV);
      if (aV.Orientation()==TopAbs_INTERNAL) {
        nVSD=pPF->FindSDVertex(nV);
        if (nVSD) {
          nV=nVSD;
        }
        //
        UpdateCandidates(nF, nV, aMFMV);
      }
    }
    //
    // 2. Process face nF
    if (!aMFMV.Contains(nF)) {
      continue;
    }
    //
    const TColStd_IndexedMapOfInteger& aMVC=aMFMV.FindFromKey(nF);
    aNbVC=aMVC.Extent();
    if (!aNbVC) {
      continue;
    }
    //
    // 2.1 Refine candidates
    TopTools_IndexedDataMapOfShapeListOfShape aMVE;
    TopTools_ListOfShape aLV;
    //
    bHasImage=myImages.HasImage(aF);
    if (bHasImage) {
      const TopTools_ListOfShape& aLFx=myImages.Image(aF);
      aIt.Initialize(aLFx);
      for (; aIt.More(); aIt.Next()) {
        const TopoDS_Shape& aFx=aIt.Value();
        TopExp::MapShapesAndAncestors(aFx, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
      }
    }
    else {
      Standard_Boolean bFaceToProcess;
      //
      TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
      bFaceToProcess=Standard_False;
      for (j=1; j<=aNbVC; ++j) {
        nV=aMVC(j);
        const TopoDS_Shape& aV=aDS.Shape(nV);
        if (!aMVE.Contains(aV)) {
          bFaceToProcess=!bFaceToProcess;
          break;
        }
      }
      if (!bFaceToProcess) {
        continue;
      }
    }// else
    //
    for (j=1; j<=aNbVC; ++j) {
      nV=aMVC(j);
      const TopoDS_Shape& aV=aDS.Shape(nV);
      if (aMVE.Contains(aV)) {
        const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
        aNbE=aLE.Extent();
        if (aNbE) {
          continue;
        }
      }
      aLV.Append(aV);
    }
    //
    aNbV=aLV.Extent();
    if (aNbV) {
      //  3. Try to put vertices into the face(s)
      aItV.Initialize(aLV);
      for (; aItV.More(); aItV.Next()) {
        TopoDS_Vertex aV=TopoDS::Vertex(aItV.Value());
        aV.Orientation(TopAbs_INTERNAL);
        //
        bHasImage=myImages.HasImage(aF);
        if (bHasImage) {
          const TopTools_ListOfShape& aLFx=myImages.Image(aF);
          aIt.Initialize(aLFx);
          for (; aIt.More(); aIt.Next()) {
            TopoDS_Face aFx=TopoDS::Face(aIt.Value());
            // update classifier
            IntTools_FClass2d& aClsf=aCtx->FClass2d(aFx);
            aClsf.Init(aFx, aTol);
            //
            iFlag=aCtx->ComputeVS (aV, aFx, aU1, aU2);
            if (!iFlag) {
              aBB.Add(aFx, aV);
              break;
            }
          }
        }
        else {
          const TopoDS_Face& aFx=TopoDS::Face(aF);
          // update classifier
          IntTools_FClass2d& aClsf=aCtx->FClass2d(aFx);
          aClsf.Init(aFx, aTol);
          //
          iFlag=aCtx->ComputeVS (aV, aFx, aU1, aU2);
          if (!iFlag) {
            TopoDS_Face aFz;
            //
            GEOMAlgo_Tools3D::CopyFace(aFx, aFz);
            aBB.Add(aFz, aV);
            myImages.Bind(aF, aFz);
          }
        }
      }// for (; aItV.More(); aItV.Next()) {
    }// if (aNbV) {
  }// for (nF=1; nF<=aNb; ++nF) {
}
//=======================================================================
// function: PerformVE
// purpose:
//=======================================================================
void NMTTools_PaveFiller::PerformVE()
{
  myIsDone=Standard_False;
  //
  Standard_Boolean bJustAdd;
  Standard_Integer n1, n2, anIndexIn, aFlag, aWhat;
  Standard_Integer aWith, aNbVEs, aBlockLength, iSDV, nV1;
  Standard_Real aT;
#if OCC_VERSION_LARGE > 0x06030008
  // In OCCT6.3.0sp9 is changed a signature of IntTools_Context::ComputeVE() method
  Standard_Boolean bToUpdateVertex;
  Standard_Real aDist;
#endif
  TopoDS_Vertex aV1;
  TopoDS_Edge aE2;
  BOPTools_IndexedMapOfCoupleOfInteger aSnareMap;
  BOPTools_CoupleOfInteger aCouple;
  //
  BOPTools_CArray1OfVEInterference& aVEs=myIP->VEInterferences();
  //
  myDSIt->Initialize (TopAbs_VERTEX, TopAbs_EDGE);
  //
  // BlockLength correction
  aNbVEs=myDSIt->BlockLength();
  aBlockLength=aVEs.BlockLength();
  if (aNbVEs > aBlockLength) {
    aVEs.SetBlockLength(aNbVEs);
  }
  //
  for (; myDSIt->More(); myDSIt->Next()) {
    myDSIt->Current(n1, n2, bJustAdd);
    if (!IsSuccessorsComputed(n1, n2)) {
      anIndexIn=0;
      aWhat=n1; // Vertex
      aWith=n2; // Edge
      if (myDS->GetShapeType(n1)==TopAbs_EDGE) {
        aWhat=n2;
        aWith=n1;
      }
      //
      if(bJustAdd) {
        continue;
      }
      // Edge
      aE2=TopoDS::Edge(myDS->Shape(aWith));
      if (BRep_Tool::Degenerated(aE2)){
        continue;
      }
      // Vertex
      nV1=aWhat;
      aV1=TopoDS::Vertex(myDS->Shape(aWhat));
      //
      iSDV=FindSDVertex(aWhat);
      if (iSDV) {
        nV1=iSDV;
        aV1=TopoDS::Vertex(myDS->Shape(nV1));
        // Modified to find same domain vertex Thu Sep 14 14:35:18 2006
        // Contribution of Samtech www.samcef.com BEGIN
        Standard_Integer nVE, iSDVE, iRet;
        //
        BooleanOperations_OnceExplorer aExp(*myDS);
        iRet=0;
        aExp.Init(aWith, TopAbs_VERTEX);
        for (; aExp.More(); aExp.Next()) {
          nVE=aExp.Current();
          iSDVE=FindSDVertex(nVE);
          if (iSDVE==iSDV) {
            iRet=1;
            break;
          }
        }
        if (iRet) {
          continue;
        }
      }
      else {
        if (Contains(aE2, aV1)) {
          continue;
        }
        // Contribution of Samtech www.samcef.com END
      }
      //
      //modified by NIZNHY-PKV Mon Dec 28 08:58:05 2009f
#if OCC_VERSION_LARGE > 0x06030008
      // In OCCT6.3.0sp9 is changed a signature of IntTools_Context::ComputeVE() method
      aFlag = myContext->ComputeVE (aV1, aE2, aT, bToUpdateVertex, aDist);
#else
      aFlag = myContext->ComputeVE (aV1, aE2, aT);
#endif
      //modified by NIZNHY-PKV Mon Dec 28 08:58:13 2009t
      //
      if (!aFlag) {
        // Add Interference to the Pool
        BOPTools_VEInterference anInterf (aWhat, aWith, aT);
        anIndexIn=aVEs.Append(anInterf);
        //
        // Add Pave to the Edge's myPavePool
        aCouple.SetCouple(nV1, aWith);
        if (!aSnareMap.Contains(aCouple)){
          aSnareMap.Add(aCouple);
          //
          BOPTools_Pave aPave(nV1, aT, BooleanOperations_VertexEdge);
          aPave.SetInterference(anIndexIn);
          BOPTools_PaveSet& aPaveSet= myPavePool(myDS->RefEdge(aWith));
          aPaveSet.Append(aPave);
        }
        //
        // State for the Vertex in DS;
        myDS->SetState (aWhat, BooleanOperations_ON);
        // Insert Vertex in Interference Object
        BOPTools_VEInterference& aVE=aVEs(anIndexIn);
        aVE.SetNewShape(aWhat);
        //
        myIP->Add(aWhat, aWith, Standard_True, NMTDS_TI_VE);
        //
        //modified by NIZNHY-PKV Mon Dec 28 09:00:54 2009f
#if OCC_VERSION_LARGE > 0x06030008
        // In OCCT6.3.0sp9 is changed a signature of IntTools_Context::ComputeVE() method
        if (bToUpdateVertex) {
          BRep_Builder aBB;
          //
          aBB.UpdateVertex(aV1, aDist);
        }
#endif
        //modified by NIZNHY-PKV Mon Dec 28 09:00:57 2009t
        //
      } //if (!aFlag) {
    }
  }
  myIsDone=Standard_True;
}