//=======================================================================
//function : addEdgeRelation
//purpose  : local function to remember relation between initial and modified edge
//=======================================================================
static void addEdgeRelation(TopTools_DataMapOfShapeShape& theMap,
                            const TopoDS_Edge& theInitE,
                            const TopoDS_Edge& theResE)
{
  if ( theMap.IsBound( theInitE ) )
    theMap.ChangeFind( theInitE ) = theResE;
  else
    theMap.Bind( theInitE, theResE );
}
//=======================================================================
// function: FuseVertices
// purpose:
//=======================================================================
void NMTTools_PaveFiller::FuseVertices
  (const TopoDS_Shape& aCompound,
   TopTools_DataMapOfShapeShape& aDMVV)const
{
  Standard_Integer i, aNbVV, n1, n2, nX;
  NMTTools_PaveFiller tPF;
  //
  tPF.SetCompositeShape(aCompound);
  //
  tPF.Init();
  //
  tPF.PerformVV();
  //tPF.PerformNewVertices(); //qq
  //
  NMTDS_ShapesDataStructure& tDS=*(tPF.DS());
  NMTDS_InterfPool& tInterfPool=*(tPF.IP());
  BOPTools_CArray1OfVVInterference& aVVt=tInterfPool.VVInterferences();
  //
  aNbVV=aVVt.Extent();
  for (i=1; i<=aNbVV; ++i) {
    const BOPTools_VVInterference& aVV=aVVt(i);
    aVV.Indices(n1, n2);
    nX=aVV.NewShape();
    if (nX) {
      const TopoDS_Shape& aV1=tDS.Shape(n1);
      const TopoDS_Shape& aV2=tDS.Shape(n2);
      const TopoDS_Shape& aVx=tDS.Shape(nX);
      aDMVV.Bind(aV1, aVx);
      aDMVV.Bind(aV2, aVx);
    }
  }
}
//=======================================================================
// 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
}
Ejemplo n.º 4
0
bool FaceUniter::process()
{
    if (workShell.IsNull())
        return false;
    modifiedShapes.clear();
    deletedShapes.clear();
    typeObjects.push_back(&getPlaneObject());
    typeObjects.push_back(&getCylinderObject());
    //add more face types.

    ModelRefine::FaceTypeSplitter splitter;
    splitter.addShell(workShell);
    std::vector<FaceTypedBase *>::iterator typeIt;
    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
        splitter.registerType((*typeIt)->getType());
    splitter.split();

    ModelRefine::FaceVectorType facesToRemove;
    ModelRefine::FaceVectorType facesToSew;

    ModelRefine::FaceAdjacencySplitter adjacencySplitter(workShell);

    for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt)
    {
        ModelRefine::FaceVectorType typedFaces = splitter.getTypedFaceVector((*typeIt)->getType());
        ModelRefine::FaceEqualitySplitter equalitySplitter;
        equalitySplitter.split(typedFaces, *typeIt);
        for (std::size_t indexEquality(0); indexEquality < equalitySplitter.getGroupCount(); ++indexEquality)
        {
            adjacencySplitter.split(equalitySplitter.getGroup(indexEquality));
//            std::cout << "      adjacency group count: " << adjacencySplitter.getGroupCount() << std::endl;
            for (std::size_t adjacentIndex(0); adjacentIndex < adjacencySplitter.getGroupCount(); ++adjacentIndex)
            {
//                    std::cout << "         face count is: " << adjacencySplitter.getGroup(adjacentIndex).size() << std::endl;
                TopoDS_Face newFace = (*typeIt)->buildFace(adjacencySplitter.getGroup(adjacentIndex));
                if (!newFace.IsNull())
                {
                    facesToSew.push_back(newFace);
                    if (facesToRemove.capacity() <= facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size())
                        facesToRemove.reserve(facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size());
                    FaceVectorType temp = adjacencySplitter.getGroup(adjacentIndex);
                    facesToRemove.insert(facesToRemove.end(), temp.begin(), temp.end());
                    // the first shape will be marked as modified, i.e. replaced by newFace, all others are marked as deleted
                    if (!temp.empty())
                    {
                        modifiedShapes.push_back(std::make_pair(temp.front(), newFace));
                        deletedShapes.insert(deletedShapes.end(), temp.begin()+1, temp.end());
                    }
                }
            }
        }
    }
    if (facesToSew.size() > 0)
    {
        modifiedSignal = true;
        workShell = ModelRefine::removeFaces(workShell, facesToRemove);
        TopExp_Explorer xp;
        bool emptyShell = true;
        for (xp.Init(workShell, TopAbs_FACE); xp.More(); xp.Next())
        {
            emptyShell = false;
            break;
        }

        if (!emptyShell || facesToSew.size() > 1)
        {
            BRepBuilderAPI_Sewing sew;
            sew.Add(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                sew.Add(*sewIt);
            sew.Perform();
            workShell = TopoDS::Shell(sew.SewedShape());
            // update the list of modifications
            for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
            {
                if (sew.IsModified(it->second))
                {
                    it->second = sew.Modified(it->second);
                    break;
                }
            }
        }
        else
        {
            // workShell has no more faces and we add exactly one face
            BRep_Builder builder;
            builder.MakeShell(workShell);
            FaceVectorType::iterator sewIt;
            for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
                builder.Add(workShell, *sewIt);
        }

        BRepLib_FuseEdges edgeFuse(workShell, Standard_True);
        TopTools_DataMapOfShapeShape affectedFaces;
        edgeFuse.Faces(affectedFaces);
        TopTools_DataMapIteratorOfDataMapOfShapeShape mapIt;
        for (mapIt.Initialize(affectedFaces); mapIt.More(); mapIt.Next())
        {
            ShapeFix_Face faceFixer(TopoDS::Face(mapIt.Value()));
            faceFixer.Perform();
        }
        workShell = TopoDS::Shell(edgeFuse.Shape());
        // update the list of modifications
        TopTools_DataMapOfShapeShape faceMap;
        edgeFuse.Faces(faceMap);
        for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it)
        {
            if (faceMap.IsBound(it->second))
            {
                const TopoDS_Shape& value = faceMap.Find(it->second);
                if (!value.IsSame(it->second))
                    it->second = value;
            }
        }
    }
    return true;
}
//=======================================================================
//function : Execute
//purpose  :
//=======================================================================
Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IFillet1d aCI (aFunction);

  Handle(GEOM_Function) aRefShape = aCI.GetShape();
  TopoDS_Shape aShape = aRefShape->GetValue();
  if (aShape.IsNull())
    return 0;
  if (aShape.ShapeType() != TopAbs_WIRE)
    Standard_ConstructionError::Raise("Wrong arguments: polyline as wire must be given");

  TopoDS_Wire aWire = TopoDS::Wire(aShape);

  double rad = aCI.GetR();

  if ( rad < Precision::Confusion())
    return 0;

  // collect vertices for make fillet
  TopTools_ListOfShape aVertexList;
  TopTools_MapOfShape mapShape;
  int aLen = aCI.GetLength();
  if ( aLen > 0 ) {
    for (int ind = 1; ind <= aLen; ind++) {
      TopoDS_Shape aShapeVertex;
      if (GEOMImpl_ILocalOperations::GetSubShape
          (aWire, aCI.GetVertex(ind), aShapeVertex))
        if (mapShape.Add(aShapeVertex))
          aVertexList.Append( aShapeVertex );
    }
  } else { // get all vertices from wire
    TopExp_Explorer anExp( aWire, TopAbs_VERTEX );
    for ( ; anExp.More(); anExp.Next() ) {
      if (mapShape.Add(anExp.Current()))
        aVertexList.Append( anExp.Current() );
    }
  }
  if (aVertexList.IsEmpty())
    Standard_ConstructionError::Raise("Invalid input no vertices to make fillet");

  //INFO: this algorithm implemented in assumption that user can select both
  //  vertices of some edges to make fillet. In this case we should remember
  //  already modified initial edges to take care in next fillet step
  TopTools_DataMapOfShapeShape anEdgeToEdgeMap;

  //iterates on vertices, and make fillet on each couple of edges
  //collect result fillet edges in list
  TopTools_ListOfShape aListOfNewEdge;
  // remember relation between initial and modified map
  TopTools_IndexedDataMapOfShapeListOfShape aMapVToEdges;
  TopExp::MapShapesAndAncestors( aWire, TopAbs_VERTEX, TopAbs_EDGE, aMapVToEdges );
  TopTools_ListIteratorOfListOfShape anIt( aVertexList );
  for ( ; anIt.More(); anIt.Next() ) {
    TopoDS_Vertex aV = TopoDS::Vertex( anIt.Value() );
    if ( aV.IsNull() || !aMapVToEdges.Contains( aV ) )
      continue;
    const TopTools_ListOfShape& aVertexEdges = aMapVToEdges.FindFromKey( aV );
    if ( aVertexEdges.Extent() != 2 )
      continue; // no input data to make fillet
    TopoDS_Edge anEdge1 = TopoDS::Edge( aVertexEdges.First() );
    TopoDS_Edge anEdge2 = TopoDS::Edge( aVertexEdges.Last() );
    // check if initial edges already modified in previous fillet operation
    if ( anEdgeToEdgeMap.IsBound( anEdge1 ) ) anEdge1 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge1 ));
    if ( anEdgeToEdgeMap.IsBound( anEdge2 ) ) anEdge2 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge2 ));
    if ( anEdge1.IsNull() || anEdge2.IsNull() || anEdge1.IsSame( anEdge2 ) )
      continue; //no input data to make fillet

    // create plane on 2 edges
    gp_Pln aPlane;
    if ( !takePlane(anEdge1, anEdge2, aV, aPlane) )
      continue; // seems edges does not belong to same plane or parallel (fillet can not be build)

    GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane);
    if ( !aFilletAlgo.Perform(rad) )
      continue; // can not create fillet with given radius

    // take fillet result in given vertex
    TopoDS_Edge aModifE1, aModifE2;
    TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2);
    if (aNewE.IsNull())
      continue; // no result found

    // add  new created edges and take modified edges
    aListOfNewEdge.Append( aNewE );

    // check if face edges modified,
    // if yes, than map to original edges (from vertex-edges list), because edges can be modified before
    if (aModifE1.IsNull() || !anEdge1.IsSame( aModifE1 ))
      addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 );
    if (aModifE2.IsNull() || !anEdge2.IsSame( aModifE2 ))
      addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 );
  }

  if ( anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) {
    StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius");
    return 0;
  }

  // create new wire instead of original
  for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
    TopoDS_Shape anEdge = anExp.Current();
    if ( !anEdgeToEdgeMap.IsBound( anEdge ) )
      aListOfNewEdge.Append( anEdge );
    else if (!anEdgeToEdgeMap.Find( anEdge ).IsNull())
      aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) );
  }

  GEOMImpl_IShapesOperations::SortShapes( aListOfNewEdge );

  BRepBuilderAPI_MakeWire aWireTool;
  aWireTool.Add( aListOfNewEdge );
  aWireTool.Build();
  if (!aWireTool.IsDone())
    return 0;

  aWire = aWireTool.Wire();
  aFunction->SetValue(aWire);
  log.SetTouched(Label());

  return 1;
}
Ejemplo n.º 6
0
//=======================================================================
//function : PerformAreas
//purpose  : 
//=======================================================================
  void GEOMAlgo_BuilderFace::PerformAreas()
{
  myErrorStatus=0;
  //
  Standard_Boolean bIsGrowth, bIsHole;
  Standard_Real aTol;
  TopTools_ListOfShape aNewFaces, aHoleWires; 
  TopoDS_Shape anInfinitePointShape;
  TopTools_DataMapOfShapeShape aInOutMap;
  TopTools_DataMapOfShapeListOfShape aMSH;
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
  TopTools_ListIteratorOfListOfShape aIt1, aIt2;
  TopTools_IndexedMapOfShape aMHE;
  BRep_Builder aBB;
  Handle(Geom_Surface) aS;
  TopLoc_Location aLoc;
  //
  aTol=BRep_Tool::Tolerance(myFace);
  aS=BRep_Tool::Surface(myFace, aLoc);
  //
  myAreas.Clear();
  //
  //  Draft faces [aNewFaces]
  aIt1.Initialize(myLoops);
  for ( ; aIt1.More(); aIt1.Next()) {
    const TopoDS_Shape& aWire=aIt1.Value();
    //
    bIsGrowth=IsGrowthWire(aWire, aMHE);
    if (bIsGrowth) {
      // make a growth face from a wire
      TopoDS_Face aFace;
      aBB.MakeFace(aFace, aS, aLoc, aTol);
      aBB.Add (aFace, aWire);
      //
      aNewFaces.Append (aFace);
    }
    else{
      // check if a wire is a hole 
      //XX
      //bIsHole=IsHole(aWire, myFace, myContext);
      bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
      //XX
      if (bIsHole) {
	aHoleWires.Append(aWire);
	TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
      }
      else {
	// make a growth face from a wire
	TopoDS_Face aFace;
	aBB.MakeFace(aFace, aS, aLoc, aTol);
	aBB.Add (aFace, aWire);
	//
	aNewFaces.Append (aFace);
      }
    }
  }
  //
  // 2. Find outer growth shell that is most close to each hole shell
  aIt2.Initialize(aHoleWires);
  for (; aIt2.More(); aIt2.Next()) {
    const TopoDS_Shape& aHole = aIt2.Value();
    //
    aIt1.Initialize(aNewFaces);
    for ( ; aIt1.More(); aIt1.Next()) {
      const TopoDS_Shape& aF=aIt1.Value();
      //
      if (!IsInside(aHole, aF, myContext)){
        continue;
      }
      //
      if ( aInOutMap.IsBound (aHole)){
        const TopoDS_Shape& aF2=aInOutMap(aHole);
        if (IsInside(aF, aF2, myContext)) {
          aInOutMap.UnBind(aHole);
          aInOutMap.Bind (aHole, aF);
        }
      }
      else{
        aInOutMap.Bind (aHole, aF);
      }
    }
    //
    // Add aHole to a map Face/ListOfHoles [aMSH]
    if (aInOutMap.IsBound(aHole)){
      const TopoDS_Shape& aF=aInOutMap(aHole);
      if (aMSH.IsBound(aF)) {
	TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
	aLH.Append(aHole);
      }
      else {
	TopTools_ListOfShape aLH;
	aLH.Append(aHole);
	aMSH.Bind(aF, aLH);
      }
    }
  }// for (; aIt2.More(); aIt2.Next())
  //
  // 3. Add aHoles to Faces
  aItMSH.Initialize(aMSH);
  for (; aItMSH.More(); aItMSH.Next()) {
    TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
    //
    const TopTools_ListOfShape& aLH=aItMSH.Value();
    aIt2.Initialize(aLH);
    for (; aIt2.More(); aIt2.Next()) {
      const TopoDS_Shape& aHole = aIt2.Value();
      aBB.Add (aF, aHole);
    }
    //
    // update classifier 
    aTol=BRep_Tool::Tolerance(aF);
    IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
    aClsf.Init(aF, aTol);
  }
  //
  // These aNewFaces are draft faces that 
  // do not contain any internal shapes
  //
  myAreas.Append(aNewFaces);
}