1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0029711: General Fuse operation produces invalid result

The following improvements have been introduced in Boolean Operations algorithm s:
1. UBTree is replaced with EBTree in Boolean operations to be able to add/remove elements into the tree of bounding boxes.
2. Repeated (nested) intersection of sub-shapes is performed with argument vertices whose tolerances increased during the operation.
3. The algorithms of Edge/Edge and Edge/Face intersection have been improved for the cases when the intersection point is located close to the edge boundaries .
4. New procedure has been implemented to ensure forced creation of Edge/Face common blocks in cases when the edge is really close to the face.
5. Post-processing of Face/Face intersection results has been improved.
6. Extension of the planar faces for Plane/Plane intersection is avoided.
7. Builder Face now better classifies potentially internal edges relatively to new faces with filtering by bounding boxes.

Side effect changes:
1. IntTools_ShrunkRange now keeps the length of the valid range of the edge.
2. The method BOPDS_DS::UpdateEdgeTolerance() has been removed as unused (replaced by the BOPAlgo_PaveFiller::UpdateEdgeTolerance()).

Test case for the issue 0029900.
Test case for the issue 0029711.
Adjustments of the existing test cases.

Avoid using uninitialized variables.
This commit is contained in:
emv 2018-05-16 12:12:09 +03:00 committed by bugmaster
parent fb60181a3a
commit d3578357e3
48 changed files with 1885 additions and 864 deletions

View File

@ -92,5 +92,8 @@ Error: The Feature Removal algorithm has failed
.BOPAlgo_AlertSolidBuilderUnusedFaces
Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation
.BOPAlgo_AlertFaceBuilderUnusedEdges
Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation
.BOPAlgo_AlertUnableToOrientTheShape
Warning: Unable to orient the shape correctly

View File

@ -104,6 +104,10 @@ DEFINE_SIMPLE_ALERT(BOPAlgo_AlertRemoveFeaturesFailed)
//! and not used for solids creation
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertSolidBuilderUnusedFaces)
//! Some of the edges passed to the Face Builder algorithm have not been classified
//! and not used for faces creation
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertFaceBuilderUnusedEdges)
//! Unable to orient the shape correctly
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToOrientTheShape)

View File

@ -95,5 +95,8 @@ static const char BOPAlgo_BOPAlgo_msg[] =
".BOPAlgo_AlertSolidBuilderUnusedFaces\n"
"Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n"
"\n"
".BOPAlgo_AlertFaceBuilderUnusedEdges\n"
"Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation\n"
"\n"
".BOPAlgo_AlertUnableToOrientTheShape\n"
"Warning: Unable to orient the shape correctly\n";

View File

@ -39,7 +39,7 @@
#include <IntTools_FClass2d.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_UBTreeFiller.hxx>
#include <TColStd_MapIntegerHasher.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <TopAbs.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
@ -443,6 +443,7 @@ void BOPAlgo_BuilderFace::PerformAreas()
{
// No holes, stop the analysis
myAreas.Append(aNewFaces);
return;
}
// Classify holes relatively faces
@ -580,76 +581,132 @@ void BOPAlgo_BuilderFace::PerformAreas()
//=======================================================================
void BOPAlgo_BuilderFace::PerformInternalShapes()
{
if (myAvoidInternalShapes) {
if (myAvoidInternalShapes)
// User-defined option to avoid internal edges
// in the result is in force.
return;
}
//
Standard_Integer aNbWI=myLoopsInternal.Extent();
if (!aNbWI) {// nothing to do
if (myLoopsInternal.IsEmpty())
// No edges left for classification
return;
// Prepare tree filler with the boxes of the edges to classify
NCollection_UBTree<Standard_Integer, Bnd_Box2d> aBBTree;
NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
// Map of edges to classify
TopTools_IndexedMapOfShape anEdgesMap;
// Fill the tree and the map
TopTools_ListIteratorOfListOfShape itLE(myLoopsInternal);
for (; itLE.More(); itLE.Next())
{
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
aTreeFiller.Add(anEdgesMap.Add(aE), aBoxE);
}
}
}
//
//Standard_Real aTol;
Standard_Integer i;
BRep_Builder aBB;
TopTools_ListIteratorOfListOfShape aIt1, aIt2;
TopoDS_Iterator aIt;
TopTools_IndexedMapOfShape aME1, aME2, aMEP;
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
// Shake the tree
aTreeFiller.Fill();
// Fence map
TColStd_MapOfInteger aMEDone;
// Classify edges relatively faces
TopTools_ListIteratorOfListOfShape itLF(myAreas);
for (; itLF.More(); itLF.Next())
{
TopoDS_Face& aF = *(TopoDS_Face*)&itLF.Value();
// Build box
Bnd_Box2d aBoxF;
BRepTools::AddUVBounds(aF, aBoxF);
// Select edges for the classification
BOPTools_BoxSelector<Bnd_Box2d> aSelector;
aSelector.SetBox(aBoxF);
if (!aBBTree.Select(aSelector))
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;
//
// 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();
aME1.Add(aE);
}
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);
}
//
// 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
aME2.Clear();
aMEP.Clear();
aNbWI = aME1.Extent();
for (i = 1; i <= aNbWI; ++i) {
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aME1(i)));
if (IsInside(aE, aF, myContext)) {
aMEP.Add(aE);
}
else {
aME2.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
aME1 = aME2;
//
aNbWI = aME1.Extent();
if (!aNbWI) {
break;
}
} //for ( ; aIt2.More(); aIt2.Next()) {
// Add warning
AddWarning(new BOPAlgo_AlertFaceBuilderUnusedEdges(aWShape));
}
//=======================================================================
//function : MakeInternalWires

View File

@ -685,7 +685,8 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
aBB.Add(aWShape, aItLS.Value());
}
AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape)); }
AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape));
}
}
//=======================================================================
//function : MakeInternalShells

View File

@ -461,6 +461,7 @@ void BOPAlgo_Builder::BuildSplitFaces()
{
BOPAlgo_BuilderFace& aBF = aVBF(k);
aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
myReport->Merge(aBF.GetReport());
}
aNbBF = aFacesIm.Extent();

View File

@ -54,7 +54,10 @@ BOPAlgo_PaveFiller::BOPAlgo_PaveFiller()
BOPAlgo_PaveFiller::BOPAlgo_PaveFiller
(const Handle(NCollection_BaseAllocator)& theAllocator)
:
BOPAlgo_Algo(theAllocator)
BOPAlgo_Algo(theAllocator),
myFPBDone(1, theAllocator),
myIncreasedSS(1, theAllocator),
myVertsToAvoidExtension(1, theAllocator)
{
myDS = NULL;
myIterator = NULL;
@ -134,6 +137,7 @@ void BOPAlgo_PaveFiller::Clear()
delete myDS;
myDS=NULL;
}
myIncreasedSS.Clear();
}
//=======================================================================
//function : DS
@ -286,9 +290,17 @@ void BOPAlgo_PaveFiller::PerformInternal()
UpdatePaveBlocksWithSDVertices();
UpdateInterfsWithSDVertices();
// Repeat Intersection with increased vertices
RepeatIntersection();
if (HasErrors())
return;
// Force intersection of edges after increase
// of the tolerance values of their vertices
ForceInterfEE();
// Force Edge/Face intersection after increase
// of the tolerance values of their vertices
ForceInterfEF();
//
// 22
PerformFF();
@ -326,3 +338,58 @@ void BOPAlgo_PaveFiller::PerformInternal()
return;
}
}
//=======================================================================
// function: RepeatIntersection
// purpose:
//=======================================================================
void BOPAlgo_PaveFiller::RepeatIntersection()
{
// Find all vertices with increased tolerance
TColStd_MapOfInteger anExtraInterfMap;
const Standard_Integer aNbS = myDS->NbSourceShapes();
for (Standard_Integer i = 0; i < aNbS; ++i)
{
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
if (aSI.ShapeType() != TopAbs_VERTEX)
continue;
// Check if the tolerance of the original vertex has been increased
if (myIncreasedSS.Contains(i))
{
anExtraInterfMap.Add(i);
continue;
}
// Check if the vertex created a new vertex with greater tolerance
Standard_Integer nVSD;
if (!myDS->HasShapeSD(i, nVSD))
continue;
if (myIncreasedSS.Contains(nVSD))
anExtraInterfMap.Add(i);
}
if (anExtraInterfMap.IsEmpty())
return;
// Update iterator of pairs of shapes with interfering boxes
myIterator->PrepareExt(anExtraInterfMap);
// Perform intersections with vertices
PerformVV();
if (HasErrors())
return;
UpdatePaveBlocksWithSDVertices();
PerformVE();
if (HasErrors())
return;
UpdatePaveBlocksWithSDVertices();
PerformVF();
if (HasErrors())
return;
UpdatePaveBlocksWithSDVertices();
UpdateInterfsWithSDVertices();
}

View File

