1 // Created on: 1995-07-18
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Adaptor3d_Surface.hxx>
19 #include <Extrema_GenExtSS.hxx>
20 #include <Extrema_POnSurf.hxx>
21 #include <math_BFGS.hxx>
22 #include <math_FunctionSetRoot.hxx>
23 #include <math_MultipleVarFunctionWithGradient.hxx>
24 #include <math_Vector.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <StdFail_NotDone.hxx>
28 //! This class represents distance objective function for surface / surface.
29 class Extrema_FuncDistSS : public math_MultipleVarFunctionWithGradient
34 Standard_EXPORT Extrema_FuncDistSS(const Adaptor3d_Surface& S1,
35 const Adaptor3d_Surface& S2)
41 Standard_EXPORT Standard_Integer NbVariables() const
46 Standard_EXPORT virtual Standard_Boolean Value(const math_Vector& X,Standard_Real& F)
48 F = myS1->Value(X(1), X(2)).SquareDistance(myS2->Value(X(3), X(4)));
52 Standard_EXPORT Standard_Boolean Gradient(const math_Vector& X,math_Vector& G)
57 myS1->D1(X(1),X(2),P1,Du1s1,Dv1s1);
58 myS2->D1(X(3),X(4),P2,Du2s2,Dv2s2);
62 G(1) = P1P2.Dot(Du1s1);
63 G(2) = P1P2.Dot(Dv1s1);
64 G(3) = -P1P2.Dot(Du2s2);
65 G(4) = -P1P2.Dot(Dv2s2);
70 Standard_EXPORT virtual Standard_Boolean Values(const math_Vector& X,Standard_Real& F,math_Vector& G)
72 F = myS1->Value(X(1), X(2)).SquareDistance(myS2->Value(X(3), X(4)));
77 myS1->D1(X(1),X(2),P1,Du1s1,Dv1s1);
78 myS2->D1(X(3),X(4),P2,Du2s2,Dv2s2);
82 G(1) = P1P2.Dot(Du1s1);
83 G(2) = P1P2.Dot(Dv1s1);
84 G(3) = -P1P2.Dot(Du2s2);
85 G(4) = -P1P2.Dot(Dv2s2);
94 const Adaptor3d_Surface *myS1;
95 const Adaptor3d_Surface *myS2;
98 //=======================================================================
99 //function : Extrema_GenExtSS
101 //=======================================================================
102 Extrema_GenExtSS::Extrema_GenExtSS()
117 myDone = Standard_False;
118 myInit = Standard_False;
121 //=======================================================================
122 //function : Extrema_GenExtSS
124 //=======================================================================
126 Extrema_GenExtSS::Extrema_GenExtSS(const Adaptor3d_Surface& S1,
127 const Adaptor3d_Surface& S2,
128 const Standard_Integer NbU,
129 const Standard_Integer NbV,
130 const Standard_Real Tol1,
131 const Standard_Real Tol2) : myF(S1,S2)
133 Initialize(S2, NbU, NbV, Tol2);
137 //=======================================================================
138 //function : Extrema_GenExtSS
140 //=======================================================================
142 Extrema_GenExtSS::Extrema_GenExtSS(const Adaptor3d_Surface& S1,
143 const Adaptor3d_Surface& S2,
144 const Standard_Integer NbU,
145 const Standard_Integer NbV,
146 const Standard_Real U1min,
147 const Standard_Real U1sup,
148 const Standard_Real V1min,
149 const Standard_Real V1sup,
150 const Standard_Real U2min,
151 const Standard_Real U2sup,
152 const Standard_Real V2min,
153 const Standard_Real V2sup,
154 const Standard_Real Tol1,
155 const Standard_Real Tol2): myF(S1, S2)
157 Initialize(S2, NbU, NbV, U2min,U2sup,V2min,V2sup,Tol2);
158 Perform(S1, U1min,U1sup,V1min,V1sup,Tol1);
161 //=======================================================================
162 //function : Initialize
164 //=======================================================================
166 void Extrema_GenExtSS::Initialize(const Adaptor3d_Surface& S2,
167 const Standard_Integer NbU,
168 const Standard_Integer NbV,
169 const Standard_Real Tol2)
171 myu2min = S2.FirstUParameter();
172 myu2sup = S2.LastUParameter();
173 myv2min = S2.FirstVParameter();
174 myv2sup = S2.LastVParameter();
175 Initialize(S2,NbU,NbV,myu2min,myu2sup,myv2min,myv2sup,Tol2);
178 //=======================================================================
179 //function : Initialize
181 //=======================================================================
183 void Extrema_GenExtSS::Initialize(const Adaptor3d_Surface& S2,
184 const Standard_Integer NbU,
185 const Standard_Integer NbV,
186 const Standard_Real U2min,
187 const Standard_Real U2sup,
188 const Standard_Real V2min,
189 const Standard_Real V2sup,
190 const Standard_Real Tol2)
193 mypoints1 = new TColgp_HArray2OfPnt(0,NbU+1,0,NbV+1);
194 mypoints2 = new TColgp_HArray2OfPnt(0,NbU+1,0,NbV+1);
203 // Parametrage de l echantillon sur S2
205 Standard_Real PasU = myu2sup - myu2min;
206 Standard_Real PasV = myv2sup - myv2min;
207 Standard_Real U0 = PasU / myusample / 100.;
208 Standard_Real V0 = PasV / myvsample / 100.;
210 PasU = (PasU - U0) / (myusample - 1);
211 PasV = (PasV - V0) / (myvsample - 1);
212 U0 = myu2min + U0/2.;
213 V0 = myv2min + V0/2.;
215 // Calcul des distances
217 Standard_Integer NoU, NoV;
219 for ( NoU = 1, U = U0; NoU <= myusample; NoU++, U += PasU) {
220 for ( NoV = 1, V = V0; NoV <= myvsample; NoV++, V += PasV) {
221 P1 = myS2->Value(U, V);
222 mypoints2->SetValue(NoU,NoV,P1);
227 //=======================================================================
230 //=======================================================================
232 void Extrema_GenExtSS::Perform(const Adaptor3d_Surface& S1,
233 const Standard_Real Tol1)
235 myu1min = S1.FirstUParameter();
236 myu1sup = S1.LastUParameter();
237 myv1min = S1.FirstVParameter();
238 myv1sup = S1.LastVParameter();
239 Perform(S1, myu1min, myu1sup,myv1min,myv1sup,Tol1);
242 //=======================================================================
245 //=======================================================================
247 void Extrema_GenExtSS::Perform(const Adaptor3d_Surface& S1,
248 const Standard_Real U1min,
249 const Standard_Real U1sup,
250 const Standard_Real V1min,
251 const Standard_Real V1sup,
252 const Standard_Real Tol1)
254 myF.Initialize(S1,*myS2);
261 Standard_Real U1, V1, U2, V2;
262 Standard_Integer NoU1, NoV1, NoU2, NoV2;
265 // Parametrage de l echantillon sur S1
267 Standard_Real PasU1 = myu1sup - myu1min;
268 Standard_Real PasV1 = myv1sup - myv1min;
269 Standard_Real U10 = PasU1 / myusample / 100.;
270 Standard_Real V10 = PasV1 / myvsample / 100.;
271 PasU1 = (PasU1 - U10) / (myusample - 1);
272 PasV1 = (PasV1 - V10) / (myvsample - 1);
273 U10 = myu1min + U10/2.;
274 V10 = myv1min + V10/2.;
276 Standard_Real PasU2 = myu2sup - myu2min;
277 Standard_Real PasV2 = myv2sup - myv2min;
278 Standard_Real U20 = PasU2 / myusample / 100.;
279 Standard_Real V20 = PasV2 / myvsample / 100.;
280 PasU2 = (PasU2 - U20) / (myusample - 1);
281 PasV2 = (PasV2 - V20) / (myvsample - 1);
282 U20 = myu2min + U20/2.;
283 V20 = myv2min + V20/2.;
285 // Calcul des distances
287 for ( NoU1 = 1, U1 = U10; NoU1 <= myusample; NoU1++, U1 += PasU1) {
288 for ( NoV1 = 1, V1 = V10; NoV1 <= myvsample; NoV1++, V1 += PasV1) {
289 P1 = S1.Value(U1, V1);
290 mypoints1->SetValue(NoU1,NoV1,P1);
295 b- Calcul des minima:
297 b.a) Initialisations:
300 math_Vector Tol(1, 4);
305 math_Vector UV(1,4), UVinf(1,4), UVsup(1,4);
316 Standard_Real distmin = RealLast(), distmax = 0.0, TheDist;
318 Standard_Integer N1Umin=0,N1Vmin=0,N2Umin=0,N2Vmin=0;
319 gp_Pnt PP1min, PP2min;
320 Standard_Integer N1Umax=0,N1Vmax=0,N2Umax=0,N2Vmax=0;
321 gp_Pnt PP1max, PP2max;
323 for ( NoU1 = 1, U1 = U10; NoU1 <= myusample; NoU1++, U1 += PasU1) {
324 for ( NoV1 = 1, V1 = V10; NoV1 <= myvsample; NoV1++, V1 += PasV1) {
325 P1 = mypoints1->Value(NoU1, NoV1);
326 for ( NoU2 = 1, U2 = U20; NoU2 <= myusample; NoU2++, U2 += PasU2) {
327 for ( NoV2 = 1, V2 = V20; NoV2 <= myvsample; NoV2++, V2 += PasV2) {
328 P2 = mypoints2->Value(NoU2, NoV2);
329 TheDist = P1.SquareDistance(P2);
330 if (TheDist < distmin) {
339 if (TheDist > distmax) {
353 UV(1) = U10 + (N1Umin - 1) * PasU1;
354 UV(2) = V10 + (N1Vmin - 1) * PasV1;
355 UV(3) = U20 + (N2Umin - 1) * PasU2;
356 UV(4) = V20 + (N2Vmin - 1) * PasV2;
358 Extrema_FuncDistSS aGFSS(S1, *myS2);
359 math_BFGS aBFGSSolver(4);
360 aBFGSSolver.Perform(aGFSS, UV);
361 if (aBFGSSolver.IsDone())
363 aBFGSSolver.Location(UV);
365 // Store result in myF.
367 myF.GetStateNumber();
371 // If optimum is not computed successfully then compute by old approach.
373 // Restore initial point.
374 UV(1) = U10 + (N1Umin - 1) * PasU1;
375 UV(2) = V10 + (N1Vmin - 1) * PasV1;
376 UV(3) = U20 + (N2Umin - 1) * PasU2;
377 UV(4) = V20 + (N2Vmin - 1) * PasV2;
379 math_FunctionSetRoot SR1(myF, Tol);
380 SR1.Perform(myF, UV, UVinf, UVsup);
383 //math_FunctionSetRoot SR1(myF, Tol);
384 //SR1.Perform(myF, UV, UVinf, UVsup);
386 UV(1) = U10 + (N1Umax - 1) * PasU1;
387 UV(2) = V10 + (N1Vmax - 1) * PasV1;
388 UV(3) = U20 + (N2Umax - 1) * PasU2;
389 UV(4) = V20 + (N2Vmax - 1) * PasV2;
391 // It is impossible to compute max distance in the same manner,
392 // since for the distance functional for max have bad definition.
393 // So, for max computation old approach is used.
394 math_FunctionSetRoot SR2(myF, Tol);
395 SR2.Perform(myF, UV, UVinf, UVsup);
397 myDone = Standard_True;
400 //=======================================================================
403 //=======================================================================
405 Standard_Boolean Extrema_GenExtSS::IsDone() const
410 //=======================================================================
413 //=======================================================================
415 Standard_Integer Extrema_GenExtSS::NbExt() const
417 if (!IsDone()) { throw StdFail_NotDone(); }
422 //=======================================================================
423 //function : SquareDistance
425 //=======================================================================
427 Standard_Real Extrema_GenExtSS::SquareDistance(const Standard_Integer N) const
429 if (N < 1 || N > NbExt())
431 throw Standard_OutOfRange();
434 return myF.SquareDistance(N);
437 //=======================================================================
438 //function : PointOnS1
440 //=======================================================================
442 const Extrema_POnSurf& Extrema_GenExtSS::PointOnS1(const Standard_Integer N) const
444 if (N < 1 || N > NbExt())
446 throw Standard_OutOfRange();
449 return myF.PointOnS1(N);
452 //=======================================================================
453 //function : PointOnS2
455 //=======================================================================
457 const Extrema_POnSurf& Extrema_GenExtSS::PointOnS2(const Standard_Integer N) const
459 if (N < 1 || N > NbExt())
461 throw Standard_OutOfRange();
464 return myF.PointOnS2(N);