1 // Copyright (c) 2021 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <BRepLib_ValidateEdge.hxx>
15
16 #include <Adaptor3d_Curve.hxx>
17 #include <Adaptor3d_CurveOnSurface.hxx>
18 #include <BRepCheck.hxx>
19 #include <Extrema_LocateExtPC.hxx>
20
21 //=============================================================================
22 //function : BRepLib_ValidateEdge
23 //purpose : Constructor
24 //=============================================================================
BRepLib_ValidateEdge(Handle (Adaptor3d_Curve)theReferenceCurve,Handle (Adaptor3d_CurveOnSurface)theOtherCurve,Standard_Boolean theSameParameter)25 BRepLib_ValidateEdge::BRepLib_ValidateEdge(Handle(Adaptor3d_Curve) theReferenceCurve,
26 Handle(Adaptor3d_CurveOnSurface) theOtherCurve,
27 Standard_Boolean theSameParameter):
28 myReferenceCurve(theReferenceCurve),
29 myOtherCurve(theOtherCurve),
30 mySameParameter(theSameParameter),
31 myControlPointsNumber(22),
32 myToleranceForChecking(0),
33 myCalculatedDistance(0),
34 myExitIfToleranceExceeded(Standard_False),
35 myIsDone(Standard_False)
36 { }
37
38 //=============================================================================
39 //function : CheckTolerance
40 //purpose :
41 //=============================================================================
CheckTolerance(Standard_Real theToleranceToCheck)42 Standard_Boolean BRepLib_ValidateEdge::CheckTolerance(Standard_Real theToleranceToCheck)
43 {
44 return correctTolerance(theToleranceToCheck) > myCalculatedDistance;
45 }
46
47 //=============================================================================
48 //function : GetMaxDistance
49 //purpose :
50 //=============================================================================
GetMaxDistance()51 Standard_Real BRepLib_ValidateEdge::GetMaxDistance()
52 {
53 Standard_Real aCorrectedTolerance = myCalculatedDistance * 1.00001;
54 return aCorrectedTolerance;
55 }
56
57 //=============================================================================
58 //function : UpdateTolerance
59 //purpose :
60 //=============================================================================
UpdateTolerance(Standard_Real & theToleranceToUpdate)61 void BRepLib_ValidateEdge::UpdateTolerance(Standard_Real& theToleranceToUpdate)
62 {
63 Standard_Real aCorrectedTolerance = myCalculatedDistance * 1.00001;
64 if (aCorrectedTolerance > theToleranceToUpdate)
65 {
66 theToleranceToUpdate = aCorrectedTolerance;
67 }
68 }
69
70 //=============================================================================
71 //function : correctTolerance
72 //purpose :
73 //=============================================================================
correctTolerance(Standard_Real theTolerance)74 Standard_Real BRepLib_ValidateEdge::correctTolerance(Standard_Real theTolerance)
75 {
76 const Handle(Adaptor3d_Surface)& aSurface = myOtherCurve->GetSurface();
77 Standard_Real aCurvePrecision = BRepCheck::PrecCurve(*myReferenceCurve);
78 Standard_Real aSurfacePrecision = BRepCheck::PrecSurface(aSurface);
79 Standard_Real aToleranceDelta = (aCurvePrecision > aSurfacePrecision) ? aCurvePrecision : aSurfacePrecision;
80 Standard_Real aCorrectedTolerance = theTolerance + aToleranceDelta;
81 return aCorrectedTolerance;
82 }
83
84 //=============================================================================
85 //function : SetExitIfToleranceExceeded
86 //purpose :
87 //=============================================================================
SetExitIfToleranceExceeded(Standard_Real theToleranceForChecking)88 void BRepLib_ValidateEdge::SetExitIfToleranceExceeded(Standard_Real theToleranceForChecking)
89 {
90 myExitIfToleranceExceeded = Standard_True;
91 myToleranceForChecking = correctTolerance(theToleranceForChecking);
92 }
93
94 //=============================================================================
95 //function : Process
96 //purpose :
97 //=============================================================================
Process()98 void BRepLib_ValidateEdge::Process()
99 {
100 myIsDone = Standard_True;
101 Standard_Real aSquareToleranceForChecking = myToleranceForChecking * myToleranceForChecking;
102 Standard_Real aReferenceFirstParam = myReferenceCurve->FirstParameter();
103 Standard_Real aReferenceLastParam = myReferenceCurve->LastParameter();
104 Standard_Real anOtherFirstParam = myOtherCurve->FirstParameter();
105 Standard_Real anOtherLastParam = myOtherCurve->LastParameter();
106 Standard_Real aMaxSquareDistance = 0.;
107
108 Standard_Integer aControlPointsNumber = (myControlPointsNumber < 1) ? 1 : myControlPointsNumber;
109 Standard_Boolean anIsProjection = (!mySameParameter ||
110 Abs(anOtherFirstParam - aReferenceFirstParam) > Precision::PConfusion() ||
111 Abs(anOtherLastParam - aReferenceLastParam) > Precision::PConfusion());
112
113 if (!anIsProjection)
114 {
115 for (Standard_Integer i = 0; i <= aControlPointsNumber; ++i)
116 {
117 Standard_Real aControlPointParam =
118 ((aControlPointsNumber - i) * aReferenceFirstParam + i * aReferenceLastParam) / aControlPointsNumber;
119 gp_Pnt aReferencePoint = myReferenceCurve->Value(aControlPointParam);
120 gp_Pnt anOtherPoint = myOtherCurve->Value(aControlPointParam);
121 Standard_Real aSquareDistance = aReferencePoint.SquareDistance(anOtherPoint);
122 if (aSquareDistance > aMaxSquareDistance)
123 {
124 aMaxSquareDistance = aSquareDistance;
125 }
126 // Stop process for best performance
127 if (myExitIfToleranceExceeded && aMaxSquareDistance > aSquareToleranceForChecking)
128 {
129 myCalculatedDistance = Sqrt(aMaxSquareDistance);
130 return;
131 }
132 }
133 }
134 else
135 {
136 gp_Pnt aReferencePoint = myReferenceCurve->Value(aReferenceFirstParam);
137 gp_Pnt anOtherPoint = myOtherCurve->Value(anOtherFirstParam);
138 Standard_Real aSquareDistance = aReferencePoint.SquareDistance(anOtherPoint);
139 if (aSquareDistance > aMaxSquareDistance)
140 {
141 aMaxSquareDistance = aSquareDistance;
142 }
143 if (myExitIfToleranceExceeded && aMaxSquareDistance > aSquareToleranceForChecking)
144 {
145 myCalculatedDistance = Sqrt(aMaxSquareDistance);
146 return;
147 }
148
149 aReferencePoint = myReferenceCurve->Value(aReferenceLastParam);
150 anOtherPoint = myOtherCurve->Value(anOtherLastParam);
151 aSquareDistance = aReferencePoint.SquareDistance(anOtherPoint);
152 if (aSquareDistance > aMaxSquareDistance)
153 {
154 aMaxSquareDistance = aSquareDistance;
155 }
156 if (myExitIfToleranceExceeded && aMaxSquareDistance > aSquareToleranceForChecking)
157 {
158 myCalculatedDistance = Sqrt(aMaxSquareDistance);
159 return;
160 }
161
162 Extrema_LocateExtPC aReferenceExtrema, anOtherExtrema;
163 aReferenceExtrema.Initialize(*myReferenceCurve, aReferenceFirstParam, aReferenceLastParam, myReferenceCurve->Resolution(Precision::Confusion()));
164 anOtherExtrema.Initialize(*myOtherCurve, anOtherFirstParam, anOtherLastParam, myOtherCurve->Resolution(Precision::Confusion()));
165 for (Standard_Integer i = 1; i < aControlPointsNumber; i++)
166 {
167 Standard_Real aReferenceParam = ((aControlPointsNumber - i) * aReferenceFirstParam + i * aReferenceLastParam) / aControlPointsNumber;
168 gp_Pnt aReferenceExtremaPoint = myReferenceCurve->Value(aReferenceParam);
169 Standard_Real anOtherParam = ((aControlPointsNumber - i) * anOtherFirstParam + i * anOtherLastParam) / aControlPointsNumber;
170 gp_Pnt anOtherExtremaPoint = myOtherCurve->Value(anOtherParam);
171
172 aReferenceExtrema.Perform(anOtherExtremaPoint, aReferenceParam);
173 if (aReferenceExtrema.IsDone())
174 {
175 if (aReferenceExtrema.SquareDistance() > aMaxSquareDistance)
176 {
177 aMaxSquareDistance = aReferenceExtrema.SquareDistance();
178 }
179 if (myExitIfToleranceExceeded && aMaxSquareDistance > aSquareToleranceForChecking)
180 {
181 myCalculatedDistance = Sqrt(aMaxSquareDistance);
182 return;
183 }
184 }
185 else
186 {
187 myIsDone = Standard_False;
188 // Stop process for best performance
189 return;
190 }
191
192 anOtherExtrema.Perform(aReferenceExtremaPoint, anOtherParam);
193 if (anOtherExtrema.IsDone())
194 {
195 if (anOtherExtrema.SquareDistance() > aMaxSquareDistance)
196 {
197 aMaxSquareDistance = anOtherExtrema.SquareDistance();
198 }
199 if (myExitIfToleranceExceeded && aMaxSquareDistance > aSquareToleranceForChecking)
200 {
201 myCalculatedDistance = Sqrt(aMaxSquareDistance);
202 return;
203 }
204 }
205 else
206 {
207 myIsDone = Standard_False;
208 // Stop process for best performance
209 return;
210 }
211 }
212 }
213 myCalculatedDistance = Sqrt(aMaxSquareDistance);
214 }
215