ba07b737814ba4b5c6b0a427a8e7d716bfacf8f2
[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 : myCurveMinTol(Precision::PConfusion()),
31   myLowBorder(1,2),
32   myUppBorder(1,2),
33   myDone(Standard_False)
34 {
35   myC[0] = myC[1] = 0;
36 }
37
38 //=======================================================================
39 //function : Extrema_GenExtCC
40 //purpose  : 
41 //=======================================================================
42 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
43                                    const Curve2& C2)
44 : myCurveMinTol(Precision::PConfusion()),
45   myLowBorder(1,2),
46   myUppBorder(1,2),
47   myDone(Standard_False)
48 {
49   myC[0] = (Standard_Address)&C1;
50   myC[1] = (Standard_Address)&C2;
51   myLowBorder(1) = C1.FirstParameter();
52   myLowBorder(2) = C2.FirstParameter();
53   myUppBorder(1) = C1.LastParameter();
54   myUppBorder(2) = C2.LastParameter();
55 }
56
57 //=======================================================================
58 //function : Extrema_GenExtCC
59 //purpose  : 
60 //=======================================================================
61 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
62                                    const Curve2& C2,
63                                    const Standard_Real Uinf,
64                                    const Standard_Real Usup,
65                                    const Standard_Real Vinf,
66                                    const Standard_Real Vsup)
67 : myCurveMinTol(Precision::PConfusion()),
68   myLowBorder(1,2),
69   myUppBorder(1,2),
70   myDone(Standard_False)
71 {
72   myC[0] = (Standard_Address)&C1;
73   myC[1] = (Standard_Address)&C2;
74   myLowBorder(1) = Uinf;
75   myLowBorder(2) = Vinf;
76   myUppBorder(1) = Usup;
77   myUppBorder(2) = Vsup;
78 }
79
80 //=======================================================================
81 //function : SetParams
82 //purpose  : 
83 //=======================================================================
84 void Extrema_GenExtCC::SetParams(const Curve1& C1,
85                                  const Curve2& C2,
86                                  const Standard_Real Uinf,
87                                  const Standard_Real Usup,
88                                  const Standard_Real Vinf,
89                                  const Standard_Real Vsup)
90 {
91   myC[0] = (Standard_Address)&C1;
92   myC[1] = (Standard_Address)&C2;
93   myLowBorder(1) = Uinf;
94   myLowBorder(2) = Vinf;
95   myUppBorder(1) = Usup;
96   myUppBorder(2) = Vsup;
97 }
98
99 //=======================================================================
100 //function : SetTolerance
101 //purpose  : 
102 //=======================================================================
103 void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
104 {
105   myCurveMinTol = theTol;
106 }
107
108 //=======================================================================
109 //function : Perform
110 //purpose  : 
111 //=======================================================================
112 void Extrema_GenExtCC::Perform()
113 {
114   myDone = Standard_False;
115
116   Curve1 &C1 = *(Curve1*)myC[0];
117   Curve2 &C2 = *(Curve2*)myC[1];
118
119   Standard_Integer aNbInter[2];
120   aNbInter[0] = C1.NbIntervals(GeomAbs_C2);
121   aNbInter[1] = C2.NbIntervals(GeomAbs_C2);
122   TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
123   TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
124   C1.Intervals(anIntervals1, GeomAbs_C2);
125   C2.Intervals(anIntervals2, GeomAbs_C2);
126
127   Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
128   math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder);
129   Standard_Real aDiscTol = 1.0e-2;
130   Standard_Real aValueTol = 1.0e-2;
131   Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
132   aFinder.SetTol(aDiscTol, aSameTol);
133
134   Standard_Real anEps1 = (myUppBorder(1) - myLowBorder(1)) * Precision::Confusion();
135   Standard_Real anEps2 = (myUppBorder(2) - myLowBorder(2)) * Precision::Confusion();
136
137   Standard_Integer i,j,k;
138   math_Vector aFirstBorderInterval(1,2);
139   math_Vector aSecondBorderInterval(1,2);
140   Standard_Real aF = RealLast(); // best functional value
141   Standard_Real aCurrF = RealLast(); // current functional value computed on current interval
142   for(i = 1; i <= aNbInter[0]; i++)
143   {
144     for(j = 1; j <= aNbInter[1]; j++)
145     {
146       aFirstBorderInterval(1) = anIntervals1(i);
147       aFirstBorderInterval(2) = anIntervals2(j); 
148       aSecondBorderInterval(1) = anIntervals1(i + 1);
149       aSecondBorderInterval(2) = anIntervals2(j + 1);
150
151       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
152       aFinder.Perform();
153
154       // check that solution found on current interval is not worse than previous
155       aCurrF = aFinder.GetF();
156       if (aCurrF >= aF + aSameTol * aValueTol)
157       {
158         continue;
159       }
160
161       // clean previously computed solution if current one is better
162       if (aCurrF > aF - aSameTol * aValueTol)
163       {
164         if (aCurrF < aF)
165           aF = aCurrF;
166       }
167       else
168       {
169         aF = aCurrF;
170         myPoints1.Clear();
171         myPoints2.Clear();
172       }
173
174       // save found solutions avoiding repetitions
175       math_Vector sol(1,2);
176       for(k = 1; k <= aFinder.NbExtrema(); k++)
177       {
178         aFinder.Points(k, sol);
179
180         // avoid duplicated points
181         Standard_Boolean isNew = Standard_True;
182         for (Standard_Integer iSol = 1; isNew && iSol <= myPoints1.Length(); iSol++)
183         {
184           if (Abs(myPoints1(iSol) - sol(1)) < anEps1 &&
185               Abs(myPoints2(iSol) - sol(2)) < anEps2)
186             isNew = Standard_False;
187         }
188         if (isNew)
189         {
190           myPoints1.Append(sol(1));
191           myPoints2.Append(sol(2));
192         }
193       }
194     }
195   }
196
197   myDone = Standard_True;
198 }
199
200 //=======================================================================
201 //function : IsDone
202 //purpose  : 
203 //=======================================================================
204 Standard_Boolean Extrema_GenExtCC::IsDone() const 
205 {
206   return myDone; 
207 }
208
209 //=======================================================================
210 //function : NbExt
211 //purpose  : 
212 //=======================================================================
213 Standard_Integer Extrema_GenExtCC::NbExt() const
214 {
215   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::NbExt()")
216
217   return myPoints1.Length();
218 }
219
220 //=======================================================================
221 //function : SquareDistance
222 //purpose  : 
223 //=======================================================================
224 Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
225 {
226   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()")
227   Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()")
228
229   return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
230 }
231
232 //=======================================================================
233 //function : Points
234 //purpose  : 
235 //=======================================================================
236 void Extrema_GenExtCC::Points(const Standard_Integer N,
237                               POnC& P1,
238                               POnC& P2) const
239 {
240   StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::Points()")
241   Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::Points()")
242
243   P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
244   P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
245 }