// File:	BRepAlgo_DSAccess.cxx
// Created:	Wed Aug 13 16:05:15 1997
// Author:	Prestataire Mary FABIEN
//		<fbi@langdox.paris1.matra-dtv.fr>


#include <BRepAlgo_DSAccess.ixx>
#include <BRepAlgo_EdgeConnector.hxx>

#include <TColStd_ListOfInteger.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
#include <TColStd_SetIteratorOfSetOfInteger.hxx>

#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TColStd_ListIteratorOfListOfInteger.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Wire.hxx>
#include <TopOpeBRepDS_PointIterator.hxx>
#include <TopOpeBRepDS_BuildTool.hxx>
#include <TopOpeBRepDS_CheckStatus.hxx>
#include <TopOpeBRepDS_Check.hxx>
#include <TopOpeBRepDS_ListOfInterference.hxx>
#include <TopOpeBRepDS_Interference.hxx>
#include <TopOpeBRepDS_InterferenceIterator.hxx>
#include <TopOpeBRepDS_ListIteratorOfListOfInterference.hxx>
#include <TopOpeBRepDS_ShapeShapeInterference.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_CurveExplorer.hxx>
#include <TopOpeBRepDS_CurveIterator.hxx>
#include <TopOpeBRepDS_Filter.hxx>
#include <TopOpeBRepDS_Reducer.hxx>
#include <TopOpeBRepTool_GeomTool.hxx>
#include <TopOpeBRepBuild_HBuilder.hxx>
#include <TopOpeBRepBuild_WireEdgeSet.hxx>
#include <TopOpeBRepBuild_FaceBuilder.hxx>
#include <TopOpeBRep_DSFiller.hxx>

#ifdef DRAW
//#include <TestTopOpe.hxx>
#endif

//=======================================================================
//function : Create
//purpose  : 
//=======================================================================

BRepAlgo_DSAccess::BRepAlgo_DSAccess() {
  Init();
}

//=======================================================================
//function : Init
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Init()
{
  if(myHDS.IsNull()) 
    myHDS = new TopOpeBRepDS_HDataStructure();
  else
    myHDS->ChangeDS().Init();
  myRecomputeBuilderIsDone = Standard_False;
  myGetSectionIsDone = Standard_False;
  myListOfCompoundOfEdgeConnected.Clear();
  myEC = new BRepAlgo_EdgeConnector();
  myHB.Nullify();
  
  // init du builder
  Standard_Real tol3dAPPROX = 1e-7;
  Standard_Real tol2dAPPROX = 1e-7;
  // set tolerance values used by the APPROX process
  TopOpeBRepTool_GeomTool GT;
  GT.Define(TopOpeBRepTool_APPROX);
  GT.SetTolerances(tol3dAPPROX,tol2dAPPROX);
  TopOpeBRepDS_BuildTool BT(GT);
  myHB = new TopOpeBRepBuild_HBuilder(BT);
  myHB->ChangeBuilder().ChangeClassify(Standard_False);

  myState1 = TopAbs_UNKNOWN;
  myState2 = TopAbs_UNKNOWN;

}


// Remplissage de la SD

//=======================================================================
//function : Load
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Load(const TopoDS_Shape& S)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  myS1 = S;
  DS.AddShape(S, 1);
}

//=======================================================================
//function : Load
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Load(TopoDS_Shape& S1, 
			     TopoDS_Shape& S2)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  
  if ( S1.Orientation() == TopAbs_REVERSED ) {
    S1.Orientation(TopAbs_FORWARD);
  }
  if ( S2.Orientation() == TopAbs_REVERSED ) {
    S2.Orientation(TopAbs_FORWARD);
  }
  
  DS.AddShape(S1,1);
  DS.AddShape(S2,2);

  TopOpeBRepTool_ShapeExplorer ex1,ex2;
  for (ex1.Init(S1,TopAbs_SOLID); ex1.More(); ex1.Next()) {
    const TopoDS_Shape& so1 = ex1.Current();
    for (ex2.Init(S2,TopAbs_SOLID); ex2.More(); ex2.Next()) {
      const TopoDS_Shape& so2 = ex2.Current();
      DS.FillShapesSameDomain(so1,so2);
    }
  }
  
  myS1 = S1;
  myS2 = S2;

#ifdef DRAW
//  TestTopOpe::CurrentDS(myHDS);
//  TestTopOpe::Shapes(myS1,myS2);
#endif
}

//=======================================================================
//function : Intersect
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Intersect()
{
  myRecomputeBuilderIsDone = Standard_False;
  
  if(!myS1.IsNull() && !myS2.IsNull())
    myDSFiller.Insert(myS1, myS2, myHDS);
}

//=======================================================================
//function : Intersect
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Intersect
(const TopoDS_Shape& S1,
 const TopoDS_Shape& S2)
{
  myRecomputeBuilderIsDone = Standard_False;
  
  if(S1.IsNull() || S2.IsNull()) {
    return;
  }
  
  Standard_Boolean orientFORWARD = Standard_False;
  TopExp_Explorer exp;
  if(S1.ShapeType() != TopAbs_FACE) {
    exp.Init(S1, TopAbs_FACE);
    if(!exp.More())
      return;
  }
  if(S2.ShapeType() != TopAbs_FACE) {
    exp.Init(S2, TopAbs_FACE);
    if(!exp.More())
      return;
  }
  myDSFiller.Insert(S1, S2, myHDS, orientFORWARD);
}

//=======================================================================
//function : SameDomain
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::SameDomain
(const TopoDS_Shape& S1,
 const TopoDS_Shape& S2)
{
  myRecomputeBuilderIsDone = Standard_False;
  
  if(S1.IsNull() || S2.IsNull())
    return;

  TopExp_Explorer exp1, exp2;
    exp1.Init(S1, TopAbs_FACE);
    if(!exp1.More())
      return;
    exp2.Init(S2, TopAbs_FACE);
    if(!exp2.More())
      return;
  
  myDSFiller.Insert2d(S1, S2, myHDS);
}


// Construction des Sections

#define FindKeep Standard_False

//=======================================================================
//function : GetSectionEdgeSet
//purpose  : 
//=======================================================================