@ -172,6 +172,14 @@ protected:
Bnd_Box,
TColStd_MapTransientHasher> BOPAlgo_DataMapOfPaveBlockBndBox;
typedef NCollection_DataMap
<Handle(BOPDS_PaveBlock),
TColStd_ListOfInteger,
TColStd_MapTransientHasher> BOPAlgo_DataMapOfPaveBlockListOfInteger;
typedef NCollection_DataMap
<Standard_Integer,
BOPDS_MapOfPaveBlock> BOPAlgo_DataMapOfIntegerMapOfPaveBlock;
//! Sets non-destructive mode automatically if an argument
//! contains a locked sub-shape (see TopoDS_Shape::Locked()).
@ -265,7 +273,8 @@ protected:
TColStd_DataMapOfIntegerReal& theMVTol,
TColStd_DataMapOfIntegerListOfInteger& theDMVLV);
Standard_EXPORT void FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC);
Standard_EXPORT void FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC,
TColStd_DataMapOfIntegerReal& theMVTol);
//! Depending on the parameter aType it checks whether
//! the vertex nV was created in EE or EF intersections.
@ -281,21 +290,30 @@ protected:
const TopoDS_Face& theF2,
BOPDS_Curve& theNC,
TColStd_ListOfInteger& theLBV);
//! Checks if the given pave block (created on section curve)
//! coincides with any of the pave blocks of the faces
//! created the section curve.
Standard_EXPORT Standard_Boolean IsExistingPaveBlock
(const Handle(BOPDS_PaveBlock)& thePB, const BOPDS_Curve& theNC,
const Standard_Real theTolR3D, const BOPDS_IndexedMapOfPaveBlock& theMPB,
const BOPDS_MapOfPaveBlock& theMPBCommon,
Handle(BOPDS_PaveBlock)& thePBOut, Standard_Real& theTolNew);
Standard_EXPORT Standard_Boolean IsExistingPaveBlock (const Handle(BOPDS_PaveBlock)& thePB, const BOPDS_Curve& theNC, const TColStd_ListOfInteger& theLSE);
//! Checks if the given pave block (created on section curve)
//! coincides with any of the edges shared between the faces
//! created the section curve.
Standard_EXPORT Standard_Boolean IsExistingPaveBlock(const Handle(BOPDS_PaveBlock)& thePB,
const BOPDS_Curve& theNC,
const TColStd_ListOfInteger& theLSE,
Standard_Integer& theNEOut,
Standard_Real& theTolNew);
//! Treatment of section edges.
Standard_EXPORT void PostTreatFF (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDMExEdges,
TColStd_DataMapOfIntegerInteger& theDMNewSD,
const TopTools_IndexedMapOfShape& theMicroEdges,
const BOPDS_IndexedMapOfPaveBlock& theMicroPB,
const TopTools_IndexedMapOfShape& theVertsOnRejectedPB,
const Handle(NCollection_BaseAllocator)& theAllocator);
@ -360,14 +378,24 @@ protected:
//! Adds the existing edges from the map <theMPBOnIn> which interfere
//! with the vertices from <theMVB> map to the post treatment of section edges.
Standard_EXPORT void ProcessExistingPaveBlocks (const Standard_Integer theInt, const BOPDS_IndexedMapOfPaveBlock& theMPBOnIn, const TColStd_DataMapOfIntegerListOfInteger& theDMBV, BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB, TopTools_DataMapOfShapeInteger& theMVI, BOPDS_MapOfPaveBlock& theMPB);
Standard_EXPORT void ProcessExistingPaveBlocks (const Standard_Integer theInt,
const Standard_Integer nF1,
const Standard_Integer nF2,
const BOPDS_IndexedMapOfPaveBlock& theMPBOnIn,
const TColStd_DataMapOfIntegerListOfInteger& theDMBV,
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
TopTools_DataMapOfShapeInteger& theMVI,
BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap,
BOPDS_MapOfPaveBlock& theMPB);
//! Replaces existing pave block <thePB> with new pave blocks <theLPB>.
//! The list <theLPB> contains images of <thePB> which were created in
//! the post treatment of section edges.
Standard_EXPORT void UpdateExistingPaveBlocks (const Handle(BOPDS_PaveBlock)& thePB, BOPDS_ListOfPaveBlock& theLPB, const Standard_Integer nF1, const Standard_Integer nF2);
//! Tries to project the new edges on the faces contained in the <thePBFacesMap>.
Standard_EXPORT void UpdateExistingPaveBlocks(const Handle(BOPDS_PaveBlock)& thePB,
BOPDS_ListOfPaveBlock& theLPB,
const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap);
//! Treatment of vertices that were created in EE intersections.
Standard_EXPORT void TreatNewVertices(const BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB, TopTools_IndexedDataMapOfShapeListOfShape& theImages);
@ -382,8 +410,9 @@ protected:
Standard_EXPORT void PreparePostTreatFF (const Standard_Integer aInt, const Standard_Integer aCur, const Handle(BOPDS_PaveBlock)& aPB, BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& aMSCPB, TopTools_DataMapOfShapeInteger& aMVI, BOPDS_ListOfPaveBlock& aLPB);
//! Updates the information about faces
Standard_EXPORT void UpdateFaceInfo (BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME, const TColStd_DataMapOfIntegerInteger& theDMV);
Standard_EXPORT void UpdateFaceInfo(BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME,
const TColStd_DataMapOfIntegerInteger& theDMV,
const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap);
//! Updates tolerance of vertex with index <nV>
//! to make it interfere with edge.
@ -485,17 +514,31 @@ protected:
//! Adds the warning about failed intersection of pair of sub-shapes
Standard_EXPORT void AddIntersectionFailedWarning(const TopoDS_Shape& theS1, const TopoDS_Shape& theS2);
//! Repeat intersection of sub-shapes with increased vertices.
Standard_EXPORT void RepeatIntersection();
//! Updates vertices of CommonBlocks with real tolerance of CB.
Standard_EXPORT void UpdateVerticesOfCB();
//! The method looks for the additional common blocks among pairs of edges
//! which did not participate in edges intersection (PerformEE() method)
//! due to being rejected by bounding boxes intersection.
//! with the same bounding vertices.
Standard_EXPORT void ForceInterfEE();
//! The method looks for the additional edge/face common blocks
//! among pairs of edge/face having the same vertices.
Standard_EXPORT void ForceInterfEF();
//! Performs intersection of given pave blocks
//! with all faces from arguments.
Standard_EXPORT void ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB,
const Standard_Boolean theAddInterf);
//! When all section edges are created and no increase of the tolerance
//! of vertices put on the section edges is expected, make sure that
//! the created sections have valid range.
//! If any of the section edges do not have valid range, remove them
//! from Face/Face intersection info and from the input <theMSCPB> map.
//! Put such edges into <aMicroEdges> map for further unification of their
//! Put such edges into <MicroPB> map for further unification of their
//! vertices in the PostTreatFF method.
//!
//! All these section edges have already been checked to have valid range.
@ -503,7 +546,7 @@ protected:
//! been put on other section edges with greater tolerance, which has caused
//! increase of the tolerance value of the vertices.
Standard_EXPORT void RemoveMicroSectionEdges(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
TopTools_IndexedMapOfShape& theMicroEdges);
BOPDS_IndexedMapOfPaveBlock& theMicroPB);
TopTools_ListOfShape myArguments;
@ -516,8 +559,12 @@ protected:
Standard_Boolean myAvoidBuildPCurve;
BOPAlgo_GlueEnum myGlue;
private:
BOPAlgo_DataMapOfIntegerMapOfPaveBlock myFPBDone; //!< Fence map of intersected faces and pave blocks
TColStd_MapOfInteger myIncreasedSS; //!< Sub-shapes with increased tolerance during the operation
TColStd_MapOfInteger myVertsToAvoidExtension; //!< Vertices located close to E/E or E/F intersection points
//! which has already been extended to cover the real intersection
//! points, and should not be extended any longer to be put
//! on a section curve.
};

View File

@ -68,14 +68,27 @@ void BOPAlgo_PaveFiller::PerformVV()
for (; myIterator->More(); myIterator->Next()) {
myIterator->Value(n1, n2);
//
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(n1)));
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(n2)));
//
iFlag=BOPTools_AlgoTools::ComputeVV(aV1, aV2, myFuzzyValue);
if (myDS->HasInterf(n1, n2))
{
BOPAlgo_Tools::FillMap<Standard_Integer, TColStd_MapIntegerHasher>(n1, n2, aMILI, aAllocator);
continue;
}
// Check for SD vertices
Standard_Integer n1SD = n1;
myDS->HasShapeSD(n1, n1SD);
Standard_Integer n2SD = n2;
myDS->HasShapeSD(n2, n2SD);
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(n1SD)));
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(n2SD)));
iFlag = BOPTools_AlgoTools::ComputeVV(aV1, aV2, myFuzzyValue);
if (!iFlag) {
BOPAlgo_Tools::FillMap<Standard_Integer, TColStd_MapIntegerHasher>(n1, n2, aMILI, aAllocator);
}
}
}
//
// 2. Make blocks
BOPAlgo_Tools::MakeBlocks<Standard_Integer, TColStd_MapIntegerHasher>(aMILI, aMBlocks, aAllocator);
@ -182,11 +195,12 @@ Standard_Integer BOPAlgo_PaveFiller::MakeSDVertices
}
//
if (theAddInterfs) {
myDS->AddInterf(n1, n2);
BOPDS_InterfVV& aVV = aVVs.Appended();
//
aVV.SetIndices(n1, n2);
aVV.SetIndexNew(nV);
if (myDS->AddInterf(n1, n2))
{
BOPDS_InterfVV& aVV = aVVs.Appended();
aVV.SetIndices(n1, n2);
aVV.SetIndexNew(nV);
}
}
}
}

View File

@ -63,59 +63,40 @@ void BOPAlgo_PaveFiller::SetNonDestructive()
//purpose :
//=======================================================================
void BOPAlgo_PaveFiller::UpdateEdgeTolerance (const Standard_Integer nE,
const Standard_Real aTol)
const Standard_Real theTol)
{
Standard_Boolean bIsNewShape, bHasShapeSD;
Standard_Integer nV, nVx;
Standard_Real aTolV;
BRep_Builder aBB;
TColStd_ListIteratorOfListOfInteger aIt;
//
BOPDS_ShapeInfo& aSIE=myDS->ChangeShapeInfo(nE);
const TColStd_ListOfInteger& aLI=aSIE.SubShapes();
//
if (myNonDestructive) {
bIsNewShape=myDS->IsNewShape(nE);
if (!bIsNewShape) {
BOPDS_ShapeInfo& aSIE = myDS->ChangeShapeInfo(nE);
const TColStd_ListOfInteger& aLI = aSIE.SubShapes();
// For the safe input mode avoid modifying the input shapes
if (myNonDestructive)
{
if (!myDS->IsNewShape(nE))
return;
}
//
aIt.Initialize(aLI);
for (; aIt.More(); aIt.Next()) {
nV = aIt.Value();
bHasShapeSD=myDS->HasShapeSD(nV, nVx);
if (bHasShapeSD) {
continue;
}
bIsNewShape=myDS->IsNewShape(nV);
if (!bIsNewShape) {
TColStd_ListIteratorOfListOfInteger itLI(aLI);
for (; itLI.More(); itLI.Next())
{
Standard_Integer nV = itLI.Value(), nVSD;
if (!myDS->IsNewShape(nV) &&
!myDS->HasShapeSD(nV, nVSD))
return;
}
}
}
//
// Update edge
const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(nE);
aBB.UpdateEdge(aE, aTol);
Bnd_Box& aBoxE=aSIE.ChangeBox();
BRep_Builder().UpdateEdge(aE, theTol);
Bnd_Box& aBoxE = aSIE.ChangeBox();
BRepBndLib::Add(aE, aBoxE);
aBoxE.SetGap(aBoxE.GetGap() + Precision::Confusion());
//
aIt.Initialize(aLI);
for (; aIt.More(); aIt.Next()) {
nV = aIt.Value();
bHasShapeSD=myDS->HasShapeSD(nV, nVx);
if (bHasShapeSD) {
nV=nVx;
}
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV);
aTolV = BRep_Tool::Tolerance(aV);
if (aTolV < aTol) {
aBB.UpdateVertex(aV, aTol);
BOPDS_ShapeInfo& aSIV = myDS->ChangeShapeInfo(nV);
Bnd_Box& aBoxV = aSIV.ChangeBox();
BRepBndLib::Add(aV, aBoxV);
aBoxV.SetGap(aBoxV.GetGap() + Precision::Confusion());
}
// Update vertices
TColStd_ListIteratorOfListOfInteger itLI(aLI);
for (; itLI.More(); itLI.Next())
{
Standard_Integer nV = itLI.Value();
UpdateVertex(nV, theTol);
}
}
//=======================================================================
@ -143,6 +124,7 @@ Standard_Integer BOPAlgo_PaveFiller::UpdateVertex
Bnd_Box& aBoxV = aSIV.ChangeBox();
BRepBndLib::Add(aVSD, aBoxV);
aBoxV.SetGap(aBoxV.GetGap() + Precision::Confusion());
myIncreasedSS.Add(nV);
}
return nVNew;
}
@ -172,7 +154,13 @@ Standard_Integer BOPAlgo_PaveFiller::UpdateVertex
myDS->AddShapeSD(nV, nVNew);
//
myDS->InitPaveBlocksForVertex(nV);
//
// Add new vertex to map of vertices to avoid further extension
myVertsToAvoidExtension.Add(nVNew);
if (aTolV < aTolNew)
myIncreasedSS.Add(nV);
return nVNew;
}
//=======================================================================

View File

@ -179,6 +179,10 @@ void BOPAlgo_PaveFiller::PerformVE()
continue;
}
//
if (myDS->HasInterf(nV, nE)) {
continue;
}
//
if (myDS->HasInterfShapeSubShapes(nV, nE)) {
continue;
}

View File

