a793d9c3dda137ff5ebee4042610fec166fae1fc
[occt.git] / src / Extrema / Extrema_GenExtCC.gxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Extrema_GlobOptFuncCC.hxx>
18 #include <math_GlobOptMin.hxx>
19 #include <Standard_NullObject.hxx>
20 #include <Standard_OutOfRange.hxx>
21 #include <StdFail_NotDone.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <Precision.hxx>
24
25 //=======================================================================
26 //function : Extrema_GenExtCC
27 //purpose  : 
28 //=======================================================================
29 Extrema_GenExtCC::Extrema_GenExtCC()
30 : myLowBorder(1,2),
31   myUppBorder(1,2),
32   myDone(Standard_False)
33 {
34 }
35
36 //=======================================================================
37 //function : Extrema_GenExtCC
38 //purpose  : 
39 //=======================================================================
40 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
41                                    const Curve2& C2)
42 : myLowBorder(1,2),
43   myUppBorder(1,2),
44   myDone(Standard_False)
45 {
46   myC[0] = (Standard_Address)&C1;
47   myC[1] = (Standard_Address)&C2;
48   myLowBorder(1) = C1.FirstParameter();
49   myLowBorder(2) = C2.FirstParameter();
50   myUppBorder(1) = C1.LastParameter();
51   myUppBorder(2) = C2.LastParameter();
52   myCurveMinTol = 1.0e-9;
53 }
54
55 //=======================================================================
56 //function : Extrema_GenExtCC
57 //purpose  : 
58 //=======================================================================
59 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
60                                    const Curve2& C2,
61                                    const Standard_Real Uinf,
62                                    const Standard_Real Usup,
63                                    const Standard_Real Vinf,
64                                    const Standard_Real Vsup)
65 : myLowBorder(1,2),
66   myUppBorder(1,2),
67   myDone(Standard_False)
68 {
69   myC[0] = (Standard_Address)&C1;
70   myC[1] = (Standard_Address)&C2;
71   myLowBorder(1) = Uinf;
72   myLowBorder(2) = Vinf;
73   myUppBorder(1) = Usup;
74   myUppBorder(2) = Vsup;
75   myCurveMinTol = 1.0e-9;
76 }
77
78 //=======================================================================
79 //function : SetParams
80 //purpose  : 
81 //=======================================================================
82 void Extrema_GenExtCC::SetParams(const Curve1& C1,
83                                  const Curve2& C2,
84                                  const Standard_Real Uinf,
85                                  const Standard_Real Usup,
86                                  const Standard_Real Vinf,
87                                  const Standard_Real Vsup)
88 {
89   myC[0] = (Standard_Address)&C1;
90   myC[1] = (Standard_Address)&C2;
91   myLowBorder(1) = Uinf;
92   myLowBorder(2) = Vinf;
93   myUppBorder(1) = Usup;
94   myUppBorder(2) = Vsup;
95 }
96
97 //=======================================================================
98 //function : SetTolerance
99 //purpose  : 
100 //=======================================================================
101 void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
102 {
103   myCurveMinTol = theTol;
104 }
105
106 //=======================================================================
107 //function : Perform
108 //purpose  : 
109 //=======================================================================
110 void Extrema_GenExtCC::Perform()
111 {
112   myDone = Standard_False;
113
114   Curve1 &C1 = *(Curve1*)myC[0];
115   Curve2 &C2 = *(Curve2*)myC[1];
116
117   Standard_Integer aNbInter[2];
118   aNbInter[0] = C1.NbIntervals(GeomAbs_C2);
119   aNbInter[1] = C2.NbIntervals(GeomAbs_C2);
120   TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
121   TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
122   C1.Intervals(anIntervals1, GeomAbs_C2);
123   C2.Intervals(anIntervals2, GeomAbs_C2);
124
125   math_MultipleVarFunction *aFunc = new Extrema_GlobOptFuncCCC2(C1, C2);
126   math_GlobOptMin aFinder(aFunc, myLowBorder, myUppBorder);
127   Standard_Real aDiscTol = 1.0e-2;
128   Standard_Real aValueTol = 1.0e-2;
129   Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
130   aFinder.SetTol(aDiscTol, aSameTol);
131
132   Standard_Integer i,j,k;
133   math_Vector aFirstBorderInterval(1,2);
134   math_Vector aSecondBorderInterval(1,2);
135   Standard_Real aF = RealLast(); // best functional value
136   Standard_Real aCurrF = RealLast(); // current functional value computed on current interval
137   for(i = 1; i <= aNbInter[0]; i++)
138   {
139     for(j = 1; j <= aNbInter[1]; j++)
140     {
141       aFirstBorderInterval(1) = anIntervals1(i);
142       aFirstBorderInterval(2) = anIntervals2(j); 
143       aSecondBorderInterval(1) = anIntervals1(i + 1);
144       aSecondBorderInterval(2) = anIntervals2(j + 1);
145
146       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
147       aFinder.Perform();
148
149       aCurrF = aFinder.GetF();
150       if (aCurrF < aF + aSameTol * aValueTol)
151       {
152         if (aCurrF > aF - aSameTol * aValueTol)
153         {
154           if (aCurrF < aF)
155             aF = aCurrF;
156
157           math_Vector sol(1,2);
158           Standard_Integer myTmpSolCount = aFinder.NbExtrema();
159           for(k = 1; k <= myTmpSolCount; k++)
160           {
161             aFinder.Points(k, sol);
162             myPoints1.Append(sol(1));
163             myPoints2.Append(sol(2));
164           }
165           mySolCount += myTmpSolCount;
166         } // if (aCurrF > aF - aSameTol * aValueTol)
167         else
168         {
169           aF = aCurrF;
170           mySolCount = aFinder.NbExtrema();
171           myPoints1.Clear();
172           myPoints2.Clear();
173           math_Vector sol(1,2);
174           for(k = 1; k <= mySolCount; k++)
175           {
176             aFinder.Points(k, sol);
177             myPoints1.Append(sol(1));
178             myPoints2.Append(sol(2));
179           }
180         } // else
181       } //if (aCurrF < aF + aSameTol * aValueTol)
182     }
183   }
184
185   // Clear solutions clusters if it is necessary.
186   for(i = 1; i <= mySolCount - 1; i++)
187   {
188     for(j = i + 1; j <= mySolCount; j++)
189     {
190       if (Abs(myPoints1(i) - myPoints1(j)) < (myUppBorder(1) - myLowBorder(1)) * Precision::Confusion() &&
191           Abs(myPoints2(i) - myPoints2(j)) < (myUppBorder(2) - myLowBorder(2)) * Precision::Confusion())
192       {
193         // Points with indexes i and j is in same cluster, delete j point from extrema array.
194         myPoints1.Remove(j);
195         myPoints2.Remove(j);
196         j--;
197         mySolCount--;
198       }
199     }
200   }
201
202   delete aFunc;
203   myDone = Standard_True;
204 }
205
206 //=======================================================================
207 //function : IsDone
208 //purpose  : 
209 //=======================================================================
210 Standard_Boolean Extrema_GenExtCC::IsDone() const 
211 {
212   return myDone; 
213 }
214
215 //=======================================================================
216 //function : NbExt
217 //purpose  : 
218 //=======================================================================
219 Standard_Integer Extrema_GenExtCC::NbExt() const
220 {
221   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::NbExt()")
222
223   return mySolCount;
224 }
225
226 //=======================================================================
227 //function : SquareDistance
228 //purpose  : 
229 //=======================================================================
230 Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
231 {
232   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()")
233   Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()")
234
235   return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
236 }
237
238 //=======================================================================
239 //function : Points
240 //purpose  : 
241 //=======================================================================
242 void Extrema_GenExtCC::Points(const Standard_Integer N,
243                               POnC& P1,
244                               POnC& P2) const
245 {
246   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::Points()")
247   Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::Points()")
248
249   P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
250   P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
251 }