const TopTools_ListOfShape& BRepAlgo_DSAccess::GetSectionEdgeSet
(const TopoDS_Shape& S1,
 const TopoDS_Shape& S2)
{
  GetSectionEdgeSet();

  // vérifier que S1 et S2 contiennent bien des faces
  TopExp_Explorer exp1, exp2;
  exp1.Init(S1, TopAbs_FACE);
  if(!exp1.More())
    return myEmptyListOfShape;
  exp2.Init(S2, TopAbs_FACE);
  if(!exp2.More())
    return myEmptyListOfShape;
  
  for(exp1.Init(S1, TopAbs_FACE); exp1.More(); exp1.Next()) {
    if(!myHDS->HasShape(exp1.Current(), FindKeep))
      return myEmptyListOfShape;
  }
  for(exp2.Init(S2, TopAbs_FACE); exp2.More(); exp2.Next())
    if(!myHDS->HasShape(exp2.Current(), FindKeep))
      return myEmptyListOfShape;
  
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepBuild_Builder& Builder = myHB->ChangeBuilder();
  
  // on recherche, parmi les interférences associées aux faces,
  // les edges qui proviennent de leur Geometry (= Edge || Curve)
  TopTools_ListOfShape LE;
  LE.Clear();
  TopExp_Explorer exp;
  for(exp1.Init(S1, TopAbs_FACE); exp1.More(); exp1.Next()) {
    const TopoDS_Shape& F1 = exp1.Current();
    
    TopOpeBRepDS_ListOfInterference& lof = DS.ChangeShapeInterferences(F1);
    TopOpeBRepDS_InterferenceIterator li(lof);
    li.SupportKind(TopOpeBRepDS_FACE);
    for(exp2.Init(S2, TopAbs_FACE); exp2.More(); exp2.Next()) {
      const TopoDS_Shape& F2 = exp2.Current();
      Standard_Integer si = DS.Shape(F2, FindKeep);
      li.Support(si);
      
      for(; li.More(); li.Next()) {
	const TopOpeBRepDS_Interference& CurrInt = li.Value();
	TopOpeBRepDS_Kind gk = CurrInt.GeometryType();
	Standard_Integer gi = CurrInt.Geometry();
	const TopoDS_Shape& geosha = DS.Shape(gi, FindKeep);
	if(gk == TopOpeBRepDS_CURVE) {
	  const TopTools_ListOfShape& lEdge = myHB->NewEdges(gi);
	  LE.Append(lEdge.First());
	} else {
	  const TopTools_ListOfShape& lEdge = Builder.Splits(geosha, TopAbs_ON);
	  TopTools_ListIteratorOfListOfShape it(lEdge);
	  for(; it.More(); it.Next()) {
	    const TopoDS_Shape& CurrEdge = it.Value();
	    Standard_Integer ipv1, ipv2;
	    TopOpeBRepDS_Kind pvk1, pvk2;
	    PntVtxOnSectEdge(CurrEdge, ipv1, pvk1, ipv2, pvk2);
	    if(pvk1 != TopOpeBRepDS_VERTEX) {
	      ipv1 = 0;
	      if(pvk2 != TopOpeBRepDS_VERTEX) continue;
	    } else {
	      if(pvk2 != TopOpeBRepDS_VERTEX)
		ipv2 = 0;
	    }
	    for(exp.Init(F1, TopAbs_VERTEX); exp.More(); exp.Next()) {
	      Standard_Integer iVert = DS.Shape(exp.Current());
	      if(iVert) {
		if((iVert == ipv1) || (iVert == ipv2)) {
		  LE.Append(CurrEdge);
		  break;
		}
	      }
	    }
	  }
	}
      }
    }
  }

  // rechercher les ensembles d'Edge connexes associés à LE
  TopTools_ListIteratorOfListOfShape ILE;
  myCurrentList.Clear();
  TopTools_MapOfShape ME;
  ME.Clear();
  TopTools_ListIteratorOfListOfShape ILC;
  TopExp_Explorer ECE;
  ILE.Initialize(LE);
  for(;ILE.More();ILE.Next()) {
    const TopoDS_Shape& E = ILE.Value();
    ILC.Initialize(myListOfCompoundOfEdgeConnected);
    for(;ILC.More();ILC.Next()) {
      const TopoDS_Shape& Com = ILC.Value();
      ECE.Init(Com, TopAbs_EDGE);
      for(;ECE.More();ECE.Next()) {
	if(ECE.Current().IsSame(E)) {
	  if(!ME.Contains(Com)) {
	    myCurrentList.Append(Com);
	    ME.Add(Com);
	    break;
	  }
	}
      }
    }
  }
  
  return myCurrentList;
}

//=======================================================================
//function : GetSectionEdgeSet
//purpose  : 
//=======================================================================

const TopTools_ListOfShape& BRepAlgo_DSAccess::GetSectionEdgeSet()
{
  if(!myRecomputeBuilderIsDone) {
    // on peut très bien appeller la méthode plusieurs fois de suite
    myHDS->AddAncestors(myS1);
    // modif lpa debut
    if (!myS1.IsSame(myS2) && !myS2.IsNull()) {
      myHDS->AddAncestors(myS2);
      myHB->Perform(myHDS,myS1,myS2);
    }
    else {
      myHB->Perform(myHDS);
    }
    // fin modif lpa
    myRecomputeBuilderIsDone = Standard_True;
    myGetSectionIsDone = Standard_False;
  } 
  if(myGetSectionIsDone)
    return myListOfCompoundOfEdgeConnected;
  myGetSectionIsDone = Standard_True;
  
  myListOfCompoundOfEdgeConnected.Clear();
  
  // EdgeConnector
  Handle(BRepAlgo_EdgeConnector) EC = myEC;
  EC->ClearStartElement();
  TopTools_MapOfShape ME;
  ME.Clear();
  myHB->InitSection();
  for(; myHB->MoreSection(); myHB->NextSection()) {
    const TopoDS_Edge& ES = TopoDS::Edge(myHB->CurrentSection());
    if(ME.Contains(ES)) continue;
    ME.Add(ES);
    EC->AddStart(ES);
  }
  TopTools_ListOfShape& LW = EC->MakeBlock();
  
  // on tranforme les wires en compounds.
  myCompoundWireMap.Clear();
  BRep_Builder BB;
  TopTools_ListIteratorOfListOfShape ILW(LW);
  TopExp_Explorer Explor;
  for(;ILW.More();ILW.Next()) {
      TopoDS_Compound Compound;
//POP
      BB.MakeCompound(Compound);
//      BB.MakeCompound(TopoDS::Compound(Compound));
      Explor.Init(ILW.Value(), TopAbs_EDGE);
      for(;Explor.More(); Explor.Next()) {
	BB.Add(Compound, Explor.Current());
      }
      myListOfCompoundOfEdgeConnected.Append(Compound);
      myCompoundWireMap.Bind(Compound,ILW.Value());
    }
  return myListOfCompoundOfEdgeConnected;
}

//=======================================================================
//function : IsWire
//purpose  : 
//=======================================================================

Standard_Boolean BRepAlgo_DSAccess::IsWire(const TopoDS_Shape& S)
{
  Standard_Boolean b = Standard_False;
  if(myEC->IsDone()) {
    if (myCompoundWireMap.IsBound(S))
      b = myEC->IsWire(myCompoundWireMap(S));
  }
  return b;
}

//=======================================================================
//function : Wire
//purpose  : 
//=======================================================================

const TopoDS_Shape& BRepAlgo_DSAccess::Wire(const TopoDS_Shape& S)
{
  if(!IsWire(S)) {
    myWire.Nullify();
  }
  else {
    BRep_Builder BB;
    BB.MakeWire(myWire);
    TopExp_Explorer Explor(S, TopAbs_EDGE);
    for(;Explor.More(); Explor.Next()) BB.Add(myWire, Explor.Current());
  }
  return myWire;
}

//=======================================================================
//function : SectionVertex
//purpose  : 
//=======================================================================

const TopTools_ListOfShape& BRepAlgo_DSAccess::SectionVertex
(const TopoDS_Shape& F,
 const TopoDS_Shape& E)
{
  TopTools_ListOfShape Result;
  Result.Clear();
  if(F.ShapeType() != TopAbs_FACE) return myEmptyListOfShape;
  if(E.ShapeType() != TopAbs_EDGE) return myEmptyListOfShape;
  Standard_Integer iF = myHDS->Shape(F), iE = myHDS->Shape(E);
  if((iF == 0) || (iE == 0)) return myEmptyListOfShape;

  const TopOpeBRepDS_DataStructure& DS = myHDS->DS();
  const TopOpeBRepDS_ListOfInterference& LI = 
    DS.ShapeInterferences(E, Standard_False);
  TopOpeBRepDS_InterferenceIterator II(LI);
  Standard_Integer goodIndex = 0;
  TopOpeBRepDS_Kind goodKind;
  for(;II.More();II.Next()) {
    Handle(TopOpeBRepDS_Interference)& I = II.Value();
    const TopOpeBRepDS_Transition& T = I->Transition();
    if((T.ONAfter() == TopAbs_FACE) &&
       (T.IndexAfter()  == iF)) {
      goodKind  = I->GeometryType();
      goodIndex = I->Geometry();
      if(goodKind == TopOpeBRepDS_VERTEX)
	Result.Append(myHDS->Shape(goodIndex));
      else 
	if (goodKind == TopOpeBRepDS_POINT)
	  Result.Append(myHB->NewVertex(goodIndex));
    }
  }
  myListOfVertex = Result;
  return myListOfVertex;
}


// Édition de la SD

//=======================================================================
//function : SuppressEdgeSet
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::SuppressEdgeSet
(const TopoDS_Shape& C)
{
  // On vérifie que C est bien un Coumpound d'Edges connexes

  myHB->InitExtendedSectionDS();
//  myGetSectionIsDone = Standard_False;

  TopTools_ListIteratorOfListOfShape LLS(myListOfCompoundOfEdgeConnected);
  for(;LLS.More(); LLS.Next())
    if(C == LLS.Value())
      break;
  if(!LLS.More())
    return;
  
  // Netoyage
  TopoDS_Shape Empty;
  Empty.Nullify();
  Suppress(C, Empty);
  myListOfCompoundOfEdgeConnected.Remove(LLS);
}

