0030611: Coding Rules - eliminate GCC compiler warnings -Wcatch-value
[occt.git] / src / IntPatch / IntPatch_SpecialPoints.cxx
CommitLineData
e2e0498b 1//! Created on: 2016-06-03
2//! Created by: NIKOLAI BUKHALOV
3//! Copyright (c) 2016 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <IntPatch_SpecialPoints.hxx>
17
18#include <Adaptor3d_HSurface.hxx>
3306fdd9 19#include <ElCLib.hxx>
e2e0498b 20#include <Extrema_ExtPS.hxx>
21#include <Extrema_GenLocateExtPS.hxx>
22#include <Geom_ConicalSurface.hxx>
23#include <Geom_SphericalSurface.hxx>
24#include <IntPatch_Point.hxx>
25#include <IntSurf.hxx>
26#include <IntSurf_PntOn2S.hxx>
27#include <Standard_TypeMismatch.hxx>
28#include <math_FunctionSetRoot.hxx>
29#include <math_FunctionSetWithDerivatives.hxx>
30#include <math_Matrix.hxx>
31
32// The function for searching intersection point, which
33// lies in the seam-edge of the quadric definetely.
34class FuncPreciseSeam: public math_FunctionSetWithDerivatives
35{
36public:
37 FuncPreciseSeam(const Handle(Adaptor3d_HSurface)& theQSurf, // quadric
38 const Handle(Adaptor3d_HSurface)& thePSurf, // another surface
3306fdd9 39 const Standard_Boolean isTheUSeam,
40 const Standard_Real theIsoParameter):
e2e0498b 41 myQSurf(theQSurf),
42 myPSurf(thePSurf),
3306fdd9 43 mySeamCoordInd(isTheUSeam? 1 : 0), // Defines, U- or V-seam is used
44 myIsoParameter(theIsoParameter)
e2e0498b 45 {
46 };
47
48 virtual Standard_Integer NbVariables() const
49 {
50 return 3;
51 };
52
53 virtual Standard_Integer NbEquations() const
54 {
55 return 3;
56 }
57
58 virtual Standard_Boolean Value(const math_Vector& theX,
59 math_Vector& theF)
60 {
61 try
62 {
63 const Standard_Integer anIndX = theX.Lower(), anIndF = theF.Lower();
3306fdd9 64 Standard_Real aUV[] = {myIsoParameter, myIsoParameter};
e2e0498b 65 aUV[mySeamCoordInd] = theX(anIndX+2);
66 const gp_Pnt aP1(myPSurf->Value(theX(anIndX), theX(anIndX+1)));
67 const gp_Pnt aP2(myQSurf->Value(aUV[0], aUV[1]));
68
69 (aP1.XYZ()-aP2.XYZ()).Coord(theF(anIndF), theF(anIndF+1), theF(anIndF+2));
70 }
a738b534 71 catch(Standard_Failure const&)
e2e0498b 72 {
73 return Standard_False;
74 }
75
76 return Standard_True;
77 };
78
79 virtual Standard_Boolean Derivatives(const math_Vector& theX,
80 math_Matrix& theD)
81 {
82 try
83 {
84 const Standard_Integer anIndX = theX.Lower(),
85 anIndRD = theD.LowerRow(),
86 anIndCD = theD.LowerCol();
3306fdd9 87 Standard_Real aUV[] = {myIsoParameter, myIsoParameter};
e2e0498b 88 aUV[mySeamCoordInd] = theX(anIndX+2);
89
90 gp_Pnt aPt;
91
92 //0 for U-coordinate, 1 - for V one
93 gp_Vec aD1[2], aD2[2];
94 myPSurf->D1(theX(anIndX), theX(anIndX+1), aPt, aD1[0], aD1[1]);
95 myQSurf->D1(aUV[0], aUV[1], aPt, aD2[0], aD2[1]);
96
97 // d/dX1
98 aD1[0].Coord(theD(anIndRD, anIndCD),
99 theD(anIndRD+1, anIndCD), theD(anIndRD+2, anIndCD));
100
101 // d/dX2
102 aD1[1].Coord(theD(anIndRD, anIndCD+1),
103 theD(anIndRD+1, anIndCD+1), theD(anIndRD+2, anIndCD+1));
104
105 // d/dX3
106 aD2[mySeamCoordInd].Reversed().Coord(theD(anIndRD, anIndCD+2),
107 theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2));
108 }
a738b534 109 catch(Standard_Failure const&)
e2e0498b 110 {
111 return Standard_False;
112 }
113
114 return Standard_True;
115 };
116
117 virtual Standard_Boolean Values (const math_Vector& theX,
118 math_Vector& theF,
119 math_Matrix& theD)
120 {
121 if(!Value(theX, theF))
122 return Standard_False;
123
124 if(!Derivatives(theX, theD))
125 return Standard_False;
126
127 return Standard_True;
128 }
129
130protected:
131 FuncPreciseSeam operator=(FuncPreciseSeam&);
132
133private:
134 const Handle(Adaptor3d_HSurface)& myQSurf;
135 const Handle(Adaptor3d_HSurface)& myPSurf;
136
3306fdd9 137 //! 1 for U-coordinate, 0 - for V one.
e2e0498b 138 const Standard_Integer mySeamCoordInd;
3306fdd9 139
140 //! Constant parameter of iso-line
141 const Standard_Real myIsoParameter;
e2e0498b 142};
143
3306fdd9 144//=======================================================================
145//function : GetTangent
146//purpose : Computes tangent having the given parameter.
147// See calling method(s) for detailed information
148//=======================================================================
149static inline void GetTangent(const Standard_Real theConeSemiAngle,
150 const Standard_Real theParameter,
151 gp_XYZ& theResult)
152{
153 const Standard_Real aW2 = theParameter*theParameter;
154 const Standard_Real aCosUn = (1.0 - aW2) / (1.0 + aW2);
155 const Standard_Real aSinUn = 2.0*theParameter / (1.0 + aW2);
156
157 const Standard_Real aTanA = Tan(theConeSemiAngle);
158 theResult.SetCoord(aTanA*aCosUn, aTanA*aSinUn, 1.0);
159}
160
e2e0498b 161//=======================================================================
162//function : IsPointOnSurface
163//purpose : Checks if thePt is in theSurf (with given tolerance).
164// Returns the foot of projection (theProjPt) and its parameters
165// on theSurf.
166//=======================================================================
167static Standard_Boolean IsPointOnSurface(const Handle(Adaptor3d_HSurface)& theSurf,
168 const gp_Pnt& thePt,
169 const Standard_Real theTol,
170 gp_Pnt& theProjPt,
171 Standard_Real& theUpar,
172 Standard_Real& theVpar)
173{
174 Standard_Boolean aRetVal = Standard_False;
175
176 switch(theSurf->GetType())
177 {
178 case GeomAbs_Plane:
179 case GeomAbs_Cylinder:
180 case GeomAbs_Cone:
181 case GeomAbs_Sphere:
182 case GeomAbs_Torus:
183 case GeomAbs_SurfaceOfExtrusion:
184 case GeomAbs_SurfaceOfRevolution:
185 {
186 Extrema_ExtPS anExtr(thePt, theSurf->Surface(), theSurf->UResolution(theTol),
187 theSurf->VResolution(theTol), Extrema_ExtFlag_MIN);
188 if(!anExtr.IsDone() || (anExtr.NbExt() < 1))
189 {
190 aRetVal = Standard_False;
191 }
192 else
193 {
194 Standard_Integer anExtrIndex = 1;
195 Standard_Real aSqDistMin = anExtr.SquareDistance(anExtrIndex);
196 for(Standard_Integer i = anExtrIndex + 1; i <= anExtr.NbExt(); i++)
197 {
198 const Standard_Real aSqD = anExtr.SquareDistance(i);
199 if(aSqD < aSqDistMin)
200 {
201 aSqDistMin = aSqD;
202 anExtrIndex = i;
203 }
204 }
205
206 if(aSqDistMin > theTol*theTol)
207 {
208 aRetVal = Standard_False;
209 }
210 else
211 {
212 theProjPt.SetXYZ(anExtr.Point(anExtrIndex).Value().XYZ());
213 anExtr.Point(anExtrIndex).Parameter(theUpar, theVpar);
214 aRetVal = Standard_True;
215 }
216 }
217 }
218 break;
219 default:
220 {
221 Extrema_GenLocateExtPS anExtr(theSurf->Surface());
222 anExtr.Perform(thePt, theUpar, theVpar);
223 if(!anExtr.IsDone() || (anExtr.SquareDistance() > theTol*theTol))
224 {
225 aRetVal = Standard_False;
226 }
227 else
228 {
229 anExtr.Point().Parameter(theUpar, theVpar);
230 theProjPt.SetXYZ(anExtr.Point().Value().XYZ());
231 aRetVal = Standard_True;
232 }
233 }
234 break;
235 }
236
237 return aRetVal;
238}
239
240//=======================================================================
241//function : AddCrossUVIsoPoint
242//purpose : theQSurf is the surface possibly containing special point,
243// thePSurf is another surface to intersect.
244//=======================================================================
245Standard_Boolean IntPatch_SpecialPoints::
246 AddCrossUVIsoPoint(const Handle(Adaptor3d_HSurface)& theQSurf,
247 const Handle(Adaptor3d_HSurface)& thePSurf,
248 const IntSurf_PntOn2S& theRefPt,
249 const Standard_Real theTol,
250 IntSurf_PntOn2S& theAddedPoint,
251 const Standard_Boolean theIsReversed)
252{
253 Standard_Real anArrOfPeriod[4] = {0.0, 0.0, 0.0, 0.0};
254 IntSurf::SetPeriod(theIsReversed ? thePSurf : theQSurf,
255 theIsReversed ? theQSurf : thePSurf, anArrOfPeriod);
256
257 gp_Pnt aPQuad;
258
259 //Not quadric point
260 Standard_Real aU0 = 0.0, aV0 = 0.0;
261 if(theIsReversed)
262 theRefPt.ParametersOnS1(aU0, aV0);
263 else
264 theRefPt.ParametersOnS2(aU0, aV0);
265
266 //Quadric point
267 Standard_Real aUquad = 0.0, aVquad = 0.0;
268
269 theQSurf->D0(aUquad, aVquad, aPQuad);
270
271 Extrema_GenLocateExtPS anExtr(thePSurf->Surface());
272 anExtr.Perform(aPQuad, aU0, aV0);
273
274 if(!anExtr.IsDone())
275 {
276 return Standard_False;
277 }
278
279 if(anExtr.SquareDistance() > theTol*theTol)
280 {
281 return Standard_False;
282 }
283
284 anExtr.Point().Parameter(aU0, aV0);
285 gp_Pnt aP0(anExtr.Point().Value());
286
287 if(theIsReversed)
288 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad);
289 else
290 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0);
291
292 AdjustPointAndVertex(theRefPt, anArrOfPeriod, theAddedPoint);
293
294 return Standard_True;
295}
296
297//=======================================================================
298//function : AddPointOnUorVIso
299//purpose : theQSurf is the surface possibly containing special point,
300// thePSurf is another surface to intersect.
301//=======================================================================
302Standard_Boolean IntPatch_SpecialPoints::
303 AddPointOnUorVIso(const Handle(Adaptor3d_HSurface)& theQSurf,
304 const Handle(Adaptor3d_HSurface)& thePSurf,
305 const IntSurf_PntOn2S& theRefPt,
306 const Standard_Boolean theIsU,
3306fdd9 307 const Standard_Real theIsoParameter,
e2e0498b 308 const math_Vector& theToler,
309 const math_Vector& theInitPoint,
310 const math_Vector& theInfBound,
311 const math_Vector& theSupBound,
312 IntSurf_PntOn2S& theAddedPoint,
313 const Standard_Boolean theIsReversed)
314{
315 Standard_Real anArrOfPeriod[4] = {0.0, 0.0, 0.0, 0.0};
316 IntSurf::SetPeriod(theIsReversed ? thePSurf : theQSurf,
317 theIsReversed ? theQSurf : thePSurf, anArrOfPeriod);
318
3306fdd9 319 FuncPreciseSeam aF(theQSurf, thePSurf, theIsU, theIsoParameter);
e2e0498b 320
321 math_FunctionSetRoot aSRF(aF, theToler);
322 aSRF.Perform(aF, theInitPoint, theInfBound, theSupBound);
323
324 if(!aSRF.IsDone())
325 {
326 return Standard_False;
327 }
328
329 math_Vector aRoots(theInitPoint.Lower(), theInitPoint.Upper());
330 aSRF.Root(aRoots);
331
332 //On parametric
333 Standard_Real aU0 = aRoots(1), aV0 = aRoots(2);
334
335 //On quadric
336 Standard_Real aUquad = theIsU ? 0.0 : aRoots(3);
337 Standard_Real aVquad = theIsU ? aRoots(3) : 0.0;
338 const gp_Pnt aPQuad(theQSurf->Value(aUquad, aVquad));
339 const gp_Pnt aP0(thePSurf->Value(aU0, aV0));
340
341 if(theIsReversed)
342 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad);
343 else
344 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0);
345
346 AdjustPointAndVertex(theRefPt, anArrOfPeriod, theAddedPoint);
347 return Standard_True;
348}
349
3306fdd9 350//=======================================================================
351//function : ProcessSphere
352//purpose :
353/*
354The intersection point (including the pole)
355must be satisfied to the following system:
356
357 \left\{\begin{matrix}
358 R*\cos (U_{q})*\cos (V_{q})=S_{x}(U_{s},V_{s})
359 R*\sin (U_{q})*\cos (V_{q})=S_{y}(U_{s},V_{s})
360 R*\sin (V_{q})=S_{z}(U_{s},V_{s})
361 \end{matrix}\right,
362where
363 R is the radius of the sphere;
364 @S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf;
365 @U_{s}@ and @V_{s}@ are parameters on the parametric surface;
366 @U_{q}@ and @V_{q}@ are equal to theUquad and theVquad correspondingly.
367
368Consequently (from first two equations),
369 \left\{\begin{matrix}
370 \cos (U_{q}) = \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}
371 \sin (U_{q}) = \frac{S_{y}(U_{s},V_{s})}{R*\cos (V_{q})}
372 \end{matrix}\right.
373
374For pole,
375 V_{q}=\pm \pi /2 \Rightarrow \cos (V_{q}) = 0 (denominator is equal to 0).
376
377Therefore, computation U_{q} directly is impossibly.
378
379Let @V_{q}@ tends to @\pm \pi /2@.
380Then (indeterminate form is evaluated in accordance of L'Hospital rule),
381 \cos (U_{q}) = \lim_{V_{q} \to (\pi /2-0)}
382 \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}=
383 -\lim_{V_{q} \to (\pi /2-0)}
384 \frac{\frac{\partial S_{x}}
385 {\partial U_{s}}*\frac{\mathrm{d} U_{s}}
386 {\mathrm{d} V_{q}}+\frac{\partial S_{x}}
387 {\partial V_{s}}*\frac{\mathrm{d} V_{s}}
388 {\mathrm{d} V_{q}}}{R*\sin (V_{q})} =
389 -\frac{1}{R}*\frac{\mathrm{d} U_{s}}
390 {\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
391 {\partial U_{s}}+\frac{\partial S_{x}}
392 {\partial V_{s}}*\frac{\mathrm{d} V_{s}}
393 {\mathrm{d} U_{s}}) =
394 -\frac{1}{R}*\frac{\mathrm{d} V_{s}}
395 {\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
396 {\partial U_{s}}*\frac{\mathrm{d} U_{s}}
397 {\mathrm{d} V_{s}}+\frac{\partial S_{x}}
398 {\partial V_{s}}).
399
400Analogicaly for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@).
401
402Let mean, that
403 \cos (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \cos (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
404 \sin (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \sin (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
405
406From the 3rd equation of the system, we obtain
407 \frac{\mathrm{d} (R*\sin (V_{q}))}{\mathrm{d} V_{q}} =
408 \frac{\mathrm{d} S_{z}(U_{s},V_{s})}{\mathrm{d} V_{q}}
409or
410 R*\cos (V_{q}) = \frac{\partial S_{z}}{\partial U_{s}}*
411 \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
412 {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}}.
413
414If @V_{q}=\pm \pi /2@, then
415 \frac{\partial S_{z}}{\partial U_{s}}*
416 \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
417 {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}} = 0.
418
419Consequently, if @\frac{\partial S_{z}}{\partial U_{s}} \neq 0 @ then
420 \frac{\mathrm{d} U_{s}}{\mathrm{d} V_{s}} =
421 -\frac{\frac{\partial S_{z}}{\partial V_{s}}}
422 {\frac{\partial S_{z}}{\partial U_{s}}}.
423
424If @ \frac{\partial S_{z}}{\partial V_{s}} \neq 0 @ then
425 \frac{\mathrm{d} V_{s}}{\mathrm{d} U_{s}} =
426 -\frac{\frac{\partial S_{z}}{\partial U_{s}}}
427 {\frac{\partial S_{z}}{\partial V_{s}}}
428
429Cases, when @ \frac{\partial S_{z}}{\partial U_{s}} =
430\frac{\partial S_{z}}{\partial V_{s}} = 0 @ are not consider here.
431The reason is written below.
432*/
433//=======================================================================
434Standard_Boolean IntPatch_SpecialPoints::ProcessSphere(const IntSurf_PntOn2S& thePtIso,
435 const gp_Vec& theDUofPSurf,
436 const gp_Vec& theDVofPSurf,
437 const Standard_Boolean theIsReversed,
438 const Standard_Real theVquad,
439 Standard_Real& theUquad,
440 Standard_Boolean& theIsIsoChoosen)
441{
442 theIsIsoChoosen = Standard_False;
443
444 //Vector with {@ \cos (U_{q}) @, @ \sin (U_{q}) @} coordinates.
445 //Ask to pay attention to the fact that this vector is always normalized.
446 gp_Vec2d aV1;
447
448 if ((Abs(theDUofPSurf.Z()) < Precision::PConfusion()) &&
449 (Abs(theDVofPSurf.Z()) < Precision::PConfusion()))
450 {
451 //Example of this case is an intersection of a plane with a sphere
452 //when the plane tangents the sphere in some pole (i.e. only one
453 //intersection point, not line). In this case, U-coordinate of the
454 //sphere is undefined (can be realy anything).
455 //Another reason is that we have tangent zone around the pole
456 //(see bug #26576).
457 //Computation of correct value of theUquad is impossible.
458 //Therefore, (in order to return something) we will consider
459 //the intersection line goes along some isoline in neighborhood
460 //of the pole.
461
462#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG
463 cout << "Cannot find UV-coordinate for quadric in the pole."
464 " See considered comment above. IntPatch_SpecialPoints.cxx,"
465 " ProcessSphere(...)" << endl;
466#endif
467 Standard_Real aUIso = 0.0, aVIso = 0.0;
468 if (theIsReversed)
469 thePtIso.ParametersOnS2(aUIso, aVIso);
470 else
471 thePtIso.ParametersOnS1(aUIso, aVIso);
472
473 theUquad = aUIso;
474 theIsIsoChoosen = Standard_True;
475 }
476 else
477 {
478 if (Abs(theDUofPSurf.Z()) > Abs(theDVofPSurf.Z()))
479 {
480 const Standard_Real aDusDvs = theDVofPSurf.Z() / theDUofPSurf.Z();
481 aV1.SetCoord(theDUofPSurf.X()*aDusDvs - theDVofPSurf.X(),
482 theDUofPSurf.Y()*aDusDvs - theDVofPSurf.Y());
483 }
484 else
485 {
486 const Standard_Real aDvsDus = theDUofPSurf.Z() / theDVofPSurf.Z();
487 aV1.SetCoord(theDVofPSurf.X()*aDvsDus - theDUofPSurf.X(),
488 theDVofPSurf.Y()*aDvsDus - theDUofPSurf.Y());
489 }
490
491 aV1.Normalize();
492
493 if (Abs(aV1.X()) > Abs(aV1.Y()))
494 theUquad = Sign(asin(aV1.Y()), theVquad);
495 else
496 theUquad = Sign(acos(aV1.X()), theVquad);
497 }
498
499 return Standard_True;
500}
501
502//=======================================================================
503//function : ProcessCone
504//purpose :
505/*
506The intersection point (including the pole)
507must be satisfied to the following system:
508
509 \left\{\begin {matrix}
510 (V_{q}\sin(a) + R)*\cos(U_{q})) = S_{x}(U_{s}, V_{s})\\
511 (V_{q}\sin(a) + R)*\sin(U_{q})) = S_{y}(U_{s}, V_{s})\\
512 V_{q}\cos(a) = S_{z}(U_{s}, V_{s})
513 \end {matrix}\right,
514where
515 R is the radius of the cone;
516 a is its semi-angle;
517 @S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf;
518 @U_{s}@ and @V_{s}@ are parameters on the parametric surface;
519 @U_{q}@ and @V_{q}@ are equal to theUquad and theVquad correspondingly.
520
521Consequently (from first two equations),
522 \left\{\begin{matrix}
523 \cos(U_{q})=\frac{S_{x}(U_{s},V_{s})}{(V_{q}\sin(a)+R)}\\
524 \sin(U_{q})=\frac{S_{y}(U_{s}, V_{s})}{(V_{q}\sin(a)+R)}
525 \end{matrix}\right.
526
527For pole, the denominator of these two equations is equal to 0.
528Therefore, computation U_{q} directly is impossibly.
529
530Let @V_{q}@ tends to @\frac{-R}{\sin(a)})@.
531Then (indeterminate form is evaluated in accordance of L'Hospital rule),
532
533 \cos (U_{q}) =
534 \lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{S_{x}(U_{s},V_{s})}{(V_{q}\sin(a)+R)}=
535 \frac{1}{\sin(a)}* \lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{dU_{s}}{dV_{q}}*
536 (\frac{\partial S_{x}}{\partial U_{s}}+\frac{\partial S_{x}}{\partial V_{s}}*
537 \frac{dV_{s}}{dU_{s}})=
538 \frac{1}{\sin(a)}* \lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{dV_{s}}{dV_{q}}*
539 (\frac{\partial S_{x}}{\partial U_{s}}*
540 \frac{dU_{s}}{dV_{s}}+\frac{\partial S_{x}}{\partial V_{s}})
541
542Analogically for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@).
543
544After differentiating 3rd equation of the system, we will obtain
545 \cos(a)=\frac{dS_{z}}{dV_{q}}=\frac{dU_{s}}{dV_{q}}*
546 (\frac{\partial S_{z}}{\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*
547 \frac{dV_{s}}{dU_{s}})
548or
549 \frac{dU_{s}}{dV_{q}}=\frac{\cos(a)}{\frac{\partial S_{z}}{\partial U_{s}}+
550 \frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
551
552After substituting we will obtain
553 \cos (U_{q}) =
554 \cot(a)*\frac{\frac{\partial S_{x}}{\partial U_{s}}+\frac{\partial S_{x}}
555 {\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}{\frac{\partial S_{z}}
556 {\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
557
558 \sin (U_{q}) =
559 \cot(a)*\frac{\frac{\partial S_{y}}{\partial U_{s}}+\frac{\partial S_{y}}
560 {\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}{\frac{\partial S_{z}}
561 {\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
562
563So, we have obtained vector with coordinates {@ \cos (U_{q}) @, @ \sin (U_{q}) @}.
564Ask to pay attention to the fact that this vector is always normalized.
565And after normalization this vector will have coordinates
566 {\cos (U_{q}), \sin (U_{q})} = {dS_{x}, dS_{y}}.Normalized().
567
568It means that we have to compute a tangent to the intersection curve in
569the cone apex point. After that, just take its X- and Y-coordinates.
570
571However, we have to compute derivative @\frac{dV_{s}}{dU_{s}}@ in order
572to compute this vector. In order to find this derivative, we use the
573information about direction of tangent to the intersection curve.
574This tangent will be directed along the cone generatrix obtained by intersection
575of the cone with a plane tangent to 2nd (intersected) surface.
576*/
577//=======================================================================
578Standard_Boolean IntPatch_SpecialPoints::ProcessCone(const IntSurf_PntOn2S& thePtIso,
579 const gp_Vec& theDUofPSurf,
580 const gp_Vec& theDVofPSurf,
581 const gp_Cone& theCone,
582 const Standard_Boolean theIsReversed,
583 Standard_Real& theUquad,
584 Standard_Boolean& theIsIsoChoosen)
585{
586 theIsIsoChoosen = Standard_False;
587
588 // A plane tangent to 2nd (intersected) surface.
589 // Its normal.
590 const gp_XYZ aTgPlaneZ(theDUofPSurf.Crossed(theDVofPSurf).XYZ());
591 const Standard_Real aSqModTg = aTgPlaneZ.SquareModulus();
592 if (aSqModTg < Precision::SquareConfusion())
593 {
594 theIsIsoChoosen = Standard_True;
595 }
596
597 gp_XYZ aTgILine[2];
598 const Standard_Integer aNbTangent = !theIsIsoChoosen?
599 GetTangentToIntLineForCone(theCone.SemiAngle(),
600 aTgPlaneZ.Divided(Sqrt(aSqModTg)),
601 aTgILine) : 0;
602
603 if (aNbTangent == 0)
604 {
605 theIsIsoChoosen = Standard_True;
606 }
607 else
608 {
609 const Standard_Real aPeriod = M_PI + M_PI;
610 Standard_Real aUIso = 0.0, aVIso = 0.0;
611 if (theIsReversed)
612 thePtIso.ParametersOnS2(aUIso, aVIso);
613 else
614 thePtIso.ParametersOnS1(aUIso, aVIso);
615
616 aUIso = ElCLib::InPeriod(aUIso, 0.0, aPeriod);
617
618 // Sought U-parameter in the apex point
619
620 // For 2 possible parameters value,
621 // one will be chosen which is nearer
622 // to aUIso. Following variables will help to chose.
623 Standard_Real aMinDelta = RealLast();
624 for (Standard_Integer anIdx = 0; anIdx < aNbTangent; anIdx++)
625 {
626 // Vector {@\cos(a), \sin(a)@}
627 gp_Vec2d aVecCS(aTgILine[anIdx].X(), aTgILine[anIdx].Y());
628 const Standard_Real aSqMod = aVecCS.SquareMagnitude();
629 if (aSqMod < Precision::SquareConfusion())
630 {
631 theIsIsoChoosen = Standard_True;
632 break;
633 }
634
635 // Normalize
636 aVecCS.Divide(Sqrt(aSqMod));
637
638 // Angle in range [0, PI/2]
639 Standard_Real anUq = (Abs(aVecCS.X()) < Abs(aVecCS.Y())) ? ACos(Abs(aVecCS.X())) : ASin(Abs(aVecCS.Y()));
640
641 // Convert angles to the range [0, 2*PI]
642 if (aVecCS.Y() < 0.0)
643 {
644 if (aVecCS.X() > 0.0)
645 {
646 anUq = -anUq;
647 }
648 else
649 {
650 anUq += M_PI;
651 }
652 }
653 else if (aVecCS.X() < 0.0)
654 {
655 anUq = M_PI - anUq;
656 }
657
658 //Select the parameter the nearest to aUIso
659 anUq = ElCLib::InPeriod(anUq, 0.0, aPeriod);
660 Standard_Real aDelta = Abs(anUq - aUIso);
661 if (aDelta > M_PI)
662 aDelta = aPeriod - aDelta;
663
664 if (aDelta < aMinDelta)
665 {
666 aMinDelta = aDelta;
667 theUquad = anUq;
668 }
669 }
670 }
671
672 if (theIsIsoChoosen)
673 {
674#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG
675 cout << "Cannot find UV-coordinate for quadric in the pole."
676 " IntPatch_AddSpecialPoints.cxx, ProcessCone(...)" << endl;
677#endif
678 theIsIsoChoosen = Standard_True;
679
680 Standard_Real aUIso = 0.0, aVIso = 0.0;
681 if (theIsReversed)
682 thePtIso.ParametersOnS2(aUIso, aVIso);
683 else
684 thePtIso.ParametersOnS1(aUIso, aVIso);
685
686 theUquad = aUIso;
687 return Standard_True;
688 }
689 else
690 {
691 return Standard_True;
692 }
693
694 //return Standard_False;
695}
696
697//=======================================================================
698//function : GetTangentToIntLineForCone
699//purpose : The following conditions must be satisfied:
700//1. The cone is represented in its canonical form.
701//2. The plane goes through the cone apex and has the normal vector thePlnNormal.
702//3. Vector thePlnNormal has already been normalized
703/*
704Let us enter the new coordinate system where the origin will be in the cone apex
705and axes are the same as in World-Coordinate-System (WCS).
706There the horizontal plane (which is parallel XY-plane) with the origin
707(0, 0, 1) will intersect the cone by the circle with center (0, 0, 1),
708direction {0, 0, 1} and radius tg(a) where a is the cone semi-angle.
709Its equation will be
710\left\{\begin{matrix}
711x(U_{n}) = \tan(a)*\cos(U_{n}) = \tan(a)*\frac{1-\tan^{2}(U_{n}/2)}{1+\tan^{2}(U_{n}/2)}\\
712y(U_{n}) = \tan(a)*\sin (U_{n}) = \tan(a)*\frac{2*\tan(U_{n}/2)}{1+\tan^{2}(U_{n}/2)}\\
713z(U_{n}) = 1
714\end{matrix}\right.
715
716The given plane has (in this coordinate system) location (0, 0, 0) and
717the same normal thePlnNormal=={nx,ny,nz}. Its equation is:
718nx*x+ny*y+nz*z==0
719
720After substitution circle's equation to the plane's equation
721we will obtain a quadratic equation
722aA*w^2 + 2*aB*w + aC = 0.
723*/
724//=======================================================================
725Standard_Integer IntPatch_SpecialPoints::GetTangentToIntLineForCone(const Standard_Real theConeSemiAngle,
726 const gp_XYZ& thePlnNormal,
727 gp_XYZ theResult[2])
728{
729 const Standard_Real aNullTol = Epsilon(1.0);
730 const Standard_Real aTanA = Tan(theConeSemiAngle);
731 const Standard_Real aA = thePlnNormal.Z() / aTanA - thePlnNormal.X();
732 const Standard_Real aB = thePlnNormal.Y();
733 const Standard_Real aC = thePlnNormal.Z() / aTanA + thePlnNormal.X();
734
735 if (Abs(aA) < aNullTol)
736 {
737 if (Abs(aB) > aNullTol)
738 {
739 //The plane goes along the cone generatrix.
740 GetTangent(theConeSemiAngle, -aC / (aB + aB), theResult[0]);
741 return 1;
742 }
743
744 //The cone and the plane have only one common point.
745 //It is the cone apex.
746 return 0;
747 }
748
749 //Discriminant of this equation is equal to
750 Standard_Real aDiscr = thePlnNormal.Z() / Sin(theConeSemiAngle);
751 aDiscr = 1.0 - aDiscr*aDiscr;
752
753 if (Abs(aDiscr) < aNullTol)
754 {
755 //The plane goes along the cone generatrix.
756 // Attention! Mathematically, this cond. is equivalent to
757 // above processed one (Abs(aA) < aNullTol && (Abs(aB) > aNullTol)).
758 // However, we separate this branch in order to eliminate numerical
759 // instability.
760
761 GetTangent(theConeSemiAngle, -aB / aA, theResult[0]);
762 return 1;
763 }
764 else if (aDiscr > 0.0)
765 {
766 const Standard_Real aRD = Sqrt(aDiscr);
767 GetTangent(theConeSemiAngle, (-aB+aRD)/aA, theResult[0]);
768 GetTangent(theConeSemiAngle, (-aB-aRD)/aA, theResult[1]);
769 return 2;
770 }
771
772 // We will never come here.
773 return 0;
774}
775
e2e0498b 776//=======================================================================
777//function : AddSingularPole
778//purpose : theQSurf is the surface possibly containing special point,
779// thePSurf is another surface to intersect.
780// Returns TRUE, if the pole is an intersection point.
781//=======================================================================
782Standard_Boolean IntPatch_SpecialPoints::
783 AddSingularPole(const Handle(Adaptor3d_HSurface)& theQSurf,
784 const Handle(Adaptor3d_HSurface)& thePSurf,
785 const IntSurf_PntOn2S& thePtIso,
e2e0498b 786 IntPatch_Point& theVertex,
3306fdd9 787 IntSurf_PntOn2S& theAddedPoint,
e2e0498b 788 const Standard_Boolean theIsReversed,
789 const Standard_Boolean theIsReqRefCheck)
790{
e2e0498b 791 //On parametric
792 Standard_Real aU0 = 0.0, aV0 = 0.0;
793 //aPQuad is Pole
794 gp_Pnt aPQuad, aP0;
795 Standard_Real aUquad = 0.0, aVquad = 0.0;
796 if(theIsReversed)
797 theVertex.Parameters(aU0, aV0, aUquad, aVquad);
798 else
799 theVertex.Parameters(aUquad, aVquad, aU0, aV0);
800
801 aUquad = 0.0;
802
803 if(theQSurf->GetType() == GeomAbs_Sphere)
804 {
805 aVquad = Sign(M_PI_2, aVquad);
806 }
807 else if(theQSurf->GetType() == GeomAbs_Cone)
808 {
809 const gp_Cone aCo = theQSurf->Cone();
810 const Standard_Real aRadius = aCo.RefRadius();
811 const Standard_Real aSemiAngle = aCo.SemiAngle();
812 aVquad = -aRadius / sin(aSemiAngle);
813 }
814 else
815 {
9775fa61 816 throw Standard_TypeMismatch( "IntPatch_SpecialPoints::AddSingularPole(),"
e2e0498b 817 "Unsupported quadric with Pole");
818 }
819
820 theQSurf->D0(aUquad, aVquad, aPQuad);
3306fdd9 821 const Standard_Real aTol = theVertex.Tolerance();
822 if (theIsReqRefCheck && (aPQuad.SquareDistance(theVertex.Value()) >= aTol*aTol))
e2e0498b 823 {
824 return Standard_False;
825 }
826
3306fdd9 827 if (!IsPointOnSurface(thePSurf, aPQuad, aTol, aP0, aU0, aV0))
e2e0498b 828 {
829 return Standard_False;
830 }
831
832 //Pole is an intersection point
833 //(lies in the quadric and the parametric surface)
834
835 if(theIsReversed)
836 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad);
837 else
838 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0);
839
3306fdd9 840 const Standard_Boolean isSame = theAddedPoint.IsSame(theVertex.PntOn2S(),
841 Precision::Confusion());
e2e0498b 842
843 //Found pole does not exist in the Walking-line
844 //It must be added there (with correct 2D-parameters)
845
3306fdd9 846 //2D-parameters of thePSurf surface have already been found (aU0, aV0).
e2e0498b 847 //Let find 2D-parameters on the quadric.
848
3306fdd9 849 //The algorithm depends on the type of the quadric.
850 //Here we consider a Sphere and cone only.
e2e0498b 851
3306fdd9 852 //First of all, we need in adjusting thePSurf in the coordinate system of the Sphere/Cone
853 //(in order to make its equation maximal simple). However, as it will be
e2e0498b 854 //shown later, thePSurf is used in algorithm in order to get its derivatives.
855 //Therefore, for improving performance, transformation of these vectors is enough
856 //(there is no point in transformation of full surface).
857
858 gp_Pnt aPtemp;
859 gp_Vec aVecDu, aVecDv;
860 thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv);
861
862 //Transforms parametric surface in coordinate-system of the quadric
863 gp_Trsf aTr;
864 aTr.SetTransformation((theQSurf->GetType() == GeomAbs_Sphere) ?
865 theQSurf->Sphere().Position() :
866 theQSurf->Cone().Position());
867
868 //Derivatives of transformed thePSurf
869 aVecDu.Transform(aTr);
870 aVecDv.Transform(aTr);
871
872 Standard_Boolean isIsoChoosen = Standard_False;
873
874 if(theQSurf->GetType() == GeomAbs_Sphere)
875 {
3306fdd9 876 if (!ProcessSphere(thePtIso, aVecDu, aVecDv, theIsReversed,
877 aVquad, aUquad, isIsoChoosen))
e2e0498b 878 {
3306fdd9 879 return Standard_False;
e2e0498b 880 }
881 }
882 else //if(theQSurf->GetType() == GeomAbs_Cone)
883 {
3306fdd9 884 if (!ProcessCone(thePtIso, aVecDu, aVecDv, theQSurf->Cone(),
885 theIsReversed, aUquad, isIsoChoosen))
886 {
887 return Standard_False;
888 }
e2e0498b 889 }
890
891 if(theIsReversed)
892 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad);
893 else
894 theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0);
895
896 if (isSame)
897 {
898 theVertex.SetValue(theAddedPoint);
899 return Standard_True;
900 }
901
902 if (!isIsoChoosen)
903 {
3306fdd9 904 Standard_Real anArrOfPeriod[4];
905 if (theIsReversed)
906 {
907 IntSurf::SetPeriod(thePSurf, theQSurf, anArrOfPeriod);
908 }
909 else
910 {
911 IntSurf::SetPeriod(theQSurf, thePSurf, anArrOfPeriod);
912 }
913
e2e0498b 914 AdjustPointAndVertex(theVertex.PntOn2S(), anArrOfPeriod, theAddedPoint);
915 }
916 else
917 {
918 theVertex.SetValue(theAddedPoint);
919 }
920
921 return Standard_True;
922}
923
924//=======================================================================
925//function : ContinueAfterSpecialPoint
3306fdd9 926//purpose : If the last point of the line is the pole of the quadric then
927// the Walking-line has been broken in this point.
928// However, new line must start from this point. Here we must
929// find 2D-coordinates of "this new" point.
930/*
931The inters. line in the neighborhood of the Apex/Pole(s) can be
932approximated by the intersection result of the Cone/Sphere with
933the plane going through the Apex/Pole and being tangent to the
9342nd intersected surface. This intersection result is well known.
935
936In case of sphere, the inters. result is a circle.
937If we go along this circle and across the Pole then U-parameter of
938the sphere (@U_{q}@) will change to +/-PI.
939
940In case of cone, the inters. result is two intersected lines (which
941can be merged to one in a special case when the plane goes along
942some generatrix of the cone). The direction of these lines
943are computed by GetTangentToIntLineForCone(...) method).
944
945When the real (not lines) inters. curve goes through the cone apex then
946two variants are possible:
947a) The tangent line to the inters. curve will be left. In this case
948U-parameter of the cone (@U_{q}@) will be change to +/-PI.
949b) Another line (as inters. result of cone + plane) will tangent
950to the inters. curve. In this case @U_{q}@ must be recomputed.
951*/
e2e0498b 952//=======================================================================
953Standard_Boolean IntPatch_SpecialPoints::
954 ContinueAfterSpecialPoint(const Handle(Adaptor3d_HSurface)& theQSurf,
955 const Handle(Adaptor3d_HSurface)& thePSurf,
956 const IntSurf_PntOn2S& theRefPt,
957 const IntPatch_SpecPntType theSPType,
958 const Standard_Real theTol2D,
959 IntSurf_PntOn2S& theNewPoint,
960 const Standard_Boolean theIsReversed)
961{
962 if(theSPType == IntPatch_SPntNone)
963 return Standard_False;
964
e2e0498b 965 if(theNewPoint.IsSame(theRefPt, Precision::Confusion(), theTol2D))
966 {
967 return Standard_False;
968 }
969
3306fdd9 970 if ((theSPType == IntPatch_SPntPole) && (theQSurf->GetType() == GeomAbs_Cone))
971 {
972 //Check if the condition b) is satisfied.
973 //Repeat the same steps as in
974 //IntPatch_SpecialPoints::AddSingularPole(...) method.
975
976 //On parametric
977 Standard_Real aU0 = 0.0, aV0 = 0.0;
978 //On quadric
979 Standard_Real aUquad = 0.0, aVquad = 0.0;
980
981 if (theIsReversed)
982 theNewPoint.Parameters(aU0, aV0, aUquad, aVquad);
983 else
984 theNewPoint.Parameters(aUquad, aVquad, aU0, aV0);
985
986 gp_Pnt aPtemp;
987 gp_Vec aVecDu, aVecDv;
988 thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv);
989
990 //Transforms parametric surface in coordinate-system of the quadric
991 gp_Trsf aTr;
992 aTr.SetTransformation(theQSurf->Cone().Position());
993
994 //Derivatives of transformed thePSurf
995 aVecDu.Transform(aTr);
996 aVecDv.Transform(aTr);
997
998 Standard_Boolean isIsoChoosen = Standard_False;
999 ProcessCone(theRefPt, aVecDu, aVecDv, theQSurf->Cone(),
1000 theIsReversed, aUquad, isIsoChoosen);
1001
1002 theNewPoint.SetValue(!theIsReversed, aUquad, aVquad);
1003 }
1004
1005 //As it has already been said, in case of going through the Pole/Apex,
1006 //U-parameter of the quadric surface will change to +/-PI. This rule has some
1007 //exceptions:
1008 //1. When 2nd surface has C0-continuity in the point common with the Apex/Pole.
1009 // In this case, the tangent line to the intersection curve after the Apex/Pole
1010 // must be totally recomputed according to the new derivatives of the 2nd surface.
1011 // Currently, it is not implemented but will be able to be done after the
1012 // corresponding demand.
1013 //2. The inters. curve has C1 continuity but huge curvature in the point common with
1014 // the Apex/Pole. Existing inters. algorithm does not allow putting many points
1015 // near to the Apex/Pole in order to cover this "sharp" piece of the inters. curve.
1016 // Therefore, we use adjusting U-parameter of the quadric surface with
1017 // period PI/2 instead of 2PI. It does not have any mathematical idea
1018 // but allows creating WLine with more or less uniform distributed points.
1019 // In other words, we forbid "jumping" between two neighbor Walking-points
1020 // with step greater than PI/4.
1021
e2e0498b 1022 const Standard_Real aPeriod = (theSPType == IntPatch_SPntPole)? M_PI_2 : 2.0*M_PI;
1023
1024 const Standard_Real aUpPeriod = thePSurf->IsUPeriodic() ? thePSurf->UPeriod() : 0.0;
1025 const Standard_Real aUqPeriod = theQSurf->IsUPeriodic() ? aPeriod : 0.0;
1026 const Standard_Real aVpPeriod = thePSurf->IsVPeriodic() ? thePSurf->VPeriod() : 0.0;
1027 const Standard_Real aVqPeriod = theQSurf->IsVPeriodic() ? aPeriod : 0.0;
1028
1029 const Standard_Real anArrOfPeriod[4] = {theIsReversed? aUpPeriod : aUqPeriod,
1030 theIsReversed? aVpPeriod : aVqPeriod,
1031 theIsReversed? aUqPeriod : aUpPeriod,
1032 theIsReversed? aVqPeriod : aVpPeriod};
1033
1034 AdjustPointAndVertex(theRefPt, anArrOfPeriod, theNewPoint);
1035 return Standard_True;
1036}
1037
1038//=======================================================================
1039//function : AdjustPointAndVertex
1040//purpose :
1041//=======================================================================
1042void IntPatch_SpecialPoints::
1043 AdjustPointAndVertex(const IntSurf_PntOn2S &theRefPoint,
1044 const Standard_Real theArrPeriods[4],
1045 IntSurf_PntOn2S &theNewPoint,
1046 IntPatch_Point* const theVertex)
1047{
1048 Standard_Real aRefPar[2] = {0.0, 0.0};
1049 Standard_Real aPar[4] = {0.0, 0.0, 0.0, 0.0};
1050 theNewPoint.Parameters(aPar[0], aPar[1], aPar[2], aPar[3]);
1051
1052 for(Standard_Integer i = 0; i < 4; i++)
1053 {
1054 if(theArrPeriods[i] == 0)
1055 continue;
1056
1057 const Standard_Real aPeriod = theArrPeriods[i], aHalfPeriod = 0.5*theArrPeriods[i];
1058
1059 if(i < 2)
1060 {// 1st surface is used
1061 theRefPoint.ParametersOnS1(aRefPar[0], aRefPar[1]);
1062 }
1063 else
1064 {
1065 theRefPoint.ParametersOnS2(aRefPar[0], aRefPar[1]);
1066 }
1067
1068 const Standard_Integer aRefInd = i%2;
1069
1070 {
1071 Standard_Real aDeltaPar = aRefPar[aRefInd]-aPar[i];
1072 const Standard_Real anIncr = Sign(aPeriod, aDeltaPar);
1073 while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod))
1074 {
1075 aPar[i] += anIncr;
1076 aDeltaPar = aRefPar[aRefInd]-aPar[i];
1077 }
1078 }
1079 }
1080
1081 if(theVertex)
1082 (*theVertex).SetParameters(aPar[0], aPar[1], aPar[2], aPar[3]);
1083
1084 theNewPoint.SetValue(aPar[0], aPar[1], aPar[2], aPar[3]);
1085}
1086