@ -30,11 +30,13 @@
#include <BOPDS_PaveBlock.hxx>
#include <BOPDS_VectorOfInterfEE.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_Parallel.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <gp_Pnt.hxx>
#include <IntTools_CommonPrt.hxx>
#include <IntTools_Context.hxx>
@ -312,7 +314,7 @@ void BOPAlgo_PaveFiller::PerformEE()
continue;
}
//
Standard_Boolean bIsOnPave[4], bFlag;
Standard_Boolean bIsOnPave[4];
Standard_Integer nV[4], j;
Standard_Real aT1, aT2, aTol;
TopoDS_Vertex aVnew;
@ -343,23 +345,50 @@ void BOPAlgo_PaveFiller::PerformEE()
continue;
}
//
bFlag = Standard_False;
for (j = 0; j < 4; ++j) {
if (bIsOnPave[j]) {
//add interf VE(nV[j], nE)
Standard_Boolean isVExists = Standard_False;
for (j = 0; j < 4; ++j)
{
if (bIsOnPave[j])
{
Handle(BOPDS_PaveBlock)& aPB = (j < 2) ? aPB2 : aPB1;
bFlag = ForceInterfVE(nV[j], aPB, aMEdges);
break;
bIsOnPave[j] = ForceInterfVE(nV[j], aPB, aMEdges);
if (bIsOnPave[j]) isVExists = Standard_True;
}
}
if (bFlag) {
BOPDS_InterfEE& aEE = aEEs.Appended();
aEE.SetIndices(nE1, nE2);
aEE.SetCommonPart(aCPart);
continue;
}
//
BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
if (isVExists)
{
// The found intersection point is located closely to one of the
// pave blocks bounds. So, do not create the new vertex in this point.
// Check if this point is a real intersection point or just a touching point.
// If it is a touching point, do nothing.
// If it is an intersection point, update the existing vertex to cover the
// intersection point.
const gp_Pnt aPOnE1 = BRepAdaptor_Curve(aE1).Value(aT1);
const gp_Pnt aPOnE2 = BRepAdaptor_Curve(aE2).Value(aT2);
if (aPOnE1.Distance(aPOnE2) > Precision::Intersection())
// No intersection point
continue;
// Real intersection is present.
// Update the existing vertex to cover the intersection point.
for (j = 0; j < 4; ++j)
{
if (bIsOnPave[j])
{
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
const gp_Pnt aP = BRep_Tool::Pnt(aV);
Standard_Real aDistPP = aP.Distance(aPnew);
// Just update the vertex
UpdateVertex(nV[j], aDistPP);
myVertsToAvoidExtension.Add(nV[j]);
}
}
}
Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
if (bAnalytical) {
// increase tolerance for Line/Line intersection, but do not update
@ -375,7 +404,7 @@ void BOPAlgo_PaveFiller::PerformEE()
Standard_Integer nVS[2], iFound;
Standard_Real aTolVx, aD2, aDT2;
TColStd_MapOfInteger aMV;
gp_Pnt aPnew, aPx;
gp_Pnt aPx;
//
iFound=0;
j=-1;
@ -391,8 +420,6 @@ void BOPAlgo_PaveFiller::PerformEE()
nVS[j]=nV[3];
}
//
aPnew=BRep_Tool::Pnt(aVnew);
//
for (Standard_Integer k1=0; k1<=j; ++k1) {
const TopoDS_Vertex& aVx= *(TopoDS_Vertex*)&(myDS->Shape(nVS[k1]));
aTolVx=BRep_Tool::Tolerance(aVx);
@ -459,7 +486,10 @@ void BOPAlgo_PaveFiller::PerformEE()
//=========================================
// post treatment
//=========================================
BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS);
BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS, myContext);
// Update vertices of common blocks with real CB tolerances
UpdateVerticesOfCB();
PerformNewVertices(aMVCPB, aAllocator);
//
if (aMEdges.Extent()) {
@ -598,8 +628,11 @@ void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
thePB->Indices(nV1, nV2);
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
// Original edge
// Get the edge
Standard_Integer nE = thePB->OriginalEdge();
if (nE < 0 && !thePB->HasEdge(nE))
return;
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
// Range
Standard_Real aT1, aT2;
@ -628,7 +661,7 @@ void BOPAlgo_PaveFiller::AnalyzeShrunkData(const Handle(BOPDS_PaveBlock)& thePB,
BRep_Tool::Range(theSR.Edge(), aEFirst, aELast);
thePB->Range(aPBFirst, aPBLast);
bWholeEdge = !(aPBFirst > aEFirst || aPBLast < aELast);
if (bWholeEdge) {
if (bWholeEdge && thePB->OriginalEdge() >= 0) {
aWarnShape = theSR.Edge();
}
else {
@ -678,20 +711,20 @@ Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVE(const Standard_Integer nV,
//
const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
if (aSIE.HasSubShape(nV)) {
return Standard_False;
return Standard_True;
}
//
if (myDS->HasInterf(nV, nE)) {
return Standard_False;
return Standard_True;
}
//
if (myDS->HasInterfShapeSubShapes(nV, nE)) {
return Standard_False;
return Standard_True;
}
//
if (aPB->Pave1().Index() == nV ||
aPB->Pave2().Index() == nV) {
return Standard_False;
return Standard_True;
}
//
nVx = nV;
@ -787,6 +820,41 @@ Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
return bValid;
}
//=======================================================================
//function : UpdateVerticesOfCB
//purpose :
//=======================================================================
void BOPAlgo_PaveFiller::UpdateVerticesOfCB()
{
// Fence map to avoid checking same Common block twice
BOPDS_MapOfPaveBlock aMPBFence;
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
const Standard_Integer aNbPBP = aPBP.Length();
for (Standard_Integer i = 0; i < aNbPBP; ++i)
{
const BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPB);
for (; itPB.More(); itPB.Next())
{
const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(itPB.Value());
if (aCB.IsNull())
continue;
const Handle(BOPDS_PaveBlock)& aPBR = aCB->PaveBlock1();
if (!aMPBFence.Add(aPBR))
continue;
Standard_Real aTolCB = aCB->Tolerance();
if (aTolCB > 0.)
{
UpdateVertex(aPBR->Pave1().Index(), aTolCB);
UpdateVertex(aPBR->Pave2().Index(), aTolCB);
}
}
}
}
//=======================================================================
//function : ForceInterfEE
//purpose :
@ -794,28 +862,27 @@ Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
void BOPAlgo_PaveFiller::ForceInterfEE()
{
// Now that we have vertices increased and unified, try to find additional
// common blocks among the pairs of edges that did not participate in
// intersection (PerformEE() method) due to being rejected by bounding boxes.
// Here, we are interested in common blocks only, as all real intersections
// should have happened already. Thus, we need to look only for the same
// vertices in the pairs of pave blocks and check the coincidence of such pave blocks.
// common blocks among the pairs of edges.
// Since all real intersections should have already happened, here we
// are interested in common blocks only, thus we need to check only
// those pairs of pave blocks with the same bounding vertices.
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
// Initialize pave blocks for all SD vertices
// Initialize pave blocks for all vertices which participated in intersections
const Standard_Integer aNbS = myDS->NbSourceShapes();
for (Standard_Integer i = 0; i < aNbS; ++i)
{
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
if (aSI.ShapeType() == TopAbs_VERTEX)
{
Standard_Integer nVSD;
if (myDS->HasShapeSD(i, nVSD))
if (myDS->HasInterf(i))
myDS->InitPaveBlocksForVertex(i);
}
}
// Find all Pave Blocks with both paves being SD vertices.
// Fill the connection map from bounding vertices to pave blocks
// having those bounding vertices
NCollection_IndexedDataMap<BOPDS_Pair,
BOPDS_ListOfPaveBlock,
BOPDS_PairMapHasher> aPBMap(1, anAlloc);
@ -863,8 +930,7 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
if (!aNbPB)
return;
// Find pairs of Pave Blocks having the same SD vertices
// and put them into the vector for parallel intersection.
// Prepare pave blocks with the same vertices for intersection.
BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
for (Standard_Integer i = 1; i <= aNbPB; ++i)
@ -892,9 +958,16 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1);
const Standard_Integer nE1 = aPB1->OriginalEdge();
const Standard_Integer iR1 = myDS->Rank(nE1);
const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
Standard_Real aT11, aT12;
aPB1->Range(aT11, aT12);
BRepAdaptor_Curve aBAC1(aE1);
gp_Pnt aPm;
gp_Vec aVTgt1;
aBAC1.D1((aT11 + aT12) * 0.5, aPm, aVTgt1);
if (aVTgt1.SquareMagnitude() < gp::Resolution())
continue;
BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1;
for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
@ -902,10 +975,18 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2);
const Standard_Integer nE2 = aPB2->OriginalEdge();
const Standard_Integer iR2 = myDS->Rank(nE2);
// Make sure that the edges came from different arguments
if (myDS->Rank(nE1) == myDS->Rank(nE2))
continue;
// Check that the edges came from different arguments
if (iR1 == iR2)
{
// If the sharing of the vertices is not original, but has been acquired
// during the operation, check the coincidence of the edges even if
// they came from the same argument
if ((!myDS->IsNewShape(nV1) && (myDS->Rank(nV1) == iR1)) ||
(!myDS->IsNewShape(nV2) && (myDS->Rank(nV2) == iR2)))
continue;
}
// Check that the Pave blocks do not form the Common block already
if (!aCB1.IsNull() && !aCB2.IsNull())
@ -918,6 +999,28 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
Standard_Real aT21, aT22;
aPB2->Range(aT21, aT22);
// Check the angle between edges in the middle point.
// If the angle is more than 10 degrees, do not use the additional
// tolerance, as it may lead to undesired unification of edges
Standard_Boolean bUseAddTol = Standard_True;
{
GeomAPI_ProjectPointOnCurve& aProjPC = myContext->ProjPC(aE2);
aProjPC.Perform(aPm);
if (!aProjPC.NbPoints())
continue;
BRepAdaptor_Curve aBAC2(aE2);
gp_Pnt aPm2;
gp_Vec aVTgt2;
aBAC2.D1(aProjPC.LowerDistanceParameter(), aPm2, aVTgt2);
if (aVTgt2.SquareMagnitude() < gp::Resolution())
continue;
// The angle should be close to zero
Standard_Real aCos = aVTgt1.Dot(aVTgt2);
if (Abs(aCos) < 0.984)
bUseAddTol = Standard_False;
}
// Add pair for intersection
BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Appended();
anEdgeEdge.UseQuickCoincidenceCheck(Standard_True);
@ -925,7 +1028,10 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
anEdgeEdge.SetPaveBlock2(aPB2);
anEdgeEdge.SetEdge1(aE1, aT11, aT12);
anEdgeEdge.SetEdge2(aE2, aT21, aT22);
anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
if (bUseAddTol)
anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
else
anEdgeEdge.SetFuzzyValue(myFuzzyValue);
anEdgeEdge.SetProgressIndicator(myProgressIndicator);
}
}
@ -975,6 +1081,16 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
const Standard_Integer nE1 = aPB[0]->OriginalEdge();
const Standard_Integer nE2 = aPB[1]->OriginalEdge();
if (myDS->Rank(nE1) == myDS->Rank(nE2))
{
// Add acquired self-interference warning
TopoDS_Compound aWC;
BRep_Builder().MakeCompound(aWC);
BRep_Builder().Add(aWC, myDS->Shape(nE1));
BRep_Builder().Add(aWC, myDS->Shape(nE2));
AddWarning(new BOPAlgo_AlertAcquiredSelfIntersection(aWC));
}
BOPDS_InterfEE& aEE = aEEs.Appended();
aEE.SetIndices(nE1, nE2);
aEE.SetCommonPart(aCP);

View File

@ -184,6 +184,10 @@ void BOPAlgo_PaveFiller::PerformVF()
//
aVFs.SetIncrement(iSize);
//
// Avoid repeated intersection of the same vertex with face in case
// the group of vertices formed a single SD vertex
NCollection_DataMap<BOPDS_Pair, TColStd_MapOfInteger, BOPDS_PairMapHasher> aMVFPairs;
for (; myIterator->More(); myIterator->Next()) {
myIterator->Value(nV, nF);
//
@ -191,6 +195,10 @@ void BOPAlgo_PaveFiller::PerformVF()
continue;
}
//
if (myDS->HasInterf(nV, nF)) {
continue;
}
//
myDS->ChangeFaceInfo(nF);
if (myDS->HasInterfShapeSubShapes(nV, nF)) {
continue;
@ -201,12 +209,23 @@ void BOPAlgo_PaveFiller::PerformVF()
nVx=nVSD;
}
//
BOPDS_Pair aVFPair(nVx, nF);
TColStd_MapOfInteger* pMV = aMVFPairs.ChangeSeek(aVFPair);
if (pMV)
{
pMV->Add(nV);
continue;
}
pMV = aMVFPairs.Bound(aVFPair, TColStd_MapOfInteger());
pMV->Add(nV);
const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&myDS->Shape(nVx)));
const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF)));
//
BOPAlgo_VertexFace& aVertexFace=aVVF.Appended();
//
aVertexFace.SetIndices(nV, nF);
aVertexFace.SetIndices(nVx, nF);
aVertexFace.SetVertex(aV);
aVertexFace.SetFace(aF);
aVertexFace.SetFuzzyValue(myFuzzyValue);
@ -231,22 +250,30 @@ void BOPAlgo_PaveFiller::PerformVF()
continue;
}
//
aVertexFace.Indices(nV, nF);
aVertexFace.Indices(nVx, nF);
aVertexFace.Parameters(aT1, aT2);
// 1
BOPDS_InterfVF& aVF=aVFs.Appended();
aVF.SetIndices(nV, nF);
aVF.SetUV(aT1, aT2);
// 2
myDS->AddInterf(nV, nF);
//
// 3 update vertex V/F if necessary
Standard_Real aTolVNew = aVertexFace.VertexNewTolerance();
nVx=UpdateVertex(nV, aTolVNew);
//
// 4
if (myDS->IsNewShape(nVx)) {
aVF.SetIndexNew(nVx);
BOPDS_Pair aVFPair(nVx, nF);
const TColStd_MapOfInteger& aMV = aMVFPairs.Find(aVFPair);
TColStd_MapIteratorOfMapOfInteger itMV(aMV);
for (; itMV.More(); itMV.Next())
{
nV = itMV.Value();
// 1
BOPDS_InterfVF& aVF = aVFs.Appended();
aVF.SetIndices(nV, nF);
aVF.SetUV(aT1, aT2);
// 2
myDS->AddInterf(nV, nF);
//
// 3 update vertex V/F if necessary
nVx = UpdateVertex(nV, aTolVNew);
//
// 4
if (myDS->IsNewShape(nVx)) {
aVF.SetIndexNew(nVx);
}
}
// 5 update FaceInfo
BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);

View File