//=======================================================================
//function : ChangeEdgeSet
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::ChangeEdgeSet
(const TopoDS_Shape& Old, const TopoDS_Shape& New)
{
  // On vérifie que Old est bien un Coumpound d'Edges connexes

  myHB->InitExtendedSectionDS();

  TopTools_ListIteratorOfListOfShape LLS(myListOfCompoundOfEdgeConnected);
  for(;LLS.More(); LLS.Next())
    if(Old == LLS.Value())
      break;
  if(!LLS.More())
    return;

  // On construit le compound des Edges a virer
  BRep_Builder B;
  Standard_Boolean Trouve;
  Standard_Integer iC;
  TopoDS_Compound C;
  TopoDS_Edge E;
  B.MakeCompound(C);
  TColStd_SetOfInteger RPoint; //Les points a controler 
  
 TopOpeBRepDS_ListIteratorOfListOfInterference iter;
  TopExp_Explorer exp(Old, TopAbs_EDGE);
  TopExp_Explorer exp2;
  for(; exp.More(); exp.Next()) {
    const TopoDS_Shape& Edge = exp.Current(); 
    for(exp2.Init(New, TopAbs_EDGE), Trouve=Standard_False;
	exp2.More() && (!Trouve); exp2.Next()) {
      E = TopoDS::Edge(exp2.Current());
      Trouve = E.IsSame(Edge);
    }

    if (!Trouve) B.Add(C, Edge); // Edge a supprimer
    else if (!E.IsEqual(Edge)) {
      // Il faut changer les Interferences => prendre le complement
      iC = myHB->GetDSCurveFromSectEdge(Edge);
      if (!iC) {
#if DEB
	cout << "Warning DSAccess:Modifs d'une Edge non implemente" << endl;
#endif
      }
      else {
	// Complement sur les interferences Courbe/Face
	Standard_Integer iF;
	Handle(TopOpeBRepDS_Interference) interf;

	iF = myHB->GetDSFaceFromDSCurve(iC, 1);	
	TopOpeBRepDS_ListOfInterference& list1 = 
	   myHDS->ChangeDS().ChangeShapeInterferences(iF);
	for(iter.Initialize(list1); iter.More(); iter.Next()) {
	  interf = iter.Value();
	  if (interf->Geometry() == iC)
	    interf->Transition(interf->Transition().Complement());
	}
	iF = myHB->GetDSFaceFromDSCurve(iC, 2);	
	TopOpeBRepDS_ListOfInterference& list2 = 
	  myHDS->ChangeDS().ChangeShapeInterferences(iF);
	for(iter.Initialize(list2); iter.More(); iter.Next()) {
	  interf = iter.Value();
	  if (interf->Geometry() == iC)
	    interf->Transition(interf->Transition().Complement());
	}
	// On note les points associes
	Standard_Integer ipv1, ipv2;
	//Standard_Boolean bid; // skl
	TopOpeBRepDS_Kind k1, k2;	
	PntVtxOnCurve(iC, ipv1, k1, ipv2, k2);
	if (ipv1 != 0) /*bid = */RPoint.Add(ipv1); // skl
	if (ipv2 != 0) /*bid = */RPoint.Add(ipv2); // skl
      }
    }
  }


  // Netoyage
  Suppress(C, New);

  // Faut il renverser des Interferences "Edge on Fa"
  if (!RPoint.IsEmpty()) {
    const TopOpeBRepDS_DataStructure & DS = myHDS->DS();
    Standard_Integer iP,iE, nbShape = DS.NbShapes();
    Handle(TopOpeBRepDS_Interference) interf;
    for (iE=1; iE<=nbShape; iE++) {
      if (DS.Shape(iE,0).ShapeType() == TopAbs_EDGE) { 
	const TopOpeBRepDS_ListOfInterference& List = 
	  myHDS->DS().ShapeInterferences(iE);
	for(iter.Initialize(List); iter.More(); iter.Next()) {
	  interf = iter.Value();
	  if (interf->GeometryType() == TopOpeBRepDS_POINT) {
	    iP = interf->Geometry();
	    if (RPoint.Contains(iP))
	      interf->Transition(interf->Transition().Complement());
	  }
	}
      }
    }
  }

  // On remplace old par new
  LLS.Value() = New;
}


//=======================================================================
//function : Suppress
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::Suppress(const TopoDS_Shape& C,
				 const TopoDS_Shape& Keep)
{
 TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
 TopOpeBRepBuild_Builder& Builder = myHB->ChangeBuilder();
 Standard_Integer i, iC = 0, iF1, iF2,iE1, iE2;
// TopOpeBRepDS_ListIteratorOfListOfInterference lioloi;
 TColStd_ListIteratorOfListOfInteger it1, it2;

  //On Construit l'ensemble des points a garder
 mySetOfKeepPoint.Clear();
 if (!Keep.IsNull()) {
   //Standard_Boolean B; // skl
   Standard_Integer ipv1, ipv2;
   TopOpeBRepDS_Kind k1, k2;
   TopExp_Explorer exp(Keep, TopAbs_EDGE);
   for(; exp.More(); exp.Next()) {
     const TopoDS_Shape& SectEdge = exp.Current();
     iC = myHB->GetDSCurveFromSectEdge(SectEdge);
     if(!iC) 
       PntVtxOnSectEdge(SectEdge, ipv1, k1, ipv2, k2);
     else 
       PntVtxOnCurve(iC, ipv1, k1, ipv2, k2);
     if (ipv1 != 0) /*B = */mySetOfKeepPoint.Add(ipv1); // skl
     if (ipv2 != 0) /*B = */mySetOfKeepPoint.Add(ipv2); // skl
   }
 }

  // On retrouve les curves qui ont généré les Edges
  // on récupère au passage les Edges qui proviennent d'Edge
  // (= MapOfInteger : ESE)
  
  // En premier, les interferences de support 1d.
  TopExp_Explorer exp(C, TopAbs_EDGE);
  for(; exp.More(); exp.Next()) {
    const TopoDS_Shape& SectEdge = exp.Current();
    iC = myHB->GetDSCurveFromSectEdge(SectEdge);
    if(!iC) {
      // on s'occupe des Edges qui proviennent d'Edge
      // on supprime les interferences liées aux Edges :
      iE1 = myHB->GetDSEdgeFromSectEdge(SectEdge, 1);
      iE2 = myHB->GetDSEdgeFromSectEdge(SectEdge, 2);
      
      RemoveEdgeInterferences(iE1,iE2,SectEdge);
      
      TColStd_ListOfInteger& loi11 = myHB->GetDSFaceFromDSEdge(iE1, 1);
      TColStd_ListOfInteger& loi12 = myHB->GetDSFaceFromDSEdge(iE1, 2);
      for(it1.Initialize(loi11); it1.More(); it1.Next()) {
	iF1 = it1.Value();
	for(it2.Initialize(loi12); it2.More(); it2.Next()) {
	  iF2 = it2.Value();
	  // resemble au cas des SectEdges qui proviennent de curve.
	  RemoveEdgeInterferences(iF1,iF2,SectEdge);
	}
      }
      TColStd_ListOfInteger& loi21 = myHB->GetDSFaceFromDSEdge(iE2, 1);
      TColStd_ListOfInteger& loi22 = myHB->GetDSFaceFromDSEdge(iE2, 2);
      for(it1.Initialize(loi21); it1.More(); it1.Next()) {
	iF1 = it1.Value();
	for(it2.Initialize(loi22); it2.More(); it2.Next()) {
	  iF2 = it2.Value();
	  // resemble au cas des SectEdges qui proviennent de curve.
	  RemoveEdgeInterferences(iF1,iF2,SectEdge);
	}
      }
      continue;
    }    
    // On s'occupe des Edges qui proviennent de Curve
    iF1 = myHB->GetDSFaceFromDSCurve(iC, 1);
    iF2 = myHB->GetDSFaceFromDSCurve(iC, 2);
    
    RemoveEdgeInterferences(iF1, iF2, iC);
    DS.ChangeKeepCurve(iC, FindKeep);
  }
  
  // En deuxième, les interferences de support 2d.
  exp.Init(C, TopAbs_EDGE);
  for(; exp.More(); exp.Next()) {
    const TopoDS_Shape& SectEdge = exp.Current();
    iC = myHB->GetDSCurveFromSectEdge(SectEdge);
    if(!iC) {
      iE1 = myHB->GetDSEdgeFromSectEdge(SectEdge, 1);
      iE2 = myHB->GetDSEdgeFromSectEdge(SectEdge, 2);
      TColStd_ListOfInteger& loi11 = myHB->GetDSFaceFromDSEdge(iE1, 1);
      TColStd_ListOfInteger& loi12 = myHB->GetDSFaceFromDSEdge(iE1, 2);
      for(it1.Initialize(loi11); it1.More(); it1.Next()) {
	iF1 = it1.Value();
	for(it2.Initialize(loi12); it2.More(); it2.Next()) {
	  iF2 = it2.Value();
	  if(iF1 == iF2)
	    continue;
	  RemoveFaceInterferences(iF1, iF2, iE1, iE2);
	}
      }
      TColStd_ListOfInteger& loi21 = myHB->GetDSFaceFromDSEdge(iE2, 1);
      TColStd_ListOfInteger& loi22 = myHB->GetDSFaceFromDSEdge(iE2, 2);
      for(it1.Initialize(loi21); it1.More(); it1.Next()) {
	iF1 = it1.Value();
	for(it2.Initialize(loi22); it2.More(); it2.Next()) {
	  iF2 = it2.Value();
	  if(iF1 == iF2)
	    continue;
	  RemoveFaceInterferences(iF1, iF2, iE1, iE2);
	}
      }
    }
    else {
      iF1 = myHB->GetDSFaceFromDSCurve(iC, 1);
      iF2 = myHB->GetDSFaceFromDSCurve(iC, 2);
      
      RemoveFaceInterferences(iF1, iF2, iC);
    }
  }
  
  // En troisième, pour les faces contenant toutes les Edges de C,
  // et qui sont SameDomain et sans Geometry, on fait RemoveSameDomain.
  
  RemoveFaceSameDomain(C);
  
  // En quatrième, on supprime les faces non touchées
  Standard_Integer NbSh = DS.NbShapes();
  for(i = 1; i <= NbSh; i++) {
    const TopoDS_Shape& Face = DS.Shape(i);
    if(Face.IsNull())
      continue;
    if((Face.ShapeType() != TopAbs_FACE) || DS.HasGeometry(Face) ||
       (myHDS->HasSameDomain(Face)))
      continue;
    for(exp.Init(Face, TopAbs_EDGE); exp.More(); exp.Next()){
      const TopoDS_Shape& Edge = exp.Current();
      if(DS.HasShape(Edge))
	break;
    }
    if(exp.More())
      continue;
    DS.ChangeKeepShape(Face, Standard_False);
  }
  
  // On reconstruit Builder.myKPMAPf1f2
  Builder.FindIsKPart(); 
  
  //  On supprime dans Builder.mySplitON les Edges de section
  exp.Init(C, TopAbs_EDGE);
  for(; exp.More(); exp.Next()) {
    const TopoDS_Shape& SectE= exp.Current();
    TopTools_ListOfShape& losob = Builder.ChangeSplit(SectE, TopAbs_ON);
    losob.Clear();
  }
}

