//=======================================================================
// function: FillSameDomainFaces
// purpose:
//=======================================================================
void GEOMAlgo_Builder::FillSameDomainFaces()
{
  Standard_Boolean bIsSDF, bHasImage1, bHasImage2, bForward;
  Standard_Integer i, j, aNbFF, nF1, nF2, aNbPBInOn, aNbC, aNbSE;
  Standard_Integer aNbF1, aNbF2, i2s, aNbSD;
  TopTools_MapOfShape aMFence;
  TopTools_ListOfShape aLX1, aLX2;
  TopTools_ListIteratorOfListOfShape aItF1, aItF2;
  NMTTools_ListOfCoupleOfShape aLCS;
  //
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences();
  const Handle(IntTools_Context)& aCtx= pPF->Context();
  //
  //
  //mySameDomainShapes.Clear();
  //
  // 1. For each FF find among images of faces
  //    all pairs of same domain faces (SDF) [=> aLCS]
  aNbFF=aFFs.Extent();
  for (i=1; i<=aNbFF; ++i) {
    BOPTools_SSInterference& aFF=aFFs(i);
    aFF.Indices(nF1, nF2);
    //
    const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1));
    const TopoDS_Face& aF2=TopoDS::Face(aDS.Shape(nF2));
    //
    // if there are no in/on 2D split parts the faces nF1, nF2
    // can not be SDF
    const BOPTools_ListOfPaveBlock& aLPBInOn=aFF.PaveBlocks();
    aNbPBInOn=aLPBInOn.Extent();
    //
    //===
    const TColStd_ListOfInteger& aLSE=aFF.SharedEdges();
    aNbSE=aLSE.Extent();
    if (!aNbPBInOn && !aNbSE) {
      continue;
    }
    //===
    //
    // if there is at least one section edge between faces nF1, nF2
    // they can not be SDF
    BOPTools_SequenceOfCurves& aSC=aFF.Curves();
    aNbC=aSC.Length();
    if (aNbC) {
      continue;
    }
    //
    // the faces are suspected to be SDF.
    // Try to find SDF among images of nF1, nF2
    aMFence.Clear();
    //
    //--------------------------------------------------------
    bHasImage1=mySplitFaces.HasImage(aF1);
    bHasImage2=mySplitFaces.HasImage(aF2);
    //
    aLX1.Clear();
    if (!bHasImage1) {
      aLX1.Append(aF1);
    }
    //
    aLX2.Clear();
    if (!bHasImage2) {
      aLX2.Append(aF2);
    }
    //
    const TopTools_ListOfShape& aLF1r=(bHasImage1)? mySplitFaces.Image(aF1) : aLX1;
    const TopTools_ListOfShape& aLF2r=(bHasImage2)? mySplitFaces.Image(aF2) : aLX2;
    //
    TopTools_DataMapOfIntegerShape aMIS;
    TColStd_ListIteratorOfListOfInteger aItLI;
    NMTDS_BoxBndTreeSelector aSelector;
    NMTDS_BoxBndTree aBBTree;
    NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
    //
    aNbF1=aLF1r.Extent();
    aNbF2=aLF2r.Extent();
    bForward=(aNbF1<aNbF2);
    //
    const TopTools_ListOfShape& aLF1=bForward ? aLF1r : aLF2r;
    const TopTools_ListOfShape& aLF2=bForward ? aLF2r : aLF1r;
    //
    // 1. aTreeFiller
    aItF2.Initialize(aLF2);
    for (i2s=1; aItF2.More(); aItF2.Next(), ++i2s) {
      Bnd_Box aBoxF2s;
      //
      const TopoDS_Face& aF2s=*((TopoDS_Face*)(&aItF2.Value()));
      //
      BRepBndLib::Add(aF2s, aBoxF2s);
      //
      aMIS.Bind(i2s, aF2s);
      //
      aTreeFiller.Add(i2s, aBoxF2s);
    }//for (i2s=1; aItF2.More(); aItF2.Next(), ++i2s) {
    //
    aTreeFiller.Fill();
    //
    // 2.
    aItF1.Initialize(aLF1);
    for (j=1; aItF1.More(); aItF1.Next(), ++j) {
      Bnd_Box aBoxF1x;
      //
      const TopoDS_Face& aF1x=*((TopoDS_Face*)(&aItF1.Value()));
      //
      BRepBndLib::Add(aF1x, aBoxF1x);
      //
      aSelector.Clear();
      aSelector.SetBox(aBoxF1x);
      aNbSD=aBBTree.Select(aSelector);
      if (!aNbSD) {
        continue;
      }
      //
      const TColStd_ListOfInteger& aLI=aSelector.Indices();
      aItLI.Initialize(aLI);
      for (; aItLI.More(); aItLI.Next()) {
        i2s=aItLI.Value();
        const TopoDS_Face& aF2y=*((TopoDS_Face*)(&aMIS.Find(i2s)));
        //
        bIsSDF=NMTTools_Tools::AreFacesSameDomain(aF1x, aF2y, aCtx);
        if (bIsSDF) {
          if (aMFence.Contains(aF1x) || aMFence.Contains(aF2y)) {
            continue;
          }
          aMFence.Add(aF1x);
          aMFence.Add(aF2y);
          //
          NMTTools_CoupleOfShape aCS;
          //
          aCS.SetShape1(aF1x);
          aCS.SetShape2(aF2y);
          aLCS.Append(aCS);
          //
          if (bForward) {
            if (aF1x==aF1) {
              if (!mySplitFaces.HasImage(aF1)) {
                mySplitFaces.Bind(aF1, aF1);
              }
            }
            if (aF2y==aF2) {
              if (!mySplitFaces.HasImage(aF2)) {
                mySplitFaces.Bind(aF2, aF2);
              }
            }
          }
          else {
            if (aF1x==aF2) {
              if (!mySplitFaces.HasImage(aF2)) {
                mySplitFaces.Bind(aF2, aF2);
              }
            }
            if (aF2y==aF1) {
              if (!mySplitFaces.HasImage(aF1)) {
                mySplitFaces.Bind(aF1, aF1);
              }
            }
          }
          //
          break;
        }//if (bIsSDF) {
      }//for (; aItLI.More(); aItLI.Next()) {
    }//for (; aItF1.More(); aItF1.Next()) {
  }//for (i=1; i<=aNbFF; ++i)
  //-------------------------------------------------------------
  aNbC=aLCS.Extent();
  if (!aNbC) {
    return;
  }
  //
  // 2. Find Chains
  NMTTools_IndexedDataMapOfShapeIndexedMapOfShape aMC;
  //
  NMTTools_Tools::FindChains(aLCS, aMC);
  //
  Standard_Boolean bIsImage;
  Standard_Integer aIx, aIxMin, aNbMSDF, k, aNbMFj;
  TopoDS_Shape aFOld, aFSDmin;
  TopTools_IndexedMapOfShape aMFj;
  TopTools_DataMapOfShapeInteger aDMSI;
  //
  aItF1.Initialize(myShapes);
  for (j=1; aItF1.More(); aItF1.Next(), ++j) {
    const TopoDS_Shape& aSj=aItF1.Value();
    aMFj.Clear();
    TopExp::MapShapes(aSj, TopAbs_FACE, aMFj);
    aNbMFj=aMFj.Extent();
    for (k=1; k<=aNbMFj; ++k) {
      const TopoDS_Shape& aFk=aMFj(k);
      if (!aDMSI.IsBound(aFk)) {
	aDMSI.Bind(aFk, j);
      }
    }
  }
  //
  // 3. Fill the map of SDF mySameDomainFaces
  aNbC=aMC.Extent();
  for (i=1; i<=aNbC; ++i) {
   // const TopoDS_Shape& aF=aMC.FindKey(i);
    const TopTools_IndexedMapOfShape& aMSDF=aMC(i);
    //
    aNbMSDF=aMSDF.Extent();
    for (j=1; j<=aNbMSDF; ++j) {
      const TopoDS_Shape& aFSD=aMSDF(j);
      bIsImage=mySplitFaces.IsImage(aFSD);
      aFOld=aFSD;
      if (bIsImage) {
	aFOld=mySplitFaces.ImageFrom(aFSD);
      }
      //
      aIx=aDMSI.Find(aFOld);
      if (j==1) {
	aIxMin=aIx;
	aFSDmin=aFSD;
	continue;
      }
      else {
	if (aIx<aIxMin) {
	  aIxMin=aIx;
	  aFSDmin=aFSD;
	}
      }
    }
    //
    for (j=1; j<=aNbMSDF; ++j) {
      const TopoDS_Shape& aFSD=aMSDF(j);
      mySameDomainShapes.Add(aFSD, aFSDmin);
    }
  }
  //
}
//=======================================================================
// function: FillIn2DParts
// purpose:
//=======================================================================
void GEOMAlgo_Builder::FillIn2DParts()
{
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences();
  NMTTools_CommonBlockPool& aCBP=pPF->ChangeCommonBlockPool();
  //
  Standard_Integer  j, nSpIn, nSpSc, aNbCurves;
  Standard_Integer aNbS, nF, aNbCBP, n1, n2, aNbFFs, aNbSpIn;
  TopTools_MapOfShape  aMFence;
  TopTools_ListOfShape aLSpIn;
  TopoDS_Face aF;
  NMTTools_ListIteratorOfListOfCommonBlock aItCB;
  BOPTools_ListIteratorOfListOfPaveBlock aItPB;
  //
  myInParts.Clear();
  //
  aNbFFs=aFFs.Extent();
  aNbCBP=aCBP.Extent();
  //
  aNbS=aDS.NumberOfShapesOfTheObject();
  for (nF=1; nF<=aNbS; ++nF) {
    if (aDS.GetShapeType(nF)!=TopAbs_FACE) {
      continue;
    }
    //
    aF=TopoDS::Face(aDS.Shape(nF));
    //
    aMFence.Clear();
    aLSpIn.Clear();
    //
    // 1. In Parts
    BOPTools_ListOfPaveBlock aLPBIn;
    //
    pPF->RealSplitsInFace(nF, aLPBIn);
    //
    aItPB.Initialize(aLPBIn);
    for (; aItPB.More(); aItPB.Next()) {
      const BOPTools_PaveBlock& aPB1=aItPB.Value();
      nSpIn=aPB1.Edge();
      const TopoDS_Shape& aSpIn=aDS.Shape(nSpIn);
      aLSpIn.Append(aSpIn);
    }
    //
    // 2. Section Parts
    for (j=1; j<=aNbFFs; ++j) {
      BOPTools_SSInterference& aFF=aFFs(j);
      aFF.Indices(n1, n2);
      if (!(n1==nF || n2==nF)) {
        continue;
      }
      BOPTools_SequenceOfCurves& aSC=aFF.Curves();
      aNbCurves=aSC.Length();
      if (!aNbCurves) {
        continue;
      }
      //
      const BOPTools_Curve& aBC=aSC(1);
      const BOPTools_ListOfPaveBlock& aLPB=aBC.NewPaveBlocks();
      aItPB.Initialize(aLPB);
      for (; aItPB.More(); aItPB.Next()) {
        const BOPTools_PaveBlock& aPBSc=aItPB.Value();
        nSpSc=aPBSc.Edge();
        const TopoDS_Shape& aSpSc=aDS.Shape(nSpSc);
        if (aMFence.Add(aSpSc)){
          aLSpIn.Append(aSpSc);
        }
      }
    }
    aNbSpIn=aLSpIn.Extent();
    if (aNbSpIn) {
      myInParts.Add(aF, aLSpIn);
    }
  }//for (nF=1; nF<=aNbS; ++nF) {
}
//=======================================================================
// function: BuildSplitFaces
// purpose:
//=======================================================================
void GEOMAlgo_Builder::BuildSplitFaces()
{
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences();
  const Handle(IntTools_Context)& aCtx= pPF->Context();
  //
  Standard_Boolean bToReverse, bIsClosed, bIsDegenerated;
  Standard_Integer i, aNb, aNbF, nF;
  TopTools_MapOfShape aMFence;
  TColStd_IndexedMapOfInteger aMFP;
  TopExp_Explorer anExp;
  TopoDS_Face aFF;
  TopoDS_Edge aSp, aEE;
  TopTools_ListIteratorOfListOfShape aIt;
  TopAbs_Orientation anOriF, anOriE;
  //
  mySplitFaces.Clear();
  //
  // 1. Select Faces to process (MFP)
  aNb=aDS.NumberOfShapesOfTheObject();
  for (i=1; i<=aNb; ++i) {
    const TopoDS_Shape& aF=aDS.Shape(i);
    if (aF.ShapeType()!=TopAbs_FACE) {
      continue;
    }
    if (!aMFence.Add(aF)) {
      continue;
    }
    //
    if (myInParts.Contains(aF)) {
      aMFP.Add(i);
      continue;
    }
    //
    anExp.Init(aF, TopAbs_EDGE);
    for (; anExp.More(); anExp.Next()) {
      const TopoDS_Shape& aE=anExp.Current();
      if (myImages.HasImage(aE)) {
        aMFP.Add(i);
        break;
      }
    }
    //
    //===
    {
      Standard_Integer aNbFFs, aNbSE, j, n1, n2;
      //
      aNbFFs=aFFs.Extent();
      for (j=1; j<=aNbFFs; ++j) {
        BOPTools_SSInterference& aFFj=aFFs(j);
        aFFj.Indices(n1, n2);
        if (!(n1==i || n2==i)) {
          continue;
        }
        //
        const TColStd_ListOfInteger& aLSE=aFFj.SharedEdges();
        aNbSE=aLSE.Extent();
        if (aNbSE) {
          aMFP.Add(i);
          break;
        }
      }
    }
    //===
    //
  }// for (i=1; i<=aNb; ++i)
  //
  // 2. ProcessFaces
  aNbF=aMFP.Extent();
  for (i=1; i<=aNbF; ++i) {
    nF=aMFP(i);
    const TopoDS_Face& aF=TopoDS::Face(aDS.Shape(nF));
    anOriF=aF.Orientation();
    aFF=aF;
    aFF.Orientation(TopAbs_FORWARD);
    //
    aMFence.Clear();
    //
    // 2.1. Fill WES
    GEOMAlgo_WireEdgeSet aWES;
    aWES.SetFace(aFF);
    //
    //  2.1.1. Add Split parts
    anExp.Init(aFF, TopAbs_EDGE);
    for (; anExp.More(); anExp.Next()) {
      const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current());
      anOriE=aE.Orientation();
      //
      if (!myImages.HasImage(aE)) {
        if (anOriE==TopAbs_INTERNAL) {
          aEE=aE;
          aEE.Orientation(TopAbs_FORWARD);
          aWES.AddStartElement(aEE);
          aEE.Orientation(TopAbs_REVERSED);
          aWES.AddStartElement(aEE);
        }
        else {
          aWES.AddStartElement(aE);
        }
        continue;
      }
      //
      bIsDegenerated=BRep_Tool::Degenerated(aE);
      //modified by NIZNHY-PKV Wed Mar 07 07:46:09 2012f
      bIsClosed=IsClosed(aE, aF);
      //bIsClosed=BRep_Tool::IsClosed(aE, aF);
      //modified by NIZNHY-PKV Wed Mar 07 07:46:13 2012t
      //
      const TopTools_ListOfShape& aLIE=myImages.Image(aE);
      aIt.Initialize(aLIE);
      for (; aIt.More(); aIt.Next()) {
        aSp=TopoDS::Edge(aIt.Value());
        //
        if (bIsDegenerated) {
          aSp.Orientation(anOriE);
          aWES.AddStartElement(aSp);
          continue;
        }
        //
        if (anOriE==TopAbs_INTERNAL) {
          aSp.Orientation(TopAbs_FORWARD);
          aWES.AddStartElement(aSp);
          aSp.Orientation(TopAbs_REVERSED);
          aWES.AddStartElement(aSp);
          continue;
        }
        //
        if (bIsClosed){
          if (aMFence.Add(aSp)) {
            //
            if (!BRep_Tool::IsClosed(aSp, aF)){
              BOPTools_Tools3D::DoSplitSEAMOnFace(aSp, aF);
            }
            //
            aSp.Orientation(TopAbs_FORWARD);
            aWES.AddStartElement(aSp);
            aSp.Orientation(TopAbs_REVERSED);
            aWES.AddStartElement(aSp);
          }
          continue;
        }// if (aMFence.Add(aSp))
        //
        aSp.Orientation(anOriE);
        bToReverse=BOPTools_Tools3D::IsSplitToReverse1(aSp, aE, aCtx);
        if (bToReverse) {
          aSp.Reverse();
        }
        aWES.AddStartElement(aSp);
      }// for (; aIt.More(); aIt.Next()) {
    }// for (; anExp.More(); anExp.Next()) {
    //
    // 2.1.2. Add In2D Parts
    if (myInParts.Contains(aF)) {
      const TopTools_ListOfShape& aLE=myInParts.FindFromKey(aF);
      aIt.Initialize(aLE);
      for (; aIt.More(); aIt.Next()) {
        aSp=TopoDS::Edge(aIt.Value());
        //
        aSp.Orientation(TopAbs_FORWARD);
        aWES.AddStartElement(aSp);
        //
        aSp.Orientation(TopAbs_REVERSED);
        aWES.AddStartElement(aSp);
      }
    }
    //
    // 2.2. Build images Faces
    TopTools_ListOfShape aLFR;
    GEOMAlgo_ShapeSet aS1, aS2;
    //
    const TopTools_ListOfShape& aSE=aWES.StartElements();
    aS1.Add(aSE);
    aS2.Add(aFF, TopAbs_EDGE);
    if (aS1.IsEqual(aS2)) {
      aLFR.Append(aF);
    }
    else {
      GEOMAlgo_BuilderFace aBF;
      //
      aBF.SetFace(aFF);
      aBF.SetContext(aCtx);
      aBF.SetShapes(aSE);
      // <-DEB
      aBF.Perform();
      //
      const TopTools_ListOfShape& aLF=aBF.Areas();
      aIt.Initialize(aLF);
      for (; aIt.More(); aIt.Next()) {
        TopoDS_Shape& aFR=aIt.Value();
        if (anOriF==TopAbs_REVERSED) {
          aFR.Orientation(TopAbs_REVERSED);
        }
        aLFR.Append(aFR);
      }
    }
    //
    // 2.3. Collect draft images Faces
    mySplitFaces.Bind(aF, aLFR);
  }//for (i=1; i<=aNbF; ++i)
}
bool NETGENPlugin_NETGEN_3D::Evaluate(SMESH_Mesh& aMesh,
                                      const TopoDS_Shape& aShape,
                                      MapShapeNbElems& aResMap)
{
    int nbtri = 0, nbqua = 0;
    double fullArea = 0.0;
    for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
        TopoDS_Face F = TopoDS::Face( exp.Current() );
        SMESH_subMesh *sm = aMesh.GetSubMesh(F);
        MapShapeNbElemsItr anIt = aResMap.find(sm);
        if( anIt==aResMap.end() ) {
            SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
            smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
            return false;
        }
        std::vector<int> aVec = (*anIt).second;
        nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
        nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
        GProp_GProps G;
        BRepGProp::SurfaceProperties(F,G);
        double anArea = G.Mass();
        fullArea += anArea;
    }

    // collect info from edges
    int nb0d_e = 0, nb1d_e = 0;
    bool IsQuadratic = false;
    bool IsFirst = true;
    TopTools_MapOfShape tmpMap;
    for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) {
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        if( tmpMap.Contains(E) )
            continue;
        tmpMap.Add(E);
        SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
        MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
        if( anIt==aResMap.end() ) {
            SMESH_ComputeErrorPtr& smError = aSubMesh->GetComputeError();
            smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
                                                  "Submesh can not be evaluated",this));
            return false;
        }
        std::vector<int> aVec = (*anIt).second;
        nb0d_e += aVec[SMDSEntity_Node];
        nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
        if(IsFirst) {
            IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
            IsFirst = false;
        }
    }
    tmpMap.Clear();

    double ELen_face = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
    double ELen_vol = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );
    double ELen = Min(ELen_vol,ELen_face*2);

    GProp_GProps G;
    BRepGProp::VolumeProperties(aShape,G);
    double aVolume = G.Mass();
    double tetrVol = 0.1179*ELen*ELen*ELen;
    double CoeffQuality = 0.9;
    int nbVols = (int)aVolume/tetrVol/CoeffQuality;
    int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
    int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
    std::vector<int> aVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
    if( IsQuadratic ) {
        aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
        aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
        aVec[SMDSEntity_Quad_Pyramid] = nbqua;
    }
    else {
        aVec[SMDSEntity_Node] = nb1d_in/6 + 1;
        aVec[SMDSEntity_Tetra] = nbVols - nbqua*2;
        aVec[SMDSEntity_Pyramid] = nbqua;
    }
    SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
    aResMap.insert(std::make_pair(sm,aVec));

    return true;
}
Beispiel #5
0
//=======================================================================
//function : GetEdgeNearPoint
//purpose  :
//=======================================================================
TopoDS_Shape GEOMUtils::GetEdgeNearPoint (const TopoDS_Shape& theShape,
                                          const TopoDS_Vertex& thePoint)
{
  TopoDS_Shape aResult;

  // 1. Explode the shape on edges
  TopTools_MapOfShape mapShape;
  Standard_Integer nbEdges = 0;
  TopExp_Explorer exp (theShape, TopAbs_EDGE);
  for (; exp.More(); exp.Next()) {
    if (mapShape.Add(exp.Current())) {
      nbEdges++;
    }
  }

  if (nbEdges == 0)
    Standard_NullObject::Raise("Given shape contains no edges");

  mapShape.Clear();
  Standard_Integer ind = 1;
  TopTools_Array1OfShape anEdges (1, nbEdges);
  TColStd_Array1OfReal aDistances (1, nbEdges);
  for (exp.Init(theShape, TopAbs_EDGE); exp.More(); exp.Next()) {
    if (mapShape.Add(exp.Current())) {
      TopoDS_Shape anEdge = exp.Current();
      anEdges(ind) = anEdge;

      // 2. Classify the point relatively each edge
      BRepExtrema_DistShapeShape aDistTool (thePoint, anEdges(ind));
      if (!aDistTool.IsDone())
        Standard_ConstructionError::Raise("Cannot find a distance from the given point to one of edges");

      aDistances(ind) = aDistTool.Value();
      ind++;
    }
  }

  // 3. Define edge, having minimum distance to the point
  Standard_Real nearest = RealLast(), nbFound = 0;
  Standard_Real prec = Precision::Confusion();
  for (ind = 1; ind <= nbEdges; ind++) {
    if (Abs(aDistances(ind) - nearest) < prec) {
      nbFound++;
    }
    else if (aDistances(ind) < nearest) {
      nearest = aDistances(ind);
      aResult = anEdges(ind);
      nbFound = 1;
    }
    else {
    }
  }
  if (nbFound > 1) {
    Standard_ConstructionError::Raise("Multiple edges near the given point are found");
  }
  else if (nbFound == 0) {
    Standard_ConstructionError::Raise("There are no edges near the given point");
  }
  else {
  }

  return aResult;
}
//=======================================================================
//function : FillIn3DParts
//purpose  :
//=======================================================================
  void GEOMAlgo_Builder::FillIn3DParts()
{
  myErrorStatus=0;
  //
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  const Handle(IntTools_Context)& aCtx= pPF->Context();
  //
  Standard_Boolean bIsIN, bHasImage;
  Standard_Integer aNbS, aNbSolids, i, j, aNbFaces, aNbFP, aNbFPx, aNbFIN, aNbLIF;
  TopAbs_ShapeEnum aType;
  TopAbs_State aState;
  TopTools_IndexedMapOfShape aMSolids, aMS, aMFaces, aMFIN;
  TopTools_MapOfShape aMFDone;
  TopTools_IndexedDataMapOfShapeListOfShape aMEF;
  TopTools_ListIteratorOfListOfShape aItS;
  TopoDS_Iterator aIt, aItF;
  BRep_Builder aBB;
  TopoDS_Solid aSolidSp;
  TopoDS_Face aFP;
  //
  myDraftSolids.Clear();
  //
  aNbS=aDS.NumberOfShapesOfTheObject();
  for (i=1; i<=aNbS; ++i) {
    const TopoDS_Shape& aS=aDS.Shape(i);
    //
    aType=aS.ShapeType();
    if (aType==TopAbs_SOLID) {
      // all solids from DS
      aMSolids.Add(aS);
    }
    else if (aType==TopAbs_FACE) {
      // all faces (originals from DS or theirs images)
      if (myImages.HasImage(aS)) {
        const TopTools_ListOfShape& aLS=myImages.Image(aS);
        aItS.Initialize(aLS);
        for (; aItS.More(); aItS.Next()) {
          const TopoDS_Shape& aFx=aItS.Value();
          //
          if (mySameDomainShapes.Contains(aFx)) {
            const TopoDS_Shape& aFSDx=mySameDomainShapes.FindFromKey(aFx);
            aMFaces.Add(aFSDx);
          }
          else {
            aMFaces.Add(aFx);
          }
        }
      }
      else {
        if (mySameDomainShapes.Contains(aS)) {
          const TopoDS_Shape& aFSDx=mySameDomainShapes.FindFromKey(aS);
          aMFaces.Add(aFSDx);
        }
        else {
          aMFaces.Add(aS);
        }
      }
    }
  }
  //
  aNbFaces=aMFaces.Extent();
  aNbSolids=aMSolids.Extent();
  //
  for (i=1; i<=aNbSolids; ++i) {
    const TopoDS_Solid& aSolid=TopoDS::Solid(aMSolids(i));
    aMFDone.Clear();
    aMFIN.Clear();
    aMEF.Clear();
    //
    aBB.MakeSolid(aSolidSp);
    //
    TopTools_ListOfShape aLIF;
    //
    BuildDraftSolid(aSolid, aSolidSp, aLIF);
    aNbLIF=aLIF.Extent();
    //
    // 1 all faces/edges from aSolid [ aMS ]
    bHasImage=Standard_False;
    aMS.Clear();
    aIt.Initialize(aSolid);
    for (; aIt.More(); aIt.Next()) {
      const TopoDS_Shape& aShell=aIt.Value();
      //
      if (myImages.HasImage(aShell)) {
        bHasImage=Standard_True;
        //
        const TopTools_ListOfShape& aLS=myImages.Image(aShell);
        aItS.Initialize(aLS);
        for (; aItS.More(); aItS.Next()) {
          const TopoDS_Shape& aSx=aItS.Value();
          aMS.Add(aSx);
          TopExp::MapShapes(aSx, TopAbs_FACE, aMS);
          TopExp::MapShapes(aSx, TopAbs_EDGE, aMS);
          TopExp::MapShapesAndAncestors(aSx, TopAbs_EDGE, TopAbs_FACE, aMEF);
        }
      }
      else {
        //aMS.Add(aShell);
        TopExp::MapShapes(aShell, TopAbs_FACE, aMS);
        //modified by NIZNHY-PKV Fri Dec 03 11:18:45 2010f
        TopExp::MapShapes(aShell, TopAbs_EDGE, aMS);
        //modified by NIZNHY-PKV Fri Dec 03 11:18:51 2010t
        TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEF);
      }
    }
    //
    // 2 all faces that are not from aSolid [ aLFP1 ]
    Standard_Integer aNbEFP;
    TopTools_IndexedDataMapOfShapeListOfShape aMEFP;
    TopTools_ListIteratorOfListOfShape aItFP, aItEx;
    TopTools_MapOfShape aMFence;
    TopTools_ListOfShape aLFP1, aLFP2, aLFP, aLCBF, aLFIN, aLEx;//*pLFP,
    //
    // for all non-solid faces build EF map [ aMEFP ]
    for (j=1; j<=aNbFaces; ++j) {
      const TopoDS_Shape& aFace=aMFaces(j);
      if (!aMS.Contains(aFace)) {
        TopExp::MapShapesAndAncestors(aFace, TopAbs_EDGE, TopAbs_FACE, aMEFP);
      }
    }
    //
    // among all faces from aMEFP select these that have same edges
    // with the solid (i.e aMEF). These faces will be treated first
    // to prevent the usage of 3D classifier.
    // The full list of faces to process is aLFP1.
    aNbEFP=aMEFP.Extent();
    for (j=1; j<=aNbEFP; ++j) {
      const TopoDS_Shape& aE=aMEFP.FindKey(j);
      //
      if (aMEF.Contains(aE)) { // !!
        const TopTools_ListOfShape& aLF=aMEFP(j);
        aItFP.Initialize(aLF);
        for (; aItFP.More(); aItFP.Next()) {
          const TopoDS_Shape& aF=aItFP.Value();
          if (aMFence.Add(aF)) {
            aLFP1.Append(aF);
          }
        }
      }
      else {
        aLEx.Append(aE);
      }
    }
    //
    aItEx.Initialize(aLEx);
    for (; aItEx.More(); aItEx.Next()) {
      const TopoDS_Shape& aE=aItEx.Value();
      const TopTools_ListOfShape& aLF=aMEFP.FindFromKey(aE);
      aItFP.Initialize(aLF);
      for (; aItFP.More(); aItFP.Next()) {
        const TopoDS_Shape& aF=aItFP.Value();
        if (aMFence.Add(aF)) {
          aLFP2.Append(aF);
        }
      }
    }
    aLFP1.Append(aLFP2);
    //==========
    //
    // 3 Process faces aLFP1
    aNbFP=aLFP1.Extent();
    aItFP.Initialize(aLFP1);
    for (; aItFP.More(); aItFP.Next()) {
      const TopoDS_Shape& aSP=aItFP.Value();
      if (!aMFDone.Add(aSP)) {
        continue;
      }

      //
      // first face to process
      aFP=TopoDS::Face(aSP);
      bIsIN= GEOMAlgo_Tools3D::IsInternalFace(aFP, aSolidSp, aMEF, 1.e-14, aCtx);
      aState=(bIsIN) ? TopAbs_IN : TopAbs_OUT;
      //
      // collect faces to process [ aFP is the first ]
      aLFP.Clear();
      aLFP.Append(aFP);
      aItS.Initialize(aLFP1);
      for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aSk=aItS.Value();
        if (!aMFDone.Contains(aSk)) {
          aLFP.Append(aSk);
        }
      }
      //
      // Connexity Block that spreads from aFP the Bound
      // or till the end of the block itself
      aLCBF.Clear();
      GEOMAlgo_Tools3D::MakeConnexityBlock(aLFP, aMS, aLCBF);
      //
      // fill states for the Connexity Block
      aItS.Initialize(aLCBF);
      for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aSx=aItS.Value();
        aMFDone.Add(aSx);
        if (aState==TopAbs_IN) {
          aMFIN.Add(aSx);
        }
      }
      //
      aNbFPx=aMFDone.Extent();
      if (aNbFPx==aNbFP) {
        break;
      }
    }//for (; aItFP.More(); aItFP.Next())
    //
    // faces Inside aSolid
    aLFIN.Clear();
    aNbFIN=aMFIN.Extent();
    if (aNbFIN || aNbLIF) {
      for (j=1; j<=aNbFIN; ++j) {
        const TopoDS_Shape& aFIN=aMFIN(j);
        aLFIN.Append(aFIN);
      }
      //
      aItS.Initialize(aLIF);
      for (; aItS.More(); aItS.Next()) {
        const TopoDS_Shape& aFIN=aItS.Value();
        aLFIN.Append(aFIN);
      }
      //
      myInParts.Add(aSolid, aLFIN);
    }
    if (aNbFIN || bHasImage) {
      myDraftSolids.Add(aSolid, aSolidSp);
    }
  }//for (i=1; i<=aNbSolids; ++i) { // next solid
}
bool StdMeshers_RadialPrism_3D::Evaluate(SMESH_Mesh& aMesh,
                                         const TopoDS_Shape& aShape,
                                         MapShapeNbElems& aResMap)
{
  // get 2 shells
  TopoDS_Solid solid = TopoDS::Solid( aShape );
  TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
  TopoDS_Shape innerShell;
  int nbShells = 0;
  for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
    if ( !outerShell.IsSame( It.Value() ))
      innerShell = It.Value();
  if ( nbShells != 2 ) {
    std::vector<int> aResVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
    SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
    aResMap.insert(std::make_pair(sm,aResVec));
    SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
    smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
    return false;
  }

  // Associate sub-shapes of the shells
  ProjectionUtils::TShapeShapeMap shape2ShapeMap;
  if ( !ProjectionUtils::FindSubShapeAssociation( outerShell, &aMesh,
                                                  innerShell, &aMesh,
                                                  shape2ShapeMap) ) {
    std::vector<int> aResVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
    SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
    aResMap.insert(std::make_pair(sm,aResVec));
    SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
    smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
    return false;
  }

  // get info for outer shell
  int nb0d_Out=0, nb2d_3_Out=0, nb2d_4_Out=0;
  //TopTools_SequenceOfShape FacesOut;
  for (TopExp_Explorer exp(outerShell, TopAbs_FACE); exp.More(); exp.Next()) {
    //FacesOut.Append(exp.Current());
    SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
    MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
    std::vector<int> aVec = (*anIt).second;
    nb0d_Out += aVec[SMDSEntity_Node];
    nb2d_3_Out += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
    nb2d_4_Out += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
  }
  int nb1d_Out = 0;
  TopTools_MapOfShape tmpMap;
  for (TopExp_Explorer exp(outerShell, TopAbs_EDGE); exp.More(); exp.Next()) {
    if( tmpMap.Contains( exp.Current() ) )
      continue;
    tmpMap.Add( exp.Current() );
    SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
    MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
    std::vector<int> aVec = (*anIt).second;
    nb0d_Out += aVec[SMDSEntity_Node];
    nb1d_Out += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
  }
  tmpMap.Clear();
  for (TopExp_Explorer exp(outerShell, TopAbs_VERTEX); exp.More(); exp.Next()) {
    if( tmpMap.Contains( exp.Current() ) )
      continue;
    tmpMap.Add( exp.Current() );
    nb0d_Out++;
  }

  // get info for inner shell
  int nb0d_In=0, nb2d_3_In=0, nb2d_4_In=0;
  //TopTools_SequenceOfShape FacesIn;
  for (TopExp_Explorer exp(innerShell, TopAbs_FACE); exp.More(); exp.Next()) {
    //FacesIn.Append(exp.Current());
    SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
    MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
    std::vector<int> aVec = (*anIt).second;
    nb0d_In += aVec[SMDSEntity_Node];
    nb2d_3_In += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
    nb2d_4_In += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
  }
  int nb1d_In = 0;
  tmpMap.Clear();
  bool IsQuadratic = false;
  bool IsFirst = true;
  for (TopExp_Explorer exp(innerShell, TopAbs_EDGE); exp.More(); exp.Next()) {
    if( tmpMap.Contains( exp.Current() ) )
      continue;
    tmpMap.Add( exp.Current() );
    SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
    MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
    std::vector<int> aVec = (*anIt).second;
    nb0d_In += aVec[SMDSEntity_Node];
    nb1d_In += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
    if(IsFirst) {
      IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
      IsFirst = false;
    }
  }
  tmpMap.Clear();
  for (TopExp_Explorer exp(innerShell, TopAbs_VERTEX); exp.More(); exp.Next()) {
    if( tmpMap.Contains( exp.Current() ) )
      continue;
    tmpMap.Add( exp.Current() );
    nb0d_In++;
  }

  bool IsOK = (nb0d_Out==nb0d_In) && (nb1d_Out==nb1d_In) && 
              (nb2d_3_Out==nb2d_3_In) && (nb2d_4_Out==nb2d_4_In);
  if(!IsOK) {
    std::vector<int> aResVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
    SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
    aResMap.insert(std::make_pair(sm,aResVec));
    SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
    smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
    return false;
  }

  int nbLayers = 0;
  if( myNbLayerHypo ) {
    nbLayers = myNbLayerHypo->GetNumberOfLayers();
  }
  if ( myDistributionHypo ) {
    if ( !myDistributionHypo->GetLayerDistribution() ) {
      std::vector<int> aResVec(SMDSEntity_Last);
      for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
      SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
      aResMap.insert(std::make_pair(sm,aResVec));
      SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
      smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
      return false;
    }
    TopExp_Explorer exp(outerShell, TopAbs_VERTEX);
    TopoDS_Vertex Vout = TopoDS::Vertex(exp.Current());
    TopoDS_Vertex Vin = TopoDS::Vertex( shape2ShapeMap(Vout) );
    if ( myLayerPositions.empty() ) {
      gp_Pnt pIn = BRep_Tool::Pnt(Vin);
      gp_Pnt pOut = BRep_Tool::Pnt(Vout);
      computeLayerPositions( pIn, pOut );
    }
    nbLayers = myLayerPositions.size() + 1;
  }

  std::vector<int> aResVec(SMDSEntity_Last);
  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
  if(IsQuadratic) {
    aResVec[SMDSEntity_Quad_Penta] = nb2d_3_Out * nbLayers;
    aResVec[SMDSEntity_Quad_Hexa] = nb2d_4_Out * nbLayers;
    int nb1d = ( nb2d_3_Out*3 + nb2d_4_Out*4 ) / 2;
    aResVec[SMDSEntity_Node] = nb0d_Out * ( 2*nbLayers - 1 ) - nb1d * nbLayers;
  }
  else {
    aResVec[SMDSEntity_Node] = nb0d_Out * ( nbLayers - 1 );
    aResVec[SMDSEntity_Penta] = nb2d_3_Out * nbLayers;
    aResVec[SMDSEntity_Hexa] = nb2d_4_Out * nbLayers;
  }
  SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
  aResMap.insert(std::make_pair(sm,aResVec));

  return true;
}
bool NETGENPlugin_NETGEN_2D_ONLY::Evaluate(SMESH_Mesh& aMesh,
        const TopoDS_Shape& aShape,
        MapShapeNbElems& aResMap)
{
    TopoDS_Face F = TopoDS::Face(aShape);
    if(F.IsNull())
        return false;

    // collect info from edges
    int nb0d = 0, nb1d = 0;
    bool IsQuadratic = false;
    bool IsFirst = true;
    double fullLen = 0.0;
    TopTools_MapOfShape tmpMap;
    for (TopExp_Explorer exp(F, TopAbs_EDGE); exp.More(); exp.Next()) {
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        if( tmpMap.Contains(E) )
            continue;
        tmpMap.Add(E);
        SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
        MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
        if( anIt==aResMap.end() ) {
            SMESH_subMesh *sm = aMesh.GetSubMesh(F);
            SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
            smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
            return false;
        }
        std::vector<int> aVec = (*anIt).second;
        nb0d += aVec[SMDSEntity_Node];
        nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
        double aLen = SMESH_Algo::EdgeLength(E);
        fullLen += aLen;
        if(IsFirst) {
            IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
            IsFirst = false;
        }
    }
    tmpMap.Clear();

    // compute edge length
    double ELen = 0;
    if (_hypLengthFromEdges || (!_hypLengthFromEdges && !_hypMaxElementArea)) {
        if ( nb1d > 0 )
            ELen = fullLen / nb1d;
    }
    if ( _hypMaxElementArea ) {
        double maxArea = _hypMaxElementArea->GetMaxArea();
        ELen = sqrt(2. * maxArea/sqrt(3.0));
    }
    GProp_GProps G;
    BRepGProp::SurfaceProperties(F,G);
    double anArea = G.Mass();

    const int hugeNb = numeric_limits<int>::max()/10;
    if ( anArea / hugeNb > ELen*ELen )
    {
        SMESH_subMesh *sm = aMesh.GetSubMesh(F);
        SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
        smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated.\nToo small element length",this));
        return false;
    }
    int nbFaces = (int) ( anArea / ( ELen*ELen*sqrt(3.) / 4 ) );
    int nbNodes = (int) ( ( nbFaces*3 - (nb1d-1)*2 ) / 6 + 1 );
    std::vector<int> aVec(SMDSEntity_Last);
    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
    if( IsQuadratic ) {
        aVec[SMDSEntity_Node] = nbNodes;
        aVec[SMDSEntity_Quad_Triangle] = nbFaces;
    }
    else {
        aVec[SMDSEntity_Node] = nbNodes;
        aVec[SMDSEntity_Triangle] = nbFaces;
    }
    SMESH_subMesh *sm = aMesh.GetSubMesh(F);
    aResMap.insert(std::make_pair(sm,aVec));

    return true;
}