1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/BOPTools/BOPTools_AlgoTools3D.cxx
jgv 5db1a7a3db 0031890: Modeling Algorithms - Invalid result of common fuse BOP. Intersection has failed.
Modify the method BOPTools_AlgoTools3D::DoSplitSEAMOnFace: correct processing closed non-periodic surfaces.
2021-08-30 11:33:18 +03:00

1035 lines
28 KiB
C++

// Created by: Peter KURNEV
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// 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 <Bnd_Box.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_AlgoTools3D.hxx>
#include <BRep_Builder.hxx>
#include <BRep_CurveRepresentation.hxx>
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
#include <BRep_PointRepresentation.hxx>
#include <BRep_TEdge.hxx>
#include <BRep_TFace.hxx>
#include <BRep_Tool.hxx>
#include <BRep_TVertex.hxx>
#include <BRepBndLib.hxx>
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dHatch_Hatcher.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <GProp_GProps.hxx>
#include <HatchGen_Domain.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_Tools.hxx>
#include <Poly_Triangulation.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
static void Add(const TopoDS_Shape& aS,
TopTools_IndexedMapOfShape& myShapes,
Standard_Boolean& bHasGeometry);
static
Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
//=======================================================================
//function : DoSplitSEAMOnFace
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
const TopoDS_Face& aF)
{
Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft;
Standard_Real anUPeriod = 0., anVPeriod = 0.;
Standard_Real aTol, a, b, aT, anU, dU, anU1;
Standard_Real aScPr, anV, dV, anV1;
Standard_Real aUmin, aUmax, aVmin, aVmax;
gp_Pnt2d aP2D;
gp_Vec2d aVec2D;
Handle(Geom2d_Curve) aTmpC1, aTmpC2;
Handle(Geom2d_Curve) C2D1;
Handle(Geom2d_Line) aLD1;
Handle(Geom_Surface) aS;
BRep_Builder BB;
TopoDS_Edge aSp;
//
bIsLeft = Standard_False;
aSp=aSplit;
aSp.Orientation(TopAbs_FORWARD);
aTol=BRep_Tool::Tolerance(aSp);
//
aS=BRep_Tool::Surface(aF);
//
aS->Bounds(aUmin, aUmax, aVmin, aVmax);
//
bIsUPeriodic = aS->IsUClosed();
bIsVPeriodic = aS->IsVClosed();
if (bIsUPeriodic)
anUPeriod = aUmax - aUmin;
if (bIsVPeriodic)
anVPeriod = aVmax - aVmin;
//
if (!bIsUPeriodic && !bIsVPeriodic) {
Handle(Geom_RectangularTrimmedSurface) aRTS;
aRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
//
if (aRTS.IsNull())
return Standard_False;
else {
Handle(Geom_Surface) aSB;
//
aSB = aRTS->BasisSurface();
bIsUPeriodic = aSB->IsUPeriodic();
bIsVPeriodic = aSB->IsVPeriodic();
//
if (bIsUPeriodic || bIsVPeriodic)
{
anUPeriod = bIsUPeriodic ? aSB->UPeriod() : 0.;
anVPeriod = bIsVPeriodic ? aSB->VPeriod() : 0.;
}
else
{
Standard_Boolean bIsUClosed = aSB->IsUClosed();
Standard_Boolean bIsVClosed = aSB->IsVClosed();
Standard_Real aGlobalUmin, aGlobalUmax, aGlobalVmin, aGlobalVmax;
aSB->Bounds(aGlobalUmin, aGlobalUmax, aGlobalVmin, aGlobalVmax);
if (bIsUClosed &&
Abs(aUmin - aGlobalUmin) < aTol &&
Abs(aUmax - aGlobalUmax) < aTol)
{
bIsUPeriodic = Standard_True;
anUPeriod = aUmax - aUmin;
}
if (bIsVClosed &&
Abs(aVmin - aGlobalVmin) < aTol &&
Abs(aVmax - aGlobalVmax) < aTol)
{
bIsVPeriodic = Standard_True;
anVPeriod = aVmax - aVmin;
}
}
if (!(bIsUPeriodic || bIsVPeriodic)) {
return Standard_False;
}
} //if !RTS.IsNull
}
//
//---------------------------------------------------
C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
//
aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
C2D1->D1(aT, aP2D, aVec2D);
gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.);
//
anU=aP2D.X();
anV=aP2D.Y();
//
anU1=anU;
anV1=anV;
//
GeomAdaptor_Surface aGAS(aS);
dU = aGAS.UResolution(aTol);
dV = aGAS.VResolution(aTol);
//
if (anUPeriod > 0.){
if (fabs (anU-aUmin) < dU) {
bIsLeft=Standard_True;
anU1=anU+anUPeriod;
}
else if (fabs (anU-aUmax) < dU) {
bIsLeft=Standard_False;
anU1=anU-anUPeriod;
}
}
//
if (anVPeriod > 0.) {
if (fabs (anV-aVmin) < dV) {
bIsLeft=Standard_True;
anV1=anV+anVPeriod;
}
else if (fabs (anV-aVmax) < dV) {
bIsLeft=Standard_False;
anV1=anV-anVPeriod;
}
}
//
if (anU1==anU && anV1==anV) {
return Standard_False;
}
//
aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
//
aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
Handle(Geom2d_TrimmedCurve) aC1 =
new Geom2d_TrimmedCurve(aTmpC1, a, b);
//
aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
Handle(Geom2d_TrimmedCurve) aC2 =
new Geom2d_TrimmedCurve(aTmpC2, a, b);
gp_Vec2d aTrV(anU1-anU, anV1-anV);
aC2->Translate(aTrV);
//
if (!bIsLeft) {
if (aScPr<0.) {
BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
}
else {
BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
}
}
else {
if (aScPr<0.) {
BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
}
else {
BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
}
}
return Standard_True;
}
//=======================================================================
//function : DoSplitSEAMOnFace
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& theEOrigin,
const TopoDS_Edge& theESplit,
const TopoDS_Face& theFace)
{
if (!BRep_Tool::IsClosed (theEOrigin, theFace))
return Standard_False;
if (BRep_Tool::IsClosed (theESplit, theFace))
return Standard_True;
TopoDS_Edge aESplit = theESplit;
aESplit.Orientation (TopAbs_FORWARD);
TopoDS_Face aFace = theFace;
aFace.Orientation (TopAbs_FORWARD);
Standard_Real aTS1, aTS2;
Handle(Geom2d_Curve) aC2DSplit = BRep_Tool::CurveOnSurface (aESplit, aFace, aTS1, aTS2);
if (aC2DSplit.IsNull())
return Standard_False;
Standard_Real aT1, aT2;
Handle(Geom2d_Curve) aC2D1 = BRep_Tool::CurveOnSurface (
TopoDS::Edge (theEOrigin.Oriented (TopAbs_FORWARD)), aFace, aT1, aT2);
Handle(Geom2d_Curve) aC2D2 = BRep_Tool::CurveOnSurface (
TopoDS::Edge (theEOrigin.Oriented (TopAbs_REVERSED)), aFace, aT1, aT2);
Standard_Real aT = BOPTools_AlgoTools2D::IntermediatePoint (aTS1, aTS2);
gp_Pnt2d aPMid;
gp_Vec2d aVTgt;
aC2DSplit->D1 (aT, aPMid, aVTgt);
// project on original 2d curves
Geom2dAPI_ProjectPointOnCurve aProjPC1, aProjPC2;
aProjPC1.Init (aPMid, aC2D1, aT1, aT2);
aProjPC2.Init (aPMid, aC2D2, aT1, aT2);
if (!aProjPC1.NbPoints() && !aProjPC2.NbPoints())
return Standard_False;
Standard_Real aDist1 = aProjPC1.NbPoints() ? aProjPC1.LowerDistance() : RealLast();
Standard_Real aDist2 = aProjPC2.NbPoints() ? aProjPC2.LowerDistance() : RealLast();
if (aDist1 > Precision::PConfusion() && aDist2 > Precision::PConfusion())
return Standard_False;
// choose the closest and take corresponding point from the opposite
gp_Pnt2d aNewPnt = aDist1 < aDist2 ? aC2D2->Value (aProjPC1.LowerDistanceParameter()) :
aC2D1->Value (aProjPC2.LowerDistanceParameter());
Handle (Geom2d_Curve) aTmpC1 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy());
Handle (Geom2d_Curve) aTmpC2 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy());
Handle (Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve (aTmpC1, aTS1, aTS2);
Handle (Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve (aTmpC2, aTS1, aTS2);
gp_Vec2d aTrVec (aPMid, aNewPnt);
aC2->Translate (aTrVec);
gp_Pnt2d aPProj;
gp_Vec2d aVTgtOrigin;
if (aDist1 < aDist2)
{
aC2D1->D1 (aProjPC1.LowerDistanceParameter(), aPProj, aVTgtOrigin);
}
else
{
aC2D2->D1 (aProjPC2.LowerDistanceParameter(), aPProj, aVTgtOrigin);
}
Standard_Real aDot = aVTgt.Dot (aVTgtOrigin);
if ((aDist1 < aDist2) == (aDot > 0))
{
BRep_Builder().UpdateEdge (aESplit, aC1, aC2, aFace, BRep_Tool::Tolerance (aESplit));
}
else
{
BRep_Builder().UpdateEdge (aESplit, aC2, aC1, aFace, BRep_Tool::Tolerance (aESplit));
}
return Standard_True;
}
//=======================================================================
//function : GetNormalToFaceOnEdge
//purpose :
//=======================================================================
void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
const TopoDS_Face& aF,
gp_Dir& aDNF,
const Handle(IntTools_Context)& theContext)
{
Standard_Real aT, aT1, aT2;
BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF, theContext);
if (aF.Orientation()==TopAbs_REVERSED){
aDNF.Reverse();
}
}
//=======================================================================
//function : GetNormalToFaceOnEdge
//purpose :
//=======================================================================
void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
const TopoDS_Face& aF1,
const Standard_Real aT,
gp_Dir& aDNF1,
const Handle(IntTools_Context)& theContext)
{
Standard_Real U, V, aTolPC;
gp_Pnt2d aP2D;
gp_Pnt aP;
gp_Vec aD1U, aD1V;
Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
Handle(Geom2d_Curve)aC2D1;
BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC, theContext);
aC2D1->D0(aT, aP2D);
U=aP2D.X();
V=aP2D.Y();
aS1->D1(U, V, aP, aD1U, aD1V);
gp_Dir aDD1U(aD1U);
gp_Dir aDD1V(aD1V);
aDNF1=aDD1U^aDD1V;
}
//=======================================================================
//function : SenseFlag
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1,
const gp_Dir& aDNF2)
{
Standard_Boolean bIsDirsCoinside;
//
bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
if (!bIsDirsCoinside) {
return 0;
}
Standard_Real aScPr;
aScPr=aDNF1*aDNF2;
if (aScPr<0.) {
return -1;
}
else if (aScPr>0.) {
return 1;
}
return -1;
}
//=======================================================================
//function : GetNormalToSurface
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface
(const Handle(Geom_Surface)& aS,
const Standard_Real U,
const Standard_Real V,
gp_Dir& aDNS)
{
gp_Pnt aP;
gp_Vec aD1U, aD1V;
aS->D1(U, V, aP, aD1U, aD1V);
Standard_Real aLenU = aD1U.SquareMagnitude();
if (aLenU < gp::Resolution())
return Standard_False;
Standard_Real aLenV = aD1V.SquareMagnitude();
if (aLenV < gp::Resolution())
return Standard_False;
gp_Dir aDD1U(aD1U);
gp_Dir aDD1V(aD1V);
Standard_Boolean bFlag = IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
if (!bFlag)
return bFlag;
aDNS = aDD1U^aDD1V;
return bFlag;
}
//=======================================================================
//function : GetApproxNormalToFaceOnEdge
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
gp_Pnt& aPNear,
gp_Dir& aDNF,
Standard_Real aDt2D)
{
gp_Pnt2d aPx2DNear;
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aE, aF, aT, aDt2D, aPx2DNear, aPNear);
if (iErr != 1) {
Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
BOPTools_AlgoTools3D::GetNormalToSurface
(aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
if (aF.Orientation()==TopAbs_REVERSED){
aDNF.Reverse();
}
}
//
return (iErr == 0);
}
//=======================================================================
//function : GetApproxNormalToFaceOnEdge
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
gp_Pnt& aPNear,
gp_Dir& aDNF,
const Handle(IntTools_Context)& theContext)
{
gp_Pnt2d aPx2DNear;
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aE, aF, aT, aPx2DNear, aPNear, theContext);
if (iErr != 1) {
Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
BOPTools_AlgoTools3D::GetNormalToSurface
(aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
if (aF.Orientation()==TopAbs_REVERSED){
aDNF.Reverse();
}
}
//
return (iErr == 0);
}
//=======================================================================
//function : GetApproxNormalToFaceOnEdge
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
const Standard_Real theStep,
gp_Pnt& aPNear,
gp_Dir& aDNF,
const Handle(IntTools_Context)& theContext)
{
gp_Pnt2d aPx2DNear;
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aE, aF, aT, theStep, aPx2DNear, aPNear, theContext);
if (iErr != 1) {
Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
BOPTools_AlgoTools3D::GetNormalToSurface
(aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
if (aF.Orientation()==TopAbs_REVERSED){
aDNF.Reverse();
}
}
//
return (iErr == 0);
}
//=======================================================================
//function : PointNearEdge
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointNearEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
const Standard_Real aDt2D,
gp_Pnt2d& aPx2DNear,
gp_Pnt& aPxNear)
{
Standard_Real aFirst, aLast, aETol, aFTol, transVal;
GeomAbs_SurfaceType aTS;
Handle(Geom2d_Curve) aC2D;
Handle(Geom_Surface) aS;
//
aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
Standard_Integer iErr = aC2D.IsNull() ? 1 : 0;
if (iErr) {
return iErr;
}
//
aS=BRep_Tool::Surface(aF);
//
gp_Pnt2d aPx2D;
gp_Vec2d aVx2D;
aC2D->D1 (aT, aPx2D, aVx2D);
gp_Dir2d aDx2D(aVx2D);
gp_Dir2d aDP;
aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
if (aE.Orientation()==TopAbs_REVERSED){
aDP.Reverse();
}
if (aF.Orientation()==TopAbs_REVERSED) {
aDP.Reverse();
}
//
aETol = BRep_Tool::Tolerance(aE);
aFTol = BRep_Tool::Tolerance(aF);
// NPAL19220
GeomAdaptor_Surface aGAS(aS);
aTS=aGAS.GetType();
if (aTS==GeomAbs_BSplineSurface) {
if (aETol > 1.e-5) {
aFTol=aETol;
}
}
if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
//
if(aTS!=GeomAbs_Sphere) {
gp_Vec2d transVec( aDP );
transVal = aDt2D + aETol + aFTol;
if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
Standard_Real aR, dT;
//
gp_Cylinder aCyl=aGAS.Cylinder();
aR=aCyl.Radius();
dT=1.-transVal/aR;
if (dT>=-1 && dT<=1) {
dT=acos(dT);
transVal=dT;
}
}
//
transVec.Multiply(transVal);
aPx2DNear = aPx2D.Translated( transVec );
}
else {
aPx2DNear.SetCoord
(aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
}
}
else {
aPx2DNear.SetCoord
(aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
}
//
aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
return iErr;
}
//=======================================================================
//function : PointNearEdge
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointNearEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
gp_Pnt2d& aPx2DNear,
gp_Pnt& aPxNear,
const Handle(IntTools_Context)& theContext)
{
Standard_Real aTolE, aTolF, dTx, dT2D;
Handle(Geom_Surface) aS;
GeomAdaptor_Surface aGAS;
//
dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5;
//
aS = BRep_Tool::Surface(aF);
aGAS.Load(aS);
if (aGAS.GetType()==GeomAbs_Cylinder ||
aGAS.GetType()==GeomAbs_Sphere) {
dT2D=10.*dT2D;
}
//
aTolE = BRep_Tool::Tolerance(aE);
aTolF = BRep_Tool::Tolerance(aF);
dTx = 2.*(aTolE + aTolF);
if (dTx > dT2D) {
dT2D=dTx;
}
//
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aE, aF, aT, dT2D, aPx2DNear, aPxNear);
if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) {
gp_Pnt aP;
gp_Pnt2d aP2d;
//
iErr = BOPTools_AlgoTools3D::PointInFace
(aF, aE, aT, dT2D, aP, aP2d, theContext);
if (iErr == 0) {
aPxNear = aP;
aPx2DNear = aP2d;
}
else {
iErr = 2; // point is out of the face
}
}
//
return iErr;
}
//=======================================================================
//function : PointNearEdge
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointNearEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const Standard_Real aT,
const Standard_Real theStep,
gp_Pnt2d& aPx2DNear,
gp_Pnt& aPxNear,
const Handle(IntTools_Context)& theContext)
{
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aE, aF, aT, theStep, aPx2DNear, aPxNear);
if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) {
gp_Pnt aP;
gp_Pnt2d aP2d;
//
iErr = BOPTools_AlgoTools3D::PointInFace
(aF, aE, aT, theStep, aP, aP2d, theContext);
if (iErr == 0) {
aPxNear = aP;
aPx2DNear = aP2d;
}
else {
iErr = 2; // point is out of the face
}
}
//
return iErr;
}
//=======================================================================
// function: PointNearEdge
// purpose:
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointNearEdge
(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
gp_Pnt2d& aPInFace2D,
gp_Pnt& aPInFace,
const Handle(IntTools_Context)& theContext)
{
Standard_Real aT, aT1, aT2;
//
// 1. compute parameter on edge
BRep_Tool::Range(aE, aT1, aT2);
aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
//
// 2. compute point inside the face near the edge
TopoDS_Face aFF=aF;
TopoDS_Edge aERight;
aFF.Orientation(TopAbs_FORWARD);
BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight);
//
Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
(aERight, aFF, aT, aPInFace2D, aPInFace, theContext);
//
return iErr;
}
//=======================================================================
//function : MinStepIn2d
//purpose :
//=======================================================================
Standard_Real BOPTools_AlgoTools3D::MinStepIn2d()
{
Standard_Real dt=1.e-5;
return dt;
}
//=======================================================================
//function : IsEmptyShape
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape
(const TopoDS_Shape& aS)
{
Standard_Boolean bHasGeometry=Standard_False;
//
TopTools_IndexedMapOfShape myShapes;
//
Add(aS, myShapes, bHasGeometry);
return !bHasGeometry;
}
//=======================================================================
//function : Add
//purpose :
//=======================================================================
void Add(const TopoDS_Shape& aS,
TopTools_IndexedMapOfShape& myShapes,
Standard_Boolean& bHasGeometry)
{
Standard_Integer anIndex;
//
if (bHasGeometry) {
return;
}
//
if (aS.IsNull()) {
return;
}
//
TopoDS_Shape aSx = aS;
//
anIndex=myShapes.FindIndex(aSx);
if (!anIndex) {
bHasGeometry=HasGeometry (aSx);
if (bHasGeometry) {
return;
}
//
TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
for(; anIt.More(); anIt.Next()) {
const TopoDS_Shape& aSy=anIt.Value();
Add(aSy, myShapes, bHasGeometry);
//
if (bHasGeometry) {
return;
}
//
myShapes.Add(aSx);
}
}
}
//=======================================================================
//function : HasGeometry
//purpose :
//=======================================================================
Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
{
Standard_Boolean bHasGeometry=Standard_True;
TopAbs_ShapeEnum aType= aS.ShapeType();
if (aType == TopAbs_VERTEX) {
return bHasGeometry;
}
//
else if (aType == TopAbs_EDGE) {
Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
while (itrc.More()) {
const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
if (CR->IsCurve3D()) {
if (!CR->Curve3D().IsNull()) {
return bHasGeometry;
}
}
else if (CR->IsCurveOnSurface()) {
return bHasGeometry;
}
else if (CR->IsRegularity()) {
return bHasGeometry;
}
else if (!CR->Polygon3D().IsNull()) {
return bHasGeometry;
}
else if (CR->IsPolygonOnTriangulation()) {
return bHasGeometry;
}
else if (CR->IsPolygonOnSurface()) {
return bHasGeometry;
}
itrc.Next();
}
}
//
else if (aType == TopAbs_FACE) {
Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
if (!TF->Surface().IsNull()) {
return bHasGeometry;
}
Handle(Poly_Triangulation) Tr = TF->Triangulation();
if (!Tr.IsNull()) {
return bHasGeometry;
}
}
return !bHasGeometry;
}
//=======================================================================
//function : OrientEdgeOnFace
//purpose :
//=======================================================================
void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
const TopoDS_Face& aF,
TopoDS_Edge& aERight)
{
if (BRep_Tool::IsClosed(aE, aF)) {
aERight=aE;
aERight.Orientation(aE.Orientation());
Standard_Integer iFoundCount = 0;
TopoDS_Edge anEdge = aE;
TopExp_Explorer anExp(aF, TopAbs_EDGE);
for (; anExp.More(); anExp.Next()) {
const TopoDS_Shape& aSS=anExp.Current();
if (aSS.IsSame(aE)) {
anEdge = TopoDS::Edge(aSS);
iFoundCount++;
}
}
if(iFoundCount == 1) {
aERight = anEdge;
}
return;
}
TopExp_Explorer anExp(aF, TopAbs_EDGE);
for (; anExp.More(); anExp.Next()) {
const TopoDS_Shape& aSS=anExp.Current();
if (aSS.IsSame(aE)) {
aERight=aE;
aERight.Orientation(aSS.Orientation());
return;
}
}
aERight=aE;
aERight.Orientation(aE.Orientation());
}
//=======================================================================
//function : PointInFace
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointInFace
(const TopoDS_Face& theF,
gp_Pnt& theP,
gp_Pnt2d& theP2D,
const Handle(IntTools_Context)& theContext)
{
Standard_Integer i, iErr = 1;
Standard_Real aUMin, aUMax, aVMin, aVMax, aUx;
//
theContext->UVBounds(theF, aUMin, aUMax, aVMin, aVMax);
//
gp_Dir2d aD2D(0. , 1.);
aUx = IntTools_Tools::IntermediatePoint(aUMin, aUMax);
//
for (i = 0; i < 2; ++i) {
gp_Pnt2d aP2D(aUx, 0.);
Handle(Geom2d_Line) aL2D = new Geom2d_Line (aP2D, aD2D);
iErr = BOPTools_AlgoTools3D::PointInFace
(theF, aL2D, theP, theP2D, theContext);
if (iErr == 0) {
// done
break;
}
else {
// possible reason - incorrect computation of the 2d box of the face.
// try to compute the point with the translated line.
aUx = aUMax - (aUx - aUMin);
}
}
//
return iErr;
}
//=======================================================================
//function : PointInFace
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointInFace
(const TopoDS_Face& theF,
const TopoDS_Edge& theE,
const Standard_Real theT,
const Standard_Real theDt2D,
gp_Pnt& theP,
gp_Pnt2d& theP2D,
const Handle(IntTools_Context)& theContext)
{
Standard_Integer iErr;
Standard_Real f, l;
Handle(Geom2d_Curve) aC2D;
//
iErr = 0;
aC2D = BRep_Tool::CurveOnSurface (theE, theF, f, l);
if (aC2D.IsNull()) {
iErr = 5;
return iErr;
}
//
gp_Pnt2d aP2D;
gp_Vec2d aV2D;
//
aC2D->D1(theT, aP2D, aV2D);
gp_Dir2d aD2Dx(aV2D);
//
gp_Dir2d aD2D;
aD2D.SetCoord (-aD2Dx.Y(), aD2Dx.X());
//
if (theE.Orientation()==TopAbs_REVERSED){
aD2D.Reverse();
}
//
if (theF.Orientation()==TopAbs_REVERSED) {
aD2D.Reverse();
}
//
Handle(Geom2d_Line) aL2D = new Geom2d_Line(aP2D, aD2D);
Handle(Geom2d_TrimmedCurve) aL2DTrim =
new Geom2d_TrimmedCurve(aL2D, 0., Precision::Infinite());
//
iErr = BOPTools_AlgoTools3D::PointInFace
(theF, aL2DTrim, theP, theP2D, theContext, theDt2D);
//
return iErr;
}
//=======================================================================
//function : PointInFace
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools3D::PointInFace
(const TopoDS_Face& theF,
const Handle(Geom2d_Curve)& theL2D,
gp_Pnt& theP,
gp_Pnt2d& theP2D,
const Handle(IntTools_Context)& theContext,
const Standard_Real theDt2D)
{
Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
Standard_Integer iErr, aIH, aNbDomains;
Standard_Real aVx, aV1, aV2;
//
Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(theF);
//
Geom2dAdaptor_Curve aHCur(theL2D);
//
aHatcher.ClrHatchings();
aIH = aHatcher.AddHatching(aHCur);
//
iErr = 0;
for (;;) {
aHatcher.Trim();
bIsDone = aHatcher.TrimDone(aIH);
if (!bIsDone) {
iErr = 1;
break;
}
//
aHatcher.ComputeDomains(aIH);
bIsDone = aHatcher.IsDone(aIH);
if (!bIsDone) {
iErr = 2;
break;
}
//
aNbDomains = aHatcher.NbDomains(aIH);
if (aNbDomains == 0) {
iErr = 2;
break;
}
//
const HatchGen_Domain& aDomain = aHatcher.Domain (aIH, 1);
bHasFirstPoint = aDomain.HasFirstPoint();
if (!bHasFirstPoint) {
iErr = 3;
break;
}
//
bHasSecondPoint = aDomain.HasSecondPoint();
if (!bHasSecondPoint) {
iErr = 4;
break;
}
//
aV1 = aDomain.FirstPoint().Parameter();
aV2 = aDomain.SecondPoint().Parameter();
//
aVx = (theDt2D > 0. && (aV2 - aV1) > theDt2D) ? (aV1 + theDt2D) :
IntTools_Tools::IntermediatePoint(aV1, aV2);
//
Handle(Geom_Surface) aS = BRep_Tool::Surface(theF);
//
theL2D->D0(aVx, theP2D);
aS->D0(theP2D.X(), theP2D.Y(), theP);
break;
}
//
aHatcher.RemHatching(aIH);
return iErr;
}