//=======================================================================
// function: FillImagesCompounds
// purpose:
//=======================================================================
void FillImagesCompounds(const TopTools_MapOfShape& theMS,
                         BRepAlgo_Image& theImages)
{
    TopTools_MapOfShape aMFP;
    TopTools_MapIteratorOfMapOfShape aItS;
    //
    aItS.Initialize(theMS);
    for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aC=aItS.Key();
        FillImagesCompound(aC, theImages, aMFP);
    }
}
//=======================================================================
//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);
  }
}
//=======================================================================
// function: FillImagesContainers
// purpose:
//=======================================================================
void GEOMAlgo_Builder::FillImagesContainers(const TopAbs_ShapeEnum theType)
{
    myErrorStatus=0;
    //
    Standard_Boolean bInterferred, bToReverse;
    Standard_Integer i, aNbS;
    TopAbs_ShapeEnum aType;
    BRep_Builder aBB;
    TopoDS_Iterator aIt;
    TopTools_ListIteratorOfListOfShape aItIm;
    TopTools_MapOfShape aMS;
    TopTools_MapIteratorOfMapOfShape aItS;
    //
    const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
    NMTTools_PaveFiller* pPF=myPaveFiller;
    const Handle(IntTools_Context)& aCtx= pPF->Context();
    //
    aNbS=aDS.NumberOfShapesOfTheObject();
    for (i=1; i<=aNbS; ++i) {
        const TopoDS_Shape& aC=aDS.Shape(i);
        aType=aC.ShapeType();
        if (aType==theType) {
            aMS.Add(aC);
        }
    }
    //
    if (theType==TopAbs_COMPOUND) {
        FillImagesCompounds(aMS, myImages);
        return;
    }
    //
    aItS.Initialize(aMS);
    for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aC=aItS.Key();
        // whether the shape has image
        bInterferred=Standard_False;
        aIt.Initialize(aC);
        for (; aIt.More(); aIt.Next()) {
            const TopoDS_Shape& aF=aIt.Value();
            if (myImages.HasImage(aF)) {
                bInterferred=!bInterferred;
                break;
            }
        }
        if (!bInterferred) {
            continue;
        }
        //
        TopoDS_Shape aCIm;
        GEOMAlgo_Tools3D::MakeContainer(theType, aCIm);
        //
        aIt.Initialize(aC);
        for (; aIt.More(); aIt.Next()) {
            const TopoDS_Shape& aF=aIt.Value();
            if (myImages.HasImage(aF)) {
                const TopTools_ListOfShape& aLFIm=myImages.Image(aF);
                aItIm.Initialize(aLFIm);
                for (; aItIm.More(); aItIm.Next()) {
                    TopoDS_Shape aFIm=aItIm.Value();
                    //
                    bToReverse=GEOMAlgo_Tools3D::IsSplitToReverse(aFIm, aF, aCtx);
                    if (bToReverse) {
                        aFIm.Reverse();
                    }
                    aBB.Add(aCIm, aFIm);
                }
            }
            else {
                aBB.Add(aCIm, aF);
            }
        }
        myImages.Bind(aC, aCIm);
    }// for (; aItS.More(); aItS.Next()) {
}
//=======================================================================
//function :FillInternalShapes
//purpose  :
//=======================================================================
  void GEOMAlgo_Builder::FillInternalShapes()
{
  myErrorStatus=0;
  //
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  const Handle(IntTools_Context)& aCtx= pPF->Context();
  //
  //Standard_Boolean bHasImage;
  Standard_Integer i, j, jT, aNbS, aNbSI, aNbSx, aNbSd;
  TopAbs_ShapeEnum aType, aT[]={ TopAbs_VERTEX, TopAbs_EDGE };
  TopAbs_State aState;
  TopTools_ListIteratorOfListOfShape aIt, aIt1;
  TopTools_IndexedDataMapOfShapeListOfShape aMSx;
  TopTools_IndexedMapOfShape aMx;
  TopTools_MapOfShape aMSI, aMFence, aMSOr;
  TopTools_MapIteratorOfMapOfShape aItM;
  TopTools_ListOfShape aLSI, aLSd;
  TopoDS_Iterator aItS;
  BRep_Builder aBB;
  //
  // 1. Shapes to process
  //
  // 1.1 Shapes from pure arguments aMSI
  // 1.1.1 vertex, edge
  for (i=0; i<2; ++i) {
    jT=(Standard_Integer)aT[i];
    const TopTools_ListOfShape &aLS=myShapes1[jT];
    aIt.Initialize(aLS);
    for (; aIt.More(); aIt.Next()) {
      const TopoDS_Shape& aS=aIt.Value();
      if (aMFence.Add(aS)) {
        aLSI.Append(aS);
      }
    }
  }
  // 1.1.2 wire
  {
    jT=(Standard_Integer)TopAbs_WIRE;
    const TopTools_ListOfShape &aLW=myShapes1[jT];
    aIt.Initialize(aLW);
    for (; aIt.More(); aIt.Next()) {
      const TopoDS_Shape& aW=aIt.Value();
      aItS.Initialize(aW);
      for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aE=aItS.Value();
        if (aMFence.Add(aE)) {
          aLSI.Append(aE);
        }
      }
    }
  }
  // 1.1.3 theirs images/sources
  aIt1.Initialize(aLSI);
  for (; aIt1.More(); aIt1.Next()) {
    const TopoDS_Shape& aS=aIt1.Value();
    if (myImages.HasImage(aS)) {
      const TopTools_ListOfShape &aLSp=myImages.Image(aS);
      aIt.Initialize(aLSp);
      for (; aIt.More(); aIt.Next()) {
        const TopoDS_Shape& aSI=aIt.Value();
        aMSI.Add(aSI);
      }
    }
    else {
      aMSI.Add(aS);
    }
  }
  aLSI.Clear();
  aNbSI=aMSI.Extent();
  //
  // 2. Internal vertices, edges from source solids
  aMFence.Clear();
  aLSd.Clear();
  //
  aNbS=aDS.NumberOfShapesOfTheObject();
  for (i=1; i<=aNbS; ++i) {
    const TopoDS_Shape& aS=aDS.Shape(i);
    aType=aS.ShapeType();
    if (aType==TopAbs_SOLID) {
      //
      aMx.Clear();
      OwnInternalShapes(aS, aMx);
      //
      aNbSx=aMx.Extent();
      for (j=1; j<=aNbSx; ++j) {
        const TopoDS_Shape& aSI=aMx(j);
        if (myImages.HasImage(aSI)) {
          const TopTools_ListOfShape &aLSp=myImages.Image(aSI);
          aIt.Initialize(aLSp);
          for (; aIt.More(); aIt.Next()) {
            const TopoDS_Shape& aSp=aIt.Value();
            aMSI.Add(aSp);
          }
        }
        else {
          aMSI.Add(aSI);
        }
      }
      //
      // build aux map from splits of solids
      if (myImages.HasImage(aS)) {
        const TopTools_ListOfShape &aLSp=myImages.Image(aS);
        aIt.Initialize(aLSp);
        for (; aIt.More(); aIt.Next()) {
          const TopoDS_Shape& aSp=aIt.Value();
          if (aMFence.Add(aSp)) {
            TopExp::MapShapesAndAncestors(aSp, TopAbs_VERTEX, TopAbs_EDGE, aMSx);
            TopExp::MapShapesAndAncestors(aSp, TopAbs_VERTEX, TopAbs_FACE, aMSx);
            TopExp::MapShapesAndAncestors(aSp, TopAbs_EDGE  , TopAbs_FACE, aMSx);
            aLSd.Append(aSp);
          }
        }
      }
      else {
        if (aMFence.Add(aS)) {
          TopExp::MapShapesAndAncestors(aS, TopAbs_VERTEX, TopAbs_EDGE, aMSx);
          TopExp::MapShapesAndAncestors(aS, TopAbs_VERTEX, TopAbs_FACE, aMSx);
          TopExp::MapShapesAndAncestors(aS, TopAbs_EDGE  , TopAbs_FACE, aMSx);
          aLSd.Append(aS);
          aMSOr.Add(aS);
        }
      }
    }//if (aType==TopAbs_SOLID)
  }
  //
  aNbSd=aLSd.Extent();
  //
  // 3. Some shapes of aMSI can be already tied with faces of
  //    split solids
  aItM.Initialize(aMSI);
  for (; aItM.More(); aItM.Next()) {
    const TopoDS_Shape& aSI=aItM.Key();
    if (aMSx.Contains(aSI)) {
      const TopTools_ListOfShape &aLSx=aMSx.FindFromKey(aSI);
      aNbSx=aLSx.Extent();
      if (aNbSx) {
        aMSI.Remove(aSI);
      }
    }
  }
  //
  // 4. Just check it
  aNbSI=aMSI.Extent();
  if (!aNbSI) {
    return;
  }
  //
  // 5 Settle internal vertices and edges into solids
  aMx.Clear();
  aIt.Initialize(aLSd);
  for (; aIt.More(); aIt.Next()) {
    TopoDS_Solid aSd=TopoDS::Solid(aIt.Value());
    //
    aItM.Initialize(aMSI);
    for (; aItM.More(); aItM.Next()) {
      TopoDS_Shape aSI=aItM.Key();
      aSI.Orientation(TopAbs_INTERNAL);
      //
      aState=GEOMAlgo_Tools3D::ComputeStateByOnePoint(aSI, aSd, 1.e-11, aCtx);
      if (aState==TopAbs_IN) {
        //
        if(aMSOr.Contains(aSd)) {
          //
          TopoDS_Solid aSdx;
          //
          aBB.MakeSolid(aSdx);
          aItS.Initialize(aSd);
          for (; aItS.More(); aItS.Next()) {
            const TopoDS_Shape& aSh=aItS.Value();
            aBB.Add(aSdx, aSh);
          }
          //
          aBB.Add(aSdx, aSI);
          //
          myImages.Bind(aSd, aSdx);
          aMSOr.Remove(aSd);
          aSd=aSdx;
        }
        else {
          aBB.Add(aSd, aSI);
        }
        //
        aMSI.Remove(aSI);
      } //if (aState==TopAbs_IN) {
    }// for (; aItM.More(); aItM.Next()) {
  }//for (; aIt1.More(); aIt1.Next()) {
}
//=======================================================================
//function : PrepareHistory
//purpose  :
//=======================================================================
void GEOMAlgo_Builder::PrepareHistory()
{
    if(myShape.IsNull()) {
        return;
    }
    //
    Standard_Boolean bHasImage, bContainsSD;
    TopAbs_ShapeEnum aType;
    TopTools_MapOfShape aMS;
    TopTools_ListIteratorOfListOfShape aIt;
    TopTools_MapIteratorOfMapOfShape aItM;
    //
    // 1. Clearing
    GEOMAlgo_BuilderShape::PrepareHistory();
    //
    // 2. myMapShape - all shapes of result with theirs sub-shapes
    MapShapes(myShape, myMapShape);
    //
    // 3. MS - all argument shapes with theirs sub-shapes
    aIt.Initialize(myShapes);
    for (; aIt.More(); aIt.Next()) {
        const TopoDS_Shape& aSx=aIt.Value();
        MapShapes(aSx, aMS);
    }
    //
    // 4. Treatment
    aItM.Initialize(aMS);
    for (; aItM.More(); aItM.Next()) {
        const TopoDS_Shape& aSx=aItM.Key();
        aType=aSx.ShapeType();
        //modified by NIZNHY-PKV Thu Dec  7 11:34:05 2006f
        //
        // 4.1 .myImagesResult
        TopTools_ListOfShape aLSx;
        //
        bHasImage=myImages.HasImage(aSx);
        if (!bHasImage) {
            if (myMapShape.Contains(aSx)) {
                aLSx.Append(aSx);
                myImagesResult.Add(aSx, aLSx);
            }
        }
        else {
            const TopTools_ListOfShape& aLSp=myImages.Image(aSx);
            aIt.Initialize(aLSp);
            for (; aIt.More(); aIt.Next()) {
                const TopoDS_Shape& aSp=aIt.Value();
                if (myMapShape.Contains(aSp)) {
                    aLSx.Append(aSp);
                }
            }
            myImagesResult.Add(aSx, aLSx);
        }
        //
        //modified by NIZNHY-PKV Thu Dec  7 11:34:10 2006t
        //
        // 4.2 As it was
        if (!myHasDeleted) {
            myHasDeleted=IsDeleted(aSx);//xx
        }
        //
        if (!myHasGenerated || !myHasModified) {
            if (aType==TopAbs_EDGE   || aType==TopAbs_FACE ||
                    aType==TopAbs_VERTEX || aType==TopAbs_SOLID) {
                //modified by NIZNHY-PKV Thu Dec  7 11:53:01 2006f
                //bHasImage=myImages.HasImage(aSx);
                //modified by NIZNHY-PKV Thu Dec  7 11:53:04 2006t
                if (bHasImage) {
                    const TopTools_ListOfShape& aLSp=myImages.Image(aSx);
                    aIt.Initialize(aLSp);
                    for (; aIt.More(); aIt.Next()) {
                        const TopoDS_Shape& aSp=aIt.Value();
                        //
                        if (myMapShape.Contains(aSp)) {
                            bContainsSD=mySameDomainShapes.Contains(aSp);
                            //
                            if (!myHasGenerated) {
                                if (bContainsSD) {
                                    myHasGenerated=Standard_True;
                                }
                            }
                            if (!myHasModified) {
                                if (!bContainsSD) {
                                    myHasModified=Standard_True;
                                }
                            }
                        } // if (myMapShape.Contains(aSp))
                    }
                }
            }
        }
    }

}
//=======================================================================
//function : PerformInternalShapes
//purpose  : 
//=======================================================================
  void GEOMAlgo_BuilderFace::PerformInternalShapes()
{
  myErrorStatus=0;
  //
  Standard_Integer aNbWI=myLoopsInternal.Extent();
  if (!aNbWI) {// nothing to do
    return;
  }
  // 
  //Standard_Real aTol;
  BRep_Builder aBB;
  TopTools_ListIteratorOfListOfShape aIt1, aIt2;
  TopoDS_Iterator aIt; 
  TopTools_MapOfShape aME, aMEP;
  TopTools_MapIteratorOfMapOfShape aItME;
  TopTools_IndexedDataMapOfShapeListOfShape aMVE;
  TopTools_ListOfShape aLSI;
  //
  // 1. All internal edges
  aIt1.Initialize(myLoopsInternal);
  for (; aIt1.More(); aIt1.Next()) {
    const TopoDS_Shape& aWire=aIt1.Value();
    aIt.Initialize(aWire);
    for (; aIt.More(); aIt.Next()) {
      const TopoDS_Shape& aE=aIt.Value();
      aME.Add(aE);
    }
  }
  aNbWI=aME.Extent();
  //
  // 2 Process faces
  aIt2.Initialize(myAreas);
  for ( ; aIt2.More(); aIt2.Next()) {
    TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
    //
    aMVE.Clear();
    TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
    //
    // 2.1 Separate faces to process aMEP
    aMEP.Clear();
    aItME.Initialize(aME);
    for (; aItME.More(); aItME.Next()) {
      const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
      if (IsInside(aE, aF, myContext)) {
	aMEP.Add(aE);
      }
    }
    //
    // 2.2 Make Internal Wires
    aLSI.Clear();
    MakeInternalWires(aMEP, aLSI);
    //
    // 2.3 Add them to aF
    aIt1.Initialize(aLSI);
    for (; aIt1.More(); aIt1.Next()) {
      const TopoDS_Shape& aSI=aIt1.Value();
      aBB.Add (aF, aSI);
    }
    //
    // 2.4 Remove faces aMFP from aMF
    aItME.Initialize(aMEP);
    for (; aItME.More(); aItME.Next()) {
      const TopoDS_Shape& aE=aItME.Key();
      aME.Remove(aE);
    }
    //
    aNbWI=aME.Extent();
    if (!aNbWI) {
      break;
    }
  } //for ( ; aIt2.More(); aIt2.Next()) {
}