Warnings on vc14 were eliminated
[occt.git] / src / GeomAPI / GeomAPI_ExtremaCurveCurve.cxx
1 // Created on: 1994-03-18
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-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
18 #include <Extrema_ExtCC.hxx>
19 #include <Geom_Curve.hxx>
20 #include <GeomAdaptor_Curve.hxx>
21 #include <GeomAPI_ExtremaCurveCurve.hxx>
22 #include <GeomAPI_ProjectPointOnCurve.hxx>
23 #include <gp_Pnt.hxx>
24 #include <Precision.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <StdFail_NotDone.hxx>
27
28 //#include <Extrema_POnCurv.hxx>
29 //=======================================================================
30 //function : GeomAPI_ExtremaCurveCurve
31 //purpose  : 
32 //=======================================================================
33 GeomAPI_ExtremaCurveCurve::GeomAPI_ExtremaCurveCurve()
34 {
35   myIsDone = Standard_False;
36   myTotalExt = Standard_False;
37 }
38
39
40 //=======================================================================
41 //function : GeomAPI_ExtremaCurveCurve
42 //purpose  : 
43 //=======================================================================
44
45 GeomAPI_ExtremaCurveCurve::GeomAPI_ExtremaCurveCurve
46   (const Handle(Geom_Curve)& C1,
47    const Handle(Geom_Curve)& C2)
48 {
49   Init(C1,C2);
50 }
51
52
53 //=======================================================================
54 //function : GeomAPI_ExtremaCurveCurve
55 //purpose  : 
56 //=======================================================================
57
58 GeomAPI_ExtremaCurveCurve::GeomAPI_ExtremaCurveCurve
59   (const Handle(Geom_Curve)& C1,
60    const Handle(Geom_Curve)& C2,
61    const Standard_Real       U1min,
62    const Standard_Real       U1max,
63    const Standard_Real       U2min,
64    const Standard_Real       U2max)
65 {
66   Init(C1,C2,U1min,U1max,U2min,U2max);
67 }
68
69
70 //=======================================================================
71 //function : Init
72 //purpose  : 
73 //=======================================================================
74
75 void GeomAPI_ExtremaCurveCurve::Init
76   (const Handle(Geom_Curve)& C1,
77    const Handle(Geom_Curve)& C2)
78 {
79
80   myTotalExt = Standard_False;
81   
82   Standard_Real Tol = Precision::PConfusion();
83   myC1.Load(C1);
84   myC2.Load(C2);
85   Extrema_ExtCC theExtCC(myC1, myC2, Tol,Tol);
86   myExtCC = theExtCC;
87
88   myIsDone = myExtCC.IsDone() && ( myExtCC.NbExt() > 0);
89
90   if ( myIsDone) {
91
92     // evaluate the lower distance and its index;
93     
94     Standard_Real Dist2, Dist2Min = myExtCC.SquareDistance(1);
95     myIndex = 1;
96     
97     for ( Standard_Integer i = 2; i <= myExtCC.NbExt(); i++) {
98       Dist2 = myExtCC.SquareDistance(i);
99       if ( Dist2 < Dist2Min) {
100         Dist2Min = Dist2;
101         myIndex = i;
102       }
103     }
104   }
105 }
106
107
108 //=======================================================================
109 //function : Init
110 //purpose  : 
111 //=======================================================================
112
113 void GeomAPI_ExtremaCurveCurve::Init
114   (const Handle(Geom_Curve)& C1,
115    const Handle(Geom_Curve)& C2,
116    const Standard_Real       U1min,
117    const Standard_Real       U1max,
118    const Standard_Real       U2min,
119    const Standard_Real       U2max)
120 {
121  
122   myTotalExt = Standard_False;
123
124   Standard_Real Tol = Precision::PConfusion();
125   myC1.Load(C1);
126   myC2.Load(C2);
127   Extrema_ExtCC theExtCC(myC1,myC2,U1min,U1max,U2min,U2max,Tol,Tol);
128   myExtCC = theExtCC;
129
130   myIsDone = myExtCC.IsDone() && ( myExtCC.NbExt() > 0 );
131
132   if ( myIsDone) {
133
134     // evaluate the lower distance and its index;
135     
136     Standard_Real Dist2, Dist2Min = myExtCC.SquareDistance(1);
137     myIndex = 1;
138     
139     for ( Standard_Integer i = 2; i <= myExtCC.NbExt(); i++) {
140       Dist2 = myExtCC.SquareDistance(i);
141       if ( Dist2 < Dist2Min) {
142         Dist2Min = Dist2;
143         myIndex = i;
144       }
145     }
146   }
147 }
148
149
150 //=======================================================================
151 //function : NbExtrema
152 //purpose  : 
153 //=======================================================================
154
155 Standard_Integer GeomAPI_ExtremaCurveCurve::NbExtrema() const 
156 {
157   if ( myIsDone)
158     return myExtCC.NbExt();
159   else
160     return 0;
161 }
162
163
164 //=======================================================================
165 //function : Points
166 //purpose  : 
167 //=======================================================================
168
169 void GeomAPI_ExtremaCurveCurve::Points
170   (const Standard_Integer Index,
171          gp_Pnt&          P1,
172          gp_Pnt&          P2) const 
173 {
174   Standard_OutOfRange_Raise_if( Index < 1 || Index > NbExtrema(),
175                                "GeomAPI_ExtremaCurveCurve::Points");
176
177   Extrema_POnCurv PC1, PC2;
178   myExtCC.Points(Index,PC1,PC2);
179
180   P1 = PC1.Value();
181   P2 = PC2.Value();
182 }
183
184
185 //=======================================================================
186 //function : Parameters
187 //purpose  : 
188 //=======================================================================
189
190 void GeomAPI_ExtremaCurveCurve::Parameters
191   (const Standard_Integer Index, 
192          Standard_Real&   U1,
193          Standard_Real&   U2) const 
194 {
195   Standard_OutOfRange_Raise_if( Index < 1 || Index > NbExtrema(),
196                                "GeomAPI_ExtremaCurveCurve::Parameters");
197
198   Extrema_POnCurv PC1, PC2;
199   myExtCC.Points(Index,PC1,PC2);
200
201   U1 = PC1.Parameter();
202   U2 = PC2.Parameter();
203 }
204
205
206 //=======================================================================
207 //function : Distance
208 //purpose  : 
209 //=======================================================================
210
211 Standard_Real GeomAPI_ExtremaCurveCurve::Distance
212   (const Standard_Integer Index) const 
213 {
214   Standard_OutOfRange_Raise_if( Index < 1 || Index > NbExtrema(),
215                                "GeomAPI_ExtremaCurveCurve::Distance");
216
217   return sqrt (myExtCC.SquareDistance(Index));
218 }
219
220
221 //=======================================================================
222 //function : NearestPoints
223 //purpose  : 
224 //=======================================================================
225
226 void GeomAPI_ExtremaCurveCurve::NearestPoints(gp_Pnt& P1, gp_Pnt& P2) const 
227 {
228   StdFail_NotDone_Raise_if
229     (!myIsDone, "GeomAPI_ExtremaCurveCurve::NearestPoints");
230
231   Points(myIndex,P1,P2);
232 }
233
234
235 //=======================================================================
236 //function : LowerDistanceParameters
237 //purpose  : 
238 //=======================================================================
239
240 void GeomAPI_ExtremaCurveCurve::LowerDistanceParameters
241   (Standard_Real& U1,
242    Standard_Real& U2) const 
243 {
244   StdFail_NotDone_Raise_if
245     (!myIsDone, "GeomAPI_ExtremaCurveCurve::LowerDistanceParameters");
246
247   Parameters(myIndex,U1,U2);
248 }
249
250
251 //=======================================================================
252 //function : LowerDistance
253 //purpose  : 
254 //=======================================================================
255
256 Standard_Real GeomAPI_ExtremaCurveCurve::LowerDistance() const 
257 {
258   StdFail_NotDone_Raise_if
259     (!myIsDone, "GeomAPI_ExtremaCurveCurve::LowerDistance");
260
261   return sqrt (myExtCC.SquareDistance(myIndex));
262 }
263
264
265 //=======================================================================
266 //function : Standard_Real
267 //purpose  : 
268 //=======================================================================
269
270 GeomAPI_ExtremaCurveCurve::operator Standard_Real() const
271 {
272   return LowerDistance();
273 }
274
275
276 //=======================================================================
277 //function : Standard_Integer
278 //purpose  : 
279 //=======================================================================
280
281 GeomAPI_ExtremaCurveCurve::operator Standard_Integer() const
282 {
283   return myExtCC.NbExt();
284 }
285
286
287 Standard_Boolean GeomAPI_ExtremaCurveCurve::TotalNearestPoints(gp_Pnt& P1,gp_Pnt& P2) 
288 {
289
290   if(!myTotalExt) {
291
292     TotalPerform();
293     myTotalExt = Standard_True;
294
295   }
296
297   if(myIsInfinite) return Standard_False;
298
299   P1 = myTotalPoints[0];
300   P2 = myTotalPoints[1];
301
302   return Standard_True;
303     
304 }
305
306 Standard_Boolean GeomAPI_ExtremaCurveCurve::TotalLowerDistanceParameters(Quantity_Parameter& U1, 
307                                                                          Quantity_Parameter& U2) 
308 {
309   if(!myTotalExt) {
310
311     TotalPerform();
312     myTotalExt = Standard_True;
313
314   }
315
316   if(myIsInfinite) return Standard_False;
317
318   U1 = myTotalPars[0];
319   U2 = myTotalPars[1];
320
321   return Standard_True;
322
323 }
324
325 Quantity_Length GeomAPI_ExtremaCurveCurve::TotalLowerDistance() 
326 {
327   if(!myTotalExt) {
328
329     TotalPerform();
330     myTotalExt = Standard_True;
331
332   }
333
334   return myTotalDist;
335
336 }
337
338
339 void GeomAPI_ExtremaCurveCurve::TotalPerform()
340
341 {
342 //  StdFail_NotDone_Raise_if
343 //    (!myExtCC.IsDone(), "GeomAPI_ExtremaCurveCurve::TotalPerform");
344
345   Standard_Real u11 = myC1.FirstParameter();
346   Standard_Real u12 = myC1.LastParameter();
347   Standard_Real u21 = myC2.FirstParameter();
348   Standard_Real u22 = myC2.LastParameter();
349   
350   Standard_Boolean infinite = Precision::IsInfinite(u11) &&
351                               Precision::IsInfinite(u12) &&
352                               Precision::IsInfinite(u21) &&
353                               Precision::IsInfinite(u22);
354
355   myIsInfinite = Standard_False;
356
357   if(infinite && myExtCC.IsParallel()) {
358     
359     myIsInfinite = Standard_True;
360
361     //calculate distance between any suitable point on C1 and C2
362     
363     gp_Pnt PonC1 = myC1.Value(0.);
364     GeomAPI_ProjectPointOnCurve proj(PonC1, myC2.Curve());
365     myTotalDist = proj.LowerDistance();
366
367     return;
368
369   }
370
371   myTotalDist = RealLast();
372
373   if(myIsDone && !myExtCC.IsParallel()) {
374     
375     Points(myIndex, myTotalPoints[0], myTotalPoints[1]);
376     Parameters(myIndex, myTotalPars[0], myTotalPars[1]);
377     myTotalDist = sqrt (myExtCC.SquareDistance(myIndex));
378
379     if(myTotalDist <= Precision::Confusion()) return;
380
381   }
382
383   gp_Pnt P11, P12, P21, P22;
384   Standard_Real d11, d12, d21, d22;
385   myExtCC.TrimmedSquareDistances(d11, d12, d21, d22, P11, P12, P21, P22);
386
387   Standard_Real aTotalDist2 = myTotalDist * myTotalDist;
388   if(aTotalDist2  > d11) {
389     myTotalDist = sqrt (d11);
390     myTotalPoints[0] = P11;
391     myTotalPoints[1] = P21;
392     myTotalPars[0] = u11;
393     myTotalPars[1] = u21;
394     
395     if(myTotalDist <= Precision::Confusion()) return;
396     
397   }
398   
399   if(aTotalDist2 > d12) {
400     myTotalDist = sqrt (d12);
401     myTotalPoints[0] = P11;
402     myTotalPoints[1] = P22;
403     myTotalPars[0] = u11;
404     myTotalPars[1] = u22;
405     
406     if(myTotalDist <= Precision::Confusion()) return;
407     
408   }
409   
410   if(aTotalDist2 > d21) {
411     myTotalDist = sqrt (d21);
412     myTotalPoints[0] = P12;
413     myTotalPoints[1] = P21;
414     myTotalPars[0] = u12;
415     myTotalPars[1] = u21;
416     
417     if(myTotalDist <= Precision::Confusion()) return;
418     
419   }
420   
421   if(aTotalDist2 > d22) {
422     myTotalDist = sqrt (d22);
423     myTotalPoints[0] = P12;
424     myTotalPoints[1] = P22;
425     myTotalPars[0] = u12;
426     myTotalPars[1] = u22;
427     
428     if(myTotalDist <= Precision::Confusion()) return;
429     
430   }
431  
432   // calculate distances between extremities one curve and other curve
433
434   if(!Precision::IsInfinite(u11)) {
435     GeomAPI_ProjectPointOnCurve proj(P11, myC2.Curve(), u21, u22);  
436
437     if(proj.NbPoints() > 0) {
438
439       Standard_Real dmin = proj.LowerDistance();
440       if(myTotalDist > dmin) {
441         myTotalDist = dmin;
442         myTotalPoints[0] = P11;
443         myTotalPars[0] = u11;
444         myTotalPoints[1] = proj.NearestPoint();
445         myTotalPars[1] = proj.LowerDistanceParameter();
446
447         if(myTotalDist <= Precision::Confusion()) return;
448     
449       }
450     }
451   }
452
453   if(!Precision::IsInfinite(u12)) {
454     GeomAPI_ProjectPointOnCurve proj(P12, myC2.Curve(), u21, u22);  
455
456     if(proj.NbPoints() > 0) {
457
458       Standard_Real dmin = proj.LowerDistance();
459       if(myTotalDist > dmin) {
460         myTotalDist = dmin;
461         myTotalPoints[0] = P12;
462         myTotalPars[0] = u12;
463         myTotalPoints[1] = proj.NearestPoint();
464         myTotalPars[1] = proj.LowerDistanceParameter();
465
466         if(myTotalDist <= Precision::Confusion()) return;
467     
468       }
469     }
470   }
471
472   if(!Precision::IsInfinite(u21)) {
473     GeomAPI_ProjectPointOnCurve proj(P21, myC1.Curve(), u11, u12);  
474
475     if(proj.NbPoints() > 0) {
476
477       Standard_Real dmin = proj.LowerDistance();
478       if(myTotalDist > dmin) {
479         myTotalDist = dmin;
480         myTotalPoints[0] = proj.NearestPoint();
481         myTotalPars[0] = proj.LowerDistanceParameter();
482         myTotalPoints[1] = P21;
483         myTotalPars[1] = u21;
484
485         if(myTotalDist <= Precision::Confusion()) return;
486     
487       }
488     }
489   }
490
491   if(!Precision::IsInfinite(u22)) {
492     GeomAPI_ProjectPointOnCurve proj(P22, myC1.Curve(), u11, u12);  
493
494     if(proj.NbPoints() > 0) {
495
496       Standard_Real dmin = proj.LowerDistance();
497       if(myTotalDist > dmin) {
498         myTotalDist = dmin;
499         myTotalPoints[0] = proj.NearestPoint();
500         myTotalPars[0] = proj.LowerDistanceParameter();
501         myTotalPoints[1] = P22;
502         myTotalPars[1] = u22;
503     
504       }
505     }
506   }
507
508
509 }