@ -30,10 +30,13 @@
#include <BOPDS_Pave.hxx>
#include <BOPDS_PaveBlock.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_BoxSelector.hxx>
#include <BOPTools_Parallel.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <gp_Pnt.hxx>
#include <IntTools_CommonPrt.hxx>
#include <IntTools_Context.hxx>
@ -41,6 +44,7 @@
#include <IntTools_Range.hxx>
#include <IntTools_SequenceOfCommonPrts.hxx>
#include <IntTools_Tools.hxx>
#include <NCollection_IncAllocator.hxx>
#include <NCollection_Vector.hxx>
#include <Precision.hxx>
#include <TColStd_MapOfInteger.hxx>
@ -251,7 +255,11 @@ void BOPAlgo_PaveFiller::PerformEF()
BOPTools_AlgoTools::CorrectRange(aE, aF, aSR, aPBRange);
aEdgeFace.SetRange (aPBRange);
aEdgeFace.SetProgressIndicator(myProgressIndicator);
//
// Save the pair to avoid their forced intersection
BOPDS_MapOfPaveBlock* pMPB = myFPBDone.ChangeSeek(nF);
if (!pMPB)
pMPB = myFPBDone.Bound(nF, BOPDS_MapOfPaveBlock());
pMPB->Add(aPB);
}//for (; aIt.More(); aIt.Next()) {
}//for (; myIterator->More(); myIterator->Next()) {
//
@ -354,72 +362,86 @@ void BOPAlgo_PaveFiller::PerformEF()
continue;
}
//
for (j=0; j<2; ++j) {
if (bIsOnPave[j]) {
bV[j]=CheckFacePaves(nV[j], aMIFOn, aMIFIn);
if (bV[j]) {
const TopoDS_Vertex& aV=
(*(TopoDS_Vertex *)(&myDS->Shape(nV[j])));
//
Standard_Real f, l, aTolVnew, aDistPP, aTolPC, aTolV;
//
const Handle(Geom_Curve)& aCur = BRep_Tool::Curve(aE, f, l);
//
gp_Pnt aP1 = BRep_Tool::Pnt(aV);
gp_Pnt aP2 = aCur->Value(aT);
//
aDistPP=aP1.Distance(aP2);
//
aTolPC=Precision::PConfusion();
aTolV=BRep_Tool::Tolerance(aV);
if (aDistPP > (aTolV+aTolPC)) {
aTolVnew=Max(aTolE, aDistPP);
UpdateVertex(nV[j], aTolVnew);
}
}
else {
for (j = 0; j < 2; ++j)
{
if (bIsOnPave[j])
{
bV[j] = CheckFacePaves(nV[j], aMIFOn, aMIFIn);
if (!bV[j])
bIsOnPave[j] = ForceInterfVF(nV[j], nF);
}
}
if (bIsOnPave[0] || bIsOnPave[1])
{
// The found intersection point is located closely to one of the pave block's
// bounds. So, do not create the new vertex in this point.
// Check if this point is a real intersection, or just a touching point.
// If it is a touching point, do nothing.
// If it is an intersection point, update the existing vertex to cover the
// intersection point.
GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
aProjPS.Perform(aPnew);
Standard_Real aMinDistEF = (aProjPS.IsDone() && aProjPS.NbPoints()) ?
aProjPS.LowerDistance() : Precision::Infinite();
Standard_Boolean hasRealIntersection = aMinDistEF < Precision::Intersection();
if (!hasRealIntersection)
// no intersection point
continue;
// Real intersection is present.
// Update the existing vertex to cover the intersection point.
for (j = 0; j < 2; ++j)
{
if (bIsOnPave[j])
{
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
const gp_Pnt aP = BRep_Tool::Pnt(aV);
Standard_Real aDistPP = aP.Distance(aPnew);
UpdateVertex(nV[j], aDistPP);
myVertsToAvoidExtension.Add(nV[j]);
}
}
continue;
}
if (CheckFacePaves(aVnew, aMIFOn)) {
continue;
}
//
if (!bIsOnPave[0] && !bIsOnPave[1]) {
if (CheckFacePaves(aVnew, aMIFOn)) {
continue;
}
//
Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
aTolVnew = Max(aTolVnew, Max(aTolE, aTolF));
BRep_Builder().UpdateVertex(aVnew, aTolVnew);
if (bLinePlane) {
// increase tolerance for Line/Plane intersection, but do not update
// the vertex till its intersection with some other shape
IntTools_Range aCR = aCPart.Range1();
aTolVnew = Max(aTolVnew, (aCR.Last() - aCR.First()) / 2.);
}
//
const gp_Pnt& aPnew = BRep_Tool::Pnt(aVnew);
//
if (!myContext->IsPointInFace(aPnew, aF, aTolVnew)) {
continue;
}
//
aMIEFC.Add(nF);
// 1
BOPDS_InterfEF& aEF=aEFs.Appended();
iX=aEFs.Length()-1;
aEF.SetIndices(nE, nF);
aEF.SetCommonPart(aCPart);
// 2
myDS->AddInterf(nE, nF);
// 3
BOPDS_CoupleOfPaveBlocks aCPB;
//
aCPB.SetPaveBlocks(aPB, aPB);
aCPB.SetIndexInterf(iX);
aCPB.SetTolerance(aTolVnew);
aMVCPB.Add(aVnew, aCPB);
Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
aTolVnew = Max(aTolVnew, Max(aTolE, aTolF));
BRep_Builder().UpdateVertex(aVnew, aTolVnew);
if (bLinePlane) {
// increase tolerance for Line/Plane intersection, but do not update
// the vertex till its intersection with some other shape
IntTools_Range aCR = aCPart.Range1();
aTolVnew = Max(aTolVnew, (aCR.Last() - aCR.First()) / 2.);
}
//
const gp_Pnt& aPnew = BRep_Tool::Pnt(aVnew);
//
if (!myContext->IsPointInFace(aPnew, aF, aTolVnew)) {
continue;
}
//
aMIEFC.Add(nF);
// 1
BOPDS_InterfEF& aEF = aEFs.Appended();
iX = aEFs.Length() - 1;
aEF.SetIndices(nE, nF);
aEF.SetCommonPart(aCPart);
// 2
myDS->AddInterf(nE, nF);
// 3
BOPDS_CoupleOfPaveBlocks aCPB;
//
aCPB.SetPaveBlocks(aPB, aPB);
aCPB.SetIndexInterf(iX);
aCPB.SetTolerance(aTolVnew);
aMVCPB.Add(aVnew, aCPB);
}
break;
case TopAbs_EDGE: {
@ -453,7 +475,8 @@ void BOPAlgo_PaveFiller::PerformEF()
//=========================================
// post treatment
//=========================================
BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, aAllocator, myDS);
BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, aAllocator, myDS, myContext);
UpdateVerticesOfCB();
PerformNewVertices(aMVCPB, aAllocator, Standard_False);
//
// Update FaceInfoIn for all faces having EF common parts
@ -662,3 +685,343 @@ void BOPAlgo_PaveFiller::ReduceIntersectionRange(const Standard_Integer theV1,
}
}
}
//=======================================================================
//function : ForceInterfEF
//purpose :
//=======================================================================
void BOPAlgo_PaveFiller::ForceInterfEF()
{
if (!myIsPrimary)
return;
// Now that we have vertices increased and unified, try to find additional
// edge/face common blocks among the pairs of edge/face.
// Here, we are interested in common blocks only, as all real intersections
// should have happened already. Thus, we need to check only those pairs
// of edge/face which have the same vertices.
// Collect all pave blocks
BOPDS_IndexedMapOfPaveBlock aMPB;
const Standard_Integer aNbS = myDS->NbSourceShapes();
for (Standard_Integer nE = 0; nE < aNbS; ++nE)
{
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nE);
if (aSI.ShapeType() != TopAbs_EDGE)
// Not an edge
continue;
if (!aSI.HasReference())
// Edge has no pave blocks
continue;
if (aSI.HasFlag())
// Degenerated edge
continue;
const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(nE);
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
for (; aItLPB.More(); aItLPB.Next())
{
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
aMPB.Add(aPBR);
}
}
// Perform intersection of collected pave blocks with faces
ForceInterfEF(aMPB, Standard_True);
}
//=======================================================================
//function : ForceInterfEF
//purpose :
//=======================================================================
void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB,
const Standard_Boolean theAddInterf)
{
if (theMPB.IsEmpty())
return;
// Fill the tree with bounding boxes of the pave blocks
NCollection_UBTree<Standard_Integer, Bnd_Box> aBBTree;
NCollection_UBTreeFiller<Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
BOPDS_IndexedMapOfPaveBlock aPBMap(1, anAlloc);
Standard_Integer aNbPB = theMPB.Extent();
for (Standard_Integer iPB = 1; iPB <= aNbPB; ++iPB)
{
Handle(BOPDS_PaveBlock) aPB = theMPB(iPB);
if (!aPB->HasShrunkData() || !myDS->IsValidShrunkData(aPB))
{
FillShrunkData(aPB);
if (!aPB->HasShrunkData())
continue;
}
Standard_Real f, l;
Bnd_Box aPBBox;
Standard_Boolean isSplit;
aPB->ShrunkData(f, l, aPBBox, isSplit);
aTreeFiller.Add(aPBMap.Add(aPB), aPBBox);
}
// Shake the tree
aTreeFiller.Fill();
// Find pairs of Face/PaveBlock containing the same vertices
// and prepare those pairs for intersection.
BOPAlgo_VectorOfEdgeFace aVEdgeFace;
const Standard_Integer aNbS = myDS->NbSourceShapes();
for (Standard_Integer nF = 0; nF < aNbS; ++nF)
{
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
if (aSI.ShapeType() != TopAbs_FACE)
// Not a face
continue;
if (!aSI.HasReference())
// Face has no face info
continue;
const Bnd_Box& aBoxF = aSI.Box();
BOPTools_BoxSelector<Bnd_Box> aSelector;
aSelector.SetBox(aBoxF);
if (!aBBTree.Select(aSelector))
continue;
const TopoDS_Face& aF = TopoDS::Face(aSI.Shape());
const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nF);
// Vertices of the face
TColStd_MapOfInteger aMVF;
const TColStd_MapOfInteger* pMVF[] = { &aFI.VerticesOn(),
&aFI.VerticesIn(),
&aFI.VerticesSc() };
for (Standard_Integer iM = 0; iM < 3; ++iM)
{
TColStd_MapIteratorOfMapOfInteger itM(*pMVF[iM]);
for (; itM.More(); itM.Next())
aMVF.Add(itM.Value());
}
// Pave Blocks of the face
const BOPDS_IndexedMapOfPaveBlock* pMPBF[] = { &aFI.PaveBlocksOn(),
&aFI.PaveBlocksIn(),
&aFI.PaveBlocksSc() };
for (Standard_Integer iM = 0; iM < 3; ++iM)
{
const Standard_Integer aNb = pMPBF[iM]->Extent();
for (Standard_Integer iPB = 1; iPB <= aNb; ++iPB)
{
const Handle(BOPDS_PaveBlock)& aPB = pMPBF[iM]->FindKey(iPB);
aMVF.Add(aPB->Pave1().Index());
aMVF.Add(aPB->Pave2().Index());
}
}
// Projection tool
GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
// Iterate on pave blocks and combine pairs containing
// the same vertices
const TColStd_ListOfInteger& aLIPB = aSelector.Indices();
TColStd_ListOfInteger::Iterator itLIPB(aLIPB);
for (; itLIPB.More(); itLIPB.Next())
{
const Handle(BOPDS_PaveBlock)& aPB = aPBMap(itLIPB.Value());
if (pMPBF[0]->Contains(aPB) ||
pMPBF[1]->Contains(aPB) ||
pMPBF[2]->Contains(aPB))
continue;
// Check if the face contains both vertices of the pave block
Standard_Integer nV1, nV2;
aPB->Indices(nV1, nV2);
if (!aMVF.Contains(nV1) || !aMVF.Contains(nV2))
// Face does not contain the vertices
continue;
// Get the edge
Standard_Integer nE;
if (!aPB->HasEdge(nE))
{
nE = aPB->OriginalEdge();
if (nE < 0)
continue;
// Make sure that the edge and face came from different arguments
if (myDS->Rank(nF) == myDS->Rank(nE))
continue;
}
const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
BRepAdaptor_Curve aBAC(aE);
// Check directions coincidence at middle point on the edge
// and projection of that point on the face.
// If the angle between tangent vector to the curve and normal
// of the face is not in the range of 80 - 100 degrees, do not use the additional
// tolerance, as it may lead to undesired unification of edge with the face.
Standard_Boolean bUseAddTol = Standard_True;
Standard_Real aTS[2];
Bnd_Box aPBBox;
Standard_Boolean isSplit;
aPB->ShrunkData(aTS[0], aTS[1], aPBBox, isSplit);
// Middle point
gp_Pnt aPOnE;
// Tangent vector in the middle point
gp_Vec aVETgt;
aBAC.D1(BOPTools_AlgoTools2D::IntermediatePoint(aTS[0], aTS[1]), aPOnE, aVETgt);
if (aVETgt.SquareMagnitude() < gp::Resolution())
continue;
aProjPS.Perform(aPOnE);
if (!aProjPS.NbPoints())
continue;
// Check the distance in the middle point, using the max vertices
// tolerance as the criteria.
const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
Standard_Real aTolCheck = 2 * Max(BRep_Tool::Tolerance(aV1),
BRep_Tool::Tolerance(aV2));
if (aProjPS.LowerDistance() > aTolCheck + myFuzzyValue)
continue;
Standard_Real U, V;
aProjPS.LowerDistanceParameters(U, V);
if (!myContext->IsPointInFace(aF, gp_Pnt2d(U, V)))
continue;
gp_Pnt aPOnS = aProjPS.NearestPoint();
gp_Vec aVFNorm(aPOnS, aPOnE);
if (aVFNorm.SquareMagnitude() > gp::Resolution())
{
// Angle between vectors should be close to 90 degrees.
// We allow deviation of 10 degrees.
Standard_Real aCos = aVFNorm.Dot(aVETgt);
if (Abs(aCos) > 0.174)
bUseAddTol = Standard_False;
}
// Compute an addition to Fuzzy value
Standard_Real aTolAdd = 0.0;
if (bUseAddTol)
{
// Compute the distance from the bounding points of the edge
// to the face and use the maximal of these distances as a
// fuzzy tolerance for the intersection.
// Use the maximal tolerance of the pave block's vertices
// as a max criteria for the computed distance.
for (Standard_Integer iP = 0; iP < 2; ++iP)
{
gp_Pnt aP = aBAC.Value(aTS[iP]);
aProjPS.Perform(aP);
if (aProjPS.NbPoints())
{
Standard_Real aDistEF = aProjPS.LowerDistance();
if (aDistEF < aTolCheck && aDistEF > aTolAdd)
aTolAdd = aDistEF;
}
}
if (aTolAdd > 0.)
{
aTolAdd -= (BRep_Tool::Tolerance(aE) + BRep_Tool::Tolerance(aF));
if (aTolAdd < 0.)
aTolAdd = 0.;
}
}
Standard_Boolean bIntersect = aTolAdd > 0;
if (!bIntersect)
{
const BOPDS_MapOfPaveBlock* pMPB = myFPBDone.Seek(nF);
bIntersect = !pMPB || !(pMPB->Contains(aPB));
}
if (bIntersect)
{
// Prepare pair for intersection
BOPAlgo_EdgeFace& aEdgeFace = aVEdgeFace.Appended();
aEdgeFace.SetIndices(nE, nF);
aEdgeFace.SetPaveBlock(aPB);
aEdgeFace.SetEdge(aE);
aEdgeFace.SetFace(aF);
aEdgeFace.SetFuzzyValue(myFuzzyValue + aTolAdd);
aEdgeFace.UseQuickCoincidenceCheck(Standard_True);
aEdgeFace.SetRange(IntTools_Range(aPB->Pave1().Parameter(), aPB->Pave2().Parameter()));
aEdgeFace.SetProgressIndicator(myProgressIndicator);
}
}
}
Standard_Integer aNbEFs = aVEdgeFace.Length();
if (!aNbEFs)
return;
aPBMap.Clear();
anAlloc->Reset();
// Perform intersection of the found pairs
BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
if (theAddInterf && aEFs.IsEmpty())
aEFs.SetIncrement(10);
// Analyze the results of intersection looking for TopAbs_EDGE
// intersection type only.
// Collect all pairs for common block creation
BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(1, anAlloc);
for (Standard_Integer i = 0; i < aNbEFs; ++i)
{
BOPAlgo_EdgeFace& anEdgeFace = aVEdgeFace(i);
if (!anEdgeFace.IsDone() || anEdgeFace.HasErrors())
{
// Warn about failed intersection of sub-shapes
AddIntersectionFailedWarning(anEdgeFace.Edge(), anEdgeFace.Face());
continue;
}
const IntTools_SequenceOfCommonPrts& aCParts = anEdgeFace.CommonParts();
if (aCParts.Length() != 1)
continue;
const IntTools_CommonPrt& aCP = aCParts(1);
if (aCP.Type() != TopAbs_EDGE)
continue;
Standard_Integer nE, nF;
anEdgeFace.Indices(nE, nF);
if (theAddInterf)
{
// Add interference
BOPDS_InterfEF& aEF = aEFs.Appended();
aEF.SetIndices(nE, nF);
aEF.SetCommonPart(aCP);
myDS->AddInterf(nE, nF);
}
const Handle(BOPDS_PaveBlock)& aPB = anEdgeFace.PaveBlock();
// Update face information with new IN pave block
myDS->ChangeFaceInfo(nF).ChangePaveBlocksIn().Add(aPB);
if (theAddInterf)
// Fill map for common blocks creation
BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, anAlloc);
}
if (aMPBLI.Extent())
// Create new common blocks for coinciding pairs
BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, anAlloc, myDS);
}