//=======================================================================
//function : SuppressSectionVertex
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::SuppressSectionVertex
(const TopoDS_Vertex& /*V*/)
{
  if(!myRecomputeBuilderIsDone)
    return;
}


// Reconstruction des Shapes

//=======================================================================
//function : Merge
//purpose  : 
//=======================================================================

const TopoDS_Shape& BRepAlgo_DSAccess::Merge
(const TopAbs_State state1,
 const TopAbs_State state2)
{
  if((state1 != TopAbs_IN) &&
     (state1 != TopAbs_OUT))
    return myEmptyShape;
  if((state2 != TopAbs_IN) &&
     (state2 != TopAbs_OUT))
    return myEmptyShape;
  // si GetSectionEdgeSet a déjà été appellé, rien ne sera fait 
  // dans GetSectionEdgeSet.
  if(myState1 != TopAbs_UNKNOWN)
    if(myState1 != state1 || myState2 != state2)
      myGetSectionIsDone = Standard_False;
  myState1 = state1;
  myState2 = state2;
  GetSectionEdgeSet();
  
  myHB->Clear();
  myHB->MergeShapes(myS1,state1,myS2,state2);
  const TopTools_ListOfShape& L1 = myHB->Merged(myS1,state1);
  
  BRep_Builder BB;
  myResultShape.Nullify();
  BB.MakeCompound(TopoDS::Compound(myResultShape));
  TopTools_ListIteratorOfListOfShape it(L1);
  for(;it.More(); it.Next()) {
    BB.Add(myResultShape, it.Value());
  }
  return myResultShape;
}

//=======================================================================
//function : Merge
//purpose  : 
//=======================================================================

const TopoDS_Shape& BRepAlgo_DSAccess::Merge
(const TopAbs_State state1)
{
  if((state1 != TopAbs_IN) &&
     (state1 != TopAbs_OUT))
    return myEmptyShape;
  GetSectionEdgeSet();

  myHB->Clear();
  myHB->MergeSolid(myS1,state1);
  const TopTools_ListOfShape& L1 = myHB->Merged(myS1,state1);
  
  BRep_Builder BB;
  myResultShape.Nullify();
  BB.MakeCompound(TopoDS::Compound(myResultShape));
  TopTools_ListIteratorOfListOfShape it(L1);
  for(;it.More(); it.Next()) {
    BB.Add(myResultShape, it.Value());
  }
  return myResultShape;
}

//=======================================================================
//function : Propagate
//purpose  : 
//=======================================================================

const TopoDS_Shape& BRepAlgo_DSAccess::Propagate
(const TopAbs_State what,
 const TopoDS_Shape& /*fromShape*/,
 const TopoDS_Shape& /*LoadShape*/)
{
  if((what != TopAbs_IN) &&
     (what != TopAbs_OUT))
    return myEmptyShape;
  if(!myRecomputeBuilderIsDone)
    return myEmptyShape;

//  myHB->MergeShapes(myS1,t1,myS2,t2);

  //POP pour NT;
  static TopoDS_Shape bid;
  return bid;
}

//=======================================================================
//function : PropagateFromSection
//purpose  : 
//=======================================================================

const TopoDS_Shape& BRepAlgo_DSAccess::PropagateFromSection
(const TopoDS_Shape& SectionShape)
{
  GetSectionEdgeSet();
  TopTools_ListIteratorOfListOfShape ils(myListOfCompoundOfEdgeConnected);
  TopExp_Explorer exp;
  for(; ils.More(); ils.Next()) {
    const TopoDS_Shape& SetEdgSet = ils.Value();
    exp.Init(SetEdgSet, TopAbs_EDGE);
    for(; exp.More(); exp.Next()) {
      if(SectionShape.IsSame(exp.Current()))
	return SetEdgSet;
    }
  }
  return myEmptyShape;
}

//=======================================================================
//function : Modified
//purpose  : 
//=======================================================================

