//===========================================================================
//function : FillMap
//purpose  : 
//===========================================================================
void NMTDS_ShapesDataStructure::FillMap
  (const TopoDS_Shape& aS,
   BooleanOperations_IndexedDataMapOfShapeAncestorsSuccessors& aMSA,
   BooleanOperations_IndexedDataMapOfShapeAncestorsSuccessors& aMS) const
{
  Standard_Integer iX, i, j, aIndex, aNbSc, aNbS;
  BooleanOperations_AncestorsSeqAndSuccessorsSeq aAS;
  //
  aMSA.Add(aS, aAS);
  aMS.Add(aS, aAS);
  FillSubshapes(aS, aMSA, aMS);
  //
  aNbS=aMS.Extent();
  for(i=1; i<=aNbS; ++i) {
    TColStd_MapOfInteger aMFence;
    //
    const TopoDS_Shape& aSX=aMS.FindKey(i);
    iX=aMSA.FindIndex(aSX);
    const BooleanOperations_AncestorsSeqAndSuccessorsSeq& aAS1=aMSA(iX);
    //
    aNbSc=aAS1.NumberOfSuccessors();
    for(j=1; j<=aNbSc; ++j) {
      aIndex=aAS1.GetSuccessor(j);
      if(aMFence.Add(aIndex)) {
        BooleanOperations_AncestorsSeqAndSuccessorsSeq& aAS2=aMSA.ChangeFromIndex(aIndex);
        aAS2.SetNewAncestor(iX);
      }
    }
  }
}
//=======================================================================
// function: PrepareSetForFace
// purpose:
//=======================================================================
void NMTTools_PaveFiller::PrepareSetForFace(const Standard_Integer ,//nF1,
                                            const Standard_Integer ,//nF2,
                                            const BOPTools_ListOfPaveBlock& aLPBC,
                                            BOPTools_PaveSet& aPSF)
{
  Standard_Integer nV1, nV2;
  TColStd_MapOfInteger aMap;
  BOPTools_ListIteratorOfListOfPaveBlock anIt;
  //
  anIt.Initialize(aLPBC);
  for (; anIt.More(); anIt.Next()) {
    const BOPTools_PaveBlock& aPB=anIt.Value();
    const BOPTools_Pave& aPave1=aPB.Pave1();
    nV1=aPave1.Index();
    if (!aMap.Contains(nV1)) {
      aMap.Add(nV1);
      aPSF.Append(aPave1);
    }
    const BOPTools_Pave& aPave2=aPB.Pave2();
    nV2=aPave2.Index();
    if (!aMap.Contains(nV2)) {
      aMap.Add(nV2);
      aPSF.Append(aPave2);
    }
  }
}
//=======================================================================
// function: MakeAloneVertices
// purpose:
//=======================================================================
void NMTTools_PaveFiller::MakeAloneVertices()
{
  Standard_Integer i, aNbFFs, nF1, nF2, j, aNbPnts, nFx, aNbV;
  Standard_Real aTolF1, aTolF2, aTolSum, aTolV;
  TColStd_ListIteratorOfListOfInteger aIt;
  TColStd_ListOfInteger aLI;
  TopoDS_Vertex aV;
  TopoDS_Compound aCompound;
  BRep_Builder aBB;
  TopTools_DataMapOfShapeListOfInteger aDMVFF, aDMVFF1;
  TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger aItDMVFF;
  TopTools_DataMapOfShapeShape aDMVV;
  TopTools_DataMapOfIntegerShape aDMIV;
  TopTools_DataMapOfShapeInteger aDMVI;
  TopTools_DataMapIteratorOfDataMapOfShapeInteger aItDMVI;
  TopTools_DataMapIteratorOfDataMapOfIntegerShape aItDMIV;
  //
  aBB.MakeCompound(aCompound);
  //
  myAloneVertices.Clear();
  //
  BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences();
  //
  // 1. Collect alone vertices from FFs
  aNbV=0;
  aNbFFs=aFFs.Extent();
  for (i=1; i<=aNbFFs; ++i) {
    BOPTools_SSInterference& aFFi=aFFs(i);
    aFFi.Indices(nF1, nF2);
    //
    const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv
    const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv
    //
    aTolF1=BRep_Tool::Tolerance(aF1);
    aTolF2=BRep_Tool::Tolerance(aF2);
    aTolSum=aTolF1+aTolF2;
    //
    aLI.Clear();
    aLI.Append(nF1);
    aLI.Append(nF2);
    //
    const IntTools_SequenceOfPntOn2Faces& aSeqAlonePnts=aFFi.AlonePnts();
    aNbPnts=aSeqAlonePnts.Length();
    for (j=1; j<=aNbPnts; ++j) {
      const gp_Pnt& aP=aSeqAlonePnts(j).P1().Pnt();
      BOPTools_Tools::MakeNewVertex(aP, aTolSum, aV);
      aDMVFF.Bind(aV, aLI);
      aBB.Add(aCompound, aV);
      ++aNbV;
    }
  }
  if (!aNbV) {
    return;
  }
  //
  // 2. Try to fuse alone vertices themselves;
  FuseVertices(aCompound, aDMVV);
  //
  // if some are fused, replace them by new ones
  aItDMVFF.Initialize(aDMVFF);
  for (;  aItDMVFF.More(); aItDMVFF.Next()) {
    const TopoDS_Shape& aVx=aItDMVFF.Key();
    const TColStd_ListOfInteger& aLIx=aItDMVFF.Value();
    //
    if (!aDMVV.IsBound(aVx)) {
      aDMVFF1.Bind(aVx, aLIx);
    }
    else {
      const TopoDS_Shape& aVy=aDMVV.Find(aVx);

      if (aDMVFF1.IsBound(aVy)) {
        TColStd_ListOfInteger& aLIy=aDMVFF1.ChangeFind(aVy);
        aIt.Initialize(aLIx);
        for(; aIt.More(); aIt.Next()) {
          nFx=aIt.Value();
          aLIy.Append(nFx);
        }
      }
      else {
        aDMVFF1.Bind(aVy, aLIx);
      }
    }
  }
  aDMVFF.Clear();
  //
  // refine lists of faces in aDMVFF1;
  aItDMVFF.Initialize(aDMVFF1);
  for (;  aItDMVFF.More(); aItDMVFF.Next()) {
    TColStd_MapOfInteger aMIy;
    TColStd_ListOfInteger aLIy;
    //
    const TopoDS_Shape& aVx=aItDMVFF.Key();
    TColStd_ListOfInteger& aLIx=aDMVFF1.ChangeFind(aVx);
    aIt.Initialize(aLIx);
    for(; aIt.More(); aIt.Next()) {
      nFx=aIt.Value();
      if (aMIy.Add(nFx)) {
        aLIy.Append(nFx);
      }
    }
    aLIx.Clear();
    aLIx.Append(aLIy);
  }
  //==================================
  //
  // 3. Collect vertices from DS
  Standard_Integer aNbS, nV, nVSD, aNbVDS, i1, i2, aNbVSD;
  //
  aNbS=myDS->NumberOfShapesOfTheObject();
  // old shapes
  for (i=1; i<=aNbS; ++i) {
    const TopoDS_Shape& aS=myDS->Shape(i);
    if (aS.ShapeType() != TopAbs_VERTEX){
      continue;
    }
    //
    nVSD=FindSDVertex(i);
    nV=(nVSD) ? nVSD : i;
    const TopoDS_Shape& aVx=myDS->Shape(nV);
    if (!aDMVI.IsBound(aVx)) {
      aDMVI.Bind(aVx, nV);
    }
  }
  // new shapes
  i1=myDS->NumberOfSourceShapes()+1;
  i2=myDS->NumberOfInsertedShapes();
  for (i=i1; i<=i2; ++i) {
    const TopoDS_Shape aS=myDS->Shape(i);//mpv
    if (aS.ShapeType() != TopAbs_VERTEX){
      continue;
    }
    if (!aDMVI.IsBound(aS)) {
      aDMVI.Bind(aS, i);
    }
  }
  //
  // 4. Initialize BoundSortBox on aDMVI
  //
  Handle(Bnd_HArray1OfBox) aHAB;
  Bnd_BoundSortBox aBSB;
  //
  aNbVDS=aDMVI.Extent();
  aHAB=new Bnd_HArray1OfBox(1, aNbVDS);
  //
  aItDMVI.Initialize(aDMVI);
  for (i=1; aItDMVI.More(); aItDMVI.Next(), ++i) {
    Bnd_Box aBox;
    //
    nV=aItDMVI.Value();
    aV=TopoDS::Vertex(aItDMVI.Key());
    aTolV=BRep_Tool::Tolerance(aV);
    aBox.SetGap(aTolV);
    BRepBndLib::Add(aV, aBox);
    aHAB->SetValue(i, aBox);
    //
    aDMIV.Bind(i, aV);
  }
  aBSB.Initialize(aHAB);
  //
  // 5. Compare
  aItDMVFF.Initialize(aDMVFF1);
  for (;  aItDMVFF.More(); aItDMVFF.Next()) {
    Bnd_Box aBoxV;
    //
    const TColStd_ListOfInteger& aLIFF=aItDMVFF.Value();
    aV=TopoDS::Vertex(aItDMVFF.Key());
    //
    aTolV=BRep_Tool::Tolerance(aV);
    aBoxV.SetGap(aTolV);
    BRepBndLib::Add(aV, aBoxV);
    //
    const TColStd_ListOfInteger& aLIVSD=aBSB.Compare(aBoxV);
    aNbVSD=aLIVSD.Extent();
    if (aNbVSD==0) {
      // add new vertex in DS and update map myAloneVertices
      BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
      //
      myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq);
      nV=myDS->NumberOfInsertedShapes();
      //
      aIt.Initialize(aLIFF);
      for (; aIt.More(); aIt.Next()) {
        nFx=aIt.Value();
        if (myAloneVertices.Contains(nFx)) {
          TColStd_IndexedMapOfInteger& aMVx=myAloneVertices.ChangeFromKey(nFx);
          aMVx.Add(nV);
        }
        else {
          TColStd_IndexedMapOfInteger aMVx;
          aMVx.Add(nV);
          myAloneVertices.Add(nFx, aMVx);
        }
      }
    }
  }
  // qqf
  {
    Standard_Integer aNbF, aNbAV, nF, k;
    NMTTools_IndexedDataMapOfIndexedMapOfInteger aMAVF;
    //
    aNbF=myAloneVertices.Extent();
    if (aNbF<2) {
      return;
    }
    //
    // 1. fill map Alone Vertex/Face ->  aMAVF
    for (i=1; i<=aNbF; ++i) {
      nF=myAloneVertices.FindKey(i);
      const TColStd_IndexedMapOfInteger& aMAV=myAloneVertices(i);
      aNbAV=aMAV.Extent();
      for(j=1; j<=aNbAV; ++j) {
        nV=aMAV(j);
        if (aMAVF.Contains(nV)) {
          TColStd_IndexedMapOfInteger& aMF=aMAVF.ChangeFromKey(nV);
          aMF.Add(nF);
        }
        else{
          TColStd_IndexedMapOfInteger aMF;
          aMF.Add(nF);
          aMAVF.Add(nV, aMF);
        }
      }
    }
    //
    // 2 Obtain pairs of faces
    aNbAV=aMAVF.Extent();
    for (i=1; i<=aNbAV; ++i) {
      const TColStd_IndexedMapOfInteger& aMF=aMAVF(i);
      aNbF=aMF.Extent();
      for(j=1; j<aNbF; ++j) {
        nF1=aMF(j);
        for(k=j+1; k<=aNbF; ++k) {
          nF2=aMF(k);
          myIP->Add(nF1, nF2, Standard_True, NMTDS_TI_FF);
        }
      }
    }
  }
  // qqt
}
Пример #4
0
//=======================================================================
//function : MergeEdges
//purpose  : auxilary
//=======================================================================
static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
                                   const TopoDS_Face& aFace,
                                   const Standard_Real Tol,
                                   TopoDS_Edge& anEdge)
{
  // make chain for union
  BRep_Builder B;
  ShapeAnalysis_Edge sae;
  TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1));
  TopoDS_Edge LastE = FirstE;
  TopoDS_Vertex VF = sae.FirstVertex(FirstE);
  TopoDS_Vertex VL = sae.LastVertex(LastE);
  TopTools_SequenceOfShape aChain;
  aChain.Append(FirstE);
  TColStd_MapOfInteger IndUsedEdges;
  IndUsedEdges.Add(1);
  Standard_Integer j;
  for(j=2; j<=SeqEdges.Length(); j++) {
    for(Standard_Integer k=2; k<=SeqEdges.Length(); k++) {
      if(IndUsedEdges.Contains(k)) continue;
      TopoDS_Edge edge = TopoDS::Edge(SeqEdges.Value(k));
      TopoDS_Vertex VF2 = sae.FirstVertex(edge);
      TopoDS_Vertex VL2 = sae.LastVertex(edge);
      if(sae.FirstVertex(edge).IsSame(VL)) {
        aChain.Append(edge);
        LastE = edge;
        VL = sae.LastVertex(LastE);
        IndUsedEdges.Add(k);
      }
      else if(sae.LastVertex(edge).IsSame(VF)) {
        aChain.Prepend(edge);
        FirstE = edge;
        VF = sae.FirstVertex(FirstE);
        IndUsedEdges.Add(k);
      }
    }
  }
  if(aChain.Length()<SeqEdges.Length()) {
    MESSAGE ("can not create correct chain...");
    return Standard_False;
  }
  // union edges in chain
  // first step: union lines and circles
  TopLoc_Location Loc;
  Standard_Real fp1,lp1,fp2,lp2;
  for(j=1; j<aChain.Length(); j++) {
    TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
    Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1);
    if(c3d1.IsNull()) break;
    while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
      Handle(Geom_TrimmedCurve) tc =
        Handle(Geom_TrimmedCurve)::DownCast(c3d1);
      c3d1 = tc->BasisCurve();
    }
    TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
    Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,Loc,fp2,lp2);
    if(c3d2.IsNull()) break;
    while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
      Handle(Geom_TrimmedCurve) tc =
        Handle(Geom_TrimmedCurve)::DownCast(c3d2);
      c3d2 = tc->BasisCurve();
    }
    if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
      // union lines
      Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
      Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
      gp_Dir Dir1 = L1->Position().Direction();
      gp_Dir Dir2 = L2->Position().Direction();
      //if(!Dir1.IsEqual(Dir2,Precision::Angular())) { 
      //if(!Dir1.IsParallel(Dir2,Precision::Angular())) { 
      if(!Dir1.IsParallel(Dir2,Tol)) { 
        continue;
      }
      // can union lines => create new edge
      TopoDS_Vertex V1 = sae.FirstVertex(edge1);
      gp_Pnt PV1 = BRep_Tool::Pnt(V1);
      TopoDS_Vertex V2 = sae.LastVertex(edge2);
      gp_Pnt PV2 = BRep_Tool::Pnt(V2);
      gp_Vec Vec(PV1,PV2);
      Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
      Standard_Real dist = PV1.Distance(PV2);
      Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
      TopoDS_Edge E;
      B.MakeEdge (E,tc,Precision::Confusion());
      B.Add (E,V1);  B.Add (E,V2);
      B.UpdateVertex(V1, 0., E, 0.);
      B.UpdateVertex(V2, dist, E, 0.);
      //ShapeFix_Edge sfe;
      //sfe.FixAddPCurve(E,aFace,Standard_False);
      //sfe.FixSameParameter(E);
      aChain.Remove(j);
      aChain.SetValue(j,E);
      j--;
    }
    if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
      // union circles
      Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
      Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
      gp_Pnt P01 = C1->Location();
      gp_Pnt P02 = C2->Location();
      if (P01.Distance(P02) > Precision::Confusion()) continue;
      // can union circles => create new edge
      TopoDS_Vertex V1 = sae.FirstVertex(edge1);
      gp_Pnt PV1 = BRep_Tool::Pnt(V1);
      TopoDS_Vertex V2 = sae.LastVertex(edge2);
      gp_Pnt PV2 = BRep_Tool::Pnt(V2);
      TopoDS_Vertex VM = sae.LastVertex(edge1);
      gp_Pnt PVM = BRep_Tool::Pnt(VM);
      GC_MakeCircle MC (PV1,PVM,PV2);
      Handle(Geom_Circle) C = MC.Value();
      TopoDS_Edge E;
      if (!MC.IsDone() || C.IsNull()) {
        // jfa for Mantis issue 0020228
        if (PV1.Distance(PV2) > Precision::Confusion()) continue;
        // closed chain
        C = C1;
        B.MakeEdge (E,C,Precision::Confusion());
        B.Add(E,V1);
        B.Add(E,V2);
      }
      else {
        gp_Pnt P0 = C->Location();
        gp_Dir D1(gp_Vec(P0,PV1));
        gp_Dir D2(gp_Vec(P0,PV2));
        Standard_Real fpar = C->XAxis().Direction().Angle(D1);
        if(fabs(fpar)>Precision::Confusion()) {
          // check orientation
          gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
          if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
            fpar = -fpar;
          }
        }
        Standard_Real lpar = C->XAxis().Direction().Angle(D2);
        if(fabs(lpar)>Precision::Confusion()) {
          // check orientation
          gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
          if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
            lpar = -lpar;
          }
        }
        if(lpar<fpar) lpar += 2*M_PI;
        Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
        B.MakeEdge (E,tc,Precision::Confusion());
        B.Add(E,V1);
        B.Add(E,V2);
        B.UpdateVertex(V1, fpar, E, 0.);
        B.UpdateVertex(V2, lpar, E, 0.);
      }
      aChain.Remove(j);
      aChain.SetValue(j,E);
      j--;
    }
  }
  if (j < aChain.Length()) {
    MESSAGE ("null curve3d in edge...");
    return Standard_False;
  }
  if (aChain.Length() > 1) {
    // second step: union edges with various curves
    // skl for bug 0020052 from Mantis: perform such unions
    // only if curves are bspline or bezier
    bool NeedUnion = true;
    for(j=1; j<=aChain.Length(); j++) {
      TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
      Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
      if(c3d.IsNull()) continue;
      while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
        Handle(Geom_TrimmedCurve) tc =
          Handle(Geom_TrimmedCurve)::DownCast(c3d);
        c3d = tc->BasisCurve();
      }
      if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
            c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
      NeedUnion = false;
      break;
    }
    if(NeedUnion) {
      MESSAGE ("can not make analitical union => make approximation");
      TopoDS_Wire W;
      B.MakeWire(W);
      for(j=1; j<=aChain.Length(); j++) {
        TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
        B.Add(W,edge);
      }
      Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W);
      Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000);
      Handle(Geom_BSplineCurve) bc = Conv.Curve();
      TopoDS_Edge E;
      B.MakeEdge (E,bc,Precision::Confusion());
      B.Add (E,VF);
      B.Add (E,VL);
      aChain.SetValue(1,E);
    }
    else {
      MESSAGE ("can not make approximation for such types of curves");
      return Standard_False;
    }
  }

  anEdge = TopoDS::Edge(aChain.Value(1));
  return Standard_True;
}
//=======================================================================
// function: MakeBlocks
// purpose:
//=======================================================================
void NMTTools_PaveFiller::MakeBlocks()
{
  myIsDone=Standard_False;
  //
  Standard_Boolean bIsExistingPaveBlock, bIsValidIn2D, bIsCoincided;
  Standard_Boolean bIsMicroEdge, bHasES;
  Standard_Integer i, aNbFFs, nF1, nF2;
  Standard_Integer nV1, nV2, j, aNbCurves;
  Standard_Real aTolR3D, aTol2D, aT1, aT2, aTolPPC=Precision::PConfusion();
  TopoDS_Face aF1, aF2;
  NMTTools_IndexedDataMapOfShapePaveBlock aMEPB;
  BooleanOperations_IndexedDataMapOfShapeInteger aMapEI;
  BOPTools_ListIteratorOfListOfPaveBlock anIt;
  //
  BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences();
  //

  //
  // 1. Make Section Edges from intersection curves
  //    between each pair of faces
  aNbFFs=aFFs.Extent();
  if (!aNbFFs) {
    return;
  }
  //
  FillFaceInfo();
  //
  for (i=1; i<=aNbFFs; ++i) {
    BOPTools_ListOfPaveBlock aLPB;
    TColStd_MapOfInteger aMVStick;
    TopTools_ListOfShape aLSE;
    TColStd_ListOfInteger aLNE;
    BOPTools_PaveSet aPSF;
    NMTTools_MapOfPaveBlock aMPBX;
    TColStd_MapIteratorOfMapOfInteger aItMI;
    NMTTools_MapIteratorOfMapOfPaveBlock aItMPB;
    //
    BOPTools_SSInterference& aFFi=aFFs(i);
    //
    // Faces
    aFFi.Indices(nF1, nF2);
    aF1=*((TopoDS_Face*)(&myDS->Shape(nF1)));
    aF2=*((TopoDS_Face*)(&myDS->Shape(nF2)));
    //
    SharedEdges(nF1, nF2, aLNE, aLSE);
    aFFi.SetSharedEdges(aLNE);
    //
    // aMVStick
    const NMTTools_FaceInfo& aFI1=myFaceInfo.Find(nF1);
    const NMTTools_FaceInfo& aFI2=myFaceInfo.Find(nF2);
    //
    const TColStd_MapOfInteger& aMVOn1=aFI1.VerticesOn();
    const TColStd_MapOfInteger& aMVIn1=aFI1.VerticesIn();
    const TColStd_MapOfInteger& aMVOn2=aFI2.VerticesOn();
    const TColStd_MapOfInteger& aMVIn2=aFI2.VerticesIn();
    //
    for (j=0; j<2; ++j) {
      const TColStd_MapOfInteger& aMV1=(!j) ? aMVOn1 :aMVIn1;
      aItMI.Initialize(aMV1);
      for (; aItMI.More(); aItMI.Next()) {
	nV1=aItMI.Key();
	if (aMVOn2.Contains(nV1) || aMVIn2.Contains(nV1)) {
	  aMVStick.Add(nV1);
	}
      }
    }
    //
    //  aLPB
    const NMTTools_MapOfPaveBlock& aMPBIn1=aFI1.PaveBlocksIn();
    const NMTTools_MapOfPaveBlock& aMPBOn1=aFI1.PaveBlocksOn();
    const NMTTools_MapOfPaveBlock& aMPBIn2=aFI2.PaveBlocksIn();
    const NMTTools_MapOfPaveBlock& aMPBOn2=aFI2.PaveBlocksOn();
    //
    aMPBX.Clear();
    for (j=0; j<4; ++j) {
      NMTTools_MapOfPaveBlock *pMPB;
      //
      if (!j) {
	pMPB=((NMTTools_MapOfPaveBlock*)&aMPBIn1);
      }
      else if (j==1) {
	pMPB=((NMTTools_MapOfPaveBlock*)&aMPBOn1);
      }
      else if (j==2) {
	pMPB=((NMTTools_MapOfPaveBlock*)&aMPBIn2);
      }
      else if (j==3) {
	pMPB=((NMTTools_MapOfPaveBlock*)&aMPBOn2);
      }
      //
      const NMTTools_MapOfPaveBlock& aMPB=*pMPB;
      aItMPB.Initialize(aMPB);
      for (; aItMPB.More(); aItMPB.Next()) {
	const BOPTools_PaveBlock& aPB=aItMPB.Key();
	if (aMPBX.Add(aPB)) {
	  aLPB.Append(aPB);
	}
	//
	else {
	  if (j>1) {
	    aFFi.AppendBlock(aPB);
	  }
	}
	//
      }
    }
    //
    BOPTools_SequenceOfCurves& aSCvs=aFFi.Curves();
    aNbCurves=aSCvs.Length();
    if (!aNbCurves) {
      continue;
    }
    //
    aTolR3D=aFFi.TolR3D();
    aTol2D=(aTolR3D < 1.e-3) ? 1.e-3 : aTolR3D;
    //
    CorrectTolR3D(aFFi, aMVStick, aTolR3D);
    //
    PrepareSetForFace (nF1, nF2, aLPB, aPSF);
    //
    // Put Paves On Curves
    for (j=1; j<=aNbCurves; ++j) {
      BOPTools_Curve& aBC=aSCvs(j);
      const IntTools_Curve& aC=aBC.Curve();
      // DEBUG f
      Handle(Geom_Curve) aC3D = aC.Curve();
      // DEBUG t
      PutPaveOnCurve (aPSF, aTolR3D, aBC);
    }
    //
    // Put bounding paves on curves
    for (j=1; j<=aNbCurves; ++j) {
      BOPTools_Curve& aBC=aSCvs(j);
      PutBoundPaveOnCurve (aBC, aFFi);
    }
    //modified by NIZNHY-PKV Wed Sep 14 13:12:14 2011f
#if OCC_VERSION_LARGE > 0x06050100 // For OCCT6.5.2 and higher
    //
    // Put closing pave if needded
    for (j=1; j<=aNbCurves; ++j) {
      BOPTools_Curve& aBC=aSCvs(j);
      PutClosingPaveOnCurve (aBC, aFFi);
    }
#endif // OCC_VERSION_LARGE > 0x06050100 // For OCCT6.5.2 and higher
    //modified by NIZNHY-PKV Wed Sep 14 13:12:17 2011t
    //
    //  Pave Blocks on Curves
    bHasES=Standard_False;
    for (j=1; j<=aNbCurves; ++j) {
      BOPTools_Curve& aBC=aSCvs(j);
      const IntTools_Curve& aIC= aBC.Curve();
      BOPTools_PaveSet& aPaveSet=aBC.Set();
      //
      BOPTools_PaveBlockIterator aPBIter(0, aPaveSet);
      for (; aPBIter.More(); aPBIter.Next()) {
        BOPTools_PaveBlock& aPBNew=aPBIter.Value();
        aPBNew.SetCurve(aIC);
        aPBNew.SetFace1(nF1);
        aPBNew.SetFace2(nF2);
        //
        nV1=aPBNew.Pave1().Index();
        nV2=aPBNew.Pave2().Index();
        aT1=aPBNew.Pave1().Param();
        aT2=aPBNew.Pave2().Param();
        //
        if((nV1==nV2) && (Abs(aT2 - aT1) < aTolPPC)) {
          continue;// mkk ft ???
        }
        //
        // 1
        bIsExistingPaveBlock=IsExistingPaveBlock(aPBNew, aLPB, aTolR3D);
        if (bIsExistingPaveBlock) {
          continue;
        }
        //
        bIsCoincided=CheckCoincidence(aPBNew, aLPB);
        if(bIsCoincided) {
          continue;
        }
        //
        // 2
        bIsExistingPaveBlock=IsExistingPaveBlock(aPBNew, aLSE, aTolR3D);
        if (bIsExistingPaveBlock) {
          continue;
        }
	//
        // Checking of validity in 2D
        //
        bIsValidIn2D=myContext->IsValidBlockForFaces(aT1, aT2, aIC, aF1, aF2, aTol2D);
        if (!bIsValidIn2D) {
          continue;
        }
        //
        //
        // Make Section Edge
        TopoDS_Edge aES;
        //
        const TopoDS_Vertex aV1=TopoDS::Vertex(myDS->Shape(nV1));
        const TopoDS_Vertex aV2=TopoDS::Vertex(myDS->Shape(nV2));
        //
        {
          Standard_Real aT;
          //
          myContext->IsVertexOnLine(aV1, aIC, aTolR3D, aT);
          BOPTools_Tools::UpdateVertex (aIC, aT, aV1);
          //
          myContext->IsVertexOnLine(aV2, aIC, aTolR3D, aT);
          BOPTools_Tools::UpdateVertex (aIC, aT, aV2);
        }
        //
        BOPTools_Tools::MakeSectEdge (aIC, aV1, aT1, aV2, aT2, aES);
        //
        NMTTools_Tools::UpdateEdge (aES, aTolR3D);
        bIsMicroEdge=IsMicroEdge(aES, myContext);
        if (bIsMicroEdge) {
          continue;
        }
        //
        {
          Handle(Geom2d_Curve) aC2D1, aC2D2;
          //
          aC2D1=aIC.FirstCurve2d();
          aC2D2=aIC.SecondCurve2d();
          //
          NMTTools_Tools::MakePCurve(aES, aF1, aC2D1);
          NMTTools_Tools::MakePCurve(aES, aF2, aC2D2);
        }
        //
        aMEPB.Add(aES, aPBNew);
        aMapEI.Add(aES, i);
        //
        bHasES=Standard_True;
      }// for (; aPBIter.More(); aPBIter.Next())
    } // end of for (j=1; j<=aNbCurves; ++j)
    // qqf
    if (bHasES) {
      myIP->Add(nF1, nF2, Standard_True, NMTDS_TI_FF);
    }
    // qqt
  }// for (i=1; i<=aNbFFs; ++i)
  //=============================================================
  //
  // II. Post treatment
  //
  // Input data: aMEPB, aMapEI
  // Result    : section edges in myDS
  //
  Standard_Integer aNbSE;
  //
  aNbSE=aMEPB.Extent();
  if (!aNbSE) {
    // there is nothing to do here
    return;
  }
  //
  BRep_Builder aBB;
  TopoDS_Compound aCompound;
  //
  // 1. Make compound from SE
  aBB.MakeCompound(aCompound);
  for (i=1; i<=aNbSE; ++i) {
    const TopoDS_Shape& aSE=aMEPB.FindKey(i);
    aBB.Add(aCompound, aSE);
  }
  //
  //
  // 2. Intersect SE using auxiliary Filler
  NMTTools_PaveFiller tPF;
  //
  tPF.SetCompositeShape(aCompound);
  //
  // 2.1.VV
  tPF.Init();
  tPF.PerformVV();
  //
  // 2.2.VE
  tPF.myPavePool.Resize (tPF.myNbEdges);
  tPF.PrepareEdges();
  tPF.PerformVE();
  //
  // 2.3.VF
  tPF.PerformVF();
  //
  // 2.4.EE
  tPF.myCommonBlockPool.Resize (tPF.myNbEdges);
  tPF.mySplitShapesPool.Resize (tPF.myNbEdges);
  tPF.myPavePoolNew    .Resize (tPF.myNbEdges);

  tPF.PreparePaveBlocks(TopAbs_VERTEX, TopAbs_EDGE);
  tPF.PreparePaveBlocks(TopAbs_EDGE, TopAbs_EDGE);
  //
  tPF.PerformEE();
  //
  tPF.RefinePavePool ();
  //
  tPF.myPavePoolNew.Destroy();
  //
  tPF.MakeSplitEdges();
  tPF.UpdateCommonBlocks();
  //
  // 3. Treatment of the result of intersection
  //
  Standard_Integer aNbOld, aNbLines, aNbPB, mV1, mV2, nE, mE, iFF;
  TopAbs_ShapeEnum aType;
  BOPTools_ListIteratorOfListOfPaveBlock aIt;
  BOPTColStd_IndexedDataMapOfIntegerInteger aMNewOld;
  //
  const NMTDS_ShapesDataStructure& tDS=*(tPF.DS());
  const BOPTools_SplitShapesPool& aSSP=tPF.mySplitShapesPool;
  const NMTTools_CommonBlockPool& aCBP=tPF.myCommonBlockPool;
  //
  aNbLines=tDS.NumberOfInsertedShapes();
  aNbOld=tDS.NumberOfShapesOfTheObject();
  //
  // 3.1 Links between indices in tDS and DS (kept in aMNewOld)
  //
  // 3.1.1.Old vertices [ links ]
  for (i=1; i<=aNbOld; ++i) {
    const TopoDS_Shape& aV=tDS.Shape(i);
    aType=aV.ShapeType();
    if (aType!=TopAbs_VERTEX) {
      continue;
    }
    //
    for (j=1; j<=aNbSE; ++j) {
      const BOPTools_PaveBlock& aPBSE=aMEPB(j);
      nV1=aPBSE.Pave1().Index();
      const TopoDS_Shape aV1=myDS->Shape(nV1);//mpv
      if (aV1.IsSame(aV)) {
        aMNewOld.Add(i, nV1);
        break;
      }
      nV2=aPBSE.Pave2().Index();
      const TopoDS_Shape aV2=myDS->Shape(nV2);//mpv
      if (aV2.IsSame(aV)) {
        aMNewOld.Add(i, nV2);
        break;
      }
    }
  }
  //
  // 3.1.2. New vertices [ links ]
  i=tDS.NumberOfSourceShapes()+1;
  for (; i<=aNbLines; ++i) {
    const TopoDS_Shape& aV=tDS.Shape(i);
    aType=aV.ShapeType();
    if (aType!=TopAbs_VERTEX) {
      continue;
    }
    //
    // Insert new vertex in myDS
    BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
    myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq);
    nV1=myDS->NumberOfInsertedShapes();
    // link
    aMNewOld.Add(i, nV1);
  }
  //
  // 3.2. Treatment of section edges (SE)
  for (i=1; i<=aNbOld; ++i) {
    const TopoDS_Shape& aE=tDS.Shape(i);
    aType=aE.ShapeType();
    if (aType!=TopAbs_EDGE) {
      continue;
    }
    //
    //  block of section edge that we already have for this SE
    BOPTools_PaveBlock& aPBSE=aMEPB.ChangeFromKey(aE);
    //
    // Corresponding FF-interference
    iFF=aMapEI.FindFromKey(aE);
    BOPTools_SSInterference& aFFi=aFFs(iFF);
    BOPTools_SequenceOfCurves& aSCvs=aFFi.Curves();
    //
    BOPTools_Curve& aBC=aSCvs(1);
    //
    const BOPTools_ListOfPaveBlock& aLPB=aSSP(tDS.RefEdge(i));
    aNbPB=aLPB.Extent();
    //
    if (!aNbPB) {
      // no pave blocks -> use aPBSE and whole edge aE
      BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
      //
      nV1=aPBSE.Pave1().Index();
      const TopoDS_Shape aV1=myDS->Shape(nV1);//mpv
      nV2=aPBSE.Pave2().Index();
      const TopoDS_Shape aV2=myDS->Shape(nV2);//mpv
      //
      anASSeq.SetNewSuccessor(nV1);
      anASSeq.SetNewOrientation(aV1.Orientation());
      anASSeq.SetNewSuccessor(nV2);
      anASSeq.SetNewOrientation(aV2.Orientation());
      //
      myDS->InsertShapeAndAncestorsSuccessors(aE, anASSeq);
      nE=myDS->NumberOfInsertedShapes();
      //
      aPBSE.SetEdge(nE);
      aBC.AppendNewBlock(aPBSE);
      //
      continue;
    }
    //
    nF1=aPBSE.Face1();
    nF2=aPBSE.Face2();
    //
    const NMTTools_ListOfCommonBlock& aLCB=aCBP(tDS.RefEdge(i));
    NMTTools_CommonBlockAPI aCBAPI(aLCB);
    //
    aIt.Initialize(aLPB);
    for (; aIt.More(); aIt.Next()) {
      BOPTools_PaveBlock aPB=aIt.Value();
      //
      const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));
      const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));
      //
      if (aCBAPI.IsCommonBlock(aPB)) {
        // it can be Common Block
        Standard_Real aTolEx;
        Handle(Geom2d_Curve) aC2D1, aC2D2;
        TopoDS_Face aF1FWD, aF2FWD;
        //
        NMTTools_CommonBlock& aCB=aCBAPI.CommonBlock(aPB);
        //const BOPTools_ListOfPaveBlock& aLPBx=aCB.PaveBlocks();
        //
        aPB=aCB.PaveBlock1();
        mE=aPB.Edge(); // index of edge in tDS
        const TopoDS_Edge& aEx=TopoDS::Edge(tDS.Shape(mE));
        aTolEx=BRep_Tool::Tolerance(aEx);
        //
        aF1FWD=aF1;
        aF1FWD.Orientation(TopAbs_FORWARD);
        aF2FWD=aF2;
        aF2FWD.Orientation(TopAbs_FORWARD);
        //
        NMTTools_Tools::MakePCurve(aEx, aF1FWD, aC2D1);
        NMTTools_Tools::MakePCurve(aEx, aF2FWD, aC2D2);
        NMTTools_Tools::UpdateEdge (aEx, aTolEx);
      } //if (aCBAPI.IsCommonBlock(aPB))
      //
      // new SE
      mE=aPB.Edge(); // index of edge in tDS
      const TopoDS_Shape& aSp=tDS.Shape(mE);
      //
      const BOPTools_Pave& aPave1=aPB.Pave1();
      aT1=aPave1.Param();
      mV1=aPave1.Index();            // index in tDS
      nV1=aMNewOld.FindFromKey(mV1); // index in myDS
      const TopoDS_Shape aV1=myDS->Shape(nV1);//mpv
      //
      const BOPTools_Pave& aPave2=aPB.Pave2();
      aT2=aPave2.Param();
      mV2=aPave2.Index();
      nV2=aMNewOld.FindFromKey(mV2);
      const TopoDS_Shape aV2=myDS->Shape(nV2);//mpv
      //
      if (!aMNewOld.Contains(mE)) {
        // add new SE to the myDS
        BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
        //
        anASSeq.SetNewSuccessor(nV1);
        anASSeq.SetNewOrientation(aV1.Orientation());

        anASSeq.SetNewSuccessor(nV2);
        anASSeq.SetNewOrientation(aV2.Orientation());

        myDS->InsertShapeAndAncestorsSuccessors(aSp, anASSeq);
        nE=myDS->NumberOfInsertedShapes();
        //
        aMNewOld.Add(mE, nE);
      }
      else {
        nE=aMNewOld.FindFromKey(mE);
      }
      // Form PaveBlock;
      BOPTools_PaveBlock aPBx;
      BOPTools_Pave aP1, aP2;
      //
      aPBx.SetFace1(nF1);
      aPBx.SetFace1(nF2);
      //
      aP1.SetIndex(nV1);
      aP1.SetParam(aT1);
      //
      aP2.SetIndex(nV2);
      aP2.SetParam(aT2);
      //
      aPBx.SetPave1(aP1);
      aPBx.SetPave2(aP2);
      //
      aPBx.SetEdge(nE);
      //
      aBC.AppendNewBlock(aPBx);
    }// for (; aIt.More(); aIt.Next())
  }// for (i=1; i<=aNbOld; ++i)
  //
  myIsDone=Standard_True;
}