File diff suppressed because it is too large Load Diff

View File

@ -478,7 +478,7 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
aCB->SetEdge(nE);
// Compute tolerance of the common block and update the edge
Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, myDS, myContext);
myDS->UpdateEdgeTolerance(nE, aTol);
UpdateEdgeTolerance(nE, aTol);
}
}
else if (aLPB.Extent() == 1)
@ -527,10 +527,6 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
//======================================================
//
BOPDS_ShapeInfo aSI;
//
aSI.SetShapeType(TopAbs_EDGE);
//
for (k=0; k < aNbVBSE; ++k) {
BOPAlgo_SplitEdge& aBSE=aVBSE(k);
//
@ -540,13 +536,18 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
//
BOPDS_ShapeInfo aSI;
aSI.SetShapeType(TopAbs_EDGE);
aSI.SetShape(aSp);
aSI.ChangeBox()=aBox;
TColStd_ListOfInteger& aSubShapes = aSI.ChangeSubShapes();
aSubShapes.Append(aPBk->Pave1().Index());
aSubShapes.Append(aPBk->Pave2().Index());
//
nSp=myDS->Append(aSI);
//
if (!aCBk.IsNull()) {
myDS->UpdateEdgeTolerance(nSp, aBSE.Tolerance());
UpdateEdgeTolerance(nSp, aBSE.Tolerance());
aCBk->SetEdge(nSp);
}
else {
@ -644,54 +645,53 @@ void BOPAlgo_PaveFiller::MakePCurves()
continue;
}
//
Handle(BOPDS_CommonBlock) aCB=myDS->CommonBlock(aPB);
if (aCB.IsNull()) {
continue;
}
//
const BOPDS_ListOfPaveBlock& aLPB=aCB->PaveBlocks();
if (aLPB.Extent()<2) {
continue;
}
//
BOPAlgo_MPC& aMPC=aVMPC.Appended();
//
aItLPB.Initialize(aLPB);
for(; aItLPB.More(); aItLPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
if (aPBx==aPB) {
continue;
BOPAlgo_MPC& aMPC = aVMPC.Appended();
Handle(BOPDS_CommonBlock) aCB = myDS->CommonBlock(aPB);
if (!aCB.IsNull())
{
const BOPDS_ListOfPaveBlock& aLPB = aCB->PaveBlocks();
if (aLPB.Extent() >= 2)
{
aItLPB.Initialize(aLPB);
for(; aItLPB.More(); aItLPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
if (aPBx==aPB) {
continue;
}
//
nEx=aPBx->OriginalEdge();
const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx)));
bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
if (!bHasPC) {
continue;
}
//
Standard_Integer nV1x, nV2x;
Standard_Real aT1x, aT2x;
TopoDS_Vertex aV1x, aV2x;
TopoDS_Edge aEz;
//
aEz=aEx;
aEz.Orientation(TopAbs_FORWARD);
//
aPBx->Indices(nV1x, nV2x);
aPBx->Range(aT1x, aT2x);
//
aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
aV1x.Orientation(TopAbs_FORWARD);
//
aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
aV2x.Orientation(TopAbs_REVERSED);
//
aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
//
break;
}
}
//
nEx=aPBx->OriginalEdge();
const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx)));
bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
if (!bHasPC) {
continue;
}
//
Standard_Integer nV1x, nV2x;
Standard_Real aT1x, aT2x;
TopoDS_Vertex aV1x, aV2x;
TopoDS_Edge aEz;
//
aEz=aEx;
aEz.Orientation(TopAbs_FORWARD);
//
aPBx->Indices(nV1x, nV2x);
aPBx->Range(aT1x, aT2x);
//
aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
aV1x.Orientation(TopAbs_FORWARD);
//
aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
aV2x.Orientation(TopAbs_REVERSED);
//
aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
//
break;
}
//
aMPC.SetEdge(aE);
aMPC.SetFace(aF1F);
aMPC.SetProgressIndicator(myProgressIndicator);

View File

