0026383: Incorrect tolerance computing in IntTools_FaceFace::ComputeTolerance()
[occt.git] / src / BRepLib / BRepLib_CheckCurveOnSurface.cxx
CommitLineData
1b7ae951 1// Created by: Eugeny MALTCHIKOV
2// Copyright (c) 2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#include <BRepLib_CheckCurveOnSurface.ixx>
16
17#include <math_GlobOptMin.hxx>
18#include <math_MultipleVarFunctionWithHessian.hxx>
19#include <math_Matrix.hxx>
20
21#include <Geom_Plane.hxx>
22#include <Geom_RectangularTrimmedSurface.hxx>
23#include <Geom_TrimmedCurve.hxx>
24
25#include <Geom2dAdaptor.hxx>
26
27#include <GeomAdaptor_HSurface.hxx>
28#include <GeomAdaptor_HCurve.hxx>
94f71cad 29#include <Geom2dAdaptor_HCurve.hxx>
1b7ae951 30
31#include <GeomProjLib.hxx>
32
33#include <BRep_Tool.hxx>
34#include <BRep_TEdge.hxx>
35#include <BRep_CurveRepresentation.hxx>
36#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
37
38#include <TopLoc_Location.hxx>
39
40#include <ProjLib_ProjectedCurve.hxx>
41
42
43//=======================================================================
44//class : BRepLib_CheckCurveOnSurface_GlobOptFunc
45//purpose : provides necessary methods to be used in math_GlobOptMin
46//=======================================================================
47class BRepLib_CheckCurveOnSurface_GlobOptFunc :
48 public math_MultipleVarFunctionWithHessian
49{
50 public:
51 BRepLib_CheckCurveOnSurface_GlobOptFunc
52 (BRepLib_CheckCurveOnSurface_GlobOptFunc&);
53 BRepLib_CheckCurveOnSurface_GlobOptFunc
54 (const Handle(Geom_Curve)& theC3D,
55 const Handle(Geom2d_Curve)& theC2D,
56 const Handle(Geom_Surface)& theSurf,
57 const Standard_Real theFirst,
58 const Standard_Real theLast)
59 :
1b7ae951 60 myFirst(theFirst),
61 myLast(theLast)
62 {
94f71cad 63 myCurve = new GeomAdaptor_HCurve(theC3D);
64 myPCurve = new Geom2dAdaptor_HCurve(theC2D);
65 mySurf = new GeomAdaptor_HSurface(theSurf);
1b7ae951 66 }
67 //
68 virtual Standard_Integer NbVariables() const {
69 return 1;
70 }
71 //
72 virtual Standard_Boolean Value(const math_Vector& theX,
73 Standard_Real& theFVal) {
74 try {
75 const Standard_Real aPar = theX(1);
76 if (!CheckParameter(aPar))
77 return Standard_False;
78 gp_Pnt aP1, aP2;
79 gp_Pnt2d aP2d;
80 //
81 myCurve->D0(aPar, aP1);
82 myPCurve->D0(aPar, aP2d);
83 mySurf->D0(aP2d.X(), aP2d.Y(), aP2);
84 //
85 theFVal = -1.0*aP1.SquareDistance(aP2);
86 }
87 catch(Standard_Failure) {
88 return Standard_False;
89 }
90 //
91 return Standard_True;
92 }
93 //
94 virtual Standard_Integer GetStateNumber() {
95 return 0;
96 }
97 //
98 virtual Standard_Boolean Gradient(const math_Vector& theX,
99 math_Vector& theGrad) {
100 try {
101 const Standard_Real aPar = theX(1);
102 if (!CheckParameter(aPar)) {
103 return Standard_False;
104 }
105 //
106 gp_Pnt aP1, aP2;
107 gp_Vec aDC3D, aDSU, aDSV;
108 gp_Pnt2d aP2d;
109 gp_Vec2d aDC2D;
110 //
111 myCurve->D1(aPar, aP1, aDC3D);
112 myPCurve->D1(aPar, aP2d, aDC2D);
113 mySurf->D1(aP2d.X(), aP2d.Y(), aP2, aDSU, aDSV);
114 //
115 aP1.SetXYZ(aP1.XYZ() - aP2.XYZ());
116 aP2.SetXYZ(aDC3D.XYZ() - aDC2D.X()*aDSU.XYZ() - aDC2D.Y()*aDSV.XYZ());
117 //
118 theGrad(1) = -2.0*aP1.XYZ().Dot(aP2.XYZ());
119 }
120 catch(Standard_Failure) {
121 return Standard_False;
122 }
123 //
124 return Standard_True;
125 }
126 //
127 virtual Standard_Boolean Values(const math_Vector& theX,
128 Standard_Real& theVal,
129 math_Vector& theGrad) {
130 if (!Value(theX, theVal)) {
131 return Standard_False;
132 }
133 //
134 if (!Gradient(theX, theGrad)) {
135 return Standard_False;
136 }
137 //
138 return Standard_True;
139 }
140 //
141 virtual Standard_Boolean Values(const math_Vector& theX,
142 Standard_Real& theVal,
143 math_Vector& theGrad,
144 math_Matrix& theHessian) {
145 if (!Value(theX, theVal)) {
146 return Standard_False;
147 }
148 //
149 if (!Gradient(theX, theGrad)) {
150 return Standard_False;
151 }
152 //
153 theHessian(1,1) = theGrad(1);
154 //
155 return Standard_True;
156 }
157 //
158 private:
159
160 Standard_Boolean CheckParameter(const Standard_Real theParam) {
161 return ((myFirst <= theParam) && (theParam <= myLast));
162 }
163
94f71cad 164 Handle(GeomAdaptor_HCurve) myCurve;
165 Handle(Geom2dAdaptor_HCurve) myPCurve;
166 Handle(GeomAdaptor_HSurface) mySurf;
1b7ae951 167 Standard_Real myFirst;
168 Standard_Real myLast;
169};
170
171static
172 void MinComputing(BRepLib_CheckCurveOnSurface_GlobOptFunc& theFunction,
173 const Standard_Real theFirst,
174 const Standard_Real theLast,
175 const Standard_Real theEpsilon,
176 Standard_Real& theBestValue,
177 Standard_Real& theBestParameter);
178
179
180//=======================================================================
181//function : BRepLib_CheckCurveOnSurface
182//purpose :
183//=======================================================================
184BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface()
185:
186 myFirst(0.),
187 myLast(0.),
188 myErrorStatus(0),
189 myMaxDistance(0.),
190 myMaxParameter(0.)
191{
192}
193
194//=======================================================================
195//function : BRepLib_CheckCurveOnSurface
196//purpose :
197//=======================================================================
198BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface
199 (const TopoDS_Edge& theEdge,
200 const TopoDS_Face& theFace)
201:
202 myErrorStatus(0),
203 myMaxDistance(0.),
204 myMaxParameter(0.)
205{
206 Init(theEdge, theFace);
207}
208
209//=======================================================================
210//function : BRepLib_CheckCurveOnSurface
211//purpose :
212//=======================================================================
213BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface
214 (const Handle(Geom_Curve)& the3DCurve,
215 const Handle(Geom2d_Curve)& the2DCurve,
216 const Handle(Geom_Surface)& theSurface,
217 const Standard_Real theFirst,
218 const Standard_Real theLast)
219:
220 myErrorStatus(0),
221 myMaxDistance(0.),
222 myMaxParameter(0.)
223{
224 Init(the3DCurve, the2DCurve, theSurface, theFirst, theLast);
225}
226
227//=======================================================================
228//function : Init
229//purpose :
230//=======================================================================
231void BRepLib_CheckCurveOnSurface::Init
232 (const TopoDS_Edge& theEdge,
233 const TopoDS_Face& theFace)
234{
235 if (theEdge.IsNull() || theFace.IsNull()) {
236 return;
237 }
238 //
239 if (BRep_Tool::Degenerated(theEdge) ||
240 !BRep_Tool::IsGeometric(theEdge)) {
241 return;
242 }
243 //
244 Standard_Boolean isPCurveFound;
245 TopLoc_Location aLocE, aLocF, aLocC2D;
246 //
247 // 3D curve initialization
248 myCurve = Handle(Geom_Curve)::
249 DownCast(BRep_Tool::Curve(theEdge, aLocE, myFirst, myLast)->Copy());
250 myCurve->Transform(aLocE.Transformation());
251 //
252 // Surface initialization
253 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLocF);
254 mySurface = Handle(Geom_Surface)::
255 DownCast(aS->Copy()->Transformed(aLocF.Transformation()));
256 //
257 // 2D curves initialization
258 isPCurveFound = Standard_False;
259 aLocC2D = aLocF.Predivided(aLocE);
260 const Handle(BRep_TEdge)& aTE = *((Handle(BRep_TEdge)*)&theEdge.TShape());
261 BRep_ListIteratorOfListOfCurveRepresentation itcr(aTE->Curves());
262 //
263 for (; itcr.More(); itcr.Next()) {
264 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
265 if (cr->IsCurveOnSurface(aS, aLocC2D)) {
266 isPCurveFound = Standard_True;
267 myPCurve = cr->PCurve();
268 //
269 if (cr->IsCurveOnClosedSurface()) {
270 myPCurve2 = cr->PCurve2();
271 }
272 break;
273 }
274 }
275 //
276 if (isPCurveFound) {
277 return;
278 }
279 //
280 Handle(Geom_Plane) aPlane;
281 Handle(Standard_Type) dtyp = mySurface->DynamicType();
282 //
283 if (dtyp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
284 aPlane = Handle(Geom_Plane)::
285 DownCast(Handle(Geom_RectangularTrimmedSurface)::
286 DownCast(mySurface)->BasisSurface()->Copy());
287 }
288 else {
289 aPlane = Handle(Geom_Plane)::DownCast(mySurface->Copy());
290 }
291 //
292 if (aPlane.IsNull()) { // not a plane
293 return;
294 }
295 //
296 aPlane = Handle(Geom_Plane)::DownCast(aPlane);
297 //
298 Handle(GeomAdaptor_HSurface) aGAHS = new GeomAdaptor_HSurface(aPlane);
299 Handle(Geom_Curve) aProjOnPlane =
300 GeomProjLib::ProjectOnPlane (new Geom_TrimmedCurve(myCurve, myFirst, myLast),
301 aPlane, aPlane->Position().Direction(),
302 Standard_True);
303 Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(aProjOnPlane);
304 //
305 ProjLib_ProjectedCurve aProj(aGAHS, aHCurve);
306 myPCurve = Geom2dAdaptor::MakeCurve(aProj);
307}
308
309//=======================================================================
310//function : Init
311//purpose :
312//=======================================================================
313void BRepLib_CheckCurveOnSurface::Init
314 (const Handle(Geom_Curve)& the3DCurve,
315 const Handle(Geom2d_Curve)& the2DCurve,
316 const Handle(Geom_Surface)& theSurface,
317 const Standard_Real theFirst,
318 const Standard_Real theLast)
319{
320 myCurve = the3DCurve;
321 myPCurve = the2DCurve;
322 mySurface = theSurface;
323 myFirst = theFirst;
324 myLast = theLast;
325}
326
327//=======================================================================
328//function : Perform
329//purpose :
330//=======================================================================
331void BRepLib_CheckCurveOnSurface::Perform()
332{
333 try {
334 //
335 // 1. Check data
336 CheckData();
337 if (myErrorStatus) {
338 return;
339 }
340 //
341 // 2. Compute the max distance
342 Compute(myPCurve);
343 //
344 if (!myPCurve2.IsNull()) {
345 // compute max distance for myPCurve2
346 // (for the second curve on closed surface)
347 Compute(myPCurve2);
348 }
349 }
350 catch (Standard_Failure) {
351 myErrorStatus = 3;
352 }
353}
354
355//=======================================================================
356//function : Compute
357//purpose :
358//=======================================================================
359void BRepLib_CheckCurveOnSurface::Compute
360 (const Handle(Geom2d_Curve)& thePCurve)
361{
362 Standard_Integer aNbIt, aStatus;
363 Standard_Real anEpsilonRange, aMinDelta;
364 Standard_Real aFirst, aLast;
365 Standard_Real aValue, aParam, aBP;
366 Standard_Real theMaxDist, theMaxPar;
367 //
368 anEpsilonRange = 1.e-3;
369 aMinDelta = 1.e-5;
370 aFirst = myFirst;
371 aLast = myLast;
372 //
373 BRepLib_CheckCurveOnSurface_GlobOptFunc aFunc
374 (myCurve, thePCurve, mySurface, myFirst, myLast);
375 //
376 math_Vector anOutputParam(1, 1);
377 anOutputParam(1) = aFirst;
378 theMaxDist = 0.;
379 theMaxPar = aFirst;
380 aNbIt = 100;
381 aStatus = Standard_True;
382 //
383 MinComputing(aFunc, aFirst, aLast, anEpsilonRange, theMaxDist, theMaxPar);
384 //
385 while((aNbIt-- >= 0) && aStatus) {
386 aValue = theMaxDist;
387 aParam = theMaxPar;
388 aBP = theMaxPar - aMinDelta;
e002f1ce 389
390 if((aBP - aFirst) > Precision::PConfusion())
391 MinComputing(aFunc, aFirst, aBP, anEpsilonRange, theMaxDist, theMaxPar);
1b7ae951 392 //
393 if(theMaxDist < aValue) {
394 aLast = aBP;
395 aStatus = Standard_True;
396 }
397 else {
398 theMaxDist = aValue;
399 theMaxPar = aParam;
400 aStatus = Standard_False;
401 }
402 //
403 if(!aStatus) {
404 aBP = theMaxPar + aMinDelta;
e002f1ce 405
406 if((aLast - aBP) > Precision::PConfusion())
407 MinComputing(aFunc, aBP, aLast, 1.0e-3, theMaxDist, theMaxPar);
1b7ae951 408 //
409 if(theMaxDist < aValue) {
410 aFirst = aBP;
411 aStatus = Standard_True;
412 }
413 else {
414 theMaxDist = aValue;
415 theMaxPar = aParam;
416 aStatus = Standard_False;
417 }
418 }
419 }
420 //
421 theMaxDist = sqrt(Abs(theMaxDist));
422 if (theMaxDist > myMaxDistance) {
423 myMaxDistance = theMaxDist;
424 myMaxParameter = theMaxPar;
425 }
426}
427
428//=======================================================================
429// Function : MinComputing
430// purpose :
431//=======================================================================
432void MinComputing
433 (BRepLib_CheckCurveOnSurface_GlobOptFunc& theFunction,
434 const Standard_Real theFirst,
435 const Standard_Real theLast,
436 const Standard_Real theEpsilon, //1.0e-3
437 Standard_Real& theBestValue,
438 Standard_Real& theBestParameter)
439{
440 const Standard_Real aStepMin = 1.0e-2;
441 math_Vector aFirstV(1, 1), aLastV(1, 1), anOutputParam(1, 1);
442 aFirstV(1) = theFirst;
443 aLastV(1) = theLast;
444 //
445 math_GlobOptMin aFinder(&theFunction, aFirstV, aLastV);
446 aFinder.SetTol(aStepMin, theEpsilon);
447 aFinder.Perform();
448 //
449 const Standard_Integer aNbExtr = aFinder.NbExtrema();
450 for(Standard_Integer i = 1; i <= aNbExtr; i++)
451 {
452 Standard_Real aValue = 0.0;
453 aFinder.Points(i, anOutputParam);
454 theFunction.Value(anOutputParam, aValue);
455 //
456 if(aValue < theBestValue) {
457 theBestValue = aValue;
458 theBestParameter = anOutputParam(1);
459 }
460 }
461}