1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-01 10:26:12 +03:00
occt/src/BOPTools/BOPTools_AlgoTools2D_1.cxx
emv 80d55adf7c 0029698: Regression vs 7.2.0: Common operation raises FLT_INVALID_OPERATION exception
When checking if the split edge is oriented as the original one (BOPTools_AlgoTools::IsSplitToReverse()) the tangent vectors should be computed for both edges at the same point. This point is taken on the split edge and projected on the original edge.
The fix is intended to ensuring that the reference point will be taken inside the valid range of the split edge (i.e. not covered by the tolerance spheres of its bounding vertices) and the projection of this point on the original edge will be successful. Moreover, several sampling points are now taken on the split edge and processed until first valid point is found.

If requested (by a not null pointer) all *BOPTools_AlgoTools::IsSplitToReverse()* methods are now return the error status of the check. Before using the returned flag, the calling program should check this error status. For successful check the error status should be equal to zero.

New warning *BOPAlgo_AlertUnableToOrientTheShape* is now returned in the algorithms in Boolean component in case the check for correct shape orientation failed.

Test case for the issue.
2018-05-23 05:44:12 +03:00

304 lines
8.1 KiB
C++

// Created by: Peter KURNEV
// Copyright (c) 1999-2015 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 <BOPTools_AlgoTools2D.hxx>
#include <Precision.hxx>
#include <gp_Vec2d.hxx>
#include <gp_Dir2d.hxx>
#include <TopLoc_Location.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom_Surface.hxx>
#include <GeomLib.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepLib.hxx>
#include <TopExp_Explorer.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_Tools.hxx>
#include <BOPTools_AlgoTools.hxx>
static
Standard_Integer UpdateClosedPCurve(const TopoDS_Edge& ,
const TopoDS_Edge& ,
const TopoDS_Face& ,
const Handle(IntTools_Context)& );
static
Standard_Boolean IsClosed(const TopoDS_Edge& ,
const TopoDS_Face& );
//=======================================================================
//function : AttachExistingPCurve
//purpose :
//=======================================================================
Standard_Integer BOPTools_AlgoTools2D::AttachExistingPCurve
(const TopoDS_Edge& aE2, // old
const TopoDS_Edge& aE1, // new
const TopoDS_Face& aF,
const Handle(IntTools_Context)& aCtx)
{
Standard_Boolean bIsToReverse, bIsClosed, bComp;
Standard_Integer iRet;
Standard_Real aTol, aT11, aT12, aT21, aT22, aTolPPC;
Standard_Real aTolSP, aTMax;
Handle(Geom2d_Curve) aC2Dold, aC2DoldC;
Handle(Geom2d_Curve) aC2DT;
BRep_Builder aBB;
//
iRet=0;
//
aC2Dold=BRep_Tool::CurveOnSurface(aE2, aF, aT21, aT22);
if (aC2Dold.IsNull()){
iRet=1;
return iRet;
}
//
aC2DoldC=Handle(Geom2d_Curve)::DownCast(aC2Dold->Copy());
//
bIsToReverse = BOPTools_AlgoTools::IsSplitToReverse(aE1, aE2, aCtx);
if (bIsToReverse) {
Standard_Real aT21r, aT22r;
//
aC2DoldC->Reverse();
//
aT21r=aC2DoldC->ReversedParameter(aT21);
aT22r=aC2DoldC->ReversedParameter(aT22);
aT21=aT22r;
aT22=aT21r;
}
//
aC2DT=new Geom2d_TrimmedCurve(aC2DoldC, aT21, aT22);
//
aTolPPC=Precision::PConfusion();
//
Handle(Geom_Curve) aCE1 = BRep_Tool::Curve(aE1, aT11, aT12);
//
GeomLib::SameRange(aTolPPC, aC2DT, aT21, aT22, aT11, aT12, aC2DT);
//
if (aC2DT.IsNull()){
iRet=2;
return iRet;
}
//
// check the curves on same parameter to prevent
// big tolerance increasing
Handle(Geom_Surface) aSF = BRep_Tool::Surface(aF);
//
bComp = IntTools_Tools::ComputeTolerance
(aCE1, aC2DT, aSF, aT11, aT12, aTolSP, aTMax, aTolPPC);
if (!bComp) {
iRet = 3;
return iRet;
}
//
aTol = BRep_Tool::Tolerance(aE1);
//
if ((aTolSP > 10.*aTol) && aTolSP > 0.1) {
iRet = 4;
return iRet;
}
//
// create a temporary edge to make same parameter pcurve
TopoDS_Edge aE1T;
aBB.MakeEdge(aE1T, aCE1, aTol);
aBB.Range(aE1T, aT11, aT12);
aBB.SameRange(aE1T, Standard_False);
aBB.SameParameter(aE1T, Standard_False);
//
aBB.UpdateEdge(aE1T, aC2DT, aF, aTol);
try {
BRepLib::SameParameter(aE1T);
BRepLib::SameRange(aE1T);
}
catch (Standard_Failure)
{
iRet = 6;
return iRet;
}
//
bIsClosed = IsClosed(aE2, aF);
if (bIsClosed) {
iRet = UpdateClosedPCurve(aE2, aE1T, aF, aCtx);
if(iRet) {
iRet = 5;
return iRet;
}
}
// transfer pcurve(s) from the temporary edge to the new edge
aBB.Transfert(aE1T, aE1);
// update tolerance of vertices
Standard_Real aNewTol = BRep_Tool::Tolerance(aE1T);
TopoDS_Iterator it(aE1);
for (; it.More(); it.Next())
aBB.UpdateVertex(TopoDS::Vertex(it.Value()), aNewTol);
return iRet;
}
//=======================================================================
//function : UpdateClosedPCurve
//purpose :
//=======================================================================
Standard_Integer UpdateClosedPCurve(const TopoDS_Edge& aEold,
const TopoDS_Edge& aEnew,
const TopoDS_Face& aF,
const Handle(IntTools_Context)& aCtx)
{
Standard_Boolean bUClosed, bRevOrder;
Standard_Integer aNbPoints, iRet;
Standard_Real aTS1, aTS2, aTS, aScPr, aUS1, aVS1, aUS2, aVS2, aT, aU, aV;
Standard_Real aT1, aT2, aTol;
gp_Pnt2d aP2DS1, aP2DS2, aP2D;
gp_Vec2d aV2DT, aV2D, aV2DS1, aV2DS2;
gp_Pnt aP;
Handle(Geom2d_Curve) aC2D, aC2DS1, aC2DS2, aC2Dnew, aC2DoldCT;
Handle(Geom2d_Curve) aC2Dold;
Handle(Geom2d_TrimmedCurve) aC2DTnew;
Handle(Geom_Surface) aS;
TopoDS_Edge aES;
BRep_Builder aBB;
//
iRet=0;
aTol=BRep_Tool::Tolerance(aEnew);
//
// aC2DoldCT is alone p-curve of aEnew that we've built
// The task is to build closed p-curves for aEnew
aC2DoldCT=BRep_Tool::CurveOnSurface(aEnew, aF, aT1, aT2);
//
// aC2Dold is p-curve of aEold
aC2Dold=BRep_Tool::CurveOnSurface(aEold, aF, aT1, aT2);
//
// As aEold is closed on aF, it is possible to retrieve
// the two p-curves:
// aC2DS1 -first p-curve
// aC2DS2 -second p-curve
aES=aEold;
aES.Orientation(TopAbs_FORWARD);
aC2DS1=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
//
aES.Orientation(TopAbs_REVERSED);
aC2DS2=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
//
aTS=BOPTools_AlgoTools2D::IntermediatePoint(aTS1, aTS2);
//
aC2DS1->D1(aTS, aP2DS1, aV2DS1);
aC2DS2->D1(aTS, aP2DS2, aV2DS2);
//
// aV2DS12 - translation vector
gp_Vec2d aV2DS12(aP2DS1, aP2DS2);
gp_Dir2d aD2DS12(aV2DS12);
const gp_Dir2d& aD2DX=gp::DX2d();
//
// Directoion of closeness: U-Closed or V-Closed
aScPr=aD2DS12*aD2DX;
bUClosed=Standard_True;
if (fabs(aScPr) < aTol) {
bUClosed=!bUClosed;
}
//
aP2DS1.Coord(aUS1, aVS1);
aP2DS2.Coord(aUS2, aVS2);
//
// aP - some 3D-point on seam edge of the surface aS
aS=BRep_Tool::Surface(aF);
aS->D0(aUS1, aVS1, aP);
//
GeomAPI_ProjectPointOnCurve& aProjPC=aCtx->ProjPC(aEnew);
//
aProjPC.Perform(aP);
aNbPoints=aProjPC.NbPoints();
if (!aNbPoints) {
iRet=1;
return iRet;
}
//
// aT - parameter for aP on the curves of aEnew
aT=aProjPC.LowerDistanceParameter();
//
aC2D=aC2DoldCT;
aC2D->D1(aT, aP2D, aV2D);
aP2D.Coord(aU, aV);
//
aC2Dnew=Handle(Geom2d_Curve)::DownCast(aC2D->Copy());
aC2DTnew=new Geom2d_TrimmedCurve(aC2Dnew, aT1, aT2);
//
aV2DT=aV2DS12;
if (!bUClosed) { // V Closed
if (fabs(aV-aVS2)<aTol) {
aV2DT.Reverse();
}
}
else { // U Closed
if (fabs(aU-aUS2)<aTol) {
aV2DT.Reverse();
}
}
//
// Translate aC2DTnew
aC2DTnew->Translate(aV2DT);
//
// 4 Order the 2D curves
bRevOrder=Standard_False;
aScPr=aV2D*aV2DS1;
if(aScPr<0.) {
bRevOrder=!bRevOrder;
}
//
if (!bRevOrder) {
aBB.UpdateEdge(aEnew, aC2D, aC2DTnew, aF, aTol);
}
else {
aBB.UpdateEdge(aEnew, aC2DTnew, aC2D , aF, aTol);
}
return iRet;
}
//=======================================================================
//function : IsClosed
//purpose :
//=======================================================================
Standard_Boolean IsClosed(const TopoDS_Edge& aE,
const TopoDS_Face& aF)
{
Standard_Boolean bRet;
//
bRet=BRep_Tool::IsClosed(aE, aF);
if (bRet) {
Standard_Integer iCnt;
//
iCnt=0;
TopExp_Explorer aExp(aF, TopAbs_EDGE);
for (; (aExp.More() || iCnt==2); aExp.Next()) {
const TopoDS_Shape& aEx=aExp.Current();
if(aEx.IsSame(aE)) {
++iCnt;
}
}
bRet=(iCnt==2);
}
return bRet;
}