From 03cca6f742e2377fff6fa97bf357dfe3e6e832cc Mon Sep 17 00:00:00 2001 From: emv Date: Tue, 26 Dec 2017 14:28:27 +0300 Subject: [PATCH] 0028599: Replacement of old Boolean operations with new ones in BRepProj_Projection algorithm The usage of *BRepAlgo_Section* has been replaced with the usage of *BRepAlgoAPI_Section* in *BRepProj_Projection* algorithm. The TODO statements have been removed from the failing test case in the "prj" grid as they are working correctly now. The following changes have been made to improve the performance *BRepAlgoAPI_Section*: 1. Revision of the *IntPolyh_Intersection* class to avoid repeated calculation of the deflection of the same triangulation. 2. Small revision of the Edge/Face intersection algorithm to perform Extrema computation on the whole intersection range of the edge instead of discrete ranges. 3. Implementation of the extrema computation for the Circle and Sphere. 4. Correct computation of the parameter of the point on the Circle. --- dox/dev_guides/upgrade/upgrade.md | 3 + src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx | 9 +- src/BOPAlgo/BOPAlgo_SectionAttribute.cxx | 55 -- src/BOPAlgo/BOPAlgo_SectionAttribute.hxx | 105 ++- src/BOPAlgo/BOPAlgo_SectionAttribute.lxx | 41 - src/BOPAlgo/FILES | 2 - src/BOPTest/BOPTest_BOPCommands.cxx | 5 +- src/BRepAlgoAPI/BRepAlgoAPI_Section.cxx | 41 +- src/BRepAlgoAPI/BRepAlgoAPI_Section.hxx | 14 - src/BRepProj/BRepProj_Projection.cxx | 16 +- src/BRepTest/BRepTest_ProjectionCommands.cxx | 113 ++- src/ElCLib/ElCLib.cxx | 22 +- src/Extrema/Extrema_ExtCS.cxx | 326 ++++---- src/Extrema/Extrema_ExtElCS.cxx | 136 +++- src/GeomAPI/GeomAPI_ExtremaCurveSurface.cxx | 4 +- src/GeometryTest/GeometryTest_APICommands.cxx | 9 +- src/IntPolyh/FILES | 4 +- .../IntPolyh_ArrayOfPointNormal.hxx} | 23 +- src/IntPolyh/IntPolyh_Intersection.cxx | 698 +++++++++++------- src/IntPolyh/IntPolyh_Intersection.hxx | 281 ++++--- src/IntPolyh/IntPolyh_Intersection_1.cxx | 317 -------- src/IntPolyh/IntPolyh_MaillageAffinage.cxx | 309 +++----- src/IntPolyh/IntPolyh_MaillageAffinage.hxx | 50 +- src/IntPolyh/IntPolyh_Tools.cxx | 198 +++++ src/IntPolyh/IntPolyh_Tools.hxx | 60 ++ src/IntTools/FILES | 1 - src/IntTools/IntTools_BeanFaceIntersector.cxx | 523 +++++-------- src/IntTools/IntTools_BeanFaceIntersector.hxx | 22 +- src/IntTools/IntTools_EdgeFace.cxx | 151 +--- src/IntTools/IntTools_EdgeFace.hxx | 193 ++--- tests/bugs/modalg_1/buc60462_2 | 4 +- tests/bugs/modalg_1/buc60463 | 6 +- tests/bugs/modalg_6/bug26063 | 12 +- tests/bugs/modalg_7/bug23927 | 4 +- tests/bugs/modalg_7/bug25385 | 4 +- tests/bugs/moddata_3/bug25407_1 | 7 +- tests/bugs/moddata_3/bug25407_2 | 7 +- tests/de/step_1/J6 | 8 +- tests/lowalgos/extcs/bug29426_1 | 18 + tests/lowalgos/extcs/bug29426_2 | 17 + tests/lowalgos/extcs/circ_sph_inter | 127 ++++ tests/lowalgos/extcs/circ_sph_nointer | 160 ++++ tests/lowalgos/extcs/circ_sph_parallel | 82 ++ tests/lowalgos/extcs/circ_sph_touch | 93 +++ tests/lowalgos/grids.list | 1 + tests/prj/base/C5 | 3 - tests/prj/base/D9 | 3 - tests/prj/base/E2 | 3 - tests/prj/base/E7 | 3 - tests/prj/base/H4 | 3 - 50 files changed, 2329 insertions(+), 1967 deletions(-) delete mode 100644 src/BOPAlgo/BOPAlgo_SectionAttribute.cxx delete mode 100644 src/BOPAlgo/BOPAlgo_SectionAttribute.lxx rename src/{IntTools/IntTools_BeanFaceIntersector.lxx => IntPolyh/IntPolyh_ArrayOfPointNormal.hxx} (54%) delete mode 100644 src/IntPolyh/IntPolyh_Intersection_1.cxx create mode 100644 src/IntPolyh/IntPolyh_Tools.cxx create mode 100644 src/IntPolyh/IntPolyh_Tools.hxx create mode 100644 tests/lowalgos/extcs/bug29426_1 create mode 100644 tests/lowalgos/extcs/bug29426_2 create mode 100644 tests/lowalgos/extcs/circ_sph_inter create mode 100644 tests/lowalgos/extcs/circ_sph_nointer create mode 100644 tests/lowalgos/extcs/circ_sph_parallel create mode 100644 tests/lowalgos/extcs/circ_sph_touch diff --git a/dox/dev_guides/upgrade/upgrade.md b/dox/dev_guides/upgrade/upgrade.md index 970fc6ab96..2029e70118 100644 --- a/dox/dev_guides/upgrade/upgrade.md +++ b/dox/dev_guides/upgrade/upgrade.md @@ -1529,3 +1529,6 @@ The public method *BuildSection()* in the class *BOPAlgo_Section* has became pro The method BRepAdaptor_CompCurve::SetPeriodic has been eliminated. Since new version, the method BRepAdaptor_CompCurve::IsPeriodic() will always return FALSE. Earlier, it could return TRUE in case if the wire contained only one edge based on periodic curve. + +@subsection upgrade_730_removed Removed features +* The methods *SetDeflection*, *SetEpsilonT*, *SetDiscretize* of the class *IntTools_EdgeFace* have been removed as excessive. diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx index 19afaa4152..7aa22d16f9 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx @@ -167,9 +167,9 @@ void BOPAlgo_PaveFiller::PerformEF() Standard_Boolean bV[2], bIsPBSplittable; Standard_Boolean bV1, bV2, bExpressCompute; Standard_Integer nV1, nV2; - Standard_Integer aDiscretize, i, aNbCPrts, iX, nV[2]; + Standard_Integer i, aNbCPrts, iX, nV[2]; Standard_Integer aNbEdgeFace, k; - Standard_Real aTolE, aTolF, aTS1, aTS2, aT1, aT2, aDeflection; + Standard_Real aTolE, aTolF, aTS1, aTS2, aT1, aT2; Handle(NCollection_BaseAllocator) aAllocator; TopAbs_ShapeEnum aType; BOPDS_ListIteratorOfListOfPaveBlock aIt; @@ -183,9 +183,6 @@ void BOPAlgo_PaveFiller::PerformEF() BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(100, aAllocator); BOPAlgo_DataMapOfPaveBlockBndBox aDMPBBox(100, aAllocator); // - aDiscretize=35; - aDeflection=0.01; - // BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF(); aEFs.SetIncrement(iSize); // @@ -242,8 +239,6 @@ void BOPAlgo_PaveFiller::PerformEF() aEdgeFace.SetEdge (aE); aEdgeFace.SetFace (aF); aEdgeFace.SetFuzzyValue(myFuzzyValue); - aEdgeFace.SetDiscretize (aDiscretize); - aEdgeFace.SetDeflection (aDeflection); aEdgeFace.UseQuickCoincidenceCheck(bExpressCompute); // IntTools_Range aSR(aTS1, aTS2); diff --git a/src/BOPAlgo/BOPAlgo_SectionAttribute.cxx b/src/BOPAlgo/BOPAlgo_SectionAttribute.cxx deleted file mode 100644 index 8509a716b8..0000000000 --- a/src/BOPAlgo/BOPAlgo_SectionAttribute.cxx +++ /dev/null @@ -1,55 +0,0 @@ -// Created on: 2002-03-04 -// Created by: Michael KLOKOV -// Copyright (c) 2002-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 - -//======================================================================= -// function: BOPAlgo_SectionAttribute -// purpose: -//======================================================================= -BOPAlgo_SectionAttribute::BOPAlgo_SectionAttribute(const Standard_Boolean Aproximation, - const Standard_Boolean PCurveOnS1, - const Standard_Boolean PCurveOnS2) -{ - myApproximation = Aproximation; - myPCurve1 = PCurveOnS1; - myPCurve2 = PCurveOnS2; -} -//======================================================================= -// function: Approximation -// purpose: -//======================================================================= -void BOPAlgo_SectionAttribute::Approximation(const Standard_Boolean theFlag) -{ - myApproximation = theFlag; -} -//======================================================================= -// function: PCurveOnS1 -// purpose: -//======================================================================= -void BOPAlgo_SectionAttribute::PCurveOnS1(const Standard_Boolean theFlag) -{ - myPCurve1 = theFlag; -} -//======================================================================= -// function: PCurveOnS2 -// purpose: -//======================================================================= -void BOPAlgo_SectionAttribute::PCurveOnS2(const Standard_Boolean theFlag) -{ - myPCurve2 = theFlag; -} - diff --git a/src/BOPAlgo/BOPAlgo_SectionAttribute.hxx b/src/BOPAlgo/BOPAlgo_SectionAttribute.hxx index 3c6bb8bc75..a0770c3c7a 100644 --- a/src/BOPAlgo/BOPAlgo_SectionAttribute.hxx +++ b/src/BOPAlgo/BOPAlgo_SectionAttribute.hxx @@ -16,75 +16,72 @@ #ifndef _BOPAlgo_SectionAttribute_HeaderFile #define _BOPAlgo_SectionAttribute_HeaderFile -#include -#include -#include - #include - -//! Class is a container of three flags used +//! Class is a container of the flags used //! by intersection algorithm -class BOPAlgo_SectionAttribute +class BOPAlgo_SectionAttribute { public: - DEFINE_STANDARD_ALLOC - - - - //! Initializes me by flags - Standard_EXPORT BOPAlgo_SectionAttribute(const Standard_Boolean Aproximation = Standard_True, const Standard_Boolean PCurveOnS1 = Standard_True, const Standard_Boolean PCurveOnS2 = Standard_True); - - - //! Modifier - Standard_EXPORT void Approximation (const Standard_Boolean theFlag); - - - //! Modifier - Standard_EXPORT void PCurveOnS1 (const Standard_Boolean theFlag); - - - //! Modifier - Standard_EXPORT void PCurveOnS2 (const Standard_Boolean theFlag); - - - //! Selector - Standard_Boolean Approximation() const; - - - //! Selector - Standard_Boolean PCurveOnS1() const; - - - //! Selector - Standard_Boolean PCurveOnS2() const; - - - + //! Default constructor + BOPAlgo_SectionAttribute() + : myApproximation(Standard_True), + myPCurve1(Standard_True), + myPCurve2(Standard_True) {} + + //! Constructor + BOPAlgo_SectionAttribute(const Standard_Boolean theAproximation, + const Standard_Boolean thePCurveOnS1, + const Standard_Boolean thePCurveOnS2) + : myApproximation(theAproximation), + myPCurve1(thePCurveOnS1), + myPCurve2(thePCurveOnS2) {} + + //! Sets the Approximation flag + void Approximation(const Standard_Boolean theApprox) + { + myApproximation = theApprox; + } + + //! Sets the PCurveOnS1 flag + void PCurveOnS1(const Standard_Boolean thePCurveOnS1) + { + myPCurve1 = thePCurveOnS1; + } + + //! Sets the PCurveOnS2 flag + void PCurveOnS2(const Standard_Boolean thePCurveOnS2) + { + myPCurve2 = thePCurveOnS2; + } + + //! Returns the Approximation flag + Standard_Boolean Approximation() const + { + return myApproximation; + } + + //! Returns the PCurveOnS1 flag + Standard_Boolean PCurveOnS1() const + { + return myPCurve1; + } + + //! Returns the PCurveOnS2 flag + Standard_Boolean PCurveOnS2() const + { + return myPCurve2; + } protected: - - - - private: - - Standard_Boolean myApproximation; Standard_Boolean myPCurve1; Standard_Boolean myPCurve2; - }; - -#include - - - - - #endif // _BOPAlgo_SectionAttribute_HeaderFile diff --git a/src/BOPAlgo/BOPAlgo_SectionAttribute.lxx b/src/BOPAlgo/BOPAlgo_SectionAttribute.lxx deleted file mode 100644 index c09b5915be..0000000000 --- a/src/BOPAlgo/BOPAlgo_SectionAttribute.lxx +++ /dev/null @@ -1,41 +0,0 @@ -// Created on: 2002-03-04 -// Created by: Michael KLOKOV -// Copyright (c) 2002-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. - -//======================================================================= -// function:Approximation -// purpose: -//======================================================================= -inline Standard_Boolean BOPAlgo_SectionAttribute::Approximation() const -{ - return myApproximation; -} -//======================================================================= -// function:PCurveOnS1 -// purpose: -//======================================================================= -inline Standard_Boolean BOPAlgo_SectionAttribute::PCurveOnS1() const -{ - return myPCurve1; -} -//======================================================================= -// function:PCurveOnS2 -// purpose: -//======================================================================= -inline Standard_Boolean BOPAlgo_SectionAttribute::PCurveOnS2() const -{ - return myPCurve2; -} - - diff --git a/src/BOPAlgo/FILES b/src/BOPAlgo/FILES index 651807aea9..37036eb35a 100644 --- a/src/BOPAlgo/FILES +++ b/src/BOPAlgo/FILES @@ -55,9 +55,7 @@ BOPAlgo_PSection.hxx BOPAlgo_PWireEdgeSet.hxx BOPAlgo_Section.cxx BOPAlgo_Section.hxx -BOPAlgo_SectionAttribute.cxx BOPAlgo_SectionAttribute.hxx -BOPAlgo_SectionAttribute.lxx BOPAlgo_ShellSplitter.cxx BOPAlgo_ShellSplitter.hxx BOPAlgo_Tools.cxx diff --git a/src/BOPTest/BOPTest_BOPCommands.cxx b/src/BOPTest/BOPTest_BOPCommands.cxx index d6c1f552ea..26a5be4ead 100644 --- a/src/BOPTest/BOPTest_BOPCommands.cxx +++ b/src/BOPTest/BOPTest_BOPCommands.cxx @@ -101,7 +101,10 @@ static Standard_Integer mkvolume (Draw_Interpretor&, Standard_Integer, const c theCommands.Add("bfuse" , "use bfuse r s1 s2" , __FILE__,bfuse, g); theCommands.Add("bcut" , "use bcut r s1 s2" , __FILE__,bcut, g); theCommands.Add("btuc" , "use btuc r s1 s2" , __FILE__,btuc, g); - theCommands.Add("bsection", "use bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]", + theCommands.Add("bsection", "use bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]" + "Builds section between shapes. Options:\n" + "-n2d/-n2d1/-n2d2 - disable the PCurve construction;\n" + "-na - disables the approximation of the section curves.\n", __FILE__, bsection, g); // theCommands.Add("bopcurves", "use bopcurves F1 F2 [-2d/-2d1/-2d2] " diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Section.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_Section.cxx index ac992b3aa8..2e59aaf5f4 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_Section.cxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_Section.cxx @@ -17,24 +17,22 @@ // modified by Michael KLOKOV Wed Mar 6 15:01:25 2002 // modified by Eugeny MALTCHIKOV Wed Jul 04 11:13:01 2012 -#include +#include + #include -#include + #include -#include -#include + #include #include -#include + #include #include + #include -#include -#include + #include #include -#include -#include // static @@ -176,11 +174,9 @@ BRepAlgoAPI_Section::~BRepAlgoAPI_Section() void BRepAlgoAPI_Section::Init(const Standard_Boolean bFlag) { myOperation=BOPAlgo_SECTION; - myParametersChanged = Standard_False; myApprox = Standard_False; myComputePCurve1 = Standard_False; myComputePCurve2 = Standard_False; - myParametersChanged = Standard_True; // if (bFlag) { Build(); @@ -194,7 +190,6 @@ void BRepAlgoAPI_Section::Init1(const TopoDS_Shape& S1) { myArguments.Clear(); myArguments.Append(S1); - myParametersChanged = Standard_True; } //======================================================================= //function : Init1 @@ -220,7 +215,6 @@ void BRepAlgoAPI_Section::Init2(const TopoDS_Shape& S2) { myTools.Clear(); myTools.Append(S2); - myParametersChanged = Standard_True; } //======================================================================= //function : Init2 @@ -244,10 +238,7 @@ void BRepAlgoAPI_Section::Init2(const Handle(Geom_Surface)& Sf) //======================================================================= void BRepAlgoAPI_Section::Approximation(const Standard_Boolean B) { - if(myApprox != B) { - myApprox = B; - myParametersChanged = Standard_True; - } + myApprox = B; } //======================================================================= //function : ComputePCurveOn1 @@ -255,10 +246,7 @@ void BRepAlgoAPI_Section::Approximation(const Standard_Boolean B) //======================================================================= void BRepAlgoAPI_Section::ComputePCurveOn1(const Standard_Boolean B) { - if(myComputePCurve1 != B) { - myComputePCurve1 = B; - myParametersChanged = Standard_True; - } + myComputePCurve1 = B; } //======================================================================= //function : ComputePCurveOn2 @@ -266,10 +254,7 @@ void BRepAlgoAPI_Section::ComputePCurveOn1(const Standard_Boolean B) //======================================================================= void BRepAlgoAPI_Section::ComputePCurveOn2(const Standard_Boolean B) { - if(myComputePCurve2 != B) { - myComputePCurve2 = B; - myParametersChanged = Standard_True; - } + myComputePCurve2 = B; } //======================================================================= //function : SetAttributes @@ -277,9 +262,9 @@ void BRepAlgoAPI_Section::ComputePCurveOn2(const Standard_Boolean B) //======================================================================= void BRepAlgoAPI_Section::SetAttributes() { - BOPAlgo_SectionAttribute theSecAttr(myApprox, - myComputePCurve1, - myComputePCurve2); + BOPAlgo_SectionAttribute theSecAttr(myApprox, + myComputePCurve1, + myComputePCurve2); myDSFiller->SetSectionAttribute(theSecAttr); } //======================================================================= diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Section.hxx b/src/BRepAlgoAPI/BRepAlgoAPI_Section.hxx index 2d24faf1b1..e465059642 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_Section.hxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_Section.hxx @@ -193,8 +193,6 @@ Standard_EXPORT virtual ~BRepAlgoAPI_Section(); Standard_EXPORT Standard_Boolean HasAncestorFaceOn2 (const TopoDS_Shape& E, TopoDS_Shape& F) const; - - protected: @@ -203,24 +201,12 @@ protected: Standard_EXPORT virtual void SetAttributes() Standard_OVERRIDE; - - private: - - - Standard_Boolean myParametersChanged; Standard_Boolean myApprox; Standard_Boolean myComputePCurve1; Standard_Boolean myComputePCurve2; - }; - - - - - - #endif // _BRepAlgoAPI_Section_HeaderFile diff --git a/src/BRepProj/BRepProj_Projection.cxx b/src/BRepProj/BRepProj_Projection.cxx index c401e6dbe3..b08f0858e3 100644 --- a/src/BRepProj/BRepProj_Projection.cxx +++ b/src/BRepProj/BRepProj_Projection.cxx @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -125,15 +125,17 @@ void BRepProj_Projection::BuildSection (const TopoDS_Shape& theShape, if ( aShape.IsNull() ) throw Standard_ConstructionError(__FILE__": target shape has no faces"); - // build section computing pcurves on the shape -// BRepAlgoAPI_Section aSectionTool (aShape, theTool, Standard_False); - BRepAlgo_Section aSectionTool (aShape, theTool, Standard_False); - aSectionTool.Approximation (Standard_True); - aSectionTool.ComputePCurveOn1 (Standard_True); + // build section computing p-curves on both shapes to get higher precision + BRepAlgoAPI_Section aSectionTool(aShape, theTool, Standard_False); + aSectionTool.Approximation(Standard_True); + aSectionTool.ComputePCurveOn1(Standard_True); + aSectionTool.ComputePCurveOn2(Standard_True); + // Use Oriented Bounding Boxes inside Booleans to speed up calculation of the section + aSectionTool.SetUseOBB(Standard_True); aSectionTool.Build(); // check for successful work of the section tool - if (! aSectionTool.IsDone()) + if (!aSectionTool.IsDone()) return; // get edges of the result diff --git a/src/BRepTest/BRepTest_ProjectionCommands.cxx b/src/BRepTest/BRepTest_ProjectionCommands.cxx index 9caf045a31..72a83082be 100644 --- a/src/BRepTest/BRepTest_ProjectionCommands.cxx +++ b/src/BRepTest/BRepTest_ProjectionCommands.cxx @@ -26,67 +26,57 @@ #include #include +//======================================================================= +//function : prj +//purpose : Draw command for Conical and Cylindrical projection +//======================================================================= static Standard_Integer prj(Draw_Interpretor& di, Standard_Integer n, const char** a) -{ - char newname[255]; - if (n < 7) return 1; - TopoDS_Shape InpLine = DBRep::Get(a[2]); - TopoDS_Shape InpShape = DBRep::Get(a[3]); - Standard_Real DX=Draw::Atof(a[4]),DY=Draw::Atof(a[5]),DZ=Draw::Atof(a[6]); - gp_Dir TD(DX,DY,DZ); - BRepProj_Projection Prj(InpLine,InpShape,TD); - Standard_Integer i = 1; - char* temp = newname; - - - if (Prj.IsDone()) { - while (Prj.More()) { - Sprintf(newname,"%s_%d",a[1],i); - DBRep::Set(temp,Prj.Current()); - //cout< gp::Resolution()) - Teta = (Pos.XDirection()).AngleWithRef(aVec, Pos.Direction()); + if (aVec.SquareMagnitude() < gp::Resolution()) + // coinciding points -> infinite number of parameters + return 0.0; + + const gp_Dir& dir = Pos.Direction(); + // Project vector on circle's plane + gp_XYZ aVProj = dir.XYZ().CrossCrossed(aVec.XYZ(), dir.XYZ()); + + if (aVProj.SquareModulus() < gp::Resolution()) + return 0.0; + + // Angle between X direction and projected vector + Standard_Real Teta = (Pos.XDirection()).AngleWithRef(aVProj, dir); + if (Teta < -1.e-16) Teta += PIPI; else if (Teta < 0) Teta = 0; return Teta; diff --git a/src/Extrema/Extrema_ExtCS.cxx b/src/Extrema/Extrema_ExtCS.cxx index 4b953656bd..797e001c5f 100644 --- a/src/Extrema/Extrema_ExtCS.cxx +++ b/src/Extrema/Extrema_ExtCS.cxx @@ -113,6 +113,9 @@ void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C, NbT = NbU = NbV = 10; GeomAbs_CurveType myCtype = C.GetType(); + myDone = Standard_False; + // Try analytic computation of extrema + Standard_Boolean isComputeAnalytic = Standard_True; switch(myCtype) { @@ -233,6 +236,11 @@ void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C, myExtElCS.Perform(C.Circle(), myS->Plane()); break; } + else if (myStype == GeomAbs_Sphere) + { + myExtElCS.Perform(C.Circle(), myS->Sphere()); + break; + } } Standard_FALLTHROUGH case GeomAbs_Hyperbola: @@ -246,157 +254,225 @@ void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C, Standard_FALLTHROUGH default: { - Extrema_GenExtCS Ext; - Ext.Initialize(*myS, NbU, NbV, mytolS); - if(myCtype == GeomAbs_Hyperbola) { - Standard_Real tmin = Max(-20., C.FirstParameter()); - Standard_Real tmax = Min(20., C.LastParameter()); - Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow + isComputeAnalytic = Standard_False; + break; + } + } + + if (isComputeAnalytic) + { + if (myExtElCS.IsDone()) + { + myDone = Standard_True; + myIsPar = myExtElCS.IsParallel(); + if (myIsPar) + { + mySqDist.Append(myExtElCS.SquareDistance(1)); } - else { - if((myCtype == GeomAbs_Circle && NbT < 13) || - (myCtype == GeomAbs_BSplineCurve && NbT < 13) ) + else + { + Standard_Integer NbExt = myExtElCS.NbExt(); + for (i = 1; i <= NbExt; i++) { - NbT = 13; - } - Ext.Perform(C, NbT, mytolC); - } - - myDone = Ext.IsDone(); - if (myDone) { - Standard_Integer NbExt = Ext.NbExt(); - Standard_Real T,U,V; - Extrema_POnCurv PC; - Extrema_POnSurf PS; - for (i = 1; i <= NbExt; i++) { - PC = Ext.PointOnCurve(i); - PS = Ext.PointOnSurface(i); - T = PC.Parameter(); + Extrema_POnCurv PC; + Extrema_POnSurf PS; + myExtElCS.Points(i, PC, PS); + Standard_Real Ucurve = PC.Parameter(); + Standard_Real U, V; PS.Parameter(U, V); - AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i)); + AddSolution(C, Ucurve, U, V, PC.Value(), PS.Value(), myExtElCS.SquareDistance(i)); } - //Add sharp points - Standard_Integer SolNumber = mySqDist.Length(); - Standard_Address CopyC = (Standard_Address)&C; - Adaptor3d_Curve& aC = *(Adaptor3d_Curve*)CopyC; - Standard_Integer NbIntervals = aC.NbIntervals(GeomAbs_C1); - TColStd_Array1OfReal SharpPoints(1, NbIntervals+1); - aC.Intervals(SharpPoints, GeomAbs_C1); - - Extrema_ExtPS aProjPS; - aProjPS.Initialize (*myS, - myS->FirstUParameter(), - myS->LastUParameter(), - myS->FirstVParameter(), - myS->LastVParameter(), - mytolS, - mytolS); - - for (i = 2; i < SharpPoints.Upper(); ++i) + if (mySqDist.Length() == 0 && NbExt > 0) { - T = SharpPoints(i); - gp_Pnt aPnt = C.Value(T); - aProjPS.Perform (aPnt); - if (!aProjPS.IsDone()) - continue; - Standard_Integer NbProj = aProjPS.NbExt(), jmin = 0; - Standard_Real MinSqDist = RealLast(); - for (j = 1; j <= NbProj; j++) + // Analytical extrema seem to be out of curve/surface boundaries. + // Try extremity points of curve. + gp_Pnt aPOnC[2], aPOnS[2]; + Standard_Real aT[2] = { myucinf, myucsup }, U[2], V[2]; + Standard_Real aDist[2] = { -1, -1 }; + for (i = 0; i < 2; ++i) { - Standard_Real aSqDist = aProjPS.SquareDistance(j); - if (aSqDist < MinSqDist) + if (Precision::IsInfinite(aT[i])) + continue; + + aPOnC[i] = C.Value(aT[i]); + switch (myStype) { - MinSqDist = aSqDist; - jmin = j; + case GeomAbs_Plane: + { + ElSLib::Parameters(myS->Plane(), aPOnC[i], U[i], V[i]); + aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Plane()); + break; + } + case GeomAbs_Sphere: + { + ElSLib::Parameters(myS->Sphere(), aPOnC[i], U[i], V[i]); + aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Sphere()); + break; + } + case GeomAbs_Cylinder: + { + ElSLib::Parameters(myS->Cylinder(), aPOnC[i], U[i], V[i]); + aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cylinder()); + break; + } + case GeomAbs_Torus: + { + ElSLib::Parameters(myS->Torus(), aPOnC[i], U[i], V[i]); + aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Torus()); + break; + } + case GeomAbs_Cone: + { + ElSLib::Parameters(myS->Cone(), aPOnC[i], U[i], V[i]); + aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cone()); + break; + } + default: + continue; } + + aDist[i] = aPOnC[i].SquareDistance(aPOnS[i]); } - if (jmin != 0) + + Standard_Boolean bAdd[2] = {Standard_False, Standard_False}; + + // Choose solution to add + if (aDist[0] >= 0. && aDist[1] >= 0.) { - aProjPS.Point(jmin).Parameter(U,V); - AddSolution(C, T, U, V, - aPnt, aProjPS.Point(jmin).Value(), MinSqDist); + Standard_Real aDiff = aDist[0] - aDist[1]; + // Both computed -> take only minimal + if (Abs(aDiff) < Precision::Confusion()) + // Add both + bAdd[0] = bAdd[1] = Standard_True; + else if (aDiff < 0) + // Add first + bAdd[0] = Standard_True; + else + // Add second + bAdd[1] = Standard_True; + } + else if (aDist[0] >= 0.) + // Add first + bAdd[0] = Standard_True; + else if (aDist[1] >= 0.) + // Add second + bAdd[1] = Standard_True; + + for (i = 0; i < 2; ++i) + { + if (bAdd[i]) + AddSolution(C, aT[i], U[i], V[i], aPOnC[i], aPOnS[i], aDist[i]); } - } - //Cut sharp solutions to keep only minimum and maximum - Standard_Integer imin = SolNumber + 1, imax = mySqDist.Length(); - for (i = SolNumber + 1; i <= mySqDist.Length(); i++) - { - if (mySqDist(i) < mySqDist(imin)) - imin = i; - if (mySqDist(i) > mySqDist(imax)) - imax = i; - } - if (mySqDist.Length() > SolNumber + 2) - { - Standard_Real MinSqDist = mySqDist(imin); - Standard_Real MaxSqDist = mySqDist(imax); - Extrema_POnCurv MinPC = myPOnC(imin); - Extrema_POnCurv MaxPC = myPOnC(imax); - Extrema_POnSurf MinPS = myPOnS(imin); - Extrema_POnSurf MaxPS = myPOnS(imax); - - mySqDist.Remove(SolNumber + 1, mySqDist.Length()); - myPOnC.Remove(SolNumber + 1, myPOnC.Length()); - myPOnS.Remove(SolNumber + 1, myPOnS.Length()); - - mySqDist.Append(MinSqDist); - myPOnC.Append(MinPC); - myPOnS.Append(MinPS); - mySqDist.Append(MaxSqDist); - myPOnC.Append(MaxPC); - myPOnS.Append(MaxPS); } } return; } - break; } - myDone = myExtElCS.IsDone(); + // Elementary extrema is not done, try generic solution + Extrema_GenExtCS Ext; + Ext.Initialize(*myS, NbU, NbV, mytolS); + if (myCtype == GeomAbs_Hyperbola) { + Standard_Real tmin = Max(-20., C.FirstParameter()); + Standard_Real tmax = Min(20., C.LastParameter()); + Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow + } + else { + if ((myCtype == GeomAbs_Circle && NbT < 13) || + (myCtype == GeomAbs_BSplineCurve && NbT < 13)) + { + NbT = 13; + } + Ext.Perform(C, NbT, mytolC); + } + + myDone = Ext.IsDone(); if (myDone) { - myIsPar = myExtElCS.IsParallel(); - if (myIsPar) { - mySqDist.Append(myExtElCS.SquareDistance(1)); + Standard_Integer NbExt = Ext.NbExt(); + Standard_Real T, U, V; + Extrema_POnCurv PC; + Extrema_POnSurf PS; + for (i = 1; i <= NbExt; i++) { + PC = Ext.PointOnCurve(i); + PS = Ext.PointOnSurface(i); + T = PC.Parameter(); + PS.Parameter(U, V); + AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i)); } - else { - Standard_Integer NbExt = myExtElCS.NbExt(); - Standard_Real U, V; - for (i = 1; i <= NbExt; i++) { - Extrema_POnCurv PC; - Extrema_POnSurf PS; - myExtElCS.Points(i, PC, PS); - Standard_Real Ucurve = PC.Parameter(); - PS.Parameter(U, V); - AddSolution(C, Ucurve, U, V, PC.Value(), PS.Value(), myExtElCS.SquareDistance(i)); - } - if(mySqDist.Length() == 0 && NbExt > 0) + + //Add sharp points + Standard_Integer SolNumber = mySqDist.Length(); + Standard_Address CopyC = (Standard_Address)&C; + Adaptor3d_Curve& aC = *(Adaptor3d_Curve*)CopyC; + Standard_Integer NbIntervals = aC.NbIntervals(GeomAbs_C1); + TColStd_Array1OfReal SharpPoints(1, NbIntervals + 1); + aC.Intervals(SharpPoints, GeomAbs_C1); + + Extrema_ExtPS aProjPS; + aProjPS.Initialize(*myS, + myS->FirstUParameter(), + myS->LastUParameter(), + myS->FirstVParameter(), + myS->LastVParameter(), + mytolS, + mytolS); + + for (i = 2; i < SharpPoints.Upper(); ++i) + { + T = SharpPoints(i); + gp_Pnt aPnt = C.Value(T); + aProjPS.Perform(aPnt); + if (!aProjPS.IsDone()) + continue; + Standard_Integer NbProj = aProjPS.NbExt(), jmin = 0; + Standard_Real MinSqDist = RealLast(); + for (j = 1; j <= NbProj; j++) { - //Analytical extremas seem to be out of curve/surface boundaries. - //For plane it is possible to add extremity points of curve - if(myStype == GeomAbs_Plane) + Standard_Real aSqDist = aProjPS.SquareDistance(j); + if (aSqDist < MinSqDist) { - gp_Pln aPln = myS->Plane(); - gp_Pnt PC, PP; - if(!Precision::IsInfinite(myucinf)) - { - PC = C.Value(myucinf); - ElSLib::PlaneParameters(aPln.Position(), PC, U, V); - PP = ElSLib::PlaneValue(U, V, aPln.Position()); - AddSolution(C, myucinf, U, V, PC, PP, PC.SquareDistance(PP)); - } - if(!Precision::IsInfinite(myucsup)) - { - PC = C.Value(myucsup); - ElSLib::PlaneParameters(aPln.Position(), PC, U, V); - PP = ElSLib::PlaneValue(U, V, aPln.Position()); - AddSolution(C, myucsup, U, V, PC, PP, PC.SquareDistance(PP)); - } + MinSqDist = aSqDist; + jmin = j; } } + if (jmin != 0) + { + aProjPS.Point(jmin).Parameter(U, V); + AddSolution(C, T, U, V, + aPnt, aProjPS.Point(jmin).Value(), MinSqDist); + } + } + //Cut sharp solutions to keep only minimum and maximum + Standard_Integer imin = SolNumber + 1, imax = mySqDist.Length(); + for (i = SolNumber + 1; i <= mySqDist.Length(); i++) + { + if (mySqDist(i) < mySqDist(imin)) + imin = i; + if (mySqDist(i) > mySqDist(imax)) + imax = i; + } + if (mySqDist.Length() > SolNumber + 2) + { + Standard_Real MinSqDist = mySqDist(imin); + Standard_Real MaxSqDist = mySqDist(imax); + Extrema_POnCurv MinPC = myPOnC(imin); + Extrema_POnCurv MaxPC = myPOnC(imax); + Extrema_POnSurf MinPS = myPOnS(imin); + Extrema_POnSurf MaxPS = myPOnS(imax); + + mySqDist.Remove(SolNumber + 1, mySqDist.Length()); + myPOnC.Remove(SolNumber + 1, myPOnC.Length()); + myPOnS.Remove(SolNumber + 1, myPOnS.Length()); + + mySqDist.Append(MinSqDist); + myPOnC.Append(MinPC); + myPOnS.Append(MinPS); + mySqDist.Append(MaxSqDist); + myPOnC.Append(MaxPC); + myPOnS.Append(MaxPS); } } - } diff --git a/src/Extrema/Extrema_ExtElCS.cxx b/src/Extrema/Extrema_ExtElCS.cxx index 67b573226e..31e5f80eac 100644 --- a/src/Extrema/Extrema_ExtElCS.cxx +++ b/src/Extrema/Extrema_ExtElCS.cxx @@ -33,11 +33,13 @@ #include #include #include +#include #include #include #include #include #include +#include Extrema_ExtElCS::Extrema_ExtElCS() { @@ -534,19 +536,137 @@ void Extrema_ExtElCS::Perform(const gp_Circ& , +//======================================================================= +//function : Extrema_ExtElCS +//purpose : Circle/Sphere +//======================================================================= Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, - const gp_Sphere& S) -{ Perform(C, S);} + const gp_Sphere& S) +{ + Perform(C, S); +} + +//======================================================================= +//function : Perform +//purpose : Circle/Sphere +//======================================================================= +void Extrema_ExtElCS::Perform(const gp_Circ& C, + const gp_Sphere& S) +{ + myDone = Standard_False; + + if (gp_Lin(C.Axis()).SquareDistance(S.Location()) < Precision::SquareConfusion()) + { + // Circle and sphere are parallel + myIsPar = Standard_True; + myDone = Standard_True; + // Compute distance from circle to the sphere + Standard_Real aSqDistLoc = C.Location().SquareDistance(S.Location()); + Standard_Real aSqDist = aSqDistLoc + C.Radius() * C.Radius(); + Standard_Real aDist = sqrt(aSqDist) - S.Radius(); + mySqDist = new TColStd_HArray1OfReal(1, 1); + mySqDist->SetValue(1, aDist * aDist); + return; + } + // Intersect sphere with circle's plane + gp_Pln CPln(C.Location(), C.Axis().Direction()); + IntAna_QuadQuadGeo anInter(CPln, S); + if (!anInter.IsDone()) + // not done + return; -//void Extrema_ExtElCS::Perform(const gp_Circ& C, -// const gp_Sphere& S) -void Extrema_ExtElCS::Perform(const gp_Circ& , - const gp_Sphere& ) -{ - throw Standard_NotImplemented(); + if (anInter.TypeInter() != IntAna_Circle) + { + // Intersection is empty or just a point. + // The parallel case has already been considered, + // thus, here we have to find only one minimal solution + myNbExt = 1; + myDone = Standard_True; + + mySqDist = new TColStd_HArray1OfReal(1, 1); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1); + + // Compute parameter on circle + const Standard_Real aT = ElCLib::Parameter(C, S.Location()); + // Compute point on circle + gp_Pnt aPOnC = ElCLib::Value(aT, C); + + // Compute parameters on sphere + Standard_Real aU, aV; + ElSLib::Parameters(S, aPOnC, aU, aV); + // Compute point on sphere + gp_Pnt aPOnS = ElSLib::Value(aU, aV, S); + + // Save solution + myPoint1->SetValue(1, Extrema_POnCurv(aT, aPOnC)); + myPoint2->SetValue(1, Extrema_POnSurf(aU, aV, aPOnS)); + mySqDist->SetValue(1, aPOnC.SquareDistance(aPOnS)); + return; + } + + // Here, the intersection is a circle + + // Intersection circle + gp_Circ aCInt = anInter.Circle(1); + + // Perform intersection of the input circle with the intersection circle + Extrema_ExtElC anExtC(C, aCInt); + Standard_Boolean isExtremaCircCircValid = anExtC.IsDone() // Check if intersection is done + && !anExtC.IsParallel() // Parallel case has already been considered + && anExtC.NbExt() > 0; // Check that some solutions have been found + if (!isExtremaCircCircValid) + // not done + return; + + myDone = Standard_True; + + // Few solutions + Standard_Real aNbExt = anExtC.NbExt(); + // Find the minimal distance + Standard_Real aMinSqDist = ::RealLast(); + for (Standard_Integer i = 1; i <= aNbExt; ++i) + { + Standard_Real aSqDist = anExtC.SquareDistance(i); + if (aSqDist < aMinSqDist) + aMinSqDist = aSqDist; + } + // Collect all solutions close to the minimal one + TColStd_ListOfInteger aSols; + for (Standard_Integer i = 1; i <= aNbExt; ++i) + { + Standard_Real aDiff = anExtC.SquareDistance(i) - aMinSqDist; + if (aDiff < Precision::SquareConfusion()) + aSols.Append(i); + } + + // Save all minimal solutions + myNbExt = aSols.Extent(); + + mySqDist = new TColStd_HArray1OfReal(1, myNbExt); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); + + TColStd_ListIteratorOfListOfInteger it(aSols); + for (Standard_Integer iSol = 1; it.More(); it.Next(), ++iSol) + { + Extrema_POnCurv P1, P2; + anExtC.Points(it.Value(), P1, P2); + + // Compute parameters on sphere + Standard_Real aU, aV; + ElSLib::Parameters(S, P1.Value(), aU, aV); + // Compute point on sphere + gp_Pnt aPOnS = ElSLib::Value(aU, aV, S); + + // Save solution + myPoint1->SetValue(iSol, P1); + myPoint2->SetValue(iSol, Extrema_POnSurf(aU, aV, aPOnS)); + mySqDist->SetValue(iSol, P1.Value().SquareDistance(aPOnS)); + } } Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, diff --git a/src/GeomAPI/GeomAPI_ExtremaCurveSurface.cxx b/src/GeomAPI/GeomAPI_ExtremaCurveSurface.cxx index ba3303ca21..742c8e3547 100644 --- a/src/GeomAPI/GeomAPI_ExtremaCurveSurface.cxx +++ b/src/GeomAPI/GeomAPI_ExtremaCurveSurface.cxx @@ -86,7 +86,7 @@ void GeomAPI_ExtremaCurveSurface::Init Extrema_ExtCS theExtCS(TheCurve,TheSurface,Tol,Tol); myExtCS = theExtCS; - myIsDone = myExtCS.IsDone() && ( myExtCS.NbExt() > 0); + myIsDone = myExtCS.IsDone() && (myExtCS.IsParallel() || myExtCS.NbExt() > 0); if ( myIsDone) { @@ -129,7 +129,7 @@ void GeomAPI_ExtremaCurveSurface::Init Wmin,Wmax,Umin,Umax,Vmin,Vmax,Tol,Tol); myExtCS = theExtCS; - myIsDone = myExtCS.IsDone() && ( myExtCS.NbExt() > 0); + myIsDone = myExtCS.IsDone() && (myExtCS.IsParallel() || myExtCS.NbExt() > 0); if ( myIsDone) { diff --git a/src/GeometryTest/GeometryTest_APICommands.cxx b/src/GeometryTest/GeometryTest_APICommands.cxx index c0227d0010..64cc7402f8 100644 --- a/src/GeometryTest/GeometryTest_APICommands.cxx +++ b/src/GeometryTest/GeometryTest_APICommands.cxx @@ -407,7 +407,8 @@ static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const } // Since GeomAPI cannot provide access to flag directly. isInfinitySolutions = Ex.Extrema().IsParallel(); - aMinDist = Ex.LowerDistance(); + if (isInfinitySolutions) + aMinDist = Ex.LowerDistance(); } else if (C1 && S2) { @@ -425,6 +426,9 @@ static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const aPrms[2].Append(aU2); aPrms[3].Append(aV2); } + isInfinitySolutions = Ex.Extrema().IsParallel(); + if (isInfinitySolutions) + aMinDist = Ex.LowerDistance(); } else if (S1 && C2) { @@ -442,6 +446,9 @@ static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const aPrms[1].Append(aV1); aPrms[2].Append(aU2); } + isInfinitySolutions = Ex.Extrema().IsParallel(); + if (isInfinitySolutions) + aMinDist = Ex.LowerDistance(); } else if (S1 && S2) { diff --git a/src/IntPolyh/FILES b/src/IntPolyh/FILES index be4aa88a66..d586b0593d 100755 --- a/src/IntPolyh/FILES +++ b/src/IntPolyh/FILES @@ -1,6 +1,7 @@ IntPolyh_Array.hxx IntPolyh_ArrayOfEdges.hxx IntPolyh_ArrayOfPoints.hxx +IntPolyh_ArrayOfPointNormal.hxx IntPolyh_ArrayOfSectionLines.hxx IntPolyh_ArrayOfTangentZones.hxx IntPolyh_ArrayOfTriangles.hxx @@ -11,7 +12,6 @@ IntPolyh_Edge.cxx IntPolyh_Edge.hxx IntPolyh_Intersection.cxx IntPolyh_Intersection.hxx -IntPolyh_Intersection_1.cxx IntPolyh_ListOfCouples.hxx IntPolyh_MaillageAffinage.cxx IntPolyh_MaillageAffinage.hxx @@ -23,5 +23,7 @@ IntPolyh_SectionLine.hxx IntPolyh_SeqOfStartPoints.hxx IntPolyh_StartPoint.cxx IntPolyh_StartPoint.hxx +IntPolyh_Tools.cxx +IntPolyh_Tools.hxx IntPolyh_Triangle.cxx IntPolyh_Triangle.hxx \ No newline at end of file diff --git a/src/IntTools/IntTools_BeanFaceIntersector.lxx b/src/IntPolyh/IntPolyh_ArrayOfPointNormal.hxx similarity index 54% rename from src/IntTools/IntTools_BeanFaceIntersector.lxx rename to src/IntPolyh/IntPolyh_ArrayOfPointNormal.hxx index ed9737fc20..130c4281a1 100644 --- a/src/IntTools/IntTools_BeanFaceIntersector.lxx +++ b/src/IntPolyh/IntPolyh_ArrayOfPointNormal.hxx @@ -1,4 +1,5 @@ -// Copyright (c) 1999-2014 OPEN CASCADE SAS +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -11,9 +12,21 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -inline Standard_Boolean IntTools_BeanFaceIntersector::IsDone() const +#ifndef IntPolyh_ArrayOfPointNormal_HeaderFile +#define IntPolyh_ArrayOfPointNormal_HeaderFile + +#include +#include +#include + +//! Auxiliary structure to represent pair of point and +//! normal vector in this point on the surface. +struct IntPolyh_PointNormal { - return myIsDone; -} + gp_Pnt Point; + gp_Vec Normal; +}; + +typedef IntPolyh_Array IntPolyh_ArrayOfPointNormal; - +#endif diff --git a/src/IntPolyh/IntPolyh_Intersection.cxx b/src/IntPolyh/IntPolyh_Intersection.cxx index 0d8802614e..9662e0ab15 100644 --- a/src/IntPolyh/IntPolyh_Intersection.cxx +++ b/src/IntPolyh/IntPolyh_Intersection.cxx @@ -14,292 +14,398 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -// modified by Edward AGAPOV (eap) Tue Jan 22 12:29:55 2002 (occ53) -// Modified by skv - Thu Sep 25 18:24:29 2003 OCC567 + +#include #include + #include -#include +#include #include #include #include +#include #include + #include -#include -Standard_Integer MYDISPLAY = 0; -Standard_Integer MYPRINT = 0; +static Standard_Boolean IsAdvRequired(IntPolyh_PMaillageAffinage& theMaillage); -IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, - const Handle(Adaptor3d_HSurface)& S2) +static Standard_Integer ComputeIntersection(IntPolyh_PMaillageAffinage& theMaillage); + +static Standard_Boolean AnalyzeIntersection(IntPolyh_PMaillageAffinage& theMaillage); + +//======================================================================= +//function : IntPolyh_Intersection +//purpose : +//======================================================================= +IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2) { - myNbSU1 = -1; - myNbSV1 = -1; - myNbSU2 = -1; - myNbSV2 = -1; - mySurf1 = S1; - mySurf2 = S2; - done = Standard_False; - TSectionLines.Init(1000); - TTangentZones.Init(10000); + mySurf1 = theS1; + mySurf2 = theS2; + myNbSU1 = 10; + myNbSV1 = 10; + myNbSU2 = 10; + myNbSV2 = 10; + myIsDone = Standard_False; + mySectionLines.Init(1000); + myTangentZones.Init(10000); Perform(); } -IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, - const Standard_Integer NbSU1, - const Standard_Integer NbSV1, - const Handle(Adaptor3d_HSurface)& S2, - const Standard_Integer NbSU2, - const Standard_Integer NbSV2) +//======================================================================= +//function : IntPolyh_Intersection +//purpose : +//======================================================================= +IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const Standard_Integer theNbSU1, + const Standard_Integer theNbSV1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Integer theNbSU2, + const Standard_Integer theNbSV2) { - myNbSU1 = NbSU1; - myNbSV1 = NbSV1; - myNbSU2 = NbSU2; - myNbSV2 = NbSV2; - mySurf1 = S1; - mySurf2 = S2; - done = Standard_False; - TSectionLines.Init(1000); - TTangentZones.Init(10000); + mySurf1 = theS1; + mySurf2 = theS2; + myNbSU1 = theNbSU1; + myNbSV1 = theNbSV1; + myNbSU2 = theNbSU2; + myNbSV2 = theNbSV2; + myIsDone = Standard_False; + mySectionLines.Init(1000); + myTangentZones.Init(10000); Perform(); } -void IntPolyh_Intersection::Perform() { - - done = Standard_True; - - Standard_Boolean isStdDone = Standard_False; - Standard_Boolean isAdvDone = Standard_False; - Standard_Integer nbCouplesStd = 0; - Standard_Integer nbCouplesAdv = 0; - - IntPolyh_PMaillageAffinage aPMaillageStd = 0; - IntPolyh_PMaillageAffinage aPMaillageFF = 0; - IntPolyh_PMaillageAffinage aPMaillageFR = 0; - IntPolyh_PMaillageAffinage aPMaillageRF = 0; - IntPolyh_PMaillageAffinage aPMaillageRR = 0; - - isStdDone = PerformStd(aPMaillageStd,nbCouplesStd); - - // default interference done well, use it - if(isStdDone && nbCouplesStd > 10) { - aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones); - } - // default interference done, but too few interferences foud; - // use advanced interference - else if(isStdDone && nbCouplesStd <= 10) { - isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv); - - // advanced interference found - if(isAdvDone && nbCouplesAdv > 0) { - aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones); - } - else { - // use result of default - if(nbCouplesStd > 0) - aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones); - } - } - // default interference faild, use advanced - else { - // isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv); - - // if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl; - // aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones); - // aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones); - // aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones); - // aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones); - // } - } - - // accept result - nbsectionlines = TSectionLines.NbItems(); - nbtangentzones = TTangentZones.NbItems(); - - // clean up - if(aPMaillageStd) delete aPMaillageStd; - if(aPMaillageFF) delete aPMaillageFF; - if(aPMaillageFR) delete aPMaillageFR; - if(aPMaillageRF) delete aPMaillageRF; - if(aPMaillageRR) delete aPMaillageRR; - - // verify - if(!isStdDone && !isAdvDone) - done = Standard_False; +//======================================================================= +//function : IntPolyh_Intersection +//purpose : +//======================================================================= +IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const Handle(Adaptor3d_HSurface)& theS2, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2) +{ + mySurf1 = theS1; + mySurf2 = theS2; + myNbSU1 = theUPars1.Length(); + myNbSV1 = theVPars1.Length(); + myNbSU2 = theUPars2.Length(); + myNbSV2 = theVPars2.Length(); + myIsDone = Standard_False; + mySectionLines.Init(1000); + myTangentZones.Init(10000); + Perform(theUPars1, theVPars1, theUPars2, theVPars2); } - -Standard_Boolean IntPolyh_Intersection::IsDone() const { - return(done); +//======================================================================= +//function : GetLinePoint +//purpose : +//======================================================================= +void IntPolyh_Intersection::GetLinePoint(const Standard_Integer Indexl, + const Standard_Integer Indexp, + Standard_Real &x, + Standard_Real &y, + Standard_Real &z, + Standard_Real &u1, + Standard_Real &v1, + Standard_Real &u2, + Standard_Real &v2, + Standard_Real &incidence) const +{ + const IntPolyh_SectionLine &msl = mySectionLines[Indexl - 1]; + const IntPolyh_StartPoint &sp = msl[Indexp - 1]; + x = sp.X(); + y = sp.Y(); + z = sp.Z(); + u1 = sp.U1(); + v1 = sp.V1(); + u2 = sp.U2(); + v2 = sp.V2(); + incidence = sp.GetAngle(); } - -Standard_Integer IntPolyh_Intersection::NbSectionLines() const { - return(nbsectionlines); +//======================================================================= +//function : GetTangentZonePoint +//purpose : +//======================================================================= +void IntPolyh_Intersection::GetTangentZonePoint(const Standard_Integer Indexz, + const Standard_Integer /*Indexp*/, + Standard_Real &x, + Standard_Real &y, + Standard_Real &z, + Standard_Real &u1, + Standard_Real &v1, + Standard_Real &u2, + Standard_Real &v2) const +{ + const IntPolyh_StartPoint &sp = myTangentZones[Indexz - 1]; + x = sp.X(); + y = sp.Y(); + z = sp.Z(); + u1 = sp.U1(); + v1 = sp.V1(); + u2 = sp.U2(); + v2 = sp.V2(); } +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void IntPolyh_Intersection::Perform() +{ + // Prepare the sampling of the surfaces - UV parameters of the triangulation nodes + TColStd_Array1OfReal UPars1, VPars1, UPars2, VPars2; + IntPolyh_Tools::MakeSampling(mySurf1, myNbSU1, myNbSV1, Standard_False, UPars1, VPars1); + IntPolyh_Tools::MakeSampling(mySurf2, myNbSU2, myNbSV2, Standard_False, UPars2, VPars2); -Standard_Integer IntPolyh_Intersection::NbPointsInLine(const Standard_Integer IndexLine) const { - - return(TSectionLines[IndexLine-1].NbStartPoints()); + // Perform intersection + Perform(UPars1, VPars1, UPars2, VPars2); } +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void IntPolyh_Intersection::Perform(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2) +{ + myIsDone = Standard_True; + + // Compute the deflection of the given sampling if it is not set + Standard_Real aDeflTol1 = IntPolyh_Tools::ComputeDeflection(mySurf1, theUPars1, theVPars1); + Standard_Real aDeflTol2 = IntPolyh_Tools::ComputeDeflection(mySurf2, theUPars2, theVPars2); + + // Perform standard intersection + IntPolyh_PMaillageAffinage pMaillageStd = 0; + Standard_Integer nbCouplesStd = 0; + Standard_Boolean isStdDone = PerformStd(theUPars1, theVPars1, + theUPars2, theVPars2, + aDeflTol1, aDeflTol2, + pMaillageStd, nbCouplesStd); + + if (!isStdDone) + { + // Intersection not done + myIsDone = Standard_False; + if (pMaillageStd) delete pMaillageStd; + return; + } -Standard_Integer IntPolyh_Intersection::NbPointsInTangentZone(const Standard_Integer) const { - //-- IndexLine--; (pas implemente) Attention : Tableaux de 0 a n-1 - // eap - // return(TTangentZones.NbTangentZones()); - return 1; -} + if (!IsAdvRequired(pMaillageStd)) + { + // Default interference done well, use it + pMaillageStd->StartPointsChain(mySectionLines, myTangentZones); + } + else + { + // Default intersection is done, but too few interferences found. + // Perform advanced intersection - perform intersection four times with different shifts. + IntPolyh_PMaillageAffinage pMaillageFF = 0; + IntPolyh_PMaillageAffinage pMaillageFR = 0; + IntPolyh_PMaillageAffinage pMaillageRF = 0; + IntPolyh_PMaillageAffinage pMaillageRR = 0; + Standard_Integer nbCouplesAdv = 0; + + Standard_Boolean isAdvDone = PerformAdv(theUPars1, theVPars1, + theUPars2, theVPars2, + aDeflTol1, aDeflTol2, + pMaillageFF, + pMaillageFR, + pMaillageRF, + pMaillageRR, + nbCouplesAdv); + + if (isAdvDone && nbCouplesAdv > 0) + { + // Advanced interference found + pMaillageFF->StartPointsChain(mySectionLines, myTangentZones); + pMaillageFR->StartPointsChain(mySectionLines, myTangentZones); + pMaillageRF->StartPointsChain(mySectionLines, myTangentZones); + pMaillageRR->StartPointsChain(mySectionLines, myTangentZones); + } + else + { + // Advanced intersection not done or no intersection is found -> use standard intersection + if (nbCouplesStd > 0) + pMaillageStd->StartPointsChain(mySectionLines, myTangentZones); + } + // Clean up + if (pMaillageFF) delete pMaillageFF; + if (pMaillageFR) delete pMaillageFR; + if (pMaillageRF) delete pMaillageRF; + if (pMaillageRR) delete pMaillageRR; + } -Standard_Integer IntPolyh_Intersection::NbTangentZones() const { - return(nbtangentzones); + // clean up + if (pMaillageStd) delete pMaillageStd; } - -void IntPolyh_Intersection::GetLinePoint(const Standard_Integer Indexl, - const Standard_Integer Indexp, - Standard_Real &x, - Standard_Real &y, - Standard_Real &z, - Standard_Real &u1, - Standard_Real &v1, - Standard_Real &u2, - Standard_Real &v2, - Standard_Real &incidence) const { - const IntPolyh_SectionLine &msl=TSectionLines[Indexl-1]; - const IntPolyh_StartPoint &sp=msl[Indexp-1]; - x=sp.X(); - y=sp.Y(); - z=sp.Z(); - u1=sp.U1(); - v1=sp.V1(); - u2=sp.U2(); - v2=sp.V2(); - incidence=sp.GetAngle(); +//======================================================================= +//function : PerformStd +//purpose : +//======================================================================= +Standard_Boolean IntPolyh_Intersection::PerformStd(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillageS, + Standard_Integer& theNbCouples) +{ + Standard_Boolean isDone = PerformMaillage(theUPars1, theVPars1, + theUPars2, theVPars2, + theDeflTol1, theDeflTol2, + theMaillageS); + theNbCouples = (isDone) ? (theMaillageS->GetCouples().Extent()) : 0; + return isDone; } +//======================================================================= +//function : PerformAdv +//purpose : +//======================================================================= +Standard_Boolean IntPolyh_Intersection::PerformAdv(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillageFF, + IntPolyh_PMaillageAffinage& theMaillageFR, + IntPolyh_PMaillageAffinage& theMaillageRF, + IntPolyh_PMaillageAffinage& theMaillageRR, + Standard_Integer& theNbCouples) +{ + // Compute the points on the surface and normal directions in these points + IntPolyh_ArrayOfPointNormal aPoints1, aPoints2; + IntPolyh_Tools::FillArrayOfPointNormal(mySurf1, theUPars1, theVPars1, aPoints1); + IntPolyh_Tools::FillArrayOfPointNormal(mySurf2, theUPars2, theVPars2, aPoints2); + + // Perform intersection with the different shifts of the triangles + Standard_Boolean isDone = + PerformMaillage(theUPars1, theVPars1, theUPars2, theVPars2, // sampling + theDeflTol1, theDeflTol2, // deflection tolerance + aPoints1, aPoints2, // points and normals + Standard_True , Standard_False, // shift + theMaillageFR) + && + PerformMaillage(theUPars1, theVPars1, theUPars2, theVPars2, // sampling + theDeflTol1, theDeflTol2, // deflection tolerance + aPoints1, aPoints2, // points and normals + Standard_False, Standard_True, // shift + theMaillageRF) + && + PerformMaillage(theUPars1, theVPars1, theUPars2, theVPars2, // sampling + theDeflTol1, theDeflTol2, // deflection tolerance + aPoints1, aPoints2, // points and normals + Standard_True, Standard_True, // shift + theMaillageFF) + && + PerformMaillage(theUPars1, theVPars1, theUPars2, theVPars2, // sampling + theDeflTol1, theDeflTol2, // deflection tolerance + aPoints1, aPoints2, // points and normals + Standard_False, Standard_False, // shift + theMaillageRR); + + if (isDone) + { + theNbCouples = theMaillageFF->GetCouples().Extent() + + theMaillageFR->GetCouples().Extent() + + theMaillageRF->GetCouples().Extent() + + theMaillageRR->GetCouples().Extent(); + + // Merge couples + if(theNbCouples > 0) + MergeCouples(theMaillageFF->GetCouples(), + theMaillageFR->GetCouples(), + theMaillageRF->GetCouples(), + theMaillageRR->GetCouples()); + } -void IntPolyh_Intersection::GetTangentZonePoint(const Standard_Integer Indexz, - const Standard_Integer /*Indexp*/, - Standard_Real &x, - Standard_Real &y, - Standard_Real &z, - Standard_Real &u1, - Standard_Real &v1, - Standard_Real &u2, - Standard_Real &v2) const { - //-- Indexz--; tableaux C - // eap - //const IntPolyh_StartPoint &sp=TTangentZones[Indexp-1]; - const IntPolyh_StartPoint &sp=TTangentZones[Indexz-1]; - x=sp.X(); - y=sp.Y(); - z=sp.Z(); - u1=sp.U1(); - v1=sp.V1(); - u2=sp.U2(); - v2=sp.V2(); + return isDone; } -// Modified by skv - Thu Sep 25 18:07:41 2003 OCC567 Begin //======================================================================= //function : PerformMaillage -//purpose : Computes MaillageAffinage +//purpose : Computes standard MaillageAffinage (without shift) //======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformMaillage - (const Standard_Boolean isFirstFwd, - const Standard_Boolean isSecondFwd, - IntPolyh_PMaillageAffinage &theMaillageS) +Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillage) { - if (myNbSU1 == -1) - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, mySurf2, MYPRINT); - else - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, myNbSU1, myNbSV1, - mySurf2, myNbSU2, myNbSV2, - MYPRINT); - - theMaillageS->FillArrayOfPnt(1, isFirstFwd); - theMaillageS->FillArrayOfPnt(2, isSecondFwd); - - - Standard_Real xx0,yy0,zz0,xx1,yy1,zz1; - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - - theMaillageS->TrianglesDeflectionsRefinementBSB(); - - Standard_Integer FinTTC = theMaillageS->TriangleCompare(); - - // if too many intersections, consider surfaces parallel (eap) - if(FinTTC > 200 && - (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbItems() || - FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbItems()) ) { - return Standard_False; + theMaillage = + new IntPolyh_MaillageAffinage(mySurf1, theUPars1.Length(), theVPars1.Length(), + mySurf2, theUPars2.Length(), theVPars2.Length(), + 0); + + theMaillage->FillArrayOfPnt(1, theUPars1, theVPars1, &theDeflTol1); + theMaillage->FillArrayOfPnt(2, theUPars2, theVPars2, &theDeflTol2); + + Standard_Integer FinTTC = ComputeIntersection(theMaillage); + + // If no intersecting triangles are found, try enlarged surfaces + if (FinTTC == 0) + { + // Check if enlarge for the surfaces is possible + Standard_Boolean isEnlargeU1, isEnlargeV1, isEnlargeU2, isEnlargeV2; + IntPolyh_Tools::IsEnlargePossible(mySurf1, isEnlargeU1, isEnlargeV1); + IntPolyh_Tools::IsEnlargePossible(mySurf2, isEnlargeU2, isEnlargeV2); + + if (isEnlargeU1 || isEnlargeV1 || isEnlargeU2 || isEnlargeV2) + { + theMaillage->SetEnlargeZone(Standard_True); + // Make new points on the enlarged surface + theMaillage->FillArrayOfPnt(1); + theMaillage->FillArrayOfPnt(2); + // Compute intersection + ComputeIntersection(theMaillage); + theMaillage->SetEnlargeZone(Standard_False); + } } - return Standard_True; + // if too many intersections, consider surfaces parallel + return AnalyzeIntersection(theMaillage); } //======================================================================= //function : PerformMaillage //purpose : Computes MaillageAffinage //======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformMaillage(IntPolyh_PMaillageAffinage &theMaillageS) +Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + const IntPolyh_ArrayOfPointNormal& thePoints1, + const IntPolyh_ArrayOfPointNormal& thePoints2, + const Standard_Boolean theIsFirstFwd, + const Standard_Boolean theIsSecondFwd, + IntPolyh_PMaillageAffinage& theMaillage) { - if (myNbSU1 == -1) - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, mySurf2, MYPRINT); - else - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, myNbSU1, myNbSV1, - mySurf2, myNbSU2, myNbSV2, - MYPRINT); - - theMaillageS->FillArrayOfPnt(1); - theMaillageS->FillArrayOfPnt(2); - - - Standard_Real xx0,yy0,zz0,xx1,yy1,zz1; - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - - theMaillageS->TrianglesDeflectionsRefinementBSB(); - - Standard_Integer FinTTC = theMaillageS->TriangleCompare(); - - if( FinTTC == 0 ) { - Standard_Boolean myZone = Standard_True; - theMaillageS->SetEnlargeZone( myZone ); - theMaillageS->FillArrayOfPnt(1); - theMaillageS->FillArrayOfPnt(2); - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - theMaillageS->TrianglesDeflectionsRefinementBSB(); - FinTTC = theMaillageS->TriangleCompare(); - myZone = Standard_False; - theMaillageS->SetEnlargeZone( myZone ); - } + theMaillage = + new IntPolyh_MaillageAffinage(mySurf1, theUPars1.Length(), theVPars1.Length(), + mySurf2, theUPars2.Length(), theVPars2.Length(), + 0); - return Standard_True; + theMaillage->FillArrayOfPnt(1, theIsFirstFwd , thePoints1, theUPars1, theVPars1, theDeflTol1); + theMaillage->FillArrayOfPnt(2, theIsSecondFwd, thePoints2, theUPars2, theVPars2, theDeflTol2); + + ComputeIntersection(theMaillage); + + return AnalyzeIntersection(theMaillage); } //======================================================================= @@ -308,7 +414,6 @@ Standard_Boolean IntPolyh_Intersection::PerformMaillage(IntPolyh_PMaillageAffina // If some are detected it leaves the couple in only one list // deleting from others. //======================================================================= - void IntPolyh_Intersection::MergeCouples(IntPolyh_ListOfCouples &anArrayFF, IntPolyh_ListOfCouples &anArrayFR, IntPolyh_ListOfCouples &anArrayRF, @@ -331,45 +436,100 @@ void IntPolyh_Intersection::MergeCouples(IntPolyh_ListOfCouples &anArrayFF, } //======================================================================= -//function : PerformStd -//purpose : +//function : IsAdvRequired +//purpose : Analyzes the standard intersection on the angles between triangles. +// If the angle between some of the interfering triangles is +// too small (less than 5 deg), the advanced intersection is required. +// Otherwise, the standard intersection is considered satisfactory. //======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformStd(IntPolyh_PMaillageAffinage& MaillageS, - Standard_Integer& NbCouples) +Standard_Boolean IsAdvRequired(IntPolyh_PMaillageAffinage& theMaillage) { - Standard_Boolean isdone = PerformMaillage(MaillageS); - NbCouples = (isdone) ? (MaillageS->GetCouples().Extent()) : 0; - return isdone; + if (!theMaillage) + return Standard_True; + + // Interfering triangles + IntPolyh_ListOfCouples& Couples = theMaillage->GetCouples(); + // Number of interfering pairs + Standard_Integer aNbCouples = Couples.Extent(); + // Flag to define whether advanced intersection is required or not + Standard_Boolean isAdvReq = (aNbCouples == 0); + if (isAdvReq) + // No interfering triangles are found -> perform advanced intersection + return isAdvReq; + + if (aNbCouples > 10) + // Enough interfering triangles are found -> no need to perform advanced intersection + return isAdvReq; + + const Standard_Real anEps = .996; //~ cos of 5 deg + IntPolyh_ListIteratorOfListOfCouples aIt(Couples); + for(; aIt.More(); aIt.Next()) + { + if (Abs(aIt.Value().Angle()) > anEps) + { + // The angle between interfering triangles is small -> perform advanced + // intersection to make intersection more precise + isAdvReq = Standard_True; + break; + } + } + + return isAdvReq; } //======================================================================= -//function : PerformAdv -//purpose : +//function : ComputeIntersection +//purpose : Computes the intersection of the triangles +//======================================================================= +Standard_Integer ComputeIntersection(IntPolyh_PMaillageAffinage& theMaillage) +{ + if (!theMaillage) + return 0; + + // Compute common box and mark the points inside that box + theMaillage->CommonBox(); + + // Make triangles + theMaillage->FillArrayOfTriangles(1); + theMaillage->FillArrayOfTriangles(2); + + // Make edges + theMaillage->FillArrayOfEdges(1); + theMaillage->FillArrayOfEdges(2); + + // Deflection refinement + theMaillage->TrianglesDeflectionsRefinementBSB(); + + return theMaillage->TriangleCompare(); +} + +//======================================================================= +//function : AnalyzeIntersection +//purpose : Analyzes the intersection on the number of interfering triangles //======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformAdv(IntPolyh_PMaillageAffinage& MaillageFF, - IntPolyh_PMaillageAffinage& MaillageFR, - IntPolyh_PMaillageAffinage& MaillageRF, - IntPolyh_PMaillageAffinage& MaillageRR, - Standard_Integer& NbCouples) +Standard_Boolean AnalyzeIntersection(IntPolyh_PMaillageAffinage& theMaillage) { - Standard_Boolean isdone = Standard_True; - NbCouples = 0; - - if(!PerformMaillage(Standard_True,Standard_False,MaillageFR) || - !PerformMaillage(Standard_False,Standard_True,MaillageRF) || - !PerformMaillage(Standard_True,Standard_True,MaillageFF) || - !PerformMaillage(Standard_False,Standard_False,MaillageRR) ) - isdone = Standard_False; - - if(isdone) { - NbCouples = MaillageFF->GetCouples().Extent() + - MaillageFR->GetCouples().Extent() + - MaillageRF->GetCouples().Extent() + - MaillageRR->GetCouples().Extent(); - - if(NbCouples > 0) - MergeCouples(MaillageFF->GetCouples(),MaillageFR->GetCouples(), - MaillageRF->GetCouples(),MaillageRR->GetCouples()); + if (!theMaillage) + return Standard_False; + + IntPolyh_ListOfCouples& Couples = theMaillage->GetCouples(); + Standard_Integer FinTTC = Couples.Extent(); + if(FinTTC > 200) + { + const Standard_Real eps = .996; //~ cos of 5deg. + Standard_Integer npara = 0; + IntPolyh_ListIteratorOfListOfCouples aIt(Couples); + for(; aIt.More(); aIt.Next()) + { + Standard_Real cosa = Abs(aIt.Value().Angle()); + if(cosa > eps) ++npara; + } + + if (npara >= theMaillage->GetArrayOfTriangles(1).NbItems() || + npara >= theMaillage->GetArrayOfTriangles(2).NbItems()) + { + return Standard_False; + } } - return isdone; + return Standard_True; } diff --git a/src/IntPolyh/IntPolyh_Intersection.hxx b/src/IntPolyh/IntPolyh_Intersection.hxx index 5103fb190d..6c1197e9fa 100644 --- a/src/IntPolyh/IntPolyh_Intersection.hxx +++ b/src/IntPolyh/IntPolyh_Intersection.hxx @@ -21,128 +21,191 @@ #include #include -#include -#include +#include #include #include +#include +#include #include +#include #include -#include -#include class Adaptor3d_HSurface; - -//! the main algorithm. Algorithm outputs are -//! lines and points like describe in the last -//! paragraph. The Algorithm provides direct access to -//! the elements of those lines and points. Other -//! classes of this package are for internal use and -//! only concern the algorithmic part. -class IntPolyh_Intersection +//! API algorithm for intersection of two surfaces by intersection +//! of their triangulations. +//! +//! Algorithm provides possibility to intersect surfaces as without +//! the precomputed sampling as with it. +//! +//! If the numbers of sampling points are not given, it will build the +//! net of 10x10 sampling points for each surface. +//! +//! The intersection is done inside constructors. +//! Before obtaining the results of intersection it is necessary to check +//! if intersection has been performed correctly. It can be done by calling +//! the *IsDone()* method. +//! +//! The results of intersection are the intersection lines and points. +class IntPolyh_Intersection { public: DEFINE_STANDARD_ALLOC - - //! Constructor - Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_HSurface)& S2); - - //! NbSU1 ... NbSV2 are used to compute the initial - //! samples of the iso parametric meshes on the - //! surfaces. - Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, const Standard_Integer NbSU1, const Standard_Integer NbSV1, const Handle(Adaptor3d_HSurface)& S2, const Standard_Integer NbSU2, const Standard_Integer NbSV2); - - //! D1, D2 are used to compute the initial - //! samples of the iso parametric meshes on the - //! surfaces. - Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, const TColStd_Array1OfReal& anUpars1, const TColStd_Array1OfReal& aVpars1, const Handle(Adaptor3d_HSurface)& S2, const TColStd_Array1OfReal& anUpars2, const TColStd_Array1OfReal& aVpars2); - - //! Compute the intersection. +public: //! @name Constructors + + //! Constructor for intersection of two surfaces with default parameters. + //! Performs intersection. + Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2); + + //! Constructor for intersection of two surfaces with the given + //! size of the sampling nets: + //! - x - for the first surface ; + //! - x - for the second surface . + //! Performs intersection. + Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const Standard_Integer theNbSU1, + const Standard_Integer theNbSV1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Integer theNbSU2, + const Standard_Integer theNbSV2); + + //! Constructor for intersection of two surfaces with the precomputed sampling. + //! Performs intersection. + Standard_EXPORT IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& theS1, + const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const Handle(Adaptor3d_HSurface)& theS2, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2); + + +public: //! @name Getting the results + + //! Returns state of the operation + Standard_Boolean IsDone() const + { + return myIsDone; + } + + //! Returns the number of section lines + Standard_Integer NbSectionLines() const + { + return mySectionLines.NbItems(); + } + + //! Returns the number of points in the given line + Standard_Integer NbPointsInLine(const Standard_Integer IndexLine) const + { + return mySectionLines[IndexLine-1].NbStartPoints(); + } + + // Returns number of tangent zones + Standard_Integer NbTangentZones() const + { + return myTangentZones.NbItems(); + } + + //! Returns number of points in tangent zone + Standard_Integer NbPointsInTangentZone(const Standard_Integer) const + { + return 1; + } + + //! Gets the parameters of the point in section line + Standard_EXPORT void GetLinePoint(const Standard_Integer IndexLine, + const Standard_Integer IndexPoint, + Standard_Real& x, Standard_Real& y, Standard_Real& z, + Standard_Real& u1, Standard_Real& v1, + Standard_Real& u2, Standard_Real& v2, + Standard_Real& incidence) const; + + //! Gets the parameters of the point in tangent zone + Standard_EXPORT void GetTangentZonePoint(const Standard_Integer IndexLine, + const Standard_Integer IndexPoint, + Standard_Real& x, Standard_Real& y, Standard_Real& z, + Standard_Real& u1, Standard_Real& v1, + Standard_Real& u2, Standard_Real& v2) const; + + +private: //! @name Performing the intersection + + //! Compute the intersection by first making the sampling of the surfaces. Standard_EXPORT void Perform(); - - //! Compute the intersection. - Standard_EXPORT void Perform (const TColStd_Array1OfReal& Upars1, const TColStd_Array1OfReal& Vpars1, const TColStd_Array1OfReal& Upars2, const TColStd_Array1OfReal& Vpars2); - - Standard_EXPORT Standard_Boolean IsDone() const; - - Standard_EXPORT Standard_Integer NbSectionLines() const; - - Standard_EXPORT Standard_Integer NbPointsInLine (const Standard_Integer IndexLine) const; - - Standard_EXPORT void GetLinePoint (const Standard_Integer IndexLine, const Standard_Integer IndexPoint, Standard_Real& x, Standard_Real& y, Standard_Real& z, Standard_Real& u1, Standard_Real& v1, Standard_Real& u2, Standard_Real& v2, Standard_Real& incidence) const; - - Standard_EXPORT Standard_Integer NbTangentZones() const; - - Standard_EXPORT Standard_Integer NbPointsInTangentZone (const Standard_Integer IndexLine) const; - - Standard_EXPORT void GetTangentZonePoint (const Standard_Integer IndexLine, const Standard_Integer IndexPoint, Standard_Real& x, Standard_Real& y, Standard_Real& z, Standard_Real& u1, Standard_Real& v1, Standard_Real& u2, Standard_Real& v2) const; - - - - -protected: - - - - - -private: - - - //! Computes MaillageAffinage - Standard_EXPORT Standard_Boolean PerformMaillage (const Standard_Boolean isFirstFwd, const Standard_Boolean isSecondFwd, IntPolyh_PMaillageAffinage& MaillageS); - - //! The method PerformMaillage(..) is used to compute MaillageAffinage. It is - //! called four times (two times for each surface) for creation of inscribed - //! and circumscribed mesh for each surface. - Standard_EXPORT Standard_Boolean PerformMaillage (IntPolyh_PMaillageAffinage& MaillageS); - - //! Computes MaillageAffinage - Standard_EXPORT Standard_Boolean PerformMaillage (const Standard_Boolean isFirstFwd, const Standard_Boolean isSecondFwd, const TColStd_Array1OfReal& Upars1, const TColStd_Array1OfReal& Vpars1, const TColStd_Array1OfReal& Upars2, const TColStd_Array1OfReal& Vpars2, IntPolyh_PMaillageAffinage& MaillageS); - - //! The method PerformMaillage(..) is used to compute MaillageAffinage. It is - //! called four times (two times for each surface) for creation of inscribed - //! and circumscribed mesh for each surface. - Standard_EXPORT Standard_Boolean PerformMaillage (const TColStd_Array1OfReal& Upars1, const TColStd_Array1OfReal& Vpars1, const TColStd_Array1OfReal& Upars2, const TColStd_Array1OfReal& Vpars2, IntPolyh_PMaillageAffinage& MaillageS); - - //! This method analyzes arrays to find same couples. If some - //! are detected it leaves the couple in only one array - //! deleting from others. - Standard_EXPORT void MergeCouples (IntPolyh_ListOfCouples& anArrayFF, IntPolyh_ListOfCouples& anArrayFR, IntPolyh_ListOfCouples& anArrayRF, IntPolyh_ListOfCouples& anArrayRR) const; - - //! Process default interference - Standard_EXPORT Standard_Boolean PerformStd (IntPolyh_PMaillageAffinage& MaillageS, Standard_Integer& NbCouples); - - //! Process advanced interference - Standard_EXPORT Standard_Boolean PerformAdv (IntPolyh_PMaillageAffinage& MaillageFF, IntPolyh_PMaillageAffinage& MaillageFR, IntPolyh_PMaillageAffinage& MaillageRF, IntPolyh_PMaillageAffinage& MaillageRR, Standard_Integer& NbCouples); - - //! Process default interference - Standard_EXPORT Standard_Boolean PerformStd (const TColStd_Array1OfReal& Upars1, const TColStd_Array1OfReal& Vpars1, const TColStd_Array1OfReal& Upars2, const TColStd_Array1OfReal& Vpars2, IntPolyh_PMaillageAffinage& MaillageS, Standard_Integer& NbCouples); - - //! Process advanced interference - Standard_EXPORT Standard_Boolean PerformAdv (const TColStd_Array1OfReal& Upars1, const TColStd_Array1OfReal& Vpars1, const TColStd_Array1OfReal& Upars2, const TColStd_Array1OfReal& Vpars2, IntPolyh_PMaillageAffinage& MaillageFF, IntPolyh_PMaillageAffinage& MaillageFR, IntPolyh_PMaillageAffinage& MaillageRF, IntPolyh_PMaillageAffinage& MaillageRR, Standard_Integer& NbCouples); - - - Standard_Boolean done; - Standard_Integer nbsectionlines; - Standard_Integer nbtangentzones; - IntPolyh_ArrayOfSectionLines TSectionLines; - IntPolyh_ArrayOfTangentZones TTangentZones; - Standard_Integer myNbSU1; - Standard_Integer myNbSV1; - Standard_Integer myNbSU2; - Standard_Integer myNbSV2; - Handle(Adaptor3d_HSurface) mySurf1; - Handle(Adaptor3d_HSurface) mySurf2; - + //! Compute the intersection on the precomputed sampling. + Standard_EXPORT void Perform(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2); + + //! Performs the default (standard) intersection of the triangles + Standard_EXPORT Standard_Boolean PerformStd(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillageS, + Standard_Integer& theNbCouples); + + //! Performs the advanced intersection of the triangles - four intersection with + //! different shifts of the sampling points. + Standard_EXPORT Standard_Boolean PerformAdv(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillageFF, + IntPolyh_PMaillageAffinage& theMaillageFR, + IntPolyh_PMaillageAffinage& theMaillageRF, + IntPolyh_PMaillageAffinage& theMaillageRR, + Standard_Integer& theNbCouples); + + //! Performs the advanced intersection of the triangles. + Standard_EXPORT Standard_Boolean PerformMaillage(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + IntPolyh_PMaillageAffinage& theMaillage); + + //! Performs the advanced intersection of the triangles. + Standard_EXPORT Standard_Boolean PerformMaillage(const TColStd_Array1OfReal& theUPars1, + const TColStd_Array1OfReal& theVPars1, + const TColStd_Array1OfReal& theUPars2, + const TColStd_Array1OfReal& theVPars2, + const Standard_Real theDeflTol1, + const Standard_Real theDeflTol2, + const IntPolyh_ArrayOfPointNormal& thePoints1, + const IntPolyh_ArrayOfPointNormal& thePoints2, + const Standard_Boolean theIsFirstFwd, + const Standard_Boolean theIsSecondFwd, + IntPolyh_PMaillageAffinage& theMaillage); + + //! Clears the arrays from the duplicate couples, keeping only one instance of it. + Standard_EXPORT void MergeCouples(IntPolyh_ListOfCouples& theArrayFF, + IntPolyh_ListOfCouples& theArrayFR, + IntPolyh_ListOfCouples& theArrayRF, + IntPolyh_ListOfCouples& theArrayRR) const; + + +private: //! @name Fields + + // Inputs + Handle(Adaptor3d_HSurface) mySurf1; //!< First surface + Handle(Adaptor3d_HSurface) mySurf2; //!< Second surface + Standard_Integer myNbSU1; //!< Number of samples in U direction for first surface + Standard_Integer myNbSV1; //!< Number of samples in V direction for first surface + Standard_Integer myNbSU2; //!< Number of samples in U direction for second surface + Standard_Integer myNbSV2; //!< Number of samples in V direction for second surface + // Results + Standard_Boolean myIsDone; //!< State of the operation + IntPolyh_ArrayOfSectionLines mySectionLines; //!< Section lines + IntPolyh_ArrayOfTangentZones myTangentZones; //!< Tangent zones }; - - - - - - #endif // _IntPolyh_Intersection_HeaderFile diff --git a/src/IntPolyh/IntPolyh_Intersection_1.cxx b/src/IntPolyh/IntPolyh_Intersection_1.cxx deleted file mode 100644 index 512754a372..0000000000 --- a/src/IntPolyh/IntPolyh_Intersection_1.cxx +++ /dev/null @@ -1,317 +0,0 @@ -// Created on: 2005-09-26 -// Created by: Igor FEOKTISTOV -// Copyright (c) 2005-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 -#include -#include -#include -#include -#include -#include - -Standard_Integer MYPRINT1 = 0; - - -//======================================================================= -//function : IntPolyh_Intersection -//purpose : -//======================================================================= -IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1, - const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const Handle(Adaptor3d_HSurface)& S2, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2) -{ - myNbSU1 = Upars1.Length(); - myNbSV1 = Vpars1.Length(); - myNbSU2 = Upars2.Length(); - myNbSV2 = Vpars2.Length(); - mySurf1 = S1; - mySurf2 = S2; - done = Standard_False; - TSectionLines.Init(1000); - TTangentZones.Init(10000); - Perform(Upars1, Vpars1, Upars2, Vpars2); -} - -//======================================================================= -//function : Perform -//purpose : -//======================================================================= - -void IntPolyh_Intersection::Perform(const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2) { - - done = Standard_True; - - Standard_Boolean isStdDone = Standard_False; - Standard_Boolean isAdvDone = Standard_False; - Standard_Integer nbCouplesStd = 0; - Standard_Integer nbCouplesAdv = 0; - - - IntPolyh_PMaillageAffinage aPMaillageStd = 0; - IntPolyh_PMaillageAffinage aPMaillageFF = 0; - IntPolyh_PMaillageAffinage aPMaillageFR = 0; - IntPolyh_PMaillageAffinage aPMaillageRF = 0; - IntPolyh_PMaillageAffinage aPMaillageRR = 0; - - isStdDone = PerformStd( Upars1, Vpars1, Upars2, Vpars2, - aPMaillageStd,nbCouplesStd); - - // default interference done well, use it - if(isStdDone && nbCouplesStd > 10) { - aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones); - } - // default interference done, but too few interferences foud; - // use advanced interference - else if(isStdDone && nbCouplesStd <= 10) { - isAdvDone = PerformAdv( Upars1, Vpars1, Upars2, Vpars2, - aPMaillageFF,aPMaillageFR,aPMaillageRF, - aPMaillageRR,nbCouplesAdv); - - // advanced interference found - if(isAdvDone && nbCouplesAdv > 0) { - aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones); - aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones); - } - else { - // use result of default - if(nbCouplesStd > 0) - aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones); - } - } - // default interference faild, use advanced - else { -// isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv); - -// if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl; -// aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones); -// aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones); -// aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones); -// aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones); -// } - } - - // accept result - nbsectionlines = TSectionLines.NbItems(); - nbtangentzones = TTangentZones.NbItems(); - - // clean up - if(aPMaillageStd) delete aPMaillageStd; - if(aPMaillageFF) delete aPMaillageFF; - if(aPMaillageFR) delete aPMaillageFR; - if(aPMaillageRF) delete aPMaillageRF; - if(aPMaillageRR) delete aPMaillageRR; - - // verify - if(!isStdDone && !isAdvDone) - done = Standard_False; -} - -//======================================================================= -//function : PerformMaillage -//purpose : Computes MaillageAffinage -//======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformMaillage(const Standard_Boolean isFirstFwd, - const Standard_Boolean isSecondFwd, - const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2, - IntPolyh_PMaillageAffinage &theMaillageS) -{ - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(), - mySurf2, Upars2.Length(), Vpars2.Length(), - MYPRINT1); - - - theMaillageS->FillArrayOfPnt(1, isFirstFwd, Upars1, Vpars1); - theMaillageS->FillArrayOfPnt(2, isSecondFwd, Upars2, Vpars2); - - - - Standard_Real xx0,yy0,zz0,xx1,yy1,zz1; - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - - theMaillageS->TrianglesDeflectionsRefinementBSB(); - - Standard_Integer FinTTC = theMaillageS->TriangleCompare(); - - // if too many intersections, consider surfaces parallel (eap) - // test for parallel surf - if(FinTTC > 200) { - const Standard_Real eps = .996; //~ cos of 5deg. - IntPolyh_ListOfCouples& Couples = theMaillageS->GetCouples(); - - Standard_Integer npara = 0; - IntPolyh_ListIteratorOfListOfCouples aIt(Couples); - for(; aIt.More(); aIt.Next()) { - Standard_Real cosa = Abs(aIt.Value().Angle()); - if(cosa > eps) ++npara; - } - if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() || - npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) { - return Standard_False; - } - } - - return Standard_True; -} - -//======================================================================= -//function : PerformMaillage -//purpose : Computes MaillageAffinage -//======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2, - IntPolyh_PMaillageAffinage &theMaillageS) -{ - - theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(), - mySurf2, Upars2.Length(), Vpars2.Length(), - MYPRINT1); - - theMaillageS->FillArrayOfPnt(1, Upars1, Vpars1); - theMaillageS->FillArrayOfPnt(2, Upars2, Vpars2); - - - Standard_Real xx0,yy0,zz0,xx1,yy1,zz1; - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - - theMaillageS->TrianglesDeflectionsRefinementBSB(); - - Standard_Integer FinTTC = theMaillageS->TriangleCompare(); - - if( FinTTC == 0 ) { - Standard_Boolean myZone = Standard_True; - theMaillageS->SetEnlargeZone( myZone ); - theMaillageS->FillArrayOfPnt(1); - theMaillageS->FillArrayOfPnt(2); - theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2), - xx0, yy0, zz0, xx1, yy1, zz1); - theMaillageS->FillArrayOfTriangles(1); - theMaillageS->FillArrayOfTriangles(2); - theMaillageS->FillArrayOfEdges(1); - theMaillageS->FillArrayOfEdges(2); - theMaillageS->TrianglesDeflectionsRefinementBSB(); - FinTTC = theMaillageS->TriangleCompare(); - myZone = Standard_False; - theMaillageS->SetEnlargeZone( myZone ); - } - - // if too many intersections, consider surfaces parallel (eap) -//IFV test for parallel surf - if(FinTTC > 200) { - const Standard_Real eps = .996; //~ cos of 5deg. - IntPolyh_ListOfCouples& Couples = theMaillageS->GetCouples(); - - Standard_Integer npara = 0; - IntPolyh_ListIteratorOfListOfCouples aIt(Couples); - for(; aIt.More(); aIt.Next()) { - Standard_Real cosa = Abs(aIt.Value().Angle()); - if(cosa > eps) ++npara; - } - if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() || - npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) { - return Standard_False; - } - } - - return Standard_True; -} - -//======================================================================= -//function : PerformAdv -//purpose : -//======================================================================= -Standard_Boolean IntPolyh_Intersection::PerformAdv(const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2, - IntPolyh_PMaillageAffinage& MaillageFF, - IntPolyh_PMaillageAffinage& MaillageFR, - IntPolyh_PMaillageAffinage& MaillageRF, - IntPolyh_PMaillageAffinage& MaillageRR, - Standard_Integer& NbCouples) -{ - Standard_Boolean isdone = Standard_True; - NbCouples = 0; - - if(!PerformMaillage(Standard_True,Standard_False, - Upars1, Vpars1, Upars2, Vpars2, - MaillageFR) || - !PerformMaillage(Standard_False,Standard_True, - Upars1, Vpars1, Upars2, Vpars2, - MaillageRF) || - !PerformMaillage(Standard_True,Standard_True, - Upars1, Vpars1, Upars2, Vpars2, - MaillageFF) || - !PerformMaillage(Standard_False,Standard_False, - Upars1, Vpars1, Upars2, Vpars2, - MaillageRR) ) - isdone = Standard_False; - - if(isdone) { - NbCouples = MaillageFF->GetCouples().Extent() + - MaillageFR->GetCouples().Extent() + - MaillageRF->GetCouples().Extent() + - MaillageRR->GetCouples().Extent(); - - if(NbCouples > 0) - MergeCouples(MaillageFF->GetCouples(),MaillageFR->GetCouples(), - MaillageRF->GetCouples(),MaillageRR->GetCouples()); - } - return isdone; -} -//======================================================================= -//function : PerformStd -//purpose : -//======================================================================= - -Standard_Boolean IntPolyh_Intersection::PerformStd(const TColStd_Array1OfReal& Upars1, - const TColStd_Array1OfReal& Vpars1, - const TColStd_Array1OfReal& Upars2, - const TColStd_Array1OfReal& Vpars2, - IntPolyh_PMaillageAffinage& MaillageS, - Standard_Integer& NbCouples) -{ - Standard_Boolean isdone = PerformMaillage(Upars1, Vpars1, Upars2, Vpars2, - MaillageS); - NbCouples = (isdone) ? (MaillageS->GetCouples().Extent()) : 0; - return isdone; -} diff --git a/src/IntPolyh/IntPolyh_MaillageAffinage.cxx b/src/IntPolyh/IntPolyh_MaillageAffinage.cxx index 9d18c37f12..a0f7958673 100644 --- a/src/IntPolyh/IntPolyh_MaillageAffinage.cxx +++ b/src/IntPolyh/IntPolyh_MaillageAffinage.cxx @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -131,12 +131,6 @@ static const Standard_Integer aIsoDirection, Standard_Integer& aI1, Standard_Integer& aI2); -static - void EnlargeZone(const Handle(Adaptor3d_HSurface)& MaSurface, - Standard_Real &u0, - Standard_Real &u1, - Standard_Real &v0, - Standard_Real &v1); //======================================================================= //class : IntPolyh_BoxBndTreeSelector @@ -184,6 +178,7 @@ static NCollection_UBTreeFiller aTreeFiller(aBBTree); // 1. Fill the tree with the boxes of the triangles from second surface Standard_Integer i, aNbT2 = theTriangles2.NbItems(); + Standard_Boolean bAdded = Standard_False; for (i = 0; i < aNbT2; ++i) { IntPolyh_Triangle& aT = theTriangles2[i]; if (!aT.IsIntersectionPossible() || aT.IsDegenerated()) { @@ -192,8 +187,13 @@ static // const Bnd_Box& aBox = aT.BoundingBox(thePoints2); aTreeFiller.Add(i, aBox); + bAdded = Standard_True; } // + if (!bAdded) + // Intersection is not possible for all triangles in theTriangles2 + return; + // 2. Shake the tree filler aTreeFiller.Fill(); // @@ -245,8 +245,6 @@ IntPolyh_MaillageAffinage::IntPolyh_MaillageAffinage FlecheMax2(0.0), FlecheMin1(0.0), FlecheMin2(0.0), - FlecheMoy1(0.0), - FlecheMoy2(0.0), myEnlargeZone(Standard_False) { } @@ -273,11 +271,23 @@ IntPolyh_MaillageAffinage::IntPolyh_MaillageAffinage FlecheMax2(0.0), FlecheMin1(0.0), FlecheMin2(0.0), - FlecheMoy1(0.0), - FlecheMoy2(0.0), myEnlargeZone(Standard_False) { } +//======================================================================= +//function : MakeSampling +//purpose : +//======================================================================= +void IntPolyh_MaillageAffinage::MakeSampling(const Standard_Integer SurfID, + TColStd_Array1OfReal& theUPars, + TColStd_Array1OfReal& theVPars) +{ + if (SurfID == 1) + IntPolyh_Tools::MakeSampling(MaSurface1, NbSamplesU1, NbSamplesV1, myEnlargeZone, theUPars, theVPars); + else + IntPolyh_Tools::MakeSampling(MaSurface2, NbSamplesU2, NbSamplesV2, myEnlargeZone, theUPars, theVPars); +} + //======================================================================= //function : FillArrayOfPnt //purpose : Compute points on one surface and fill an array of points @@ -285,47 +295,10 @@ IntPolyh_MaillageAffinage::IntPolyh_MaillageAffinage void IntPolyh_MaillageAffinage::FillArrayOfPnt (const Standard_Integer SurfID) { - Standard_Integer NbSamplesU, NbSamplesV, i, aNbSamplesU1, aNbSamplesV1; - Standard_Real u0, u1, v0, v1, aU, aV, dU, dV; - // - const Handle(Adaptor3d_HSurface)& MaSurface=(SurfID==1)? MaSurface1 : MaSurface2; - NbSamplesU=(SurfID==1)? NbSamplesU1:NbSamplesU2; - NbSamplesV=(SurfID==1)? NbSamplesV1:NbSamplesV2; - // - u0 = (MaSurface)->FirstUParameter(); - u1 = (MaSurface)->LastUParameter(); - v0 = (MaSurface)->FirstVParameter(); - v1 = (MaSurface)->LastVParameter(); - - if(myEnlargeZone) { - EnlargeZone(MaSurface, u0, u1, v0, v1); - } - // - TColStd_Array1OfReal aUpars(1, NbSamplesU); - TColStd_Array1OfReal aVpars(1, NbSamplesV); - // - aNbSamplesU1=NbSamplesU-1; - aNbSamplesV1=NbSamplesV-1; - // - dU=(u1-u0)/Standard_Real(aNbSamplesU1); - dV=(v1-v0)/Standard_Real(aNbSamplesV1); - // - for (i=0; iFirstUParameter(); - u1 = (MaSurface)->LastUParameter(); - v0 = (MaSurface)->FirstVParameter(); - v1 = (MaSurface)->LastVParameter(); - - if(myEnlargeZone) { - EnlargeZone(MaSurface, u0, u1, v0, v1); - } - // - TColStd_Array1OfReal aUpars(1, NbSamplesU); - TColStd_Array1OfReal aVpars(1, NbSamplesV); - // - aNbSamplesU1=NbSamplesU-1; - aNbSamplesV1=NbSamplesV-1; - // - dU=(u1-u0)/Standard_Real(aNbSamplesU1); - dV=(v1-v0)/Standard_Real(aNbSamplesV1); - // - for (i=0; iD1(aU, aV, aP, aDU, aDV); - - aNorm = aDU.Crossed(aDV); - aMag = aNorm.Magnitude(); - if (aMag > resol) { - aNorm /= aMag; - aNorm.Multiply(Tol*1.5); - // - if (isShiftFwd) { - aP.Translate(aNorm); - } - else{ - aP.Translate(aNorm.Reversed()); - } - } - - IntPolyh_Point& aIP=TPoints[iCnt]; + + Standard_Integer aJD1(0), aJD2(0), aID1(0), aID2(0); + DegeneratedIndex(theVPars, aNbV, aS, 1, aJD1, aJD2); + if (!(aJD1 || aJD2)) + DegeneratedIndex(theUPars, aNbU, aS, 2, aID1, aID2); + + Standard_Boolean bDegI, bDeg; + Standard_Integer iCnt(0), i, j; + Standard_Real aX, aY, aZ, aU, aV; + + TPoints.Init(thePointsNorm.NbItems()); + + for (i = 1; i <= aNbU; ++i) + { + aU = theUPars(i); + bDegI = (aID1 == i || aID2 == i); + for (j = 1; j <= aNbV; ++j) + { + aV = theVPars(j); + + const IntPolyh_PointNormal& aPN = thePointsNorm.Value(iCnt); + gp_Vec aNorm = aPN.Normal.Multiplied(1.5*theDeflTol); + if (!isShiftFwd) + aNorm.Reverse(); + gp_Pnt aP = aPN.Point.Translated(aNorm); + + IntPolyh_Point& aIP = TPoints[iCnt]; aP.Coord(aX, aY, aZ); aIP.Set(aX, aY, aZ, aU, aV); - // - bDeg=bDegI || (aJD1==j || aJD2==j); - if (bDeg) { + bDeg = bDegI || (aJD1 == j || aJD2 == j); + if (bDeg) aIP.SetDegenerated(bDeg); - } + ++iCnt; aBox.Add(aP); } } - // + TPoints.SetNbItems(iCnt); - // - Tol*=1.2; - // + + // Update box + Standard_Real Tol = theDeflTol*1.2; Standard_Real a1,a2,a3,b1,b2,b3; - // aBox.Get(a1,a2,a3,b1,b2,b3); aBox.Update(a1-Tol,a2-Tol,a3-Tol,b1+Tol,b2+Tol,b3+Tol); aBox.Enlarge(MyTolerance); } + +//======================================================================= +//function : FillArrayOfPnt +//purpose : Compute points on one surface and fill an array of points +//======================================================================= +void IntPolyh_MaillageAffinage::FillArrayOfPnt + (const Standard_Integer SurfID, + const Standard_Boolean isShiftFwd, + const TColStd_Array1OfReal& Upars, + const TColStd_Array1OfReal& Vpars, + const Standard_Real *theDeflTol) +{ + Handle(Adaptor3d_HSurface) aS = (SurfID == 1) ? MaSurface1 : MaSurface2; + // Compute the tolerance + Standard_Real aTol = theDeflTol != NULL ? * theDeflTol : + IntPolyh_Tools::ComputeDeflection(aS, Upars, Vpars); + // Fill array of point normal + IntPolyh_ArrayOfPointNormal aPoints; + IntPolyh_Tools::FillArrayOfPointNormal(aS, Upars, Vpars, aPoints); + + // Fill array of points + FillArrayOfPnt(1, isShiftFwd, aPoints, Upars, Vpars, aTol); +} + +//======================================================================= +//function : CommonBox +//purpose : +//======================================================================= +void IntPolyh_MaillageAffinage::CommonBox() +{ + Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax; + CommonBox(GetBox(1), GetBox(2), XMin, YMin, ZMin, XMax, YMax, ZMax); +} + //======================================================================= //function : CommonBox //purpose : Compute the common box witch is the intersection @@ -939,12 +888,10 @@ void IntPolyh_MaillageAffinage::ComputeDeflections IntPolyh_ArrayOfPoints &TPoints=(SurfID==1)? TPoints1:TPoints2; IntPolyh_ArrayOfTriangles &TTriangles=(SurfID==1)? TTriangles1:TTriangles2; Standard_Real &FlecheMin=(SurfID==1)? FlecheMin1:FlecheMin2; - Standard_Real &FlecheMoy=(SurfID==1)? FlecheMoy1:FlecheMoy2; Standard_Real &FlecheMax=(SurfID==1)? FlecheMax1:FlecheMax2; FlecheMax=-RealLast(); FlecheMin=RealLast(); - FlecheMoy=0.0; const Standard_Integer FinTT = TTriangles.NbItems(); for(Standard_Integer i = 0; i < FinTT; i++) { @@ -2878,7 +2825,7 @@ IntPolyh_ListOfCouples &IntPolyh_MaillageAffinage::GetCouples() //function : SetEnlargeZone //purpose : //======================================================================= -void IntPolyh_MaillageAffinage::SetEnlargeZone(Standard_Boolean& EnlargeZone) +void IntPolyh_MaillageAffinage::SetEnlargeZone(const Standard_Boolean EnlargeZone) { myEnlargeZone = EnlargeZone; } @@ -3030,29 +2977,3 @@ Standard_Boolean IsDegenerated(const Handle(Adaptor3d_HSurface)& aS, // return bRet; } -//======================================================================= -//function : EnlargeZone -//purpose : -//======================================================================= -void EnlargeZone(const Handle(Adaptor3d_HSurface)& MaSurface, - Standard_Real &u0, - Standard_Real &u1, - Standard_Real &v0, - Standard_Real &v1) -{ - if(MaSurface->GetType() == GeomAbs_BSplineSurface || - MaSurface->GetType() == GeomAbs_BezierSurface) { - if((!MaSurface->IsUClosed() && !MaSurface->IsUPeriodic()) && - (Abs(u0) < 1.e+100 && Abs(u1) < 1.e+100) ) { - Standard_Real delta_u = 0.01*Abs(u1 - u0); - u0 -= delta_u; - u1 += delta_u; - } - if((!MaSurface->IsVClosed() && !MaSurface->IsVPeriodic()) && - (Abs(v0) < 1.e+100 && Abs(v1) < 1.e+100) ) { - Standard_Real delta_v = 0.01*Abs(v1 - v0); - v0 -= delta_v; - v1 += delta_v; - } - } -} diff --git a/src/IntPolyh/IntPolyh_MaillageAffinage.hxx b/src/IntPolyh/IntPolyh_MaillageAffinage.hxx index 693b581a5f..dd090b5600 100644 --- a/src/IntPolyh/IntPolyh_MaillageAffinage.hxx +++ b/src/IntPolyh/IntPolyh_MaillageAffinage.hxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include class Adaptor3d_HSurface; @@ -40,8 +41,9 @@ class IntPolyh_Triangle; class IntPolyh_SectionLine; -//! Provide the algorythms used in the package -class IntPolyh_MaillageAffinage +//! Low-level algorithm to compute intersection of the surfaces +//! by computing the intersection of their triangulations. +class IntPolyh_MaillageAffinage { public: @@ -52,7 +54,14 @@ public: Standard_EXPORT IntPolyh_MaillageAffinage(const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_HSurface)& S2, const Standard_Integer PRINT); - //! Compute points on one surface and fill an array of points; + + //! Makes the sampling of the surface - + //! Fills the arrays with the parametric values of the sampling points (triangulation nodes). + Standard_EXPORT void MakeSampling (const Standard_Integer SurfID, + TColStd_Array1OfReal& theUPars, + TColStd_Array1OfReal& theVPars); + + //! Computes points on one surface and fills an array of points; //! standard (default) method Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID); @@ -63,11 +72,16 @@ public: //! direction) is defined by isShiftFwd flag. //! Compute points on one surface and fill an array of points; //! advanced method - Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, const Standard_Boolean isShiftFwd); + Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, + const Standard_Boolean isShiftFwd); //! Compute points on one surface and fill an array of points; + //! If given, is the deflection tolerance of the given sampling. //! standard (default) method - Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, const TColStd_Array1OfReal& Upars, const TColStd_Array1OfReal& Vpars); + Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, + const TColStd_Array1OfReal& Upars, + const TColStd_Array1OfReal& Vpars, + const Standard_Real *theDeflTol = NULL); //! isShiftFwd flag is added. The purpose is to define shift //! of points along normal to the surface in this point. The @@ -75,9 +89,26 @@ public: //! The direction (forward or reversed regarding to normal //! direction) is defined by isShiftFwd flag. //! Compute points on one surface and fill an array of points; + //! If given, is the deflection tolerance of the given sampling. //! advanced method - Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, const Standard_Boolean isShiftFwd, const TColStd_Array1OfReal& Upars, const TColStd_Array1OfReal& Vpars); - + Standard_EXPORT void FillArrayOfPnt (const Standard_Integer SurfID, + const Standard_Boolean isShiftFwd, + const TColStd_Array1OfReal& Upars, + const TColStd_Array1OfReal& Vpars, + const Standard_Real *theDeflTol = NULL); + + //! Fills the array of points for the surface taking into account the shift + Standard_EXPORT void FillArrayOfPnt(const Standard_Integer SurfID, + const Standard_Boolean isShiftFwd, + const IntPolyh_ArrayOfPointNormal& thePoints, + const TColStd_Array1OfReal& theUPars, + const TColStd_Array1OfReal& theVPars, + const Standard_Real theDeflTol); + + //! Looks for the common box of the surfaces and marks the points + //! of the surfaces inside that common box for possible intersection + Standard_EXPORT void CommonBox(); + //! Compute the common box witch is the intersection //! of the two bounding boxes, and mark the points of //! the two surfaces that are inside. @@ -156,7 +187,7 @@ public: //! This method returns list of couples of contact triangles. Standard_EXPORT IntPolyh_ListOfCouples& GetCouples(); - Standard_EXPORT void SetEnlargeZone (Standard_Boolean& EnlargeZone); + Standard_EXPORT void SetEnlargeZone (const Standard_Boolean EnlargeZone); Standard_EXPORT Standard_Boolean GetEnlargeZone() const; @@ -173,7 +204,6 @@ protected: private: - Handle(Adaptor3d_HSurface) MaSurface1; Handle(Adaptor3d_HSurface) MaSurface2; Bnd_Box MyBox1; @@ -186,8 +216,6 @@ private: Standard_Real FlecheMax2; Standard_Real FlecheMin1; Standard_Real FlecheMin2; - Standard_Real FlecheMoy1; - Standard_Real FlecheMoy2; // For the arrays of Points, Edges and Triangles we need instant access to the items. // Moreover, we might add new items during refinement process in case the deflection // is too big, thus the vectors should be used. diff --git a/src/IntPolyh/IntPolyh_Tools.cxx b/src/IntPolyh/IntPolyh_Tools.cxx new file mode 100644 index 0000000000..00d342fc1d --- /dev/null +++ b/src/IntPolyh/IntPolyh_Tools.cxx @@ -0,0 +1,198 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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 + +//======================================================================= +//function : IsEnlargePossible +//purpose : +//======================================================================= +void IntPolyh_Tools::IsEnlargePossible(const Handle(Adaptor3d_HSurface)& theSurf, + Standard_Boolean& theUEnlarge, + Standard_Boolean& theVEnlarge) +{ + theUEnlarge = Standard_False; + theVEnlarge = Standard_False; + + // In the context of IntPolyh_Intersection only BSpline and Bezier surfaces + // should be enlarged + if (theSurf->GetType() == GeomAbs_BSplineSurface || + theSurf->GetType() == GeomAbs_BezierSurface) + { + // Check U periodicity and closeness + if (!theSurf->IsUClosed() && !theSurf->IsUPeriodic()) + { + // Check that surface is not infinite in U direction + if (!Precision::IsInfinite(theSurf->FirstUParameter()) && + !Precision::IsInfinite(theSurf->LastUParameter())) + { + theUEnlarge = Standard_True; + } + } + + // Check V periodicity and closeness + if (!theSurf->IsVClosed() && !theSurf->IsVPeriodic()) + { + // Check that surface is not infinite in V direction + if (!Precision::IsInfinite(theSurf->FirstVParameter()) && + !Precision::IsInfinite(theSurf->LastVParameter())) + { + theVEnlarge = Standard_True; + } + } + } +} + +//======================================================================= +//function : EnlargeZone +//purpose : Enlarges the sampling zone of the surface +//======================================================================= +static void EnlargeZone(const Handle(Adaptor3d_HSurface)& theSurf, + Standard_Real &u0, + Standard_Real &u1, + Standard_Real &v0, + Standard_Real &v1) +{ + Standard_Boolean isToEnlargeU, isToEnlargeV; + IntPolyh_Tools::IsEnlargePossible(theSurf, isToEnlargeU, isToEnlargeV); + // Enlarge U + if (isToEnlargeU) + { + Standard_Real delta_u = 0.01*Abs(u1 - u0); + u0 -= delta_u; + u1 += delta_u; + } + + if (isToEnlargeV) + { + Standard_Real delta_v = 0.01*Abs(v1 - v0); + v0 -= delta_v; + v1 += delta_v; + } +} + +//======================================================================= +//function : MakeSampling +//purpose : +//======================================================================= +void IntPolyh_Tools::MakeSampling(const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Integer theNbSU, + const Standard_Integer theNbSV, + const Standard_Boolean theEnlargeZone, + TColStd_Array1OfReal& theUPars, + TColStd_Array1OfReal& theVPars) +{ + // Resize arrays + theUPars.Resize(1, theNbSU, Standard_False); + theVPars.Resize(1, theNbSV, Standard_False); + // + Standard_Real u0, u1, v0, v1; + u0 = theSurf->FirstUParameter(); + u1 = theSurf->LastUParameter(); + v0 = theSurf->FirstVParameter(); + v1 = theSurf->LastVParameter(); + + // Enlarge surface intersection zone if necessary + if (theEnlargeZone) + EnlargeZone(theSurf, u0, u1, v0, v1); + + Standard_Integer aNbSamplesU1 = theNbSU - 1; + Standard_Integer aNbSamplesV1 = theNbSV - 1; + + // U step + Standard_Real dU = (u1 - u0) / Standard_Real(aNbSamplesU1); + // V step + Standard_Real dV = (v1 - v0) / Standard_Real(aNbSamplesV1); + + // Fill arrays + for (Standard_Integer i = 0; i < theNbSU; ++i) { + Standard_Real aU = u0 + i*dU; + if (i == aNbSamplesU1) { + aU = u1; + } + theUPars.SetValue(i + 1, aU); + } + // + for (Standard_Integer i = 0; i < theNbSV; ++i) { + Standard_Real aV = v0 + i*dV; + if (i == aNbSamplesV1) { + aV = v1; + } + theVPars.SetValue(i + 1, aV); + } +} + +//======================================================================= +//function : ComputeDeflection +//purpose : +//======================================================================= +Standard_Real IntPolyh_Tools::ComputeDeflection(const Handle(Adaptor3d_HSurface)& theSurf, + const TColStd_Array1OfReal& theUPars, + const TColStd_Array1OfReal& theVPars) +{ + IntCurveSurface_ThePolyhedronOfHInter polyhedron(theSurf, theUPars, theVPars); + Standard_Real aDeflTol = polyhedron.DeflectionOverEstimation(); + return aDeflTol; +} + +//======================================================================= +//function : FillArrayOfPointNormal +//purpose : +//======================================================================= +void IntPolyh_Tools::FillArrayOfPointNormal(const Handle(Adaptor3d_HSurface)& theSurf, + const TColStd_Array1OfReal& theUPars, + const TColStd_Array1OfReal& theVPars, + IntPolyh_ArrayOfPointNormal& thePoints) +{ + Standard_Integer aNbU = theUPars.Length(); + Standard_Integer aNbV = theVPars.Length(); + Standard_Integer iCnt = 0; + thePoints.Init(aNbU * aNbV); + for (Standard_Integer i = 1; i <= aNbU; ++i) + { + Standard_Real aU = theUPars(i); + + for (Standard_Integer j = 1; j <= aNbV; ++j) + { + Standard_Real aV = theVPars(j); + // Compute the point + gp_Pnt aP; + gp_Vec aDU, aDV; + theSurf->D1(aU, aV, aP, aDU, aDV); + // Compute normal + gp_Vec aVNorm = aDU.Crossed(aDV); + Standard_Real aLength = aVNorm.Magnitude(); + if (aLength > gp::Resolution()) + { + aVNorm /= aLength; + } + else + { + aVNorm.SetCoord(0.0, 0.0, 0.0); + } + + // Save the pair + IntPolyh_PointNormal& aPN = thePoints[iCnt]; + aPN.Point = aP; + aPN.Normal = aVNorm; + + ++iCnt; + } + } + thePoints.SetNbItems(iCnt); +} diff --git a/src/IntPolyh/IntPolyh_Tools.hxx b/src/IntPolyh/IntPolyh_Tools.hxx new file mode 100644 index 0000000000..36d646465f --- /dev/null +++ b/src/IntPolyh/IntPolyh_Tools.hxx @@ -0,0 +1,60 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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. + +#ifndef _IntPolyh_Tools_HeaderFile +#define _IntPolyh_Tools_HeaderFile + +#include +#include + +class Adaptor3d_HSurface; +//! The class provides tools for surface sampling. +class IntPolyh_Tools +{ +public: + + //! Checks if the surface can be enlarged in U or V direction. + Standard_EXPORT static void IsEnlargePossible(const Handle(Adaptor3d_HSurface)& theSurf, + Standard_Boolean& theUEnlarge, + Standard_Boolean& theVEnlarge); + + //! Makes the sampling of the given surface + //! making the net of x sampling points. + //! The flag controls the enlargement of the + //! sampling zone on the surface. + //! The parameters of the sampling points are stored into + //! and arrays. + Standard_EXPORT static void MakeSampling(const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Integer theNbSU, + const Standard_Integer theNbSV, + const Standard_Boolean theEnlargeZone, + TColStd_Array1OfReal& theUPars, + TColStd_Array1OfReal& theVPars); + + //! Computes the deflection tolerance on the surface for the given sampling. + Standard_EXPORT static Standard_Real ComputeDeflection(const Handle(Adaptor3d_HSurface)& theSurf, + const TColStd_Array1OfReal& theUPars, + const TColStd_Array1OfReal& theVPars); + + //! Fills the array with the points (triangulation nodes) on the surface + //! and normal directions of the surface in these points. + Standard_EXPORT static void FillArrayOfPointNormal(const Handle(Adaptor3d_HSurface)& theSurf, + const TColStd_Array1OfReal& theUPars, + const TColStd_Array1OfReal& theVPars, + IntPolyh_ArrayOfPointNormal& thePoints); + + +}; + +#endif // _IntPolyh_Tools_HeaderFile diff --git a/src/IntTools/FILES b/src/IntTools/FILES index 4dc8a6d44d..6917e7b63d 100644 --- a/src/IntTools/FILES +++ b/src/IntTools/FILES @@ -7,7 +7,6 @@ IntTools_BaseRangeSample.hxx IntTools_BaseRangeSample.lxx IntTools_BeanFaceIntersector.cxx IntTools_BeanFaceIntersector.hxx -IntTools_BeanFaceIntersector.lxx IntTools_CArray1.gxx IntTools_CArray1.lxx IntTools_CArray1OfInteger.hxx diff --git a/src/IntTools/IntTools_BeanFaceIntersector.cxx b/src/IntTools/IntTools_BeanFaceIntersector.cxx index 3839ac7b77..cbae85db3e 100644 --- a/src/IntTools/IntTools_BeanFaceIntersector.cxx +++ b/src/IntTools/IntTools_BeanFaceIntersector.cxx @@ -125,7 +125,6 @@ myVMinParameter(0.), myVMaxParameter(0.), myBeanTolerance(0.), myFaceTolerance(0.), -myDeflection(0.01), myIsDone(Standard_False) { myCriteria = Precision::Confusion(); @@ -147,7 +146,6 @@ IntTools_BeanFaceIntersector::IntTools_BeanFaceIntersector(const TopoDS_Edge& th myVMaxParameter(0.), myBeanTolerance(0.), myFaceTolerance(0.), - myDeflection(0.01), myIsDone(Standard_False) { Init(theEdge, theFace); @@ -167,7 +165,6 @@ IntTools_BeanFaceIntersector::IntTools_BeanFaceIntersector(const BRepAdaptor_Cur myUMaxParameter(0.), myVMinParameter(0.), myVMaxParameter(0.), - myDeflection(0.01), myIsDone(Standard_False) { Init(theCurve, theSurface, theBeanTolerance, theFaceTolerance); @@ -195,7 +192,6 @@ IntTools_BeanFaceIntersector::IntTools_BeanFaceIntersector(const BRepAdaptor_Cur myVMaxParameter(theVMaxParameter), myBeanTolerance(theBeanTolerance), myFaceTolerance(theFaceTolerance), - myDeflection(0.01), myIsDone(Standard_False) { myCurve = theCurve; @@ -322,142 +318,93 @@ void IntTools_BeanFaceIntersector::SetSurfaceParameters(const Standard_Real theU // function: Perform // purpose: // ================================================================================== -void IntTools_BeanFaceIntersector::Perform() +void IntTools_BeanFaceIntersector::Perform() { myIsDone = Standard_False; myResults.Clear(); - Standard_Integer bRet; - Standard_Integer aDiscretization = 30; - Standard_Real aRelativeDeflection = 0.01; - myDeflection = aRelativeDeflection; - // - if (myContext.IsNull()) { + + if (myContext.IsNull()) + { myContext=new IntTools_Context; } - // - if(myCurve.GetType()==GeomAbs_Line && mySurface.GetType()==GeomAbs_Plane) { + + // Fast computation of Line/Plane case + if (myCurve.GetType() == GeomAbs_Line && + mySurface.GetType() == GeomAbs_Plane) + { ComputeLinePlane(); return; } - if(myCurve.GetType()==GeomAbs_Line) { - aDiscretization = 3; - myDeflection = Precision::Confusion(); - } - else { - if(myCurve.GetType()==GeomAbs_Circle) { - aDiscretization = 23; - Standard_Real R = myCurve.Circle().Radius(); - myDeflection = aRelativeDeflection * R; - } - if(myCurve.GetType() == GeomAbs_Ellipse) { - aDiscretization = 23; - Standard_Real R = myCurve.Ellipse().MajorRadius(); - myDeflection = 2 * aRelativeDeflection * R; - } - } -// modified by NIZHNY-MKK Wed Oct 19 12:15:21 2005 - Standard_Boolean bLocalize = Standard_False; - - if(((mySurface.GetType() == GeomAbs_BSplineSurface) && - ((mySurface.UDegree() > 2) || (mySurface.VDegree() > 2)) && - //modified by NIZNHY-PKV Wed Feb 25 15:02:00 2009f - //((mySurface.NbUKnots() > 2) || (mySurface.NbVKnots() > 2))) || - ((mySurface.NbUKnots() > 2) && (mySurface.NbVKnots() > 2))) || - //modified by NIZNHY-PKV Wed Feb 25 15:02:13 2009t - (mySurface.GetType() == GeomAbs_BezierSurface) || - (mySurface.GetType() == GeomAbs_OtherSurface)) { - bLocalize = Standard_True; - } - - if(bLocalize) { - if(Precision::IsInfinite(myUMinParameter) || - Precision::IsInfinite(myUMaxParameter) || - Precision::IsInfinite(myVMinParameter) || - Precision::IsInfinite(myVMaxParameter)) - bLocalize = Standard_False; + // Fast check on coincidence for analytic cases + if (FastComputeAnalytic()) + { + // no further computation is necessary + myIsDone = Standard_True; + return; } - Standard_Boolean bSuccessLocalize = Standard_False; - if( bLocalize) { - myRangeManager.SetBoundaries(myFirstParameter, myLastParameter, 0); - Standard_Boolean coinside = TestComputeCoinside(); + // Initialization of the range manager + myRangeManager.SetBoundaries(myFirstParameter, myLastParameter, 0); - if(!coinside) - bSuccessLocalize = ComputeLocalized(); + // Check coincidence + Standard_Boolean isCoincide = TestComputeCoinside(); + if (isCoincide) + { + myResults.Append(IntTools_Range(myFirstParameter, myLastParameter)); + myIsDone = Standard_True; + return; } - if(!bLocalize || !bSuccessLocalize) { -// modified by NIZHNY-MKK Wed Oct 19 12:15:26 2005.END + // Perform intersection - IntTools_CArray1OfReal aParams; - - if(IntTools::PrepareArgs(myCurve, - myLastParameter, - myFirstParameter, - aDiscretization, - aRelativeDeflection, - aParams)) { - return; - } + // try to find localized solution + Standard_Boolean bLocalize = (!Precision::IsInfinite(myUMinParameter) && + !Precision::IsInfinite(myUMaxParameter) && + !Precision::IsInfinite(myVMinParameter) && + !Precision::IsInfinite(myVMaxParameter)); + bLocalize = bLocalize && (mySurface.GetType() == GeomAbs_BezierSurface || + mySurface.GetType() == GeomAbs_OtherSurface || + (mySurface.GetType() == GeomAbs_BSplineSurface && + (mySurface.UDegree() > 2 || mySurface.VDegree() > 2) && + (mySurface.NbUKnots() > 2 && mySurface.NbVKnots() > 2))); - myRangeManager.SetRanges(aParams, 0); + Standard_Boolean isLocalized = bLocalize && ComputeLocalized(); - if(myRangeManager.Length()==0) { - return; - } - // - bRet=FastComputeExactIntersection(); - if(bRet == 1) { - IntTools_Range aRange(myFirstParameter, myLastParameter); - myResults.Append(aRange); - myIsDone = Standard_True; - return; - } - //modified by NIZHNY-EMV Fri Apr 20 09:38:08 2012 - else if (bRet == 2) { - myIsDone = Standard_True; - return; - } - //modified by NIZHNY-EMV Fri Apr 20 09:38:10 2012 + // Perform real intersection + if (!isLocalized) + { + ComputeAroundExactIntersection(); + ComputeUsingExtremum(); -// Standard_Boolean coinside = TestCoinside(myCurve,mySurface); - Standard_Boolean coinside = TestComputeCoinside(); -// if(coinside) { -// myRangeManager.InsertRange(myFirstParameter, myLastParameter, 2); -// } -// else { - if(!coinside) { - ComputeAroundExactIntersection(); - - ComputeUsingExtremum(); - - ComputeNearRangeBoundaries(); - } + ComputeNearRangeBoundaries(); } myIsDone = Standard_True; - for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) { - - if(myRangeManager.Flag(i) == 2) { - IntTools_Range aRange = myRangeManager.Range(i); + // Treatment of the results + for (Standard_Integer i = 1; i <= myRangeManager.Length(); i++) + { + if (myRangeManager.Flag(i) != 2) + continue; - if(myResults.Length() > 0) { - const IntTools_Range& aLastRange = myResults.Last(); - - if(Abs(aRange.First() - aLastRange.Last()) > Precision::PConfusion()) { - myResults.Append(aRange); - } - else { - myResults.ChangeValue(myResults.Length()).SetLast(aRange.Last()); - } - } - else { + IntTools_Range aRange = myRangeManager.Range(i); + Standard_Integer iLastRange = myResults.Length(); + if (iLastRange > 0) + { + IntTools_Range& aLastRange = myResults.ChangeValue(iLastRange); + if (Abs(aRange.First() - aLastRange.Last()) > Precision::PConfusion()) + { myResults.Append(aRange); } + else + { + aLastRange.SetLast(aRange.Last()); + } } + else + myResults.Append(aRange); } } @@ -721,238 +668,127 @@ void IntTools_BeanFaceIntersector::ComputeAroundExactIntersection() // function: FastComputeExactIntersection // purpose: // ================================================================================== -Standard_Integer IntTools_BeanFaceIntersector::FastComputeExactIntersection() +Standard_Boolean IntTools_BeanFaceIntersector::FastComputeAnalytic() { - Standard_Integer aresult; - GeomAbs_CurveType aCT; - GeomAbs_SurfaceType aST; - // - aresult = 0; - aCT=myCurve.GetType(); - aST=mySurface.GetType(); - // - if((aCT==GeomAbs_BezierCurve) || - (aCT==GeomAbs_BSplineCurve) || - (aCT==GeomAbs_OffsetCurve) || - (aCT==GeomAbs_OtherCurve)) { - return aresult; + GeomAbs_CurveType aCT = myCurve.GetType(); + if (aCT == GeomAbs_BezierCurve || + aCT == GeomAbs_BSplineCurve || + aCT == GeomAbs_OffsetCurve || + aCT == GeomAbs_OtherCurve) + { + // not supported type + return Standard_False; } - if(aST==GeomAbs_Plane) { - gp_Pln surfPlane = mySurface.Plane(); + Standard_Boolean isCoincide = Standard_False; + Standard_Boolean hasIntersection = Standard_True; - if(aCT==GeomAbs_Line) { - if((surfPlane.Distance(myCurve.Value(myFirstParameter)) < myCriteria) && - (surfPlane.Distance(myCurve.Value(myLastParameter)) < myCriteria)) { - aresult = 1; - } - } - else { // else 1 - gp_Dir aDir; + GeomAbs_SurfaceType aST = mySurface.GetType(); - switch(aCT) { - case GeomAbs_Circle: { - aDir = myCurve.Circle().Axis().Direction(); - break; - } - case GeomAbs_Ellipse: { - aDir = myCurve.Ellipse().Axis().Direction(); - break; - } - case GeomAbs_Hyperbola: { - aDir = myCurve.Hyperbola().Axis().Direction(); - break; - } - case GeomAbs_Parabola: { - aDir = myCurve.Parabola().Axis().Direction(); - break; - } - default: { - return aresult; - } - } - // - Standard_Real anAngle = aDir.Angle(surfPlane.Axis().Direction()); - - if(anAngle < Precision::Angular()) { - Standard_Boolean insertRange = Standard_False; - - switch(aCT) { - case GeomAbs_Circle: { - Standard_Real adist = - surfPlane.Distance(myCurve.Circle().Location()) + - myCurve.Circle().Radius() * Precision::Angular(); - - if(adist < myCriteria) { - insertRange = Standard_True; - } - break; - } - case GeomAbs_Ellipse: { - Standard_Real adist = - surfPlane.Distance(myCurve.Ellipse().Location()) + - myCurve.Ellipse().MajorRadius() * Precision::Angular(); - - if(adist < myCriteria) { - insertRange = Standard_True; - } - break; - } - case GeomAbs_Hyperbola: - case GeomAbs_Parabola: { - Standard_Real aMaxPar = - (Abs(myFirstParameter) > Abs(myLastParameter)) ? - Abs(myFirstParameter) : Abs(myLastParameter); - - gp_Pnt aLoc = (aCT == GeomAbs_Parabola) ? - myCurve.Parabola().Location() : - myCurve.Hyperbola().Location(); - Standard_Real adist = aLoc.Distance(myCurve.Value(aMaxPar)); - adist = surfPlane.Distance(aLoc) + adist * Precision::Angular(); - - if(adist < myCriteria) { - insertRange = Standard_True; - } - break; - } - default: { - break; - } - } - // - if(insertRange) { - aresult = 1; - } - }//if(anAngle < Precision::Angular()) { - }//else { // else 1 - }// if(aST==GeomAbs_Plane) { - - if(aCT==GeomAbs_Circle) { - gp_Circ aCircle = myCurve.Circle(); - - if(aST==GeomAbs_Cylinder) { - gp_Cylinder aCylinder = mySurface.Cylinder(); - gp_Dir aDir1(aCylinder.Axis().Direction()); - gp_Dir aDir2(aCircle.Axis().Direction()); - Standard_Real anAngle = aDir1.Angle(aDir2); - - if(anAngle < Precision::Angular()) { - gp_Pnt aLoc = aCircle.Location(); - gp_Lin anCylAxis(aCylinder.Axis()); - Standard_Real alocdist = anCylAxis.Distance(aLoc); - Standard_Real adist = alocdist; - Standard_Real adiff = aCircle.Radius() - aCylinder.Radius(); - adist += Abs(adiff); - - if(adist < myCriteria) { - Standard_Real acylradius = aCylinder.Radius(); - Standard_Real atmpvalue = aCircle.Radius() * sin(Precision::Angular()); - Standard_Real aprojectedradius = atmpvalue; - aprojectedradius = - sqrt((aCircle.Radius() * aCircle.Radius()) - - (aprojectedradius * aprojectedradius)); - adiff = aprojectedradius - acylradius; - adist = alocdist + Abs(adiff); - - if(adist < myCriteria) { // Abs is important function here - aresult = 1; - } - } - } - }// if(aST==GeomAbs_Cylinder) + // Plane - Circle/Ellipse/Hyperbola/Parabola + if (aST == GeomAbs_Plane) + { + gp_Pln surfPlane = mySurface.Plane(); - if(aST==GeomAbs_Sphere) { - gp_Pln aCirclePln(aCircle.Location(), aCircle.Axis().Direction()); - IntAna_QuadQuadGeo anInter(aCirclePln, mySurface.Sphere()); - - if(anInter.IsDone()) { - if(anInter.TypeInter() == IntAna_Circle) { - gp_Circ aCircleToCompare = anInter.Circle(1); - Standard_Real adist = - aCircleToCompare.Location().Distance(aCircle.Location()); - Standard_Real adiff = aCircle.Radius() - aCircleToCompare.Radius(); - adist += Abs(adiff); - - if(adist < myCriteria) { - aresult = 1; - } - } + gp_Dir aDir; + gp_Pnt aPLoc; + switch (aCT) { + case GeomAbs_Circle: + { + aDir = myCurve.Circle().Axis().Direction(); + aPLoc = myCurve.Circle().Location(); + break; } - }// if(aST==GeomAbs_Sphere) { - }// if(aCT==GeomAbs_Circle) { - // - //modified by NIZNHY-PKV Thu Mar 01 11:54:04 2012f - if(aST==GeomAbs_Cylinder) { - Standard_Real aRC; - gp_Cylinder aCyl; - // - aCyl=mySurface.Cylinder(); - aRC=aCyl.Radius(); - const gp_Ax1& aAx1C=aCyl.Axis(); - const gp_Dir& aDirC=aAx1C.Direction(); - // - if(aCT==GeomAbs_Line) { - Standard_Real aCos, aAng2, aTolang2; - gp_Lin aLin; - // - aTolang2=1.e-16; - aLin=myCurve.Line(); - const gp_Dir& aDirL=aLin.Direction(); - // - aCos=aDirC.Dot(aDirL); - if(aCos >= 0.) { - aAng2 = 2.*(1. - aCos); + case GeomAbs_Ellipse: + { + aDir = myCurve.Ellipse().Axis().Direction(); + aPLoc = myCurve.Ellipse().Location(); + break; } - else { - aAng2 = 2.*(1. + aCos); + case GeomAbs_Hyperbola: + { + aDir = myCurve.Hyperbola().Axis().Direction(); + aPLoc = myCurve.Hyperbola().Location(); + break; } - // - if(aAng2<=aTolang2) {// IsParallel = Standard_True; - Standard_Boolean bFlag = Standard_False; - Standard_Integer i; - Standard_Real aD; - gp_Pnt aPL[2]; - gp_Lin aLC(aAx1C); - // - aPL[0]=myCurve.Value(myFirstParameter); - aPL[1]=myCurve.Value(myLastParameter); - // - for (i=0; i<2; ++i) { - aD=aLC.Distance(aPL[i]); - aD=fabs(aD-aRC); - bFlag=(aD > myCriteria); - if (bFlag) { - break; - } - } - if (!bFlag){ - aresult = 1; - } + case GeomAbs_Parabola: + { + aDir = myCurve.Parabola().Axis().Direction(); + aPLoc = myCurve.Parabola().Location(); + break; } - - }//if(aCT==GeomAbs_Line) { + default: + return Standard_False; + } + + Standard_Real anAngle = aDir.Angle(surfPlane.Axis().Direction()); + if (anAngle > Precision::Angular()) + return Standard_False; + + hasIntersection = Standard_False; + + Standard_Real aDist = surfPlane.Distance(aPLoc); + isCoincide = aDist < myCriteria; } - //modified by NIZNHY-PKV Thu Mar 01 11:54:06 2012t - // - if (aresult==1) { - //check intermediate point - Standard_Real aTm; - Standard_Boolean bValid; - // - const TopoDS_Face& aF = mySurface.Face(); - aTm = IntTools_Tools::IntermediatePoint(myFirstParameter, myLastParameter); - const gp_Pnt& aPm = myCurve.Value(aTm); - // - bValid = myContext->IsValidPointForFace(aPm, aF, myCriteria); - if (bValid) { - IntTools_Range aRange(myFirstParameter, myLastParameter); - myRangeManager.InsertRange(aRange, 2); - } else { - aresult=2; + + // Cylinder - Line/Circle + else if (aST == GeomAbs_Cylinder) + { + gp_Cylinder aCylinder = mySurface.Cylinder(); + const gp_Ax1& aCylAxis = aCylinder.Axis(); + const gp_Dir& aCylDir = aCylAxis.Direction(); + Standard_Real aCylRadius = aCylinder.Radius(); + + if (aCT == GeomAbs_Line) + { + gp_Lin aLin = myCurve.Line(); + if (!aLin.Direction().IsParallel(aCylDir, Precision::Angular())) + return Standard_False; + + hasIntersection = Standard_False; + + Standard_Real aDist = Abs(aLin.Distance(aCylAxis.Location()) - aCylRadius); + isCoincide = (aDist < myCriteria); + } + + else if (aCT == GeomAbs_Circle) + { + gp_Circ aCircle = myCurve.Circle(); + + Standard_Real anAngle = aCylDir.Angle(aCircle.Axis().Direction()); + if (anAngle > Precision::Angular()) + return Standard_False; + + Standard_Real aDistLoc = gp_Lin(aCylAxis).Distance(aCircle.Location()); + Standard_Real aDist = aDistLoc + Abs(aCircle.Radius() - aCylRadius); + isCoincide = (aDist < myCriteria); + + if (!isCoincide) + hasIntersection = (aDistLoc - (aCircle.Radius() + aCylRadius)) < myCriteria && + (Abs(aCircle.Radius() - aCylRadius) - aDistLoc) < myCriteria; } } - // - return aresult; + + // Sphere - Line + else if (aST == GeomAbs_Sphere) + { + gp_Sphere aSph = mySurface.Sphere(); + gp_Pnt aSphLoc = aSph.Location(); + if (aCT == GeomAbs_Line) + { + gp_Lin aLin = myCurve.Line(); + Standard_Real aDist = aLin.Distance(aSphLoc) - aSph.Radius(); + hasIntersection = aDist < myCriteria; + } + } + + // Check intermediate point + if (isCoincide) + { + myResults.Append(IntTools_Range(myFirstParameter, myLastParameter)); + } + + return isCoincide || !hasIntersection; } // ================================================================================== @@ -1057,10 +893,6 @@ void IntTools_BeanFaceIntersector::ComputeUsingExtremum() myUMaxParameter, myVMinParameter, myVMaxParameter); - - Bnd_Box FBox; - BndLib_AddSurface::Add(mySurface, 0., FBox); - FBox.Enlarge(myFaceTolerance); for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) { @@ -1073,24 +905,13 @@ void IntTools_BeanFaceIntersector::ComputeUsingExtremum() if(anarg2 - anarg1 < Precision::PConfusion()) { - if(((i > 1) && (myRangeManager.Flag(i-1) == 2)) || - ((i < myRangeManager.Length()) && (myRangeManager.Flag(i+1) == 2))) { - myRangeManager.SetFlag(i, 1); - continue; + if (((i > 1) && (myRangeManager.Flag(i - 1) == 2)) || + ((i < myRangeManager.Length()) && (myRangeManager.Flag(i + 1) == 2))) { + myRangeManager.SetFlag(i, 1); + continue; } } - // check bounding boxes - Bnd_Box EBox; - EBox.Add(myCurve.Value(anarg1)); - EBox.Add(myCurve.Value(anarg2)); - EBox.Enlarge(myBeanTolerance + myDeflection); - - if(EBox.IsOut(FBox)) { - myRangeManager.SetFlag(i, 1); - continue; - } - GeomAdaptor_Curve aGACurve(aCurve, anarg1, anarg2); Extrema_ExtCS theExtCS(aGACurve, aGASurface, Tol, Tol); myExtrema = theExtCS; diff --git a/src/IntTools/IntTools_BeanFaceIntersector.hxx b/src/IntTools/IntTools_BeanFaceIntersector.hxx index 24046d8cc0..da5f2f4d0a 100644 --- a/src/IntTools/IntTools_BeanFaceIntersector.hxx +++ b/src/IntTools/IntTools_BeanFaceIntersector.hxx @@ -120,7 +120,11 @@ public: //! Launches the algorithm Standard_EXPORT void Perform(); - Standard_Boolean IsDone() const; + //! Returns Done/NotDone state of the algorithm. + Standard_Boolean IsDone() const + { + return myIsDone; + } Standard_EXPORT const IntTools_SequenceOfRanges& Result() const; @@ -142,7 +146,12 @@ private: Standard_EXPORT void ComputeLinePlane(); - Standard_EXPORT Standard_Integer FastComputeExactIntersection(); + //! Fast check on coincidence of the edge with face for the cases when both shapes are + //! based on analytic geometries. The method also computes if the intersection + //! between shapes is possible. + //! The method returns TRUE if the computation was successful and further computation is unnecessary. + //! Otherwise it returns FALSE and computation continues. + Standard_EXPORT Standard_Boolean FastComputeAnalytic(); Standard_EXPORT void ComputeUsingExtremum(); @@ -179,19 +188,10 @@ private: Extrema_ExtCS myExtrema; GeomAPI_ProjectPointOnSurf myProjector; IntTools_MarkedRangeSet myRangeManager; - Standard_Real myDeflection; Handle(IntTools_Context) myContext; IntTools_SequenceOfRanges myResults; Standard_Boolean myIsDone; - }; - -#include - - - - - #endif // _IntTools_BeanFaceIntersector_HeaderFile diff --git a/src/IntTools/IntTools_EdgeFace.cxx b/src/IntTools/IntTools_EdgeFace.cxx index 2ce57e0529..36f181e58a 100644 --- a/src/IntTools/IntTools_EdgeFace.cxx +++ b/src/IntTools/IntTools_EdgeFace.cxx @@ -68,146 +68,11 @@ static IntTools_EdgeFace::IntTools_EdgeFace() { myFuzzyValue = Precision::Confusion(); - myDiscret = 30; - myEpsT =1e-12; - myDeflection=0.01; myIsDone=Standard_False; myErrorStatus=1; myQuickCoincidenceCheck=Standard_False; } //======================================================================= -//function : SetContext -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetContext(const Handle(IntTools_Context)& theContext) -{ - myContext = theContext; -} - -//======================================================================= -//function : Context -//purpose : -//======================================================================= -const Handle(IntTools_Context)& IntTools_EdgeFace::Context()const -{ - return myContext; -} -//======================================================================= -//function : SetEdge -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetEdge(const TopoDS_Edge& anEdge) -{ - myEdge=anEdge; -} -//======================================================================= -//function : SetFace -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetFace(const TopoDS_Face& aFace) -{ - myFace=aFace; -} -//======================================================================= -//function : Edge -//purpose : -//======================================================================= -const TopoDS_Edge& IntTools_EdgeFace::Edge()const -{ - return myEdge; -} -//======================================================================= -//function : Face -//purpose : -//======================================================================= -const TopoDS_Face& IntTools_EdgeFace::Face()const -{ - return myFace; -} -//======================================================================= -//function : SetFuzzyValue -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetFuzzyValue(const Standard_Real theFuzz) -{ - myFuzzyValue = Max(theFuzz, Precision::Confusion()); -} -//======================================================================= -//function : SetDiscretize -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetDiscretize(const Standard_Integer aDiscret) -{ - myDiscret=aDiscret; -} -//======================================================================= -//function : SetDeflection -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetDeflection(const Standard_Real aDefl) -{ - myDeflection=aDefl; -} -//======================================================================= -//function : SetEpsilonT -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetEpsilonT(const Standard_Real anEpsT) -{ - myEpsT=anEpsT; -} -//======================================================================= -//function : SetRange -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetRange(const Standard_Real aFirst, - const Standard_Real aLast) -{ - myRange.SetFirst (aFirst); - myRange.SetLast (aLast); -} - -//======================================================================= -//function : SetRange -//purpose : -//======================================================================= -void IntTools_EdgeFace::SetRange(const IntTools_Range& aRange) -{ - SetRange(aRange.First(), aRange.Last()); -} -//======================================================================= -//function : IsDone -//purpose : -//======================================================================= -Standard_Boolean IntTools_EdgeFace::IsDone()const -{ - return myIsDone; -} -//======================================================================= -//function : ErrorStatus -//purpose : -//======================================================================= -Standard_Integer IntTools_EdgeFace::ErrorStatus()const -{ - return myErrorStatus; -} -//======================================================================= -//function : CommonParts -//purpose : -//======================================================================= -const IntTools_SequenceOfCommonPrts& IntTools_EdgeFace::CommonParts() const -{ - return mySeqOfCommonPrts; -} -//======================================================================= -//function : Range -//purpose : -//======================================================================= -const IntTools_Range& IntTools_EdgeFace::Range() const -{ - return myRange; -} -//======================================================================= //function : IsCoincident //purpose : //======================================================================= @@ -352,7 +217,7 @@ Standard_Real IntTools_EdgeFace::DistanceFunction // if (!bFlag) { - myErrorStatus=11; + myErrorStatus = 4; return 99.; } @@ -597,11 +462,11 @@ Standard_Boolean IntTools_EdgeFace::CheckTouch return theflag; } - if (fabs (aTx-aTF) < myEpsT) { + if (fabs (aTx-aTF) < Precision::PConfusion()) { return !theflag; } - if (fabs (aTx-aTL) < myEpsT) { + if (fabs (aTx-aTL) < Precision::PConfusion()) { return !theflag; } @@ -769,16 +634,6 @@ void IntTools_EdgeFace::Perform() myIsDone=Standard_True; } -// -// myErrorStatus -// 1 - the method Perform() is not invoked -// 2,3,4,5 -the method CheckData() fails -// 6 - PrepareArgs() problems -// 7 - No Projectable ranges -// 8,9 - PrepareArgs() problems occured inside projectable Ranges -// 11 - can't fill array aFunc(i) in PrepareArgsFuncArrays - - //======================================================================= //function : CheckTouch //purpose : diff --git a/src/IntTools/IntTools_EdgeFace.hxx b/src/IntTools/IntTools_EdgeFace.hxx index 53970cfb87..33af356183 100644 --- a/src/IntTools/IntTools_EdgeFace.hxx +++ b/src/IntTools/IntTools_EdgeFace.hxx @@ -38,113 +38,148 @@ class gp_Pnt; class BRepAdaptor_Surface; class IntTools_CommonPrt; - -//! The class provides Edge/Face algorithm to determine -//! common parts between edge and face in 3-d space. -//! Common parts can be : Vertices or Edges. +//! The class provides Edge/Face intersection algorithm to determine +//! common parts between edge and face in 3-d space. +//! Common parts between Edge and Face can be: +//! - Vertices - in case of intersection or touching; +//! - Edge - in case of full coincidence of the edge with the face. class IntTools_EdgeFace { public: DEFINE_STANDARD_ALLOC - +public: //! @name Constructors //! Empty Constructor Standard_EXPORT IntTools_EdgeFace(); - - - //! Initializes algorithm by the edge anEdge - Standard_EXPORT void SetEdge (const TopoDS_Edge& anEdge); - - //! Initializes algorithm by the face aFace - Standard_EXPORT void SetFace (const TopoDS_Face& aFace); - +public: //! @name Setters/Getters - //! Returns edge - Standard_EXPORT const TopoDS_Edge& Edge() const; - + //! Sets the edge for intersection + void SetEdge(const TopoDS_Edge& theEdge) + { + myEdge = theEdge; + } - //! Returns face - Standard_EXPORT const TopoDS_Face& Face() const; - + //! Returns the edge + const TopoDS_Edge& Edge() const + { + return myEdge; + } - //! Initializes algorithm by discretization value - Standard_EXPORT void SetDiscretize (const Standard_Integer aDiscret); - + //! Sets the face for intersection + void SetFace(const TopoDS_Face& theFace) + { + myFace = theFace; + } - //! Initializes algorithm by deflection value - Standard_EXPORT void SetDeflection (const Standard_Real aDeflection); - + //! Returns the face + const TopoDS_Face& Face() const + { + return myFace; + } - //! Initializes algorithm by parameter tolerance - Standard_EXPORT void SetEpsilonT (const Standard_Real anEpsT); - - //! Sets boundaries for edge. + //! Sets the boundaries for the edge. //! The algorithm processes edge inside these boundaries. - Standard_EXPORT void SetRange (const IntTools_Range& aRange); - + void SetRange(const IntTools_Range& theRange) + { + myRange = theRange; + } - //! Sets boundaries for edge. + //! Sets the boundaries for the edge. //! The algorithm processes edge inside these boundaries. - Standard_EXPORT void SetRange (const Standard_Real aFirst, const Standard_Real aLast); - + void SetRange(const Standard_Real theFirst, const Standard_Real theLast) + { + myRange.SetFirst(theFirst); + myRange.SetLast(theLast); + } - //! Sets the intersecton context - Standard_EXPORT void SetContext (const Handle(IntTools_Context)& theContext); - + //! Returns intersection range of the edge + const IntTools_Range& Range() const + { + return myRange; + } + + //! Sets the intersection context + void SetContext(const Handle(IntTools_Context)& theContext) + { + myContext = theContext; + } + + //! Returns the intersection context + const Handle(IntTools_Context)& Context() const + { + return myContext; + } - //! Gets the intersecton context - Standard_EXPORT const Handle(IntTools_Context)& Context() const; - //! Sets the Fuzzy value - Standard_EXPORT void SetFuzzyValue(const Standard_Real theFuzz); + void SetFuzzyValue(const Standard_Real theFuzz) + { + myFuzzyValue = Max(theFuzz, Precision::Confusion()); + } - //! Returns Fuzzy value + //! Returns the Fuzzy value Standard_Real FuzzyValue() const { return myFuzzyValue; } + //! Sets the flag for quick coincidence check. + //! It is safe to use the quick check for coincidence only if both + //! of the following conditions are met: + //! - The vertices of edge are lying on the face; + //! - The edge does not intersect the boundaries of the face on the given range. + void UseQuickCoincidenceCheck(const Standard_Boolean theFlag) + { + myQuickCoincidenceCheck = theFlag; + } + + //! Returns the flag myQuickCoincidenceCheck + Standard_Boolean IsCoincidenceCheckedQuickly() + { + return myQuickCoincidenceCheck; + } + + + +public: //! @name Performing the operation + //! Launches the process Standard_EXPORT void Perform(); - - //! Returns true if computation was done - //! successfully, otherwise returns false - Standard_EXPORT Standard_Boolean IsDone() const; - - //! Returns code of completion - //! 0 - means successful completion - //! 1 - the process was not started - //! 2,3,4,5 - invalid source data for the algorithm - //! 6 - discretization failed - //! 7 - no projectable ranges found - //! 11 - distance computing error - Standard_EXPORT Standard_Integer ErrorStatus() const; - +public: //! @name Checking validity of the intersection - //! Returns results - Standard_EXPORT const IntTools_SequenceOfCommonPrts& CommonParts() const; - - - //! Returns boundaries for edge - Standard_EXPORT const IntTools_Range& Range() const; + //! Returns TRUE if computation was successful. + //! Otherwise returns FALSE. + Standard_Boolean IsDone() const + { + return myIsDone; + } - //! Sets the flag myQuickCoincidenceCheck - void UseQuickCoincidenceCheck(const Standard_Boolean bFlag) { - myQuickCoincidenceCheck=bFlag; + //! Returns the code of completion: + //! 0 - means successful completion; + //! 1 - the process was not started; + //! 2,3 - invalid source data for the algorithm; + //! 4 - projection failed. + Standard_Integer ErrorStatus() const + { + return myErrorStatus; } - //! Returns the flag myQuickCoincidenceCheck - Standard_Boolean IsCoincidenceCheckedQuickly () { - return myQuickCoincidenceCheck; + +public: //! @name Obtaining results + + //! Returns resulting common parts + const IntTools_SequenceOfCommonPrts& CommonParts() const + { + return mySeqOfCommonPrts; } -protected: +protected: //! @name Protected methods performing the intersection + Standard_EXPORT static Standard_Boolean IsEqDistance (const gp_Pnt& aP, const BRepAdaptor_Surface& aS, const Standard_Real aT, Standard_Real& aD); Standard_EXPORT void CheckData(); @@ -161,18 +196,11 @@ protected: //! Checks if the edge is in the face really. Standard_EXPORT Standard_Boolean IsCoincident(); - - private: - - TopoDS_Edge myEdge; TopoDS_Face myFace; Standard_Real myFuzzyValue; - Standard_Integer myDiscret; - Standard_Real myEpsT; - Standard_Real myDeflection; BRepAdaptor_Curve myC; BRepAdaptor_Surface myS; Standard_Real myCriteria; @@ -181,20 +209,7 @@ private: Handle(IntTools_Context) myContext; IntTools_SequenceOfCommonPrts mySeqOfCommonPrts; IntTools_Range myRange; - - //! Allows avoiding use Edge-Face intersection - //! algorithm (i.e. speeding up the Boolean algorithm) - //! if the edges are coincided really. - //! If it is not evidently set of this flag should - //! be avoided (otherwise, the performance of - //! Boolean algorithm will be slower). Standard_Boolean myQuickCoincidenceCheck; }; - - - - - - #endif // _IntTools_EdgeFace_HeaderFile diff --git a/tests/bugs/modalg_1/buc60462_2 b/tests/bugs/modalg_1/buc60462_2 index a3f18ad7fc..13e5c38c0c 100755 --- a/tests/bugs/modalg_1/buc60462_2 +++ b/tests/bugs/modalg_1/buc60462_2 @@ -1,5 +1,4 @@ puts "TODO OCC27024 ALL: Error : operation bfuse is WRONG because number of SOLID entities in shape" -puts "TODO OCC27024 ALL: Faulty shapes in variables faulty_1 to faulty_" puts "==========" puts "BUC60462" @@ -13,8 +12,7 @@ puts "Fuse begin" bfuse result a b puts "Fuse end" -checkshape result r +checkshape result checknbshapes result -solid 1 -m "operation bfuse" checkprops result -s 93237.9 -checkshape result checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_1/buc60463 b/tests/bugs/modalg_1/buc60463 index e2eb82bc97..2fae3cdaa5 100755 --- a/tests/bugs/modalg_1/buc60463 +++ b/tests/bugs/modalg_1/buc60463 @@ -1,6 +1,3 @@ -puts "TODO OCC12345 ALL: Error : The length of result shape is" -puts "TODO OCC12345 ALL: Faulty : Section is incorrect" - puts "=============" puts "BUC60463" puts "=============" @@ -18,8 +15,7 @@ if { $cs != 0 } { puts "Faulty : Section is incorrect" } -checkprops result -l 0 +checkprops result -l 520.961 checkshape result -checksection result checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_6/bug26063 b/tests/bugs/modalg_6/bug26063 index 6b22d84fba..7ef0fb7808 100644 --- a/tests/bugs/modalg_6/bug26063 +++ b/tests/bugs/modalg_6/bug26063 @@ -10,18 +10,18 @@ polyline l 0 -10 -10 0 10 -10 0 10 10 0 -10 10 0 -10 -10 mkplane pl l mksurface surf pl -vinit -vdisplay pl vertex v1 10 -5 0 vertex v2 10 5 0 edge e v1 v2 mkcurve curv e -vdisplay e -vfit set bug_info [extrema surf curv] -if {$bug_info != "No solutions!\n"} { +if {$bug_info != "Infinite number of extremas, distance = 10\n"} { puts "ERROR: OCC25063 is reproduced." } -checkview -screenshot -3d -path ${imagedir}/${test_image}.png +smallview +don pl e +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug23927 b/tests/bugs/modalg_7/bug23927 index 551f5ebb09..2aad3445d3 100644 --- a/tests/bugs/modalg_7/bug23927 +++ b/tests/bugs/modalg_7/bug23927 @@ -24,8 +24,8 @@ explode line V set tol_abs 0.001 set tol_rel 0 -distmini d p_1_1 line_1 +distmini d p_1_1 line_2 checkreal "Projection, p1" [dval d_val] 0 $tol_abs $tol_rel -distmini d p_1_2 line_2 +distmini d p_1_2 line_1 checkreal "Projection, p2" [dval d_val] 0 $tol_abs $tol_rel diff --git a/tests/bugs/modalg_7/bug25385 b/tests/bugs/modalg_7/bug25385 index a2bbcf7efb..201a5a1211 100644 --- a/tests/bugs/modalg_7/bug25385 +++ b/tests/bugs/modalg_7/bug25385 @@ -1,5 +1,3 @@ -puts "TODO OCC25385 ALL: is not equal to expected" - puts "============" puts "OCC25385" puts "============" @@ -22,3 +20,5 @@ regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance s] full MaxTol_s_2 set tol_abs_MaxTol 0.0001 set tol_rel_MaxTol 0.0001 checkreal "MaxTolerance " ${MaxTol_s_2} ${MaxTol_s_1} ${tol_abs_MaxTol} ${tol_rel_MaxTol} + +checkprops r -l 36.2401 \ No newline at end of file diff --git a/tests/bugs/moddata_3/bug25407_1 b/tests/bugs/moddata_3/bug25407_1 index 069135853f..a549cee125 100755 --- a/tests/bugs/moddata_3/bug25407_1 +++ b/tests/bugs/moddata_3/bug25407_1 @@ -15,11 +15,8 @@ mksurface s f extrema c s if { [isdraw ext_1] } { - mkedge result ext_1 - checkprops result -l 1.88322e-11 - checksection result + set len [lindex [length ext_1] end] + checkreal "Extrema min distance" $len 1.88322e-11 1.e-7 1.e-7 } else { puts "Error: invalid result" } - -checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_3/bug25407_2 b/tests/bugs/moddata_3/bug25407_2 index 72f051c3b2..1629dc581d 100755 --- a/tests/bugs/moddata_3/bug25407_2 +++ b/tests/bugs/moddata_3/bug25407_2 @@ -18,11 +18,8 @@ trim ct c 1.1167213545471877e-008 0.033333343614041021 extrema ct st if { [isdraw ext_1] } { - mkedge result ext_1 - checkprops result -l 1.00005e-07 - checksection result + set len [lindex [length ext_1] end] + checkreal "Extrema min distance" $len 1.00005e-07 1.e-7 1.e-7 } else { puts "Error: invalid result" } - -checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/de/step_1/J6 b/tests/de/step_1/J6 index 84752d8e14..f30c26dd3f 100755 --- a/tests/de/step_1/J6 +++ b/tests/de/step_1/J6 @@ -8,11 +8,11 @@ set filename bm1_pe_t4.stp set ref_data { DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 0 ) Summary = 0 ( 0 ) -TPSTAT : Faulties = 0 ( 2 ) Warnings = 14 ( 28 ) Summary = 14 ( 30 ) +TPSTAT : Faulties = 0 ( 3 ) Warnings = 13 ( 30 ) Summary = 13 ( 33 ) CHECKSHAPE : Wires = 3 ( 2 ) Faces = 3 ( 3 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) -NBSHAPES : Solid = 0 ( 0 ) Shell = 12 ( 12 ) Face = 15 ( 15 ) Summary = 142 ( 143 ) -STATSHAPE : Solid = 0 ( 0 ) Shell = 12 ( 12 ) Face = 15 ( 15 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 53 ( 51 ) -TOLERANCE : MaxTol = 1562.051497 ( 1562.051497 ) AvgTol = 273.5183373 ( 208.7393976 ) +NBSHAPES : Solid = 0 ( 0 ) Shell = 12 ( 12 ) Face = 15 ( 15 ) Summary = 140 ( 141 ) +STATSHAPE : Solid = 0 ( 0 ) Shell = 12 ( 12 ) Face = 15 ( 15 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 52 ( 50 ) +TOLERANCE : MaxTol = 1562.051497 ( 1562.051497 ) AvgTol = 272.6255712 ( 211.9512858 ) LABELS : N0Labels = 1 ( 1 ) N1Labels = 0 ( 0 ) N2Labels = 0 ( 0 ) TotalLabels = 1 ( 1 ) NameLabels = 1 ( 1 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 ) NCOLORS : NColors = 0 ( 0 ) diff --git a/tests/lowalgos/extcs/bug29426_1 b/tests/lowalgos/extcs/bug29426_1 new file mode 100644 index 0000000000..d8146b216d --- /dev/null +++ b/tests/lowalgos/extcs/bug29426_1 @@ -0,0 +1,18 @@ +puts "========" +puts "OCC29426" +puts "========" +puts "" +######################################## +# Extrema algorithm fails to find minimal distance between Circle and Sphere +######################################## + + +circle c 3.59679185933224e-016 11.6635040382361 -3.23970209548358 -3.67401855705945e-017 -0.943656647634893 0.330926172090505 -2.2723161366922e-016 0.330926172090505 0.943656647634893 1.30000000000039 +sphere s 0 2.425 0 0 1 0 1 -0 0 9.876 + +set log [extrema c s] + +if {![regexp "Point" $log]} { + set ext_dist [lindex [length ext_1] end] + checkreal "Circle/Sphere min distance" $ext_dist 0. 1.e-10 1.e-10 +} diff --git a/tests/lowalgos/extcs/bug29426_2 b/tests/lowalgos/extcs/bug29426_2 new file mode 100644 index 0000000000..82155b225f --- /dev/null +++ b/tests/lowalgos/extcs/bug29426_2 @@ -0,0 +1,17 @@ +puts "========" +puts "OCC29426" +puts "========" +puts "" +######################################## +# Extrema algorithm fails to find minimal distance between Circle and Sphere +######################################## + +circle c 3.53600008984273e-016 11.5073628633636 -3.18494573739955 -3.67401855705945e-017 -0.943656647634893 0.330926172090505 -2.2723161366922e-016 0.330926172090505 0.943656647634893 1.30000000000039 +sphere s 0 2.425 0 0 1 0 1 -0 0 9.712 + +set log [extrema c s] + +if {![regexp "Point" $log]} { + set ext_dist [lindex [length ext_1] end] + checkreal "Circle/Sphere min distance" $ext_dist 0. 1.e-10 1.e-10 +} diff --git a/tests/lowalgos/extcs/circ_sph_inter b/tests/lowalgos/extcs/circ_sph_inter new file mode 100644 index 0000000000..7fe93a5cba --- /dev/null +++ b/tests/lowalgos/extcs/circ_sph_inter @@ -0,0 +1,127 @@ +puts "=======================" +puts "Test for Circle/Sphere extrema algorithm" +puts "Intersection case (two intersection points should be found" +puts "=======================" +puts "" + +# Make sphere +set x0 0. +set y0 0. +set z0 0. +set sph_radius 10. +sphere s $x0 $y0 $z0 $sph_radius + +# All circles will be to connect the two points - one inside the sphere, another - outside. +# Such circle will definitely intersect the initial sphere in two points. +# The points to make the circle will taken two spheres - with smaller and bigger radius. + +# Set the number of iterations (number of pairs of spheres) +set nbpairs 2 + +# Set ratio to increase/decrease the radius if additional spheres +set ratio_radius 2. + +# Number of sampling points on the spheres +set nbsamples 5 + +# Number of circles rotations +set nbsteps 5 +set angle [expr 180. / $nbsteps] + +# Iteration step +set iStep 1 + +for {set i 1} {$i <= $nbpairs} {incr i} { + # Define the radius for spheres + set s_in_radius [expr $sph_radius / ($i * $ratio_radius)] + set s_out_radius [expr $sph_radius * ($i * $ratio_radius)] + + # Make the spheres + sphere s_in $x0 $y0 $z0 $s_in_radius + sphere s_out $x0 $y0 $z0 $s_out_radius + + # Make the sampling of the spheres + + # spheres are the same, so there is no difference from which one to take the parameters + bounds s_in umin umax vmin vmax + set du [dval (umax-umin)/$nbsteps] + set dv [dval (vmax-vmin)/$nbsteps] + + for {set u1 1} {$u1 <= $nbsamples} {incr u1} { + for {set v1 1} {$v1 <= $nbsamples} {incr v1} { + + # point on inner sphere + svalue s_in [dval umin+$u1*$du] [dval vmin+$v1*$dv] x1 y1 z1 + + for {set u2 1} {$u2 <= $nbsamples} {incr u2} { + for {set v2 1} {$v2 <= $nbsamples} {incr v2} { + + # point on outer sphere + svalue s_out [dval umin+$u2*$du] [dval vmin+$v2*$dv] x2 y2 z2 + + # rotation direction + set dx [dval x2-x1] + set dy [dval y2-y1] + set dz [dval z2-z1] + + # center of the circle + set xc [dval (x1+x2)/2.] + set yc [dval (y1+y2)/2.] + set zc [dval (z1+z2)/2.] + + # compute radius for circle + set cir_radius [expr sqrt($dx*$dx + $dy*$dy + $dz*$dz) / 2.] + + # make plane to get its XAxis + plane p $xc $yc $zc $dx $dy $dz + + regexp {XAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump p] full dxx dxy dxz + + circle c $xc $yc $zc $dxx $dxy $dxz $cir_radius + + # make rotation + copy c c_rotated + for {set j 1} {$j <= $nbsteps} {incr j} { + rotate c_rotated $xc $yc $zc $dx $dy $dz $angle + + set log [extrema c_rotated s] + + # save each circle if necessary + # copy c_rotated c_$iStep + + set isfound1 0 + set isfound2 0 + + if {[regexp "ext_1" $log]} { + set ext_dist [lindex [length ext_1] end] + checkreal "Step $iStep, min distance 1" $ext_dist 0 1.e-7 1.e-7 + set isfound1 1 + } + + if {[regexp "ext_2" $log]} { + set ext_dist [lindex [length ext_2] end] + checkreal "Step $iStep, min distance 2" $ext_dist 0 1.e-7 1.e-7 + set isfound2 1 + } + + if {[regexp "Extrema 1 is point" $log]} { + puts "Check of Step $iStep, min distance 1 OK" + set isfound1 1 + } + + if {[regexp "Extrema 2 is point" $log]} { + puts "Check of Step $iStep, min distance 2 OK" + set isfound2 1 + } + + if {$isfound1 == 0 || $isfound2 == 0} { + puts "Error: Extrema has not detected the intersection case on step $iStep" + } + + incr iStep + } + } + } + } + } +} diff --git a/tests/lowalgos/extcs/circ_sph_nointer b/tests/lowalgos/extcs/circ_sph_nointer new file mode 100644 index 0000000000..413126064f --- /dev/null +++ b/tests/lowalgos/extcs/circ_sph_nointer @@ -0,0 +1,160 @@ +puts "=======================" +puts "Test for Circle/Sphere extrema algorithm" +puts "No intersection cases - one minimum solution should be found" +puts "=======================" +puts "" + +# Make sphere +set x0 0. +set y0 0. +set z0 0. +set sph_radius 10. +sphere s $x0 $y0 $z0 $sph_radius + +# The circles will be made on the distance from the surface +# as intersection of pairs of inner and outer spheres with the plane + +# Set the number of iterations +set nbstep 5 +# Rotation angle +set angle [expr 180. / $nbstep] + +# Set the number of Inner/Outer spheres in one direction +set nbpairs 1 +# Set the delta for the radius of inner circle +set delta_radius [expr $sph_radius * 0.9 / (2 * $nbpairs)] + +# Step for sampling of the circle +set dt [expr [dval 2*pi] / $nbstep] + +# Iteration step +set iStep 1 + +for {set i 1} {$i <= $nbpairs} {incr i} { + # Define the inner circle + set circ_radius [expr $i * $delta_radius] + circle c $x0 $y0 $z0 0 0 1 $circ_radius + + set diff [expr $sph_radius - $circ_radius] + + # Distance between inner sphere on circle and initial sphere + set real_dist [expr $sph_radius - 2*$circ_radius] + + # Circle will be rotated around the line + line rotation_line $x0 $y0 $z0 1 0 0 + + # Line rotation + for {set j 1} {$j <= $nbstep} {incr j} { + rotate rotation_line $x0 $y0 $z0 0 0 1 $angle + + # Get direction for circle's rotation + regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz + + # Circle rotation + copy c c_rotated + for {set k 1} {$k <= $nbstep} {incr k} { + rotate c_rotated 0 0 0 $dx $dy $dz $angle + + # Sampling of the circle + for {set n 1} {$n <= $nbstep} {incr n} { + cvalue c_rotated $n*$dt x1 y1 z1 + + set x1 [dval x1] + set y1 [dval y1] + set z1 [dval z1] + + # Normalize the vector + set dtx [expr ($x1 - $x0) / $circ_radius] + set dty [expr ($y1 - $y0) / $circ_radius] + set dtz [expr ($z1 - $z0) / $circ_radius] + + # Create inner and outer spheres + set iC 1 + + repeat 2 { + sphere s_to_int $x1 $y1 $z1 $circ_radius + + # Define the point closest to the initial sphere + set x_sol [expr $x1 + $iC * $circ_radius * $dtx] + set y_sol [expr $y1 + $iC * $circ_radius * $dty] + set z_sol [expr $z1 + $iC * $circ_radius * $dtz] + + + # Intersect the sphere with the plane originated in closes point + + # Make the sampling of the sphere to define section plane's direction + + bounds s_to_int umin umax vmin vmax + + set du [dval (umax-umin)/$nbstep] + set dv [dval (vmax-vmin)/$nbstep] + + for {set u 1} {$u <= $nbstep} {incr u} { + for {set v 1} {$v <= $nbstep} {incr v} { + + # Get point on surface + svalue s_to_int [dval umin+$u*$du] [dval vmin+$v*$dv] xs ys zs + + # Check that it is not the same point + set sqdist [dval (xs-$x_sol)*(xs-$x_sol)+(ys-$y_sol)*(ys-$y_sol)+(zs-$z_sol)*(zs-$z_sol)] + if {$sqdist < 1.e-16} { + # Skip the sampling point + continue; + } + + # Create the intersection plane + plane p_int $x_sol $y_sol $z_sol [dval xs-$x_sol] [dval ys-$y_sol] [dval zs-$z_sol] + # Intersect the sphere by plane to obtain the circle + foreach c_int [intersect c_inter s_to_int p_int] { + + # Check if the circle contains the point + if {![regexp "Point on curve" [proj $c_int $x_sol $y_sol $z_sol]]} { + if {[lindex [length ext_1] end] >= 1.e-7} { + # run extrema - one of the ends of the curve should be the solution + set log [extrema $c_int s 1] + if {[regexp "prm_1_1" $log]} { + # get parameters of the curve + bounds $c_int fp lp + if {[dval prm_1_1-fp] > 1.e-7 && [dval lp-prm_1_1] > 1.e-7} { + puts "Error: Extrema has failed to find the minimal distance on step $iStep" + } + } else { + puts "Error: Extrema has failed to find the minimal distance on step $iStep" + } + + # save each circle if necessary + # copy $c_int c_$iStep + + incr iStep + continue + } + } + + # Make extrema computation + set log [extrema $c_int s] + + # save each circle if necessary + # copy $c_int c_$iStep + + if {![regexp "ext_1" $log]} { + puts "Error: Extrema has failed to find the minimal distance on step $iStep" + } else { + set ext_dist [lindex [length ext_1] end] + checkreal "Step $iStep, min distance " $ext_dist $real_dist 1.e-7 1.e-7 + } + incr iStep + } + } + } + + # prepare for the outer sphere + set x1 [expr $x1 + 2 * $diff * $dtx] + set y1 [expr $y1 + 2 * $diff * $dty] + set z1 [expr $z1 + 2 * $diff * $dtz] + + set iC -1 + } + } + } + } +} diff --git a/tests/lowalgos/extcs/circ_sph_parallel b/tests/lowalgos/extcs/circ_sph_parallel new file mode 100644 index 0000000000..8625e04caf --- /dev/null +++ b/tests/lowalgos/extcs/circ_sph_parallel @@ -0,0 +1,82 @@ +puts "=======================" +puts "Test for Circle/Sphere extrema algorithm" +puts "Parallel case (center of sphere is on the circle's axis)" +puts "=======================" +puts "" + +# Make sphere +set x0 0. +set y0 0. +set z0 0. +set sph_radius 10. +sphere s $x0 $y0 $z0 $sph_radius + +# Initially the circle will be made at the same place as sphere with different radius +# and will be rotated and shifted many times. +# The distance between circle and sphere is a Abs(sqrt(centers_dist^2 + circ_radius^2) - sph_radius) + +# Number of different radius of initial circle +set nb_radius 7 +# Number of circle's rotations +set nbstep 8 +set angle [expr 180. / $nbstep] + +# Define the shift +set shift_start -3 +set shift_end 3 +set shift 4 + +# Iteration step +set iStep 1 + +for {set i 1} {$i < $nb_radius} {incr i} { + set circ_radius [expr $i*2.] + circle c $x0 $y0 $z0 0 0 1 $circ_radius + + # Circle will be rotated around the line + line rotation_line $x0 $y0 $z0 1 0 0 + # Line rotation + for {set j 1} {$j <= $nbstep} {incr j} { + rotate rotation_line $x0 $y0 $z0 0 0 1 $angle + + # Get direction for circle's rotation + regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz + + # Circle rotation + copy c c_rotated + for {set k 1} {$k <= $nbstep} {incr k} { + rotate c_rotated $x0 $y0 $z0 $dx $dy $dz $angle + + # Add shift of the circle along its own axis + + # Get shift direction + regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dcx dcy dcz + + set dcx [expr $shift*$dcx] + set dcy [expr $shift*$dcy] + set dcz [expr $shift*$dcz] + + # Make the shift + for {set t $shift_start} {$t <= $shift_end} {incr t} { + copy c_rotated c_shifted + translate c_shifted $t*$dcx $t*$dcy $t*$dcz + + set log [extrema c_shifted s] + + # save each circle if necessary + # copy c_shifted c_$iStep + + if {![regexp "Infinite number of extremas" $log]} { + puts "Error: Extrema has not detected the parallel case on step $iStep" + } else { + regexp {Center :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_shifted] full x y z + set centers_dist [expr sqrt($x*$x + $y*$y + $z*$z)] + set real_dist [expr abs(sqrt($centers_dist*$centers_dist + $circ_radius*$circ_radius) - $sph_radius)] + set ext_dist [lindex $log end] + checkreal "Step $iStep, min distance " $ext_dist $real_dist 1.e-7 1.e-7 + } + incr iStep + } + } + } +} diff --git a/tests/lowalgos/extcs/circ_sph_touch b/tests/lowalgos/extcs/circ_sph_touch new file mode 100644 index 0000000000..d4483a4a01 --- /dev/null +++ b/tests/lowalgos/extcs/circ_sph_touch @@ -0,0 +1,93 @@ +puts "=======================" +puts "Test for Circle/Sphere extrema algorithm" +puts "Touch case (circle is just touching the sphere)" +puts "=======================" +puts "" + +# Make sphere +set x0 0. +set y0 0. +set z0 0. +set sph_radius 10. +sphere s $x0 $y0 $z0 $sph_radius + +# Initially the circle will be made at the same place as sphere with different radius +# and will shifted many times to touch the sphere. +# The distance should always be close to zero. + +# Number of different radius of initial circle +set nb_radius 7 +# Number of circle's rotations +set nbstep 8 +set angle [expr 180. / $nbstep] + +# Iteration step +set iStep 1 + +for {set i 1} {$i < $nb_radius} {incr i} { + set circ_radius [expr $i*2.] + if {$circ_radius == $sph_radius} { + set circ_radius [expr $circ_radius + 0.1] + } + circle c $x0 $y0 $z0 0 0 1 $circ_radius + + # Circle will be rotated around the line + line rotation_line $x0 $y0 $z0 1 0 0 + # Line rotation + for {set j 1} {$j <= $nbstep} {incr j} { + rotate rotation_line $x0 $y0 $z0 0 0 1 $angle + + # Get direction for circle's rotation + regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump rotation_line] full dx dy dz + + # Circle rotation + copy c c_rotated + for {set k 1} {$k <= $nbstep} {incr k} { + rotate c_rotated $x0 $y0 $z0 $dx $dy $dz $angle + + # Get translation axis for the circle + regexp {XAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dxx dxy dxz + + # Get rotation plane for translation line + regexp {YAxis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump c_rotated] full dyx dyy dyz + + line translation_line $x0 $y0 $z0 $dxx $dxy $dxz + + for {set n 1} {$n <= $nbstep} {incr n} { + rotate translation_line $x0 $y0 $z0 $dyx $dyy $dyz $angle + + # Get direction for circle's translation + regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump translation_line] full dtx dty dtz + + # Circle's translation + copy c_rotated c_shifted + translate c_shifted $sph_radius*$dtx $sph_radius*$dty $sph_radius*$dtz + + # Shift circle to touch sphere + set shift -1 + repeat 2 { + copy c_shifted c_touch + translate c_touch $shift*$circ_radius*$dxx $shift*$circ_radius*$dxy $shift*$circ_radius*$dxz + + set log [extrema c_touch s] + + # save each circle if necessary + # copy c_touch c_$iStep + + if {![regexp "ext_1" $log]} { + if {![regexp "Extrema 1 is point" $log]} { + puts "Error: Extrema has not detected the touching case on step $iStep" + } else { + puts "Check of Step $iStep, min distance OK" + } + } else { + set ext_dist [lindex [length ext_1] end] + checkreal "Step $iStep, min distance " $ext_dist 0 1.e-7 1.e-7 + } + incr iStep + set shift 1 + } + } + } + } +} diff --git a/tests/lowalgos/grids.list b/tests/lowalgos/grids.list index 6a82606186..381fd9de5d 100644 --- a/tests/lowalgos/grids.list +++ b/tests/lowalgos/grids.list @@ -1,2 +1,3 @@ 001 2dinter 002 bnd +003 extcs diff --git a/tests/prj/base/C5 b/tests/prj/base/C5 index e493727835..47ea07914d 100644 --- a/tests/prj/base/C5 +++ b/tests/prj/base/C5 @@ -1,6 +1,3 @@ -puts "TODO OCC26677 All:An exception was caught" -puts "TODO OCC26677 All:\\*\\* Exception \\*\\*" -puts "TODO OCC26677 All:TEST INCOMPLETE" restore [locate_data_file bug26606_002_extract_C301-full_014_offset.brep] plate restore [locate_data_file bug26606_002_extract_C301-full_014_marker_1.brep] marker set prlist [prj pr marker plate 0.008936 -0.001151 0.999959] \ No newline at end of file diff --git a/tests/prj/base/D9 b/tests/prj/base/D9 index e1bc305bc8..fb4a08353b 100644 --- a/tests/prj/base/D9 +++ b/tests/prj/base/D9 @@ -1,6 +1,3 @@ -puts "TODO OCC26677 All:An exception was caught" -puts "TODO OCC26677 All:\\*\\* Exception \\*\\*" -puts "TODO OCC26677 All:TEST INCOMPLETE" restore [locate_data_file bug26606_004_extract_2015-01-C37_0043_offset.brep] plate restore [locate_data_file bug26606_004_extract_2015-01-C37_0043_marker_2.brep] marker set prlist [prj pr marker plate 0.000490 -0.715789 0.698317] \ No newline at end of file diff --git a/tests/prj/base/E2 b/tests/prj/base/E2 index 344bafceff..f72dabf33d 100644 --- a/tests/prj/base/E2 +++ b/tests/prj/base/E2 @@ -1,6 +1,3 @@ -puts "TODO OCC26677 All:An exception was caught" -puts "TODO OCC26677 All:\\*\\* Exception \\*\\*" -puts "TODO OCC26677 All:TEST INCOMPLETE" restore [locate_data_file bug26606_004_extract_2015-01-C37_0077_offset.brep] plate restore [locate_data_file bug26606_004_extract_2015-01-C37_0077_marker_2.brep] marker set prlist [prj pr marker plate 0.000043 -0.707120 0.707094] \ No newline at end of file diff --git a/tests/prj/base/E7 b/tests/prj/base/E7 index cfa17511c6..ae808436b5 100644 --- a/tests/prj/base/E7 +++ b/tests/prj/base/E7 @@ -1,6 +1,3 @@ -puts "TODO OCC26677 All:An exception was caught" -puts "TODO OCC26677 All:\\*\\* Exception \\*\\*" -puts "TODO OCC26677 All:TEST INCOMPLETE" restore [locate_data_file bug26606_004_extract_2015-01-C37_0084_offset.brep] plate restore [locate_data_file bug26606_004_extract_2015-01-C37_0084_marker_2.brep] marker set prlist [prj pr marker plate -0.048021 -0.305504 0.950979] \ No newline at end of file diff --git a/tests/prj/base/H4 b/tests/prj/base/H4 index 5406a4ff7a..a8a6bd51d0 100644 --- a/tests/prj/base/H4 +++ b/tests/prj/base/H4 @@ -1,6 +1,3 @@ -puts "TODO OCC26677 All:An exception was caught" -puts "TODO OCC26677 All:\\*\\* Exception \\*\\*" -puts "TODO OCC26677 All:TEST INCOMPLETE" restore [locate_data_file bug26606_005_extract_C37-full_0082_offset.brep] plate restore [locate_data_file bug26606_005_extract_C37-full_0082_marker_2.brep] marker set prlist [prj pr marker plate -0.008136 -0.148145 0.988932] \ No newline at end of file -- 2.20.1