1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00
Files
occt/src/BOPAlgo/BOPAlgo_BuilderFace.cxx

864 lines
24 KiB
C++

// Created by: Peter KURNEV
// Copyright (c) 2010-2012 OPEN CASCADE SAS
// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BOPAlgo_BuilderFace.hxx>
#include <BOPAlgo_WireEdgeSet.hxx>
#include <BOPAlgo_WireSplitter.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_BoxTree.hxx>
#include <Bnd_Tools.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepBndLib.hxx>
#include <BRepTools.hxx>
#include <Geom_Surface.hxx>
#include <gp_Pnt2d.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_FClass2d.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_MapOfOrientedShape.hxx>
//
static
Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
const TopTools_IndexedMapOfShape& );
static
Standard_Boolean IsInside(const TopoDS_Shape& ,
const TopoDS_Shape& ,
Handle(IntTools_Context)& );
static
void MakeInternalWires(const TopTools_IndexedMapOfShape& ,
TopTools_ListOfShape& );
//=======================================================================
//function :
//purpose :
//=======================================================================
BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
:
BOPAlgo_BuilderArea()
{
myOrientation=TopAbs_EXTERNAL;
}
//=======================================================================
//function :
//purpose :
//=======================================================================
BOPAlgo_BuilderFace::BOPAlgo_BuilderFace
(const Handle(NCollection_BaseAllocator)& theAllocator)
:
BOPAlgo_BuilderArea(theAllocator)
{
myOrientation=TopAbs_EXTERNAL;
}
//=======================================================================
//function : ~
//purpose :
//=======================================================================
BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
{
}
//=======================================================================
//function : SetFace
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
{
myOrientation=theFace.Orientation();
myFace=theFace;
myFace.Orientation(TopAbs_FORWARD);
}
//=======================================================================
//function : Orientation
//purpose :
//=======================================================================
TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
{
return myOrientation;
}
//=======================================================================
//function : Face
//purpose :
//=======================================================================
const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
{
return myFace;
}
//=======================================================================
//function : CheckData
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::CheckData()
{
if (myFace.IsNull()) {
AddError (new BOPAlgo_AlertNullInputShapes);
return;
}
if (myContext.IsNull()) {
myContext = new IntTools_Context;
}
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::Perform(const Message_ProgressRange& theRange)
{
Message_ProgressScope aPS (theRange, NULL, 100);
GetReport()->Clear();
//
CheckData();
if (HasErrors()) {
return;
}
//
PerformShapesToAvoid (aPS.Next(1));
if (HasErrors()) {
return;
}
//
PerformLoops (aPS.Next(10));
if (HasErrors()) {
return;
}
//
PerformAreas (aPS.Next(80));
if (HasErrors()) {
return;
}
//
PerformInternalShapes(aPS.Next(9));
}
//=======================================================================
//function :PerformShapesToAvoid
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::PerformShapesToAvoid(const Message_ProgressRange& theRange)
{
Standard_Boolean bFound;
Standard_Integer i, iCnt, aNbV, aNbE;
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
TopTools_ListIteratorOfListOfShape aIt;
//
myShapesToAvoid.Clear();
//
Message_ProgressScope aPS(theRange, NULL, 1);
//
iCnt=0;
for(;;) {
if (UserBreak(aPS))
{
return;
}
++iCnt;
bFound=Standard_False;
//
// 1. MEF
aMVE.Clear();
aIt.Initialize (myShapes);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aE=aIt.Value();
if (!myShapesToAvoid.Contains(aE)) {
TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
}
}
aNbV=aMVE.Extent();
//
// 2. myEdgesToAvoid
for (i=1; i<=aNbV; ++i) {
const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
//
TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
aNbE=aLE.Extent();
if (!aNbE) {
continue;
}
//
const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
if (aNbE==1) {
if (BRep_Tool::Degenerated(aE1)) {
continue;
}
if (aV.Orientation()==TopAbs_INTERNAL) {
continue;
}
bFound=Standard_True;
myShapesToAvoid.Add(aE1);
}
else if (aNbE==2) {
const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
if (aE2.IsSame(aE1)) {
TopoDS_Vertex aV1x, aV2x;
//
TopExp::Vertices(aE1, aV1x, aV2x);
if (aV1x.IsSame(aV2x)) {
continue;
}
bFound=Standard_True;
myShapesToAvoid.Add(aE1);
myShapesToAvoid.Add(aE2);
}
}
}// for (i=1; i<=aNbE; ++i) {
//
if (!bFound) {
break;
}
}
}
//=======================================================================
//function : PerformLoops
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::PerformLoops(const Message_ProgressRange& theRange)
{
Standard_Boolean bFlag;
Standard_Integer i, aNbEA;
TopTools_ListIteratorOfListOfShape aIt;
TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
TopTools_MapOfOrientedShape aMAdded;
TopoDS_Iterator aItW;
BRep_Builder aBB;
BOPAlgo_WireEdgeSet aWES(myAllocator);
BOPAlgo_WireSplitter aWSp(myAllocator);
//
Message_ProgressScope aMainScope(theRange, "Making wires", 10);
//
// 1.
myLoops.Clear();
aWES.SetFace(myFace);
//
aIt.Initialize(myShapes);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aE=aIt.Value();
if (!myShapesToAvoid.Contains(aE)) {
aWES.AddStartElement(aE);
}
}
//
aWSp.SetWES(aWES);
aWSp.SetRunParallel(myRunParallel);
aWSp.SetContext(myContext);
aWSp.Perform(aMainScope.Next(9));
if (aWSp.HasErrors()) {
return;
}
//
const TopTools_ListOfShape& aLW=aWES.Shapes();
aIt.Initialize (aLW);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aW=aIt.Value();
myLoops.Append(aW);
}
// Post Treatment
TopTools_MapOfOrientedShape aMEP;
//
// a. collect all edges that are in loops
aIt.Initialize (myLoops);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aW=aIt.Value();
aItW.Initialize(aW);
for (; aItW.More(); aItW.Next()) {
const TopoDS_Shape& aE=aItW.Value();
aMEP.Add(aE);
}
}
if (UserBreak (aMainScope)) {
return;
}
//
// b. collect all edges that are to avoid
aNbEA = myShapesToAvoid.Extent();
for (i = 1; i <= aNbEA; ++i) {
const TopoDS_Shape& aE = myShapesToAvoid(i);
aMEP.Add(aE);
}
//
// c. add all edges that are not processed to myShapesToAvoid
aIt.Initialize (myShapes);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aE=aIt.Value();
if (!aMEP.Contains(aE)) {
myShapesToAvoid.Add(aE);
}
}
//
if (UserBreak (aMainScope)) {
return;
}
// 2. Internal Wires
myLoopsInternal.Clear();
//
aNbEA = myShapesToAvoid.Extent();
for (i = 1; i <= aNbEA; ++i) {
const TopoDS_Shape& aEE = myShapesToAvoid(i);
TopExp::MapShapesAndAncestors(aEE,
TopAbs_VERTEX,
TopAbs_EDGE,
aVEMap);
}
//
bFlag=Standard_True;
for (i = 1; (i <= aNbEA) && bFlag; ++i) {
const TopoDS_Shape& aEE = myShapesToAvoid(i);
if (!aMAdded.Add(aEE)) {
continue;
}
//
if (UserBreak (aMainScope)) {
return;
}
// make new wire
TopoDS_Wire aW;
aBB.MakeWire(aW);
aBB.Add(aW, aEE);
//
aItW.Initialize(aW);
for (; aItW.More()&&bFlag; aItW.Next()) {
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
//
TopoDS_Iterator aItE(aE);
for (; aItE.More()&&bFlag; aItE.Next()) {
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
aIt.Initialize(aLE);
for (; aIt.More()&&bFlag; aIt.Next()) {
const TopoDS_Shape& aEx=aIt.Value();
if (aMAdded.Add(aEx)) {
aBB.Add(aW, aEx);
if(aMAdded.Extent()==aNbEA) {
bFlag=!bFlag;
}
}
}//for (; aIt.More(); aIt.Next()) {
}//for (; aItE.More(); aItE.Next()) {
}//for (; aItW.More(); aItW.Next()) {
aW.Closed(BRep_Tool::IsClosed(aW));
myLoopsInternal.Append(aW);
}//for (i = 1; (i <= aNbEA) && bFlag; ++i) {
}
//=======================================================================
//function : PerformAreas
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::PerformAreas(const Message_ProgressRange& theRange)
{
myAreas.Clear();
BRep_Builder aBB;
// Location of the myFace
TopLoc_Location aLoc;
// Get surface from myFace
const Handle(Geom_Surface)& aS = BRep_Tool::Surface(myFace, aLoc);
// Get tolerance of myFace
Standard_Real aTol = BRep_Tool::Tolerance(myFace);
Message_ProgressScope aMainScope (theRange, NULL, 10);
// Check if there are no loops at all
if (myLoops.IsEmpty())
{
if (myContext->IsInfiniteFace(myFace))
{
TopoDS_Face aFace;
aBB.MakeFace(aFace, aS, aLoc, aTol);
if (BRep_Tool::NaturalRestriction(myFace))
aBB.NaturalRestriction(aFace, Standard_True);
myAreas.Append(aFace);
}
return;
}
// The new faces
TopTools_ListOfShape aNewFaces;
// The hole faces which has to be classified relatively new faces
TopTools_IndexedMapOfShape aHoleFaces;
// Map of the edges of the hole faces for quick check of the growths.
// If the analyzed wire contains any of the edges from the hole faces
// it is considered as growth.
TopTools_IndexedMapOfShape aMHE;
// Analyze the new wires - classify them to be the holes and growths
Message_ProgressScope aPSClass(aMainScope.Next(5), "Making faces", myLoops.Size());
TopTools_ListIteratorOfListOfShape aItLL(myLoops);
for (; aItLL.More(); aItLL.Next(), aPSClass.Next())
{
if (UserBreak(aPSClass))
{
return;
}
const TopoDS_Shape& aWire = aItLL.Value();
TopoDS_Face aFace;
aBB.MakeFace(aFace, aS, aLoc, aTol);
aBB.Add(aFace, aWire);
Standard_Boolean bIsGrowth = IsGrowthWire(aWire, aMHE);
if (!bIsGrowth)
{
// Fast check did not give the result, run classification
IntTools_FClass2d& aClsf = myContext->FClass2d(aFace);
bIsGrowth = !aClsf.IsHole();
}
// Save the face
if (bIsGrowth)
{
aNewFaces.Append(aFace);
}
else
{
aHoleFaces.Add(aFace);
TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
}
}
if (aHoleFaces.IsEmpty())
{
// No holes, stop the analysis
myAreas.Append(aNewFaces);
return;
}
// Classify holes relatively faces
// Prepare tree with the boxes of the hole faces
BOPTools_Box2dTree aBoxTree;
Standard_Integer i, aNbH = aHoleFaces.Extent();
aBoxTree.SetSize (aNbH);
for (i = 1; i <= aNbH; ++i)
{
const TopoDS_Face& aHFace = TopoDS::Face(aHoleFaces(i));
//
Bnd_Box2d aBox;
BRepTools::AddUVBounds(aHFace, aBox);
aBoxTree.Add(i, Bnd_Tools::Bnd2BVH (aBox));
}
// Build BVH
aBoxTree.Build();
// Find outer growth face that is most close to each hole face
TopTools_IndexedDataMapOfShapeShape aHoleFaceMap;
// Selector
BOPTools_Box2dTreeSelector aSelector;
aSelector.SetBVHSet (&aBoxTree);
Message_ProgressScope aPSHoles(aMainScope.Next(4), "Adding holes", aNewFaces.Extent());
TopTools_ListIteratorOfListOfShape aItLS(aNewFaces);
for (; aItLS.More(); aItLS.Next(), aPSHoles.Next())
{
if (UserBreak (aPSHoles))
{
return;
}
const TopoDS_Face& aFace = TopoDS::Face(aItLS.Value());
// Build box
Bnd_Box2d aBox;
BRepTools::AddUVBounds(aFace, aBox);
aSelector.Clear();
aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBox));
aSelector.Select();
const TColStd_ListOfInteger& aLI = aSelector.Indices();
TColStd_ListIteratorOfListOfInteger aItLI(aLI);
for (; aItLI.More(); aItLI.Next())
{
Standard_Integer k = aItLI.Value();
const TopoDS_Shape& aHole = aHoleFaces(k);
// Check if it is inside
if (!IsInside(aHole, aFace, myContext))
continue;
// Save the relation
TopoDS_Shape* pFaceWas = aHoleFaceMap.ChangeSeek(aHole);
if (pFaceWas)
{
if (IsInside(aFace, *pFaceWas, myContext))
{
*pFaceWas = aFace;
}
}
else
{
aHoleFaceMap.Add(aHole, aFace);
}
}
}
// Make the back map from faces to holes
TopTools_IndexedDataMapOfShapeListOfShape aFaceHolesMap;
aNbH = aHoleFaceMap.Extent();
for (i = 1; i <= aNbH; ++i)
{
const TopoDS_Shape& aHole = aHoleFaceMap.FindKey(i);
const TopoDS_Shape& aFace = aHoleFaceMap(i);
//
TopTools_ListOfShape* pLHoles = aFaceHolesMap.ChangeSeek(aFace);
if (!pLHoles)
pLHoles = &aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
pLHoles->Append(aHole);
}
// Add unused holes to the original face
if (aHoleFaces.Extent() != aHoleFaceMap.Extent())
{
Bnd_Box aBoxF;
BRepBndLib::Add(myFace, aBoxF);
if (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() ||
aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() ||
aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax())
{
TopoDS_Face aFace;
aBB.MakeFace(aFace, aS, aLoc, aTol);
TopTools_ListOfShape& anUnUsedHoles = aFaceHolesMap(aFaceHolesMap.Add(aFace, TopTools_ListOfShape()));
aNbH = aHoleFaces.Extent();
for (i = 1; i <= aNbH; ++i)
{
const TopoDS_Shape& aHole = aHoleFaces(i);
if (!aHoleFaceMap.Contains(aHole))
anUnUsedHoles.Append(aHole);
}
// Save it
aNewFaces.Append(aFace);
}
}
// Add Holes to Faces and add them to myAreas
Message_ProgressScope aPSU (aMainScope.Next(), NULL, aNewFaces.Size());
aItLS.Initialize(aNewFaces);
for ( ; aItLS.More(); aItLS.Next(), aPSU.Next())
{
if (UserBreak (aPSU))
{
return;
}
TopoDS_Face& aFace = *(TopoDS_Face*)&aItLS.Value();
const TopTools_ListOfShape* pLHoles = aFaceHolesMap.Seek(aFace);
if (pLHoles)
{
// update faces with the holes
TopTools_ListIteratorOfListOfShape aItLH(*pLHoles);
for (; aItLH.More(); aItLH.Next())
{
const TopoDS_Shape& aFHole = aItLH.Value();
// The hole face contains only one wire
TopoDS_Iterator aItW(aFHole);
aBB.Add(aFace, aItW.Value());
}
// update classifier
myContext->FClass2d(aFace).Init(aFace, aTol);
}
// The face is just a draft that does not contain any internal shapes
myAreas.Append(aFace);
}
}
//=======================================================================
//function : PerformInternalShapes
//purpose :
//=======================================================================
void BOPAlgo_BuilderFace::PerformInternalShapes(const Message_ProgressRange& theRange)
{
if (myAvoidInternalShapes)
// User-defined option to avoid internal edges
// in the result is in force.
return;
if (myLoopsInternal.IsEmpty())
// No edges left for classification
return;
// Prepare tree with the boxes of the edges to classify
BOPTools_Box2dTree aBoxTree;
// Map of edges to classify
TopTools_IndexedMapOfShape anEdgesMap;
// Main progress scope
Message_ProgressScope aMainScope (theRange, "Adding internal shapes", 3);
// Fill the tree and the map
TopTools_ListIteratorOfListOfShape itLE(myLoopsInternal);
for (; itLE.More(); itLE.Next())
{
if (UserBreak (aMainScope))
{
return;
}
TopoDS_Iterator itE(itLE.Value());
for (; itE.More(); itE.Next())
{
const TopoDS_Edge& aE = TopoDS::Edge(itE.Value());
if (!anEdgesMap.Contains(aE))
{
Bnd_Box2d aBoxE;
BRepTools::AddUVBounds(myFace, aE, aBoxE);
// Make sure the index of edge in the map and
// of the box in the tree is the same
aBoxTree.Add(anEdgesMap.Add(aE), Bnd_Tools::Bnd2BVH (aBoxE));
}
}
}
// Build BVH
aBoxTree.Build();
aMainScope.Next();
// Fence map
TColStd_MapOfInteger aMEDone;
// Classify edges relatively faces
Message_ProgressScope aPSClass(aMainScope.Next(), NULL, myAreas.Size());
TopTools_ListIteratorOfListOfShape itLF(myAreas);
for (; itLF.More(); itLF.Next(), aPSClass.Next())
{
if (UserBreak(aPSClass))
{
return;
}
TopoDS_Face& aF = *(TopoDS_Face*)&itLF.Value();
// Build box
Bnd_Box2d aBoxF;
BRepTools::AddUVBounds(aF, aBoxF);
// Select edges for the classification
BOPTools_Box2dTreeSelector aSelector;
aSelector.SetBVHSet (&aBoxTree);
aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBoxF));
if (!aSelector.Select())
continue;
// Collect edges inside the face
TopTools_IndexedMapOfShape anEdgesInside;
const TColStd_ListOfInteger& aLI = aSelector.Indices();
TColStd_ListIteratorOfListOfInteger itLI(aLI);
for (; itLI.More(); itLI.Next())
{
const Standard_Integer nE = itLI.Value();
if (aMEDone.Contains(nE))
continue;
const TopoDS_Edge& aE = TopoDS::Edge(anEdgesMap(nE));
if (IsInside(aE, aF, myContext))
{
anEdgesInside.Add(aE);
aMEDone.Add(nE);
}
}
if (anEdgesInside.IsEmpty())
continue;
// Make internal wires
TopTools_ListOfShape aLSI;
MakeInternalWires(anEdgesInside, aLSI);
// Add wires to a face
TopTools_ListIteratorOfListOfShape itLSI(aLSI);
for (; itLSI.More(); itLSI.Next())
{
const TopoDS_Shape& aWI = itLSI.Value();
BRep_Builder().Add(aF, aWI);
}
// Condition of early exit
if (aMEDone.Extent() == anEdgesMap.Extent())
// All edges are classified and added into the faces
return;
}
// Some edges are left unclassified - warn user about them
TopTools_IndexedMapOfShape anEdgesUnUsed;
for (Standard_Integer i = 1; i <= anEdgesMap.Extent(); ++i)
{
if (!aMEDone.Contains(i))
anEdgesUnUsed.Add(anEdgesMap(i));
}
// Make internal wires
TopTools_ListOfShape aLSI;
MakeInternalWires(anEdgesUnUsed, aLSI);
// Make compound
TopoDS_Compound aWShape;
BRep_Builder().MakeCompound(aWShape);
BRep_Builder().Add(aWShape, myFace);
if (aLSI.Extent() == 1)
BRep_Builder().Add(aWShape, aLSI.First());
else
{
TopoDS_Compound aCE;
BRep_Builder().MakeCompound(aCE);
for (TopTools_ListIteratorOfListOfShape it(aLSI); it.More(); it.Next())
BRep_Builder().Add(aCE, it.Value());
BRep_Builder().Add(aWShape, aCE);
}
// Add warning
AddWarning(new BOPAlgo_AlertFaceBuilderUnusedEdges(aWShape));
}
//=======================================================================
//function : MakeInternalWires
//purpose :
//=======================================================================
void MakeInternalWires(const TopTools_IndexedMapOfShape& theME,
TopTools_ListOfShape& theWires)
{
Standard_Integer i, aNbE;
TopTools_MapOfShape aAddedMap;
TopTools_ListIteratorOfListOfShape aItE;
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
BRep_Builder aBB;
//
aNbE = theME.Extent();
for (i = 1; i <= aNbE; ++i) {
const TopoDS_Shape& aE = theME(i);
TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
}
//
for (i = 1; i <= aNbE; ++i) {
TopoDS_Shape aEE = theME(i);
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);
}
}
}
}
aW.Closed(BRep_Tool::IsClosed(aW));
theWires.Append(aW);
}
}
//=======================================================================
//function : IsInside
//purpose :
//=======================================================================
Standard_Boolean IsInside(const TopoDS_Shape& theWire,
const TopoDS_Shape& theF,
Handle(IntTools_Context)& theContext)
{
// Check if the wire is located inside the face:
// take unique point from the wire and classify it relatively the face
// Avoid edges of the face
TopTools_IndexedMapOfShape aFaceEdgesMap;
TopExp::MapShapes(theF, TopAbs_EDGE, aFaceEdgesMap);
// Get classification tool from the context
const TopoDS_Face& aF = TopoDS::Face(theF);
IntTools_FClass2d& aClassifier = theContext->FClass2d(aF);
Standard_Boolean isInside = Standard_False;
// Iterate on wire edges until first classification is performed
TopExp_Explorer anExp(theWire, TopAbs_EDGE);
for (; anExp.More(); anExp.Next())
{
const TopoDS_Edge& aE = TopoDS::Edge(anExp.Current());
if (BRep_Tool::Degenerated(aE))
// Avoid checking degenerated edges.
continue;
if (aFaceEdgesMap.Contains(aE))
// Face contains the edge from the wire, thus the wire cannot be
// inside that face.
return isInside;
// Get 2d curve of the edge on the face
Standard_Real aT1, aT2;
const Handle(Geom2d_Curve)& aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
if (aC2D.IsNull())
continue;
// Get middle point on the curve
gp_Pnt2d aP2D = aC2D->Value((aT1 + aT2) / 2.);
// Classify the point
TopAbs_State aState = aClassifier.Perform(aP2D);
isInside = (aState == TopAbs_IN);
break;
}
return isInside;
}
//=======================================================================
//function : IsGrowthWire
//purpose :
//=======================================================================
Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
const TopTools_IndexedMapOfShape& theMHE)
{
if (theMHE.Extent())
{
TopoDS_Iterator aIt(theWire);
for(; aIt.More(); aIt.Next())
{
if (theMHE.Contains(aIt.Value()))
return Standard_True;
}
}
return Standard_False;
}