From: pkv Date: Thu, 30 Apr 2015 11:41:27 +0000 (+0300) Subject: 0025880: fuzzy booleans with multiple tools X-Git-Tag: V6_9_0~41 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=905522eef86206366d00b45af3e205e0b11a7b4f 0025880: fuzzy booleans with multiple tools New features: class BOPTools_AlgoTools2D method: Standard_Integer BOPTools_AlgoTools2D::AttachExistingPCurve (const TopoDS_Edge& aEold, const TopoDS_Edge& aEnew, const TopoDS_Face& aF, const Handle(IntTools_Context)& aCtx) has been added. Purpose: To attach P-Curve on surface of the face from the edge to the edge It returns 0 in case of success. Changes: 1. class BOPTools_AlgoTools method: Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse (const TopoDS_Face& theFSp, const TopoDS_Face& theFSr, Handle(IntTools_Context)& theContext) The condition for a point on the surface of a face has been changed. 2. class BOPAlgo_PaveFiller method: void BOPAlgo_PaveFiller::MakePCurves() The treatment of E/E common bocks has been changed to use mechanism of attacment P-Curves [ I.1 ] Test case for issue CR25880 --- diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx index 18b163103d..445f7ec233 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx @@ -202,9 +202,47 @@ class BOPAlgo_MPC : public BOPAlgo_Algo { return myFlag; } // + void SetData(const TopoDS_Edge& aEz, + const TopoDS_Vertex& aV1, + const Standard_Real aT1, + const TopoDS_Vertex& aV2, + const Standard_Real aT2) { + myEz=aEz; + myV1=aV1; + myT1=aT1; + myV2=aV2; + myT2=aT2; + } + // + void SetContext(const Handle(IntTools_Context)& aContext) { + myContext=aContext; + } + // + const Handle(IntTools_Context)& Context()const { + return myContext; + } + // virtual void Perform() { - BOPAlgo_Algo::UserBreak(); - BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF); + Standard_Integer iErr; + // + iErr=1; + if (!myEz.IsNull()) { + TopoDS_Edge aSpz; + // + BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1, + myV2, myT2, aSpz); + // + iErr= + BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz, + myE, + myF, + myContext); + } + // + if (iErr) { + BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF); + } + // if (myFlag) { UpdateVertices(myE, myF); } @@ -214,19 +252,29 @@ class BOPAlgo_MPC : public BOPAlgo_Algo { Standard_Boolean myFlag; TopoDS_Edge myE; TopoDS_Face myF; + TopoDS_Edge myEz; + TopoDS_Vertex myV1; + Standard_Real myT1; + TopoDS_Vertex myV2; + Standard_Real myT2; + // + Handle(IntTools_Context) myContext; }; // //======================================================================= typedef BOPCol_NCVector BOPAlgo_VectorOfMPC; // -typedef BOPCol_Functor +typedef BOPCol_ContextFunctor BOPAlgo_MPCFunctor; + BOPAlgo_VectorOfMPC, + Handle(IntTools_Context), + IntTools_Context> BOPAlgo_MPCFunctor; // -typedef BOPCol_Cnt +typedef BOPCol_ContextCnt BOPAlgo_MPCCnt; + BOPAlgo_VectorOfMPC, + Handle(IntTools_Context)> BOPAlgo_MPCCnt; // //======================================================================= //class : BOPAlgo_BPC @@ -422,8 +470,8 @@ Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE, //======================================================================= void BOPAlgo_PaveFiller::MakePCurves() { - - Standard_Integer i, nF1, nF2, aNbC, k, nE, aNbFF, aNbFI; + Standard_Boolean bHasPC; + Standard_Integer i, nF1, nF2, aNbC, k, nE, aNbFF, aNbFI, nEx; BOPDS_ListIteratorOfListOfPaveBlock aItLPB; BOPDS_MapIteratorOfMapOfPaveBlock aItMPB; TopoDS_Face aF1F, aF2F; @@ -460,15 +508,64 @@ void BOPAlgo_PaveFiller::MakePCurves() aItMPB.Initialize(aMPBOn); for(; aItMPB.More(); aItMPB.Next()) { const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value(); - if (myDS->IsCommonBlockOnEdge(aPB)) { - nE=aPB->Edge(); - const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); + nE=aPB->Edge(); + const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); + bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF1F); + if (bHasPC) { + continue; + } + // + Handle(BOPDS_CommonBlock) aCB=myDS->CommonBlock(aPB); + if (!aCB) { + continue; + } + // + const BOPDS_ListOfPaveBlock& aLPB=aCB->PaveBlocks(); + if (aLPB.Extent()<2) { + continue; + } + // + BOPAlgo_MPC& aMPC=aVMPC.Append1(); + // + aItLPB.Initialize(aLPB); + for(; aItLPB.More(); aItLPB.Next()) { + const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value(); + if (aPBx==aPB) { + continue; + } + // + nEx=aPBx->OriginalEdge(); + const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx))); + bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F); + if (!bHasPC) { + continue; + } + // + Standard_Integer nV1x, nV2x; + Standard_Real aT1x, aT2x; + TopoDS_Vertex aV1x, aV2x; + TopoDS_Edge aEz; + // + aEz=aEx; + aEz.Orientation(TopAbs_FORWARD); + // + aPBx->Indices(nV1x, nV2x); + aPBx->Range(aT1x, aT2x); // - BOPAlgo_MPC& aMPC=aVMPC.Append1(); - aMPC.SetEdge(aE); - aMPC.SetFace(aF1F); - aMPC.SetProgressIndicator(myProgressIndicator); + aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x))); + aV1x.Orientation(TopAbs_FORWARD); + // + aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x))); + aV2x.Orientation(TopAbs_REVERSED); + // + aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x); + // + break; } + // + aMPC.SetEdge(aE); + aMPC.SetFace(aF1F); + aMPC.SetProgressIndicator(myProgressIndicator); } }// for (i=0; iIsPointInFace (theFSr, aP2D); + bInFace=theContext->IsPointInOnFace (theFSr, aP2D); if (!bInFace) { return bRet; } diff --git a/src/BOPTools/BOPTools_AlgoTools2D.cdl b/src/BOPTools/BOPTools_AlgoTools2D.cdl index c88ae7eb4f..51bd22d407 100644 --- a/src/BOPTools/BOPTools_AlgoTools2D.cdl +++ b/src/BOPTools/BOPTools_AlgoTools2D.cdl @@ -27,7 +27,8 @@ uses Surface from BRepAdaptor, Curve from Geom2d, Curve from Geom, - ProjectedCurve from ProjLib, + ProjectedCurve from ProjLib, + Context from IntTools, ListOfShape from BOPCol is @@ -205,5 +206,15 @@ is ---Purpose: --- Make empty P-Curve of relevant to type --- - + AttachExistingPCurve (myclass; + aEold : Edge from TopoDS; + aEnew : Edge from TopoDS; + aF : Face from TopoDS; + aCtx : Context from IntTools) + returns Integer from Standard; + ---Purpose: + --- Attach P-Curve from the edge on surface + --- to the edge + --- Returns 0 in case of success + end AlgoTools2D; diff --git a/src/BOPTools/BOPTools_AlgoTools2D_1.cxx b/src/BOPTools/BOPTools_AlgoTools2D_1.cxx new file mode 100644 index 0000000000..028a64a67a --- /dev/null +++ b/src/BOPTools/BOPTools_AlgoTools2D_1.cxx @@ -0,0 +1,311 @@ +// 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 +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + + + +static + Standard_Integer UpdateClosedPCurve(const TopoDS_Edge& , + const TopoDS_Edge& , + const TopoDS_Face& , + const Handle(IntTools_Context)& ); +static + Standard_Boolean IsToReverse(const TopoDS_Edge& , + const TopoDS_Edge& , + 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; + Standard_Integer iRet; + Standard_Real aTol, aT11, aT12, aT21, aT22, aTolPPC; + Handle(Geom2d_Curve) aC2Dold, aC2DoldC; + Handle(Geom2d_TrimmedCurve) 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=IsToReverse(aE2, aE1, aCtx); + if (bIsToReverse) { + aC2DoldC->Reverse(); + // + gp_Pnt2d aP1, aP2; + // + aC2Dold->D0(aT22, aP2); + aC2DoldC->D0(aT21, aP1); + aC2DoldC->Translate(aP1, aP2); + } + // + aC2DT=new Geom2d_TrimmedCurve(aC2DoldC, aT21, aT22); + // + aTol=BRep_Tool::Tolerance(aE1); + BRep_Tool::Range (aE1, aT11, aT12); + aBB.SameRange(aE1, Standard_False); + aBB.SameParameter(aE1, Standard_False); + + aTolPPC=Precision::PConfusion(); + // + GeomLib::SameRange(aTolPPC, aC2DT, aT21, aT22, aT11, aT12, aC2DT); + // + if (aC2DT.IsNull()){ + iRet=2; + return iRet; + } + // + aBB.UpdateEdge(aE1, aC2DT, aF, aTol); + BRepLib::SameParameter(aE1); + BRepLib::SameRange(aE1); + // + bIsClosed=IsClosed(aE2, aF); + if (bIsClosed) { + iRet=UpdateClosedPCurve(aE2, aE1, aF, aCtx); + if(iRet) { + iRet=3; + } + } + // + 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)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 : IsToReverse +//purpose : +//======================================================================= +Standard_Boolean IsToReverse(const TopoDS_Edge& aEold, + const TopoDS_Edge& aEnew, + const Handle(IntTools_Context)& aCtx) +{ + Standard_Boolean bRet, bFlag, bIsDegenerated; + Standard_Real aTnew, aTold, aScPr, aTa, aTb, aT1, aT2; + gp_Vec aVold, aVnew, aVE, aVS; + gp_Pnt aP; + Handle(Geom_Curve) aCold, aCnew; + // + bRet=Standard_False; + // + bIsDegenerated=(BRep_Tool::Degenerated(aEold) || + BRep_Tool::Degenerated(aEnew)); + if (bIsDegenerated) { + return bRet; + } + // + aCold=BRep_Tool::Curve(aEold, aT1, aT2); + aCnew=BRep_Tool::Curve(aEnew, aTa, aTb); + // + if (aCold==aCnew) { + return bRet; + } + // + aTnew=BOPTools_AlgoTools2D::IntermediatePoint(aTa, aTb); + aCnew->D1(aTnew, aP, aVnew); + aVnew.Normalize(); + // + bFlag=aCtx->ProjectPointOnEdge(aP, aEold, aTold); + aCold->D1(aTold, aP, aVold); + aVold.Normalize(); + // + aScPr=aVnew*aVold; + bRet=(aScPr<0.); + // + return bRet; +} +//======================================================================= +//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; +} + diff --git a/src/BOPTools/FILES b/src/BOPTools/FILES index 29abf1699a..2c9ebf69d9 100755 --- a/src/BOPTools/FILES +++ b/src/BOPTools/FILES @@ -10,3 +10,5 @@ BOPTools_ListOfCoupleOfShape.hxx BOPTools_ListOfEdgeSet.hxx BOPTools_MapOfSet.hxx BOPTools_DataMapOfShapeSet.hxx + +BOPTools_AlgoTools2D_1.cxx diff --git a/src/GeomLib/GeomLib.cxx b/src/GeomLib/GeomLib.cxx index 90fff06966..a38fda2821 100644 --- a/src/GeomLib/GeomLib.cxx +++ b/src/GeomLib/GeomLib.cxx @@ -952,18 +952,9 @@ void GeomLib::SameRange(const Standard_Real Tolerance, else { // On segmente le resultat Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve( CurvePtr, FirstOnCurve, LastOnCurve ); - - Standard_Real newFirstOnCurve = TC->FirstParameter(), newLastOnCurve = TC->LastParameter(); - + // Handle(Geom2d_BSplineCurve) BS = Geom2dConvert::CurveToBSplineCurve(TC); - - if (BS->IsPeriodic()) - BS->Segment( newFirstOnCurve, newLastOnCurve) ; - else - BS->Segment( Max(newFirstOnCurve, BS->FirstParameter()), - Min(newLastOnCurve, BS->LastParameter()) ); - TColStd_Array1OfReal Knots(1,BS->NbKnots()); BS->Knots(Knots); diff --git a/tests/bugs/modalg_6/bug25880 b/tests/bugs/modalg_6/bug25880 new file mode 100755 index 0000000000..54c637d94f --- /dev/null +++ b/tests/bugs/modalg_6/bug25880 @@ -0,0 +1,65 @@ +puts "============" +puts "OCC25880" +puts "============" +puts "" +############################### +## fuzzy booleans with multiple tools +############################### + +bfuzzyvalue 0.00001 +box Box018 13.550000190735 50.200000762939 3.299999952316 +ttranslate Box018 -19.1 -0.1 2.35 +#Object Label: Box + +psphere Sphere002 1.600000023842 0 90 180 +ttranslate Sphere002 -15 50.1 5.5 +#Object Label: LeftSph + +#bfuse to-Fusion-001-t Box018 Sphere002 +pcylinder Cylinder006 1.600000023842 3.200000047684 180 +ttranslate Cylinder006 -15 50.1 2.35 + +#Object Label: LeftHalfCyl +bfuse to-Fusion-002-t to-Fusion-001-t Cylinder006 +psphere Sphere001 1.600000023842 0 90 180 +trotate Sphere001 0 0 0 1 0 0 90 +ttranslate Sphere001 -15 -0.1 5.5 + +#Object Label: RightSph +bfuse to-Fusion-003-t to-Fusion-002-t Sphere001 +pcylinder Cylinder005 1.600000023842 3.200000047684 180 +trotate Cylinder005 0 0 0 0 0 1 180 +ttranslate Cylinder005 -15 -0.1 2.35 + +#Object Label: RightHalfCyl +bfuse to-Fusion-004-t to-Fusion-003-t Cylinder005 +pcylinder Cylinder004 1.600000023842 50.200000762939 180 +trotate Cylinder004 0 0 0 0 0.7071067811865475 0.7071067811865475 180 +ttranslate Cylinder004 -15.000003814697 -0.100001335144 5.500000953674 + +#Object Label: TopHalfCyl +#bfuse Fusion to-Fusion-004-t Cylinder004 +bclearobjects +bcleartools +baddobjects Box018 +baddtools Sphere002 Cylinder006 Sphere001 Cylinder005 Cylinder004 +bfillds +bbop result 1 + +set square 1893.17 + +set nbshapes_expected " +Number of shapes in shape + VERTEX : 32 + EDGE : 51 + WIRE : 20 + FACE : 20 + SHELL : 1 + SOLID : 1 + COMPSOLID : 0 + COMPOUND : 1 + SHAPE : 126 +" +checknbshapes result -ref ${nbshapes_expected} -t -m "fuzzy booleans with multiple tools" + +set 3dviewer 1 diff --git a/tests/sewing/tol_0_01/F8 b/tests/sewing/tol_0_01/F8 index 55c402d4dd..dcc41b4586 100644 --- a/tests/sewing/tol_0_01/F8 +++ b/tests/sewing/tol_0_01/F8 @@ -1,4 +1,4 @@ -puts "TODO OCC23674 ALL: Error : Number of faults is" +#puts "TODO OCC23674 ALL: Error : Number of faults is" puts "TODO ?OCC24592 ALL: Error : Number of free edges is" restore [locate_data_file CCH_indusheq.rle] a