@ -112,7 +112,8 @@ void BOPAlgo_Tools::FillMap(const Handle(BOPDS_PaveBlock)& aPB,
//=======================================================================
void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& aMPBLPB,
const Handle(NCollection_BaseAllocator)& aAllocator,
BOPDS_PDS& pDS)
BOPDS_PDS& pDS,
const Handle(IntTools_Context)& theContext)
{
Standard_Integer aNbCB;
//
@ -171,6 +172,10 @@ void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPav
aCB->SetFaces(aLFaces);
for (aItLPB.Initialize(aLPB); aItLPB.More(); aItLPB.Next())
pDS->SetCommonBlock(aItLPB.Value(), aCB);
// Compute tolerance for Common Block
Standard_Real aTolCB = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, pDS, theContext);
aCB->SetTolerance(aTolCB);
}
}
//=======================================================================
@ -179,7 +184,8 @@ void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPav
//=======================================================================
void BOPAlgo_Tools::PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& aMPBLI,
const Handle(NCollection_BaseAllocator)& ,//aAllocator
BOPDS_PDS& pDS)
BOPDS_PDS& pDS,
const Handle(IntTools_Context)& theContext)
{
Standard_Integer nF, i, aNb;
TColStd_ListIteratorOfListOfInteger aItLI;
@ -216,6 +222,9 @@ void BOPAlgo_Tools::PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockLis
}
aCB->AppendFaces(aNewFaces);
pDS->SetCommonBlock(aPB, aCB);
// Compute tolerance for Common Block
Standard_Real aTolCB = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, pDS, theContext);
aCB->SetTolerance(aTolCB);
}
}
//=======================================================================
@ -253,6 +262,10 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
aPBR->Range(aT1, aT2);
aDt = (aT2 - aT1) / (aNbPnt + 1);
//
Handle(IntTools_Context) aCtx = theContext;
if (aCtx.IsNull())
aCtx = new IntTools_Context();
// compute max tolerance for common blocks on edges
if (aLPB.Extent() > 1) {
// compute max distance between edges
@ -270,7 +283,7 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
const TopoDS_Edge& aE = *(TopoDS_Edge*)&theDS->Shape(nE);
aTol = BRep_Tool::Tolerance(aE);
//
aProjPC = theContext->ProjPC(aE);
aProjPC = aCtx->ProjPC(aE);
//
aT = aT1;
for (Standard_Integer i=1; i <= aNbPnt; i++) {
@ -299,7 +312,7 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
const TopoDS_Face& aF = *(TopoDS_Face*)&theDS->Shape(nF);
aTol = BRep_Tool::Tolerance(aF);
//
aProjPS = theContext->ProjPS(aF);
aProjPS = aCtx->ProjPS(aF);
//
aT = aT1;
for (Standard_Integer i=1; i <= aNbPnt; i++) {

View File

@ -99,14 +99,19 @@ public:
const Standard_Integer theF,
BOPDS_IndexedDataMapOfPaveBlockListOfInteger& theMILI,
const Handle(NCollection_BaseAllocator)& theAllocator);
//! Create Common Blocks from the groups of pave blocks of <theMBlocks>
//! connection map.
Standard_EXPORT static void PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& theMBlocks,
const Handle(NCollection_BaseAllocator)& theAllocator,
BOPDS_PDS& theDS);
BOPDS_PDS& theDS,
const Handle(IntTools_Context)& theContext = Handle(IntTools_Context)());
//! Create Common Blocks on faces using the PB->Faces connection map <theMBlocks>.
Standard_EXPORT static void PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& theMBlocks,
const Handle(NCollection_BaseAllocator)& theAllocator,
BOPDS_PDS& pDS);
BOPDS_PDS& pDS,
const Handle(IntTools_Context)& theContext = Handle(IntTools_Context)());
Standard_EXPORT static Standard_Real ComputeToleranceOfCB
(const Handle(BOPDS_CommonBlock)& theCB,

View File

@ -23,7 +23,9 @@ IMPLEMENT_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
// function:
// purpose:
//=======================================================================
BOPDS_CommonBlock::BOPDS_CommonBlock()
BOPDS_CommonBlock::BOPDS_CommonBlock()
:
myTolerance(0.0)
{
}
//=======================================================================
@ -33,7 +35,8 @@ IMPLEMENT_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
BOPDS_CommonBlock::BOPDS_CommonBlock(const Handle(NCollection_BaseAllocator)& theAllocator)
:
myPaveBlocks(theAllocator),
myFaces(theAllocator)
myFaces(theAllocator),
myTolerance(0.0)
{
}
//=======================================================================

View File

@ -61,9 +61,7 @@ public:
//! Modifier
//! Adds the list of pave blocks <aLPB>
//! to the list of pave blocks
//! of the common block
//! Sets the list of pave blocks for the common block
Standard_EXPORT void SetPaveBlocks (const BOPDS_ListOfPaveBlock& aLPB);
@ -154,13 +152,25 @@ public:
//! It will be representative for the whole group.
Standard_EXPORT void SetRealPaveBlock(const Handle(BOPDS_PaveBlock)& thePB);
//! Sets the tolerance for the common block
void SetTolerance(const Standard_Real theTol)
{
myTolerance = theTol;
}
//! Return the tolerance of common block
Standard_Real Tolerance() const
{
return myTolerance;
}
DEFINE_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
protected:
BOPDS_ListOfPaveBlock myPaveBlocks;
TColStd_ListOfInteger myFaces;
BOPDS_ListOfPaveBlock myPaveBlocks; //!< Pave blocks of the common block
TColStd_ListOfInteger myFaces; //!< Faces on which the pave blocks are lying
Standard_Real myTolerance; //!< Tolerance of the common block
private:

View File

@ -88,7 +88,8 @@ BOPDS_DS::BOPDS_DS()
myInterfVZ(0, myAllocator),
myInterfEZ(0, myAllocator),
myInterfFZ(0, myAllocator),
myInterfZZ(0, myAllocator)
myInterfZZ(0, myAllocator),
myInterfered(100, myAllocator)
{
myNbShapes=0;
myNbSourceShapes=0;
@ -119,7 +120,8 @@ BOPDS_DS::BOPDS_DS(const Handle(NCollection_BaseAllocator)& theAllocator)
myInterfVZ(0, myAllocator),
myInterfEZ(0, myAllocator),
myInterfFZ(0, myAllocator),
myInterfZZ(0, myAllocator)
myInterfZZ(0, myAllocator),
myInterfered(100, myAllocator)
{
myNbShapes=0;
myNbSourceShapes=0;
@ -161,6 +163,7 @@ void BOPDS_DS::Clear()
myInterfEZ.Clear();
myInterfFZ.Clear();
myInterfZZ.Clear();
myInterfered.Clear();
}
//=======================================================================
//function : SetArguments
@ -678,30 +681,6 @@ void BOPDS_DS::InitShape
}
}
//=======================================================================
//function : HasInterf
//purpose :
//=======================================================================
Standard_Boolean BOPDS_DS::HasInterf(const Standard_Integer theI) const
{
Standard_Integer n1, n2;
Standard_Boolean bRet;
BOPDS_MapIteratorOfMapOfPair aIt;
//
bRet = Standard_False;
//
aIt.Initialize(myInterfTB);
for (; aIt.More(); aIt.Next()) {
const BOPDS_Pair& aPK = aIt.Value();
aPK.Indices(n1, n2);
if (n1 == theI || n2 == theI) {
bRet = Standard_True;
break;
}
}
//
return bRet;
}
//=======================================================================
//function : HasInterfShapeSubShapes
//purpose :
@ -1771,43 +1750,6 @@ void BOPDS_DS::Paves(const Standard_Integer theEdge,
}
}
//=======================================================================
// function: UpdateTolerance
// purpose:
//=======================================================================
void BOPDS_DS::UpdateEdgeTolerance(const Standard_Integer nE,
const Standard_Real aTol,
const Standard_Real theFuzz)
{
Standard_Integer nV;
Standard_Real aTolV;
BRep_Builder aBB;
TColStd_ListIteratorOfListOfInteger aIt;
//
Standard_Real aTolAdd = Max(theFuzz, Precision::Confusion()) * 0.5;
const TopoDS_Edge& aE = *(TopoDS_Edge*)&Shape(nE);
aBB.UpdateEdge(aE, aTol);
BOPDS_ShapeInfo& aSIE=ChangeShapeInfo(nE);
Bnd_Box& aBoxE=aSIE.ChangeBox();
BRepBndLib::Add(aE, aBoxE);
aBoxE.SetGap(aBoxE.GetGap() + aTolAdd);
//
const TColStd_ListOfInteger& aLI = aSIE.SubShapes();
aIt.Initialize(aLI);
for (; aIt.More(); aIt.Next()) {
nV = aIt.Value();
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&Shape(nV);
aTolV = BRep_Tool::Tolerance(aV);
if (aTolV < aTol) {
aBB.UpdateVertex(aV, aTol);
BOPDS_ShapeInfo& aSIV = ChangeShapeInfo(nV);
Bnd_Box& aBoxV = aSIV.ChangeBox();
BRepBndLib::Add(aV, aBoxV);
aBoxV.SetGap(aBoxV.GetGap() + aTolAdd);
}
}
}
//=======================================================================
//function : TotalShapes
//purpose :
//=======================================================================

View File

@ -395,27 +395,23 @@ Standard_EXPORT virtual ~BOPDS_DS();
//! Returns the number of types of the interferences
static Standard_Integer NbInterfTypes();
static Standard_Integer NbInterfTypes();
//! Modifier
//! Adds the information about an interference between
//! shapes with indices theI1, theI2 to the summary
//! table of interferences
void AddInterf (const Standard_Integer theI1, const Standard_Integer theI2);
Standard_Boolean AddInterf (const Standard_Integer theI1, const Standard_Integer theI2);
//! Query
//! Returns true if the shape with index theI
//! is interferred
Standard_EXPORT Standard_Boolean HasInterf (const Standard_Integer theI) const;
Standard_Boolean HasInterf (const Standard_Integer theI) const;
//! Query
//! Returns true if the shapes with indices theI1, theI2
//! are interferred
Standard_Boolean HasInterf (const Standard_Integer theI1, const Standard_Integer theI2) const;
Standard_Boolean HasInterf (const Standard_Integer theI1, const Standard_Integer theI2) const;
//! Query
//! Returns true if the shape with index theI1 is interfered
@ -444,12 +440,6 @@ Standard_EXPORT virtual ~BOPDS_DS();
//! Fills theLP with sorted paves
//! of the shape with index theIndex
Standard_EXPORT void Paves (const Standard_Integer theIndex, BOPDS_ListOfPave& theLP);
//! Updates tolerance of the sub-shapes of the shape with index <theIndex>.
Standard_EXPORT void UpdateEdgeTolerance (const Standard_Integer theIndex,
const Standard_Real theTolerance,
const Standard_Real theFuzz = Precision::Confusion());
//! Update the pave blocks for all shapes in data structure
Standard_EXPORT void UpdatePaveBlocksWithSDVertices();
@ -518,6 +508,7 @@ protected:
BOPDS_VectorOfInterfEZ myInterfEZ;
BOPDS_VectorOfInterfFZ myInterfFZ;
BOPDS_VectorOfInterfZZ myInterfZZ;
TColStd_MapOfInteger myInterfered;
private:

View File

@ -104,11 +104,24 @@ inline Standard_Integer BOPDS_DS::NbInterfTypes()
//function : AddInterf
//purpose :
//=======================================================================
inline void BOPDS_DS::AddInterf(const Standard_Integer theI1,
const Standard_Integer theI2)
inline Standard_Boolean BOPDS_DS::AddInterf(const Standard_Integer theI1,
const Standard_Integer theI2)
{
BOPDS_Pair aPK(theI1, theI2);
myInterfTB.Add(aPK);
if (myInterfTB.Add(BOPDS_Pair(theI1, theI2)))
{
myInterfered.Add(theI1);
myInterfered.Add(theI2);
return Standard_True;
}
return Standard_False;
}
//=======================================================================
//function : HasInterf
//purpose :
//=======================================================================
inline Standard_Boolean BOPDS_DS::HasInterf(const Standard_Integer theI) const
{
return myInterfered.Contains(theI);
}
//=======================================================================
//function : HasInterf

View File

