diff --git a/src/BOPAlgo/BOPAlgo.cdl b/src/BOPAlgo/BOPAlgo.cdl index 567bb832ad..f59c73f7bd 100644 --- a/src/BOPAlgo/BOPAlgo.cdl +++ b/src/BOPAlgo/BOPAlgo.cdl @@ -52,6 +52,7 @@ is IncompatibilityOfFace, OperationAborted, GeomAbs_C0, + InvalidCurveOnSurface, NotValid end CheckStatus; diff --git a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cdl b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cdl index 47fa9f4943..0c15f28392 100644 --- a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cdl +++ b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cdl @@ -115,6 +115,13 @@ is ---Purpose: Returns (modifiable) mode that means -- checking of problem of continuity of the shape. + CurveOnSurfaceMode(me: in out) + returns Boolean from Standard; + ---C++: return & + ---C++: inline + ---Purpose: Returns (modifiable) mode that means + -- checking of problem of invalid curve on surface. + --- Perform(me: out); ---Purpose: performs analysis @@ -154,6 +161,9 @@ is is protected; TestContinuity(me: out) + is protected; + + TestCurveOnSurface(me: out) is protected; -- TestMergeFace(me: out) @@ -162,20 +172,20 @@ is fields - myShape1 : Shape from TopoDS; - myShape2 : Shape from TopoDS; - myStopOnFirst : Boolean from Standard; - myOperation : Operation from BOPAlgo; - myArgumentTypeMode : Boolean from Standard; - mySelfInterMode : Boolean from Standard; - mySmallEdgeMode : Boolean from Standard; - myRebuildFaceMode : Boolean from Standard; - myTangentMode : Boolean from Standard; - myMergeVertexMode : Boolean from Standard; - myMergeEdgeMode : Boolean from Standard; - myContinuityMode : Boolean from Standard; - myEmpty1,myEmpty2 : Boolean from Standard; - myResult : ListOfCheckResult from BOPAlgo; - - + myShape1 : Shape from TopoDS; + myShape2 : Shape from TopoDS; + myStopOnFirst : Boolean from Standard; + myOperation : Operation from BOPAlgo; + myArgumentTypeMode : Boolean from Standard; + mySelfInterMode : Boolean from Standard; + mySmallEdgeMode : Boolean from Standard; + myRebuildFaceMode : Boolean from Standard; + myTangentMode : Boolean from Standard; + myMergeVertexMode : Boolean from Standard; + myMergeEdgeMode : Boolean from Standard; + myContinuityMode : Boolean from Standard; + myCurveOnSurfaceMode : Boolean from Standard; + myEmpty1, myEmpty2 : Boolean from Standard; + myResult : ListOfCheckResult from BOPAlgo; + end ArgumentAnalyzer; diff --git a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cxx b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cxx index 0ad3abc7a4..c0ee0a0474 100644 --- a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cxx +++ b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.cxx @@ -74,6 +74,7 @@ myTangentMode(Standard_False), myMergeVertexMode(Standard_False), myMergeEdgeMode(Standard_False), myContinuityMode(Standard_False), +myCurveOnSurfaceMode(Standard_False), myEmpty1(Standard_False), myEmpty2(Standard_False) { @@ -196,6 +197,11 @@ void BOPAlgo_ArgumentAnalyzer::Perform() if(!(!myResult.IsEmpty() && myStopOnFirst)) TestContinuity(); } + + if(myCurveOnSurfaceMode) { + if(!(!myResult.IsEmpty() && myStopOnFirst)) + TestCurveOnSurface(); + } } catch(Standard_Failure) { BOPAlgo_CheckResult aResult; @@ -816,3 +822,55 @@ void BOPAlgo_ArgumentAnalyzer::TestContinuity() } } } + +// ================================================================================ +// function: TestCurveOnSurface +// purpose: +// ================================================================================ +void BOPAlgo_ArgumentAnalyzer::TestCurveOnSurface() +{ + Standard_Integer i; + Standard_Real aT, aD, aTolE; + TopExp_Explorer aExpF, aExpE; + // + for(i = 0; i < 2; i++) { + const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2; + if(aS.IsNull()) { + continue; + } + // + aExpF.Init(aS, TopAbs_FACE); + for (; aExpF.More(); aExpF.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current(); + // + aExpE.Init(aF, TopAbs_EDGE); + for (; aExpE.More(); aExpE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current(); + // + if (BOPTools_AlgoTools::ComputeTolerance(aF, aE, aD, aT)) { + aTolE = BRep_Tool::Tolerance(aE); + if (aD > aTolE) { + BOPAlgo_CheckResult aResult; + aResult.SetCheckStatus(BOPAlgo_InvalidCurveOnSurface); + if(i == 0) { + aResult.SetShape1(myShape1); + aResult.AddFaultyShape1(aE); + aResult.AddFaultyShape1(aF); + aResult.SetMaxDistance1(aD); + aResult.SetMaxParameter1(aT); + } + else { + aResult.SetShape2(myShape2); + aResult.AddFaultyShape2(aE); + aResult.AddFaultyShape2(aF); + aResult.SetMaxDistance2(aD); + aResult.SetMaxParameter2(aT); + } + myResult.Append(aResult); + } + } + } + } + } +} + diff --git a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.lxx b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.lxx index e248a057cc..d5102f0302 100644 --- a/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.lxx +++ b/src/BOPAlgo/BOPAlgo_ArgumentAnalyzer.lxx @@ -57,6 +57,10 @@ inline Standard_Boolean& BOPAlgo_ArgumentAnalyzer::ContinuityMode() return myContinuityMode; } +inline Standard_Boolean& BOPAlgo_ArgumentAnalyzer::CurveOnSurfaceMode() +{ + return myCurveOnSurfaceMode; +} // inline Standard_Boolean& BOPAlgo_ArgumentAnalyzer::MergeFaceMode() // { // return myMergeFaceMode; diff --git a/src/BOPAlgo/BOPAlgo_CheckResult.cdl b/src/BOPAlgo/BOPAlgo_CheckResult.cdl index c733ec953c..541a91bffa 100644 --- a/src/BOPAlgo/BOPAlgo_CheckResult.cdl +++ b/src/BOPAlgo/BOPAlgo_CheckResult.cdl @@ -39,7 +39,7 @@ is ---Purpose: sets ancestor shape (tool) for faulty sub-shapes AddFaultyShape2(me: in out; TheShape: Shape from TopoDS); - ---Purpose: adds faulty sub-shapes from tool to a list + ---Purpose: adds faulty sub-shapes from tool to a list GetShape1(me) returns Shape from TopoDS; @@ -66,7 +66,39 @@ is GetCheckStatus(me) returns CheckStatus from BOPAlgo; - ---Purpose: gets status of faulty + ---Purpose: gets status of faulty + + SetMaxDistance1(me:out; + theDist : Real from Standard); + ---Purpose: Sets max distance for the first shape + + SetMaxDistance2(me:out; + theDist : Real from Standard); + ---Purpose: Sets max distance for the second shape + + SetMaxParameter1(me:out; + thePar : Real from Standard); + ---Purpose: Sets the parameter for the first shape + + SetMaxParameter2(me:out; + thePar : Real from Standard); + ---Purpose: Sets the parameter for the second shape + + GetMaxDistance1(me) + returns Real from Standard; + ---Purpose: Returns the distance for the first shape + + GetMaxDistance2(me) + returns Real from Standard; + ---Purpose: Returns the distance for the second shape + + GetMaxParameter1(me) + returns Real from Standard; + ---Purpose: Returns the parameter for the fircst shape + + GetMaxParameter2(me) + returns Real from Standard; + ---Purpose: Returns the parameter for the second shape fields @@ -74,6 +106,10 @@ fields myShape2 : Shape from TopoDS; myStatus : CheckStatus from BOPAlgo; myFaulty1 : ListOfShape from BOPCol; - myFaulty2 : ListOfShape from BOPCol; + myFaulty2 : ListOfShape from BOPCol; + myMaxDist1 : Real from Standard; + myMaxDist2 : Real from Standard; + myMaxPar1 : Real from Standard; + myMaxPar2 : Real from Standard; end CheckResult; diff --git a/src/BOPAlgo/BOPAlgo_CheckResult.cxx b/src/BOPAlgo/BOPAlgo_CheckResult.cxx index 2e0fd35013..9a87b82ca0 100644 --- a/src/BOPAlgo/BOPAlgo_CheckResult.cxx +++ b/src/BOPAlgo/BOPAlgo_CheckResult.cxx @@ -19,7 +19,13 @@ // function: BOPAlgo_CheckResult() // purpose: //======================================================================= -BOPAlgo_CheckResult::BOPAlgo_CheckResult() : myStatus(BOPAlgo_CheckUnknown) +BOPAlgo_CheckResult::BOPAlgo_CheckResult() +: + myStatus(BOPAlgo_CheckUnknown), + myMaxDist1(0.), + myMaxDist2(0.), + myMaxPar1(0.), + myMaxPar2(0.) { } @@ -72,3 +78,43 @@ BOPAlgo_CheckStatus BOPAlgo_CheckResult::GetCheckStatus() const { return myStatus; } + +void BOPAlgo_CheckResult::SetMaxDistance1(const Standard_Real theDist) +{ + myMaxDist1 = theDist; +} + +void BOPAlgo_CheckResult::SetMaxDistance2(const Standard_Real theDist) +{ + myMaxDist2 = theDist; +} + +void BOPAlgo_CheckResult::SetMaxParameter1(const Standard_Real thePar) +{ + myMaxPar1 = thePar; +} + +void BOPAlgo_CheckResult::SetMaxParameter2(const Standard_Real thePar) +{ + myMaxPar2 = thePar; +} + +Standard_Real BOPAlgo_CheckResult::GetMaxDistance1() const +{ + return myMaxDist1; +} + +Standard_Real BOPAlgo_CheckResult::GetMaxDistance2() const +{ + return myMaxDist2; +} + +Standard_Real BOPAlgo_CheckResult::GetMaxParameter1() const +{ + return myMaxPar1; +} + +Standard_Real BOPAlgo_CheckResult::GetMaxParameter2() const +{ + return myMaxPar2; +} diff --git a/src/BOPTest/BOPTest_CheckCommands.cxx b/src/BOPTest/BOPTest_CheckCommands.cxx index c724cd5019..6ff8ae46b7 100644 --- a/src/BOPTest/BOPTest_CheckCommands.cxx +++ b/src/BOPTest/BOPTest_CheckCommands.cxx @@ -20,6 +20,11 @@ #include +#include + +#include +#include + #include #include #include @@ -37,6 +42,8 @@ #include #include +#include + #include // static @@ -44,10 +51,15 @@ static const Standard_Integer, const BOPCol_ListOfShape&, Standard_Integer& , - Draw_Interpretor&); + Draw_Interpretor&, + Standard_Boolean bCurveOnSurf = Standard_False, + Standard_Real aMaxDist = 0., + Standard_Real aMaxParameter = 0.); // static Standard_Integer bopcheck (Draw_Interpretor&, Standard_Integer, const char** ); static Standard_Integer bopargcheck(Draw_Interpretor&, Standard_Integer, const char** ); +static Standard_Integer xdistef(Draw_Interpretor&, Standard_Integer, const char** ); +static Standard_Integer checkcurveonsurf (Draw_Interpretor&, Standard_Integer, const char**); //======================================================================= //function : CheckCommands @@ -69,6 +81,12 @@ void BOPTest::CheckCommands(Draw_Interpretor& theCommands) theCommands.Add("bopargcheck" , "Use bopargcheck without parameters to get ", __FILE__, bopargcheck, g); + theCommands.Add ("xdistef" , + "Use xdistef edge face", + __FILE__, xdistef, g); + theCommands.Add("checkcurveonsurf", + "checkcurveonsurf shape", + __FILE__, checkcurveonsurf, g); } //======================================================================= //class : BOPTest_Interf @@ -306,14 +324,14 @@ Standard_Integer bopcheck (Draw_Interpretor& di, //function : bopargcheck //purpose : //======================================================================= -Standard_Integer bopargcheck (Draw_Interpretor& di, - Standard_Integer n, +Standard_Integer bopargcheck (Draw_Interpretor& di, + Standard_Integer n, const char** a ) { if (n<2) { di << "\n"; di << " Use >bopargcheck Shape1 [[Shape2] "; - di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P]] [#BF]" << "\n" << "\n"; + di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P|C|S]] [#BF]" << "\n" << "\n"; di << " -" << "\n"; di << " F (fuse)" << "\n"; di << " O (common)" << "\n"; @@ -333,6 +351,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, di << " I (disable self-interference test)" << "\n"; di << " P (disable shape type test)" << "\n"; di << " C (disable test for shape continuity)" << "\n"; + di << " S (disable curve on surface check)" << "\n"; di << " For example: \"bopargcheck s1 s2 /RI\" disables "; di << "small edge detection and self-intersection detection" << "\n"; di << " default - all options are enabled" << "\n" << "\n"; @@ -416,11 +435,12 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, aChecker.SetShape1(aS1); // set default options (always tested!) for single and couple shapes - aChecker.ArgumentTypeMode() = Standard_True; - aChecker.SelfInterMode() = Standard_True; - aChecker.SmallEdgeMode() = Standard_True; - aChecker.RebuildFaceMode() = Standard_True; - aChecker.ContinuityMode() = Standard_True; + aChecker.ArgumentTypeMode() = Standard_True; + aChecker.SelfInterMode() = Standard_True; + aChecker.SmallEdgeMode() = Standard_True; + aChecker.RebuildFaceMode() = Standard_True; + aChecker.ContinuityMode() = Standard_True; + aChecker.CurveOnSurfaceMode() = Standard_True; // test & set options and operation for two shapes if(!aS22.IsNull()) { @@ -488,6 +508,9 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, else if(a[indxOP][ind] == 'C' || a[indxOP][ind] == 'c') { aChecker.ContinuityMode() = Standard_False; } + else if(a[indxOP][ind] == 'S' || a[indxOP][ind] == 's') { + aChecker.CurveOnSurfaceMode() = Standard_False; + } else { di << "Error: invalid test option(s)!" << "\n"; di << "Type bopargcheck without arguments for more information" << "\n"; @@ -538,6 +561,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0; Standard_Integer S1_OpAb = 0, S2_OpAb = 0; Standard_Integer S1_C0 = 0, S2_C0 = 0, S1_C0All = 0, S2_C0All = 0; + Standard_Integer S1_COnS = 0, S2_COnS = 0, S1_COnSAll = 0, S2_COnSAll = 0; Standard_Boolean hasUnknown = Standard_False; TCollection_AsciiString aS1SIBaseName("s1si_"); @@ -546,12 +570,14 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, TCollection_AsciiString aS1BVBaseName("s1bv_"); TCollection_AsciiString aS1BEBaseName("s1be_"); TCollection_AsciiString aS1C0BaseName("s1C0_"); + TCollection_AsciiString aS1COnSBaseName("s1COnS_"); TCollection_AsciiString aS2SIBaseName("s2si_"); TCollection_AsciiString aS2SEBaseName("s2se_"); TCollection_AsciiString aS2BFBaseName("s2bf_"); TCollection_AsciiString aS2BVBaseName("s2bv_"); TCollection_AsciiString aS2BEBaseName("s2be_"); TCollection_AsciiString aS2C0BaseName("s2C0_"); + TCollection_AsciiString aS2COnSBaseName("s2COnS_"); for(; anIt.More(); anIt.Next()) { const BOPAlgo_CheckResult& aResult = anIt.Value(); @@ -656,6 +682,27 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, } } break; + case BOPAlgo_InvalidCurveOnSurface: { + if(!aSS1.IsNull()) { + S1_COnS++; + if(isL1) { + Standard_Real aMaxDist = aResult.GetMaxDistance1(); + Standard_Real aMaxParameter = aResult.GetMaxParameter1(); + MakeShapeForFullOutput(aS1COnSBaseName, S1_COnS, aLS1, S1_COnSAll, di, + Standard_True, aMaxDist, aMaxParameter); + } + } + if(!aSS2.IsNull()) { + S2_COnS++; + if(isL2) { + Standard_Real aMaxDist = aResult.GetMaxDistance2(); + Standard_Real aMaxParameter = aResult.GetMaxParameter2(); + MakeShapeForFullOutput(aS2COnSBaseName, S2_COnS, aLS2, S2_COnSAll, di, + Standard_True, aMaxDist, aMaxParameter); + } + } + } + break; case BOPAlgo_OperationAborted: { if(!aSS1.IsNull()) S1_OpAb++; if(!aSS2.IsNull()) S2_OpAb++; @@ -669,9 +716,9 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, } // switch }// faulties - Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0; + Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0 + S1_COnS; FS1 += (S1_BadType != 0) ? 1 : 0; - Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0; + Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0 + S2_COnS; FS2 += (S2_BadType != 0) ? 1 : 0; // output for first shape @@ -750,6 +797,17 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, di << " Cases(" << S1_C0 << ") Total shapes(" << S1_C0All << ")" << "\n"; else di << "\n"; + + Standard_CString CString17; + if (S1_COnS != 0) + CString17="YES"; + else + CString17="NO"; + di << "Invalid Curve on Surface : " << CString17; + if(S1_COnS != 0) + di << " Cases(" << S1_COnS << ") Total shapes(" << S1_COnSAll << ")" << "\n"; + else + di << "\n"; } // output for second shape @@ -831,6 +889,17 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, else di << "\n"; + Standard_CString CString18; + if (S2_COnS != 0) + CString18="YES"; + else + CString18="NO"; + di << "Invalid Curve on Surface : " << CString18; + if(S2_COnS != 0) + di << " Cases(" << S2_COnS << ") Total shapes(" << S2_COnSAll << ")" << "\n"; + else + di << "\n"; + // warning di << "\n"; if(hasUnknown) @@ -841,15 +910,182 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, return 0; } + +//======================================================================= +//function : xdistef +//purpose : +//======================================================================= +Standard_Integer xdistef(Draw_Interpretor& di, + Standard_Integer n, + const char** a) +{ + if(n < 3) { + di << "Use efmaxdist edge face\n"; + return 1; + } + // + const TopoDS_Shape aS1 = DBRep::Get(a[1]); + const TopoDS_Shape aS2 = DBRep::Get(a[2]); + // + if (aS1.IsNull() || aS2.IsNull()) { + di << "null shapes\n"; + return 1; + } + // + if (aS1.ShapeType() != TopAbs_EDGE || + aS2.ShapeType() != TopAbs_FACE) { + di << "type mismatch\n"; + return 1; + } + // + Standard_Real aMaxDist = 0.0, aMaxPar = 0.0; + // + const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&aS1; + const TopoDS_Face& aFace = *(TopoDS_Face*)&aS2; + // + if(!BOPTools_AlgoTools::ComputeTolerance + (aFace, anEdge, aMaxDist, aMaxPar)) { + di << "Tolerance cannot be computed\n"; + return 1; + } + // + di << "Max Distance = " << aMaxDist + << "; Parameter on curve = " << aMaxPar << "\n"; + // + return 0; +} + +//======================================================================= +//function : checkcurveonsurf +//purpose : +//======================================================================= +Standard_Integer checkcurveonsurf(Draw_Interpretor& di, + Standard_Integer n, + const char** a) +{ + if (n != 2) { + di << "use checkcurveonsurf shape\n"; + return 1; + } + // + TopoDS_Shape aS = DBRep::Get(a[1]); + if (aS.IsNull()) { + di << "null shape\n"; + return 1; + } + // + Standard_Integer nE, nF, anECounter, aFCounter; + Standard_Real aT, aTolE, aD, aDMax; + TopExp_Explorer aExpF, aExpE; + char buf[200], aFName[10], anEName[10]; + NCollection_DataMap aDMETol; + BOPCol_DataMapOfShapeInteger aMSI; + // + anECounter = 0; + aFCounter = 0; + // + aExpF.Init(aS, TopAbs_FACE); + for (; aExpF.More(); aExpF.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current(); + // + aExpE.Init(aF, TopAbs_EDGE); + for (; aExpE.More(); aExpE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current(); + // + if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) { + continue; + } + // + aTolE = BRep_Tool::Tolerance(aE); + if (aDMax < aTolE) { + continue; + } + // + if (aDMETol.IsBound(aE)) { + aD = aDMETol.Find(aE); + if (aDMax > aD) { + aDMETol.UnBind(aE); + aDMETol.Bind(aE, aDMax); + } + } + else { + aDMETol.Bind(aE, aDMax); + } + // + if (anECounter == 0) { + di << "Invalid curves on surface:\n"; + } + // + if (aMSI.IsBound(aE)) { + nE = aMSI.Find(aE); + } + else { + nE = anECounter; + aMSI.Bind(aE, nE); + ++anECounter; + } + // + if (aMSI.IsBound(aF)) { + nF = aMSI.Find(aF); + } else { + nF = aFCounter; + aMSI.Bind(aF, nF); + ++aFCounter; + } + // + sprintf(anEName, "e_%d", nE); + sprintf(aFName , "f_%d", nF); + sprintf(buf, "edge %s on face %s (max dist: %3.16f, parameter on curve: %3.16f)\n", + anEName, aFName, aDMax, aT); + di << buf; + // + DBRep::Set(anEName, aE); + DBRep::Set(aFName , aF); + } + } + // + if (anECounter > 0) { + di << "\n\nSugestions to fix the shape:\n"; + di << "explode " << a[1] << " e;\n"; + // + TopTools_MapOfShape M; + aExpE.Init(aS, TopAbs_EDGE); + for (anECounter = 0; aExpE.More(); aExpE.Next()) { + const TopoDS_Shape& aE = aExpE.Current(); + if (!M.Add(aE)) { + continue; + } + ++anECounter; + // + if (!aDMETol.IsBound(aE)) { + continue; + } + // + aTolE = aDMETol.Find(aE); + aTolE *= 1.001; + sprintf(buf, "settolerance %s_%d %3.16f;\n", a[1], anECounter, aTolE); + di << buf; + } + } + else { + di << "This shape seems to be OK.\n"; + } + // + return 0; +} + //======================================================================= //function : MakeShapeForFullOutput //purpose : //======================================================================= void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName, const Standard_Integer aIndex, - const BOPCol_ListOfShape & aList, + const BOPCol_ListOfShape & aList, Standard_Integer& aCount, - Draw_Interpretor& di) + Draw_Interpretor& di, + Standard_Boolean bCurveOnSurf, + Standard_Real aMaxDist, + Standard_Real aMaxParameter) { TCollection_AsciiString aNum(aIndex); TCollection_AsciiString aName = aBaseName + aNum; @@ -865,6 +1101,14 @@ void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName, BB.Add(cmp, aS); aCount++; } - di << "Made faulty shape: " << name << "\n"; + di << "Made faulty shape: " << name; + // + if (bCurveOnSurf) { + di << " (MaxDist = " << aMaxDist + << ", MaxPar = " << aMaxParameter << ")"; + } + // + di << "\n"; + // DBRep::Set(name, cmp); } diff --git a/src/BOPTools/BOPTools_AlgoTools.cdl b/src/BOPTools/BOPTools_AlgoTools.cdl index 6425c57294..923763a79d 100644 --- a/src/BOPTools/BOPTools_AlgoTools.cdl +++ b/src/BOPTools/BOPTools_AlgoTools.cdl @@ -33,6 +33,9 @@ uses Wire from TopoDS, Shell from TopoDS, Solid from TopoDS, + Curve from Geom, + Curve from Geom2d, + Surface from Geom, -- BaseAllocator from BOPCol, ListOfShape from BOPCol, @@ -290,44 +293,41 @@ is theRunParallel: Boolean from Standard=Standard_False); ---Purpose: - --- Provides valid values of tolerances for the shape - --- is max value of the tolerance that can be - --- accepted for correction. If real value of the tolerance - --- will be greater than , the correction does not - --- perform. - --- + -- Provides valid values of tolerances for the shape + -- is max value of the tolerance that can be + -- accepted for correction. If real value of the tolerance + -- will be greater than , the correction does not + -- perform. + CorrectCurveOnSurface (myclass; theS: Shape from TopoDS; theTolMax: Real from Standard =0.0001; theRunParallel: Boolean from Standard=Standard_False); ---Purpose: - --- Provides valid values of tolerances for the shape - --- in terms of BRepCheck_InvalidCurveOnSurface. - --- + -- Provides valid values of tolerances for the shape + -- in terms of BRepCheck_InvalidCurveOnSurface. + CorrectPointOnCurve (myclass; theS: Shape from TopoDS; theTolMax: Real from Standard =0.0001; theRunParallel: Boolean from Standard=Standard_False); ---Purpose: - --- Provides valid values of tolerances for the shape - --- in terms of BRepCheck_InvalidPointOnCurve. - --- - --fields + -- Provides valid values of tolerances for the shape + -- in terms of BRepCheck_InvalidPointOnCurve. - --copy from BOPTools_AlgoTools.cdl MakeNewVertex (myclass; aP1 : Pnt from gp; aTol: Real from Standard; aNewVertex:out Vertex from TopoDS); ---Purpose: - --- Make a vertex using 3D-point and 3D-tolerance value - --- + -- Make a vertex using 3D-point and 3D-tolerance value + MakeNewVertex (myclass; aV1,aV2: Vertex from TopoDS; aNewVertex:out Vertex from TopoDS); ---Purpose: - --- Make a vertex using couple of vertices - --- + -- Make a vertex using couple of vertices + MakeNewVertex (myclass; aE1: Edge from TopoDS; aP1: Real from Standard; @@ -335,25 +335,25 @@ is aP2: Real from Standard; aNewVertex:out Vertex from TopoDS); ---Purpose: - --- Make a vertex in place of intersection between two edges - --- with parameters - --- + -- Make a vertex in place of intersection between two edges + -- with parameters + MakeNewVertex (myclass; aE1: Edge from TopoDS; aP1: Real from Standard; aF2: Face from TopoDS; aNewVertex:out Vertex from TopoDS); ---Purpose: - --- Make a vertex in place of intersection between the edge - --- with parameter and the face - --- + -- Make a vertex in place of intersection between the edge + -- with parameter and the face + PointOnEdge (myclass; aEdge: Edge from TopoDS; aPrm: Real from Standard; aP:out Pnt from gp); ---Purpose: - --- Compute a 3D-point on the edge at parameter - --- + -- Compute a 3D-point on the edge at parameter + MakeSplitEdge (myclass; aE1: Edge from TopoDS; aV1: Vertex from TopoDS; @@ -362,9 +362,9 @@ is aP2: Real from Standard; aNewEdge:out Edge from TopoDS); ---Purpose: - --- Make the edge from base edge and two vertices - --- at parameters - --- + -- Make the edge from base edge and two vertices + -- at parameters + MakeSectEdge (myclass; aIC: Curve from IntTools; aV1: Vertex from TopoDS; @@ -373,35 +373,34 @@ is aP2: Real from Standard; aNewEdge:out Edge from TopoDS); ---Purpose: - --- Make the edge from 3D-Curve and two vertices - --- at parameters - --- + -- Make the edge from 3D-Curve and two vertices + -- at parameters + UpdateVertex (myclass; aIC: Curve from IntTools; aT : Real from Standard; aV : Vertex from TopoDS); ---Purpose: - --- Update the tolerance value for vertex - --- taking into account the fact that lays on - --- the curve - --- + -- Update the tolerance value for vertex + -- taking into account the fact that lays on + -- the curve + UpdateVertex (myclass; aE : Edge from TopoDS; aT : Real from Standard; aV : Vertex from TopoDS); ---Purpose: - --- Update the tolerance value for vertex - --- taking into account the fact that lays on - --- the edge - --- + -- Update the tolerance value for vertex + -- taking into account the fact that lays on + -- the edge + UpdateVertex (myclass; aVF : Vertex from TopoDS; aVN : Vertex from TopoDS); ---Purpose: - --- Update the tolerance value for vertex - --- taking into account the fact that should - --- cover tolerance zone of - --- + -- Update the tolerance value for vertex + -- taking into account the fact that should + -- cover tolerance zone of CorrectRange (myclass; aE1: Edge from TopoDS; @@ -409,18 +408,17 @@ is aSR: Range from IntTools; aNewSR:out Range from IntTools); ---Purpose: - --- Correct shrunk range taking into account 3D-curve - --- resolution and corresp. tolerances' values of , - --- + -- Correct shrunk range taking into account 3D-curve + -- resolution and corresp. tolerances' values of , + CorrectRange (myclass; aE: Edge from TopoDS; aF: Face from TopoDS; aSR: Range from IntTools; aNewSR:out Range from IntTools); ---Purpose: - --- Correct shrunk range taking into account 3D-curve - --- resolution and corresp. tolerances' values of , - --- + -- Correct shrunk range taking into account 3D-curve + -- resolution and corresp. tolerances' values of , IsBlockInOnFace(myclass; aShR : Range from IntTools; @@ -429,29 +427,28 @@ is aContext:out Context from IntTools) returns Boolean from Standard; ---Purpose: - --- Returns TRUE if PaveBlock lays on the face , i.e - --- the is IN or ON in 2D of + -- Returns TRUE if PaveBlock lays on the face , i.e + -- the is IN or ON in 2D of IsMicroEdge(myclass; theEdge : Edge from TopoDS; theContext : Context from IntTools) returns Boolean from Standard; ---Purpose: - --- Checks if it is possible to compute shrunk range for the edge . - --- + -- Checks if it is possible to compute shrunk range for the edge . + -- CorrectShapeTolerances (myclass; theS: Shape from TopoDS; theRunParallel: Boolean from Standard=Standard_False); ---Purpose: - --- Corrects tolerance values of the sub-shapes of the shape if needed. - --- + -- Corrects tolerance values of the sub-shapes of the shape if needed. Dimension(myclass; theS:Shape from TopoDS) returns Integer from Standard; ---Purpose: - --- Retutns dimension of the shape . + -- Retutns dimension of the shape . IsOpenShell(myclass; theShell:Shell from TopoDS) @@ -461,6 +458,26 @@ is IsInvertedSolid(myclass; theSolid:Solid from TopoDS) returns Boolean from Standard; - ---Purpose: Returns true if the solid is inverted + ---Purpose: Returns true if the solid is inverted + ComputeTolerance(myclass; + theCurve3D : Curve from Geom; + theCurve2D : Curve from Geom2d; + theSurf : Surface from Geom; + theMaxDist : out Real from Standard; + theMaxPar : out Real from Standard) + returns Boolean from Standard; + ---Purpose: + -- Computes the max distance between points + -- taken from 3D and 2D curves by the same parameter + + ComputeTolerance(myclass; + theFace : Face from TopoDS; + theEdge : Edge from TopoDS; + theMaxDist : out Real from Standard; + theMaxPar : out Real from Standard) + returns Boolean from Standard; + ---Purpose: + -- Computes the necessary value of the tolerance for the edge + end AlgoTools; diff --git a/src/BOPTools/BOPTools_AlgoTools_1.cxx b/src/BOPTools/BOPTools_AlgoTools_1.cxx index a49449402e..ade9bc9d9d 100644 --- a/src/BOPTools/BOPTools_AlgoTools_1.cxx +++ b/src/BOPTools/BOPTools_AlgoTools_1.cxx @@ -311,6 +311,118 @@ typedef BOPCol_TBBCnt BOPTools_CETCnt; // +// +//======================================================================= +//class : BOPTools_CheckCurveOnSurface +//purpose : it is used to check the curve on the surface +//======================================================================= +#include +#include +#include +#include + +class BOPTools_CheckCurveOnSurface : + public math_MultipleVarFunctionWithHessian +{ + public: + BOPTools_CheckCurveOnSurface(BOPTools_CheckCurveOnSurface&); + BOPTools_CheckCurveOnSurface(const Handle(Geom_Curve)& theC3D, + const Handle(Geom2d_Curve)& theC2D, + const Handle(Geom_Surface)& theSurf) + : + my3DCurve(theC3D), + my2DCurve(theC2D), + mySurf(theSurf) + { + } + // + virtual Standard_Integer NbVariables() const { + return 1; + } + // + virtual Standard_Boolean Value(const math_Vector& theX, + Standard_Real& theFVal) { + try { + const Standard_Real aPar = theX(1); + gp_Pnt aP1, aP2; + gp_Pnt2d aP2d; + my3DCurve->D0(aPar, aP1); + my2DCurve->D0(aPar, aP2d); + mySurf->D0(aP2d.X(), aP2d.Y(), aP2); + // + theFVal = -1.0*aP1.SquareDistance(aP2); + } + catch(...) { + return Standard_False; + } + // + return Standard_True; + } + // + virtual Standard_Integer GetStateNumber() { + return 0; + } + // + virtual Standard_Boolean Gradient(const math_Vector& theX, + math_Vector& theGrad) { + try { + const Standard_Real aPar = theX(1); + + gp_Pnt aP1, aP2; + gp_Vec aDC3D, aDSU, aDSV; + gp_Pnt2d aP2d; + gp_Vec2d aDC2D; + + my3DCurve->D1(aPar, aP1, aDC3D); + my2DCurve->D1(aPar, aP2d, aDC2D); + mySurf->D1(aP2d.X(), aP2d.Y(), aP2, aDSU, aDSV); + + aP1.SetXYZ(aP1.XYZ() - aP2.XYZ()); + aP2.SetXYZ(aDC3D.XYZ() - aDC2D.X()*aDSU.XYZ() - aDC2D.Y()*aDSV.XYZ()); + + theGrad(1) = -2.0*aP1.XYZ().Dot(aP2.XYZ()); + } + catch(...) { + return Standard_False; + } + + return Standard_True; + } + // + virtual Standard_Boolean Values(const math_Vector& theX, + Standard_Real& theVal, + math_Vector& theGrad) { + if(!Value(theX, theVal)) + return Standard_False; + + if(!Gradient(theX, theGrad)) + return Standard_False; + + return Standard_True; + } + // + virtual Standard_Boolean Values(const math_Vector& theX, + Standard_Real& theVal, + math_Vector& theGrad, + math_Matrix& theHessian) { + if(!Value(theX, theVal)) + return Standard_False; + + if(!Gradient(theX, theGrad)) + return Standard_False; + + theHessian(1,1) = theGrad(1); + + return Standard_True; + } + // + private: + Handle(Geom_Curve) my3DCurve; + Handle(Geom2d_Curve) my2DCurve; + Handle(Geom_Surface) mySurf; +}; +//======================================================================= +// //======================================================================= // Function : CorrectTolerances // purpose : @@ -1037,3 +1149,237 @@ void UpdateEdges(const TopoDS_Face& aF) } } } +//======================================================================= +// Function : MinComputing +// purpose : +//======================================================================= +static Standard_Boolean MinComputing( BOPTools_CheckCurveOnSurface& theFunction, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Real theEpsilon, //1.0e-3 + Standard_Real & theBestValue, + Standard_Real & theBestParameter) +{ + //Standard_Real aPrevValue = theBestValue; + const Standard_Real aStepMin = 1.0e-2; + math_Vector aFirstV(1, 1), aLastV(1, 1), anOutputParam(1, 1); + aFirstV(1) = theFirst; + aLastV(1) = theLast; + + math_GlobOptMin aFinder(&theFunction, aFirstV, aLastV); + aFinder.SetTol(aStepMin, theEpsilon); + aFinder.Perform(); + + const Standard_Integer aNbExtr = aFinder.NbExtrema(); + for(Standard_Integer i = 1; i <= aNbExtr; i++) + { + Standard_Real aValue = 0.0; + aFinder.Points(i, anOutputParam); + theFunction.Value(anOutputParam, aValue); + + if(aValue < theBestValue) + { + theBestValue = aValue; + theBestParameter = anOutputParam(1); + } + } + + return Standard_True; +} + +//======================================================================= +// Function : ComputeTolerance +// purpose : +//======================================================================= +Standard_Boolean BOPTools_AlgoTools:: + ComputeTolerance( const Handle(Geom_Curve)& theCurve3D, + const Handle(Geom2d_Curve)& theCurve2D, + const Handle(Geom_Surface)& theSurf, + Standard_Real& theMaxDist, + Standard_Real& theMaxPar) +{ + if (theCurve3D.IsNull() || + theCurve2D.IsNull() || + theSurf.IsNull()) { + return Standard_False; + } + + const Standard_Real anEpsilonRange = 1.0e-3, aMinDelta = 1.0e-5; + + // + try { + Standard_Real aFirst = theCurve3D->FirstParameter(), + aLast = theCurve3D->LastParameter(); + + BOPTools_CheckCurveOnSurface aFunc(theCurve3D, theCurve2D, theSurf); + // + math_Vector anOutputParam(1, 1); + anOutputParam(1) = theMaxPar = aFirst; + // + theMaxDist = 0.; + MinComputing(aFunc, aFirst, aLast, anEpsilonRange, theMaxDist, theMaxPar); + + Standard_Integer aNbIteration = 100; + Standard_Boolean aStatus = Standard_True; + while((aNbIteration-- >= 0) && aStatus) + { + Standard_Real aValue = theMaxDist, aParam = theMaxPar; + Standard_Real aBP = theMaxPar - aMinDelta; + MinComputing(aFunc, aFirst, aBP, anEpsilonRange, theMaxDist, theMaxPar); + + if(theMaxDist < aValue) + { + aLast = aBP; + aStatus = Standard_True; + } + else + { + theMaxDist = aValue; + theMaxPar = aParam; + aStatus = Standard_False; + } + + if(!aStatus) + { + aBP = theMaxPar + aMinDelta; + MinComputing(aFunc, aBP, aLast, 1.0e-3, theMaxDist, theMaxPar); + + if(theMaxDist < aValue) + { + aFirst = aBP; + aStatus = Standard_True; + } + else + { + theMaxDist = aValue; + theMaxPar = aParam; + aStatus = Standard_False; + } + } + } + + theMaxDist = sqrt(Abs(theMaxDist)); + } + catch (...) { + return Standard_False; + } + // + return Standard_True; +} + +//======================================================================= +// Function : ComputeTolerance +// purpose : +//======================================================================= +Standard_Boolean BOPTools_AlgoTools::ComputeTolerance + (const TopoDS_Face& theFace, + const TopoDS_Edge& theEdge, + Standard_Real& theMaxDist, + Standard_Real& theParameter) +{ + Standard_Boolean bRet; + Standard_Real aT, aD, aFirst, aLast; + TopLoc_Location aLocC, aLocS; + // + theMaxDist = 0.; + theParameter = 0.; + bRet = Standard_False; + // + const Handle(BRep_TEdge)& aTE = *((Handle(BRep_TEdge)*)&theEdge.TShape()); + //The edge is considered to be same range and not degenerated + if ((!aTE->SameRange() && aTE->SameParameter()) || + aTE->Degenerated()) { + return bRet; + } + // + Handle(Geom_Curve) aC = Handle(Geom_Curve):: + DownCast(BRep_Tool::Curve(theEdge, aLocC, aFirst, aLast)->Copy()); + aC = new Geom_TrimmedCurve(aC, aFirst, aLast); + aC->Transform(aLocC.Transformation()); + // + const Handle(Geom_Surface)& aSurfF = BRep_Tool::Surface(theFace, aLocS); + const Handle(Geom_Surface)& aSurf = Handle(Geom_Surface):: + DownCast(aSurfF->Copy()->Transformed(aLocS.Transformation())); + // + Standard_Boolean isPCurveFound = Standard_False; + BRep_ListIteratorOfListOfCurveRepresentation itcr(aTE->Curves()); + for (; itcr.More(); itcr.Next()) { + const Handle(BRep_CurveRepresentation)& cr = itcr.Value(); + if (!(cr->IsCurveOnSurface(aSurfF, aLocS.Predivided(theEdge.Location())))) { + continue; + } + isPCurveFound = Standard_True; + // + Handle(Geom2d_Curve) aC2d = Handle(Geom2d_Curve):: + DownCast(cr->PCurve()->Copy()); + aC2d = new Geom2d_TrimmedCurve(aC2d, aFirst, aLast); + // + if(BOPTools_AlgoTools::ComputeTolerance + (aC, aC2d, aSurf, aD, aT)) { + bRet = Standard_True; + if (aD > theMaxDist) { + theMaxDist = aD; + theParameter = aT; + } + } + // + if (cr->IsCurveOnClosedSurface()) { + Handle(Geom2d_Curve) aC2d = Handle(Geom2d_Curve):: + DownCast(cr->PCurve2()->Copy()); + aC2d = new Geom2d_TrimmedCurve(aC2d, aFirst, aLast); + // + if(BOPTools_AlgoTools::ComputeTolerance + (aC, aC2d, aSurf, aD, aT)) { + bRet = Standard_True; + if (aD > theMaxDist) { + theMaxDist = aD; + theParameter = aT; + } + } + } + } + // + if (isPCurveFound) { + return bRet; + } + // + Handle(Geom_Plane) aPlane; + Handle(Standard_Type) dtyp = aSurf->DynamicType(); + // + if (dtyp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { + aPlane = Handle(Geom_Plane):: + DownCast(Handle(Geom_RectangularTrimmedSurface):: + DownCast(aSurf)->BasisSurface()->Copy()); + } + else { + aPlane = Handle(Geom_Plane)::DownCast(aSurf->Copy()); + } + // + if (aPlane.IsNull()) { // not a plane + return bRet; + } + // + aPlane = Handle(Geom_Plane)::DownCast(aPlane);// + // + Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(aPlane); + Handle(Geom_Curve) ProjOnPlane = + GeomProjLib::ProjectOnPlane (new Geom_TrimmedCurve(aC, aFirst, aLast), + aPlane, aPlane->Position().Direction(), + Standard_True); + Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(ProjOnPlane); + // + ProjLib_ProjectedCurve proj(GAHS,aHCurve); + Handle(Geom2d_Curve) aC2d = Geom2dAdaptor::MakeCurve(proj); + aC2d = new Geom2d_TrimmedCurve(aC2d, aFirst, aLast); + // + if(BOPTools_AlgoTools::ComputeTolerance + (aC, aC2d, aPlane, aD, aT)) { + bRet = Standard_True; + if (aD > theMaxDist) { + theMaxDist = aD; + theParameter = aT; + } + } + // + return bRet; +} diff --git a/tests/bugs/modalg_5/bug25410 b/tests/bugs/modalg_5/bug25410 new file mode 100755 index 0000000000..61e53cc89a --- /dev/null +++ b/tests/bugs/modalg_5/bug25410 @@ -0,0 +1,23 @@ +puts "============" +puts "OCC25410" +puts "============" +puts "" +###################################################### +# Tool for extended check of validity of the curve on the surface +###################################################### + +pload XSDRAW + +testreadiges [locate_data_file bug25410_Tank8.igs] b1 + +checkcurveonsurf b1 +xdistef e_0 f_0 +bopargcheck b1 /ic #f +bopargcheck b1 /ics #f + + +testreadiges [locate_data_file bug25410_Tank7.igs] b2 +checkcurveonsurf b2 +xdistef e_0 f_0 +bopargcheck b2 /ic #f +bopargcheck b2 /ics #f