mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
The following improvements have been made in Boolean operations algorithm in order to fix the problem: 1. Initialization of the pave blocks which vertices have acquired the SD ones. 2. Removing from Data Structure the small edges having the same vertices on both ends (either initially or acquired). 3. Avoid adding empty SD connections when one vertex points to itself. Test case for the issue.
3539 lines
113 KiB
C++
3539 lines
113 KiB
C++
// Created by: Peter KURNEV
|
|
// Copyright (c) 2010-2014 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_PaveFiller.hxx>
|
|
#include <Bnd_Box.hxx>
|
|
#include <BOPAlgo_Alerts.hxx>
|
|
#include <BOPAlgo_SectionAttribute.hxx>
|
|
#include <BOPAlgo_Tools.hxx>
|
|
#include <BOPDS_CommonBlock.hxx>
|
|
#include <BOPDS_CoupleOfPaveBlocks.hxx>
|
|
#include <BOPDS_Curve.hxx>
|
|
#include <BOPDS_DataMapOfPaveBlockListOfPaveBlock.hxx>
|
|
#include <BOPDS_DS.hxx>
|
|
#include <BOPDS_FaceInfo.hxx>
|
|
#include <BOPDS_Interf.hxx>
|
|
#include <BOPDS_Iterator.hxx>
|
|
#include <BOPDS_ListOfPave.hxx>
|
|
#include <BOPDS_ListOfPaveBlock.hxx>
|
|
#include <BOPDS_MapOfPaveBlock.hxx>
|
|
#include <BOPDS_PaveBlock.hxx>
|
|
#include <BOPDS_Point.hxx>
|
|
#include <BOPDS_ShapeInfo.hxx>
|
|
#include <BOPDS_VectorOfCurve.hxx>
|
|
#include <BOPDS_VectorOfPoint.hxx>
|
|
#include <BOPTools_AlgoTools.hxx>
|
|
#include <BOPTools_AlgoTools3D.hxx>
|
|
#include <BOPTools_Parallel.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_TEdge.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepAdaptor_Curve.hxx>
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
#include <BRepBndLib.hxx>
|
|
#include <BRepBuilderAPI_MakeVertex.hxx>
|
|
#include <BRepLib.hxx>
|
|
#include <BRepTools.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <GeomAPI_ProjectPointOnCurve.hxx>
|
|
#include <GeomAPI_ProjectPointOnSurf.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <IntSurf_ListOfPntOn2S.hxx>
|
|
#include <IntSurf_PntOn2S.hxx>
|
|
#include <IntTools.hxx>
|
|
#include <IntTools_Context.hxx>
|
|
#include <IntTools_Curve.hxx>
|
|
#include <IntTools_EdgeFace.hxx>
|
|
#include <IntTools_FaceFace.hxx>
|
|
#include <IntTools_PntOn2Faces.hxx>
|
|
#include <IntTools_SequenceOfCurves.hxx>
|
|
#include <IntTools_SequenceOfPntOn2Faces.hxx>
|
|
#include <IntTools_ShrunkRange.hxx>
|
|
#include <IntTools_Tools.hxx>
|
|
#include <NCollection_Vector.hxx>
|
|
#include <Precision.hxx>
|
|
#include <TColStd_ListOfInteger.hxx>
|
|
#include <TColStd_MapOfInteger.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopTools_DataMapOfShapeInteger.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
|
|
//
|
|
static Standard_Real ToleranceFF(const BRepAdaptor_Surface& aBAS1,
|
|
const BRepAdaptor_Surface& aBAS2);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//=======================================================================
|
|
//class : BOPAlgo_FaceFace
|
|
//purpose :
|
|
//=======================================================================
|
|
class BOPAlgo_FaceFace :
|
|
public IntTools_FaceFace,
|
|
public BOPAlgo_Algo {
|
|
|
|
public:
|
|
DEFINE_STANDARD_ALLOC
|
|
|
|
BOPAlgo_FaceFace() :
|
|
IntTools_FaceFace(),
|
|
BOPAlgo_Algo(),
|
|
myIF1(-1), myIF2(-1), myTolFF(1.e-7) {
|
|
}
|
|
//
|
|
virtual ~BOPAlgo_FaceFace() {
|
|
}
|
|
//
|
|
void SetIndices(const Standard_Integer nF1,
|
|
const Standard_Integer nF2) {
|
|
myIF1=nF1;
|
|
myIF2=nF2;
|
|
}
|
|
//
|
|
void Indices(Standard_Integer& nF1,
|
|
Standard_Integer& nF2) const {
|
|
nF1=myIF1;
|
|
nF2=myIF2;
|
|
}
|
|
//
|
|
void SetFaces(const TopoDS_Face& aF1,
|
|
const TopoDS_Face& aF2) {
|
|
myF1=aF1;
|
|
myF2=aF2;
|
|
}
|
|
//
|
|
const TopoDS_Face& Face1()const {
|
|
return myF1;
|
|
}
|
|
//
|
|
const TopoDS_Face& Face2()const {
|
|
return myF2;
|
|
}
|
|
//
|
|
void SetTolFF(const Standard_Real aTolFF) {
|
|
myTolFF=aTolFF;
|
|
}
|
|
//
|
|
Standard_Real TolFF() const{
|
|
return myTolFF;
|
|
}
|
|
//
|
|
void SetFuzzyValue(const Standard_Real theFuzz) {
|
|
IntTools_FaceFace::SetFuzzyValue(theFuzz);
|
|
}
|
|
//
|
|
virtual void Perform() {
|
|
BOPAlgo_Algo::UserBreak();
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
|
|
IntTools_FaceFace::Perform(myF1, myF2);
|
|
}
|
|
catch (Standard_Failure)
|
|
{
|
|
AddError(new BOPAlgo_AlertIntersectionFailed);
|
|
}
|
|
}
|
|
//
|
|
protected:
|
|
Standard_Integer myIF1;
|
|
Standard_Integer myIF2;
|
|
Standard_Real myTolFF;
|
|
TopoDS_Face myF1;
|
|
TopoDS_Face myF2;
|
|
};
|
|
//
|
|
//=======================================================================
|
|
typedef NCollection_Vector
|
|
<BOPAlgo_FaceFace> BOPAlgo_VectorOfFaceFace;
|
|
//
|
|
typedef BOPTools_Functor
|
|
<BOPAlgo_FaceFace,
|
|
BOPAlgo_VectorOfFaceFace> BOPAlgo_FaceFaceFunctor;
|
|
//
|
|
typedef BOPTools_Cnt
|
|
<BOPAlgo_FaceFaceFunctor,
|
|
BOPAlgo_VectorOfFaceFace> BOPAlgo_FaceFaceCnt;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//=======================================================================
|
|
//function : PerformFF
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PerformFF()
|
|
{
|
|
myIterator->Initialize(TopAbs_FACE, TopAbs_FACE);
|
|
Standard_Integer iSize = myIterator->ExpectedLength();
|
|
if (!iSize) {
|
|
return;
|
|
}
|
|
//
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
aFFs.SetIncrement(iSize);
|
|
//
|
|
// Options for the intersection algorithm
|
|
Standard_Boolean bApprox = mySectionAttribute.Approximation(),
|
|
bCompC2D1 = mySectionAttribute.PCurveOnS1(),
|
|
bCompC2D2 = mySectionAttribute.PCurveOnS2();
|
|
Standard_Real anApproxTol = 1.e-7;
|
|
// Post-processing options
|
|
Standard_Boolean bSplitCurve = Standard_False;
|
|
//
|
|
// Fence map to store faces with updated FaceInfo structure
|
|
TColStd_MapOfInteger aMIFence;
|
|
// Prepare the pairs of faces for intersection
|
|
BOPAlgo_VectorOfFaceFace aVFaceFace;
|
|
Standard_Integer nF1, nF2;
|
|
//
|
|
for (; myIterator->More(); myIterator->Next()) {
|
|
myIterator->Value(nF1, nF2);
|
|
|
|
// Update/Initialize FaceInfo structure for first face
|
|
if (myDS->HasFaceInfo(nF1))
|
|
{
|
|
if (aMIFence.Add(nF1))
|
|
{
|
|
myDS->UpdateFaceInfoOn(nF1);
|
|
myDS->UpdateFaceInfoIn(nF1);
|
|
}
|
|
}
|
|
else if (myDS->HasInterfShapeSubShapes(nF2, nF1))
|
|
{
|
|
myDS->ChangeFaceInfo(nF1);
|
|
aMIFence.Add(nF1);
|
|
}
|
|
|
|
// Update/Initialize FaceInfo structure for second face
|
|
if (myDS->HasFaceInfo(nF2))
|
|
{
|
|
if (aMIFence.Add(nF2))
|
|
{
|
|
myDS->UpdateFaceInfoOn(nF2);
|
|
myDS->UpdateFaceInfoIn(nF2);
|
|
}
|
|
}
|
|
else if (myDS->HasInterfShapeSubShapes(nF1, nF2))
|
|
{
|
|
myDS->ChangeFaceInfo(nF2);
|
|
aMIFence.Add(nF2);
|
|
}
|
|
//
|
|
if (myGlue == BOPAlgo_GlueOff)
|
|
{
|
|
const TopoDS_Face& aF1 = (*(TopoDS_Face *)(&myDS->Shape(nF1)));
|
|
const TopoDS_Face& aF2 = (*(TopoDS_Face *)(&myDS->Shape(nF2)));
|
|
//
|
|
const BRepAdaptor_Surface& aBAS1 = myContext->SurfaceAdaptor(aF1);
|
|
const BRepAdaptor_Surface& aBAS2 = myContext->SurfaceAdaptor(aF2);
|
|
if (aBAS1.GetType() == GeomAbs_Plane &&
|
|
aBAS2.GetType() == GeomAbs_Plane) {
|
|
// Check if the planes are really interfering
|
|
Standard_Boolean bToIntersect = CheckPlanes(nF1, nF2);
|
|
if (!bToIntersect) {
|
|
BOPDS_InterfFF& aFF = aFFs.Appended();
|
|
aFF.SetIndices(nF1, nF2);
|
|
aFF.Init(0, 0);
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
BOPAlgo_FaceFace& aFaceFace=aVFaceFace.Appended();
|
|
//
|
|
aFaceFace.SetIndices(nF1, nF2);
|
|
aFaceFace.SetFaces(aF1, aF2);
|
|
// compute minimal tolerance for the curves
|
|
Standard_Real aTolFF = ToleranceFF(aBAS1, aBAS2);
|
|
aFaceFace.SetTolFF(aTolFF);
|
|
//
|
|
IntSurf_ListOfPntOn2S aListOfPnts;
|
|
GetEFPnts(nF1, nF2, aListOfPnts);
|
|
Standard_Integer aNbLP = aListOfPnts.Extent();
|
|
if (aNbLP) {
|
|
aFaceFace.SetList(aListOfPnts);
|
|
}
|
|
//
|
|
aFaceFace.SetParameters(bApprox, bCompC2D1, bCompC2D2, anApproxTol);
|
|
aFaceFace.SetFuzzyValue(myFuzzyValue);
|
|
aFaceFace.SetProgressIndicator(myProgressIndicator);
|
|
}
|
|
else {
|
|
// for the Glue mode just add all interferences of that type
|
|
BOPDS_InterfFF& aFF = aFFs.Appended();
|
|
aFF.SetIndices(nF1, nF2);
|
|
aFF.SetTangentFaces(Standard_False);
|
|
aFF.Init(0, 0);
|
|
}
|
|
}//for (; myIterator->More(); myIterator->Next()) {
|
|
//
|
|
//======================================================
|
|
// Perform intersection
|
|
BOPAlgo_FaceFaceCnt::Perform(myRunParallel, aVFaceFace);
|
|
//======================================================
|
|
// Treatment of the results
|
|
Standard_Integer k, aNbFaceFace = aVFaceFace.Length();
|
|
for (k = 0; k < aNbFaceFace; ++k) {
|
|
BOPAlgo_FaceFace& aFaceFace = aVFaceFace(k);
|
|
aFaceFace.Indices(nF1, nF2);
|
|
if (!aFaceFace.IsDone() || aFaceFace.HasErrors()) {
|
|
BOPDS_InterfFF& aFF = aFFs.Appended();
|
|
aFF.SetIndices(nF1, nF2);
|
|
aFF.Init(0, 0);
|
|
// Warn about failed intersection of faces
|
|
AddIntersectionFailedWarning(aFaceFace.Face1(), aFaceFace.Face2());
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bTangentFaces = aFaceFace.TangentFaces();
|
|
Standard_Real aTolFF = aFaceFace.TolFF();
|
|
//
|
|
aFaceFace.PrepareLines3D(bSplitCurve);
|
|
//
|
|
const IntTools_SequenceOfCurves& aCvsX = aFaceFace.Lines();
|
|
const IntTools_SequenceOfPntOn2Faces& aPntsX = aFaceFace.Points();
|
|
//
|
|
Standard_Integer aNbCurves = aCvsX.Length();
|
|
Standard_Integer aNbPoints = aPntsX.Length();
|
|
//
|
|
if (aNbCurves || aNbPoints) {
|
|
myDS->AddInterf(nF1, nF2);
|
|
}
|
|
//
|
|
BOPDS_InterfFF& aFF = aFFs.Appended();
|
|
aFF.SetIndices(nF1, nF2);
|
|
aFF.SetTangentFaces(bTangentFaces);
|
|
aFF.Init(aNbCurves, aNbPoints);
|
|
//
|
|
// Curves
|
|
// Fix bounding box expanding coefficient.
|
|
Standard_Real aBoxExpandValue = aTolFF;
|
|
if (aNbCurves > 0)
|
|
{
|
|
// Modify geometric expanding coefficient by topology value,
|
|
// since this bounding box used in sharing (vertex or edge).
|
|
Standard_Real aMaxVertexTol = Max(BRep_Tool::MaxTolerance(aFaceFace.Face1(), TopAbs_VERTEX),
|
|
BRep_Tool::MaxTolerance(aFaceFace.Face2(), TopAbs_VERTEX));
|
|
aBoxExpandValue += aMaxVertexTol;
|
|
}
|
|
//
|
|
BOPDS_VectorOfCurve& aVNC = aFF.ChangeCurves();
|
|
for (Standard_Integer i = 1; i <= aNbCurves; ++i) {
|
|
Bnd_Box aBox;
|
|
const IntTools_Curve& aIC = aCvsX(i);
|
|
Standard_Boolean bIsValid = IntTools_Tools::CheckCurve(aIC, aBox);
|
|
if (bIsValid) {
|
|
BOPDS_Curve& aNC = aVNC.Appended();
|
|
aNC.SetCurve(aIC);
|
|
// make sure that the bounding box has the maximal gap
|
|
aBox.Enlarge(aBoxExpandValue);
|
|
aNC.SetBox(aBox);
|
|
aNC.SetTolerance(Max(aIC.Tolerance(), aTolFF));
|
|
}
|
|
}
|
|
//
|
|
// Points
|
|
BOPDS_VectorOfPoint& aVNP = aFF.ChangePoints();
|
|
for (Standard_Integer i = 1; i <= aNbPoints; ++i) {
|
|
const IntTools_PntOn2Faces& aPi = aPntsX(i);
|
|
const gp_Pnt& aP = aPi.P1().Pnt();
|
|
//
|
|
BOPDS_Point& aNP = aVNP.Appended();
|
|
aNP.SetPnt(aP);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UpdateSavedTolerance
|
|
//purpose : Updates the saved tolerance of the vertices of the edge
|
|
// with new tolerance of edge
|
|
//=======================================================================
|
|
static void UpdateSavedTolerance(const BOPDS_PDS& theDS,
|
|
const Standard_Integer theNE,
|
|
const Standard_Real theTolNew,
|
|
TColStd_DataMapOfIntegerReal& theMVTol)
|
|
{
|
|
const TColStd_ListOfInteger& aSubShapes = theDS->ShapeInfo(theNE).SubShapes();
|
|
TColStd_ListIteratorOfListOfInteger itSS(aSubShapes);
|
|
for (; itSS.More(); itSS.Next())
|
|
{
|
|
const Standard_Integer nV = itSS.Value();
|
|
Standard_Real *pTolSaved = theMVTol.ChangeSeek(nV);
|
|
if (pTolSaved && *pTolSaved < theTolNew)
|
|
*pTolSaved = theTolNew;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : MakeBlocks
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::MakeBlocks()
|
|
{
|
|
if (myGlue != BOPAlgo_GlueOff) {
|
|
return;
|
|
}
|
|
//
|
|
BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
|
|
Standard_Integer aNbFF = aFFs.Length();
|
|
if (!aNbFF) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Boolean bExist, bValid2D;
|
|
Standard_Integer i, nF1, nF2, aNbC, aNbP, j;
|
|
Standard_Integer nV1, nV2;
|
|
Standard_Real aT1, aT2;
|
|
Handle(NCollection_BaseAllocator) aAllocator;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
|
|
TopoDS_Edge aES;
|
|
Handle(BOPDS_PaveBlock) aPBOut;
|
|
//
|
|
//-----------------------------------------------------scope f
|
|
aAllocator=
|
|
NCollection_BaseAllocator::CommonBaseAllocator();
|
|
//
|
|
TColStd_ListOfInteger aLSE(aAllocator), aLBV(aAllocator);
|
|
TColStd_MapOfInteger aMVOnIn(100, aAllocator), aMVCommon(100, aAllocator),
|
|
aMVStick(100,aAllocator), aMVEF(100, aAllocator),
|
|
aMI(100, aAllocator), aMVBounds(100, aAllocator);
|
|
BOPDS_IndexedMapOfPaveBlock aMPBOnIn(100, aAllocator);
|
|
BOPDS_MapOfPaveBlock aMPBAdd(100, aAllocator), aMPBCommon;
|
|
BOPDS_ListOfPaveBlock aLPB(aAllocator);
|
|
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMSCPB(100, aAllocator);
|
|
TopTools_DataMapOfShapeInteger aMVI(100, aAllocator);
|
|
BOPDS_DataMapOfPaveBlockListOfPaveBlock aDMExEdges(100, aAllocator);
|
|
TColStd_DataMapOfIntegerReal aMVTol(100, aAllocator);
|
|
TColStd_DataMapOfIntegerInteger aDMNewSD(100, aAllocator);
|
|
TColStd_DataMapOfIntegerListOfInteger aDMVLV;
|
|
TColStd_DataMapOfIntegerListOfInteger aDMBV(100, aAllocator);
|
|
TColStd_DataMapIteratorOfDataMapOfIntegerReal aItMV;
|
|
BOPDS_IndexedMapOfPaveBlock aMicroPB(100, aAllocator);
|
|
TopTools_IndexedMapOfShape aVertsOnRejectedPB;
|
|
// Map of PaveBlocks with the faces to which it has to be added
|
|
BOPAlgo_DataMapOfPaveBlockListOfInteger aPBFacesMap;
|
|
//
|
|
for (i=0; i<aNbFF; ++i) {
|
|
//
|
|
UserBreak();
|
|
//
|
|
BOPDS_InterfFF& aFF=aFFs(i);
|
|
aFF.Indices(nF1, nF2);
|
|
//
|
|
BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
|
|
aNbP=aVP.Length();
|
|
BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
|
|
aNbC=aVC.Length();
|
|
if (!aNbP && !aNbC) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Face& aF1=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
|
|
const TopoDS_Face& aF2=(*(TopoDS_Face *)(&myDS->Shape(nF2)));
|
|
//
|
|
Standard_Real aTolFF = Max(BRep_Tool::Tolerance(aF1), BRep_Tool::Tolerance(aF2));
|
|
//
|
|
BOPDS_FaceInfo& aFI1 = myDS->ChangeFaceInfo(nF1);
|
|
BOPDS_FaceInfo& aFI2 = myDS->ChangeFaceInfo(nF2);
|
|
//
|
|
aMVOnIn.Clear();
|
|
aMVCommon.Clear();
|
|
aMPBOnIn.Clear();
|
|
aMPBCommon.Clear();
|
|
aDMBV.Clear();
|
|
aMVTol.Clear();
|
|
aLSE.Clear();
|
|
//
|
|
myDS->SubShapesOnIn(nF1, nF2, aMVOnIn, aMVCommon, aMPBOnIn, aMPBCommon);
|
|
myDS->SharedEdges(nF1, nF2, aLSE, aAllocator);
|
|
//
|
|
Standard_Boolean bHasRealSectionEdge = Standard_False;
|
|
// 1. Treat Points
|
|
for (j=0; j<aNbP; ++j) {
|
|
TopoDS_Vertex aV;
|
|
BOPDS_CoupleOfPaveBlocks aCPB;
|
|
//
|
|
BOPDS_Point& aNP=aVP.ChangeValue(j);
|
|
const gp_Pnt& aP=aNP.Pnt();
|
|
//
|
|
bExist=IsExistingVertex(aP, aTolFF, aMVOnIn);
|
|
if (!bExist) {
|
|
BOPTools_AlgoTools::MakeNewVertex(aP, aTolFF, aV);
|
|
//
|
|
aCPB.SetIndexInterf(i);
|
|
aCPB.SetIndex(j);
|
|
aMSCPB.Add(aV, aCPB);
|
|
}
|
|
}
|
|
//
|
|
// 2. Treat Curves
|
|
aMVStick.Clear();
|
|
aMVEF.Clear();
|
|
GetStickVertices(nF1, nF2, aMVStick, aMVEF, aMI);
|
|
//
|
|
for (j = 0; j < aNbC; ++j) {
|
|
BOPDS_Curve& aNC = aVC.ChangeValue(j);
|
|
// DEBt
|
|
aNC.InitPaveBlock1();
|
|
//
|
|
// In order to avoid problems connected with
|
|
// extending tolerance of vertex while putting
|
|
// (e.g. see "bugs modalg_6 bug26789_1" test case),
|
|
// all not-common vertices will be checked by
|
|
// BndBoxes before putting. For common-vertices,
|
|
// filtering by BndBoxes is not necessary.
|
|
PutPavesOnCurve(aMVOnIn, aMVCommon, aNC, aMI, aMVEF, aMVTol, aDMVLV);
|
|
}
|
|
|
|
// if some E-F vertex was put on a curve due to large E-F intersection range,
|
|
// and it also was put on another curve correctly then remove this vertex from
|
|
// the first curve. Detect such case if the distance to curve exceeds aTolR3D.
|
|
FilterPavesOnCurves(aVC, aMVTol);
|
|
|
|
for (j = 0; j<aNbC; ++j) {
|
|
BOPDS_Curve& aNC=aVC.ChangeValue(j);
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
//
|
|
PutStickPavesOnCurve(aF1, aF2, aMI, aNC, aMVStick, aMVTol, aDMVLV);
|
|
//904/F7
|
|
if (aNbC == 1) {
|
|
PutEFPavesOnCurve(aNC, aMI, aMVEF, aMVTol, aDMVLV);
|
|
}
|
|
//
|
|
if (aIC.HasBounds()) {
|
|
aLBV.Clear();
|
|
//
|
|
PutBoundPaveOnCurve(aF1, aF2, aNC, aLBV);
|
|
//
|
|
if (!aLBV.IsEmpty()) {
|
|
aDMBV.Bind(j, aLBV);
|
|
TColStd_ListIteratorOfListOfInteger aItI(aLBV);
|
|
for (; aItI.More(); aItI.Next()) {
|
|
aMVBounds.Add(aItI.Value());
|
|
}
|
|
}
|
|
}
|
|
}//for (j=0; j<aNbC; ++j) {
|
|
|
|
// Put closing pave if needed
|
|
for (j=0; j<aNbC; ++j) {
|
|
BOPDS_Curve& aNC=aVC.ChangeValue(j);
|
|
PutClosingPaveOnCurve (aNC);
|
|
}
|
|
//
|
|
// 3. Make section edges
|
|
for (j=0; j<aNbC; ++j) {
|
|
BOPDS_Curve& aNC=aVC.ChangeValue(j);
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
Standard_Real aTolR3D = Max(aNC.Tolerance(), aNC.TangentialTolerance());
|
|
//
|
|
BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
|
|
Handle(BOPDS_PaveBlock)& aPB1=aNC.ChangePaveBlock1();
|
|
//
|
|
aLPB.Clear();
|
|
aPB1->Update(aLPB, Standard_False);
|
|
//
|
|
aItLPB.Initialize(aLPB);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
Handle(BOPDS_PaveBlock)& aPB=aItLPB.ChangeValue();
|
|
aPB->Indices(nV1, nV2);
|
|
aPB->Range (aT1, aT2);
|
|
//
|
|
if (fabs(aT1 - aT2) < Precision::PConfusion()) {
|
|
continue;
|
|
}
|
|
|
|
// Check validity of the block for the faces:
|
|
// classify bounding and middle points on the curve
|
|
// relatively both faces
|
|
bValid2D=myContext->IsValidBlockForFaces(aT1, aT2, aIC,
|
|
aF1, aF2, aTolR3D);
|
|
if (!bValid2D) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Integer nEOut;
|
|
Standard_Real aTolNew;
|
|
bExist = IsExistingPaveBlock(aPB, aNC, aLSE, nEOut, aTolNew);
|
|
if (bExist)
|
|
{
|
|
// Update edge with new tolerance
|
|
UpdateEdgeTolerance(nEOut, aTolNew);
|
|
// Update aMVTol map with new tolerances of vertices
|
|
UpdateSavedTolerance(myDS, nEOut, aTolNew, aMVTol);
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
|
|
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
|
|
//
|
|
// check if the pave block has a valid range
|
|
Standard_Real aFirst, aLast;
|
|
if (!BRepLib::FindValidRange(GeomAdaptor_Curve(aIC.Curve()), aTolR3D,
|
|
aT1, BRep_Tool::Pnt(aV1), BRep_Tool::Tolerance(aV1),
|
|
aT2, BRep_Tool::Pnt(aV2), BRep_Tool::Tolerance(aV2),
|
|
aFirst, aLast))
|
|
{
|
|
// If the pave block does not have valid range, i.e. it is completely
|
|
// covered by the tolerance spheres of its vertices, it will be
|
|
// passed into post treatment process to fuse its vertices.
|
|
// The pave block itself will not be kept.
|
|
if (!aMVBounds.Contains(nV1) && !aMVBounds.Contains(nV2)) {
|
|
aMicroPB.Add(aPB);
|
|
// keep vertices for post treatment
|
|
aMVI.Bind(aV1, nV1);
|
|
aMVI.Bind(aV2, nV2);
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
bExist = IsExistingPaveBlock(aPB, aNC, aTolR3D, aMPBOnIn, aMPBCommon, aPBOut, aTolNew);
|
|
if (bExist)
|
|
{
|
|
Standard_Boolean bInF1 = (aFI1.PaveBlocksOn().Contains(aPBOut) ||
|
|
aFI1.PaveBlocksIn().Contains(aPBOut));
|
|
Standard_Boolean bInF2 = (aFI2.PaveBlocksOn().Contains(aPBOut) ||
|
|
aFI2.PaveBlocksIn().Contains(aPBOut));
|
|
if (!bInF1 || !bInF2)
|
|
{
|
|
// Update edge to touch both faces
|
|
Standard_Integer nE = aPBOut->Edge();
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(nE);
|
|
Standard_Real aTolE = BRep_Tool::Tolerance(aE);
|
|
if (aTolNew < aNC.Tolerance())
|
|
aTolNew = aNC.Tolerance(); // use real tolerance of intersection
|
|
if (aTolNew > aTolE) {
|
|
UpdateEdgeTolerance(nE, aTolNew);
|
|
// Update aMVTol map with new tolerances of vertices
|
|
UpdateSavedTolerance(myDS, nE, aTolNew, aMVTol);
|
|
}
|
|
|
|
// Face without pave block
|
|
const Standard_Integer nF = bInF1 ? nF2 : nF1;
|
|
TColStd_ListOfInteger* pFaces = aPBFacesMap.ChangeSeek(aPBOut);
|
|
if (!pFaces)
|
|
pFaces = aPBFacesMap.Bound(aPBOut, TColStd_ListOfInteger());
|
|
// List is expected to be short, so we allow the check here
|
|
if (pFaces->IsEmpty() || !pFaces->Contains(nF))
|
|
pFaces->Append(nF);
|
|
|
|
if (aMPBAdd.Add(aPBOut))
|
|
{
|
|
// Add edge for processing as the section edge
|
|
PreparePostTreatFF(i, j, aPBOut, aMSCPB, aMVI, aLPBC);
|
|
// Try fusing the vertices of the existing pave block
|
|
// with the vertices put on the real section curve (except
|
|
// for technological vertices, which will be removed)
|
|
Standard_Integer nVOut1, nVOut2;
|
|
aPBOut->Indices(nVOut1, nVOut2);
|
|
if (nV1 != nVOut1 && nV1 != nVOut2 && !aMVBounds.Contains(nV1))
|
|
{
|
|
aVertsOnRejectedPB.Add(aV1);
|
|
}
|
|
if (nV2 != nVOut1 && nV2 != nVOut2 && !aMVBounds.Contains(nV2))
|
|
{
|
|
aVertsOnRejectedPB.Add(aV2);
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
// Make Edge
|
|
BOPTools_AlgoTools::MakeEdge (aIC, aV1, aT1, aV2, aT2, aTolR3D, aES);
|
|
// Make p-curves
|
|
BOPTools_AlgoTools::MakePCurve(aES, aF1, aF2, aIC,
|
|
mySectionAttribute.PCurveOnS1(),
|
|
mySectionAttribute.PCurveOnS2(),
|
|
myContext);
|
|
//
|
|
// Append the Pave Block to the Curve j
|
|
aLPBC.Append(aPB);
|
|
//
|
|
// Keep info for post treatment
|
|
BOPDS_CoupleOfPaveBlocks aCPB;
|
|
aCPB.SetIndexInterf(i);
|
|
aCPB.SetIndex(j);
|
|
aCPB.SetPaveBlock1(aPB);
|
|
//
|
|
aMSCPB.Add(aES, aCPB);
|
|
aMVI.Bind(aV1, nV1);
|
|
aMVI.Bind(aV2, nV2);
|
|
//
|
|
aMVTol.UnBind(nV1);
|
|
aMVTol.UnBind(nV2);
|
|
//
|
|
bHasRealSectionEdge = Standard_True;
|
|
}
|
|
//
|
|
aLPBC.RemoveFirst();
|
|
}//for (j=0; j<aNbC; ++j) {
|
|
//
|
|
//back to previous tolerance values for unused vertices
|
|
//and forget about SD groups of such vertices
|
|
aItMV.Initialize(aMVTol);
|
|
for (; aItMV.More(); aItMV.Next()) {
|
|
nV1 = aItMV.Key();
|
|
Standard_Real aTol = aItMV.Value();
|
|
//
|
|
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV1);
|
|
const Handle(BRep_TVertex)& TV =
|
|
*((Handle(BRep_TVertex)*)&aV.TShape());
|
|
TV->Tolerance(aTol);
|
|
// reset bnd box
|
|
BOPDS_ShapeInfo& aSIDS=myDS->ChangeShapeInfo(nV1);
|
|
Bnd_Box& aBoxDS=aSIDS.ChangeBox();
|
|
aBoxDS = Bnd_Box();
|
|
BRepBndLib::Add(aV, aBoxDS);
|
|
aBoxDS.SetGap(aBoxDS.GetGap() + Precision::Confusion());
|
|
//
|
|
if (aDMVLV.IsBound(nV1))
|
|
aDMVLV.UnBind(nV1);
|
|
}
|
|
//
|
|
ProcessExistingPaveBlocks(i, nF1, nF2, aMPBOnIn, aDMBV, aMSCPB, aMVI, aPBFacesMap, aMPBAdd);
|
|
//
|
|
// If the pair of faces has produced any real section edges
|
|
// it is necessary to check if these edges do not intersect
|
|
// any common IN edges of the faces. For that, all such edges
|
|
// are added for Post Treatment along with sections edges.
|
|
if (bHasRealSectionEdge) {
|
|
const BOPDS_IndexedMapOfPaveBlock& aMPBIn1 = aFI1.PaveBlocksIn();
|
|
const BOPDS_IndexedMapOfPaveBlock& aMPBIn2 = aFI2.PaveBlocksIn();
|
|
//
|
|
// For simplicity add all IN edges into the first set of section curves.
|
|
// These existing edges will be removed from the set on the post treatment
|
|
// stage in the UpdateFaceInfo function.
|
|
BOPDS_ListOfPaveBlock& aLPBC = aVC.ChangeValue(0).ChangePaveBlocks();
|
|
//
|
|
Standard_Integer aNbIn1 = aMPBIn1.Extent();
|
|
for (j = 1; j <= aNbIn1; ++j) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aMPBIn1(j);
|
|
if (aMPBIn2.Contains(aPB) && aMPBAdd.Add(aPB)) {
|
|
PreparePostTreatFF(i, 0, aPB, aMSCPB, aMVI, aLPBC);
|
|
}
|
|
}
|
|
}
|
|
}//for (i=0; i<aNbFF; ++i) {
|
|
|
|
// Remove "micro" section edges
|
|
RemoveMicroSectionEdges(aMSCPB, aMicroPB);
|
|
|
|
// post treatment
|
|
MakeSDVerticesFF(aDMVLV, aDMNewSD);
|
|
PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroPB, aVertsOnRejectedPB, aAllocator);
|
|
if (HasErrors()) {
|
|
return;
|
|
}
|
|
// reduce tolerances of section edges where it is appropriate
|
|
CorrectToleranceOfSE();
|
|
//
|
|
// update face info
|
|
UpdateFaceInfo(aDMExEdges, aDMNewSD, aPBFacesMap);
|
|
//Update all pave blocks
|
|
UpdatePaveBlocks(aDMNewSD);
|
|
//
|
|
// Treat possible common zones by trying to put each section edge
|
|
// into all faces, not participated in creation of that edge, as IN edge
|
|
PutSEInOtherFaces();
|
|
//
|
|
//-----------------------------------------------------scope t
|
|
aMVStick.Clear();
|
|
aMPBOnIn.Clear();
|
|
aMVOnIn.Clear();
|
|
aMVCommon.Clear();
|
|
aDMExEdges.Clear();
|
|
aMI.Clear();
|
|
aDMNewSD.Clear();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : MakeSDVerticesFF
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::MakeSDVerticesFF
|
|
(const TColStd_DataMapOfIntegerListOfInteger& theDMVLV,
|
|
TColStd_DataMapOfIntegerInteger& theDMNewSD)
|
|
{
|
|
// Create a new SD vertex for each group of coinciding vertices
|
|
// and put new substitutions to theDMNewSD.
|
|
TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger aItG(theDMVLV);
|
|
for (; aItG.More(); aItG.Next()) {
|
|
const TColStd_ListOfInteger& aList = aItG.Value();
|
|
// make SD vertices w/o creation of interfs
|
|
Standard_Integer nSD = MakeSDVertices(aList, Standard_False);
|
|
// update theDMNewSD
|
|
TColStd_ListIteratorOfListOfInteger aItL(aList);
|
|
for (; aItL.More(); aItL.Next()) {
|
|
Standard_Integer nV = aItL.Value();
|
|
theDMNewSD.Bind(nV, nSD);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PostTreatFF
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PostTreatFF
|
|
(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
|
|
BOPDS_DataMapOfPaveBlockListOfPaveBlock& aDMExEdges,
|
|
TColStd_DataMapOfIntegerInteger& aDMNewSD,
|
|
const BOPDS_IndexedMapOfPaveBlock& theMicroPB,
|
|
const TopTools_IndexedMapOfShape& theVertsOnRejectedPB,
|
|
const Handle(NCollection_BaseAllocator)& theAllocator)
|
|
{
|
|
Standard_Integer aNbS = theMSCPB.Extent();
|
|
if (!aNbS) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Boolean bHasPaveBlocks, bOld;
|
|
Standard_Integer nSx, nVSD, iX, iP, iC, j, nV, iV = 0, iE, k;
|
|
Standard_Integer aNbLPBx;
|
|
TopAbs_ShapeEnum aType;
|
|
TopoDS_Shape aV, aE;
|
|
TopTools_ListIteratorOfListOfShape aItLS;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
|
|
BOPDS_PDS aPDS;
|
|
Handle(BOPDS_PaveBlock) aPB1;
|
|
BOPDS_Pave aPave[2];
|
|
BOPDS_ShapeInfo aSI;
|
|
//
|
|
TopTools_ListOfShape aLS(theAllocator);
|
|
BOPAlgo_PaveFiller aPF(theAllocator);
|
|
aPF.SetIsPrimary(Standard_False);
|
|
aPF.SetNonDestructive(myNonDestructive);
|
|
//
|
|
BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
|
|
Standard_Integer aNbFF = aFFs.Length();
|
|
//
|
|
|
|
//Find unused vertices
|
|
TopTools_IndexedMapOfShape VertsUnused;
|
|
TColStd_MapOfInteger IndMap;
|
|
for (Standard_Integer i = 0; i < aNbFF; i++)
|
|
{
|
|
BOPDS_InterfFF& aFF = aFFs(i);
|
|
Standard_Integer nF1, nF2;
|
|
aFF.Indices(nF1, nF2);
|
|
|
|
TColStd_MapOfInteger aMV, aMVEF, aMI;
|
|
GetStickVertices(nF1, nF2, aMV, aMVEF, aMI);
|
|
BOPDS_VectorOfCurve& aVC = aFF.ChangeCurves();
|
|
Standard_Integer aNbC = aVC.Length();
|
|
for (j = 0; j < aNbC; j++)
|
|
{
|
|
BOPDS_Curve& aNC = aVC.ChangeValue(j);
|
|
RemoveUsedVertices(aNC, aMV);
|
|
}
|
|
|
|
TColStd_MapIteratorOfMapOfInteger itmap(aMV);
|
|
for(; itmap.More(); itmap.Next())
|
|
{
|
|
Standard_Integer indV = itmap.Value();
|
|
const TopoDS_Shape& aVertex = myDS->Shape(indV);
|
|
if (IndMap.Add(indV))
|
|
VertsUnused.Add(aVertex);
|
|
else
|
|
VertsUnused.RemoveKey(aVertex);
|
|
}
|
|
}
|
|
/////////////////////
|
|
|
|
Standard_Integer aNbME = theMicroPB.Extent();
|
|
Standard_Integer aNbVOnRPB = theVertsOnRejectedPB.Extent();
|
|
// 0
|
|
if (aNbS==1 && (aNbME == 0) && (aNbVOnRPB == 0) && VertsUnused.IsEmpty()) {
|
|
const TopoDS_Shape& aS=theMSCPB.FindKey(1);
|
|
const BOPDS_CoupleOfPaveBlocks &aCPB=theMSCPB.FindFromIndex(1);
|
|
//
|
|
aType=aS.ShapeType();
|
|
if (aType==TopAbs_VERTEX) {
|
|
aSI.SetShapeType(aType);
|
|
aSI.SetShape(aS);
|
|
iV=myDS->Append(aSI);
|
|
//
|
|
iX=aCPB.IndexInterf();
|
|
iP=aCPB.Index();
|
|
BOPDS_InterfFF& aFF=aFFs(iX);
|
|
BOPDS_VectorOfPoint& aVNP=aFF.ChangePoints();
|
|
BOPDS_Point& aNP=aVNP(iP);
|
|
aNP.SetIndex(iV);
|
|
}
|
|
else if (aType==TopAbs_EDGE) {
|
|
aPB1=aCPB.PaveBlock1();
|
|
//
|
|
if (aPB1->HasEdge()) {
|
|
BOPDS_ListOfPaveBlock aLPBx;
|
|
aLPBx.Append(aPB1);
|
|
aDMExEdges.Bind(aPB1, aLPBx);
|
|
} else {
|
|
aSI.SetShapeType(aType);
|
|
aSI.SetShape(aS);
|
|
iE=myDS->Append(aSI);
|
|
//
|
|
aPB1->SetEdge(iE);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
//
|
|
// 1 prepare arguments
|
|
TopTools_MapOfShape anAddedSD;
|
|
for (k = aNbS; k > 0; --k) {
|
|
const TopoDS_Shape& aS=theMSCPB.FindKey(k);
|
|
aLS.Append(aS);
|
|
// add vertices-candidates for SD from the map aDMNewSD,
|
|
// so that they took part in fuse operation.
|
|
TopoDS_Iterator itV(aS);
|
|
for (; itV.More(); itV.Next())
|
|
{
|
|
const TopoDS_Shape& aVer = itV.Value();
|
|
Standard_Integer iVer = myDS->Index(aVer);
|
|
const Standard_Integer* pSD = aDMNewSD.Seek(iVer);
|
|
if (pSD)
|
|
{
|
|
const TopoDS_Shape& aVSD = myDS->Shape(*pSD);
|
|
if (anAddedSD.Add(aVSD))
|
|
aLS.Append(aVSD);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// The section edges considered as a micro should be
|
|
// specially treated - their vertices should be united and
|
|
// the edge itself should be removed. Thus, we add only
|
|
// its vertices into operation.
|
|
//
|
|
BRep_Builder aBB;
|
|
for (k = 1; k <= aNbME; ++k) {
|
|
Standard_Integer nVerts[2];
|
|
theMicroPB(k)->Indices(nVerts[0], nVerts[1]);
|
|
TopoDS_Vertex aVerts[2];
|
|
for (Standard_Integer i = 0; i < 2; ++i) {
|
|
const Standard_Integer* pSD = aDMNewSD.Seek(nVerts[i]);
|
|
aVerts[i] = TopoDS::Vertex(myDS->Shape(pSD ? *pSD : nVerts[i]));
|
|
if (anAddedSD.Add(aVerts[i]))
|
|
aLS.Append(aVerts[i]);
|
|
}
|
|
//
|
|
if (aVerts[0].IsSame(aVerts[1])) {
|
|
continue;
|
|
}
|
|
//
|
|
// make sure these vertices will be united
|
|
const gp_Pnt& aP1 = BRep_Tool::Pnt(aVerts[0]);
|
|
const gp_Pnt& aP2 = BRep_Tool::Pnt(aVerts[1]);
|
|
//
|
|
Standard_Real aDist = aP1.Distance(aP2);
|
|
Standard_Real aTolV1 = BRep_Tool::Tolerance(aVerts[0]);
|
|
Standard_Real aTolV2 = BRep_Tool::Tolerance(aVerts[1]);
|
|
//
|
|
aDist -= (aTolV1 + aTolV2);
|
|
if (aDist > 0.) {
|
|
aDist /= 2.;
|
|
aBB.UpdateVertex(aVerts[0], aTolV1 + aDist);
|
|
aBB.UpdateVertex(aVerts[1], aTolV2 + aDist);
|
|
}
|
|
}
|
|
|
|
// Add vertices put on the real section curves to unify them with the
|
|
// vertices of the edges, by which these sections curves have been rejected
|
|
// and with unused vertices
|
|
const TopTools_IndexedMapOfShape* VerMap [2] = {&theVertsOnRejectedPB, &VertsUnused};
|
|
for (Standard_Integer imap = 0; imap < 2; imap++)
|
|
{
|
|
Standard_Integer NbVer = VerMap[imap]->Extent();
|
|
for (Standard_Integer i = 1; i <= NbVer; ++i)
|
|
{
|
|
TopoDS_Shape aVer = VerMap[imap]->FindKey(i);
|
|
Standard_Integer iVer = myDS->Index(aVer);
|
|
const Standard_Integer* pSD = aDMNewSD.Seek(iVer);
|
|
if (pSD)
|
|
aVer = myDS->Shape(*pSD);
|
|
|
|
if (anAddedSD.Add(aVer))
|
|
aLS.Append(aVer);
|
|
}
|
|
}
|
|
//
|
|
// 2 Fuse shapes
|
|
aPF.SetProgressIndicator(myProgressIndicator);
|
|
aPF.SetRunParallel(myRunParallel);
|
|
aPF.SetArguments(aLS);
|
|
aPF.Perform();
|
|
if (aPF.HasErrors()) {
|
|
AddError (new BOPAlgo_AlertPostTreatFF);
|
|
return;
|
|
}
|
|
aPDS=aPF.PDS();
|
|
//
|
|
// Map to store the real tolerance of the common block
|
|
// and avoid repeated computation of it
|
|
NCollection_DataMap<Handle(BOPDS_CommonBlock),
|
|
Standard_Real,
|
|
TColStd_MapTransientHasher> aMCBTol;
|
|
// Map to avoid creation of different pave blocks for
|
|
// the same intersection edge
|
|
NCollection_DataMap<Standard_Integer, Handle(BOPDS_PaveBlock)> aMEPB;
|
|
//
|
|
aItLS.Initialize(aLS);
|
|
for (; aItLS.More(); aItLS.Next()) {
|
|
const TopoDS_Shape& aSx=aItLS.Value();
|
|
nSx=aPDS->Index(aSx);
|
|
const BOPDS_ShapeInfo& aSIx=aPDS->ShapeInfo(nSx);
|
|
//
|
|
aType=aSIx.ShapeType();
|
|
//
|
|
if (aType==TopAbs_VERTEX) {
|
|
Standard_Boolean bIntersectionPoint = theMSCPB.Contains(aSx);
|
|
//
|
|
if (aPDS->HasShapeSD(nSx, nVSD)) {
|
|
aV=aPDS->Shape(nVSD);
|
|
}
|
|
else {
|
|
aV=aSx;
|
|
}
|
|
// index of new vertex in theDS -> iV
|
|
iV = myDS->Index(aV);
|
|
if (iV < 0) {
|
|
aSI.SetShapeType(aType);
|
|
aSI.SetShape(aV);
|
|
iV=myDS->Append(aSI);
|
|
}
|
|
//
|
|
if (!bIntersectionPoint) {
|
|
// save SD connection
|
|
nSx = myDS->Index(aSx);
|
|
if (nSx != iV)
|
|
{
|
|
aDMNewSD.Bind(nSx, iV);
|
|
myDS->AddShapeSD(nSx, iV);
|
|
}
|
|
}
|
|
else {
|
|
// update FF interference
|
|
const BOPDS_CoupleOfPaveBlocks &aCPB=theMSCPB.FindFromKey(aSx);
|
|
iX=aCPB.IndexInterf();
|
|
iP=aCPB.Index();
|
|
BOPDS_InterfFF& aFF=aFFs(iX);
|
|
BOPDS_VectorOfPoint& aVNP=aFF.ChangePoints();
|
|
BOPDS_Point& aNP=aVNP(iP);
|
|
aNP.SetIndex(iV);
|
|
}
|
|
}//if (aType==TopAbs_VERTEX) {
|
|
//
|
|
else if (aType==TopAbs_EDGE) {
|
|
bHasPaveBlocks=aPDS->HasPaveBlocks(nSx);
|
|
const BOPDS_CoupleOfPaveBlocks &aCPB=theMSCPB.FindFromKey(aSx);
|
|
iX=aCPB.IndexInterf();
|
|
iC=aCPB.Index();
|
|
aPB1=aCPB.PaveBlock1();
|
|
//
|
|
bOld = aPB1->HasEdge();
|
|
if (bOld) {
|
|
BOPDS_ListOfPaveBlock aLPBx;
|
|
aDMExEdges.Bind(aPB1, aLPBx);
|
|
}
|
|
//
|
|
if (!bHasPaveBlocks) {
|
|
if (bOld) {
|
|
aDMExEdges.ChangeFind(aPB1).Append(aPB1);
|
|
}
|
|
else {
|
|
aSI.SetShapeType(aType);
|
|
aSI.SetShape(aSx);
|
|
iE = myDS->Append(aSI);
|
|
//
|
|
aPB1->SetEdge(iE);
|
|
}
|
|
}
|
|
else {
|
|
BOPDS_InterfFF& aFF=aFFs(iX);
|
|
BOPDS_VectorOfCurve& aVNC=aFF.ChangeCurves();
|
|
BOPDS_Curve& aNC=aVNC(iC);
|
|
BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
|
|
//
|
|
// check if edge occurred to be micro edge;
|
|
// note we check not the edge aSx itself, but its image in aPDS
|
|
const BOPDS_ListOfPaveBlock& aLPBx = aPDS->PaveBlocks(nSx);
|
|
aNbLPBx = aLPBx.Extent();
|
|
if (aNbLPBx == 0 || (aNbLPBx == 1 && !aLPBx.First()->HasShrunkData())) {
|
|
BOPDS_ListIteratorOfListOfPaveBlock it(aLPBC);
|
|
for (; it.More(); it.Next()) {
|
|
if (it.Value() == aPB1) {
|
|
aLPBC.Remove(it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// The edge became micro edge, check vertices for SD
|
|
TopoDS_Iterator itV(aSx);
|
|
for (; itV.More(); itV.Next())
|
|
aLS.Append(itV.Value());
|
|
|
|
continue;
|
|
}
|
|
//
|
|
if (bOld && !aNbLPBx) {
|
|
aDMExEdges.ChangeFind(aPB1).Append(aPB1);
|
|
continue;
|
|
}
|
|
//
|
|
if (!bOld) {
|
|
aItLPB.Initialize(aLPBC);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPBC=aItLPB.Value();
|
|
if (aPBC==aPB1) {
|
|
aLPBC.Remove(aItLPB);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aNbLPBx) {
|
|
aItLPB.Initialize(aLPBx);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
|
|
const Handle(BOPDS_PaveBlock) aPBRx=aPDS->RealPaveBlock(aPBx);
|
|
//
|
|
// update vertices of paves
|
|
aPave[0] = aPBx->Pave1();
|
|
aPave[1] = aPBx->Pave2();
|
|
for (j=0; j<2; ++j) {
|
|
nV = aPave[j].Index();
|
|
aV = aPDS->Shape(nV);
|
|
// index of new vertex in myDS -> iV
|
|
iV = myDS->Index(aV);
|
|
if (iV < 0) {
|
|
aSI.SetShapeType(TopAbs_VERTEX);
|
|
aSI.SetShape(aV);
|
|
iV = myDS->Append(aSI);
|
|
}
|
|
const BOPDS_Pave& aP1 = !j ? aPB1->Pave1() : aPB1->Pave2();
|
|
if (aP1.Index() != iV) {
|
|
if (aP1.Parameter() == aPave[j].Parameter()) {
|
|
aDMNewSD.Bind(aP1.Index(), iV);
|
|
myDS->AddShapeSD(aP1.Index(), iV);
|
|
}
|
|
else {
|
|
// check aPDS to have the SD connection between these vertices
|
|
const TopoDS_Shape& aVPave = myDS->Shape(aP1.Index());
|
|
Standard_Integer nVnewSD, nVnew = aPDS->Index(aVPave);
|
|
if (aPDS->HasShapeSD(nVnew, nVnewSD)) {
|
|
if (nVnewSD == nV) {
|
|
aDMNewSD.Bind(aP1.Index(), iV);
|
|
myDS->AddShapeSD(aP1.Index(), iV);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aPave[j].SetIndex(iV);
|
|
}
|
|
//
|
|
// add edge
|
|
aE=aPDS->Shape(aPBRx->Edge());
|
|
iE = myDS->Index(aE);
|
|
if (iE < 0) {
|
|
aSI.SetShapeType(aType);
|
|
aSI.SetShape(aE);
|
|
iE=myDS->Append(aSI);
|
|
}
|
|
//
|
|
// update real edge tolerance according to distances in common block if any
|
|
if (aPDS->IsCommonBlock(aPBRx)) {
|
|
const Handle(BOPDS_CommonBlock)& aCB = aPDS->CommonBlock(aPBRx);
|
|
Standard_Real *pTol = aMCBTol.ChangeSeek(aCB);
|
|
if (!pTol) {
|
|
Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, aPDS, aPF.Context());
|
|
pTol = aMCBTol.Bound(aCB, aTol);
|
|
}
|
|
//
|
|
if (aNC.Tolerance() < *pTol) {
|
|
aNC.SetTolerance(*pTol);
|
|
}
|
|
}
|
|
// append new PaveBlock to aLPBC
|
|
Handle(BOPDS_PaveBlock) *pPBC = aMEPB.ChangeSeek(iE);
|
|
if (!pPBC) {
|
|
pPBC = aMEPB.Bound(iE, new BOPDS_PaveBlock());
|
|
BOPDS_Pave aPaveR1, aPaveR2;
|
|
aPaveR1 = aPBRx->Pave1();
|
|
aPaveR2 = aPBRx->Pave2();
|
|
aPaveR1.SetIndex(myDS->Index(aPDS->Shape(aPaveR1.Index())));
|
|
aPaveR2.SetIndex(myDS->Index(aPDS->Shape(aPaveR2.Index())));
|
|
//
|
|
(*pPBC)->SetPave1(aPaveR1);
|
|
(*pPBC)->SetPave2(aPaveR2);
|
|
(*pPBC)->SetEdge(iE);
|
|
}
|
|
//
|
|
if (bOld) {
|
|
(*pPBC)->SetOriginalEdge(aPB1->OriginalEdge());
|
|
aDMExEdges.ChangeFind(aPB1).Append(*pPBC);
|
|
}
|
|
else {
|
|
aLPBC.Append(*pPBC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}//else if (aType==TopAbs_EDGE)
|
|
}//for (; aItLS.More(); aItLS.Next()) {
|
|
|
|
// Update SD for vertices that did not participate in operation
|
|
TColStd_DataMapOfIntegerInteger::Iterator itDM(aDMNewSD);
|
|
for (; itDM.More(); itDM.Next())
|
|
{
|
|
const Standard_Integer* pSD = aDMNewSD.Seek(itDM.Value());
|
|
if (pSD)
|
|
{
|
|
itDM.ChangeValue() = *pSD;
|
|
myDS->AddShapeSD(itDM.Key(), *pSD);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UpdateFaceInfo
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::UpdateFaceInfo
|
|
(BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME,
|
|
const TColStd_DataMapOfIntegerInteger& theDMV,
|
|
const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap)
|
|
{
|
|
Standard_Integer i, j, nV1, nF1, nF2,
|
|
aNbFF, aNbC, aNbP;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
|
|
TColStd_MapOfInteger aMF;
|
|
|
|
// Unify pave blocks of the existing edges united on the post-treat stage
|
|
NCollection_DataMap<Standard_Integer, BOPDS_ListOfPaveBlock> anEdgeLPB;
|
|
|
|
BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
|
|
aNbFF=aFFs.Length();
|
|
//1. Sections (curves, points);
|
|
for (i=0; i<aNbFF; ++i) {
|
|
BOPDS_InterfFF& aFF=aFFs(i);
|
|
aFF.Indices(nF1, nF2);
|
|
//
|
|
BOPDS_FaceInfo& aFI1=myDS->ChangeFaceInfo(nF1);
|
|
BOPDS_FaceInfo& aFI2=myDS->ChangeFaceInfo(nF2);
|
|
//
|
|
// 1.1. Section edges
|
|
BOPDS_VectorOfCurve& aVNC=aFF.ChangeCurves();
|
|
aNbC=aVNC.Length();
|
|
for (j=0; j<aNbC; ++j) {
|
|
BOPDS_Curve& aNC=aVNC(j);
|
|
BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
|
|
//
|
|
// Add section edges to face info
|
|
aItLPB.Initialize(aLPBC);
|
|
for (; aItLPB.More(); ) {
|
|
const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
|
|
//
|
|
// Treat existing pave blocks
|
|
if (theDME.IsBound(aPB)) {
|
|
BOPDS_ListOfPaveBlock& aLPB=theDME.ChangeFind(aPB);
|
|
UpdateExistingPaveBlocks(aPB, aLPB, thePBFacesMap);
|
|
|
|
BOPDS_ListIteratorOfListOfPaveBlock itLPB(aLPB);
|
|
for (; itLPB.More(); itLPB.Next())
|
|
{
|
|
const Standard_Integer nE = itLPB.Value()->Edge();
|
|
BOPDS_ListOfPaveBlock* pLPBOnE = anEdgeLPB.ChangeSeek(nE);
|
|
if (!pLPBOnE)
|
|
pLPBOnE = anEdgeLPB.Bound(nE, BOPDS_ListOfPaveBlock());
|
|
pLPBOnE->Append(itLPB.Value());
|
|
}
|
|
|
|
aLPBC.Remove(aItLPB);
|
|
continue;
|
|
}
|
|
//
|
|
aFI1.ChangePaveBlocksSc().Add(aPB);
|
|
aFI2.ChangePaveBlocksSc().Add(aPB);
|
|
// Add edge-PB connection
|
|
const Standard_Integer nE = aPB->Edge();
|
|
BOPDS_ListOfPaveBlock* pLPBOnE = anEdgeLPB.ChangeSeek(nE);
|
|
if (!pLPBOnE)
|
|
pLPBOnE = anEdgeLPB.Bound(nE, BOPDS_ListOfPaveBlock());
|
|
pLPBOnE->Append(aPB);
|
|
|
|
aItLPB.Next();
|
|
}
|
|
}
|
|
//
|
|
// 1.2. Section vertices
|
|
const BOPDS_VectorOfPoint& aVNP=aFF.Points();
|
|
aNbP=aVNP.Length();
|
|
for (j=0; j<aNbP; ++j) {
|
|
const BOPDS_Point& aNP=aVNP(j);
|
|
nV1=aNP.Index();
|
|
if (nV1<0) {
|
|
continue;
|
|
}
|
|
aFI1.ChangeVerticesSc().Add(nV1);
|
|
aFI2.ChangeVerticesSc().Add(nV1);
|
|
}
|
|
//
|
|
aMF.Add(nF1);
|
|
aMF.Add(nF2);
|
|
}
|
|
|
|
Standard_Boolean bNewCB = Standard_False;
|
|
{
|
|
// Unify pave blocks of the existing edges united on the post-treat stage
|
|
// by making new Common blocks from them
|
|
NCollection_DataMap<Standard_Integer,
|
|
BOPDS_ListOfPaveBlock>::Iterator itDM(anEdgeLPB);
|
|
for (; itDM.More(); itDM.Next())
|
|
{
|
|
const BOPDS_ListOfPaveBlock& aLPB = itDM.Value();
|
|
if (aLPB.Extent() == 1)
|
|
continue;
|
|
|
|
bNewCB = Standard_True;
|
|
|
|
// Find or create common block
|
|
Handle(BOPDS_CommonBlock) aCB;
|
|
// Collect all faces attached to common blocks
|
|
TColStd_MapOfInteger aMFaces;
|
|
// Collect all pave blocks attached to common blocks
|
|
BOPDS_IndexedMapOfPaveBlock aMPaveBlocks;
|
|
|
|
BOPDS_ListIteratorOfListOfPaveBlock itLPB(aLPB);
|
|
for (; itLPB.More(); itLPB.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = itLPB.Value();
|
|
aMPaveBlocks.Add(aPB);
|
|
|
|
if (myDS->IsCommonBlock(aPB))
|
|
{
|
|
Handle(BOPDS_CommonBlock) aPBCB = myDS->CommonBlock(aPB);
|
|
// Get pave blocks
|
|
const BOPDS_ListOfPaveBlock& aLPBOnCB = aPBCB->PaveBlocks();
|
|
for (BOPDS_ListOfPaveBlock::Iterator it(aLPBOnCB); it.More(); it.Next())
|
|
aMPaveBlocks.Add(it.Value());
|
|
|
|
// Get faces
|
|
const TColStd_ListOfInteger& aLFacesOnCB = aPBCB->Faces();
|
|
for (TColStd_ListOfInteger::Iterator it(aLFacesOnCB); it.More(); it.Next())
|
|
aMFaces.Add(it.Value());
|
|
|
|
if (aCB.IsNull())
|
|
aCB = aPBCB;
|
|
}
|
|
}
|
|
|
|
if (aCB.IsNull())
|
|
{
|
|
// None of the pave blocks in the list is a common block,
|
|
// so create the new one.
|
|
aCB = new BOPDS_CommonBlock;
|
|
aCB->SetPaveBlocks(aLPB);
|
|
itLPB.Initialize(aLPB);
|
|
for (; itLPB.More(); itLPB.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = itLPB.Value();
|
|
myDS->SetCommonBlock(aPB, aCB);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Update common block with new pave blocks
|
|
BOPDS_ListOfPaveBlock aLPBNew;
|
|
{
|
|
const Standard_Integer aNbPB = aMPaveBlocks.Extent();
|
|
for (Standard_Integer iPB = 1; iPB <= aNbPB; ++iPB)
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = aMPaveBlocks(iPB);
|
|
myDS->SetCommonBlock(aPB, aCB);
|
|
aLPBNew.Append(aPB);
|
|
}
|
|
}
|
|
aCB->SetPaveBlocks(aLPBNew);
|
|
|
|
// Update faces of the common block
|
|
TColStd_ListOfInteger aLFaces;
|
|
for (TColStd_MapOfInteger::Iterator it(aMFaces); it.More(); it.Next())
|
|
aLFaces.Append(it.Value());
|
|
aCB->SetFaces(aLFaces);
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Boolean bVerts = theDMV.Extent() > 0;
|
|
Standard_Boolean bEdges = theDME.Extent() > 0 || bNewCB;
|
|
//
|
|
if (!bVerts && !bEdges) {
|
|
return;
|
|
}
|
|
//
|
|
// 2. Update Face Info information with new vertices and new
|
|
// pave blocks created in PostTreatFF from existing ones
|
|
Standard_Integer nV2;
|
|
TColStd_MapIteratorOfMapOfInteger aItMF;
|
|
TColStd_DataMapIteratorOfDataMapOfIntegerInteger aItMV;
|
|
//
|
|
aItMF.Initialize(aMF);
|
|
for (; aItMF.More(); aItMF.Next()) {
|
|
nF1 = aItMF.Value();
|
|
//
|
|
BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(nF1);
|
|
//
|
|
// 2.1. Update information about vertices
|
|
if (bVerts)
|
|
{
|
|
TColStd_MapOfInteger& aMVOn = aFI.ChangeVerticesOn();
|
|
TColStd_MapOfInteger& aMVIn = aFI.ChangeVerticesIn();
|
|
//
|
|
aItMV.Initialize(theDMV);
|
|
for (; aItMV.More(); aItMV.Next())
|
|
{
|
|
nV1 = aItMV.Key();
|
|
nV2 = aItMV.Value();
|
|
//
|
|
if (aMVOn.Remove(nV1))
|
|
aMVOn.Add(nV2);
|
|
//
|
|
if (aMVIn.Remove(nV1))
|
|
aMVIn.Add(nV2);
|
|
} // for (; aItMV.More(); aItMV.Next()) {
|
|
} // if (bVerts) {
|
|
//
|
|
// 2.2. Update information about pave blocks
|
|
if (bEdges)
|
|
{
|
|
BOPDS_MapOfPaveBlock aMPBFence;
|
|
BOPDS_IndexedMapOfPaveBlock* pMPB[] = { &aFI.ChangePaveBlocksOn(),
|
|
&aFI.ChangePaveBlocksIn(),
|
|
&aFI.ChangePaveBlocksSc() };
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
BOPDS_IndexedMapOfPaveBlock aMPBCopy = *pMPB[i];
|
|
pMPB[i]->Clear();
|
|
const Standard_Integer aNbPB = aMPBCopy.Extent();
|
|
for (j = 1; j <= aNbPB; ++j)
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = aMPBCopy(j);
|
|
const BOPDS_ListOfPaveBlock* pLPB = theDME.Seek(aPB);
|
|
if (pLPB && !pLPB->IsEmpty())
|
|
{
|
|
aItLPB.Initialize(*pLPB);
|
|
for (; aItLPB.More(); aItLPB.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB.Value();
|
|
const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB1);
|
|
if (aMPBFence.Add(aPBR))
|
|
pMPB[i]->Add(aPBR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
|
|
if (aMPBFence.Add(aPBR))
|
|
pMPB[i]->Add(aPBR);
|
|
}
|
|
} // for (j = 1; j <= aNbPB; ++j) {
|
|
} // for (i = 0; i < 2; ++i) {
|
|
} // if (bEdges) {
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : IsExistingVertex
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::IsExistingVertex
|
|
(const gp_Pnt& aP,
|
|
const Standard_Real theTolR3D,
|
|
const TColStd_MapOfInteger& aMVOnIn)const
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Integer nV, iFlag;
|
|
Standard_Real aTolCheck;
|
|
gp_Pnt aPV;
|
|
Bnd_Box aBoxP;
|
|
TColStd_MapIteratorOfMapOfInteger aIt;
|
|
//
|
|
aTolCheck = theTolR3D + myFuzzyValue;
|
|
bRet=Standard_True;
|
|
//
|
|
aBoxP.Add(aP);
|
|
aBoxP.Enlarge(theTolR3D);
|
|
//
|
|
aIt.Initialize(aMVOnIn);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
nV=aIt.Value();
|
|
const BOPDS_ShapeInfo& aSIV=myDS->ShapeInfo(nV);
|
|
const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aSIV.Shape()));
|
|
const Bnd_Box& aBoxV=aSIV.Box();
|
|
//
|
|
if (!aBoxP.IsOut(aBoxV)) {
|
|
iFlag=BOPTools_AlgoTools::ComputeVV(aV, aP, aTolCheck);
|
|
if (!iFlag) {
|
|
return bRet;
|
|
}
|
|
}
|
|
}
|
|
return !bRet;
|
|
}
|
|
//=======================================================================
|
|
//function : IsExistingPaveBlock
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
|
|
(const Handle(BOPDS_PaveBlock)& thePB,
|
|
const BOPDS_Curve& theNC,
|
|
const TColStd_ListOfInteger& theLSE,
|
|
Standard_Integer& theNEOut,
|
|
Standard_Real& theTolNew)
|
|
{
|
|
if (theLSE.IsEmpty())
|
|
return Standard_False;
|
|
|
|
Standard_Real aT1, aT2, aTm, aTx, aTolE, aTolCheck, aTol, aDist;
|
|
Standard_Integer nE, iFlag, nV1, nV2;
|
|
gp_Pnt aPm;
|
|
Bnd_Box aBoxPm;
|
|
TColStd_ListIteratorOfListOfInteger aItLI;
|
|
//
|
|
thePB->Range(aT1, aT2);
|
|
thePB->Indices(nV1, nV2);
|
|
const TopoDS_Vertex &aV1 = TopoDS::Vertex(myDS->Shape(nV1)),
|
|
&aV2 = TopoDS::Vertex(myDS->Shape(nV2));
|
|
const Standard_Real aTolV1 = BRep_Tool::Tolerance(aV1),
|
|
aTolV2 = BRep_Tool::Tolerance(aV2);
|
|
|
|
aTol = Max(aTolV1, aTolV2);
|
|
|
|
aTm=IntTools_Tools::IntermediatePoint (aT1, aT2);
|
|
theNC.Curve().D0(aTm, aPm);
|
|
aBoxPm.Add(aPm);
|
|
aBoxPm.Enlarge(aTol);
|
|
//
|
|
aItLI.Initialize(theLSE);
|
|
for (; aItLI.More(); aItLI.Next()) {
|
|
nE=aItLI.Value();
|
|
if (nE < 0)
|
|
continue;
|
|
const BOPDS_ShapeInfo& aSIE=myDS->ChangeShapeInfo(nE);
|
|
const Bnd_Box& aBoxE=aSIE.Box();
|
|
if (!aBoxE.IsOut(aBoxPm)) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aSIE.Shape()));
|
|
aTolE = BRep_Tool::Tolerance(aE);
|
|
aTolCheck = Max(aTolE, aTol) + myFuzzyValue;
|
|
iFlag = myContext->ComputePE(aPm, aTolCheck, aE, aTx, aDist);
|
|
if (!iFlag)
|
|
{
|
|
theNEOut = nE;
|
|
theTolNew = aDist;
|
|
return Standard_True;
|
|
}
|
|
}
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsExistingPaveBlock
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
|
|
(const Handle(BOPDS_PaveBlock)& thePB,
|
|
const BOPDS_Curve& theNC,
|
|
const Standard_Real theTolR3D,
|
|
const BOPDS_IndexedMapOfPaveBlock& theMPBOnIn,
|
|
const BOPDS_MapOfPaveBlock& theMPBCommon,
|
|
Handle(BOPDS_PaveBlock)& aPBOut,
|
|
Standard_Real& theTolNew)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Real aT1, aT2, aTm, aTx, aTolCheck;
|
|
Standard_Integer nSp, iFlag1, iFlag2, nV11, nV12, nV21, nV22, i, aNbPB;
|
|
gp_Pnt aP1, aPm, aP2;
|
|
Bnd_Box aBoxP1, aBoxPm, aBoxP2, aBoxTmp;
|
|
//
|
|
bRet=Standard_False;
|
|
aTolCheck = theTolR3D + myFuzzyValue;
|
|
const IntTools_Curve& aIC=theNC.Curve();
|
|
//
|
|
thePB->Range(aT1, aT2);
|
|
thePB->Indices(nV11, nV12);
|
|
const Standard_Real aTolV11 = BRep_Tool::Tolerance(TopoDS::Vertex(myDS->Shape(nV11)));
|
|
const Standard_Real aTolV12 = BRep_Tool::Tolerance(TopoDS::Vertex(myDS->Shape(nV12)));
|
|
const Standard_Real aTolV1 = Max(aTolV11, aTolV12) + myFuzzyValue;
|
|
|
|
//first point
|
|
aIC.D0(aT1, aP1);
|
|
aBoxP1.Add(aP1);
|
|
aBoxP1.Enlarge(aTolV11);
|
|
//intermediate point
|
|
aTm=IntTools_Tools::IntermediatePoint (aT1, aT2);
|
|
aIC.D0(aTm, aPm);
|
|
aBoxPm.Add(aPm);
|
|
//last point
|
|
aIC.D0(aT2, aP2);
|
|
aBoxP2.Add(aP2);
|
|
aBoxP2.Enlarge(aTolV12);
|
|
//
|
|
// Look for the existing pave block closest to the section curve
|
|
theTolNew = ::RealLast();
|
|
|
|
aNbPB = theMPBOnIn.Extent();
|
|
for (i = 1; i <= aNbPB; ++i) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = theMPBOnIn(i);
|
|
aPB->Indices(nV21, nV22);
|
|
const Standard_Real aTolV21 = BRep_Tool::Tolerance(TopoDS::Vertex(myDS->Shape(nV21)));
|
|
const Standard_Real aTolV22 = BRep_Tool::Tolerance(TopoDS::Vertex(myDS->Shape(nV22)));
|
|
const Standard_Real aTolV2 = Max(aTolV21, aTolV22) + myFuzzyValue;
|
|
nSp=aPB->Edge();
|
|
if (nSp < 0)
|
|
continue;
|
|
const BOPDS_ShapeInfo& aSISp=myDS->ChangeShapeInfo(nSp);
|
|
const TopoDS_Edge& aSp=(*(TopoDS_Edge *)(&aSISp.Shape()));
|
|
const Bnd_Box& aBoxSp=aSISp.Box();
|
|
//
|
|
iFlag1 = (nV11 == nV21 || nV11 == nV22) ? 2 :
|
|
(!aBoxSp.IsOut(aBoxP1) ? 1 : 0);
|
|
iFlag2 = (nV12 == nV21 || nV12 == nV22) ? 2 :
|
|
(!aBoxSp.IsOut(aBoxP2) ? 1 : 0);
|
|
if (iFlag1 && iFlag2) {
|
|
Standard_Real aDist = 0.;
|
|
|
|
Standard_Real aRealTol = aTolCheck;
|
|
if (myDS->IsCommonBlock(aPB))
|
|
{
|
|
aRealTol = Max(aRealTol, Max(aTolV1, aTolV2));
|
|
if (theMPBCommon.Contains(aPB))
|
|
// for an edge, which is a common block with a face,
|
|
// increase the chance to coincide with section curve
|
|
aRealTol *= 2.;
|
|
}
|
|
|
|
aBoxTmp = aBoxPm;
|
|
aBoxTmp.Enlarge(aRealTol);
|
|
|
|
Standard_Real aDistToSp = 0.;
|
|
if (aBoxSp.IsOut(aBoxTmp) || myContext->ComputePE(aPm,
|
|
aRealTol,
|
|
aSp,
|
|
aTx, aDistToSp)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (iFlag1 == 1) {
|
|
iFlag1 = !myContext->ComputePE(aP1, aRealTol, aSp, aTx, aDist);
|
|
if (iFlag1 && aDistToSp < aDist)
|
|
aDistToSp = aDist;
|
|
}
|
|
//
|
|
if (iFlag2 == 1) {
|
|
iFlag2 = !myContext->ComputePE(aP2, aRealTol, aSp, aTx, aDist);
|
|
if (iFlag2 && aDistToSp < aDist)
|
|
aDistToSp = aDist;
|
|
}
|
|
//
|
|
if (iFlag1 && iFlag2)
|
|
{
|
|
if (aDistToSp < theTolNew)
|
|
{
|
|
aPBOut = aPB;
|
|
theTolNew = aDistToSp;
|
|
bRet = Standard_True;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose :
|
|
//=======================================================================
|
|
static void getBoundPaves(const BOPDS_DS* theDS,
|
|
BOPDS_Curve& theNC,
|
|
Standard_Integer theNV[2])
|
|
{
|
|
theNV[0] = theNV[1] = -1;
|
|
|
|
// get extreme paves
|
|
Handle(BOPDS_PaveBlock)& aPB = theNC.ChangePaveBlock1();
|
|
const BOPDS_ListOfPave& aLP = aPB->ExtPaves();
|
|
Standard_Integer aNbEP = aLP.Extent();
|
|
if (aNbEP == 0)
|
|
return;
|
|
Standard_Real aTmin = RealLast();
|
|
Standard_Real aTmax = -aTmin;
|
|
for (BOPDS_ListIteratorOfListOfPave aItLP(aLP); aItLP.More(); aItLP.Next())
|
|
{
|
|
const BOPDS_Pave& aPv = aItLP.Value();
|
|
Standard_Integer nV;
|
|
Standard_Real aTV;
|
|
aPv.Contents(nV, aTV);
|
|
if (aTV < aTmin) {
|
|
theNV[0] = aPv.Index();
|
|
aTmin = aTV;
|
|
}
|
|
if (aTV > aTmax) {
|
|
theNV[1] = aPv.Index();
|
|
aTmax = aTV;
|
|
}
|
|
}
|
|
|
|
// compare extreme vertices with ends of the curve
|
|
const IntTools_Curve& aIC = theNC.Curve();
|
|
Standard_Real aT[2];
|
|
gp_Pnt aP[2];
|
|
aIC.Bounds(aT[0], aT[1], aP[0], aP[1]);
|
|
Standard_Real aTol = Max(theNC.Tolerance(), theNC.TangentialTolerance());
|
|
aTol += Precision::Confusion();
|
|
for (Standard_Integer j = 0; j < 2; ++j)
|
|
{
|
|
const BOPDS_ShapeInfo& aSIV = theDS->ShapeInfo(theNV[j]);
|
|
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aSIV.Shape()));
|
|
Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV(aV, aP[j], aTol);
|
|
if (iFlag != 0)
|
|
theNV[j] = -1;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutBoundPaveOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutBoundPaveOnCurve(const TopoDS_Face& aF1,
|
|
const TopoDS_Face& aF2,
|
|
BOPDS_Curve& aNC,
|
|
TColStd_ListOfInteger& aLVB)
|
|
{
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
Standard_Real aT[2];
|
|
gp_Pnt aP[2];
|
|
aIC.Bounds(aT[0], aT[1], aP[0], aP[1]);
|
|
Standard_Real aTolR3D = Max(aNC.Tolerance(), aNC.TangentialTolerance());
|
|
Handle(BOPDS_PaveBlock)& aPB = aNC.ChangePaveBlock1();
|
|
// Get numbers of vertices assigned to the ends of the curve
|
|
Standard_Integer aBndNV[2];
|
|
getBoundPaves(myDS, aNC, aBndNV);
|
|
//
|
|
Standard_Real aTolVnew = Precision::Confusion();
|
|
for (Standard_Integer j = 0; j<2; ++j)
|
|
{
|
|
if (aBndNV[j] < 0)
|
|
{
|
|
// no vertex on this end
|
|
if (j && aP[1].IsEqual(aP[0], aTolVnew)) {
|
|
//if curve is closed, process only one bound
|
|
continue;
|
|
}
|
|
Standard_Boolean bVF = myContext->IsValidPointForFaces(aP[j], aF1, aF2, aTolR3D);
|
|
if (!bVF) {
|
|
continue;
|
|
}
|
|
TopoDS_Vertex aVn;
|
|
BOPTools_AlgoTools::MakeNewVertex(aP[j], aTolR3D, aVn);
|
|
BOPTools_AlgoTools::UpdateVertex(aIC, aT[j], aVn);
|
|
aTolVnew = BRep_Tool::Tolerance(aVn);
|
|
|
|
BOPDS_ShapeInfo aSIVn;
|
|
aSIVn.SetShapeType(TopAbs_VERTEX);
|
|
aSIVn.SetShape(aVn);
|
|
|
|
Bnd_Box& aBox = aSIVn.ChangeBox();
|
|
BRepBndLib::Add(aVn, aBox);
|
|
aBox.SetGap(aBox.GetGap() + Precision::Confusion());
|
|
|
|
Standard_Integer nVn = myDS->Append(aSIVn);
|
|
|
|
BOPDS_Pave aPn;
|
|
aPn.SetIndex(nVn);
|
|
aPn.SetParameter(aT[j]);
|
|
aPB->AppendExtPave(aPn);
|
|
|
|
aLVB.Append(nVn);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutPavesOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutPavesOnCurve(const TColStd_MapOfInteger& theMVOnIn,
|
|
const TColStd_MapOfInteger& theMVCommon,
|
|
BOPDS_Curve& theNC,
|
|
const TColStd_MapOfInteger& theMI,
|
|
const TColStd_MapOfInteger& theMVEF,
|
|
TColStd_DataMapOfIntegerReal& theMVTol,
|
|
TColStd_DataMapOfIntegerListOfInteger& theDMVLV)
|
|
{
|
|
Standard_Integer nV;
|
|
TColStd_MapIteratorOfMapOfInteger aIt;
|
|
//
|
|
const Bnd_Box& aBoxC = theNC.Box();
|
|
const Standard_Real aTolR3D = Max(theNC.Tolerance(), theNC.TangentialTolerance());
|
|
//
|
|
//Put EF vertices first
|
|
aIt.Initialize(theMVEF);
|
|
for (; aIt.More(); aIt.Next())
|
|
{
|
|
nV = aIt.Value();
|
|
PutPaveOnCurve(nV, aTolR3D, theNC, theMI, theMVTol, theDMVLV, 2);
|
|
}
|
|
|
|
//Put all other vertices
|
|
aIt.Initialize(theMVOnIn);
|
|
for (; aIt.More(); aIt.Next())
|
|
{
|
|
nV = aIt.Value();
|
|
if (theMVEF.Contains(nV))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!theMVCommon.Contains(nV))
|
|
{
|
|
const BOPDS_ShapeInfo& aSIV = myDS->ShapeInfo(nV);
|
|
const Bnd_Box& aBoxV = aSIV.Box();
|
|
//
|
|
if (aBoxC.IsOut(aBoxV))
|
|
{
|
|
continue;
|
|
}
|
|
if (!myDS->IsNewShape(nV))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
PutPaveOnCurve(nV, aTolR3D, theNC, theMI, theMVTol, theDMVLV, 1);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FilterPavesOnCurves
|
|
//purpose :
|
|
//=======================================================================
|
|
namespace {
|
|
struct PaveBlockDist {
|
|
Handle(BOPDS_PaveBlock) PB;
|
|
Standard_Real SquareDist; // square distance from vertex to the paveblock
|
|
Standard_Real SinAngle; // sinus of angle between projection vector
|
|
// and tangent at projection point
|
|
Standard_Real Tolerance; // tolerance of the section curve
|
|
};
|
|
}
|
|
void BOPAlgo_PaveFiller::FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC,
|
|
TColStd_DataMapOfIntegerReal& theMVTol)
|
|
{
|
|
// For each vertex found in ExtPaves of pave blocks of section curves
|
|
// collect list of pave blocks with distance to the curve
|
|
NCollection_IndexedDataMap<Standard_Integer,NCollection_List<PaveBlockDist> > aIDMVertPBs;
|
|
Standard_Integer i;
|
|
const Standard_Real anEps = gp::Resolution();
|
|
for (i = 0; i < theVNC.Length(); ++i)
|
|
{
|
|
const BOPDS_Curve& aNC = theVNC(i);
|
|
const IntTools_Curve& aIC = aNC.Curve();
|
|
const Standard_Real aTolR3D = Max(aNC.Tolerance(), aNC.TangentialTolerance());
|
|
GeomAdaptor_Curve aGAC(aIC.Curve());
|
|
const Handle(BOPDS_PaveBlock)& aPB = aNC.PaveBlocks().First();
|
|
const BOPDS_ListOfPave& aPaves = aPB->ExtPaves();
|
|
BOPDS_ListOfPave::Iterator itPaves(aPaves);
|
|
for (; itPaves.More(); itPaves.Next())
|
|
{
|
|
const BOPDS_Pave& aPave = itPaves.Value();
|
|
Standard_Integer nV = aPave.Index();
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV));
|
|
// compute distance from vertex to the point on curve with vertex parameter
|
|
gp_Pnt aPV = BRep_Tool::Pnt(aV);
|
|
Standard_Real aPar = aPave.Parameter();
|
|
gp_Pnt aPonC;
|
|
gp_Vec aD1;
|
|
aGAC.D1(aPar, aPonC, aD1);
|
|
gp_Vec aProjVec(aPV, aPonC);
|
|
Standard_Real aSqDist = aProjVec.SquareMagnitude();
|
|
Standard_Real aSqD1Mod = aD1.SquareMagnitude();
|
|
Standard_Real aSin = aProjVec.CrossSquareMagnitude(aD1);
|
|
if (aSqDist > anEps && aSqD1Mod > anEps)
|
|
aSin = sqrt(aSin / aSqDist / aSqD1Mod);
|
|
NCollection_List<PaveBlockDist>* pList = aIDMVertPBs.ChangeSeek(nV);
|
|
if (!pList)
|
|
pList = &aIDMVertPBs.ChangeFromIndex(aIDMVertPBs.Add(nV, NCollection_List<PaveBlockDist>()));
|
|
PaveBlockDist aPBD = { aPB, aSqDist, aSin, aTolR3D };
|
|
pList->Append(aPBD);
|
|
}
|
|
}
|
|
|
|
// Process each vertex
|
|
const Standard_Real aSinAngleMin = 0.5; // angle below which projection is suspicious
|
|
for (i = 1; i <= aIDMVertPBs.Extent(); i++)
|
|
{
|
|
Standard_Integer nV = aIDMVertPBs.FindKey(i);
|
|
const NCollection_List<PaveBlockDist>& aList = aIDMVertPBs(i);
|
|
// Find a pave with minimal distance
|
|
Standard_Real aMinDist = RealLast();
|
|
Handle(BOPDS_PaveBlock) aPBMinDist;
|
|
NCollection_List<PaveBlockDist>::Iterator itL(aList);
|
|
for (; itL.More(); itL.Next())
|
|
{
|
|
const PaveBlockDist& aPBD = itL.Value();
|
|
if (aPBD.SquareDist < aMinDist)
|
|
{
|
|
aMinDist = aPBD.SquareDist;
|
|
aPBMinDist = aPBD.PB;
|
|
}
|
|
}
|
|
// Remove a vertex from a pave block if the distance is greater than the tolerance
|
|
// and there are other pave blocks for which the distance is less than the current.
|
|
// Do not remove a vertex if it is projected on the curve with quite large angle
|
|
// (see test bugs modalg_6 bug27761).
|
|
|
|
// Reduce tolerance for the vertex to the value of maximal distance to
|
|
// to section curve on which it will be kept.
|
|
Standard_Real aMaxDistKept = -1;
|
|
Standard_Boolean isRemoved = Standard_False;
|
|
for (itL.Init(aList); itL.More(); itL.Next())
|
|
{
|
|
const PaveBlockDist& aPBD = itL.Value();
|
|
Standard_Real aCheckDist = 100. * Max(aPBD.Tolerance*aPBD.Tolerance, aMinDist);
|
|
if (aPBD.SquareDist > aCheckDist && aPBD.SinAngle < aSinAngleMin)
|
|
{
|
|
aPBD.PB->RemoveExtPave(nV);
|
|
isRemoved = Standard_True;
|
|
}
|
|
else if (aPBD.SquareDist > aMaxDistKept)
|
|
aMaxDistKept = aPBD.SquareDist;
|
|
}
|
|
|
|
if (isRemoved && aMaxDistKept > 0)
|
|
{
|
|
const Standard_Real* pTol = theMVTol.Seek(nV);
|
|
if (pTol)
|
|
{
|
|
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV);
|
|
const Standard_Real aRealTol = Max(*pTol, sqrt(aMaxDistKept) + Precision::Confusion());
|
|
(*(Handle(BRep_TVertex)*)&aV.TShape())->Tolerance(aRealTol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ExtendedTolerance
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::ExtendedTolerance
|
|
(const Standard_Integer nV,
|
|
const TColStd_MapOfInteger& aMI,
|
|
Standard_Real& aTolVExt,
|
|
const Standard_Integer aType)
|
|
{
|
|
Standard_Boolean bFound = Standard_False;
|
|
if (!(myDS->IsNewShape(nV))) {
|
|
return bFound;
|
|
}
|
|
//
|
|
Standard_Integer i, k, aNbLines, aNbInt;
|
|
Standard_Real aT11, aT12, aD1, aD2, aD;
|
|
TopoDS_Vertex aV;
|
|
gp_Pnt aPV, aP11, aP12;
|
|
//
|
|
k = 0;
|
|
aNbInt = 2;
|
|
if (aType == 1) {
|
|
aNbInt = 1;
|
|
} else if (aType == 2) {
|
|
k = 1;
|
|
}
|
|
//
|
|
aV = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
|
|
aPV=BRep_Tool::Pnt(aV);
|
|
//
|
|
BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
|
|
BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
|
|
//
|
|
for (; k<aNbInt; ++k) {
|
|
aNbLines = !k ? aEEs.Length() : aEFs.Length();
|
|
for (i = 0; i < aNbLines; ++i) {
|
|
BOPDS_Interf *aInt = !k ? (BOPDS_Interf*) (&aEEs(i)) :
|
|
(BOPDS_Interf*) (&aEFs(i));
|
|
if (aInt->IndexNew() == nV) {
|
|
if (aMI.Contains(aInt->Index1()) &&
|
|
aMI.Contains(aInt->Index2())) {
|
|
const IntTools_CommonPrt& aComPrt = !k ? aEEs(i).CommonPart() :
|
|
aEFs(i).CommonPart();
|
|
//
|
|
const TopoDS_Edge& aE1=aComPrt.Edge1();
|
|
aComPrt.Range1(aT11, aT12);
|
|
BOPTools_AlgoTools::PointOnEdge(aE1, aT11, aP11);
|
|
BOPTools_AlgoTools::PointOnEdge(aE1, aT12, aP12);
|
|
aD1=aPV.Distance(aP11);
|
|
aD2=aPV.Distance(aP12);
|
|
aD=(aD1>aD2)? aD1 : aD2;
|
|
if (aD>aTolVExt) {
|
|
aTolVExt=aD;
|
|
}
|
|
return !bFound;
|
|
}//if (aMI.Contains(aEF.Index1()) && aMI.Contains(aEF.Index2())) {
|
|
}//if (aInt->IndexNew() == nV) {
|
|
}//for (i = 0; i < aNbLines; ++i) {
|
|
}//for (k=0; k<2; ++k) {
|
|
return bFound;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetEFPnts
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::GetEFPnts
|
|
(const Standard_Integer nF1,
|
|
const Standard_Integer nF2,
|
|
IntSurf_ListOfPntOn2S& aListOfPnts)
|
|
{
|
|
Standard_Integer nE, nF, nFOpposite, aNbEFs, i;
|
|
Standard_Real U1, U2, V1, V2, f, l;
|
|
TColStd_MapOfInteger aMI;
|
|
//
|
|
//collect indexes of all shapes from nF1 and nF2.
|
|
GetFullShapeMap(nF1, aMI);
|
|
GetFullShapeMap(nF2, aMI);
|
|
//
|
|
BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
|
|
aNbEFs = aEFs.Length();
|
|
//
|
|
for(i = 0; i < aNbEFs; ++i) {
|
|
const BOPDS_InterfEF& aEF = aEFs(i);
|
|
if (aEF.HasIndexNew()) {
|
|
aEF.Indices(nE, nFOpposite);
|
|
if(aMI.Contains(nE) && aMI.Contains(nFOpposite)) {
|
|
const IntTools_CommonPrt& aCP = aEF.CommonPart();
|
|
Standard_Real aPar = aCP.VertexParameter1();
|
|
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&myDS->Shape(nE)));
|
|
const TopoDS_Face& aFOpposite =
|
|
(*(TopoDS_Face*)(&myDS->Shape(nFOpposite)));
|
|
//
|
|
const Handle(Geom_Curve)& aCurve = BRep_Tool::Curve(aE, f, l);
|
|
//
|
|
nF = (nFOpposite == nF1) ? nF2 : nF1;
|
|
const TopoDS_Face& aF = (*(TopoDS_Face*)(&myDS->Shape(nF)));
|
|
Handle(Geom2d_Curve) aPCurve =
|
|
BRep_Tool::CurveOnSurface(aE, aF, f, l);
|
|
//
|
|
GeomAPI_ProjectPointOnSurf& aProj=myContext->ProjPS(aFOpposite);
|
|
//
|
|
gp_Pnt aPoint;
|
|
aCurve->D0(aPar, aPoint);
|
|
IntSurf_PntOn2S aPnt;
|
|
if(!aPCurve.IsNull()) {
|
|
gp_Pnt2d aP2d = aPCurve->Value(aPar);
|
|
aProj.Perform(aPoint);
|
|
if(aProj.IsDone()) {
|
|
aProj.LowerDistanceParameters(U1,V1);
|
|
if (nF == nF1) {
|
|
aPnt.SetValue(aP2d.X(),aP2d.Y(),U1,V1);
|
|
} else {
|
|
aPnt.SetValue(U1,V1,aP2d.X(),aP2d.Y());
|
|
}
|
|
aListOfPnts.Append(aPnt);
|
|
}
|
|
}
|
|
else {
|
|
GeomAPI_ProjectPointOnSurf& aProj1 = myContext->ProjPS(aF);
|
|
aProj1.Perform(aPoint);
|
|
aProj.Perform(aPoint);
|
|
if(aProj1.IsDone() && aProj.IsDone()){
|
|
aProj1.LowerDistanceParameters(U1,V1);
|
|
aProj.LowerDistanceParameters(U2,V2);
|
|
if (nF == nF1) {
|
|
aPnt.SetValue(U1,V1,U2,V2);
|
|
} else {
|
|
aPnt.SetValue(U2,V2,U1,V1);
|
|
}
|
|
aListOfPnts.Append(aPnt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutEFPavesOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutEFPavesOnCurve
|
|
(BOPDS_Curve& aNC,
|
|
const TColStd_MapOfInteger& aMI,
|
|
const TColStd_MapOfInteger& aMVEF,
|
|
TColStd_DataMapOfIntegerReal& aMVTol,
|
|
TColStd_DataMapOfIntegerListOfInteger& aDMVLV)
|
|
{
|
|
if (!aMVEF.Extent()) {
|
|
return;
|
|
}
|
|
//
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
GeomAbs_CurveType aTypeC;
|
|
aTypeC=aIC.Type();
|
|
if (!(aTypeC==GeomAbs_BezierCurve || aTypeC==GeomAbs_BSplineCurve)) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer nV;
|
|
TColStd_MapOfInteger aMV;
|
|
//
|
|
aMV.Assign(aMVEF);
|
|
RemoveUsedVertices(aNC, aMV);
|
|
if (!aMV.Extent()) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Real aDist;
|
|
BOPDS_Pave aPave;
|
|
//
|
|
const Handle(Geom_Curve)& aC3D=aIC.Curve();
|
|
GeomAPI_ProjectPointOnCurve& aProjPT = myContext->ProjPT(aC3D);
|
|
//
|
|
TColStd_MapIteratorOfMapOfInteger aItMI;
|
|
aItMI.Initialize(aMV);
|
|
for (; aItMI.More(); aItMI.Next()) {
|
|
nV = aItMI.Value();
|
|
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
|
|
gp_Pnt aPV = BRep_Tool::Pnt(aV);
|
|
aProjPT.Perform(aPV);
|
|
Standard_Integer aNbPoints = aProjPT.NbPoints();
|
|
if (aNbPoints) {
|
|
aDist = aProjPT.LowerDistance();
|
|
PutPaveOnCurve(nV, aDist, aNC, aMI, aMVTol, aDMVLV);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutStickPavesOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutStickPavesOnCurve
|
|
(const TopoDS_Face& aF1,
|
|
const TopoDS_Face& aF2,
|
|
const TColStd_MapOfInteger& aMI,
|
|
BOPDS_Curve& aNC,
|
|
const TColStd_MapOfInteger& aMVStick,
|
|
TColStd_DataMapOfIntegerReal& aMVTol,
|
|
TColStd_DataMapOfIntegerListOfInteger& aDMVLV)
|
|
{
|
|
// Get numbers of vertices assigned to the ends of the curve
|
|
Standard_Integer aBndNV[2];
|
|
getBoundPaves(myDS, aNC, aBndNV);
|
|
if (aBndNV[0] >= 0 && aBndNV[1] >= 0)
|
|
{
|
|
// both curve ends already have assigned vertices
|
|
return;
|
|
}
|
|
TColStd_MapOfInteger aMV;
|
|
aMV.Assign(aMVStick);
|
|
RemoveUsedVertices(aNC, aMV);
|
|
//
|
|
if (!aMV.Extent()) {
|
|
return;
|
|
}
|
|
//
|
|
Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
|
|
Handle(Geom_Surface) aS2=BRep_Tool::Surface(aF2);
|
|
//
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
//if (aTypeC==GeomAbs_BezierCurve || aTypeC==GeomAbs_BSplineCurve) {
|
|
Handle(Geom2d_Curve) aC2D[2];
|
|
//
|
|
aC2D[0]=aIC.FirstCurve2d();
|
|
aC2D[1]=aIC.SecondCurve2d();
|
|
if (!aC2D[0].IsNull() && !aC2D[1].IsNull()) {
|
|
Standard_Integer nV, m, n;
|
|
Standard_Real aTC[2], aD, aD2, u, v, aDT2, aScPr, aDScPr;
|
|
gp_Pnt aPC[2], aPV;
|
|
gp_Dir aDN[2];
|
|
gp_Pnt2d aP2D;
|
|
TColStd_MapIteratorOfMapOfInteger aItMI, aItMI1;
|
|
//
|
|
aDT2=2e-7; // the rich criteria
|
|
aDScPr=5.e-9; // the creasing criteria
|
|
aIC.Bounds(aTC[0], aTC[1], aPC[0], aPC[1]);
|
|
//
|
|
aItMI.Initialize(aMV);
|
|
for (; aItMI.More(); aItMI.Next()) {
|
|
nV = aItMI.Value();
|
|
const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&myDS->Shape(nV));
|
|
aPV=BRep_Tool::Pnt(aV);
|
|
//
|
|
for (m=0; m<2; ++m) {
|
|
if (aBndNV[m] >= 0)
|
|
continue;
|
|
aD2=aPC[m].SquareDistance(aPV);
|
|
if (aD2>aDT2) {// no rich
|
|
continue;
|
|
}
|
|
//
|
|
for (n=0; n<2; ++n) {
|
|
Handle(Geom_Surface)& aS=(!n)? aS1 : aS2;
|
|
aC2D[n]->D0(aTC[m], aP2D);
|
|
aP2D.Coord(u, v);
|
|
BOPTools_AlgoTools3D::GetNormalToSurface(aS, u, v, aDN[n]);
|
|
}
|
|
//
|
|
aScPr=aDN[0]*aDN[1];
|
|
if (aScPr<0.) {
|
|
aScPr=-aScPr;
|
|
}
|
|
aScPr=1.-aScPr;
|
|
//
|
|
if (aScPr>aDScPr) {
|
|
continue;
|
|
}
|
|
//
|
|
// The intersection curve aIC is vanishing curve (the crease)
|
|
aD=sqrt(aD2);
|
|
//
|
|
PutPaveOnCurve(nV, aD, aNC, aMI, aMVTol, aDMVLV);
|
|
}
|
|
}//for (jVU=1; jVU=aNbVU; ++jVU) {
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetStickVertices
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::GetStickVertices(const Standard_Integer nF1,
|
|
const Standard_Integer nF2,
|
|
TColStd_MapOfInteger& aMVStick,
|
|
TColStd_MapOfInteger& aMVEF,
|
|
TColStd_MapOfInteger& aMI)
|
|
{
|
|
Standard_Integer nS1, nS2, nVNew, aTypeInt, i;
|
|
//
|
|
BOPDS_VectorOfInterfVV& aVVs=myDS->InterfVV();
|
|
BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
|
|
BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
|
|
BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF();
|
|
BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
|
|
//
|
|
Standard_Integer aNbLines[5] = {
|
|
aVVs.Length(), aVEs.Length(), aEEs.Length(),
|
|
aVFs.Length(), aEFs.Length()
|
|
};
|
|
//collect indices of all shapes from nF1 and nF2.
|
|
aMI.Clear();
|
|
GetFullShapeMap(nF1, aMI);
|
|
GetFullShapeMap(nF2, aMI);
|
|
//
|
|
//collect VV, VE, EE, VF interferences
|
|
for (aTypeInt = 0; aTypeInt < 4; ++aTypeInt) {
|
|
for (i = 0; i < aNbLines[aTypeInt]; ++i) {
|
|
BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) :
|
|
((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) :
|
|
((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) :
|
|
(BOPDS_Interf*)(&aVFs(i))));
|
|
if (aInt->HasIndexNew()) {
|
|
aInt->Indices(nS1, nS2);
|
|
if(aMI.Contains(nS1) && aMI.Contains(nS2)) {
|
|
nVNew = aInt->IndexNew();
|
|
aMVStick.Add(nVNew);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//collect EF interferences
|
|
for (i = 0; i < aNbLines[4]; ++i) {
|
|
const BOPDS_InterfEF& aInt = aEFs(i);
|
|
if (aInt.HasIndexNew()) {
|
|
aInt.Indices(nS1, nS2);
|
|
if(aMI.Contains(nS1) && aMI.Contains(nS2)) {
|
|
nVNew = aInt.IndexNew();
|
|
aMVStick.Add(nVNew);
|
|
aMVEF.Add(nVNew);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: GetFullShapeMap
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::GetFullShapeMap(const Standard_Integer nF,
|
|
TColStd_MapOfInteger& aMI)
|
|
{
|
|
TColStd_ListIteratorOfListOfInteger aIt;
|
|
Standard_Integer nS;
|
|
//
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
|
|
const TColStd_ListOfInteger& aLI = aSI.SubShapes();
|
|
//
|
|
aMI.Add(nF);
|
|
aIt.Initialize(aLI);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
nS = aIt.Value();
|
|
aMI.Add(nS);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: RemoveUsedVertices
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::RemoveUsedVertices(const BOPDS_Curve& aNC,
|
|
TColStd_MapOfInteger& aMV)
|
|
{
|
|
if (aMV.IsEmpty())
|
|
return;
|
|
|
|
const BOPDS_ListOfPaveBlock& aLPBC = aNC.PaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPBC);
|
|
for (; itPB.More(); itPB.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = itPB.Value();
|
|
const BOPDS_ListOfPave& aLP = aPB->ExtPaves();
|
|
BOPDS_ListIteratorOfListOfPave itLP(aLP);
|
|
for (; itLP.More(); itLP.Next())
|
|
aMV.Remove(itLP.Value().Index());
|
|
|
|
aMV.Remove(aPB->Pave1().Index());
|
|
aMV.Remove(aPB->Pave2().Index());
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutPaveOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutPaveOnCurve
|
|
(const Standard_Integer nV,
|
|
const Standard_Real aTolR3D,
|
|
const BOPDS_Curve& aNC,
|
|
const TColStd_MapOfInteger& aMI,
|
|
TColStd_DataMapOfIntegerReal& aMVTol,
|
|
TColStd_DataMapOfIntegerListOfInteger& aDMVLV,
|
|
const Standard_Integer iCheckExtend)
|
|
{
|
|
Standard_Boolean bIsVertexOnLine;
|
|
Standard_Real aT;
|
|
//
|
|
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
|
|
const Handle(BOPDS_PaveBlock)& aPB = aNC.PaveBlocks().First();
|
|
const IntTools_Curve& aIC = aNC.Curve();
|
|
//
|
|
Standard_Real aTolV = (aMVTol.IsBound(nV) ? aMVTol(nV) : BRep_Tool::Tolerance(aV));
|
|
|
|
bIsVertexOnLine = myContext->IsVertexOnLine(aV, aTolV, aIC, aTolR3D + myFuzzyValue, aT);
|
|
if (!bIsVertexOnLine && iCheckExtend && !myVertsToAvoidExtension.Contains(nV))
|
|
{
|
|
Standard_Real anExtraTol = aTolV;
|
|
if (ExtendedTolerance(nV, aMI, anExtraTol, iCheckExtend))
|
|
{
|
|
bIsVertexOnLine = myContext->IsVertexOnLine(aV, anExtraTol, aIC, aTolR3D + myFuzzyValue, aT);
|
|
if (bIsVertexOnLine)
|
|
{
|
|
gp_Pnt aPOnC;
|
|
aIC.D0(aT, aPOnC);
|
|
aTolV = aPOnC.Distance(BRep_Tool::Pnt(aV));
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (bIsVertexOnLine) {
|
|
// check if aPB contains the parameter aT
|
|
Standard_Boolean bExist;
|
|
Standard_Integer nVUsed;
|
|
Standard_Real aPTol, aDTol;
|
|
//
|
|
aDTol = 1.e-12;
|
|
//
|
|
GeomAdaptor_Curve aGAC(aIC.Curve());
|
|
aPTol = aGAC.Resolution(Max(aTolR3D, aTolV));
|
|
//
|
|
bExist = aPB->ContainsParameter(aT, aPTol, nVUsed);
|
|
if (bExist) {
|
|
// use existing pave
|
|
TColStd_ListOfInteger* pList = aDMVLV.ChangeSeek(nVUsed);
|
|
if (!pList) {
|
|
pList = aDMVLV.Bound(nVUsed, TColStd_ListOfInteger());
|
|
pList->Append(nVUsed);
|
|
if (!aMVTol.IsBound(nVUsed)) {
|
|
const TopoDS_Vertex& aVUsed = (*(TopoDS_Vertex *)(&myDS->Shape(nVUsed)));
|
|
aTolV = BRep_Tool::Tolerance(aVUsed);
|
|
aMVTol.Bind(nVUsed, aTolV);
|
|
}
|
|
}
|
|
// avoid repeated elements in the list
|
|
TColStd_ListIteratorOfListOfInteger aItLI(*pList);
|
|
for (; aItLI.More(); aItLI.Next()) {
|
|
if (aItLI.Value() == nV) {
|
|
break;
|
|
}
|
|
}
|
|
if (!aItLI.More()) {
|
|
pList->Append(nV);
|
|
}
|
|
// save initial tolerance for the vertex
|
|
if (!aMVTol.IsBound(nV)) {
|
|
aTolV = BRep_Tool::Tolerance(aV);
|
|
aMVTol.Bind(nV, aTolV);
|
|
}
|
|
}
|
|
else {
|
|
// add new pave
|
|
BOPDS_Pave aPave;
|
|
aPave.SetIndex(nV);
|
|
aPave.SetParameter(aT);
|
|
aPB->AppendExtPave(aPave);
|
|
//
|
|
gp_Pnt aP1 = aGAC.Value(aT);
|
|
aTolV = BRep_Tool::Tolerance(aV);
|
|
gp_Pnt aP2 = BRep_Tool::Pnt(aV);
|
|
Standard_Real aDist = aP1.Distance(aP2);
|
|
if (aDist > aTolV) {
|
|
BRep_Builder().UpdateVertex(aV, aDist + aDTol);
|
|
//
|
|
if (!aMVTol.IsBound(nV)) {
|
|
aMVTol.Bind(nV, aTolV);
|
|
}
|
|
//
|
|
BOPDS_ShapeInfo& aSIDS=myDS->ChangeShapeInfo(nV);
|
|
Bnd_Box& aBoxDS=aSIDS.ChangeBox();
|
|
BRepBndLib::Add(aV, aBoxDS);
|
|
aBoxDS.SetGap(aBoxDS.GetGap() + Precision::Confusion());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ProcessExistingPaveBlocks
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::ProcessExistingPaveBlocks
|
|
(const Standard_Integer theInt,
|
|
const Standard_Integer nF1,
|
|
const Standard_Integer nF2,
|
|
const BOPDS_IndexedMapOfPaveBlock& aMPBOnIn,
|
|
const TColStd_DataMapOfIntegerListOfInteger& aDMBV,
|
|
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& aMSCPB,
|
|
TopTools_DataMapOfShapeInteger& aMVI,
|
|
BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap,
|
|
BOPDS_MapOfPaveBlock& aMPB)
|
|
{
|
|
if (aDMBV.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Real aT, dummy;
|
|
Standard_Integer i, nV, nE, iC, aNbPB, iFlag;
|
|
TColStd_ListIteratorOfListOfInteger aItLI;
|
|
TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger aItBV;
|
|
//
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
BOPDS_InterfFF& aFF = aFFs(theInt);
|
|
BOPDS_VectorOfCurve& aVC = aFF.ChangeCurves();
|
|
//
|
|
const BOPDS_FaceInfo& aFI1 = myDS->FaceInfo(nF1);
|
|
const BOPDS_FaceInfo& aFI2 = myDS->FaceInfo(nF2);
|
|
//
|
|
aNbPB = aMPBOnIn.Extent();
|
|
//
|
|
aItBV.Initialize(aDMBV);
|
|
for (; aItBV.More(); aItBV.Next()) {
|
|
iC = aItBV.Key();
|
|
const TColStd_ListOfInteger& aLBV = aItBV.Value();
|
|
//
|
|
BOPDS_Curve& aNC = aVC.ChangeValue(iC);
|
|
BOPDS_ListOfPaveBlock& aLPBC = aNC.ChangePaveBlocks();
|
|
//
|
|
aItLI.Initialize(aLBV);
|
|
for (; aItLI.More(); aItLI.Next()) {
|
|
nV = aItLI.Value();
|
|
const BOPDS_ShapeInfo& aSIV=myDS->ShapeInfo(nV);
|
|
const Bnd_Box& aBoxV=aSIV.Box();
|
|
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aSIV.Shape();
|
|
if (!aMVI.IsBound(aV)) {
|
|
continue;
|
|
}
|
|
//
|
|
for (i = 1; i <= aNbPB; ++i) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aMPBOnIn(i);
|
|
if (aPB->Pave1().Index() == nV || aPB->Pave2().Index() == nV) {
|
|
continue;
|
|
}
|
|
//
|
|
if (aMPB.Contains(aPB)) {
|
|
continue;
|
|
}
|
|
if (myDS->ShapeInfo(aPB->OriginalEdge()).HasFlag()) { // skip degenerated edges
|
|
continue;
|
|
}
|
|
//
|
|
nE = aPB->Edge();
|
|
const BOPDS_ShapeInfo& aSIE = myDS->ShapeInfo(nE);
|
|
const Bnd_Box& aBoxE = aSIE.Box();
|
|
//
|
|
if (aBoxV.IsOut(aBoxE)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&aSIE.Shape();
|
|
//
|
|
iFlag = myContext->ComputeVE(aV, aE, aT, dummy, myFuzzyValue);
|
|
if (!iFlag) {
|
|
aMPB.Add(aPB);
|
|
PreparePostTreatFF(theInt, iC, aPB, aMSCPB, aMVI, aLPBC);
|
|
|
|
// Add faces to PB
|
|
Standard_Boolean bInF1 = (aFI1.PaveBlocksOn().Contains(aPB) ||
|
|
aFI1.PaveBlocksIn().Contains(aPB));
|
|
Standard_Boolean bInF2 = (aFI2.PaveBlocksOn().Contains(aPB) ||
|
|
aFI2.PaveBlocksIn().Contains(aPB));
|
|
if (!bInF1 || !bInF2)
|
|
{
|
|
// Face without pave block
|
|
const Standard_Integer nF = bInF1 ? nF2 : nF1;
|
|
TColStd_ListOfInteger* pFaces = thePBFacesMap.ChangeSeek(aPB);
|
|
if (!pFaces)
|
|
pFaces = thePBFacesMap.Bound(aPB, TColStd_ListOfInteger());
|
|
// List is expected to be short, so we allow the check here
|
|
if (pFaces->IsEmpty() || !pFaces->Contains(nF))
|
|
pFaces->Append(nF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : UpdateExistingPaveBlocks
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::UpdateExistingPaveBlocks
|
|
(const Handle(BOPDS_PaveBlock)& aPBf,
|
|
BOPDS_ListOfPaveBlock& aLPB,
|
|
const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap)
|
|
{
|
|
if (!aLPB.Extent()) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer nE;
|
|
Standard_Boolean bCB;
|
|
Handle(BOPDS_PaveBlock) aPB, aPB1, aPB2, aPB2n;
|
|
Handle(BOPDS_CommonBlock) aCB;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aIt, aIt1, aIt2;
|
|
//
|
|
// 1. Remove old pave blocks
|
|
const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPBf);
|
|
bCB = !aCB1.IsNull();
|
|
BOPDS_ListOfPaveBlock aLPB1;
|
|
//
|
|
if (bCB) {
|
|
aLPB1.Assign(aCB1->PaveBlocks());
|
|
} else {
|
|
aLPB1.Append(aPBf);
|
|
}
|
|
aIt1.Initialize(aLPB1);
|
|
for (; aIt1.More(); aIt1.Next()) {
|
|
aPB1 = aIt1.Value();
|
|
nE = aPB1->OriginalEdge();
|
|
//
|
|
BOPDS_ListOfPaveBlock& aLPB2 = myDS->ChangePaveBlocks(nE);
|
|
aIt2.Initialize(aLPB2);
|
|
for (; aIt2.More(); aIt2.Next()) {
|
|
aPB2 = aIt2.Value();
|
|
if (aPB1 == aPB2) {
|
|
aLPB2.Remove(aIt2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// 2. Update pave blocks
|
|
if (bCB) {
|
|
// Create new common blocks
|
|
BOPDS_ListOfPaveBlock aLPBNew;
|
|
const TColStd_ListOfInteger& aFaces = aCB1->Faces();
|
|
aIt.Initialize(aLPB);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPBValue = aIt.Value();
|
|
BOPDS_Pave aPBValuePaves[2] = {aPBValue->Pave1(), aPBValue->Pave2()};
|
|
//
|
|
aCB = new BOPDS_CommonBlock;
|
|
aIt1.Initialize(aLPB1);
|
|
for (; aIt1.More(); aIt1.Next()) {
|
|
aPB2 = aIt1.Value();
|
|
nE = aPB2->OriginalEdge();
|
|
//
|
|
// Create new pave block
|
|
aPB2n = new BOPDS_PaveBlock;
|
|
if (aPBValue->OriginalEdge() == nE) {
|
|
aPB2n->SetPave1(aPBValuePaves[0]);
|
|
aPB2n->SetPave2(aPBValuePaves[1]);
|
|
}
|
|
else {
|
|
// For the different original edge compute the parameters of paves
|
|
BOPDS_Pave aPave[2];
|
|
for (Standard_Integer i = 0; i < 2; ++i) {
|
|
Standard_Integer nV = aPBValuePaves[i].Index();
|
|
aPave[i].SetIndex(nV);
|
|
if (nV == aPB2->Pave1().Index()) {
|
|
aPave[i].SetParameter(aPB2->Pave1().Parameter());
|
|
}
|
|
else if (nV == aPB2->Pave2().Index()) {
|
|
aPave[i].SetParameter(aPB2->Pave2().Parameter());
|
|
}
|
|
else {
|
|
// Compute the parameter by projecting the point
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV));
|
|
const TopoDS_Edge& aEOr = TopoDS::Edge(myDS->Shape(nE));
|
|
Standard_Real aTOut, aDist;
|
|
Standard_Integer iErr = myContext->ComputeVE(aV, aEOr, aTOut, aDist, myFuzzyValue);
|
|
if (!iErr) {
|
|
aPave[i].SetParameter(aTOut);
|
|
}
|
|
else {
|
|
// Unable to project - set the parameter of the closest boundary
|
|
const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(aPB2->Pave1().Index()));
|
|
const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(aPB2->Pave2().Index()));
|
|
//
|
|
gp_Pnt aP = BRep_Tool::Pnt(aV);
|
|
gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
|
|
gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
|
|
//
|
|
Standard_Real aDist1 = aP.SquareDistance(aP1);
|
|
Standard_Real aDist2 = aP.SquareDistance(aP2);
|
|
//
|
|
aPave[i].SetParameter(aDist1 < aDist2 ? aPB2->Pave1().Parameter() : aPB2->Pave2().Parameter());
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aPave[1].Parameter() < aPave[0].Parameter()) {
|
|
BOPDS_Pave aPaveTmp = aPave[0];
|
|
aPave[0] = aPave[1];
|
|
aPave[1] = aPaveTmp;
|
|
}
|
|
//
|
|
aPB2n->SetPave1(aPave[0]);
|
|
aPB2n->SetPave2(aPave[1]);
|
|
}
|
|
//
|
|
aPB2n->SetEdge(aPBValue->Edge());
|
|
aPB2n->SetOriginalEdge(nE);
|
|
aCB->AddPaveBlock(aPB2n);
|
|
myDS->SetCommonBlock(aPB2n, aCB);
|
|
myDS->ChangePaveBlocks(nE).Append(aPB2n);
|
|
}
|
|
aCB->SetFaces(aFaces);
|
|
//
|
|
const Handle(BOPDS_PaveBlock)& aPBNew = aCB->PaveBlocks().First();
|
|
aLPBNew.Append(aPBNew);
|
|
}
|
|
//
|
|
aLPB = aLPBNew;
|
|
}
|
|
else {
|
|
nE = aPBf->OriginalEdge();
|
|
BOPDS_ListOfPaveBlock& aLPBE = myDS->ChangePaveBlocks(nE);
|
|
aIt.Initialize(aLPB);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
aPB = aIt.Value();
|
|
aLPBE.Append(aPB);
|
|
}
|
|
}
|
|
|
|
// Try to project the edge on the faces
|
|
const TColStd_ListOfInteger* pLFaces = thePBFacesMap.Seek(aPBf);
|
|
if (!pLFaces)
|
|
return;
|
|
TColStd_ListIteratorOfListOfInteger itLF(*pLFaces);
|
|
for (; itLF.More(); itLF.Next())
|
|
{
|
|
const Standard_Integer nF = itLF.Value();
|
|
BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(nF);
|
|
const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(nF));
|
|
|
|
aIt.Initialize(aLPB);
|
|
for (; aIt.More(); aIt.Next())
|
|
{
|
|
aPB = aIt.ChangeValue();
|
|
if (aFI.PaveBlocksOn().Contains(aPB) || aFI.PaveBlocksIn().Contains(aPB))
|
|
continue;
|
|
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(aPB->Edge());
|
|
//
|
|
IntTools_EdgeFace anEF;
|
|
anEF.SetEdge(aE);
|
|
anEF.SetFace(aF);
|
|
anEF.SetFuzzyValue(myFuzzyValue);
|
|
anEF.SetRange(aPB->Pave1().Parameter(), aPB->Pave2().Parameter());
|
|
anEF.SetContext(myContext);
|
|
anEF.Perform();
|
|
//
|
|
const IntTools_SequenceOfCommonPrts& aCPrts = anEF.CommonParts();
|
|
Standard_Boolean bCoincide = (aCPrts.Length() == 1 && aCPrts(1).Type() == TopAbs_EDGE);
|
|
if (bCoincide)
|
|
{
|
|
aCB = myDS->CommonBlock(aPB);
|
|
if (aCB.IsNull())
|
|
{
|
|
aCB = new BOPDS_CommonBlock;
|
|
aCB->AddPaveBlock(aPB);
|
|
myDS->SetCommonBlock(aPB, aCB);
|
|
}
|
|
aCB->AddFace(nF);
|
|
aFI.ChangePaveBlocksIn().Add(aPB);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: PutClosingPaveOnCurve
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutClosingPaveOnCurve(BOPDS_Curve& aNC)
|
|
{
|
|
const IntTools_Curve& aIC = aNC.Curve();
|
|
const Handle(Geom_Curve)& aC3D = aIC.Curve();
|
|
// check 3d curve
|
|
if (aC3D.IsNull())
|
|
return;
|
|
|
|
// check bounds
|
|
if (!aIC.HasBounds())
|
|
return;
|
|
|
|
// check closeness
|
|
Standard_Real aT[2];
|
|
gp_Pnt aP[2];
|
|
aIC.Bounds(aT[0], aT[1], aP[0], aP[1]);
|
|
|
|
// Find the pave which has been put at one of the ends
|
|
Standard_Integer nV = -1;
|
|
// Keep the opposite parameter
|
|
Standard_Real aTOp = 0.;
|
|
|
|
Standard_Boolean bFound = Standard_False;
|
|
|
|
Handle(BOPDS_PaveBlock)& aPB = aNC.ChangePaveBlock1();
|
|
BOPDS_ListOfPave& aLP = aPB->ChangeExtPaves();
|
|
BOPDS_ListIteratorOfListOfPave aItLP(aLP);
|
|
for (; aItLP.More() && !bFound; aItLP.Next())
|
|
{
|
|
const BOPDS_Pave& aPC = aItLP.Value();
|
|
Standard_Real aTC = aPC.Parameter();
|
|
for (Standard_Integer j = 0; j < 2; ++j)
|
|
{
|
|
if (Abs(aTC - aT[j]) < Precision::PConfusion())
|
|
{
|
|
nV = aPC.Index();
|
|
aTOp = (!j) ? aT[1] : aT[0];
|
|
bFound = Standard_True;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bFound)
|
|
return;
|
|
|
|
// Check if the curve is closed using the tolerance
|
|
// of found vertex
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV));
|
|
const Standard_Real aTolV = BRep_Tool::Tolerance(aV);
|
|
|
|
Standard_Real aDist = aP[0].Distance(aP[1]);
|
|
if (aDist > aTolV)
|
|
return;
|
|
|
|
// Check if there will be valid range on the curve
|
|
Standard_Real aFirst, aLast;
|
|
if (!BRepLib::FindValidRange(GeomAdaptor_Curve(aIC.Curve()), aIC.Tolerance(),
|
|
aT[0], aP[0], aTolV,
|
|
aT[1], aP[1], aTolV,
|
|
aFirst, aLast))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Add closing pave to the curve
|
|
BOPDS_Pave aPave;
|
|
aPave.SetIndex(nV);
|
|
aPave.SetParameter(aTOp);
|
|
aLP.Append(aPave);
|
|
}
|
|
//=======================================================================
|
|
//function : PreparePostTreatFF
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PreparePostTreatFF
|
|
(const Standard_Integer aInt,
|
|
const Standard_Integer aCur,
|
|
const Handle(BOPDS_PaveBlock)& aPB,
|
|
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& aMSCPB,
|
|
TopTools_DataMapOfShapeInteger& aMVI,
|
|
BOPDS_ListOfPaveBlock& aLPBC)
|
|
{
|
|
Standard_Integer nV1, nV2;
|
|
//
|
|
aLPBC.Append(aPB);
|
|
//
|
|
aPB->Indices(nV1, nV2);
|
|
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
|
|
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(aPB->Edge());
|
|
// Keep info for post treatment
|
|
BOPDS_CoupleOfPaveBlocks aCPB;
|
|
aCPB.SetIndexInterf(aInt);
|
|
aCPB.SetIndex(aCur);
|
|
aCPB.SetPaveBlock1(aPB);
|
|
//
|
|
aMSCPB.Add(aE, aCPB);
|
|
aMVI.Bind(aV1, nV1);
|
|
aMVI.Bind(aV2, nV2);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CheckPlanes
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::CheckPlanes
|
|
(const Standard_Integer nF1,
|
|
const Standard_Integer nF2)const
|
|
{
|
|
Standard_Boolean bToIntersect;
|
|
Standard_Integer i, nV2, iCnt;
|
|
TColStd_MapIteratorOfMapOfInteger aIt;
|
|
//
|
|
bToIntersect=Standard_False;
|
|
//
|
|
const BOPDS_FaceInfo& aFI1=myDS->ChangeFaceInfo(nF1);
|
|
const BOPDS_FaceInfo& aFI2=myDS->ChangeFaceInfo(nF2);
|
|
//
|
|
const TColStd_MapOfInteger& aMVIn1=aFI1.VerticesIn();
|
|
const TColStd_MapOfInteger& aMVOn1=aFI1.VerticesOn();
|
|
//
|
|
iCnt=0;
|
|
for (i=0; (i<2 && !bToIntersect); ++i) {
|
|
const TColStd_MapOfInteger& aMV2=(!i) ? aFI2.VerticesIn()
|
|
: aFI2.VerticesOn();
|
|
//
|
|
aIt.Initialize(aMV2);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
nV2=aIt.Value();
|
|
if (aMVIn1.Contains(nV2) || aMVOn1.Contains(nV2)) {
|
|
++iCnt;
|
|
if (iCnt>1) {
|
|
bToIntersect=!bToIntersect;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return bToIntersect;
|
|
}
|
|
//=======================================================================
|
|
//function : UpdatePaveBlocks
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::UpdatePaveBlocks
|
|
(const TColStd_DataMapOfIntegerInteger& aDMNewSD)
|
|
{
|
|
if (aDMNewSD.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer nSp, aNbPBP, nV[2], i, j;
|
|
Standard_Real aT[2];
|
|
Standard_Boolean bCB, bRebuild;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItPB;
|
|
BOPDS_MapOfPaveBlock aMPB;
|
|
TColStd_MapOfInteger aMicroEdges;
|
|
//
|
|
BOPDS_ListOfPaveBlock anAllPBs;
|
|
|
|
// Get pave blocks of section edges
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
Standard_Integer aNbFF = aFFs.Length();
|
|
for (i = 0; i < aNbFF; ++i)
|
|
{
|
|
const BOPDS_InterfFF& aFF = aFFs(i);
|
|
const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
|
|
Standard_Integer aNbC = aVNC.Length();
|
|
for (j = 0; j < aNbC; ++j)
|
|
{
|
|
const BOPDS_Curve& aNC = aVNC(j);
|
|
const BOPDS_ListOfPaveBlock& aLPBC = aNC.PaveBlocks();
|
|
aItPB.Initialize(aLPBC);
|
|
for (; aItPB.More(); aItPB.Next())
|
|
anAllPBs.Append(aItPB.Value());
|
|
}
|
|
}
|
|
|
|
// Get pave blocks from the pool
|
|
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
|
|
aNbPBP = aPBP.Length();
|
|
for (i = 0; i < aNbPBP; ++i) {
|
|
BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
|
|
aItPB.Initialize(aLPB);
|
|
for (; aItPB.More(); aItPB.Next())
|
|
anAllPBs.Append(aItPB.Value());
|
|
}
|
|
|
|
// Process all pave blocks
|
|
aItPB.Initialize(anAllPBs);
|
|
for (; aItPB.More(); aItPB.Next())
|
|
{
|
|
Handle(BOPDS_PaveBlock) aPB = aItPB.Value();
|
|
const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(aPB);
|
|
bCB = !aCB.IsNull();
|
|
if (bCB) {
|
|
aPB = aCB->PaveBlock1();
|
|
}
|
|
//
|
|
if (aMPB.Add(aPB)) {
|
|
bRebuild = Standard_False;
|
|
aPB->Indices(nV[0], nV[1]);
|
|
aPB->Range(aT[0], aT[1]);
|
|
// remember the fact if the edge had different vertices before substitution
|
|
Standard_Boolean wasRegularEdge = (nV[0] != nV[1]);
|
|
//
|
|
for (j = 0; j < 2; ++j) {
|
|
if (aDMNewSD.IsBound(nV[j])) {
|
|
BOPDS_Pave aPave;
|
|
//
|
|
nV[j] = aDMNewSD.Find(nV[j]);
|
|
aPave.SetIndex(nV[j]);
|
|
aPave.SetParameter(aT[j]);
|
|
//
|
|
bRebuild = Standard_True;
|
|
if (!j) {
|
|
aPB->SetPave1(aPave);
|
|
}
|
|
else {
|
|
aPB->SetPave2(aPave);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (bRebuild) {
|
|
Standard_Integer nE = aPB->Edge();
|
|
// Check if the Pave Block has the edge set
|
|
if (nE < 0) {
|
|
// untouched edge
|
|
nE = aPB->OriginalEdge();
|
|
}
|
|
Standard_Boolean isDegEdge = myDS->ShapeInfo(nE).HasFlag();
|
|
if (wasRegularEdge && !isDegEdge && nV[0] == nV[1]) {
|
|
// now edge has the same vertex on both ends;
|
|
// check if it is not a regular closed curve.
|
|
FillShrunkData(aPB);
|
|
if (!aPB->HasShrunkData())
|
|
{
|
|
// micro edge, so mark it for removal
|
|
aMicroEdges.Add(nE);
|
|
continue;
|
|
}
|
|
}
|
|
nSp = SplitEdge(nE, nV[0], aT[0], nV[1], aT[1]);
|
|
if (bCB)
|
|
aCB->SetEdge(nSp);
|
|
else
|
|
aPB->SetEdge(nSp);
|
|
}// if (bRebuild) {
|
|
}// if (aMPB.Add(aPB)) {
|
|
}// for (; aItPB.More(); aItPB.Next()) {
|
|
aMPB.Clear();
|
|
|
|
if (aMicroEdges.Extent())
|
|
RemovePaveBlocks(aMicroEdges);
|
|
}
|
|
//=======================================================================
|
|
//function : RemovePaveBlocks
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::RemovePaveBlocks(const TColStd_MapOfInteger theEdges)
|
|
{
|
|
// Remove all pave blocks referring to input edges:
|
|
//
|
|
// 1. from the Pave Blocks Pool
|
|
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
|
|
Standard_Integer aNbPBP = aPBP.Length(), i;
|
|
for (i = 0; i < aNbPBP; ++i) {
|
|
BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
|
|
//
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItPB(aLPB);
|
|
while (aItPB.More()) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
|
|
if (theEdges.Contains(aPB->Edge()))
|
|
aLPB.Remove(aItPB);
|
|
else
|
|
aItPB.Next();
|
|
}
|
|
}
|
|
|
|
// 2. from section curves
|
|
TColStd_MapOfInteger aMPassed;
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
Standard_Integer aNbFF = aFFs.Length(), j;
|
|
for (i = 0; i < aNbFF; ++i) {
|
|
BOPDS_InterfFF& aFF = aFFs(i);
|
|
// remove from Section pave blocks
|
|
BOPDS_VectorOfCurve& aVNC = aFF.ChangeCurves();
|
|
Standard_Integer aNbC = aVNC.Length();
|
|
for (j = 0; j < aNbC; ++j) {
|
|
BOPDS_Curve& aNC = aVNC(j);
|
|
BOPDS_ListOfPaveBlock& aLPB = aNC.ChangePaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItPB(aLPB);
|
|
while (aItPB.More()) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
|
|
if (theEdges.Contains(aPB->Edge()))
|
|
aLPB.Remove(aItPB);
|
|
else
|
|
aItPB.Next();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. From Face Info
|
|
for (i = 0; i < myDS->NbSourceShapes(); ++i)
|
|
{
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
|
if (aSI.ShapeType() != TopAbs_FACE)
|
|
continue;
|
|
if (!aSI.HasReference())
|
|
continue;
|
|
|
|
BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(i);
|
|
BOPDS_IndexedMapOfPaveBlock* aIMPB[] = { &aFI.ChangePaveBlocksIn(),
|
|
&aFI.ChangePaveBlocksOn(),
|
|
&aFI.ChangePaveBlocksSc() };
|
|
for (Standard_Integer k = 0; k < 3; k++)
|
|
{
|
|
Standard_Integer aNbPB = aIMPB[k]->Extent(), m;
|
|
for (m = 1; m <= aNbPB; ++m)
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = aIMPB[k]->FindKey(m);
|
|
if (theEdges.Contains(aPB->Edge()))
|
|
break;
|
|
}
|
|
if (m <= aNbPB)
|
|
{
|
|
BOPDS_IndexedMapOfPaveBlock aMPBCopy = *aIMPB[k];
|
|
aIMPB[k]->Clear();
|
|
for (m = 1; m <= aNbPB; ++m)
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = aMPBCopy(m);
|
|
if (!theEdges.Contains(aPB->Edge()))
|
|
aIMPB[k]->Add(aPB);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ToleranceFF
|
|
//purpose : Computes the TolFF according to the tolerance value and
|
|
// types of the faces.
|
|
//=======================================================================
|
|
Standard_Real ToleranceFF(const BRepAdaptor_Surface& aBAS1,
|
|
const BRepAdaptor_Surface& aBAS2)
|
|
{
|
|
Standard_Real aTol1 = aBAS1.Tolerance();
|
|
Standard_Real aTol2 = aBAS2.Tolerance();
|
|
Standard_Real aTolFF = Max(aTol1, aTol2);
|
|
//
|
|
Standard_Boolean isAna1, isAna2;
|
|
isAna1 = (aBAS1.GetType() == GeomAbs_Plane ||
|
|
aBAS1.GetType() == GeomAbs_Cylinder ||
|
|
aBAS1.GetType() == GeomAbs_Cone ||
|
|
aBAS1.GetType() == GeomAbs_Sphere ||
|
|
aBAS1.GetType() == GeomAbs_Torus);
|
|
//
|
|
isAna2 = (aBAS2.GetType() == GeomAbs_Plane ||
|
|
aBAS2.GetType() == GeomAbs_Cylinder ||
|
|
aBAS2.GetType() == GeomAbs_Cone ||
|
|
aBAS2.GetType() == GeomAbs_Sphere ||
|
|
aBAS2.GetType() == GeomAbs_Torus);
|
|
//
|
|
if (!isAna1 || !isAna2) {
|
|
aTolFF = Max(aTolFF, 5.e-6);
|
|
}
|
|
return aTolFF;
|
|
}
|
|
//=======================================================================
|
|
//function : UpdateBlocksWithSharedVertices
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::UpdateBlocksWithSharedVertices()
|
|
{
|
|
if (!myNonDestructive) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer aNbFF;
|
|
//
|
|
BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
|
|
aNbFF=aFFs.Length();
|
|
if (!aNbFF) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Boolean bOnCurve, bHasShapeSD;
|
|
Standard_Integer i, nF1, nF2, aNbC, j, nV, nVSD;
|
|
Standard_Real aTolV;
|
|
TColStd_MapOfInteger aMF;
|
|
//
|
|
for (i=0; i<aNbFF; ++i) {
|
|
BOPDS_InterfFF& aFF=aFFs(i);
|
|
//
|
|
BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
|
|
aNbC=aVC.Length();
|
|
if (!aNbC) {
|
|
continue;
|
|
}
|
|
//
|
|
aFF.Indices(nF1, nF2);
|
|
//
|
|
if (aMF.Add(nF1)) {
|
|
myDS->UpdateFaceInfoOn(nF1);
|
|
}
|
|
if (aMF.Add(nF2)) {
|
|
myDS->UpdateFaceInfoOn(nF2);
|
|
}
|
|
//
|
|
// Collect old vertices that are shared for nF1, nF2 ->aMI;
|
|
TColStd_MapOfInteger aMI;
|
|
TColStd_MapIteratorOfMapOfInteger aItMI;
|
|
//
|
|
BOPDS_FaceInfo& aFI1=myDS->ChangeFaceInfo(nF1);
|
|
BOPDS_FaceInfo& aFI2=myDS->ChangeFaceInfo(nF2);
|
|
//
|
|
const TColStd_MapOfInteger& aMVOn1=aFI1.VerticesOn();
|
|
const TColStd_MapOfInteger& aMVIn1=aFI1.VerticesIn();
|
|
const TColStd_MapOfInteger& aMVOn2=aFI2.VerticesOn();
|
|
const TColStd_MapOfInteger& aMVIn2=aFI2.VerticesIn();
|
|
//
|
|
for (j=0; j<2; ++j) {
|
|
const TColStd_MapOfInteger& aMV1=(!j) ? aMVOn1 : aMVIn1;
|
|
aItMI.Initialize(aMV1);
|
|
for (; aItMI.More(); aItMI.Next()) {
|
|
nV=aItMI.Value();
|
|
if (myDS->IsNewShape(nV)) {
|
|
continue;
|
|
}
|
|
if (aMVOn2.Contains(nV) || aMVIn2.Contains(nV)) {
|
|
aMI.Add(nV);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Try to put vertices aMI on curves
|
|
for (j=0; j<aNbC; ++j) {
|
|
BOPDS_Curve& aNC=aVC.ChangeValue(j);
|
|
Standard_Real aTolR3D = Max(aNC.Tolerance(), aNC.TangentialTolerance());
|
|
//
|
|
aItMI.Initialize(aMI);
|
|
for (; aItMI.More(); aItMI.Next()) {
|
|
nV=aItMI.Value();
|
|
//
|
|
bHasShapeSD=myDS->HasShapeSD(nV, nVSD);
|
|
if (bHasShapeSD) {
|
|
continue;
|
|
}
|
|
//
|
|
bOnCurve=EstimatePaveOnCurve(nV, aNC, aTolR3D);
|
|
if (!bOnCurve) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Vertex& aV=*((TopoDS_Vertex *)&myDS->Shape(nV));
|
|
aTolV=BRep_Tool::Tolerance(aV);
|
|
//
|
|
UpdateVertex(nV, aTolV);
|
|
}
|
|
}//for (j=0; j<aNbC; ++j) {
|
|
}//for (i=0; i<aNbFF; ++i) {
|
|
//
|
|
UpdateCommonBlocksWithSDVertices();
|
|
}
|
|
//=======================================================================
|
|
//function : EstimatePaveOnCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::EstimatePaveOnCurve
|
|
(const Standard_Integer nV,
|
|
const BOPDS_Curve& aNC,
|
|
const Standard_Real aTolR3D)
|
|
{
|
|
Standard_Boolean bIsVertexOnLine;
|
|
Standard_Real aT;
|
|
//
|
|
const TopoDS_Vertex& aV=*((TopoDS_Vertex *)&myDS->Shape(nV));
|
|
const IntTools_Curve& aIC=aNC.Curve();
|
|
//
|
|
bIsVertexOnLine=myContext->IsVertexOnLine(aV, aIC, aTolR3D, aT);
|
|
return bIsVertexOnLine;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CorrectToleranceOfSE
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::CorrectToleranceOfSE()
|
|
{
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
NCollection_IndexedDataMap<Standard_Integer,BOPDS_ListOfPaveBlock> aMVIPBs;
|
|
TColStd_MapOfInteger aMVIToReduce;
|
|
// Fence map to avoid repeated checking of the same edge
|
|
BOPDS_MapOfPaveBlock aMPB;
|
|
//
|
|
// 1. iterate on all sections F-F
|
|
Standard_Integer aNb = aFFs.Length(), i;
|
|
for (i = 0; i < aNb; ++i) {
|
|
BOPDS_InterfFF& aFF = aFFs(i);
|
|
//
|
|
BOPDS_VectorOfCurve& aVNC = aFF.ChangeCurves();
|
|
Standard_Integer aNbC = aVNC.Length(), k;
|
|
for (k = 0; k < aNbC; ++k) {
|
|
BOPDS_Curve& aNC = aVNC(k);
|
|
BOPDS_ListOfPaveBlock& aLPB = aNC.ChangePaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
|
|
for (; aItLPB.More(); ) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
|
|
Standard_Integer nE;
|
|
if (!aPB->HasEdge(nE)) {
|
|
aLPB.Remove(aItLPB);
|
|
continue;
|
|
}
|
|
//
|
|
if (!aMPB.Add(aPB)) {
|
|
aItLPB.Next();
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bIsReduced = Standard_False;
|
|
if (aPB->OriginalEdge() < 0) {
|
|
// It is possible that due to small angle between faces the
|
|
// common zone between faces can be large and the tangential
|
|
// tolerance of the curve will be large as well.
|
|
// Here we're trying to reduce the tolerance of the section
|
|
// edge using the valid tolerance of the edge.
|
|
// Note, that if the pave block has created common block with
|
|
// other edges its valid tolerance could have been changed to
|
|
// cover all edges in common block (see PostTreatFF() method).
|
|
Standard_Real aTolC = aNC.Tolerance();
|
|
Standard_Real aTolTang = aNC.TangentialTolerance();
|
|
if (aTolC < aTolTang) {
|
|
const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
|
|
Standard_Real aTolE = BRep_Tool::Tolerance(aE);
|
|
if (aTolC < aTolE) {
|
|
// reduce edge tolerance
|
|
reinterpret_cast<BRep_TEdge*>(aE.TShape().operator->())->Tolerance(aTolC);
|
|
bIsReduced = Standard_True;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// fill in the map vertex index - pave blocks
|
|
for (Standard_Integer j=0; j < 2; j++) {
|
|
Standard_Integer nV = (j == 0 ? aPB->Pave1().Index() : aPB->Pave2().Index());
|
|
myDS->HasShapeSD(nV, nV);
|
|
BOPDS_ListOfPaveBlock *pPBList = aMVIPBs.ChangeSeek(nV);
|
|
if (!pPBList) {
|
|
pPBList = &aMVIPBs.ChangeFromIndex(aMVIPBs.Add(nV, BOPDS_ListOfPaveBlock()));
|
|
}
|
|
pPBList->Append(aPB);
|
|
if (bIsReduced) {
|
|
aMVIToReduce.Add(nV);
|
|
}
|
|
}
|
|
aItLPB.Next();
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMVIToReduce.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// 2. try to reduce tolerances of connected vertices
|
|
// 2.1 find all other edges containing these connected vertices to avoid
|
|
// reducing the tolerance to the value less than the tolerances of edges,
|
|
// i.e. minimal tolerance for the vertex is the max tolerance of the
|
|
// edges containing this vertex
|
|
TColStd_DataMapOfIntegerReal aMVITol;
|
|
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
|
|
aNb = aPBP.Length();
|
|
for (i = 0; i < aNb; ++i) {
|
|
const BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
|
|
Standard_Integer nE;
|
|
if (!aPB->HasEdge(nE)) {
|
|
continue;
|
|
}
|
|
const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
|
|
Standard_Real aTolE = BRep_Tool::Tolerance(aE);
|
|
//
|
|
Standard_Integer nV[2];
|
|
aPB->Indices(nV[0], nV[1]);
|
|
//
|
|
for (Standard_Integer j = 0; j < 2; j++) {
|
|
if (aMVIToReduce.Contains(nV[j])) {
|
|
Standard_Real *aMaxTol = aMVITol.ChangeSeek(nV[j]);
|
|
if (!aMaxTol) {
|
|
aMVITol.Bind(nV[j], aTolE);
|
|
}
|
|
else if (aTolE > *aMaxTol) {
|
|
*aMaxTol = aTolE;
|
|
}
|
|
BOPDS_ListOfPaveBlock& aPBList = aMVIPBs.ChangeFromKey(nV[j]);
|
|
aPBList.Append(aPB);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// 2.2 reduce tolerances if possible
|
|
aNb = aMVIPBs.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
Standard_Integer nV = aMVIPBs.FindKey(i);
|
|
if (!aMVIToReduce.Contains(nV)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV));
|
|
Standard_Real aTolV = BRep_Tool::Tolerance(aV);
|
|
Standard_Real aMaxTol = aMVITol.IsBound(nV) ? aMVITol.Find(nV) : 0.;
|
|
// it makes no sense to compute the real tolerance if it is
|
|
// impossible to reduce the tolerance at least 0.1% of the current value
|
|
if (aTolV - aMaxTol < 0.001 * aTolV) {
|
|
continue;
|
|
}
|
|
//
|
|
// compute the maximal distance from the vertex to the adjacent edges
|
|
gp_Pnt aP = BRep_Tool::Pnt(aV);
|
|
//
|
|
// Avoid repeated checks
|
|
BOPDS_MapOfPaveBlock aMPBFence;
|
|
//
|
|
const BOPDS_ListOfPaveBlock& aLPB = aMVIPBs.FindFromIndex(i);
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
|
|
if (!aMPBFence.Add(aPB)) {
|
|
continue;
|
|
}
|
|
Standard_Integer nE = aPB->Edge();
|
|
const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
|
|
BRepAdaptor_Curve aC(aE);
|
|
for (Standard_Integer iPave = 0; iPave < 2; ++iPave) {
|
|
const BOPDS_Pave& aPave = !iPave ? aPB->Pave1() : aPB->Pave2();
|
|
Standard_Integer nVSD = aPave.Index();
|
|
myDS->HasShapeSD(nVSD, nVSD);
|
|
if (nVSD != nV) {
|
|
continue;
|
|
}
|
|
//
|
|
gp_Pnt aPonE = aC.Value(aPave.Parameter());
|
|
Standard_Real aDist = aP.Distance(aPonE);
|
|
aDist += BRep_Tool::Tolerance(aE);
|
|
if (aDist > aMaxTol) {
|
|
aMaxTol = aDist;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMaxTol < aTolV) {
|
|
reinterpret_cast<BRep_TVertex*>(aV.TShape().operator->())->Tolerance(aMaxTol);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : PutSEInOtherFaces
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PutSEInOtherFaces()
|
|
{
|
|
// Try to intersect each section edge with the faces
|
|
// not participated in its creation
|
|
|
|
// Get all section edges
|
|
BOPDS_IndexedMapOfPaveBlock aMPBScAll;
|
|
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
const Standard_Integer aNbFF = aFFs.Length();
|
|
for (Standard_Integer i = 0; i < aNbFF; ++i)
|
|
{
|
|
const BOPDS_VectorOfCurve& aVNC = aFFs(i).Curves();
|
|
const Standard_Integer aNbC = aVNC.Length();
|
|
for (Standard_Integer j = 0; j < aNbC; ++j)
|
|
{
|
|
const BOPDS_ListOfPaveBlock& aLPBC = aVNC(j).PaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItPB(aLPBC);
|
|
for (; aItPB.More(); aItPB.Next())
|
|
aMPBScAll.Add(aItPB.Value());
|
|
}
|
|
}
|
|
// Perform intersection of collected pave blocks
|
|
ForceInterfEF(aMPBScAll, Standard_False);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RemoveMicroSectionEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::RemoveMicroSectionEdges
|
|
(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
|
|
BOPDS_IndexedMapOfPaveBlock& theMicroPB)
|
|
{
|
|
if (theMSCPB.IsEmpty())
|
|
// no section edges
|
|
return;
|
|
|
|
// Get all F/F interferences
|
|
BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
|
|
|
|
// Build the new map of section edges avoiding the micro edges
|
|
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aSEPBMap;
|
|
// Analyze all section edges
|
|
Standard_Integer aNbCPB = theMSCPB.Extent();
|
|
for (Standard_Integer i = 1; i <= aNbCPB; ++i)
|
|
{
|
|
const TopoDS_Shape& aSI = theMSCPB.FindKey(i);
|
|
const BOPDS_CoupleOfPaveBlocks& aCPB = theMSCPB(i);
|
|
|
|
if (aSI.ShapeType() != TopAbs_EDGE)
|
|
{
|
|
// Not an edge
|
|
aSEPBMap.Add(aSI, aCPB);
|
|
continue;
|
|
}
|
|
|
|
// Get pave block for analysis
|
|
const Handle(BOPDS_PaveBlock)& aPB = aCPB.PaveBlock1();
|
|
if (aPB->HasEdge())
|
|
{
|
|
// Not a real section edge
|
|
aSEPBMap.Add(aSI, aCPB);
|
|
continue;
|
|
}
|
|
|
|
if (!BOPTools_AlgoTools::IsMicroEdge(TopoDS::Edge(aSI), myContext, Standard_False))
|
|
{
|
|
// Normal edge
|
|
aSEPBMap.Add(aSI, aCPB);
|
|
continue;
|
|
}
|
|
|
|
// Micro edge is found, avoid it in the <theMSCPB> map
|
|
// and remove from the F/F Intersection info structure
|
|
|
|
// Get F/F interference which created this micro edge
|
|
BOPDS_InterfFF& aFF = aFFs(aCPB.IndexInterf());
|
|
// Get curve from which this edge has been created
|
|
BOPDS_Curve& aCurve = aFF.ChangeCurves().ChangeValue(aCPB.Index());
|
|
// Get all section pave blocks created from this curve
|
|
BOPDS_ListOfPaveBlock& aLPBC = aCurve.ChangePaveBlocks();
|
|
// Remove pave block from the list
|
|
for (BOPDS_ListIteratorOfListOfPaveBlock it(aLPBC); it.More(); it.Next())
|
|
{
|
|
if (it.Value() == aPB)
|
|
{
|
|
aLPBC.Remove(it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Add the pave block of "micro" edge into outgoing map for
|
|
// unification of its vertices in the PostTreatFF method
|
|
theMicroPB.Add(aPB);
|
|
}
|
|
|
|
// Overwrite the old map if necessary
|
|
if (aSEPBMap.Extent() != theMSCPB.Extent())
|
|
theMSCPB = aSEPBMap;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RemoveMicroEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::RemoveMicroEdges()
|
|
{
|
|
// Fence map
|
|
BOPDS_MapOfPaveBlock aMPBFence;
|
|
// Resulting map of micro edges
|
|
TColStd_MapOfInteger aMicroEdges;
|
|
// Check all pave blocks from the pool to find the micro edges
|
|
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
|
|
Standard_Integer aNbPBP = aPBP.Length();
|
|
for (Standard_Integer i = 0; i < aNbPBP; ++i)
|
|
{
|
|
BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
|
|
if (aLPB.Extent() < 2)
|
|
// No splits
|
|
continue;
|
|
|
|
if (myDS->ShapeInfo(aLPB.First()->OriginalEdge()).HasFlag())
|
|
continue;
|
|
|
|
BOPDS_ListOfPaveBlock::Iterator it(aLPB);
|
|
for (; it.More(); it.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = it.Value();
|
|
Handle(BOPDS_PaveBlock) aPBR = myDS->RealPaveBlock(aPB);
|
|
|
|
if (aMPBFence.Add(aPBR))
|
|
{
|
|
Standard_Integer nV1, nV2;
|
|
aPBR->Indices(nV1, nV2);
|
|
if (nV1 == nV2)
|
|
{
|
|
// Check if it has the valid range
|
|
FillShrunkData(aPBR);
|
|
if (!aPBR->HasShrunkData())
|
|
aMicroEdges.Add(aPBR->Edge());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
RemovePaveBlocks(aMicroEdges);
|
|
}
|