@ -42,8 +42,8 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{
BOPDS_TSR() :
BOPTools_BoxBndTreeSelector(),
myHasBRep(Standard_False),
myTree(NULL) {
}
myTree(NULL),
myIndex(-1) {}
//
virtual ~BOPDS_TSR() {
}
@ -56,6 +56,10 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{
myTree=&aTree;
}
//
void SetIndex(const Standard_Integer theIndex) { myIndex = theIndex; }
//
Standard_Integer Index() const { return myIndex; }
//
void Perform() {
if (myHasBRep) {
myTree->Select(*this);
@ -65,6 +69,7 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{
protected:
Standard_Boolean myHasBRep;
BOPTools_BoxBndTree *myTree;
Standard_Integer myIndex;
};
//
//=======================================================================
@ -81,11 +86,12 @@ typedef BOPTools_Cnt <BOPDS_TSRFunctor, BOPDS_VectorOfTSR> BOPDS_TSRCnt;
BOPDS_Iterator::BOPDS_Iterator()
:
myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
myRunParallel(Standard_False)
myRunParallel(Standard_False),
myUseExt(Standard_False)
{
Standard_Integer i, aNb;
//
myDS=NULL;
myDS=NULL;
myLength=0;
//
aNb=BOPDS_DS::NbInterfTypes();
@ -93,6 +99,12 @@ BOPDS_Iterator::BOPDS_Iterator()
for (i=0; i<aNb; ++i) {
myLists.Appended();
}
const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
myExtLists.SetIncrement(aNbExt);
for (i = 0; i < aNbExt; ++i) {
myExtLists.Appended();
}
}
//=======================================================================
//function :
@ -103,7 +115,9 @@ BOPDS_Iterator::BOPDS_Iterator
:
myAllocator(theAllocator),
myLists(0, theAllocator),
myRunParallel(Standard_False)
myRunParallel(Standard_False),
myExtLists(0, theAllocator),
myUseExt(Standard_False)
{
Standard_Integer i, aNb;
//
@ -115,6 +129,12 @@ BOPDS_Iterator::BOPDS_Iterator
for (i=0; i<aNb; ++i) {
myLists.Appended();
}
const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
myExtLists.SetIncrement(aNbExt);
for (i = 0; i < aNbExt; ++i) {
myExtLists.Appended();
}
}
//=======================================================================
//function : ~
@ -192,12 +212,15 @@ void BOPDS_Iterator::Initialize(const TopAbs_ShapeEnum aType1,
//
myLength=0;
iX=BOPDS_Tools::TypeToInteger(aType1, aType2);
if (iX>=0) {
if (iX >= 0)
{
BOPDS_VectorOfPair& aPairs = (myUseExt && iX < BOPDS_Iterator::NbExtInterfs()) ?
myExtLists(iX) : myLists(iX);
// sort interfering pairs for constant order of intersection
std::stable_sort(myLists(iX).begin(), myLists(iX).end());
std::stable_sort(aPairs.begin(), aPairs.end());
// initialize iterator to access the pairs
myIterator.Init(myLists(iX));
myLength = myLists(iX).Length();
myIterator.Init(aPairs);
myLength = aPairs.Length();
}
}
//=======================================================================
@ -272,8 +295,8 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
Standard_Integer iTi, iTj;
TopAbs_ShapeEnum aTi, aTj;
//
BOPTools_BoxBndTree aBBTree;
NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
myBoxTree.Clear();
NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(myBoxTree);
//
aNb = myDS->NbSourceShapes();
BOPDS_VectorOfTSR aVTSR(aNb);
@ -290,8 +313,9 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
}
//
const Bnd_Box& aBoxEx=aSI.Box();
aTSR.SetTree(aBBTree);
aTSR.SetTree(myBoxTree);
aTSR.SetBox(aBoxEx);
aTSR.SetIndex(i);
//
aTreeFiller.Add(i, aBoxEx);
}
@ -366,3 +390,115 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
aVTSR.Clear();
//-----------------------------------------------------scope_1 t
}
//=======================================================================
// function: PrepareExt
// purpose:
//=======================================================================
void BOPDS_Iterator::PrepareExt(const TColStd_MapOfInteger& theIndices)
{
if (!myDS)
return;
// Update UB tree of bounding boxes with the increased shapes.
// It is expected that not too many shapes will be modified during
// the intersection, so after updating the tree it should not become
// too unbalanced.
TColStd_MapIteratorOfMapOfInteger itM(theIndices);
for (; itM.More(); itM.Next())
{
Standard_Integer nV = itM.Value();
myBoxTree.Remove(nV);
// Add with new box
Standard_Integer nVSD = nV;
myDS->HasShapeSD(nV, nVSD);
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD);
const Bnd_Box& aBox = aSI.Box();
myBoxTree.Add(nV, aBox);
}
// Clear the extra lists
const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
myLength = 0;
for (Standard_Integer i = 0; i < aNbExt; ++i)
myExtLists(i).Clear();
IntersectExt(theIndices);
myUseExt = Standard_True;
}
//=======================================================================
// function: IntersectExt
// purpose:
//=======================================================================
void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices)
{
// Prepare vector for parallel selection
BOPDS_VectorOfTSR aVTSR(theIndices.Extent());
TColStd_MapIteratorOfMapOfInteger itM(theIndices);
for (; itM.More(); itM.Next())
{
Standard_Integer nV = itM.Value();
Standard_Integer nVSD = nV;
myDS->HasShapeSD(nV, nVSD);
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD);
const Bnd_Box& aBox = aSI.Box();
BOPDS_TSR& aTSR = aVTSR.Appended();
aTSR.SetHasBRep(Standard_True);
aTSR.SetTree(myBoxTree);
aTSR.SetBox(aBox);
aTSR.SetIndex(nV);
}
// Perform selection
BOPDS_TSRCnt::Perform(myRunParallel, aVTSR);
// Treat selections
// Fence map to avoid duplicating pairs
BOPDS_MapOfPair aMPFence;
const Standard_Integer aNb = aVTSR.Length();
for (Standard_Integer k = 0; k < aNb; ++k)
{
BOPDS_TSR& aTSRi = aVTSR(k);
const TColStd_ListOfInteger& aLI = aTSRi.Indices();
if (aLI.IsEmpty())
continue;
const Standard_Integer i = aTSRi.Index();
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
const Standard_Integer iRankI = myDS->Rank(i);
const TopAbs_ShapeEnum aTI = aSI.ShapeType();
const Standard_Integer iTI = BOPDS_Tools::TypeToInteger(aTI);
TColStd_ListIteratorOfListOfInteger itLI(aLI);
for (; itLI.More(); itLI.Next())
{
const Standard_Integer j = itLI.Value(); // Index in DS
const Standard_Integer iRankJ = myDS->Rank(j);
if (iRankI == iRankJ)
continue;
const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j);
const TopAbs_ShapeEnum aTJ = aSJ.ShapeType();
const Standard_Integer iTJ = BOPDS_Tools::TypeToInteger(aTJ);
// avoid interfering of the same shapes and shape with its sub-shapes
if (((iTI < iTJ) && aSI.HasSubShape(j)) ||
((iTI > iTJ) && aSJ.HasSubShape(i)))
continue;
BOPDS_Pair aPair(i, j);
if (aMPFence.Add(aPair))
{
const Standard_Integer iX = BOPDS_Tools::TypeToInteger(aTI, aTJ);
if (iX < BOPDS_Iterator::NbExtInterfs())
myExtLists(iX).Append(aPair);
}
}
}
}

View File

@ -26,6 +26,7 @@
#include <BOPDS_PDS.hxx>
#include <BOPDS_VectorOfPair.hxx>
#include <BOPDS_VectorOfVectorOfPair.hxx>
#include <BOPTools_BoxBndTree.hxx>
#include <NCollection_BaseAllocator.hxx>
#include <Precision.hxx>
#include <Standard_Boolean.hxx>
@ -33,12 +34,11 @@
class BOPDS_DS;
class IntTools_Context;
//! The class BOPDS_Iterator is
//! 1.to compute intersections between BRep sub-shapes
//! of arguments of an operation (see the class BOPDS_DS)
//! in terms of theirs bounding boxes
//! 2.provides interface to iterare the pairs of
//! 2.provides interface to iterate the pairs of
//! intersected sub-shapes of given type
class BOPDS_Iterator
{
@ -86,6 +86,10 @@ public:
const Standard_Boolean theCheckOBB = Standard_False,
const Standard_Real theFuzzyValue = Precision::Confusion());
//! Updates the tree of Bounding Boxes with increased boxes and
//! intersects such elements with the tree.
Standard_EXPORT void PrepareExt(const TColStd_MapOfInteger& theIndicies);
//! Returns the number of intersections founded
Standard_EXPORT Standard_Integer ExpectedLength() const;
@ -100,20 +104,40 @@ public:
//! Returns the flag of parallel processing
Standard_EXPORT Standard_Boolean RunParallel() const;
protected:
public: //! @name Number of extra interfering types
// Extra lists contain only V/V, V/E, V/F interfering pairs.
// Although E/E is also initialized (but never filled) for code simplicity.
static Standard_Integer NbExtInterfs() { return 4; }
protected: //! @name Protected methods for bounding boxes intersection
//! Intersects the Bounding boxes of sub-shapes of the arguments with the tree
//! and saves the interfering pairs for further geometrical intersection.
Standard_EXPORT virtual void Intersect(const Handle(IntTools_Context)& theCtx = Handle(IntTools_Context)(),
const Standard_Boolean theCheckOBB = Standard_False,
const Standard_Real theFuzzyValue = Precision::Confusion());
Handle(NCollection_BaseAllocator) myAllocator;
Standard_Integer myLength;
BOPDS_PDS myDS;
BOPDS_VectorOfVectorOfPair myLists;
BOPDS_VectorOfPair::Iterator myIterator;
Standard_Boolean myRunParallel;
//! Intersects the bounding boxes of the shapes with given indices in DS
//! with the tree of bounding boxes and saves the interfering pairs in
//! extra lists for further geometrical intersection.
Standard_EXPORT void IntersectExt(const TColStd_MapOfInteger& theIndices);
private:
protected: //! @name Fields
Handle(NCollection_BaseAllocator) myAllocator; //!< Allocator
Standard_Integer myLength; //!< Length of the intersection vector of
//! particular intersection type
BOPDS_PDS myDS; //!< Data Structure
BOPDS_VectorOfVectorOfPair myLists; //!< Pairs with interfering bounding boxes
BOPDS_VectorOfPair::Iterator myIterator; //!< Iterator on each interfering type
Standard_Boolean myRunParallel; //!< Flag for parallel processing
BOPTools_BoxBndTree myBoxTree; //!< Unbalanced tree of bounding boxes
BOPDS_VectorOfVectorOfPair myExtLists; //!< Extra pairs of sub-shapes found after
//! intersection of increased sub-shapes
Standard_Boolean myUseExt; //!< Information flag for using the extra lists
};

View File

