mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-21 10:13:43 +03:00
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast Wrong license statements corrected in several files. Copyright and license statements added in XSD and GLSL files. Copyright year updated in some files. Obsolete documentation files removed from DrawResources.
1941 lines
54 KiB
C++
1941 lines
54 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 <BOPTools_AlgoTools.ixx>
|
|
//
|
|
#include <Precision.hxx>
|
|
//
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_XYZ.hxx>
|
|
#include <gp_Pnt2d.hxx>
|
|
#include <gp_Cylinder.hxx>
|
|
#include <gp_Cone.hxx>
|
|
#include <gp_Sphere.hxx>
|
|
#include <gp_Torus.hxx>
|
|
#include <gp_Lin.hxx>
|
|
//
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <Geom_Surface.hxx>
|
|
#include <Geom_Plane.hxx>
|
|
#include <Geom_TrimmedCurve.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <GeomAPI_ProjectPointOnSurf.hxx>
|
|
#include <Geom2dInt_Geom2dCurveTool.hxx>
|
|
//
|
|
#include <TopAbs_Orientation.hxx>
|
|
//
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TopoDS_CompSolid.hxx>
|
|
#include <TopoDS_Solid.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
//
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepLib.hxx>
|
|
#include <BRepAdaptor_Curve2d.hxx>
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
#include <BRepClass3d_SolidClassifier.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
//
|
|
#include <IntTools_Tools.hxx>
|
|
//
|
|
#include <BOPTools.hxx>
|
|
#include <BOPTools_CoupleOfShape.hxx>
|
|
#include <BOPTools_ListOfCoupleOfShape.hxx>
|
|
#include <BOPTools_AlgoTools2D.hxx>
|
|
#include <BOPTools_AlgoTools3D.hxx>
|
|
//
|
|
#include <BOPCol_IndexedMapOfShape.hxx>
|
|
#include <BOPCol_MapOfShape.hxx>
|
|
//
|
|
#include <BOPInt_ShrunkRange.hxx>
|
|
//
|
|
|
|
static
|
|
Standard_Real AngleWithRef(const gp_Dir& theD1,
|
|
const gp_Dir& theD2,
|
|
const gp_Dir& theDRef);
|
|
|
|
static
|
|
Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
|
|
const BOPCol_ListOfShape& thLF,
|
|
BOPTools_ListOfCoupleOfShape& theLCFF,
|
|
Handle(BOPInt_Context)& theContext);
|
|
static
|
|
TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
|
|
const TopoDS_Face& aF);
|
|
|
|
static
|
|
void GetFaceDir(const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF,
|
|
const gp_Pnt& aP,
|
|
const Standard_Real aT,
|
|
const gp_Dir& aDTgt,
|
|
gp_Dir& aDN,
|
|
gp_Dir& aDB,
|
|
Handle(BOPInt_Context)& theContext,
|
|
GeomAPI_ProjectPointOnSurf& aProjPL);
|
|
static
|
|
Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF,
|
|
const gp_Pnt& aP,
|
|
gp_Dir& aDB,
|
|
gp_Pnt& aPOut,
|
|
Handle(BOPInt_Context)& theContext,
|
|
GeomAPI_ProjectPointOnSurf& aProjPL);
|
|
|
|
//=======================================================================
|
|
// function: MakeConnexityBlocks
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakeConnexityBlocks (const TopoDS_Shape& theS,
|
|
const TopAbs_ShapeEnum theType1,
|
|
const TopAbs_ShapeEnum theType2,
|
|
BOPCol_ListOfShape& theLCB)
|
|
{
|
|
Standard_Integer aNbF, aNbAdd, aNbAdd1, i;
|
|
BRep_Builder aBB;
|
|
TopoDS_Compound aC;
|
|
TopoDS_Iterator aIt;
|
|
TopExp_Explorer aExp;
|
|
BOPCol_MapOfShape aMP;
|
|
BOPCol_IndexedMapOfShape aMCB, aMAdd, aMAdd1;
|
|
BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
|
|
BOPCol_ListIteratorOfListOfShape aItLF;
|
|
//
|
|
// 1. aMEF
|
|
BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aMEF);
|
|
//
|
|
// 2. aMCB
|
|
aIt.Initialize(theS);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF1=aIt.Value();
|
|
if (aMP.Contains(aF1)) {
|
|
continue;
|
|
}
|
|
//
|
|
aMCB.Clear();
|
|
aMAdd.Clear();
|
|
aMAdd.Add(aF1);
|
|
//
|
|
for(;;) {
|
|
aMAdd1.Clear();
|
|
//
|
|
aNbAdd = aMAdd.Extent();
|
|
for (i=1; i<=aNbAdd; ++i) {
|
|
const TopoDS_Shape& aF=aMAdd(i);
|
|
//
|
|
aExp.Init(aF, theType1);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE=aExp.Current();
|
|
//
|
|
const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
|
|
aItLF.Initialize(aLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aFx=aItLF.Value();
|
|
if (aFx.IsSame(aF)) {
|
|
continue;
|
|
}
|
|
if (aMCB.Contains(aFx)) {
|
|
continue;
|
|
}
|
|
aMAdd1.Add(aFx);
|
|
}
|
|
}//for (; aExp.More(); aExp.Next()){
|
|
aMCB.Add(aF);
|
|
}// for (i=1; i<=aNbAdd; ++i) {
|
|
//
|
|
aNbAdd1=aMAdd1.Extent();
|
|
if (!aNbAdd1) {
|
|
break;// ->make new CB from aMCB
|
|
}
|
|
//
|
|
aMAdd.Clear();
|
|
for (i=1; i<=aNbAdd1; ++i) {
|
|
const TopoDS_Shape& aFAdd = aMAdd1(i);
|
|
aMAdd.Add(aFAdd);
|
|
}
|
|
}//while(1) {
|
|
//
|
|
aNbF=aMCB.Extent();
|
|
if (aNbF) {
|
|
aBB.MakeCompound(aC);
|
|
//
|
|
for (i=1; i<=aNbF; ++i) {
|
|
const TopoDS_Shape& aF=aMCB(i);
|
|
aBB.Add(aC, aF);
|
|
aMP.Add(aF);
|
|
}
|
|
theLCB.Append(aC);
|
|
}
|
|
}// for (; aIt.More(); aIt.Next())
|
|
}
|
|
//=======================================================================
|
|
// function: OrientFacesOnShell
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
|
|
{
|
|
Standard_Boolean bIsProcessed1, bIsProcessed2;
|
|
Standard_Integer i, aNbE, aNbF, j;
|
|
TopAbs_Orientation anOrE1, anOrE2;
|
|
TopoDS_Face aF1x, aF2x;
|
|
TopoDS_Shape aShellNew;
|
|
BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
|
|
BOPCol_IndexedMapOfShape aProcessedFaces;
|
|
BRep_Builder aBB;
|
|
//
|
|
BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
|
|
//
|
|
BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
|
|
aNbE=aEFMap.Extent();
|
|
//
|
|
// One seam edge in aEFMap contains 2 equivalent faces.
|
|
for (i=1; i<=aNbE; ++i) {
|
|
BOPCol_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
|
|
aNbF=aLF.Extent();
|
|
if (aNbF>1) {
|
|
BOPCol_ListOfShape aLFTmp;
|
|
BOPCol_IndexedMapOfShape aFM;
|
|
//
|
|
BOPCol_ListIteratorOfListOfShape anIt(aLF);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const TopoDS_Shape& aF=anIt.Value();
|
|
if (!aFM.Contains(aF)) {
|
|
aFM.Add(aF);
|
|
aLFTmp.Append(aF);
|
|
}
|
|
}
|
|
aLF.Clear();
|
|
aLF=aLFTmp;
|
|
}
|
|
}
|
|
//
|
|
// Do
|
|
for (i=1; i<=aNbE; ++i) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
|
|
aNbF=aLF.Extent();
|
|
if (aNbF!=2) {
|
|
continue;
|
|
}
|
|
//
|
|
TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
|
|
TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
|
|
//
|
|
bIsProcessed1=aProcessedFaces.Contains(aF1);
|
|
bIsProcessed2=aProcessedFaces.Contains(aF2);
|
|
if (bIsProcessed1 && bIsProcessed2) {
|
|
continue;
|
|
}
|
|
|
|
if (!bIsProcessed1 && !bIsProcessed2) {
|
|
aProcessedFaces.Add(aF1);
|
|
aBB.Add(aShellNew, aF1);
|
|
bIsProcessed1=!bIsProcessed1;
|
|
}
|
|
//
|
|
aF1x=aF1;
|
|
if (bIsProcessed1) {
|
|
j=aProcessedFaces.FindIndex(aF1);
|
|
aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
|
|
}
|
|
//
|
|
aF2x=aF2;
|
|
if (bIsProcessed2) {
|
|
j=aProcessedFaces.FindIndex(aF2);
|
|
aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
|
|
}
|
|
//
|
|
anOrE1=Orientation(aE, aF1x);
|
|
anOrE2=Orientation(aE, aF2x);
|
|
//
|
|
if (bIsProcessed1 && !bIsProcessed2) {
|
|
if (anOrE1==anOrE2) {
|
|
if (!BRep_Tool::IsClosed(aE, aF1) &&
|
|
!BRep_Tool::IsClosed(aE, aF2)) {
|
|
aF2.Reverse();
|
|
}
|
|
}
|
|
aProcessedFaces.Add(aF2);
|
|
aBB.Add(aShellNew, aF2);
|
|
}
|
|
else if (!bIsProcessed1 && bIsProcessed2) {
|
|
if (anOrE1==anOrE2) {
|
|
if (!BRep_Tool::IsClosed(aE, aF1) &&
|
|
!BRep_Tool::IsClosed(aE, aF2)) {
|
|
aF1.Reverse();
|
|
}
|
|
}
|
|
aProcessedFaces.Add(aF1);
|
|
aBB.Add(aShellNew, aF1);
|
|
}
|
|
}
|
|
//
|
|
//
|
|
for (i=1; i<=aNbE; ++i) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
|
|
aNbF=aLF.Extent();
|
|
if (aNbF!=2) {
|
|
BOPCol_ListIteratorOfListOfShape anIt(aLF);
|
|
for(; anIt.More(); anIt.Next()) {
|
|
const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
|
|
if (!aProcessedFaces.Contains(aF)) {
|
|
aProcessedFaces.Add(aF);
|
|
aBB.Add(aShellNew, aF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
aShell=aShellNew;
|
|
}
|
|
//=======================================================================
|
|
//function : Orientation
|
|
//purpose :
|
|
//=======================================================================
|
|
TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
|
|
const TopoDS_Face& aF)
|
|
{
|
|
TopAbs_Orientation anOr=TopAbs_INTERNAL;
|
|
|
|
TopExp_Explorer anExp;
|
|
anExp.Init(aF, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
|
|
if (anEF1.IsSame(anE)) {
|
|
anOr=anEF1.Orientation();
|
|
break;
|
|
}
|
|
}
|
|
return anOr;
|
|
}
|
|
|
|
////////////
|
|
|
|
|
|
//=======================================================================
|
|
// function: MakeConnexityBlock.
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
|
|
BOPCol_IndexedMapOfShape& theMEAvoid,
|
|
BOPCol_ListOfShape& theLCB,
|
|
const Handle(NCollection_BaseAllocator)& theAllocator)
|
|
{
|
|
Standard_Integer aNbF, aNbAdd1, aNbAdd, i;
|
|
TopExp_Explorer aExp;
|
|
BOPCol_ListIteratorOfListOfShape aIt;
|
|
//
|
|
BOPCol_IndexedMapOfShape aMCB(100, theAllocator);
|
|
BOPCol_IndexedMapOfShape aMAdd(100, theAllocator);
|
|
BOPCol_IndexedMapOfShape aMAdd1(100, theAllocator);
|
|
BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
|
|
//
|
|
// 1. aMEF
|
|
aNbF=theLFIn.Extent();
|
|
aIt.Initialize(theLFIn);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF=aIt.Value();
|
|
BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
|
|
}
|
|
//
|
|
// 2. aMCB
|
|
const TopoDS_Shape& aF1=theLFIn.First();
|
|
aMAdd.Add(aF1);
|
|
//
|
|
for(;;) {
|
|
aMAdd1.Clear();
|
|
aNbAdd = aMAdd.Extent();
|
|
for (i=1; i<=aNbAdd; ++i) {
|
|
const TopoDS_Shape& aF=aMAdd(i);
|
|
//
|
|
//aMAdd1.Clear();
|
|
aExp.Init(aF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE=aExp.Current();
|
|
if (theMEAvoid.Contains(aE)){
|
|
continue;
|
|
}
|
|
//
|
|
const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
|
|
aIt.Initialize(aLF);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aFx=aIt.Value();
|
|
if (aFx.IsSame(aF)) {
|
|
continue;
|
|
}
|
|
if (aMCB.Contains(aFx)) {
|
|
continue;
|
|
}
|
|
aMAdd1.Add(aFx);
|
|
}
|
|
}//for (; aExp.More(); aExp.Next()){
|
|
aMCB.Add(aF);
|
|
}// for (i=1; i<=aNbAdd; ++i) {
|
|
//
|
|
aNbAdd1=aMAdd1.Extent();
|
|
if (!aNbAdd1) {
|
|
break;
|
|
}
|
|
//
|
|
aMAdd.Clear();
|
|
for (i=1; i<=aNbAdd1; ++i) {
|
|
const TopoDS_Shape& aFAdd=aMAdd1(i);
|
|
aMAdd.Add(aFAdd);
|
|
}
|
|
//
|
|
}//while(1) {
|
|
|
|
//
|
|
aNbF=aMCB.Extent();
|
|
for (i=1; i<=aNbF; ++i) {
|
|
const TopoDS_Shape& aF=aMCB(i);
|
|
theLCB.Append(aF);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeStateByOnePoint
|
|
// purpose:
|
|
//=======================================================================
|
|
TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS,
|
|
const TopoDS_Solid& theRef,
|
|
const Standard_Real theTol,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
TopAbs_State aState;
|
|
TopAbs_ShapeEnum aType;
|
|
//
|
|
aState=TopAbs_UNKNOWN;
|
|
aType=theS.ShapeType();
|
|
if (aType==TopAbs_VERTEX) {
|
|
const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
|
|
aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
|
|
}
|
|
else if (aType==TopAbs_EDGE) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
|
|
aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
|
|
}
|
|
return aState;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: ComputeState
|
|
// purpose:
|
|
//=======================================================================
|
|
TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
|
|
const TopoDS_Solid& theRef,
|
|
const Standard_Real theTol,
|
|
BOPCol_IndexedMapOfShape& theBounds,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
TopAbs_State aState;
|
|
TopExp_Explorer aExp;
|
|
TopoDS_Edge aE1;
|
|
gp_Pnt2d aP2D;
|
|
gp_Pnt aP3D;
|
|
//
|
|
aState=TopAbs_UNKNOWN;
|
|
//
|
|
aExp.Init(theF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (BRep_Tool::Degenerated(aSE)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (!theBounds.Contains(aSE)) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
|
|
aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
|
|
return aState;
|
|
}
|
|
if (aE1.IsNull()) {
|
|
aE1=(*(TopoDS_Edge*)(&aSE));
|
|
}
|
|
}
|
|
// !!<- process edges that are all on theRef
|
|
if (!aE1.IsNull()) {
|
|
BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, aP2D, aP3D, theContext);
|
|
aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
|
|
}
|
|
//
|
|
return aState;
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeState
|
|
// purpose:
|
|
//=======================================================================
|
|
TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Vertex& theV,
|
|
const TopoDS_Solid& theRef,
|
|
const Standard_Real theTol,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
TopAbs_State aState;
|
|
gp_Pnt aP3D;
|
|
//
|
|
aP3D=BRep_Tool::Pnt(theV);
|
|
aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
|
|
return aState;
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeState
|
|
// purpose:
|
|
//=======================================================================
|
|
TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
|
|
const TopoDS_Solid& theRef,
|
|
const Standard_Real theTol,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Real aT1, aT2, aT = 0.;
|
|
TopAbs_State aState;
|
|
Handle(Geom_Curve) aC3D;
|
|
gp_Pnt aP3D;
|
|
//
|
|
aC3D = BRep_Tool::Curve(theE, aT1, aT2);
|
|
//
|
|
if(aC3D.IsNull()) {
|
|
//it means that we are in degenerated edge
|
|
const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
|
|
if(aV.IsNull()){
|
|
return TopAbs_UNKNOWN;
|
|
}
|
|
aP3D=BRep_Tool::Pnt(aV);
|
|
}
|
|
else {//usual case
|
|
Standard_Boolean bF2Inf, bL2Inf;
|
|
Standard_Real dT=10.;
|
|
//
|
|
bF2Inf = Precision::IsNegativeInfinite(aT1);
|
|
bL2Inf = Precision::IsPositiveInfinite(aT2);
|
|
//
|
|
if (bF2Inf && !bL2Inf) {
|
|
aT=aT2-dT;
|
|
}
|
|
else if (!bF2Inf && bL2Inf) {
|
|
aT=aT1+dT;
|
|
}
|
|
else if (bF2Inf && bL2Inf) {
|
|
aT=0.;
|
|
}
|
|
else {
|
|
aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
|
|
}
|
|
aC3D->D0(aT, aP3D);
|
|
}
|
|
//
|
|
aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
|
|
//
|
|
return aState;
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeState
|
|
// purpose:
|
|
//=======================================================================
|
|
TopAbs_State BOPTools_AlgoTools::ComputeState(const gp_Pnt& theP,
|
|
const TopoDS_Solid& theRef,
|
|
const Standard_Real theTol,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
TopAbs_State aState;
|
|
//
|
|
BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
|
|
aSC.Perform(theP, theTol);
|
|
//
|
|
aState=aSC.State();
|
|
//
|
|
return aState;
|
|
}
|
|
//=======================================================================
|
|
//function : IsInternalFace
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::IsInternalFace
|
|
(const TopoDS_Face& theFace,
|
|
const TopoDS_Solid& theSolid,
|
|
BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
|
|
const Standard_Real theTol,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bDegenerated;
|
|
Standard_Integer aNbF, iRet, iFound;
|
|
TopAbs_Orientation aOr;
|
|
TopoDS_Edge aE1;
|
|
TopExp_Explorer aExp;
|
|
BOPCol_ListIteratorOfListOfShape aItF;
|
|
//
|
|
// For all invoked functions: [::IsInternalFace(...)]
|
|
// the returned value iRet means:
|
|
// iRet=0; - state is not IN
|
|
// iRet=1; - state is IN
|
|
// iRet=2; - state can not be found by the method of angles
|
|
//
|
|
// For this function the returned value iRet means:
|
|
// iRet=0; - state is not IN
|
|
// iRet=1; - state is IN
|
|
//
|
|
iRet=0;
|
|
// 1 Try to find an edge from theFace in theMEF
|
|
iFound=0;
|
|
aExp.Init(theFace, TopAbs_EDGE);
|
|
for(; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (!theMEF.Contains(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
++iFound;
|
|
//
|
|
aOr=aE.Orientation();
|
|
if (aOr==TopAbs_INTERNAL) {
|
|
continue;
|
|
}
|
|
bDegenerated=BRep_Tool::Degenerated(aE);
|
|
if (bDegenerated){
|
|
continue;
|
|
}
|
|
// aE
|
|
BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
|
|
aNbF=aLF.Extent();
|
|
if (!aNbF) {
|
|
return iRet; // it can not be so
|
|
}
|
|
//
|
|
else if (aNbF==1) {
|
|
// aE is internal edge on aLF.First()
|
|
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
|
|
BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
|
|
if (aE1.Orientation()!=TopAbs_INTERNAL) {
|
|
iRet=2;
|
|
break;
|
|
}
|
|
//
|
|
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, theContext);
|
|
break;
|
|
}
|
|
//
|
|
else if (aNbF==2) {
|
|
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
|
|
const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
|
|
//
|
|
if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
|
|
// treat as it was for 1 face
|
|
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, theContext);
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (aNbF%2) {
|
|
iRet=0;
|
|
return iRet; // it can not be so
|
|
}
|
|
else { // aNbF=2,4,6,8,...
|
|
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, theContext);
|
|
break;
|
|
}
|
|
}//for(; aExp.More(); aExp.Next()) {
|
|
//
|
|
if (!iFound) {
|
|
// the face has no shared edges with the solid
|
|
iRet=2;
|
|
}
|
|
//
|
|
if (iRet!=2) {
|
|
return iRet;
|
|
}
|
|
//
|
|
//========================================
|
|
// 2. Classify face using classifier
|
|
//
|
|
TopAbs_State aState;
|
|
BOPCol_IndexedMapOfShape aBounds;
|
|
//
|
|
BOPTools::MapShapes(theSolid, TopAbs_EDGE, aBounds);
|
|
//
|
|
aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
|
|
//
|
|
iRet=(aState==TopAbs_IN)? 1 : 0;
|
|
//
|
|
return iRet;
|
|
}
|
|
//=======================================================================
|
|
//function : IsInternalFace
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
|
|
const TopoDS_Edge& theEdge,
|
|
BOPCol_ListOfShape& theLF,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Integer aNbF, iRet;
|
|
//
|
|
iRet=0;
|
|
//
|
|
aNbF=theLF.Extent();
|
|
if (aNbF==2) {
|
|
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
|
|
const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
|
|
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
|
|
return iRet;
|
|
}
|
|
//
|
|
else {
|
|
BOPTools_ListOfCoupleOfShape aLCFF;
|
|
BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
|
|
//
|
|
FindFacePairs(theEdge, theLF, aLCFF, theContext);
|
|
//
|
|
aIt.Initialize(aLCFF);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
|
|
//
|
|
const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
|
|
const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
|
|
iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
|
|
if (iRet) {
|
|
return iRet;
|
|
}
|
|
}
|
|
}
|
|
return iRet;
|
|
}
|
|
//=======================================================================
|
|
//function : IsInternalFace
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::IsInternalFace
|
|
(const TopoDS_Face& theFace,
|
|
const TopoDS_Edge& theEdge,
|
|
const TopoDS_Face& theFace1,
|
|
const TopoDS_Face& theFace2,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Integer iRet;
|
|
TopoDS_Edge aE1, aE2;
|
|
TopoDS_Face aFOff;
|
|
BOPTools_ListOfCoupleOfShape theLCSOff;
|
|
BOPTools_CoupleOfShape aCS1, aCS2;
|
|
//
|
|
BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
|
|
if (aE1.Orientation()==TopAbs_INTERNAL) {
|
|
aE2=aE1;
|
|
aE1.Orientation(TopAbs_FORWARD);
|
|
aE2.Orientation(TopAbs_REVERSED);
|
|
}
|
|
else if (theFace1==theFace2) {
|
|
aE2=aE1;
|
|
aE1.Orientation(TopAbs_FORWARD);
|
|
aE2.Orientation(TopAbs_REVERSED);
|
|
}
|
|
else {
|
|
BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
|
|
}
|
|
//
|
|
aCS1.SetShape1(theEdge);
|
|
aCS1.SetShape2(theFace);
|
|
theLCSOff.Append(aCS1);
|
|
//
|
|
aCS2.SetShape1(aE2);
|
|
aCS2.SetShape2(theFace2);
|
|
theLCSOff.Append(aCS2);
|
|
//
|
|
bRet=GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
|
|
//
|
|
iRet=0; // theFace is not internal
|
|
if (theFace.IsEqual(aFOff)) {
|
|
// theFace is internal
|
|
iRet=1;
|
|
if (!bRet) {
|
|
// theFace seems to be internal
|
|
iRet=2;
|
|
}
|
|
}
|
|
return iRet;
|
|
}
|
|
//=======================================================================
|
|
//function : GetFaceOff
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::GetFaceOff
|
|
(const TopoDS_Edge& theE1,
|
|
const TopoDS_Face& theF1,
|
|
BOPTools_ListOfCoupleOfShape& theLCSOff,
|
|
TopoDS_Face& theFOff,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
|
|
Standard_Real aUmin, aUsup, aVmin, aVsup;
|
|
gp_Pnt aPn1, aPn2, aPx;
|
|
gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
|
|
gp_Vec aVTgt;
|
|
TopAbs_Orientation aOr;
|
|
Handle(Geom_Curve)aC3D;
|
|
Handle(Geom_Plane) aPL;
|
|
BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
|
|
GeomAPI_ProjectPointOnSurf aProjPL;
|
|
//
|
|
aAngleMin=100.;
|
|
aTwoPI=M_PI+M_PI;
|
|
aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
|
|
aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
|
|
aC3D->D0(aT, aPx);
|
|
//
|
|
BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
|
|
gp_Dir aDTgt(aVTgt), aDTgt2;
|
|
aOr = theE1.Orientation();
|
|
//
|
|
aPL = new Geom_Plane(aPx, aDTgt);
|
|
aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
|
|
aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
|
|
//
|
|
GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext, aProjPL);
|
|
//
|
|
aDTF=aDN1^aDBF;
|
|
//
|
|
bRet=Standard_True;
|
|
aIt.Initialize(theLCSOff);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const BOPTools_CoupleOfShape& aCS=aIt.Value();
|
|
const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
|
|
const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
|
|
//
|
|
aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
|
|
GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext, aProjPL);
|
|
//Angle
|
|
aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
|
|
//
|
|
if(aAngle<0.) {
|
|
aAngle=aTwoPI+aAngle;
|
|
}
|
|
//
|
|
if (aAngle<Precision::Angular()) {
|
|
if (aF2==theF1) {
|
|
aAngle=M_PI;
|
|
}
|
|
else if (aF2.IsSame(theF1)) {
|
|
aAngle=aTwoPI;
|
|
}
|
|
}
|
|
//
|
|
if (aAngle<aAngleMin){
|
|
aAngleMin=aAngle;
|
|
theFOff=aF2;
|
|
}
|
|
else if (aAngle==aAngleMin) {
|
|
// the minimal angle can not be found
|
|
bRet=Standard_False;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
//function : GetEdgeOff
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
|
|
const TopoDS_Face& theF2,
|
|
TopoDS_Edge& theE2)
|
|
{
|
|
Standard_Boolean bFound;
|
|
TopAbs_Orientation aOr1, aOr1C, aOr2;
|
|
TopExp_Explorer anExp;
|
|
//
|
|
bFound=Standard_False;
|
|
aOr1=theE1.Orientation();
|
|
aOr1C=TopAbs::Reverse(aOr1);
|
|
//
|
|
anExp.Init(theF2, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
|
|
if (aEF2.IsSame(theE1)) {
|
|
aOr2=aEF2.Orientation();
|
|
if (aOr2==aOr1C) {
|
|
theE2=aEF2;
|
|
bFound=!bFound;
|
|
return bFound;
|
|
}
|
|
}
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : AreFacesSameDomain
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
|
|
const TopoDS_Face& theF2,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bFlag;
|
|
Standard_Integer iErr;
|
|
Standard_Real aTolF1, aTolF2, aTol;
|
|
gp_Pnt2d aP2D;
|
|
gp_Pnt aP;
|
|
TopoDS_Face aF1, aF2;
|
|
TopoDS_Edge aE1;
|
|
TopExp_Explorer aExp;
|
|
//
|
|
bFlag=Standard_False;
|
|
//
|
|
aF1=theF1;
|
|
aF1.Orientation(TopAbs_FORWARD);
|
|
aF2=theF2;
|
|
aF2.Orientation(TopAbs_FORWARD);
|
|
//
|
|
aTolF1=BRep_Tool::Tolerance(aF1);
|
|
// 1
|
|
aExp.Init(aF1, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
aE1=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (!BRep_Tool::Degenerated(aE1)) {
|
|
Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
|
|
aTolF1 = (aTolE > aTolF1) ? aTolE : aTolF1;
|
|
}
|
|
}
|
|
// 2
|
|
aTolF2=BRep_Tool::Tolerance(aF2);
|
|
aTol=aTolF1+aTolF2;
|
|
//
|
|
iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D, theContext);
|
|
if (!iErr) {
|
|
bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
|
|
}
|
|
//
|
|
return bFlag;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CheckSameGeom
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::CheckSameGeom(const TopoDS_Face& theF1,
|
|
const TopoDS_Face& theF2,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Real aTolF1, aTolF2, aTol;
|
|
gp_Pnt2d aP2D;
|
|
gp_Pnt aP;
|
|
TopExp_Explorer aExp;
|
|
//
|
|
bRet=Standard_False;
|
|
aExp.Init(theF1, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (!BRep_Tool::Degenerated(aE)) {
|
|
aTolF1=BRep_Tool::Tolerance(theF1);
|
|
aTolF2=BRep_Tool::Tolerance(theF2);
|
|
aTol=aTolF1+aTolF2;
|
|
BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
|
|
bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
|
|
break;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
// function: Sense
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
|
|
const TopoDS_Face& theF2)
|
|
{
|
|
Standard_Integer iSense=0;
|
|
gp_Dir aDNF1, aDNF2;
|
|
TopoDS_Edge aE1, aE2;
|
|
TopExp_Explorer aExp;
|
|
//
|
|
aExp.Init(theF1, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
aE1=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (!BRep_Tool::Degenerated(aE1)) {
|
|
if (!BRep_Tool::IsClosed(aE1, theF1)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aExp.Init(theF2, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
aE2=(*(TopoDS_Edge*)(&aExp.Current()));
|
|
if (!BRep_Tool::Degenerated(aE2)) {
|
|
if (!BRep_Tool::IsClosed(aE2, theF2)) {
|
|
if (aE2.IsSame(aE1)) {
|
|
iSense=1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (!iSense) {
|
|
return iSense;
|
|
}
|
|
//
|
|
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1);
|
|
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2);
|
|
//
|
|
iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
|
|
//
|
|
return iSense;
|
|
}
|
|
//=======================================================================
|
|
// function: IsSplitToReverse
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
|
|
const TopoDS_Shape& theSr,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet;
|
|
TopAbs_ShapeEnum aType;
|
|
//
|
|
bRet=Standard_False;
|
|
//
|
|
aType=theSp.ShapeType();
|
|
switch (aType) {
|
|
case TopAbs_EDGE: {
|
|
const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
|
|
const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
|
|
bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
|
|
}
|
|
break;
|
|
//
|
|
case TopAbs_FACE: {
|
|
const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
|
|
const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
|
|
bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
|
|
}
|
|
break;
|
|
//
|
|
default:
|
|
break;
|
|
}
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
//function :IsSplitToReverse
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
|
|
const TopoDS_Face& theFSr,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet, bFound, bInFace;
|
|
Standard_Real aT1, aT2, aT, aU, aV, aScPr;
|
|
gp_Pnt aPFSp, aPFSr;
|
|
gp_Dir aDNFSp;
|
|
gp_Vec aD1U, aD1V;
|
|
Handle(Geom_Surface) aSr, aSp;
|
|
TopAbs_Orientation aOrSr, aOrSp;
|
|
TopExp_Explorer anExp;
|
|
TopoDS_Edge aESp;
|
|
//
|
|
bRet=Standard_False;
|
|
//
|
|
aSr=BRep_Tool::Surface(theFSr);
|
|
aSp=BRep_Tool::Surface(theFSp);
|
|
if (aSr==aSp) {
|
|
aOrSr=theFSr.Orientation();
|
|
aOrSp=theFSp.Orientation();
|
|
bRet=(aOrSr!=aOrSp);
|
|
return bRet;
|
|
}
|
|
//
|
|
bFound=Standard_False;
|
|
anExp.Init(theFSp, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
aESp=(*(TopoDS_Edge*)(&anExp.Current()));
|
|
if (!BRep_Tool::Degenerated(aESp)) {
|
|
if (!BRep_Tool::IsClosed(aESp, theFSp)) {
|
|
bFound=!bFound;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!bFound) {
|
|
Standard_Boolean bFlag;
|
|
Standard_Integer iErr;
|
|
gp_Pnt2d aP2DFSp;
|
|
//
|
|
iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
|
|
if (iErr) {
|
|
return bRet;
|
|
}
|
|
//
|
|
aP2DFSp.Coord(aU, aV);
|
|
bFlag=BOPTools_AlgoTools3D::GetNormalToSurface(aSp, aU, aV, aDNFSp);
|
|
if (!bFlag) {
|
|
return bRet;
|
|
}
|
|
}
|
|
else {
|
|
BRep_Tool::Range(aESp, aT1, aT2);
|
|
aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
|
|
BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp, theContext);
|
|
}
|
|
//
|
|
// Parts of theContext->ComputeVS(..)
|
|
GeomAPI_ProjectPointOnSurf& aProjector=theContext->ProjPS(theFSr);
|
|
aProjector.Perform(aPFSp);
|
|
if (!aProjector.IsDone()) {
|
|
return bRet;
|
|
}
|
|
//
|
|
aProjector.LowerDistanceParameters(aU, aV);
|
|
gp_Pnt2d aP2D(aU, aV);
|
|
bInFace=theContext->IsPointInFace (theFSr, aP2D);
|
|
if (!bInFace) {
|
|
return bRet;
|
|
}
|
|
//
|
|
aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
|
|
gp_Dir aDD1U(aD1U);
|
|
gp_Dir aDD1V(aD1V);
|
|
gp_Dir aDNFSr=aDD1U^aDD1V;
|
|
if (theFSr.Orientation()==TopAbs_REVERSED){
|
|
aDNFSr.Reverse();
|
|
}
|
|
//
|
|
aScPr=aDNFSp*aDNFSr;
|
|
bRet=(aScPr<0.);
|
|
//
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
//function :IsSplitToReverse
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Edge& aEF1,
|
|
const TopoDS_Edge& aEF2,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bRet, bIsDegenerated;
|
|
//
|
|
bRet=Standard_False;
|
|
bIsDegenerated=(BRep_Tool::Degenerated(aEF1) ||
|
|
BRep_Tool::Degenerated(aEF2));
|
|
if (bIsDegenerated) {
|
|
return bRet;
|
|
}
|
|
//
|
|
Standard_Real a, b;
|
|
TopAbs_Orientation aOrE, aOrSp;
|
|
Handle(Geom_Curve)aC1, aC2;
|
|
//
|
|
aC2=BRep_Tool::Curve(aEF2, a, b);
|
|
aC1=BRep_Tool::Curve(aEF1, a, b);
|
|
//
|
|
if (aC1==aC2) {
|
|
aOrE=aEF2.Orientation();
|
|
aOrSp=aEF1.Orientation();
|
|
bRet=(aOrE!=aOrSp);
|
|
return bRet;
|
|
}
|
|
//
|
|
Standard_Real aT1, aT2, aScPr;
|
|
gp_Vec aV1, aV2;
|
|
gp_Pnt aP;
|
|
//
|
|
aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
|
|
aC1->D0(aT1, aP);
|
|
BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
|
|
gp_Dir aDT1(aV1);
|
|
//
|
|
theContext->ProjectPointOnEdge(aP, aEF2, aT2);
|
|
//
|
|
BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
|
|
gp_Dir aDT2(aV2);
|
|
//
|
|
aScPr=aDT1*aDT2;
|
|
bRet=(aScPr<0.);
|
|
//
|
|
return bRet;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsHole
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
|
|
const TopoDS_Shape& aFace)
|
|
{
|
|
Standard_Boolean bIsHole;
|
|
Standard_Integer i, aNbS;
|
|
Standard_Real aT1, aT2, aS;
|
|
Standard_Real aU1, aU, dU;
|
|
Standard_Real aX1, aY1, aX0, aY0;
|
|
TopAbs_Orientation aOr;
|
|
|
|
gp_Pnt2d aP2D0, aP2D1;
|
|
Handle(Geom2d_Curve) aC2D;
|
|
TopoDS_Face aF, aFF;
|
|
TopoDS_Iterator aItW;
|
|
//
|
|
bIsHole=Standard_False;
|
|
//
|
|
aF=(*(TopoDS_Face *)(&aFace));
|
|
aFF=aF;
|
|
aFF.Orientation(TopAbs_FORWARD);
|
|
//
|
|
aS=0.;
|
|
aItW.Initialize(aW);
|
|
for (; aItW.More(); aItW.Next()) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
|
|
aOr=aE.Orientation();
|
|
if (!(aOr==TopAbs_FORWARD ||
|
|
aOr==TopAbs_REVERSED)) {
|
|
continue;
|
|
}
|
|
//
|
|
aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
|
|
if (aC2D.IsNull()) {
|
|
break; //xx
|
|
}
|
|
//
|
|
BRepAdaptor_Curve2d aBAC2D(aE, aFF);
|
|
aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
|
|
if (aNbS>2) {
|
|
aNbS*=4;
|
|
}
|
|
//
|
|
dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
|
|
aU =aT1;
|
|
aU1=aT1;
|
|
if (aOr==TopAbs_REVERSED) {
|
|
aU =aT2;
|
|
aU1=aT2;
|
|
dU=-dU;
|
|
}
|
|
//
|
|
aC2D->D0(aU, aP2D0);
|
|
for(i=2; i<=aNbS; i++) {
|
|
aU=aU1+(i-1)*dU;
|
|
aC2D->D0(aU, aP2D1);
|
|
aP2D0.Coord(aX0, aY0);
|
|
aP2D1.Coord(aX1, aY1);
|
|
//
|
|
aS=aS+(aY0+aY1)*(aX1-aX0);
|
|
//
|
|
aP2D0=aP2D1;
|
|
}
|
|
}//for (; aItW.More(); aItW.Next()) {
|
|
bIsHole=(aS>0.);
|
|
return bIsHole;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: MakeContainer
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
|
|
TopoDS_Shape& theC)
|
|
{
|
|
BRep_Builder aBB;
|
|
//
|
|
switch(theType) {
|
|
case TopAbs_COMPOUND:{
|
|
TopoDS_Compound aC;
|
|
aBB.MakeCompound(aC);
|
|
theC=aC;
|
|
}
|
|
break;
|
|
//
|
|
case TopAbs_COMPSOLID:{
|
|
TopoDS_CompSolid aCS;
|
|
aBB.MakeCompSolid(aCS);
|
|
theC=aCS;
|
|
}
|
|
break;
|
|
//
|
|
case TopAbs_SOLID:{
|
|
TopoDS_Solid aSolid;
|
|
aBB.MakeSolid(aSolid);
|
|
theC=aSolid;
|
|
}
|
|
break;
|
|
//
|
|
//
|
|
case TopAbs_SHELL:{
|
|
TopoDS_Shell aShell;
|
|
aBB.MakeShell(aShell);
|
|
theC=aShell;
|
|
}
|
|
break;
|
|
//
|
|
case TopAbs_WIRE: {
|
|
TopoDS_Wire aWire;
|
|
aBB.MakeWire(aWire);
|
|
theC=aWire;
|
|
}
|
|
break;
|
|
//
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: MakePCurve
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF1,
|
|
const TopoDS_Face& aF2,
|
|
const IntTools_Curve& aIC,
|
|
const Standard_Boolean bPC1,
|
|
const Standard_Boolean bPC2)
|
|
|
|
{
|
|
Standard_Integer i;
|
|
Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
|
|
Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
|
|
TopoDS_Face aFFWD;
|
|
BRep_Builder aBB;
|
|
Standard_Boolean bPC;
|
|
//
|
|
aTolE=BRep_Tool::Tolerance(aE);
|
|
//
|
|
const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
|
|
Handle(Geom_TrimmedCurve)aC3DETrim=new Geom_TrimmedCurve(aC3DE, aT1, aT2);
|
|
//
|
|
for (i=0; i<2; ++i) {
|
|
bPC = !i ? bPC1 : bPC2;
|
|
if (!bPC) {
|
|
continue;
|
|
}
|
|
//
|
|
if (!i) {
|
|
aFFWD=aF1;
|
|
aC2Dx1=aIC.FirstCurve2d();
|
|
}
|
|
else {
|
|
aFFWD=aF2;
|
|
aC2Dx1=aIC.SecondCurve2d();
|
|
}
|
|
//
|
|
aFFWD.Orientation(TopAbs_FORWARD);
|
|
//
|
|
aC2D=aC2Dx1;
|
|
if (aC2D.IsNull()) {
|
|
BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD);
|
|
BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D,
|
|
aOutFirst, aOutLast,
|
|
aOutTol);
|
|
}
|
|
//
|
|
if (aC3DE->IsPeriodic()) {
|
|
BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2, aC2D, aC2DA);
|
|
}
|
|
else {
|
|
BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, aC2DA);
|
|
}
|
|
//
|
|
aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
|
|
//BRepLib::SameParameter(aE);
|
|
}
|
|
BRepLib::SameParameter(aE);
|
|
}
|
|
//=======================================================================
|
|
// function: MakeEdge
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
|
|
const TopoDS_Vertex& theV1,
|
|
const Standard_Real theT1,
|
|
const TopoDS_Vertex& theV2,
|
|
const Standard_Real theT2,
|
|
const Standard_Real theTolR3D,
|
|
TopoDS_Edge& theE)
|
|
{
|
|
Standard_Real aTolV;
|
|
BRep_Builder aBB;
|
|
//
|
|
BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, theE);
|
|
//
|
|
aBB.UpdateEdge(theE, theTolR3D);
|
|
//
|
|
aTolV=BRep_Tool::Tolerance(theV1);
|
|
if (aTolV<theTolR3D) {
|
|
aBB.UpdateVertex(theV1, theTolR3D);
|
|
}
|
|
//
|
|
aTolV=BRep_Tool::Tolerance(theV2);
|
|
if (aTolV<theTolR3D) {
|
|
aBB.UpdateVertex(theV2, theTolR3D);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeVV
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
|
|
const gp_Pnt& aP2,
|
|
const Standard_Real aTolP2)
|
|
{
|
|
Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
|
|
gp_Pnt aP1;
|
|
//
|
|
aTolV1=BRep_Tool::Tolerance(aV1);
|
|
|
|
aTolSum=aTolV1+aTolP2;
|
|
aTolSum2=aTolSum*aTolSum;
|
|
//
|
|
aP1=BRep_Tool::Pnt(aV1);
|
|
//
|
|
aD2=aP1.SquareDistance(aP2);
|
|
if (aD2>aTolSum2) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
//=======================================================================
|
|
// function: ComputeVV
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
|
|
const TopoDS_Vertex& aV2)
|
|
{
|
|
Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
|
|
gp_Pnt aP1, aP2;
|
|
//
|
|
aTolV1=BRep_Tool::Tolerance(aV1);
|
|
aTolV2=BRep_Tool::Tolerance(aV2);
|
|
aTolSum=aTolV1+aTolV2;
|
|
aTolSum2=aTolSum*aTolSum;
|
|
//
|
|
aP1=BRep_Tool::Pnt(aV1);
|
|
aP2=BRep_Tool::Pnt(aV2);
|
|
//
|
|
aD2=aP1.SquareDistance(aP2);
|
|
if (aD2>aTolSum2) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
//=======================================================================
|
|
// function: MakeVertex
|
|
// purpose :
|
|
//=======================================================================
|
|
void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
|
|
TopoDS_Vertex& aVnew)
|
|
{
|
|
Standard_Integer aNb;
|
|
Standard_Real aTi, aDi, aDmax;
|
|
gp_Pnt aPi, aP;
|
|
gp_XYZ aXYZ(0.,0.,0.), aXYZi;
|
|
BOPCol_ListIteratorOfListOfShape aIt;
|
|
//
|
|
aNb=aLV.Extent();
|
|
if (aNb) {
|
|
aIt.Initialize(aLV);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
|
|
aPi=BRep_Tool::Pnt(aVi);
|
|
aXYZi=aPi.XYZ();
|
|
aXYZ=aXYZ+aXYZi;
|
|
}
|
|
//
|
|
aXYZ.Divide((Standard_Real)aNb);
|
|
aP.SetXYZ(aXYZ);
|
|
//
|
|
aDmax=-1.;
|
|
aIt.Initialize(aLV);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
|
|
aPi=BRep_Tool::Pnt(aVi);
|
|
aTi=BRep_Tool::Tolerance(aVi);
|
|
aDi=aP.SquareDistance(aPi);
|
|
aDi=sqrt(aDi);
|
|
aDi=aDi+aTi;
|
|
if (aDi > aDmax) {
|
|
aDmax=aDi;
|
|
}
|
|
}
|
|
//
|
|
BRep_Builder aBB;
|
|
aBB.MakeVertex (aVnew, aP, aDmax);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : GetEdgeOnFace
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
|
|
const TopoDS_Face& theF2,
|
|
TopoDS_Edge& theE2)
|
|
{
|
|
Standard_Boolean bFound;
|
|
TopoDS_Iterator aItF, aItW;
|
|
//
|
|
bFound=Standard_False;
|
|
//
|
|
aItF.Initialize(theF2);
|
|
for (; aItF.More(); aItF.Next()) {
|
|
const TopoDS_Shape& aW=aItF.Value();
|
|
aItW.Initialize(aW);
|
|
for (; aItW.More(); aItW.Next()) {
|
|
const TopoDS_Shape& aE=aItW.Value();
|
|
if (aE.IsSame(theE1)) {
|
|
theE2=(*(TopoDS_Edge*)(&aE));
|
|
bFound=!bFound;
|
|
return bFound;
|
|
}
|
|
}
|
|
}
|
|
return bFound;
|
|
}
|
|
//=======================================================================
|
|
//function : FindFacePairs
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
|
|
const BOPCol_ListOfShape& thLF,
|
|
BOPTools_ListOfCoupleOfShape& theLCFF,
|
|
Handle(BOPInt_Context)& theContext)
|
|
{
|
|
Standard_Boolean bFound;
|
|
Standard_Integer i, aNbCEF;
|
|
TopAbs_Orientation aOr, aOrC = TopAbs_FORWARD;
|
|
BOPCol_MapOfShape aMFP;
|
|
TopoDS_Face aF1, aF2;
|
|
TopoDS_Edge aEL, aE1;
|
|
BOPCol_ListIteratorOfListOfShape aItLF;
|
|
BOPTools_CoupleOfShape aCEF, aCFF;
|
|
BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
|
|
BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
|
|
//
|
|
bFound=Standard_True;
|
|
//
|
|
// Preface aLCEF
|
|
aItLF.Initialize(thLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
|
|
//
|
|
bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
|
|
if (!bFound) {
|
|
return bFound; // it can not be so
|
|
}
|
|
//
|
|
aCEF.SetShape1(aEL);
|
|
aCEF.SetShape2(aFL);
|
|
aLCEF.Append(aCEF);
|
|
}
|
|
//
|
|
aNbCEF=aLCEF.Extent();
|
|
while(aNbCEF) {
|
|
//
|
|
// aLCEFx
|
|
aLCEFx.Clear();
|
|
aIt.Initialize(aLCEF);
|
|
for (i=0; aIt.More(); aIt.Next(), ++i) {
|
|
const BOPTools_CoupleOfShape& aCSx=aIt.Value();
|
|
const TopoDS_Shape& aEx=aCSx.Shape1();
|
|
const TopoDS_Shape& aFx=aCSx.Shape2();
|
|
//
|
|
aOr=aEx.Orientation();
|
|
//
|
|
if (!i) {
|
|
aOrC=TopAbs::Reverse(aOr);
|
|
aE1=(*(TopoDS_Edge*)(&aEx));
|
|
aF1=(*(TopoDS_Face*)(&aFx));
|
|
aMFP.Add(aFx);
|
|
continue;
|
|
}
|
|
//
|
|
if (aOr==aOrC) {
|
|
aLCEFx.Append(aCSx);
|
|
aMFP.Add(aFx);
|
|
}
|
|
}
|
|
//
|
|
// F2
|
|
BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
|
|
//
|
|
aCFF.SetShape1(aF1);
|
|
aCFF.SetShape2(aF2);
|
|
theLCFF.Append(aCFF);
|
|
//
|
|
aMFP.Add(aF1);
|
|
aMFP.Add(aF2);
|
|
//
|
|
// refine aLCEF
|
|
aLCEFx.Clear();
|
|
aLCEFx=aLCEF;
|
|
aLCEF.Clear();
|
|
aIt.Initialize(aLCEFx);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const BOPTools_CoupleOfShape& aCSx=aIt.Value();
|
|
const TopoDS_Shape& aFx=aCSx.Shape2();
|
|
if (!aMFP.Contains(aFx)) {
|
|
aLCEF.Append(aCSx);
|
|
}
|
|
}
|
|
//
|
|
aNbCEF=aLCEF.Extent();
|
|
}//while(aNbCEF) {
|
|
//
|
|
return bFound;
|
|
}
|
|
//=======================================================================
|
|
//function : AngleWithRef
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Real AngleWithRef(const gp_Dir& theD1,
|
|
const gp_Dir& theD2,
|
|
const gp_Dir& theDRef)
|
|
{
|
|
Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
|
|
gp_XYZ aXYZ;
|
|
//
|
|
aHalfPI=0.5*M_PI;
|
|
//
|
|
const gp_XYZ& aXYZ1=theD1.XYZ();
|
|
const gp_XYZ& aXYZ2=theD2.XYZ();
|
|
aXYZ=aXYZ1.Crossed(aXYZ2);
|
|
aSinus=aXYZ.Modulus();
|
|
aCosinus=theD1*theD2;
|
|
//
|
|
aBeta=0.;
|
|
if (aSinus>=0.) {
|
|
aBeta=aHalfPI*(1.-aCosinus);
|
|
}
|
|
else {
|
|
aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
|
|
}
|
|
//
|
|
aScPr=aXYZ.Dot(theDRef.XYZ());
|
|
if (aScPr<0.) {
|
|
aBeta=-aBeta;
|
|
}
|
|
return aBeta;
|
|
}
|
|
//=======================================================================
|
|
// function: IsBlockInOnFace
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShrR,
|
|
const TopoDS_Face& aF,
|
|
const TopoDS_Edge& aE1,
|
|
Handle(BOPInt_Context)& aContext)
|
|
{
|
|
Standard_Boolean bFlag;
|
|
Standard_Real f1, l1, ULD, VLD;
|
|
gp_Pnt2d aP2D;
|
|
gp_Pnt aP11, aP12;
|
|
//
|
|
aShrR.Range(f1, l1);
|
|
Standard_Real dt=0.0075, k;//dt=0.001, k;
|
|
k=dt*(l1-f1);
|
|
f1=f1+k;
|
|
l1=l1-k;
|
|
//
|
|
// Treatment P11
|
|
BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
|
|
//
|
|
GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
|
|
aProjector.Perform(aP11);
|
|
//
|
|
bFlag=aProjector.IsDone();
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
|
|
aProjector.LowerDistanceParameters(ULD, VLD);
|
|
aP2D.SetCoord(ULD, VLD);
|
|
//
|
|
bFlag=aContext->IsPointInOnFace (aF, aP2D);
|
|
//
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
//
|
|
// Treatment P12
|
|
BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
|
|
//
|
|
aProjector.Perform(aP12);
|
|
//
|
|
bFlag=aProjector.IsDone();
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
|
|
aProjector.LowerDistanceParameters(ULD, VLD);
|
|
aP2D.SetCoord(ULD, VLD);
|
|
//
|
|
bFlag=aContext->IsPointInOnFace (aF, aP2D);
|
|
//
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
//
|
|
// Treatment intemediate
|
|
Standard_Real m1, aTolF, aTolE, aTol, aDist;
|
|
m1=IntTools_Tools::IntermediatePoint(f1, l1);
|
|
BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
|
|
//
|
|
aProjector.Perform(aP12);
|
|
//
|
|
bFlag=aProjector.IsDone();
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
//
|
|
aTolE=BRep_Tool::Tolerance(aE1);
|
|
aTolF=BRep_Tool::Tolerance(aF);
|
|
aTol=aTolE+aTolF;
|
|
aDist=aProjector.LowerDistance();
|
|
if (aDist > aTol){
|
|
return Standard_False;
|
|
}
|
|
|
|
aProjector.LowerDistanceParameters(ULD, VLD);
|
|
aP2D.SetCoord(ULD, VLD);
|
|
//
|
|
bFlag=aContext->IsPointInOnFace (aF, aP2D);
|
|
//
|
|
if (!bFlag) {
|
|
return bFlag;
|
|
}
|
|
return bFlag;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsMicroEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
|
|
const Handle(BOPInt_Context)& aCtx)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Integer iErr;
|
|
Standard_Real aT1, aT2, aTmp;
|
|
Handle(Geom_Curve) aC3D;
|
|
TopoDS_Vertex aV1, aV2;
|
|
//
|
|
bRet=(BRep_Tool::Degenerated(aE) ||
|
|
!BRep_Tool::IsGeometric(aE));
|
|
if (bRet) {
|
|
return bRet;
|
|
}
|
|
//
|
|
aC3D=BRep_Tool::Curve(aE, aT1, aT2);
|
|
TopExp::Vertices(aE, aV1, aV2);
|
|
aT1=BRep_Tool::Parameter(aV1, aE);
|
|
aT2=BRep_Tool::Parameter(aV2, aE);
|
|
if (aT2<aT1) {
|
|
aTmp=aT1;
|
|
aT1=aT2;
|
|
aT2=aTmp;
|
|
}
|
|
//
|
|
BOPInt_ShrunkRange aSR;
|
|
aSR.SetData(aE, aT1, aT2, aV1, aV2, aCtx);
|
|
aSR.Perform();
|
|
iErr=aSR.ErrorStatus();
|
|
bRet = !(iErr==0);
|
|
//
|
|
return bRet;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetFaceDir
|
|
//purpose : Get binormal direction for the face in the point aP
|
|
//=======================================================================
|
|
void GetFaceDir(const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF,
|
|
const gp_Pnt& aP,
|
|
const Standard_Real aT,
|
|
const gp_Dir& aDTgt,
|
|
gp_Dir& aDN,
|
|
gp_Dir& aDB,
|
|
Handle(BOPInt_Context)& theContext,
|
|
GeomAPI_ProjectPointOnSurf& aProjPL)
|
|
{
|
|
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN);
|
|
if (aF.Orientation()==TopAbs_REVERSED){
|
|
aDN.Reverse();
|
|
}
|
|
aDB = aDN^aDTgt;
|
|
//
|
|
gp_Pnt aPx;
|
|
if (!FindPointInFace(aE, aF, aP, aDB, aPx, theContext, aProjPL)) {
|
|
BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aE, aF, aT, aPx, aDN, theContext);
|
|
aProjPL.Perform(aPx);
|
|
aPx = aProjPL.NearestPoint();
|
|
gp_Vec aVec(aP, aPx);
|
|
aDB.SetXYZ(aVec.XYZ());
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindPointInFace
|
|
//purpose : Find a point in the face in direction of <aDB>
|
|
//=======================================================================
|
|
Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF,
|
|
const gp_Pnt& aP,
|
|
gp_Dir& aDB,
|
|
gp_Pnt& aPOut,
|
|
Handle(BOPInt_Context)& theContext,
|
|
GeomAPI_ProjectPointOnSurf& aProjPL)
|
|
{
|
|
Standard_Integer aNbItMax;
|
|
Standard_Real aDt, aDtMin, aTolE, aTolF, aDist;
|
|
Standard_Boolean bRet;
|
|
gp_Pnt aP1;
|
|
BRepAdaptor_Surface aBAS;
|
|
//
|
|
bRet = Standard_False;
|
|
aTolE = BRep_Tool::Tolerance(aE);
|
|
aTolF = BRep_Tool::Tolerance(aF);
|
|
aDt = 2*(aTolE+aTolF);
|
|
aBAS.Initialize(aF, Standard_False);
|
|
//
|
|
aDtMin=5.e-4;
|
|
if (aDt < aDtMin) {
|
|
Standard_Real aR;
|
|
GeomAbs_SurfaceType aSType=aBAS.GetType();
|
|
switch (aSType) {
|
|
case GeomAbs_Cylinder:
|
|
aR = aBAS.Cylinder().Radius();
|
|
break;
|
|
case GeomAbs_Cone: {
|
|
gp_Lin aL(aBAS.Cone().Axis());
|
|
aR = aL.Distance(aP);
|
|
break;
|
|
}
|
|
case GeomAbs_Sphere:
|
|
aR = aBAS.Sphere().Radius();
|
|
break;
|
|
case GeomAbs_Torus:
|
|
aR = aBAS.Torus().MinorRadius();
|
|
break;
|
|
case GeomAbs_SurfaceOfRevolution:
|
|
aR=1.;
|
|
break;
|
|
default:
|
|
aR=0.001;
|
|
}
|
|
if (aR < 0.01) {
|
|
aDtMin=5.e-6;
|
|
}
|
|
else if (aR > 100.) {
|
|
aDtMin*=10;
|
|
}
|
|
if (aDt < aDtMin) {
|
|
aDt=aDtMin;
|
|
}
|
|
}
|
|
//
|
|
GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
|
|
aNbItMax = 15;
|
|
//
|
|
do {
|
|
aP1.SetCoord(aP.X()+aDt*aDB.X(),
|
|
aP.Y()+aDt*aDB.Y(),
|
|
aP.Z()+aDt*aDB.Z());
|
|
//
|
|
aProj.Perform(aP1);
|
|
if (!aProj.IsDone()) {
|
|
return bRet;
|
|
}
|
|
aPOut = aProj.NearestPoint();
|
|
aDist = aProj.LowerDistance();
|
|
//
|
|
aProjPL.Perform(aPOut);
|
|
aPOut = aProjPL.NearestPoint();
|
|
//
|
|
gp_Vec aV(aP, aPOut);
|
|
aDB.SetXYZ(aV.XYZ());
|
|
} while (aDist>Precision::Angular() && --aNbItMax);
|
|
//
|
|
bRet = aDist < Precision::Angular();
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
//function : IsOpenShell
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean
|
|
BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Integer i, aNbE, aNbF;
|
|
TopAbs_Orientation aOrF;
|
|
BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
|
|
BOPCol_ListIteratorOfListOfShape aItLS;
|
|
//
|
|
bRet=Standard_False;
|
|
//
|
|
BOPTools::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
|
|
//
|
|
aNbE=aMEF.Extent();
|
|
for (i=1; i<=aNbE; ++i) {
|
|
const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
aNbF=0;
|
|
const BOPCol_ListOfShape& aLF=aMEF(i);
|
|
aItLS.Initialize(aLF);
|
|
for (; aItLS.More(); aItLS.Next()) {
|
|
const TopoDS_Shape& aF=aItLS.Value();
|
|
aOrF=aF.Orientation();
|
|
if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
|
|
continue;
|
|
}
|
|
++aNbF;
|
|
}
|
|
//
|
|
if (aNbF==1) {
|
|
bRet=!bRet; // True
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
return bRet;
|
|
}
|
|
//=======================================================================
|
|
//function : IsInvertedSolid
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean
|
|
BOPTools_AlgoTools::IsInvertedSolid(const TopoDS_Solid& aSolid)
|
|
{
|
|
Standard_Real aTolS;
|
|
TopAbs_State aState;
|
|
BRepClass3d_SolidClassifier aSC(aSolid);
|
|
//
|
|
aTolS=1.e-7;
|
|
aSC.PerformInfinitePoint(aTolS);
|
|
aState=aSC.State();
|
|
return (aState==TopAbs_IN);
|
|
}
|