1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <BRepLib_CheckCurveOnSurface.ixx>
17 #include <math_GlobOptMin.hxx>
18 #include <math_MultipleVarFunctionWithHessian.hxx>
19 #include <math_Matrix.hxx>
21 #include <Geom_Plane.hxx>
22 #include <Geom_RectangularTrimmedSurface.hxx>
23 #include <Geom_TrimmedCurve.hxx>
25 #include <Geom2dAdaptor.hxx>
27 #include <GeomAdaptor_HSurface.hxx>
28 #include <GeomAdaptor_HCurve.hxx>
29 #include <Geom2dAdaptor_HCurve.hxx>
31 #include <GeomProjLib.hxx>
33 #include <BRep_Tool.hxx>
34 #include <BRep_TEdge.hxx>
35 #include <BRep_CurveRepresentation.hxx>
36 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
38 #include <TopLoc_Location.hxx>
40 #include <ProjLib_ProjectedCurve.hxx>
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
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)
63 myCurve = new GeomAdaptor_HCurve(theC3D);
64 myPCurve = new Geom2dAdaptor_HCurve(theC2D);
65 mySurf = new GeomAdaptor_HSurface(theSurf);
68 virtual Standard_Integer NbVariables() const {
72 virtual Standard_Boolean Value(const math_Vector& theX,
73 Standard_Real& theFVal) {
75 const Standard_Real aPar = theX(1);
76 if (!CheckParameter(aPar))
77 return Standard_False;
81 myCurve->D0(aPar, aP1);
82 myPCurve->D0(aPar, aP2d);
83 mySurf->D0(aP2d.X(), aP2d.Y(), aP2);
85 theFVal = -1.0*aP1.SquareDistance(aP2);
87 catch(Standard_Failure) {
88 return Standard_False;
94 virtual Standard_Integer GetStateNumber() {
98 virtual Standard_Boolean Gradient(const math_Vector& theX,
99 math_Vector& theGrad) {
101 const Standard_Real aPar = theX(1);
102 if (!CheckParameter(aPar)) {
103 return Standard_False;
107 gp_Vec aDC3D, aDSU, aDSV;
111 myCurve->D1(aPar, aP1, aDC3D);
112 myPCurve->D1(aPar, aP2d, aDC2D);
113 mySurf->D1(aP2d.X(), aP2d.Y(), aP2, aDSU, aDSV);
115 aP1.SetXYZ(aP1.XYZ() - aP2.XYZ());
116 aP2.SetXYZ(aDC3D.XYZ() - aDC2D.X()*aDSU.XYZ() - aDC2D.Y()*aDSV.XYZ());
118 theGrad(1) = -2.0*aP1.XYZ().Dot(aP2.XYZ());
120 catch(Standard_Failure) {
121 return Standard_False;
124 return Standard_True;
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;
134 if (!Gradient(theX, theGrad)) {
135 return Standard_False;
138 return Standard_True;
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;
149 if (!Gradient(theX, theGrad)) {
150 return Standard_False;
153 theHessian(1,1) = theGrad(1);
155 return Standard_True;
160 Standard_Boolean CheckParameter(const Standard_Real theParam) {
161 return ((myFirst <= theParam) && (theParam <= myLast));
164 Handle(GeomAdaptor_HCurve) myCurve;
165 Handle(Geom2dAdaptor_HCurve) myPCurve;
166 Handle(GeomAdaptor_HSurface) mySurf;
167 Standard_Real myFirst;
168 Standard_Real myLast;
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);
180 //=======================================================================
181 //function : BRepLib_CheckCurveOnSurface
183 //=======================================================================
184 BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface()
194 //=======================================================================
195 //function : BRepLib_CheckCurveOnSurface
197 //=======================================================================
198 BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface
199 (const TopoDS_Edge& theEdge,
200 const TopoDS_Face& theFace)
206 Init(theEdge, theFace);
209 //=======================================================================
210 //function : BRepLib_CheckCurveOnSurface
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)
224 Init(the3DCurve, the2DCurve, theSurface, theFirst, theLast);
227 //=======================================================================
230 //=======================================================================
231 void BRepLib_CheckCurveOnSurface::Init
232 (const TopoDS_Edge& theEdge,
233 const TopoDS_Face& theFace)
235 if (theEdge.IsNull() || theFace.IsNull()) {
239 if (BRep_Tool::Degenerated(theEdge) ||
240 !BRep_Tool::IsGeometric(theEdge)) {
244 Standard_Boolean isPCurveFound;
245 TopLoc_Location aLocE, aLocF, aLocC2D;
247 // 3D curve initialization
248 myCurve = Handle(Geom_Curve)::
249 DownCast(BRep_Tool::Curve(theEdge, aLocE, myFirst, myLast)->Copy());
250 myCurve->Transform(aLocE.Transformation());
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()));
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());
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();
269 if (cr->IsCurveOnClosedSurface()) {
270 myPCurve2 = cr->PCurve2();
280 Handle(Geom_Plane) aPlane;
281 Handle(Standard_Type) dtyp = mySurface->DynamicType();
283 if (dtyp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
284 aPlane = Handle(Geom_Plane)::
285 DownCast(Handle(Geom_RectangularTrimmedSurface)::
286 DownCast(mySurface)->BasisSurface()->Copy());
289 aPlane = Handle(Geom_Plane)::DownCast(mySurface->Copy());
292 if (aPlane.IsNull()) { // not a plane
296 aPlane = Handle(Geom_Plane)::DownCast(aPlane);
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(),
303 Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(aProjOnPlane);
305 ProjLib_ProjectedCurve aProj(aGAHS, aHCurve);
306 myPCurve = Geom2dAdaptor::MakeCurve(aProj);
309 //=======================================================================
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)
320 myCurve = the3DCurve;
321 myPCurve = the2DCurve;
322 mySurface = theSurface;
327 //=======================================================================
330 //=======================================================================
331 void BRepLib_CheckCurveOnSurface::Perform()
341 // 2. Compute the max distance
344 if (!myPCurve2.IsNull()) {
345 // compute max distance for myPCurve2
346 // (for the second curve on closed surface)
350 catch (Standard_Failure) {
355 //=======================================================================
358 //=======================================================================
359 void BRepLib_CheckCurveOnSurface::Compute
360 (const Handle(Geom2d_Curve)& thePCurve)
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;
368 anEpsilonRange = 1.e-3;
373 BRepLib_CheckCurveOnSurface_GlobOptFunc aFunc
374 (myCurve, thePCurve, mySurface, myFirst, myLast);
376 math_Vector anOutputParam(1, 1);
377 anOutputParam(1) = aFirst;
381 aStatus = Standard_True;
383 MinComputing(aFunc, aFirst, aLast, anEpsilonRange, theMaxDist, theMaxPar);
385 while((aNbIt-- >= 0) && aStatus) {
388 aBP = theMaxPar - aMinDelta;
390 if((aBP - aFirst) > Precision::PConfusion())
391 MinComputing(aFunc, aFirst, aBP, anEpsilonRange, theMaxDist, theMaxPar);
393 if(theMaxDist < aValue) {
395 aStatus = Standard_True;
400 aStatus = Standard_False;
404 aBP = theMaxPar + aMinDelta;
406 if((aLast - aBP) > Precision::PConfusion())
407 MinComputing(aFunc, aBP, aLast, 1.0e-3, theMaxDist, theMaxPar);
409 if(theMaxDist < aValue) {
411 aStatus = Standard_True;
416 aStatus = Standard_False;
421 theMaxDist = sqrt(Abs(theMaxDist));
422 if (theMaxDist > myMaxDistance) {
423 myMaxDistance = theMaxDist;
424 myMaxParameter = theMaxPar;
428 //=======================================================================
429 // Function : MinComputing
431 //=======================================================================
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)
440 const Standard_Real aStepMin = 1.0e-2;
441 math_Vector aFirstV(1, 1), aLastV(1, 1), anOutputParam(1, 1);
442 aFirstV(1) = theFirst;
445 math_GlobOptMin aFinder(&theFunction, aFirstV, aLastV);
446 aFinder.SetTol(aStepMin, theEpsilon);
449 const Standard_Integer aNbExtr = aFinder.NbExtrema();
450 for(Standard_Integer i = 1; i <= aNbExtr; i++)
452 Standard_Real aValue = 0.0;
453 aFinder.Points(i, anOutputParam);
454 theFunction.Value(anOutputParam, aValue);
456 if(aValue < theBestValue) {
457 theBestValue = aValue;
458 theBestParameter = anOutputParam(1);