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 | //======================================================================= |
47 | class 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 | |
171 | static |
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 | //======================================================================= |
184 | BRepLib_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 | //======================================================================= |
198 | BRepLib_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 | //======================================================================= |
213 | BRepLib_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 | //======================================================================= |
231 | void 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 | //======================================================================= |
313 | void 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 | //======================================================================= |
331 | void 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 | //======================================================================= |
359 | void 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 | //======================================================================= |
432 | void 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 | } |