//=======================================================================
//function : DetectShapes
//purpose  :
//=======================================================================
  void GEOMAlgo_GlueAnalyser::DetectShapes(const TopAbs_ShapeEnum aType)
{
  myErrorStatus=0;
  //
  Standard_Integer i, aNbF, aNbSDF, iErr;
  TopoDS_Shape aNewShape;
  TopTools_IndexedMapOfShape aMF;
  TopTools_ListIteratorOfListOfShape aItS;
  GEOMAlgo_PassKeyShape aPKF;
  GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
  //
  TopExp::MapShapes(myShape, aType, aMF);
  //
  aNbF=aMF.Extent();
  for (i=1; i<=aNbF; ++i) {
    const TopoDS_Shape& aS=aMF(i);
    //
    //aPKF.Clear();//qft
    if (aType==TopAbs_FACE) {
      const TopoDS_Face& aF=TopoDS::Face(aS);
      FacePassKey(aF, aPKF);
    }
    else if (aType==TopAbs_EDGE) {
      const TopoDS_Edge& aE=TopoDS::Edge(aS);
      EdgePassKey(aE, aPKF);
    }
    //
    if (myErrorStatus) {
      return;
    }
    //
    if (aMPKLF.Contains(aPKF)) {
      TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
      aLSDF.Append(aS);
    }
    else {
      TopTools_ListOfShape aLSDF;
      //
      aLSDF.Append(aS);
      aMPKLF.Add(aPKF, aLSDF);
    }
  }
  // check geometric coincidence
  if (myCheckGeometry) {
    iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTol, myContext); //XX
    if (iErr) {
      myErrorStatus=200;
      return;
    }
  }
  //
  // Images/Origins
  aNbF=aMPKLF.Extent();
  for (i=1; i<=aNbF; ++i) {
    const TopTools_ListOfShape& aLSDF=aMPKLF(i);
    aNbSDF=aLSDF.Extent();
    if (!aNbSDF) {
      myErrorStatus=4; // it must not be
    }
    //
    const TopoDS_Shape& aS1=aLSDF.First();
    aNewShape=aS1;
    //
    myImages.Bind(aNewShape, aLSDF);
    // origins
    aItS.Initialize(aLSDF);
    for (; aItS.More(); aItS.Next()) {
      const TopoDS_Shape& aFSD=aItS.Value();
      if (!myOrigins.IsBound(aFSD)) {
        myOrigins.Bind(aFSD, aNewShape);
      }
    }
  }
}
//=======================================================================
//function : DetectSolids
//purpose  :
//=======================================================================
  void GEOMAlgo_GlueAnalyser::DetectSolids()
{
  myErrorStatus=0;
  //
  Standard_Integer i, aNbF, aNbS, aNbC, aNbX;
  TopoDS_Compound aCmp;
  BRep_Builder aBB;
  TopTools_IndexedDataMapOfShapeListOfShape aMFS;
  TopTools_IndexedMapOfShape aMx, aMS;
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
  GEOMAlgo_CoupleOfShapes aCS;
  //
  GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLS;
  GEOMAlgo_PassKeyShape aPKSx;
  //
  aBB.MakeCompound(aCmp);
  //
  TopExp::MapShapesAndAncestors(myShape, TopAbs_FACE, TopAbs_SOLID, aMFS);
  //
  aItIm.Initialize(myImages);
  for (; aItIm.More(); aItIm.Next()) {
    const TopoDS_Shape& aIm=aItIm.Key();
    if (aIm.ShapeType()!=TopAbs_FACE) {
      continue;
    }
    //
    const TopTools_ListOfShape& aLF=aItIm.Value();
    aNbF=aLF.Extent();
    if (aNbF!=2) {
      continue;
    }
    //
    TopoDS_Shape aSx[2], aFx[2];
    //
    aFx[0]=aLF.First();
    aFx[1]=aLF.Last();
    for (i=0; i<2; ++i) {
      if (!aMFS.Contains(aFx[i])) {
        continue;// it must not be so
      }
      //
      const TopTools_ListOfShape& aLS=aMFS.FindFromKey(aFx[i]);
      aNbS=aLS.Extent();
      if (aNbS!=1) {
        continue;
      }
      aSx[i]=aLS.First();
    }
    //
    if (aSx[0].IsNull() || aSx[1].IsNull()) {
      continue;
    }
    //
    //aPKSx.Clear();//qft
    //qf
    //aPKSx.SetIds(aSx[0], aSx[1]);
    aPKSx.SetShapes(aSx[0], aSx[1]);
    //qt
    //
    if (!aMPKLS.Contains(aPKSx)) {
      TopTools_ListOfShape aLSx;
      //
      aLSx.Append(aSx[0]);
      aLSx.Append(aSx[1]);
      //
      aMPKLS.Add(aPKSx, aLSx);
    }
  }
  //
  mySolidsToGlue.Clear();
  mySolidsAlone.Clear();

  //
  aNbC=aMPKLS.Extent();
  if (!aNbC) {
    return;
  }
  //
  for (i=1; i<=aNbC; ++i) {
    const TopTools_ListOfShape& aLSx=aMPKLS(i);
    const TopoDS_Shape& aSx1=aLSx.First();
    const TopoDS_Shape& aSx2=aLSx.Last();
    aCS.SetShape1(aSx1);
    aCS.SetShape2(aSx2);
    mySolidsToGlue.Append(aCS);
    //
    if (!aMx.Contains(aSx1)) {
      aBB.Add(aCmp, aSx1);
      aMx.Add(aSx1);
    }
    if (!aMx.Contains(aSx2)) {
      aBB.Add(aCmp, aSx2);
      aMx.Add(aSx2);
    }
  }
  myResult=aCmp;
  //
  // check alone solids
  TopExp::MapShapes(myShape, TopAbs_SOLID, aMS);
  //
  aNbX=aMx.Extent();
  for (i=1; i<=aNbX; ++i) {
    const TopoDS_Shape& aSx=aMx(i);
    if (!aMS.Contains(aSx)) {
      mySolidsAlone.Append(aSx);
    }
  }
}
//=======================================================================
//function : DetectShapes
//purpose  : 
//=======================================================================
void GEOMAlgo_GlueDetector::DetectShapes(const TopAbs_ShapeEnum aType)
{
  Standard_Boolean bDegenerated;
  Standard_Integer i, aNbF, aNbSDF, iErr;
  TopTools_IndexedMapOfShape aMF;
  TopTools_ListIteratorOfListOfShape aItLS;
  GEOMAlgo_PassKeyShape aPKF;
  GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
  //
  myErrorStatus=0;
  //
  TopExp::MapShapes(myArgument, aType, aMF);
  //
  aNbF=aMF.Extent();
  for (i=1; i<=aNbF; ++i) {
    const TopoDS_Shape& aS=aMF(i);
    // 
    if (aType==TopAbs_FACE) {
      const TopoDS_Face& aF=*((TopoDS_Face*)&aS);
      FacePassKey(aF, aPKF);
    }
    else if (aType==TopAbs_EDGE) {
      const TopoDS_Edge& aE=*((TopoDS_Edge*)&aS);
      EdgePassKey(aE, aPKF);
    }
    //
    if (myErrorStatus) {
      return;
    }
    //
    if (aMPKLF.Contains(aPKF)) {
      TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
      aLSDF.Append(aS);
    }
    else {
      TopTools_ListOfShape aLSDF;
      //
      aLSDF.Append(aS);
      aMPKLF.Add(aPKF, aLSDF);
    }
  }
  // check geometric coincidence
  if (myCheckGeometry) {
    iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTolerance, myContext);
    if (iErr) {
      myErrorStatus=200;
      return;
    }
  }
  //
  // Images/Origins
  aNbF=aMPKLF.Extent();
  for (i=1; i<=aNbF; ++i) {
    const TopTools_ListOfShape& aLSDF=aMPKLF(i);
    aNbSDF=aLSDF.Extent();
    if (!aNbSDF) {
      myErrorStatus=4; // it must not be
    }
    //
    if (aNbSDF==1) {
      continue;
    }
    //
    const TopoDS_Shape& aS1=aLSDF.First();  
    //
    if (aType==TopAbs_EDGE) {
      const TopoDS_Edge& aE1=*((TopoDS_Edge*)&aS1);
      bDegenerated=BRep_Tool::Degenerated(aE1);
      if (bDegenerated) {
	continue;
      }
    }
    //
    myImages.Bind(aS1, aLSDF);
    // origins
    aItLS.Initialize(aLSDF);
    for (; aItLS.More(); aItLS.Next()) {
      const TopoDS_Shape& aFSD=aItLS.Value();
      if (!myOrigins.IsBound(aFSD)) {
        myOrigins.Bind(aFSD, aS1);
      }
    }
  }// for (i=1; i<=aNbF; ++i)
}