0032008: Modeling Algorithms - disallow implicit copy of Extrema algorithms
[occt.git] / src / Extrema / Extrema_ExtPS.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
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.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //-----------------------------------------------------------------
16
17 #include <GeomAdaptor_SurfaceOfLinearExtrusion.hxx>
18 #include <GeomAdaptor_SurfaceOfRevolution.hxx>
19 #include <Adaptor3d_Surface.hxx>
20 #include <ElCLib.hxx>
21 #include <Extrema_ExtPExtS.hxx>
22 #include <Extrema_ExtPRevS.hxx>
23 #include <Extrema_ExtPS.hxx>
24 #include <Extrema_GenExtPS.hxx>
25 #include <Extrema_POnSurf.hxx>
26 #include <GeomAbs_CurveType.hxx>
27 #include <GeomAbs_IsoType.hxx>
28 #include <gp_Cone.hxx>
29 #include <gp_Cylinder.hxx>
30 #include <gp_Pln.hxx>
31 #include <gp_Pnt.hxx>
32 #include <gp_Sphere.hxx>
33 #include <gp_Torus.hxx>
34 #include <Precision.hxx>
35 #include <Standard_NotImplemented.hxx>
36 #include <Standard_OutOfRange.hxx>
37 #include <Standard_TypeMismatch.hxx>
38 #include <StdFail_NotDone.hxx>
39
40 //=======================================================================
41 //function : IsoIsDeg
42 //purpose  : 
43 //=======================================================================
44 static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
45                                    const Standard_Real      Param,
46                                    const GeomAbs_IsoType    IT,
47                                    const Standard_Real      TolMin,
48                                    const Standard_Real      TolMax) 
49 {
50     Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
51     Standard_Boolean Along = Standard_True;
52     U1 = S.FirstUParameter();
53     U2 = S.LastUParameter();
54     V1 = S.FirstVParameter();
55     V2 = S.LastVParameter();
56     gp_Vec D1U,D1V;
57     gp_Pnt P;
58     Standard_Real Step,D1NormMax;
59     if (IT == GeomAbs_IsoV) 
60     {
61       if( !Precision::IsInfinite(U1) &&  !Precision::IsInfinite(U2) )
62       {
63         Step = (U2 - U1)/10;
64         if(Step < Precision::PConfusion()) {
65           return Standard_False;
66         }
67         D1NormMax=0.;
68
69         for (T=U1;T<=U2;T=T+Step) 
70         {
71           S.D1(T,Param,P,D1U,D1V);
72           D1NormMax=Max(D1NormMax,D1U.Magnitude());
73         }
74
75         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
76           Along = Standard_False;
77       }
78     }
79     else 
80     {
81       if( !Precision::IsInfinite(V1) &&  !Precision::IsInfinite(V2) )
82       {
83         Step = (V2 - V1)/10;
84         if(Step < Precision::PConfusion()) {
85           return Standard_False;
86         }
87         D1NormMax=0.;
88         for (T=V1;T<=V2;T=T+Step) 
89         {
90           S.D1(Param,T,P,D1U,D1V);
91           D1NormMax=Max(D1NormMax,D1V.Magnitude());
92         }
93
94         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
95           Along = Standard_False;
96       }
97
98
99
100     }
101     return Along;
102 }
103
104 //=======================================================================
105 //function : TreatSolution
106 //purpose  : 
107 //=======================================================================
108
109 void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
110                                    const Standard_Real Val)
111 {
112   Standard_Real U, V;
113   PS.Parameter(U, V);
114   if (myS->IsUPeriodic()) {
115     U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
116     
117     // Handle trimmed surfaces.
118     if (U > myusup + mytolu)
119       U -= myS->UPeriod();
120     if (U < myuinf - mytolu)
121       U += myS->UPeriod();
122   }
123   if (myS->IsVPeriodic()) {
124     V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
125
126     // Handle trimmed surfaces.
127     if (V > myvsup + mytolv)
128       V -= myS->VPeriod();
129     if (V < myvinf - mytolv)
130       V += myS->VPeriod();
131   }
132   if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu &&
133       (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) {
134     myPoints.Append(Extrema_POnSurf (U, V, PS.Value()));
135     mySqDist.Append(Val);
136   }
137 }
138
139
140 //=======================================================================
141 //function : Extrema_ExtPS
142 //purpose  : 
143 //=======================================================================
144
145 Extrema_ExtPS::Extrema_ExtPS()
146 : myS(NULL),
147   myDone(Standard_False),
148   myuinf(0.0),
149   myusup(0.0),
150   myvinf(0.0),
151   myvsup(0.0),
152   mytolu(0.0),
153   mytolv(0.0),
154   d11(0.0),
155   d12(0.0),
156   d21(0.0),
157   d22(0.0),
158   mytype(GeomAbs_OtherSurface)
159 {
160 }
161
162
163 //=======================================================================
164 //function : Extrema_ExtPS
165 //purpose  : 
166 //=======================================================================
167
168 Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
169                               const Adaptor3d_Surface& theS,
170                               const Standard_Real      theTolU,
171                               const Standard_Real      theTolV,
172                               const Extrema_ExtFlag    theF,
173                               const Extrema_ExtAlgo    theA)
174 {
175   myExtPS.SetFlag (theF);
176   myExtPS.SetAlgo (theA);
177
178   Initialize (theS,
179               theS.FirstUParameter(),
180               theS.LastUParameter(),
181               theS.FirstVParameter(),
182               theS.LastVParameter(),
183               theTolU,
184               theTolV);
185
186   Perform (theP);
187 }
188
189 //=======================================================================
190 //function : Extrema_ExtPS
191 //purpose  : 
192 //=======================================================================
193
194 Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
195                               const Adaptor3d_Surface& theS,
196                               const Standard_Real      theUinf,
197                               const Standard_Real      theUsup,
198                               const Standard_Real      theVinf,
199                               const Standard_Real      theVsup,
200                               const Standard_Real      theTolU,
201                               const Standard_Real      theTolV,
202                               const Extrema_ExtFlag    theF,
203                               const Extrema_ExtAlgo    theA)
204 {
205   myExtPS.SetFlag (theF);
206   myExtPS.SetAlgo (theA);
207
208   Initialize (theS,
209               theUinf,
210               theUsup,
211               theVinf,
212               theVsup,
213               theTolU,
214               theTolV);
215
216   Perform (theP);
217 }
218
219
220 //=======================================================================
221 //function : Initialize
222 //purpose  : 
223 //=======================================================================
224
225 void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS,
226                                 const Standard_Real      theUinf,
227                                 const Standard_Real      theUsup,
228                                 const Standard_Real      theVinf,
229                                 const Standard_Real      theVsup,
230                                 const Standard_Real      theTolU,
231                                 const Standard_Real      theTolV)
232 {
233   myS = &theS;
234   myuinf = theUinf;
235   myusup = theUsup;
236   myvinf = theVinf;
237   myvsup = theVsup;
238
239   if (Precision::IsNegativeInfinite(myuinf)) myuinf = -1e10;
240   if (Precision::IsPositiveInfinite(myusup)) myusup = 1e10;
241   if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10;
242   if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10;
243
244   mytolu = theTolU;
245   mytolv = theTolV;
246   mytype = myS->GetType();
247
248   Standard_Boolean isB = ( myS->GetType() == GeomAbs_BSplineSurface ||
249                            myS->GetType() == GeomAbs_BezierSurface );
250
251   Standard_Integer nbU = (isB) ? 44 : 32;
252   Standard_Integer nbV = (isB) ? 44 : 32;
253
254   Standard_Boolean bUIsoIsDeg = Standard_False, bVIsoIsDeg = Standard_False;
255
256   if(myS->GetType() != GeomAbs_Plane) {
257     bUIsoIsDeg = IsoIsDeg(theS, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
258                  IsoIsDeg(theS, myusup, GeomAbs_IsoU, 0., 1.e-9);
259     bVIsoIsDeg = IsoIsDeg(theS, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
260                  IsoIsDeg(theS, myvsup, GeomAbs_IsoV, 0., 1.e-9);
261   }
262
263   if(bUIsoIsDeg) nbU = 300;
264   if(bVIsoIsDeg) nbV = 300;
265
266   myExtPS.Initialize(*myS, nbU, nbV, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
267
268   myExtPExtS.Nullify();
269   myExtPRevS.Nullify();
270 }
271
272 //=======================================================================
273 //function : Perform
274 //purpose  : 
275 //=======================================================================
276
277 void Extrema_ExtPS::Perform(const gp_Pnt& thePoint)
278 {
279   myPoints.Clear();
280   mySqDist.Clear();
281
282   switch (mytype)
283   {
284     case GeomAbs_Cylinder:
285       myExtPElS.Perform (thePoint, myS->Cylinder(), Precision::Confusion());
286       break;
287     case GeomAbs_Plane:
288       myExtPElS.Perform (thePoint, myS->Plane(), Precision::Confusion());
289       break;
290     case GeomAbs_Cone:
291       myExtPElS.Perform (thePoint, myS->Cone(), Precision::Confusion());
292       break;
293     case GeomAbs_Sphere:
294       myExtPElS.Perform (thePoint, myS->Sphere(), Precision::Confusion());
295       break;
296     case GeomAbs_Torus:
297       myExtPElS.Perform (thePoint, myS->Torus(), Precision::Confusion());
298       break;
299
300     case GeomAbs_SurfaceOfExtrusion:
301     {
302       if (myExtPExtS.IsNull())
303       {
304         Handle(GeomAdaptor_SurfaceOfLinearExtrusion) aS (new GeomAdaptor_SurfaceOfLinearExtrusion (
305           GeomAdaptor_SurfaceOfLinearExtrusion (myS->BasisCurve(), myS->Direction())));
306
307         myExtPExtS = new Extrema_ExtPExtS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
308       }
309       else
310       {
311         myExtPExtS->Perform (thePoint);
312       }
313
314       myDone = myExtPExtS->IsDone();
315       if (myDone)
316       {
317         for (Standard_Integer anIdx = 1; anIdx <= myExtPExtS->NbExt(); ++anIdx)
318         {
319           TreatSolution (myExtPExtS->Point (anIdx), myExtPExtS->SquareDistance (anIdx));
320         }
321       }
322
323       return;
324     }
325
326     case GeomAbs_SurfaceOfRevolution:
327     {
328       if (myExtPRevS.IsNull())
329       {
330         Handle(GeomAdaptor_SurfaceOfRevolution) aS (new GeomAdaptor_SurfaceOfRevolution (
331           GeomAdaptor_SurfaceOfRevolution (myS->BasisCurve(), myS->AxeOfRevolution())));
332
333         myExtPRevS = new Extrema_ExtPRevS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
334       }
335       else
336       {
337         myExtPRevS->Perform (thePoint);
338       }
339
340       myDone = myExtPRevS->IsDone();
341       if (myDone)
342       {
343         for (Standard_Integer anIdx = 1; anIdx <= myExtPRevS->NbExt(); ++anIdx)
344         {
345           TreatSolution (myExtPRevS->Point (anIdx), myExtPRevS->SquareDistance (anIdx));
346         }
347       }
348
349       return;
350     }
351
352     default:
353     {
354       myExtPS.Perform (thePoint);
355       myDone = myExtPS.IsDone();
356       if (myDone)
357       {
358         for (Standard_Integer anIdx = 1; anIdx <= myExtPS.NbExt(); ++anIdx)
359         {
360           TreatSolution (myExtPS.Point (anIdx), myExtPS.SquareDistance (anIdx));
361         }
362       }
363       return;
364     }
365   }
366
367   myDone = myExtPElS.IsDone();
368   if (myDone)
369   {
370     for (Standard_Integer anIdx = 1; anIdx <= myExtPElS.NbExt(); ++anIdx)
371     {
372       TreatSolution (myExtPElS.Point (anIdx), myExtPElS.SquareDistance (anIdx));
373     }
374   }
375 }
376
377
378 Standard_Boolean Extrema_ExtPS::IsDone() const
379 {
380   return myDone;
381 }
382
383
384 Standard_Real Extrema_ExtPS::SquareDistance(const Standard_Integer N) const
385 {
386   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
387   return mySqDist.Value(N);
388 }
389
390
391 Standard_Integer Extrema_ExtPS::NbExt() const
392 {
393   if (!IsDone()) throw StdFail_NotDone();
394   return mySqDist.Length();
395 }
396
397
398 const Extrema_POnSurf& Extrema_ExtPS::Point(const Standard_Integer N) const
399 {
400   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
401   return myPoints.Value(N);
402 }
403
404
405 void Extrema_ExtPS::TrimmedSquareDistances(Standard_Real& dUfVf,
406                                       Standard_Real& dUfVl,
407                                       Standard_Real& dUlVf,
408                                       Standard_Real& dUlVl,
409                                       gp_Pnt&        PUfVf,
410                                       gp_Pnt&        PUfVl,
411                                       gp_Pnt&        PUlVf,
412                                       gp_Pnt&        PUlVl) const
413 {
414   dUfVf = d11;
415   dUfVl = d12;
416   dUlVf = d21;
417   dUlVl = d22;
418   PUfVf = P11;
419   PUfVl = P12;
420   PUlVf = P21;
421   PUlVl = P22;
422 }
423
424 void Extrema_ExtPS::SetFlag(const Extrema_ExtFlag F)
425 {
426   myExtPS.SetFlag(F);
427 }
428
429 void Extrema_ExtPS::SetAlgo(const Extrema_ExtAlgo A)
430 {
431   myExtPS.SetAlgo(A);
432 }