const TopTools_ListOfShape& BRepAlgo_DSAccess::Modified (const TopoDS_Shape& Shape) 
{
  myModified.Clear() ;

//  Handle(TopOpeBRepBuild_HBuilder)& HBuilder = myDSA.myHB ;
  TopTools_ListIteratorOfListOfShape Iterator ;
  
  if (myHB->IsSplit (Shape, TopAbs_OUT)) {
    for (Iterator.Initialize (myHB->Splits (Shape, TopAbs_OUT)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }
  if (myHB->IsSplit (Shape, TopAbs_IN)) {
    for (Iterator.Initialize (myHB->Splits (Shape, TopAbs_IN)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }
  if (myHB->IsSplit (Shape, TopAbs_ON)) {
    for (Iterator.Initialize (myHB->Splits (Shape, TopAbs_ON)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }

  if (myHB->IsMerged (Shape, TopAbs_OUT)) {
    for (Iterator.Initialize (myHB->Merged (Shape, TopAbs_OUT)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }
  if (myHB->IsMerged(Shape, TopAbs_IN)) {
    for (Iterator.Initialize (myHB->Merged (Shape, TopAbs_IN)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }
  if (myHB->IsMerged(Shape, TopAbs_ON)) {
    for (Iterator.Initialize (myHB->Merged (Shape, TopAbs_ON)) ;
	 Iterator.More() ;
	 Iterator.Next()) {
      myModified.Append (Iterator.Value()) ;
    }
  }

  return myModified ;
}



//=======================================================================
//function : Check
//purpose  : 
//=======================================================================

BRepAlgo_CheckStatus BRepAlgo_DSAccess::Check()
{
//  TopOpeBRepDS_Check Ck(HDS);
  // a affiner : dans Ck, on a la possibilité de savoir 
  // précisemment les nº des shapes/points/curves/surfaces
  // qui ne sont pas bon dans la SD.
//  Standard_Boolean IsOK = Ck.ChkIntgSamDom() ;
//  IsOK = IsOK && Ck.OneVertexOnPnt();
//  IsOK = IsOK && Ck.ChkIntg();
//  if(IsOK)
//    return TopOpeBRepDS_OK;
  return BRepAlgo_NOK;
}

//=======================================================================
//function : RemoveEdgeInterferences
//purpose  : cas de SectEdge venant d'Edge(s)
//       
//     si iE1 et iE2 sont des Edges :
//       Supprimer les interferences de DSEdge(= iE1 ou iE2) de
//       geometry un vertex de SectEdge, et s'il n'y avait que celle-ci, 
//	 faire unkeep sur DSEdge 
//       si iE1 ou iE2 == 0, pas d'interference sur les Edges dans la SD 
//       NYI : gestion SameDomain
//       
//     si iE1 et iE2 sont des Faces :
//       pour chacune des faces F1 et F2, explorer en Edges
//	   pour chaque Edge :
//	     supprimer les interferences qui ont pour geometry un vertex
//	     de SectEdge. S'il n'y a pas d'autre interference attachée à 
//           ces Edges, et si ces Edges ne sont pas SameDomain,
//           faire unKeepShape.
//=======================================================================

void BRepAlgo_DSAccess::RemoveEdgeInterferences
(const Standard_Integer iE1,
 const Standard_Integer iE2,
 const TopoDS_Shape& SectEdge)
{
  if(!iE1 || !iE2)
    return;

  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepDS_Kind kind1, kind2;
  TopExp_Explorer exp(SectEdge, TopAbs_VERTEX);
  Standard_Integer i = 1, ipv1, ipv2;
  
  // on recupère les Vertex/Points de SectEdge
  PntVtxOnSectEdge(SectEdge, ipv1, kind1, ipv2, kind2);
  
  const TopoDS_Shape& Shape = DS.Shape(iE1, FindKeep);
  if(Shape.IsNull())
    return;
  if(Shape.ShapeType() == TopAbs_FACE) {
    Standard_Integer iF1 = iE1, iF2 = iE2;
    RemoveEdgeInterferencesFromFace(iF1, iF2, ipv1, kind1, ipv2, kind2);
    return;
  }
  else if(Shape.ShapeType() != TopAbs_EDGE)
    return;
  
  // on enlève les interferences de la SD
  TopOpeBRepDS_ListIteratorOfListOfInterference lioloi;
  TopOpeBRepDS_Kind gk;
  Standard_Integer iCurrE1, iCurrE2, gi;
//  Standard_Boolean RemInterf;
  
  for(i = 1; i <= 2; i++) {
    iCurrE1 = ((i == 1) ? iE1 : iE2);
    iCurrE2 = ((i == 1) ? iE2 : iE1);
    const TopoDS_Shape& DSEdge = DS.Shape(iCurrE1, FindKeep);
    if(DSEdge.IsNull())
      continue;
    TopOpeBRepDS_ListOfInterference& loi = 
      DS.ChangeShapeInterferences(DSEdge);
    //    RemInterf = Standard_True;
    for(lioloi.Initialize(loi); lioloi.More(); lioloi.Next()) {
      Handle(TopOpeBRepDS_Interference) I = lioloi.Value();
      if (I.IsNull()) continue;
      if((I->SupportType() != TopOpeBRepDS_EDGE) ||
	 (I->Support() != iCurrE2)) {
	//	RemInterf = Standard_False;//debug ...
	continue;
      }
      gk = I->GeometryType();
      gi = I->Geometry();
      if(gk == kind1) {
	if(gi == ipv1) {
	  DS.RemoveShapeInterference(DSEdge, I);
	  if(!DS.HasGeometry(DSEdge)) {
	    //	    if(RemInterf || (!lioloi.More())) {
	    RemoveEdgeSameDomain(iCurrE1, iCurrE2); // NYI : SameDomain
	    DS.ChangeKeepShape(iCurrE1, FindKeep);
	    //	  } 
	  } 
	}
      }
      else if(gk == kind2) {
	if(gi == ipv2) {
	  DS.RemoveShapeInterference(DSEdge, I);
	  if(!DS.HasGeometry(DSEdge)) {
	    //	    if(RemInterf || (!lioloi.More())) {//debug
	    RemoveEdgeSameDomain(iCurrE1, iCurrE2); // NYI : SameDomain
	    DS.ChangeKeepShape(iCurrE1, FindKeep);
	    //	  } 
	  }
	}
      }
    }
  }
}

//=======================================================================
//function : RemoveEdgeInterferences
//purpose  : cas de SectEdge venant de Curve
//       pour chacune des faces F1 et F2, explorer en Edges
//	   pour chaque Edge :
//	     supprimer les interferences qui ont pour geometry un vertex
//	     de SectEdge. S'il n'y a pas d'autre interference attachée à 
//           ces Edges, et si ces Edges ne sont pas SameDomain,
//           faire unKeepShape.
//=======================================================================

void BRepAlgo_DSAccess::RemoveEdgeInterferences
(const Standard_Integer iF1,
 const Standard_Integer iF2,
 const Standard_Integer iCurve)
{
  TopOpeBRepDS_Kind gk1, gk2;
  Standard_Integer gi1, gi2;
  
  PntVtxOnCurve(iCurve, gi1, gk1, gi2, gk2);

  if (!mySetOfKeepPoint.IsEmpty()) {
    if (mySetOfKeepPoint.Contains(gi1)) gi1 = 0;
    if (mySetOfKeepPoint.Contains(gi2)) gi2 = 0;   
  }
  
  if (gi1 || gi2)
    RemoveEdgeInterferencesFromFace(iF1, iF2, gi1, gk1, gi2, gk2);
}

//=======================================================================
//function : RemoveFaceInterferences
//purpose  : cas de SectEdge venant d'Edge(s)
//        Supprimer les interferences entre F1 et F2 concernant 
//        DSEdge (= E1 ou E2) :
//		a) si DSEdge n'est pas SameDomain -> on Remove l'edge
//		b) si parmi les autres interferences de DSEdge de 
//                 GeomtryType == VERTEX, il n'en existe pas qui soient 
//                 avec une Edge de DSFace(= F1 ou F2)
//	  si DSFace n'a plus d'interference et n'est pas SameDomain,
//        faire unkeep DSFace.
//=======================================================================

void BRepAlgo_DSAccess::RemoveFaceInterferences
(const Standard_Integer iF1,
 const Standard_Integer iF2,
 const Standard_Integer iE1,
 const Standard_Integer iE2)
{
  if(!iF1 || !iF2)
    return;
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepDS_ListIteratorOfListOfInterference lioloi;//, lioloei, liolofi;
  TopTools_ListIteratorOfListOfShape liolos;
  TopOpeBRepDS_Kind gk;
  TopExp_Explorer exp;
  Standard_Integer i, iCurrF1, iCurrF2, j, iCurrE1, /*iCurrE2,*/ gi; // skl
  Standard_Boolean RemInterf;
  
  for(i = 1; i <= 2; i++) {
    iCurrF1 = ((i == 1) ? iF1 : iF2);
    iCurrF2 = ((i == 1) ? iF2 : iF1);
    const TopoDS_Shape& DSFace = DS.Shape(iCurrF1);
    if(DSFace.IsNull())
      continue;
    const TopOpeBRepDS_ListOfInterference& loi = DS.ShapeInterferences(DSFace);
    for(lioloi.Initialize(loi); lioloi.More(); lioloi.Next()) {
      Handle(TopOpeBRepDS_Interference) I = lioloi.Value();
      if (I.IsNull()) continue;
      if((I->SupportType() != TopOpeBRepDS_FACE) ||
	 (I->Support() != iCurrF2)) {
	continue;
      }
      gk = I->GeometryType();
      gi = I->Geometry();
      if(gk != TopOpeBRepDS_EDGE) continue;
      for(j = 1; j <= 2; j++) {
	iCurrE1 = ((j == 1) ? iE1 : iE2);
	//iCurrE2 = ((j == 1) ? iE2 : iE1); // skl
	if(gi != iCurrE1) continue;
	// a) si DSEdge n'est pas SameDomain -> on Remove l'interference
	//    et DSEdge
	const TopoDS_Shape& DSEdge = DS.Shape(iCurrE1, FindKeep);
	if(DSEdge.IsNull())
	  continue;
	if(!myHDS->HasSameDomain(DSEdge)) {
	  if(!DS.HasGeometry(DSEdge)) {
	    DS.RemoveShapeInterference(DSFace, I);
	    DS.ChangeKeepShape(DSEdge, FindKeep);
	  } else {
	    // NYI : gérer le cas où la geometry de DSEdge n'a
	    // NYI : rien à voir avec les deux faces
	  }
	  if(!DS.HasGeometry(DSFace)) {
	    DS.ChangeKeepShape(DSFace, FindKeep);
	  }
	  continue;
	}
	// b) si parmi les Edges de SameDomain(DSEdge),
	//    il n'y en a pas qui appartiennent à DSFace(= F1 ou F2)
	//     -> on Remove l'interference
	const TopoDS_Shape& Edge = DS.Shape(iCurrE1, FindKeep);
	if(Edge.IsNull())
	  continue;
	const TopTools_ListOfShape& loe = DS.ShapeSameDomain(Edge);
	RemInterf = Standard_True;
	for(liolos.Initialize(loe); liolos.More(); liolos.Next()) {
	  const TopoDS_Shape& ESD = liolos.Value();
	  for(exp.Init(DSFace, TopAbs_EDGE); exp.More(); exp.Next()) {
	    if(ESD.IsSame(exp.Current())) {
	      RemInterf = Standard_False;
	      break;
	    }
	  }
	  if(!RemInterf) break;
	}
	if(RemInterf) {
	  //	  RemoveSameDomain(iCurrF1, iCurrF2);
	  
	  if(!DS.HasGeometry(DSFace)) {
	    if(!myHDS->HasSameDomain(DSFace))
	      DS.ChangeKeepShape(DSFace, FindKeep);
	  }
	}
	if(!DS.HasGeometry(DSFace) && !myHDS->HasSameDomain(DSFace))
	  DS.ChangeKeepShape(DSFace, FindKeep);
      }
    }
  }
}

//=======================================================================
//function : RemoveFaceInterferences
//purpose  : cas de SectEdge venant de Curve
//           supprimer les interferences de Geometry iCurve entre F1 et F2.
//           si Face(= F1 ou F2) n'a pas d'autre interference, et si Face
//           n'est pas SameDomain, faire unKeepShape Face.
//=======================================================================

void BRepAlgo_DSAccess::RemoveFaceInterferences
(const Standard_Integer iF1,
 const Standard_Integer iF2,
 const Standard_Integer iCurve)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepDS_ListIteratorOfListOfInterference lioloi;
  TopOpeBRepDS_Kind gk;
  Standard_Integer i, iCurrF1, iCurrF2, gi;

  for(i = 1; i <= 2; i++) {
    iCurrF1 = ((i == 1) ? iF1 : iF2);
    iCurrF2 = ((i == 1) ? iF2 : iF1);
    const TopoDS_Shape& DSFace = DS.Shape(iCurrF1);
    const TopOpeBRepDS_ListOfInterference& loi = DS.ShapeInterferences(DSFace);
    for(lioloi.Initialize(loi); lioloi.More(); lioloi.Next()) {
      Handle(TopOpeBRepDS_Interference) I = lioloi.Value();
      if (I.IsNull()) continue;
      if((I->SupportType() != TopOpeBRepDS_FACE) ||
	 (I->Support() != iCurrF2)) {
	break;;
      }
    }
    for(lioloi.Initialize(loi); lioloi.More(); lioloi.Next()) {
      Handle(TopOpeBRepDS_Interference) I = lioloi.Value();
      if (I.IsNull()) continue;
      if((I->SupportType() != TopOpeBRepDS_FACE) ||
	 (I->Support() != iCurrF2)) {
	continue;
      }
      gk = I->GeometryType();
      gi = I->Geometry();
      if(gk != TopOpeBRepDS_CURVE) continue;
      if(gi != iCurve) continue;
      DS.RemoveShapeInterference(DSFace, I);
//      const TopoDS_Shape& interferenceface = DS.Shape(iCurrF2);
//      DS.RemoveShapeInterference(interferenceface, I);
      if(!DS.HasGeometry(DSFace)) {
	const TopTools_ListOfShape& los = DS.ShapeSameDomain(DSFace);
	if(los.IsEmpty())
	  DS.ChangeKeepShape(DSFace, FindKeep);
      }
//      if(!DS.HasGeometry(interferenceface)) {
//	const TopTools_ListOfShape& los = DS.ShapeSameDomain(interferenceface);
//	if(los.IsEmpty())
//	  DS.ChangeKeepShape(interferenceface, FindKeep);
//      }
    }
  }
}

//=======================================================================
//function : RemoveEdgeInterferencesFromFace
//purpose  : enlève les interferences des Edges de iF1 ou iF2
//           qui ont comme GeometryType kind1/kind2 et 
//           comme Geometry ipv1/ipv2.
//           si kind1/kind2 == TopAbs_VERTEX -> RemoveEdgeFromFace
//=======================================================================

void BRepAlgo_DSAccess::RemoveEdgeInterferencesFromFace
(const Standard_Integer iF1,
 const Standard_Integer iF2,
 const Standard_Integer ipv1,
 const TopOpeBRepDS_Kind kind1,
 const Standard_Integer ipv2,
 const TopOpeBRepDS_Kind kind2)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepDS_ListIteratorOfListOfInterference lioloi;
  TopExp_Explorer exp, exp2;
  TopOpeBRepDS_Kind sk, gk;
  Standard_Integer i, iCurrF1, iCurrF2, iE = 0, si, gi;

  for(i = 1; i <= 2; i++) {
    iCurrF1 = ((i == 1) ? iF1 : iF2);
    iCurrF2 = ((i == 1) ? iF2 : iF1);
    const TopoDS_Shape& DSFace = DS.Shape(iCurrF1, FindKeep);
    if(DSFace.IsNull())
      continue;
    exp.Init(DSFace, TopAbs_EDGE);
    for(; exp.More(); exp.Next()) {
      const TopoDS_Shape& DSEdge = exp.Current();
      iE = DS.Shape(DSEdge, FindKeep);
      if(!iE) continue;
      const TopOpeBRepDS_ListOfInterference& loi =
	DS.ShapeInterferences(DSEdge);
      for(lioloi.Initialize(loi); lioloi.More(); lioloi.Next()) {
	Handle(TopOpeBRepDS_Interference) I = lioloi.Value();
	if (I.IsNull()) continue;
	sk = I->SupportType();
	si = I->Support();
	if((sk != TopOpeBRepDS_FACE) || (si != iCurrF2)) {
	  if(sk != TopOpeBRepDS_EDGE)
	    continue;
	  const TopoDS_Shape& DSFace2 = DS.Shape(iCurrF2, FindKeep);
	  exp2.Init(DSFace2, TopAbs_EDGE);
	  for(; exp2.More(); exp2.Next()) {
	    if(si == DS.Shape(exp2.Current(), FindKeep))
	      break;
	  }
	  if(!exp2.More())
	    continue;
	}
	gk = I->GeometryType();
	gi = I->Geometry();
	if(gk == kind1) {
	  if(gi == ipv1) {
	    DS.RemoveShapeInterference(DSEdge, I);
//	    if(!DS.HasGeometry(DSEdge)) {
//	      const TopTools_ListOfShape& los = DS.ShapeSameDomain(DSEdge);
//	      if(los.IsEmpty()) {
//		DS.ChangeKeepShape(iE, FindKeep);
//	      }
//	    }
	  }
	  else if(gk == kind2) {
	    if(gi == ipv2) {
	      DS.RemoveShapeInterference(DSEdge, I);
//	      if(!DS.HasGeometry(DSEdge)) {
//		const TopTools_ListOfShape& los = DS.ShapeSameDomain(DSEdge);
//		if(los.IsEmpty()) {
//		  DS.ChangeKeepShape(iE, FindKeep);
//		}
//	      }
	    }
	  }
	  else continue;
	}
      }
    }
    if(kind1 == TopOpeBRepDS_VERTEX)
      RemoveEdgeFromFace(iCurrF1,ipv1);
    if(kind2 == TopOpeBRepDS_VERTEX)
      RemoveEdgeFromFace(iCurrF1,ipv2);
  }
}

//=======================================================================
//function : RemoveEdgeFromFace
//purpose  : enlève de la SD les Edges appartenant à iF
//           qui ont comme Vertex iV si elles n'ont pas de Geometry et
//           ne sont pas SameDomain.
//=======================================================================

void BRepAlgo_DSAccess::RemoveEdgeFromFace
(const Standard_Integer iF,
 const Standard_Integer iV)
{
  if(!iF || !iV)
    return;
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  const TopoDS_Shape& DSFace = DS.Shape(iF, FindKeep);
  const TopoDS_Shape& Vertex = DS.Shape(iV, FindKeep);
  if(DSFace.IsNull() || Vertex.IsNull())
    return;
  TopExp_Explorer exp(DSFace, TopAbs_EDGE), exp2;
  for(; exp.More(); exp.Next()) {
    const TopoDS_Shape& Edge = exp.Current();
#ifdef DEB
//    Standard_Integer iEdge2 = DS.Shape(Edge, FindKeep);
//    Standard_Integer iEdge3 = DS.Shape(Edge);
#endif
                              
    if(!DS.HasShape(Edge)) 
      continue;
    exp2.Init(Edge, TopAbs_VERTEX);
    for(; exp2.More(); exp2.Next()) {
#ifdef DEB
//      Standard_Integer iEdge5 = DS.Shape(Vertex, FindKeep);
//      Standard_Integer iEdge4 = DS.Shape(Vertex);
//      Standard_Integer iEdge6 = DS.Shape(exp2.Current(), FindKeep);
//      Standard_Integer iEdge7 = DS.Shape(exp2.Current());
#endif
                                
      if(Vertex.IsSame(exp2.Current())) {
	if(!DS.HasGeometry(Edge)) {
	  const TopTools_ListOfShape& los = DS.ShapeSameDomain(Edge);
	  if(los.IsEmpty()) {
#ifdef DEB
//	    Standard_Integer iEdge = DS.Shape(Edge);
#endif
	    DS.ChangeKeepShape(Edge, FindKeep);
	  }
	}
      }
    }
  }
}

//=======================================================================
//function : PntVtxOnCurve
//purpose  : On recherche les points/vertex qui sont sur les curves
//=======================================================================

void BRepAlgo_DSAccess::PntVtxOnCurve
(const Standard_Integer iCurve,
 Standard_Integer& ipv1,
 TopOpeBRepDS_Kind& pvk1,
 Standard_Integer& ipv2,
 TopOpeBRepDS_Kind& pvk2)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  
  const TopOpeBRepDS_Curve& C = DS.Curve(iCurve);
  TopOpeBRepDS_Kind pvk; 
  Standard_Integer ipv, iMother = C.Mother(), igoodC = iCurve, comp = 0;
  if(iMother) igoodC = iMother;
//#ifndef DEB
  TopOpeBRepDS_PointIterator PII = myHDS->CurvePoints(igoodC);
  TopOpeBRepDS_PointIterator& PIt = PII; // skl : I change "PI" to "PIt"
//#else
//  TopOpeBRepDS_PointIterator& PIt = myHDS->CurvePoints(igoodC);
//#endif
  for(;PIt.More(); PIt.Next()) {
    comp++;
    if(comp > 2)
      // Standard_Error ...
      return;
    ipv = PIt.Current();
    // on enlève de la DS le point ou le vertex
    if(PIt.IsPoint()) {
      pvk = TopOpeBRepDS_POINT;
      DS.ChangeKeepPoint(ipv, FindKeep);
    }
    else if(PIt.IsVertex()) {
      pvk = TopOpeBRepDS_VERTEX;
      DS.ChangeKeepShape(ipv, FindKeep);
    }
    else continue;
    ((comp == 1) ? ipv1 : ipv2) = ipv;
    ((comp == 1) ? pvk1 : pvk2) = pvk;
  }
}

//=======================================================================
//function : PntVtxOnSectEdge
//purpose  : On recherche les points/Vertex qui sont sur SectEdge
//=======================================================================

void BRepAlgo_DSAccess::PntVtxOnSectEdge
(const TopoDS_Shape& SectEdge,
 Standard_Integer& ipv1,
 TopOpeBRepDS_Kind& pvk1,
 Standard_Integer& ipv2,
 TopOpeBRepDS_Kind& pvk2)
{
//  myHB->ChangeBuilder();
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  TopOpeBRepDS_Kind kind = TopOpeBRepDS_POINT;
  TopExp_Explorer exp(SectEdge, TopAbs_VERTEX);
  Standard_Integer i = 1, ipv;
  
  for(; exp.More(); exp.Next(), i++) {    
    const TopoDS_Shape& DSVertex = exp.Current();
    ipv = myHB->GetDSPointFromNewVertex(DSVertex);
    if(!ipv) {
      ipv = DS.Shape(DSVertex, FindKeep);
      kind = TopOpeBRepDS_VERTEX;
      if(!ipv)
	// Standard_Error ...
	return;
    }
    
    if(i == 1) {
      ipv1 = ipv;
      pvk1 = kind;
    }    
    else if(i == 2) {
      ipv2 = ipv;
      pvk2 = kind;
    }
    else
      // Standard_Error ...
      return;
  }
}

//=======================================================================
//function : RemoveEdgeSameDomain
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::RemoveEdgeSameDomain
(const Standard_Integer /*iE1*/,
 const Standard_Integer /*iE2*/)
{
  return;
/*  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  const TopoDS_Shape& E1 = DS.Shape(iE1);
  const TopoDS_Shape& E2 = DS.Shape(iE2);
  TopAbs_ShapeEnum ts1, ts2;
  ts1 = E1.ShapeType();
  ts2 = E2.ShapeType();
  if((ts1 != TopAbs_EDGE) ||
     (ts2 != TopAbs_EDGE)) 
    return;
  TopTools_ListOfShape& lossd = DS.ChangeShapeSameDomain(E1);
  if(lossd.IsEmpty())
    return;
  Standard_Integer exte = lossd.Extent();
  if(exte == 1) {
    if(lossd.First().IsSame(E2))
      DS.UnfillShapesSameDomain(E1,E2);
    return;
  }*/
}

//=======================================================================
//function : RemoveFaceSameDomain
//purpose  : remove l'info SameDomain des faces collés 
//=======================================================================

void BRepAlgo_DSAccess::RemoveFaceSameDomain
(const TopoDS_Shape& C)
{
//  myHB->ChangeBuilder();
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();

//TColStd_ListIteratorOfListOfInteger it;
  TopExp_Explorer exp(C, TopAbs_EDGE);
  Standard_Integer  iE1, iE2, iE, /*NbF,*/ iF1, iF2, iCurrF1, iCurrF2,   iC =0; // skl
  iF1 = iF2 = iCurrF1 = iCurrF2 = 0;
  Standard_Boolean b;
  const TopoDS_Shape& SectEdge = exp.Current();
  
  for(; exp.More(); exp.Next()) {
    iC = myHB->GetDSCurveFromSectEdge(SectEdge);
    if(!iC && !SectEdge.IsNull())
      break;
//  const TopoDS_Shape& SectEdge = exp.Current();
  }
  if(!iC && !SectEdge.IsNull()) {
    iE1 = myHB->GetDSEdgeFromSectEdge(SectEdge, 1);
    iE2 = myHB->GetDSEdgeFromSectEdge(SectEdge, 2);
    if(iE1 && iE2) return;
    iE = (iE1 ? iE1 : iE2);
    if(!iE) return;
    
    TColStd_ListOfInteger& loi = FindGoodFace(iE, iF1, b);
    if(!b) return;
    if(exp.More())
      exp.Next();
    //NbF = loi.Extent(); // skl
    for(; exp.More(); exp.Next()) {
      // skl : I change "SectEdge" to "SectEdg"
      const TopoDS_Shape& SectEdg = exp.Current();
      iC = myHB->GetDSCurveFromSectEdge(SectEdg);
      if(!iC) {
	iE1 = myHB->GetDSEdgeFromSectEdge(SectEdg, 1);
	iE2 = myHB->GetDSEdgeFromSectEdge(SectEdg, 2);
	if(iE1 && iE2) return;
	iE = (iE1 ? iE1 : iE2);
	if(!iE) return;
	
	TColStd_ListOfInteger& loi2 = FindGoodFace(iE, iCurrF1, b);
	if(!b) return;
	if(!iCurrF1 || !iF1) return;
	if(iCurrF1 != iF1) {
	  if(loi2.Extent() == 1) iCurrF2 = loi2.First();
	  if(iCurrF2 == iF1) continue;
	  if(loi.Extent() == 1) iF2 = loi.First();

	  if(!iCurrF2 || !iF2) return;
	  if((iCurrF1 == iF2) ||
	     (iCurrF2 == iF2)) {
	    iF1 = iF2;
	    continue;
	  }
	  return;
	} 
      }
    }
    
    const TopoDS_Shape& FSD = DS.Shape(iF1);
    if(FSD.IsNull()) 
      return;
    TopTools_ListOfShape& ssd = DS.ChangeShapeSameDomain(FSD);
    TopTools_ListIteratorOfListOfShape itssd(ssd);
    TopExp_Explorer exp2;
    for(; itssd.More(); itssd.Next()) {
      exp2.Init(itssd.Value(), TopAbs_VERTEX);
      for(; exp2.More(); exp2.Next()) {
	const TopoDS_Shape& exp2Curr = exp2.Current();
	exp.Init(C, TopAbs_VERTEX);
	for(; exp.More(); exp.Next()) {
	  if(exp2Curr.IsSame(exp.Current()))
	    break;
	}
	if(exp.More())
	  break;
      }
      if(exp2.More())
	break;
    }
    
    if(exp2.More()) {
      const TopoDS_Shape& FSD2 = itssd.Value();
      Standard_Integer iFSD = DS.Shape(FSD), iFSD2 = DS.Shape(FSD2);
      RemoveFaceSameDomain(iFSD, iFSD2);      
//      DS.UnfillShapesSameDomain(FSD, FSD2);
    }
  }
}

//=======================================================================
//function : FindGoodFace
//purpose  : 
//=======================================================================

TColStd_ListOfInteger& BRepAlgo_DSAccess::FindGoodFace
(const Standard_Integer iE,
 Standard_Integer& iF1,
 Standard_Boolean& b)
{
//  myHB->ChangeBuilder();
  b = Standard_False;
  TColStd_ListOfInteger& loi = myHB->GetDSFaceFromDSEdge(iE, 1);
  if(loi.Extent() == 1) {
    iF1 = loi.First();
    b = Standard_True;
    TColStd_ListOfInteger& loi2 = myHB->GetDSFaceFromDSEdge(iE, 2);
    return loi2;
  }
  else {
    TColStd_ListOfInteger& loi2 = myHB->GetDSFaceFromDSEdge(iE, 2);
    if(loi2.Extent() == 1) {
      b = Standard_True;
      iF1 = loi2.First();
      return loi;
    }
  }
  b = Standard_False;
  return myEmptyListOfInteger;
}

//=======================================================================
//function : RemoveFaceSameDomain
//purpose  : 
//=======================================================================

void BRepAlgo_DSAccess::RemoveFaceSameDomain
(const Standard_Integer iF1,
 const Standard_Integer iF2)
{
  TopOpeBRepDS_DataStructure& DS = myHDS->ChangeDS();
  const TopoDS_Shape& F1 = DS.Shape(iF1, FindKeep);
  const TopoDS_Shape& F2 = DS.Shape(iF2, FindKeep);
  if(F1.IsNull() || F2.IsNull())
    return;


  Standard_Integer iref1 = DS.SameDomainRef(F1),
  iref2 = DS.SameDomainRef(F2), istart, iend;
  if(iref1 == iF1)
    DS.SameDomainRef(F2,iF2);
  if(iref2 == iF1)
    DS.SameDomainRef(F1,iF1);
  DS.UnfillShapesSameDomain(F1,F2);

  if(iref1 != iref2)
    return;
  Standard_Boolean iF1iF2IsConnected = Standard_False;
  TColStd_IndexedMapOfInteger moi;
  moi.Clear();
  if(iref2 == iF2) {
    istart = iF2;
    iend = iF1;
  }
  else {
    istart = iF1;
    iend = iF2;
  }
  moi.Add(istart);
  Standard_Integer NbConnect = 0, icurr;
  while(moi.Extent() > NbConnect) {
    NbConnect++;
    icurr = moi.FindKey(NbConnect);
    DS.SameDomainRef(icurr, istart);
    const TopTools_ListOfShape& los = DS.ShapeSameDomain(icurr);
    if(los.IsEmpty()) {
      const TopoDS_Shape& SNSD = DS.Shape(icurr);
      DS.SameDomainRef(SNSD, 0);
    }
    TopTools_ListIteratorOfListOfShape li(los);
    for(; li.More(); li.Next()) {
      Standard_Integer iCurrShap = DS.Shape(li.Value(), FindKeep);
      if(!iCurrShap)
	return;
      if(iCurrShap == iend)
	iF1iF2IsConnected = Standard_True;
      moi.Add(iCurrShap);
    }
  }
  if(!iF1iF2IsConnected) {
    moi.Clear();
    moi.Add(iend);
    NbConnect = 0;
    while(moi.Extent() > NbConnect) {
      NbConnect++;
      icurr = moi.FindKey(NbConnect);
      DS.SameDomainRef(icurr, iend);
      const TopTools_ListOfShape& los = DS.ShapeSameDomain(icurr);
      if(los.IsEmpty()) {
	const TopoDS_Shape& SNSD = DS.Shape(icurr);
	DS.SameDomainRef(SNSD, 0);
      }
      TopTools_ListIteratorOfListOfShape li(los);
      for(; li.More(); li.Next()) {
	Standard_Integer iCurrShap = DS.Shape(li.Value(), FindKeep);
	if(!iCurrShap)
	  return;
	moi.Add(iCurrShap);
      }
    }
  }
}

//=======================================================================
//function : DS
//purpose  : 
//=======================================================================

const Handle(TopOpeBRepDS_HDataStructure)&
BRepAlgo_DSAccess::DS() const
{
  return myHDS;
}

//=======================================================================
//function : changeDS
//purpose  : 
//=======================================================================
Handle(TopOpeBRepDS_HDataStructure)&
BRepAlgo_DSAccess::ChangeDS()
{
  return myHDS;
}

//=======================================================================
//function : Builder
//purpose  : 
//=======================================================================

const Handle(TopOpeBRepBuild_HBuilder)& 
BRepAlgo_DSAccess::Builder() const
{
  return myHB;
}

//=======================================================================
//function : ChangeBuilder
//purpose  : 
//=======================================================================

Handle(TopOpeBRepBuild_HBuilder)& 
BRepAlgo_DSAccess::ChangeBuilder()
{
  return myHB;
}
