1 // Created on: 1992-06-29
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <Standard_Stream.hxx>
22 #define No_Standard_RangeError
23 #define No_Standard_OutOfRange
26 //======================================================================
27 //== I n t e r s e c t i o n C O N E Q U A D R I Q U E
28 //== C Y L I N D R E Q U A D R I Q U E
29 //======================================================================
34 #include <gp_Cone.hxx>
35 #include <gp_Cylinder.hxx>
37 #include <IntAna_Curve.hxx>
38 #include <IntAna_IntQuadQuad.hxx>
39 #include <IntAna_Quadric.hxx>
40 #include <math_TrigonometricFunctionRoots.hxx>
41 #include <Standard_DomainError.hxx>
42 #include <Standard_OutOfRange.hxx>
43 #include <StdFail_NotDone.hxx>
45 //=======================================================================
46 //function : AddSpecialPoints
47 //purpose : Sometimes the boundaries theTheta1 and theTheta2 are
48 // computed with some inaccuracy. At that, some special points
49 // (cone apex or sphere pole(s)), which are true intersection
50 // points lie out of the domain [theTheta1, theTheta2] of the ALine.
51 // This function corrects these boundaries to make them be included
52 // in the domain of the ALine.
53 // Parameters Theta1 and Theta2 must be initialized
54 // before calling this function.
55 //=======================================================================
56 template <class gpSmth>
57 static void AddSpecialPoints(const IntAna_Quadric& theQuad,
58 const gpSmth& theGpObj,
59 Standard_Real& theTheta1,
60 Standard_Real& theTheta2)
62 const Standard_Real aPeriod = M_PI + M_PI;
63 const NCollection_List<gp_Pnt> &aLSP = theQuad.SpecialPoints();
68 Standard_Real aU = 0.0, aV = 0.0;
69 Standard_Real aMaxDelta = 0.0;
70 for (NCollection_List<gp_Pnt>::Iterator anItr(aLSP); anItr.More(); anItr.Next())
72 const gp_Pnt &aPt = anItr.Value();
73 ElSLib::Parameters(theGpObj, aPt, aU, aV);
74 const gp_Pnt aPProj(ElSLib::Value(aU, aV, theGpObj));
76 if (aPt.SquareDistance(aPProj) > Precision::SquareConfusion())
78 // aPt is not an intersection point
82 Standard_Real aDelta1 = Min(aU - theTheta1, 0.0),
83 aDelta2 = Max(aU - theTheta2, 0.0);
87 // Must be aDelta1 = Min(aU - theTheta1 + aPeriod, 0.0).
88 // But aU - theTheta1 + aPeriod >= 0 always.
94 // Must be aDelta2 = Max(aU - theTheta2 - aPeriod, 0.0).
95 // But aU - theTheta2 - aPeriod <= 0 always.
99 const Standard_Real aDelta = Max(-aDelta1, aDelta2);
100 aMaxDelta = Max(aMaxDelta, aDelta);
105 theTheta1 -= aMaxDelta;
106 theTheta2 += aMaxDelta;
107 if ((theTheta2 - theTheta1) > aPeriod)
109 theTheta2 = theTheta1 + aPeriod;
114 //=======================================================================
115 //class : TrigonometricRoots
116 //purpose: Classe Interne (Donne des racines classees d un polynome trigo)
117 //======================================================================
118 class TrigonometricRoots {
121 Standard_Real Roots[4];
122 Standard_Boolean done;
123 Standard_Integer NbRoots;
124 Standard_Boolean infinite_roots;
127 TrigonometricRoots(const Standard_Real CC,
128 const Standard_Real SC,
129 const Standard_Real C,
130 const Standard_Real S,
131 const Standard_Real Cte,
132 const Standard_Real Binf,
133 const Standard_Real Bsup);
135 Standard_Boolean IsDone() {
139 Standard_Boolean IsARoot(Standard_Real u) {
141 Standard_Real aEps=RealEpsilon();
142 Standard_Real PIpPI = M_PI + M_PI;
144 for(i=0 ; i<NbRoots; ++i) {
145 if(Abs(u - Roots[i])<=aEps) {
146 return Standard_True;
148 if(Abs(u - Roots[i]-PIpPI)<=aEps) {
149 return Standard_True;
152 return Standard_False;
155 Standard_Integer NbSolutions() {
157 throw StdFail_NotDone();
162 Standard_Boolean InfiniteRoots() {
164 throw StdFail_NotDone();
166 return infinite_roots;
169 Standard_Real Value(const Standard_Integer n) {
170 if((!done)||(n>NbRoots)) {
171 throw StdFail_NotDone();
176 //=======================================================================
177 //function : TrigonometricRoots::TrigonometricRoots
179 //=======================================================================
180 TrigonometricRoots::TrigonometricRoots(const Standard_Real CC,
181 const Standard_Real SC,
182 const Standard_Real C,
183 const Standard_Real S,
184 const Standard_Real Cte,
185 const Standard_Real Binf,
186 const Standard_Real Bsup)
187 : infinite_roots(Standard_False)
189 Standard_Integer i, j, SvNbRoots;
190 Standard_Boolean Triee;
191 Standard_Real PIpPI = M_PI + M_PI;
195 //-- F= AA*CN*CN+2*BB*CN*SN+CC*CN+DD*SN+EE;
196 math_TrigonometricFunctionRoots MTFR(CC, SC, C, S, Cte, Binf, Bsup);
202 if(MTFR.InfiniteRoots()) {
203 infinite_roots=Standard_True;
207 NbRoots=MTFR.NbSolutions();
209 for(i=0; i<NbRoots; ++i) {
210 Roots[i]=MTFR.Value(i+1);
219 //-- La recherche directe donne n importe quoi.
221 for(i=0; i<SvNbRoots; ++i) {
223 Standard_Real co=cos(Roots[i]);
224 Standard_Real si=sin(Roots[i]);
225 y=co*(CC*co + (SC+SC)*si + C) + S*si + Cte;
228 return; //-- le 1er avril 98
234 for(i=1,j=0; i<SvNbRoots; ++i,++j) {
235 if(Roots[i]<Roots[j]) {
236 Triee=Standard_False;
237 Standard_Real t=Roots[i];
245 infinite_roots=Standard_False;
247 if(!NbRoots) {//--!!!!! Detection du cas Pol = Cte ( 1e-50 ) !!!!
248 if((Abs(CC) + Abs(SC) + Abs(C) + Abs(S)) < 1e-10) {
249 if(Abs(Cte) < 1e-10) {
250 infinite_roots=Standard_True;
255 //=======================================================================
256 //class : MyTrigonometricFunction
258 // Classe interne : Donne Value et Derivative sur un polynome
260 //======================================================================
261 class MyTrigonometricFunction {
264 Standard_Real CC,SS,SC,S,C,Cte;
268 MyTrigonometricFunction(const Standard_Real xCC,
269 const Standard_Real xSS,
270 const Standard_Real xSC,
271 const Standard_Real xC,
272 const Standard_Real xS,
273 const Standard_Real xCte) {
282 Standard_Real Value(const Standard_Real& U) {
283 Standard_Real sinus, cosinus, aRet;
287 aRet= CC*cosinus*cosinus +
289 2.0*(sinus*(SC*cosinus+S)+cosinus*C)+
295 Standard_Real Derivative(const Standard_Real& U) {
296 Standard_Real sinus, cosinus;
301 return(2.0*((sinus*cosinus)*(SS-CC)
304 +SC*(cosinus*cosinus-sinus*sinus)));
309 //=======================================================================
310 //function : IntAna_IntQuadQuad::IntAna_IntQuadQuad
311 //purpose : C o n s t r u c t e u r v i d e
312 //=======================================================================
313 IntAna_IntQuadQuad::IntAna_IntQuadQuad(void) {
315 identical = Standard_False;
319 myEpsilon=0.00000001;
320 myEpsilonCoeffPolyNull=0.00000001;
321 memset (nextcurve, 0, sizeof (nextcurve));
322 memset (previouscurve, 0, sizeof (previouscurve));
324 //=======================================================================
325 //function : IntAna_IntQuadQuad::IntAna_IntQuadQuad
326 //purpose : I n t e r s e c t i o n C y l i n d r e Q u a d r i q u e
327 //=======================================================================
328 IntAna_IntQuadQuad::IntAna_IntQuadQuad(const gp_Cylinder& Cyl,
329 const IntAna_Quadric& Quad,
330 const Standard_Real Tol) {
332 myEpsilon=0.00000001;
333 myEpsilonCoeffPolyNull=0.00000001;
334 Perform(Cyl,Quad,Tol);
336 //=======================================================================
338 //purpose : I n t e r s e c t i o n C y l i n d r e Q u a d r i q u e
339 //=======================================================================
340 void IntAna_IntQuadQuad::Perform(const gp_Cylinder& Cyl,
341 const IntAna_Quadric& Quad,
344 done = Standard_True;
345 identical= Standard_False;
349 Standard_Boolean UN_SEUL_Z_PAR_THETA, DEUX_Z_PAR_THETA,
350 Z_POSITIF, Z_INDIFFERENT, Z_NEGATIF;
352 UN_SEUL_Z_PAR_THETA=Standard_False;
353 DEUX_Z_PAR_THETA=Standard_True;
354 Z_POSITIF=Standard_True;
355 Z_INDIFFERENT=Standard_True;
356 Z_NEGATIF=Standard_False;
358 Standard_Real Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, aRealEpsilon, RCyl, R2;
359 Standard_Real PIpPI = M_PI + M_PI;
361 for(Standard_Integer raz = 0 ; raz < myNbMaxCurves ; raz++) {
362 previouscurve[raz] = nextcurve[raz] = 0;
366 aRealEpsilon=RealEpsilon();
367 //----------------------------------------------------------------------
368 //-- Coefficients de la quadrique :
370 //-- Qxx x + Qyy y + Qzz z + 2 ( Qxy x y + Qxz x z + Qyz y z )
371 //-- + 2 ( Qx x + Qy y + Qz z ) + Q1
372 //----------------------------------------------------------------------
373 Quad.Coefficients(Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1);
375 //----------------------------------------------------------------------
376 //-- Ecriture des Coefficients de la Quadrique dans le repere liee
378 //-- Cyl.Position() -> Ax2
379 //----------------------------------------------------------------------
380 Quad.NewCoefficients(Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,Cyl.Position());
382 //----------------------------------------------------------------------
383 //-- Parametrage du Cylindre Cyl :
384 //-- X = Rcyl * Cos(Theta)
385 //-- Y = Rcyl * Sin(Theta)
387 //----------------------------------------------------------------------
388 //-- Donne une Equation de la forme :
389 //-- F(Sin(Theta),Cos(Theta),ZCyl) = 0
390 //-- (Equation du second degre en ZCyl)
391 //-- ZCyl**2 CoeffZ2(Theta) + ZCyl CoeffZ1(Theta) + CoeffZ0(Theta)
392 //----------------------------------------------------------------------
393 //-- CoeffZ0 = Q1 + 2*Qx*RCyl*Cos[Theta] + Qxx*RCyl^2*Cos[Theta]^2
394 //-- 2*RCyl*Sin[Theta]* ( Qy + Qxy*RCyl*Cos[Theta]);
395 //-- Qyy*RCyl^2*Sin[Theta]^2;
396 //-- CoeffZ1 =2.0 * ( Qz + RCyl*(Qxz*Cos[Theta] + Sin[Theta]*Qyz)) ;
398 //-- !!!! Attention , si on norme sur Qzz pour detecter le cas 1er degre
399 //----------------------------------------------------------------------
400 //-- On Cherche Les Racines en Theta du discriminant de cette equation :
401 //-- DIS(Theta) = C_1 + C_SS Sin()**2 + C_CC Cos()**2 + 2 C_SC Sin() Cos()
402 //-- + 2 C_S Sin() + 2 C_C Cos()
404 //-- Si Qzz = 0 Alors On Resout Z=Fct(Theta) sur le domaine de Theta
405 //----------------------------------------------------------------------
407 if(Abs(Qzz)<myEpsilonCoeffPolyNull) {
408 done=Standard_False; //-- le 12 mars 98
412 //----------------------------------------------------------------------
413 //--- Cas ou F(Z,Theta) est du second degre en Z ----
414 //----------------------------------------------------------------------
417 Standard_Real C_1 = Qz*Qz - Qzz*Q1;
418 Standard_Real C_SS = R2 * ( Qyz*Qyz - Qyy*Qzz );
419 Standard_Real C_CC = R2 * ( Qxz*Qxz - Qxx*Qzz );
420 Standard_Real C_S = RCyl * ( Qyz*Qz - Qy*Qzz );
421 Standard_Real C_C = RCyl * ( Qxz*Qz - Qx*Qzz );
422 Standard_Real C_SC = R2 * ( Qxz*Qyz - Qxy*Qzz );
424 MyTrigonometricFunction MTF(C_CC,C_SS,C_SC,C_C,C_S,C_1);
425 TrigonometricRoots PolDIS(C_CC-C_SS,
429 C_1+C_SS, 0., PIpPI);
430 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
431 if(PolDIS.IsDone()==Standard_False) {
435 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
436 if(PolDIS.InfiniteRoots()) {
437 TheCurve[0].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
441 TheCurve[1].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
449 //---------------------------------------------------------------
450 //-- La Recherche des Zero de DIS a reussi
451 //---------------------------------------------------------------
452 Standard_Integer nbsolDIS=PolDIS.NbSolutions();
454 //--------------------------------------------------------------
455 //-- Le Discriminant a un signe constant :
457 //-- Si Positif ---> 2 Courbes
458 //-- Sinon ---> Pas de solution
459 //--------------------------------------------------------------
460 if(MTF.Value(M_PI) >= -aRealEpsilon) {
462 TheCurve[0].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
466 TheCurve[1].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
474 //------------------------------------------------------------
475 //-- Le Discriminant est toujours Negatif
476 //------------------------------------------------------------
481 //------------------------------------------------------------
482 //-- Le Discriminant a des racines
483 //-- (Le Discriminant est une fonction periodique donc ... )
484 //------------------------------------------------------------
486 //------------------------------------------------------------
487 //-- Point de Tangence pour ce Theta Solution
488 //-- Si Signe de Discriminant >=0 pour tout Theta
490 //-- Courbe Solution pour la partie Positive
491 //-- entre les 2 racines ( Ici Tout le domaine )
492 //-- Sinon Seulement un point Tangent
493 //------------------------------------------------------------
494 if(MTF.Value(PolDIS.Value(1)+M_PI) >= -aRealEpsilon ) {
495 //------------------------------------------------------------
496 //-- On a Un Point de Tangence + Une Courbe Solution
497 //------------------------------------------------------------
498 TheCurve[0].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
502 TheCurve[1].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
510 //------------------------------------------------------------
511 //-- On a simplement un Point de tangence
512 //------------------------------------------------------------
513 //--Standard_Real Theta = PolDIS(1);
514 //--Standard_Real SecPar= -0.5 * MTFZ1.Value(Theta) / MTFZ2.Value(Theta);
515 //--Thepoints[Nbpoints] = ElSLib::CylinderValue(Theta,SecPar,Cyl.Position(),Cyl.Radius());
521 //------------------------------------------------------------
522 //-- On detecte : Les racines double
523 //-- : Les Zones Positives [Modulo 2 PI]
524 //-- Les Courbes solutions seront obtenues pour les valeurs
525 //-- de Theta ou Discriminant(Theta) > 0 (>=0? en limite)
526 //-- Par la resolution de l equation implicite avec Theta fixe
527 //------------------------------------------------------------
528 //-- Si tout est solution, Alors on est sur une iso
529 //-- Ce cas devrait etre traite en amont
530 //------------------------------------------------------------
531 //-- On construit la fonction permettant connaissant un Theta
532 //-- de calculer les Z+ et Z- Correspondants.
533 //-------------------------------------------------------------
535 //-------------------------------------------------------------
536 //-- Calcul des Intervalles ou Discriminant >=0
537 //-- On a au plus nbsol intervalles ( en fait 2 )
538 //-- (1,2) (2,3) .. (nbsol,1+2PI)
539 //-------------------------------------------------------------
541 Standard_Real Theta1, Theta2, Theta3, autrepar, qwet;
542 Standard_Boolean UnPtTg = Standard_False;
546 for(i=1; i<=nbsolDIS ; i++) {
547 Theta1=PolDIS.Value(i);
548 Theta2=(i<nbsolDIS)? PolDIS.Value(i+1) : (PolDIS.Value(1)+PIpPI);
549 //----------------------------------------------------------------
550 //-- On detecte les racines doubles
551 //-- Si il n y a que 2 racines alors on prend tout l interval
552 //----------------------------------------------------------------
553 if(Abs(Theta2-Theta1)<=aRealEpsilon) {
554 UnPtTg = Standard_True;
560 qwet=MTF.Value(autrepar);
562 Standard_Real aParam = Theta1 + PIpPI;
563 AddSpecialPoints(Quad, Cyl, Theta1, aParam);
564 TheCurve[NbCurves].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
565 myEpsilon,Theta1,aParam,
569 TheCurve[NbCurves].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
570 myEpsilon,Theta1,aParam,
579 for(i=1; UnPtTg == (Standard_False) && (i<=nbsolDIS) ; i++) {
580 Theta1=PolDIS.Value(i);
581 Theta2=(i<nbsolDIS)? PolDIS.Value(i+1) : (PolDIS.Value(1)+PIpPI);
582 //----------------------------------------------------------------
583 //-- On detecte les racines doubles
584 //-- Si il n y a que 2 racines alors on prend tout l interval
585 //----------------------------------------------------------------
586 if(Abs(Theta2-Theta1)<=1e-12) {
587 //-- std::cout<<"\n####### Un Point de Tangence en Theta = "<<Theta1<<std::endl;
590 else { //-- On evite les pbs numeriques (Tout est du meme signe entre les racines)
591 qwet=MTF.Value(0.5*(Theta1+Theta2))
592 +MTF.Value(0.4*Theta1+0.6*Theta2)
593 +MTF.Value(0.6*Theta1+0.4*Theta2);
595 //------------------------------------------------------------
596 //-- On est positif a partir de Theta1
597 //-- L intervalle Theta1,Theta2 est retenu
598 //------------------------------------------------------------
600 //-- le 8 octobre 1997 :
601 //-- PB: Racine en 0 pi/2 pi/2 et 2pi
602 //-- On cree 2 courbes : 0 -> pi/2 2zpartheta
603 //-- pi/2 -> 2pi 2zpartheta
605 //-- la courbe 0 pi/2 passe par le double pt de tangence pi/2
606 //-- il faut donc couper cette courbe en 2
608 Theta3 = ((i+1)<nbsolDIS)? PolDIS.Value(i+2) : (PolDIS.Value(1)+PIpPI);
610 if((Theta3-Theta2)<5.e-8) {
612 AddSpecialPoints(Quad, Cyl, Theta1, Theta2);
613 TheCurve[NbCurves].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
614 myEpsilon,Theta1,Theta2,
618 TheCurve[NbCurves].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
619 myEpsilon,Theta1,Theta2,
625 AddSpecialPoints(Quad, Cyl, Theta1, Theta2);
626 TheCurve[NbCurves].SetCylinderQuadValues(Cyl,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
627 myEpsilon,Theta1,Theta2,
633 }//else { //-- On evite les pbs numerique ...
634 } //for(i=1; UnPtTg == (Standard_False) && (i<=nbsolDIS) ; i++) {
642 //=======================================================================
643 //function :IntAna_IntQuadQuad::IntAna_IntQuadQuad
645 //=======================================================================
646 IntAna_IntQuadQuad::IntAna_IntQuadQuad(const gp_Cone& Cone,
647 const IntAna_Quadric& Quad,
648 const Standard_Real Tol)
651 myEpsilon=0.00000001;
652 myEpsilonCoeffPolyNull=0.00000001;
653 Perform(Cone,Quad,Tol);
655 //=======================================================================
658 //=======================================================================
659 void IntAna_IntQuadQuad::Perform(const gp_Cone& Cone,
660 const IntAna_Quadric& Quad,
664 Standard_Boolean UN_SEUL_Z_PAR_THETA,
665 Z_POSITIF, Z_NEGATIF;
667 UN_SEUL_Z_PAR_THETA=Standard_False;
668 Z_POSITIF=Standard_True;
669 Z_NEGATIF=Standard_False;
672 Standard_Real Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1;
673 Standard_Real Theta1, Theta2, TgAngle;
674 Standard_Real PIpPI = M_PI + M_PI;
677 identical = Standard_False;
681 for(i=0 ; i<myNbMaxCurves ; ++i) {
686 Quad.Coefficients(Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1);
688 gp_Ax3 tAx3(Cone.Position());
689 tAx3.SetLocation(Cone.Apex());
690 Quad.NewCoefficients(Qxx,Qyy,Qzz,
695 TgAngle=1./(Tan(Cone.SemiAngle()));
697 // The parametrization of the Cone
699 // x= z*tan(beta)*cos(t)
700 // y= z*tan(beta)*sin(t)
703 // The intersection curves are defined by the equation
706 // f(z,t)= A(t)*z + B(t)*z + C(t)=0
709 // 1. Try to solve A(t)=0 -> PolZ2
711 Standard_Integer nbsol, nbsol1, nbsolZ2;
712 Standard_Real Z2CC, Z2SS, Z2Cte, Z2SC, Z2C, Z2S;
713 Standard_Real Z1CC, Z1SS, Z1Cte, Z1SC, Z1C, Z1S;
714 Standard_Real C_1,C_SS, C_CC, C_S, C_C, C_SC;
718 Z2Cte= Qzz * TgAngle*TgAngle;
723 TrigonometricRoots PolZ2(Z2CC-Z2SS,Z2SC,Z2C+Z2C,Z2S+Z2S,Z2Cte+Z2SS,0.,PIpPI);
724 if(!PolZ2.IsDone()) {
729 //MyTrigonometricFunction MTF2(Z2CC,Z2SS,Z2SC,Z2C,Z2S,Z2Cte);
730 nbsolZ2 = PolZ2.NbSolutions();
732 // 2. Try to solve B(t)=0 -> PolZ1
734 Z1Cte = 2.*(TgAngle)*Qz;
741 TrigonometricRoots PolZ1(Z1CC-Z1SS,Z1SC, Z1C+Z1C,Z1S+Z1S, Z1Cte+Z1SS,0.,PIpPI);
742 if(!PolZ1.IsDone()) {
746 MyTrigonometricFunction MTFZ1(Z1CC,Z1SS,Z1SC,Z1C,Z1S,Z1Cte);
748 nbsol1=PolZ1.NbSolutions();
749 if(PolZ2.InfiniteRoots()) { // i.e A(t)=0 for any t
750 if(!PolZ1.InfiniteRoots()) {
752 //-- B(t)*z + C(t) = 0 avec C(t) != 0
753 TheCurve[0].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,
762 for(ii=1; ii<= nbsol1 ; ++ii) {
763 Standard_Real Theta=PolZ1.Value(ii);
764 if(Abs(MTFZ1.Value(Theta))<=myEpsilon) {
765 //-- Une droite Solution Z= -INF -> +INF pour Theta
766 //-- std::cout<<"######## Droite Solution Pour Theta = "<<Theta<<std::endl;
769 //-- std::cout<<"\n#### _+_+_+_+_+ CAS A(t) Z + B = 0 avec A et B ==0 "<<std::endl;
776 if(Abs(Q1)<=myEpsilon) {
781 //-- Pas de Solutions
790 //-- f(z,t)=A(t)*z + B(t)*z + C(t)=0 avec A n est pas toujours nul
793 // 3. Try to explore s.c. Discriminant: D(t)=B(t)-4*A(t)*C(t) => Pol
795 // The function D(t) is just a formula that has sense for quadratic
797 // For cases when A(t)=0 (say at t=ti, t=tj. etc) the equation
800 // f(z,t)=B(t)*z + C(t)=0, where B(t)!=0,
802 // and the D(t) is nonsense for it.
804 C_1 = TgAngle*TgAngle * ( Qz * Qz - Qzz * Q1);
805 C_SS = Qy * Qy - Qyy * Q1;
806 C_CC = Qx * Qx - Qxx * Q1;
807 C_S = TgAngle*( Qy * Qz - Qyz * Q1);
808 C_C = TgAngle*( Qx * Qz - Qxz * Q1);
809 C_SC = Qx * Qy - Qxy * Q1;
811 TrigonometricRoots Pol(C_CC-C_SS, C_SC, C_C+C_C,C_S+C_S, C_1+C_SS,0.,PIpPI);
817 nbsol=Pol.NbSolutions();
818 MyTrigonometricFunction MTF(C_CC,C_SS,C_SC,C_C,C_S,C_1);
820 if(Pol.InfiniteRoots()) {
822 // f(z,t)= (z(t)-zo(t)) = 0 Discriminant(t)=0 pour tout t
824 TheCurve[0].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
826 UN_SEUL_Z_PAR_THETA, Z_POSITIF);
827 TheCurve[1].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
829 UN_SEUL_Z_PAR_THETA, Z_NEGATIF);
835 // f(z,t)=A(t)*z + B(t)*z + C(t) Discriminant(t) != 0
837 if(!nbsol && (MTF.Value(M_PI)<0.) ) {
838 //-- Discriminant signe constant negatif
843 //-- On Traite le cas : Discriminant(t) > 0 pour tout t en simulant 1
844 // racine double en 0
845 Standard_Boolean DiscriminantConstantPositif = Standard_False;
848 DiscriminantConstantPositif = Standard_True;
850 //----------------------------------------------------------------------
851 //-- Le discriminant admet au moins une racine ( -> Point de Tangence )
852 //-- ou est constant positif.
853 //----------------------------------------------------------------------
854 for(i=1; i<=nbsol; ++i) {
855 if(DiscriminantConstantPositif) {
857 Theta2 = PIpPI-myEpsilon;
861 Theta2=(i<nbsol)? Pol.Value(i+1) : (Pol.Value(1)+PIpPI);
864 if(Abs(Theta2-Theta1)<=myEpsilon){
869 Standard_Real qwet =MTF.Value(0.5*(Theta1+Theta2))+
870 MTF.Value(0.4*Theta1+0.6*Theta2)+
871 MTF.Value(0.6*Theta1+0.4*Theta2);
875 //---------------------------------------------------------------------
876 //-- On a des Solutions entre Theta1 et Theta 2
877 //---------------------------------------------------------------------
879 //---------------------------------------------------------------------
880 //-- On Subdivise si necessaire Theta1-->Theta2
881 //-- en Theta1-->t1 t1--->t2 ... tn--->Theta2
882 //-- ou t1,t2,...tn sont des racines de A(t)
884 //-- Seule la courbe Z_NEGATIF est affectee
885 //----------------------------------------------------------------------
886 Standard_Boolean RacinesdePolZ2DansTheta1Theta2;
890 //nbsolZ2=PolZ2.NbSolutions();
891 RacinesdePolZ2DansTheta1Theta2=Standard_False;
892 for(i2=1; i2<=nbsolZ2 && !RacinesdePolZ2DansTheta1Theta2; ++i2) {
894 if(r>Theta1 && r<Theta2) {
895 RacinesdePolZ2DansTheta1Theta2=Standard_True;
899 if(r>Theta1 && r<Theta2){
900 RacinesdePolZ2DansTheta1Theta2=Standard_True;
905 if(!RacinesdePolZ2DansTheta1Theta2) {
906 //--------------------------------------------------------------------
907 //-- Pas de Branches Infinies
908 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,myEpsilon,
910 UN_SEUL_Z_PAR_THETA,Z_POSITIF);
912 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1,myEpsilon,
920 Standard_Boolean NoChanges;
921 Standard_Real NewMin, NewMax, to;
925 NoChanges=Standard_True;
927 for(i2=1; i2<= (nbsolZ2+nbsolZ2) ; ++i2) {
929 to=PolZ2.Value(i2-nbsolZ2) + PIpPI;
935 // to is value of the parameter t where A(t)=0, i.e.
936 // f(z,to)=B(to)*z + C(to)=0, B(to)!=0.
938 // z=-C(to)/B(to) is one and only
939 // solution in spite of the fact that D(t)>0 for any value of t.
941 if(to<NewMax && to>NewMin) {
942 //-----------------------------------------------------------------
943 //-- On coupe au moins une fois le domaine Theta1 Theta2
944 //-----------------------------------------------------------------
945 NoChanges=Standard_False;
946 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
948 UN_SEUL_Z_PAR_THETA, Z_NEGATIF);
951 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
953 UN_SEUL_Z_PAR_THETA, Z_POSITIF);
954 //------------------------------------------------------------
956 //-- Si B < 0 Alors Infini sur Z+
957 //-- Sinon Infini sur Z-
958 //------------------------------------------------------------
959 if(PolZ2.IsARoot(NewMin)) {
960 if(MTFZ1.Value(NewMin) < 0.) {
961 TheCurve[NbCurves].SetIsFirstOpen(Standard_True);
964 TheCurve[NbCurves-1].SetIsFirstOpen(Standard_True);
967 if(MTFZ1.Value(to) < 0.) {
968 TheCurve[NbCurves].SetIsLastOpen(Standard_True);
971 TheCurve[NbCurves-1].SetIsLastOpen(Standard_True);
973 //------------------------------------------------------------
976 }//if(to<NewMax && to>NewMin)
977 }// for(i2=1; i2<= (nbsolZ2+nbsolZ2) ; ++i2)
980 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
982 UN_SEUL_Z_PAR_THETA, Z_NEGATIF);
984 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
986 UN_SEUL_Z_PAR_THETA, Z_POSITIF);
987 //------------------------------------------------------------
989 //-- Si B < 0 Alors Infini sur Z+
990 //-- Sinon Infini sur Z-
991 //------------------------------------------------------------
992 if(PolZ2.IsARoot(Theta1)) {
993 if(MTFZ1.Value(Theta1) < 0.) {
994 TheCurve[NbCurves].SetIsFirstOpen(Standard_True);
997 TheCurve[NbCurves-1].SetIsFirstOpen(Standard_True);
1000 if(PolZ2.IsARoot(Theta2)) {
1001 if(MTFZ1.Value(Theta2) < 0.) {
1002 TheCurve[NbCurves].SetIsLastOpen(Standard_True);
1005 TheCurve[NbCurves-1].SetIsLastOpen(Standard_True);
1008 //------------------------------------------------------------
1012 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
1014 UN_SEUL_Z_PAR_THETA, Z_NEGATIF);
1016 TheCurve[NbCurves].SetConeQuadValues(Cone,Qxx,Qyy,Qzz,Qxy,Qxz,Qyz,Qx,Qy,Qz,Q1, myEpsilon,
1018 UN_SEUL_Z_PAR_THETA, Z_POSITIF);
1019 //------------------------------------------------------------
1021 //-- Si B < 0 Alors Infini sur Z+
1022 //-- Sinon Infini sur Z-
1023 //------------------------------------------------------------
1024 if(PolZ2.IsARoot(NewMin)) {
1025 if(MTFZ1.Value(NewMin) < 0.) {
1026 TheCurve[NbCurves].SetIsFirstOpen(Standard_True);
1029 TheCurve[NbCurves-1].SetIsFirstOpen(Standard_True);
1032 if(PolZ2.IsARoot(Theta2)) {
1033 if(MTFZ1.Value(Theta2) < 0.) {
1034 TheCurve[NbCurves].SetIsLastOpen(Standard_True);
1037 TheCurve[NbCurves-1].SetIsLastOpen(Standard_True);
1040 //------------------------------------------------------------
1045 }//for(i=1; i<=nbsol ; i++) {
1047 InternalSetNextAndPrevious();
1049 //=======================================================================
1050 //function :InternalSetNextAndPrevious
1052 //-- Raccordement des courbes bout a bout
1053 //-- - Utilisation du champ : IsFirstOpen
1055 //-- Pas de verification si ces champs retournent Vrai.
1058 //-- 1: Test de Fin(C1) = Debut(C2) ->N(C1) et P(C2)
1059 //-- 2: Debut(C1) = Fin(C2) ->P(C1) et N(C2)
1060 //=======================================================================
1061 void IntAna_IntQuadQuad::InternalSetNextAndPrevious()
1063 Standard_Boolean NotLastOpenC2, NotFirstOpenC2;
1064 Standard_Integer c1,c2;
1065 Standard_Real aEps, aEPSILON_DISTANCE;
1066 Standard_Real DInfC1,DSupC1, DInfC2,DSupC2;
1069 aEPSILON_DISTANCE=0.0000000001;
1071 for(c1=0; c1<NbCurves; c1++) {
1073 previouscurve[c1] = 0;
1076 for(c1=0; c1 < NbCurves; c1++) {
1077 TheCurve[c1].Domain(DInfC1,DSupC1);
1079 for(c2 = 0; (c2 < NbCurves) && (c2!=c1) ; c2++) {
1081 NotLastOpenC2 = ! TheCurve[c2].IsLastOpen();
1082 NotFirstOpenC2 = ! TheCurve[c2].IsFirstOpen();
1083 TheCurve[c2].Domain(DInfC2,DSupC2);
1084 if(TheCurve[c1].IsFirstOpen() == Standard_False) {
1086 if(Abs(DInfC1-DSupC2)<=aEps &&
1087 (TheCurve[c1].Value(DInfC1)
1088 .Distance(TheCurve[c2].Value(DSupC2))<aEPSILON_DISTANCE)) {
1089 previouscurve[c1] = c2+1;
1090 nextcurve[c2] = c1+1;
1093 if(NotFirstOpenC2) {
1094 if(Abs(DInfC1-DInfC2)<=aEps
1095 && (TheCurve[c1].Value(DInfC1)
1096 .Distance(TheCurve[c2].Value(DInfC2))<aEPSILON_DISTANCE)) {
1097 previouscurve[c1] = -(c2+1);
1098 previouscurve[c2] = -(c1+1);
1102 if(TheCurve[c1].IsLastOpen() == Standard_False) {
1104 if(Abs(DSupC1-DSupC2)<=aEps
1105 && (TheCurve[c1].Value(DSupC1)
1106 .Distance(TheCurve[c2].Value(DSupC2))<aEPSILON_DISTANCE)) {
1108 nextcurve[c1] = -(c2+1);
1109 nextcurve[c2] = -(c1+1);
1112 if(NotFirstOpenC2) {
1113 if(Abs(DSupC1-DInfC2)<=aEps
1114 && (TheCurve[c1].Value(DSupC1)
1115 .Distance(TheCurve[c2].Value(DInfC2))<aEPSILON_DISTANCE)) {
1116 nextcurve[c1] = c2+1;
1117 previouscurve[c2] = c1+1;
1124 //=======================================================================
1125 //function :HasPreviousCurve
1127 //=======================================================================
1128 Standard_Boolean IntAna_IntQuadQuad::HasPreviousCurve(const Standard_Integer I) const
1131 throw StdFail_NotDone("IntQuadQuad Not done");
1134 throw Standard_DomainError("IntQuadQuad identical");
1136 if((I>NbCurves)||(I<=0)) {
1137 throw Standard_OutOfRange("Incorrect Curve Number 'HasPrevious Curve'");
1139 if(previouscurve[I-1]) {
1140 return Standard_True;
1142 return Standard_False;
1144 //=======================================================================
1145 //function :HasNextCurve
1147 //=======================================================================
1148 Standard_Boolean IntAna_IntQuadQuad::HasNextCurve(const Standard_Integer I) const
1151 throw StdFail_NotDone("IntQuadQuad Not done");
1154 throw Standard_DomainError("IntQuadQuad identical");
1156 if((I>NbCurves)||(I<=0)) {
1157 throw Standard_OutOfRange("Incorrect Curve Number 'HasNextCurve'");
1159 if(nextcurve[I-1]) {
1160 return Standard_True;
1162 return(Standard_False);
1164 //=======================================================================
1165 //function :PreviousCurve
1167 //=======================================================================
1168 Standard_Integer IntAna_IntQuadQuad::PreviousCurve (const Standard_Integer I,
1169 Standard_Boolean& theOpposite) const
1171 if(HasPreviousCurve(I)) {
1172 if(previouscurve[I-1]>0) {
1173 theOpposite = Standard_False;
1174 return(previouscurve[I-1]);
1177 theOpposite = Standard_True;
1178 return( - previouscurve[I-1]);
1182 throw Standard_DomainError("Incorrect Curve Number 'PreviousCurve'");
1185 //=======================================================================
1186 //function :NextCurve
1188 //=======================================================================
1189 Standard_Integer IntAna_IntQuadQuad::NextCurve (const Standard_Integer I,
1190 Standard_Boolean& theOpposite) const
1192 if(HasNextCurve(I)) {
1193 if(nextcurve[I]>0) {
1194 theOpposite = Standard_False;
1195 return(nextcurve[I-1]);
1198 theOpposite = Standard_True;
1199 return( - nextcurve[I-1]);
1203 throw Standard_DomainError("Incorrect Curve Number 'NextCurve'");
1206 //=======================================================================
1209 //=======================================================================
1210 const IntAna_Curve& IntAna_IntQuadQuad::Curve(const Standard_Integer i) const
1213 throw StdFail_NotDone("IntQuadQuad Not done");
1216 throw Standard_DomainError("IntQuadQuad identical");
1218 if((i <= 0) || (i>NbCurves)) {
1219 throw Standard_OutOfRange("Incorrect Curve Number");
1221 return TheCurve[i-1];
1223 //=======================================================================
1226 //=======================================================================
1227 const gp_Pnt& IntAna_IntQuadQuad::Point (const Standard_Integer i) const
1230 throw StdFail_NotDone("IntQuadQuad Not done");
1233 throw Standard_DomainError("IntQuadQuad identical");
1235 if((i <= 0) || (i>Nbpoints)) {
1236 throw Standard_OutOfRange("Incorrect Point Number");
1238 return Thepoints[i-1];
1240 //=======================================================================
1241 //function :Parameters
1243 //=======================================================================
1244 void IntAna_IntQuadQuad::Parameters (const Standard_Integer, //i,
1246 Standard_Real& ) const
1248 std::cout << "IntAna_IntQuadQuad::Parameters(...) is not yet implemented" << std::endl;
1251 /*********************************************************************************
1253 Mathematica Pour Cone Quadrique
1254 In[6]:= y[r_,t_]:=r*Sin[t]
1256 In[7]:= x[r_,t_]:=r*Cos[t]
1258 In[8]:= z[r_,t_]:=r*d
1260 In[14]:= Quad[x_,y_,z_]:=Qxx x x + Qyy y y + Qzz z z + 2 (Qxy x y + Qxz x z + Qyz y z + Qx x + Qy y + Qz z ) + Q1
1262 In[15]:= Quad[x[r,t],y[r,t],z[r,t]]
1265 Out[15]= Q1 + d Qzz r + Qxx r Cos[t] + Qyy r Sin[t] +
1268 > 2 (d Qz r + Qx r Cos[t] + d Qxz r Cos[t] + Qy r Sin[t] +
1271 > d Qyz r Sin[t] + Qxy r Cos[t] Sin[t])
1277 In[17]:= Collect[QQ,r]
1280 Out[17]= Q1 + r (2 d Qz + 2 Qx Cos[t] + 2 Qy Sin[t]) +
1283 > r (d Qzz + 2 d Qxz Cos[t] + Qxx Cos[t] + 2 d Qyz Sin[t] +
1286 > 2 Qxy Cos[t] Sin[t] + Qyy Sin[t] )
1287 ********************************************************************************/
1290 //**********************************************************************
1291 //*** C O N E - Q U A D R I Q U E ***
1293 //*** R ( d Qzz + 2 d Qxz Cos[t] + Qxx Cos[t] + 2 d Qyz Sin[t] + ***
1295 //*** 2 Qxy Cos[t] Sin[t] + Qyy Sin[t] ) ***
1297 //*** + R ( 2 d Qz + 2 Qx Cos[t] + 2 Qy Sin[t] ) ***
1300 //**********************************************************************
1301 //FortranForm= ( DIS = QQ1 QQ1 - 4 QQ0 QQ2 ) / 4
1302 // - d**2*Qz**2 - d**2*Qzz*Q1 + (Qx**2 - Qxx*Q1)*Cos(t)**2 +
1303 // - (2*d*Qy*Qz - 2*d*Qyz*Q1)*Sin(t) + (Qy**2 - Qyy*Q1)*Sin(t)**2 +
1304 // - Cos(t)*(2*d*Qx*Qz - 2*d*Qxz*Q1 + (2*Qx*Qy - 2*Qxy*Q1)*Sin(t))
1305 //**********************************************************************
1306 //modified by NIZNHY-PKV Fri Dec 2 10:56:03 2005f
1309 void DumpCurve(const Standard_Integer aIndex,
1311 //=======================================================================
1312 //function : DumpCurve
1314 //=======================================================================
1315 void DumpCurve(const Standard_Integer aIndex,
1318 Standard_Boolean bIsOpen, bIsConstant, bIsFirstOpen, bIsLastOpen;
1319 Standard_Integer i, aNb;
1320 Standard_Real aT1, aT2, aT, dT;
1323 aC.Domain(aT1, aT2);
1324 bIsOpen=aC.IsOpen();
1325 bIsConstant=aC.IsConstant();
1326 bIsFirstOpen=aC.IsFirstOpen();
1327 bIsLastOpen=aC.IsLastOpen();
1330 printf(" * IntAna_Curve #%d*\n", aIndex);
1331 printf(" Domain: [ %lf, %lf ]\n", aT1, aT2);
1332 printf(" IsOpen=%d\n", bIsOpen);
1333 printf(" IsConstant=%d\n", bIsConstant);
1334 printf(" IsFirstOpen =%d\n", bIsFirstOpen);
1335 printf(" IsLastOpen =%d\n", bIsLastOpen);
1338 dT=(aT2-aT1)/(aNb-1);
1339 for (i=0; i<aNb; ++i) {
1346 printf("point p%d_%d %lf %lf %lf\n",
1347 aIndex, i, aP.X(), aP.Y(), aP.Z());
1349 printf(" ---- end of curve ----\n");
1352 //modified by NIZNHY-PKV Fri Dec 2 10:42:16 2005t