@ -128,7 +128,7 @@ void BOPTest::DebugCommands(Draw_Interpretor& theCommands)
__FILE__, bopindex, g);
theCommands.Add("bopsd", "Gets the Same domain shape. Use: bopsd #",
__FILE__, bopsd, g);
theCommands.Add("bopsc", "Shows the section curves. Use: bopsc [nF1 nF2]",
theCommands.Add("bopsc", "Shows the section curves. Use: bopsc [nF1 [nF2]]",
__FILE__, bopsc, g);
theCommands.Add("boppb", "Shows information about pave blocks. Use: boppb [#e]",
__FILE__, boppb, g);
@ -637,8 +637,8 @@ Standard_Integer bopsc(Draw_Interpretor& di,
Standard_Integer n,
const char** a)
{
if (n != 1 && n != 3) {
di << "Shows the section curves. Use: bopsc [nF1 nF2]\n";
if (n > 3) {
di.PrintHelp(a[0]);
return 1;
}
//
@ -658,11 +658,11 @@ Standard_Integer bopsc(Draw_Interpretor& di,
BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
//
nSF1 = nSF2 = -1;
if (n == 3) {
if (n > 1)
nSF1 = Draw::Atoi(a[1]);
if (n > 2)
nSF2 = Draw::Atoi(a[2]);
}
//
BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
//
iCnt = 0;
@ -676,6 +676,10 @@ Standard_Integer bopsc(Draw_Interpretor& di,
}
iPriz = 1;
}
else if (n == 2) {
if (!aFF.Contains(nSF1))
continue;
}
//
aFF.Indices(nF1, nF2);
//

View File

@ -760,7 +760,6 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
const Handle(IntTools_Context)& theContext)
{
Standard_Boolean bDegenerated;
Standard_Integer aNbF, iRet, iFound;
TopAbs_Orientation aOr;
TopoDS_Edge aE1;
TopExp_Explorer aExp;
@ -771,14 +770,8 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
// iRet=0; - state is not IN
// iRet=1; - state is IN
// iRet=2; - state can not be found by the method of angles
//
// For this function the returned value iRet means:
// iRet=0; - state is not IN
// iRet=1; - state is IN
//
iRet=0;
Standard_Integer iRet = 0;
// 1 Try to find an edge from theFace in theMEF
iFound=0;
aExp.Init(theFace, TopAbs_EDGE);
for(; aExp.More(); aExp.Next()) {
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
@ -786,8 +779,6 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
continue;
}
//
++iFound;
//
aOr=aE.Orientation();
if (aOr==TopAbs_INTERNAL) {
continue;
@ -798,18 +789,13 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
}
// aE
TopTools_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
aNbF=aLF.Extent();
if (!aNbF) {
return iRet != 0; // it can not be so
}
//
else if (aNbF==1) {
Standard_Integer aNbF = aLF.Extent();
if (aNbF==1) {
// aE is internal edge on aLF.First()
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
if (aE1.Orientation()!=TopAbs_INTERNAL) {
iRet=2;
break;
if (aE1.Orientation() != TopAbs_INTERNAL) {
continue;
}
//
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1,
@ -820,31 +806,14 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
else if (aNbF==2) {
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
//
if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
// treat as it was for 1 face
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
theContext);
break;
}
}
//
if (aNbF%2) {
return Standard_False; // it can not be so
}
else { // aNbF=2,4,6,8,...
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF,
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
theContext);
break;
}
}//for(; aExp.More(); aExp.Next()) {
//
if (!iFound) {
// the face has no shared edges with the solid
iRet=2;
}
//
if (iRet!=2) {
if (aExp.More() && iRet != 2)
{
return iRet == 1;
}
//

View File

@ -17,10 +17,10 @@
#include <Bnd_Box.hxx>
#include <BOPTools_BoxSelector.hxx>
#include <NCollection_UBTree.hxx>
#include <NCollection_EBTree.hxx>
#include <Standard_Integer.hxx>
typedef NCollection_UBTree<Standard_Integer, Bnd_Box> BOPTools_BoxBndTree;
typedef NCollection_EBTree<Standard_Integer, Bnd_Box> BOPTools_BoxBndTree;
typedef BOPTools_BoxSelector<Bnd_Box> BOPTools_BoxBndTreeSelector;
#endif
#endif

View File

@ -581,8 +581,8 @@ Standard_Integer IntTools_Context::ComputePE
{
gp_Pnt aPV = BRep_Tool::Pnt(aV);
aTolSum = aTolP1 + BRep_Tool::Tolerance(aV) + Precision::Confusion();
Standard_Real aDist1 = aP1.SquareDistance(aPV);
if (aDist1 < aDist && aDist1 < Square(aTolSum))
Standard_Real aDist1 = aP1.Distance(aPV);
if (aDist1 < aDist && aDist1 < aTolSum)
{
aDist = aDist1;
aT = BRep_Tool::Parameter(aV, aEFwd);

View File

@ -352,11 +352,6 @@ Standard_Boolean IntTools_EdgeFace::CheckTouch
(const IntTools_CommonPrt& aCP,
Standard_Real& aTx)
{
if (myC.GetType() == GeomAbs_Line &&
myS.GetType() == GeomAbs_Plane) {
return Standard_False;
}
//
Standard_Real aTF, aTL, Tol, U1f, U1l, V1f, V1l, af, al,aDist2, aMinDist2;
Standard_Boolean theflag=Standard_False;
Standard_Integer aNbExt, iLower;

View File

@ -425,11 +425,9 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
Standard_Real umin, umax, vmin, vmax;
//
myContext->UVBounds(myFace1, umin, umax, vmin, vmax);
CorrectPlaneBoundaries(umin, umax, vmin, vmax);
myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
//
myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
CorrectPlaneBoundaries(umin, umax, vmin, vmax);
myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
//
Standard_Real TolAng = 1.e-8;

View File

@ -34,6 +34,7 @@
myTS2=myT1;
myIsDone=Standard_False;
myIsSplittable=Standard_False;
myLength = 0.0;
}
//=======================================================================
//function : ~
@ -59,6 +60,7 @@ void IntTools_ShrunkRange::SetData(const TopoDS_Edge& aE,
myT2=aT2;
myIsDone=Standard_False;
myIsSplittable=Standard_False;
myLength = 0.0;
}
//=======================================================================
//function : SetContext
@ -178,9 +180,8 @@ void IntTools_ShrunkRange::Perform()
if (aPTolE > aPTolEMin) {
aPTolE = aPTolEMin;
}
Standard_Real anEdgeLength =
GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
if (anEdgeLength < aDTol) {
myLength = GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
if (myLength < aDTol) {
// micro edge
return;
}
@ -192,11 +193,10 @@ void IntTools_ShrunkRange::Perform()
// for the edge to have possibility to be split at least once:
// 2*TolE - minimal diameter of tolerance sphere of splitting vertex
// 2*Precision::Confusion() - minimal length of the new edges
if (anEdgeLength > (2 * aTolE + 2 * aDTol)) {
if (myLength > (2 * aTolE + 2 * aDTol)) {
myIsSplittable = Standard_True;
}
//
// build bounding box for the edge on the shrunk range
BndLib_Add3dCurve::Add(aBAC, myTS1, myTS2,
aTolE + aDTol, myBndBox);
BndLib_Add3dCurve::Add(aBAC, myTS1, myTS2, aTolE + aDTol, myBndBox);
}

View File

@ -74,6 +74,9 @@ Standard_EXPORT virtual ~IntTools_ShrunkRange();
return myIsSplittable;
}
//! Returns the length of the edge if computed.
Standard_Real Length() const { return myLength; }
protected:
TopoDS_Edge myEdge;
@ -87,6 +90,7 @@ protected:
Handle(IntTools_Context) myCtx;
Standard_Boolean myIsDone;
Standard_Boolean myIsSplittable;
Standard_Real myLength;
private:

View File

@ -1,10 +1,44 @@
# Original bug : buc60127
# Date : 18mar98
puts "TODO #22911 ALL: Error : The command is not valid. The area is 0."
restore [locate_data_file buc60127-part.rle] part
restore [locate_data_file buc60127-tool.rle] tool
# fix the part shape
explode part f
# fix inner cylinder
mksurface c_in part_1
trim c_in c_in
mkface f_in c_in 0 2*pi 0 150
# fix side faces
mksurface s1 part_3
mksurface s2 part_4
mkface f1 s1 -10 10 -10 10
mkface f2 s2 -10 10 -10 10
# fix solid
mkvolume r part_2 f_in f1 f2
# find the outher solid - the one containing the outer cylinder (part_2 face)
foreach s [explode r so] {
set found 0
foreach f [explode $s f] {
if {[regexp "same shapes" [compare part_2 $f]]} {
copy $s part
set found 1
break
}
}
if {$found} {
break
}
}
bcut result part tool
checkprops result -s 0
checkshape result
checkprops result -s 5382.41 -v 2643.38
checknbshapes result -wire 14 -face 11 -shell 1 -solid 1
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -6,5 +6,8 @@ restore [locate_data_file pro10658b.rle] b
bfuse result a b
checkprops result -s 8636.79
checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png
checkshape result
checkprops result -s 8231.06 -v 30472.5
checknbshapes result -wire 9 -face 9 -shell 1 -solid 1
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -1,9 +1,11 @@
# pro10658
puts "TODO ALL: Error : The area of result shape is"
restore [locate_data_file CTO900_pro10658a.rle] a
restore [locate_data_file pro10658b.rle] b
bfuse result a b
checkprops result -s 8231.06
checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png
checkshape result
checkprops result -s 8231.06 -v 30472.5
checknbshapes result -wire 9 -face 9 -shell 1 -solid 1
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -8,6 +8,6 @@ restore [locate_data_file ger61235b.brep] object
bsection result object tool
checkprops result -l 11.8242
checkprops result -l 16.4762
checksection result
checkview -display result -2d -otherwise { object tool } -l -path ${imagedir}/${test_image}.png

View File

@ -1,24 +1,14 @@
puts "========================"
puts "BUC60703"
puts "========================"
restore [locate_data_file buc60703e.brep] a
#maxtolerance a
checkshape a
restore [locate_data_file buc60703d.brep] b
#maxtolerance b
checkshape b
if [catch {bfuse result a b } catch_result] {
puts "Faulty BUC60703: here is problem with FUSE operation"
} else {
puts "OK OCC348: function FUSE works ok"
if [catch {checkshape result} catch_result] {
puts "Faulty BUC60703 : here is checking problem. See also OCC438: 919 D3 and D4"
} else {
puts "BUC60703 : here is NOT checking problem"
}
}
checkprops result -s 371.259
bfuse result a b
checkshape result
checkprops result -s 307.2 -v 252.773
checknbshapes result -wire 10 -face 9 -shell 1 -solid 1
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -1,5 +1,6 @@
puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
puts "TODO OCC25917 ALL: Error : is WRONG because number of "
puts "TODO OCC25917 ALL: Error : The area of result shape is "
puts "========================"
puts " OCC472 "
puts "(case 3)"

View File

@ -1,5 +1,3 @@
puts "TODO OCC27014 ALL: Error : result is WRONG because number of .* entities in shape"
puts "============"
puts "OCC26619"
puts "============"
@ -22,21 +20,9 @@ bnondestructive 1
bop h0 f0
bopsection result
checkprops result -l 142.264
checkprops result -l 150.232
set nbshapes_expected "
Number of shapes in shape
VERTEX : 46
EDGE : 46
WIRE : 0
FACE : 0
SHELL : 0
SOLID : 0
COMPSOLID : 0
COMPOUND : 1
SHAPE : 93
"
checknbshapes result -ref ${nbshapes_expected} -t -m "result"
checknbshapes result -vertex 47 -edge 47 -t -m "result"
regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance h0] full MaxTolerance2
@ -46,3 +32,7 @@ set tol_rel_MaxTolerance 0.0001
checkreal "MaxTolerance" ${MaxTolerance2} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
checkview -display result -2d -path ${imagedir}/${test_image}.png
if {[regexp "alone_1" [checksection result]]} {
puts "Error: the section is not closed"
}

View File

@ -1,5 +1,3 @@
puts "TODO OCC23660 ALL: Error: tolerance"
puts "========"
puts "OCC23660"
puts "========"
@ -11,12 +9,13 @@ puts ""
restore [locate_data_file bug23660_shell_537.brep] s
restore [locate_data_file bug23660_face_537.brep] f
bsection r s f -a
explode r
bsection result s f
smallview
donly r_9 r_10
fit
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
checkmaxtol result -min_tol 0.001
checkprops result -l 19.0858
checkmaxtol r -min_tol 0.001
if {[regexp "alone_5" [checksection result]]} {
puts "Error: section with gap"
}
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -1,6 +1,3 @@
puts "TODO OCC27049 ALL: Error : result is WRONG because number of .* entities in shape"
puts "TODO OCC27049 ALL: Error: MaxTolerance"
puts "============"
puts "OCC27049"
puts "============"
@ -23,21 +20,8 @@ tolerance f0
bop h0 f0
bopsection result
checkprops result -l 142.264
set nbshapes_expected "
Number of shapes in shape
VERTEX : 46
EDGE : 46
WIRE : 0
FACE : 0
SHELL : 0
SOLID : 0
COMPSOLID : 0
COMPOUND : 1
SHAPE : 93
"
checknbshapes result -ref ${nbshapes_expected} -t -m "result"
checkprops result -l 150.23
checknbshapes result -vertex 47 -edge 47 -t -m "result"
regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance h0] full MaxTolerance2
@ -47,3 +31,7 @@ set tol_rel_MaxTolerance 0.0001
checkreal "MaxTolerance" ${MaxTolerance2} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
checkview -display result -2d -path ${imagedir}/${test_image}.png
if {[regexp "alone_1" [checksection result]]} {
puts "Error: the section is not closed"
}

View File

@ -14,7 +14,7 @@ bfillds
bsplit result
checkshape result
checknbshapes result -wire 34 -face 34 -shell 3 -solid 3
checknbshapes result -wire 33 -face 33 -shell 3 -solid 3
checkprops result -s 26451 -v 107642
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -26,7 +26,7 @@ foreach r {r0 r1 r2 r3 r4} {
}
checknbshapes r0 -wire 6 -face 6 -shell 1 -solid 1
checkprops r0 -s 4.8 -v 0.405134
checkprops r0 -s 5.2 -v 0.42
checknbshapes r1 -wire 25 -face 25 -shell 1 -solid 1
checkprops r1 -s 45921.2 -v 6839.09
@ -37,6 +37,6 @@ checkprops r2 -s 45780.6 -v 6784.77
checknbshapes r3 -wire 10 -face 10 -shell 2 -solid 2
checkprops r3 -s 142.969 -v 39.5572
checkprops r4 -l 14.8225
checkprops r4 -l 14.2568
checkview -display r2 -2d -path ${imagedir}/${test_image}.png

View File

@ -1,7 +1,3 @@
puts "TODO OCC28393 ALL: Error : The area of result shape is"
puts "TODO OCC28393 ALL: Error : The volume of result shape is"
puts "TODO OCC28393 ALL: Error : is WRONG because number of"
puts "========"
puts "OCC28393"
puts "========"
@ -13,9 +9,15 @@ puts ""
restore [locate_data_file bug28393_o.brep] o
restore [locate_data_file bug28393_t.brep] t
# object is self-interfering shape
bopcheck o
bcut result o t
checkshape result
# the self-interfering part of the object is not affected
# by the tool, and passed into result as is
bopcheck result
checkprops result -s 70266.5 -v 979408

View File

@ -0,0 +1,33 @@
puts "========"
puts "OCC29711: General Fuse operation produces invalid result"
puts "========"
puts ""
binrestore [locate_data_file bug29711_faces.bin] cf
bclearobjects
bcleartools
eval baddobjects [explode cf f]
bfillds
bbuild gf
# check each face on self-interference
foreach f [explode gf f] {
if {![regexp "OK" [bopcheck $f]]} {
puts "Error: face $f is self-interfering"
}
}
checkshape gf
checkprops gf -s 1995.07
checknbshapes gf -wire 256 -face 256
# make volumes from the faces
mkvolume result gf -ni
checkshape result
checkprops result -s 1996.57 -v 674.739
checknbshapes result -wire 256 -face 256 -shell 12 -solid 9
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -0,0 +1,37 @@
puts "TODO CR29596 All: Intersection of pair of shapes has failed"
puts "========"
puts "OCC29900: Invalid result of FUSE operation"
puts "========"
puts ""
cpulimit 3000
brestore [locate_data_file bug29900_rotated.brep] s1
brestore [locate_data_file bug29900_sewedShape.brep] s2
bdrawwarnshapes 1
bfuzzyvalue 2.1e-5
brunparallel 1
bclearobjects
bcleartools
baddobjects s1
baddtools s2
bfillds
bbop result 1
checkshape result
checknbshapes result -wire 39 -face 39 -shell 1 -solid 1
checkprops result -s 0.0199382 -v 3.24449e-005
if {![regexp "Meshing statuses: NoError" [incmesh result 0.00001]]} {
puts "Error: Meshing not done"
}
boptions -default
smallview +Y+Z
don result
fit
checkview -screenshot -2d -path ${imagedir}/${test_image}.png

View File

@ -1,5 +1,3 @@
puts "TODO CR25432 ALL: Error : The area of result shape is"
puts "================"
puts "OCC26"
puts "================"
@ -12,5 +10,6 @@ checkshape a_2
bfuse result a_2 a_1
checkprops result -s 41539.9
checkprops result -s 41539.9 -v 348665
checknbshapes result -wire 44 -face 41 -shell 1 -solid 1
checkview -display result -2d -path ${imagedir}/${test_image}.png