0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / Convert / Convert_ConeToBSplineSurface.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 //JCV 16/10/91
16
17 #include <Convert_ConeToBSplineSurface.ixx>
18
19 #include <gp.hxx>
20 #include <gp_Trsf.hxx>
21
22 static const Standard_Integer TheUDegree  = 2;
23 static const Standard_Integer TheVDegree  = 1;
24 static const Standard_Integer TheNbUKnots = 5;
25 static const Standard_Integer TheNbVKnots = 2;
26 static const Standard_Integer TheNbUPoles = 9;
27 static const Standard_Integer TheNbVPoles = 2;
28
29
30 static void ComputePoles( const Standard_Real R,
31                           const Standard_Real A,
32                           const Standard_Real U1,
33                           const Standard_Real U2,
34                           const Standard_Real V1,
35                           const Standard_Real V2,
36                                 TColgp_Array2OfPnt& Poles)
37 {
38   Standard_Real deltaU = U2 - U1;
39   
40   Standard_Integer i;
41
42   // Number of spans : maximum opening = 150 degrees ( = PI / 1.2 rds)
43   Standard_Integer 
44     nbUSpans = (Standard_Integer)IntegerPart( 1.2 * deltaU / M_PI) + 1;
45   Standard_Real AlfaU = deltaU / ( nbUSpans * 2);
46
47   Standard_Real x[TheNbVPoles];
48   Standard_Real z[TheNbVPoles];
49
50   x[0] = R + V1 * Sin(A);
51   z[0] =     V1 * Cos(A);
52   x[1] = R + V2 * Sin(A);
53   z[1] =     V2 * Cos(A);
54  
55   Standard_Real UStart = U1;
56   Poles(1,1) = gp_Pnt(x[0]*Cos(UStart),x[0]*Sin(UStart),z[0]);
57   Poles(1,2) = gp_Pnt(x[1]*Cos(UStart),x[1]*Sin(UStart),z[1]);
58   
59   for ( i = 1; i <= nbUSpans; i++) {
60     Poles( 2*i, 1) = gp_Pnt( x[0] * Cos(UStart+AlfaU) / Cos(AlfaU),
61                              x[0] * Sin(UStart+AlfaU) / Cos(AlfaU),
62                              z[0] );
63     Poles( 2*i, 2) = gp_Pnt( x[1] * Cos(UStart+AlfaU) / Cos(AlfaU),
64                              x[1] * Sin(UStart+AlfaU) / Cos(AlfaU),
65                              z[1] );
66     Poles(2*i+1,1) = gp_Pnt( x[0] * Cos(UStart+2*AlfaU),
67                              x[0] * Sin(UStart+2*AlfaU),
68                              z[0] );
69     Poles(2*i+1,2) = gp_Pnt( x[1] * Cos(UStart+2*AlfaU),
70                              x[1] * Sin(UStart+2*AlfaU),
71                              z[1] );
72     UStart += 2*AlfaU;
73   }
74 }
75
76
77 //=======================================================================
78 //function : Convert_ConeToBSplineSurface
79 //purpose  : 
80 //=======================================================================
81
82 Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface 
83   (const gp_Cone&      C , 
84    const Standard_Real U1, 
85    const Standard_Real U2, 
86    const Standard_Real V1, 
87    const Standard_Real V2 ) 
88 : Convert_ElementarySurfaceToBSplineSurface (TheNbUPoles, TheNbVPoles, 
89                                              TheNbUKnots, TheNbVKnots,
90                                              TheUDegree , TheVDegree  ) 
91 {
92   Standard_Real deltaU = U2 - U1;
93   Standard_DomainError_Raise_if( (Abs(V2-V1) <= Abs(Epsilon(V1))) ||
94                                  (deltaU  >  2*M_PI)                || 
95                                  (deltaU  <  0.  ),
96                                  "Convert_ConeToBSplineSurface");
97
98   isuperiodic = Standard_False;
99   isvperiodic = Standard_False;
100
101   Standard_Integer i,j;
102   // construction of cone in the reference mark xOy.
103
104   // Number of spans : maximum opening = 150 degrees ( = PI / 1.2 rds)
105   Standard_Integer 
106     nbUSpans = (Standard_Integer)IntegerPart( 1.2 * deltaU / M_PI) + 1;
107   Standard_Real AlfaU = deltaU / ( nbUSpans * 2);
108
109   nbUPoles = 2 * nbUSpans + 1;
110   nbUKnots = nbUSpans + 1;
111
112   nbVPoles = 2;
113   nbVKnots = 2;
114
115   Standard_Real R = C.RefRadius();
116   Standard_Real A = C.SemiAngle();
117   
118   ComputePoles( R, A, U1, U2, V1, V2, poles);
119
120   for ( i = 1; i<= nbUKnots; i++) {
121     uknots(i) = U1 + (i-1) * 2 * AlfaU;
122     umults(i) = 2;
123   }
124   umults(1)++; umults(nbUKnots)++;
125   vknots(1) = V1; vmults(1) = 2;
126   vknots(2) = V2; vmults(2) = 2;
127
128   // Replace the bspline in the mark of the sphere.
129   // and calculate the weight of the bspline.
130   Standard_Real W1;
131   gp_Trsf Trsf;
132   Trsf.SetTransformation( C.Position(), gp::XOY());
133
134   for ( i = 1; i <= nbUPoles; i++) {
135     if ( i % 2 == 0)  W1 = Cos(AlfaU);
136     else              W1 = 1.;
137
138     for ( j = 1; j <= nbVPoles; j++) {
139       weights( i, j) = W1;
140       poles( i, j).Transform( Trsf);
141     }
142   }
143 }
144
145
146 //=======================================================================
147 //function : Convert_ConeToBSplineSurface
148 //purpose  : 
149 //=======================================================================
150
151 Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface 
152   (const gp_Cone&      C , 
153    const Standard_Real V1, 
154    const Standard_Real V2 )
155 : Convert_ElementarySurfaceToBSplineSurface (TheNbUPoles, TheNbVPoles,
156                                              TheNbUKnots, TheNbVKnots,
157                                              TheUDegree,  TheVDegree)
158 {
159   Standard_DomainError_Raise_if( Abs(V2-V1) <= Abs(Epsilon(V1)),
160                                  "Convert_ConeToBSplineSurface");
161
162   Standard_Integer i,j;
163
164   isuperiodic = Standard_True;
165   isvperiodic = Standard_False;
166
167   // construction of the cone in the reference mark xOy.
168
169   Standard_Real R = C.RefRadius();
170   Standard_Real A = C.SemiAngle();
171   
172   ComputePoles( R, A, 0., 2.*M_PI, V1, V2, poles); 
173
174   nbUPoles = 6;
175   nbUKnots = 4;
176   nbVPoles = 2;
177   nbVKnots = 2;
178   
179   for ( i = 1; i <= nbUKnots; i++) {
180     uknots(i) = ( i-1) * 2. * M_PI /3.;
181     umults(i) = 2;
182   }
183   vknots(1) = V1;  vmults(1) = 2;
184   vknots(2) = V2;  vmults(2) = 2;
185
186   // replace bspline in the mark of the cone.
187   // and calculate the weight of bspline.
188   Standard_Real W;
189   gp_Trsf Trsf;
190   Trsf.SetTransformation( C.Position(), gp::XOY());
191
192   for ( i = 1; i <= nbUPoles; i++) {
193     if ( i % 2 == 0)  W = 0.5;    // = Cos(pi /3)
194     else              W = 1.;
195
196     for ( j = 1; j <= nbVPoles; j++) {
197       weights( i, j) = W;
198       poles( i, j).Transform( Trsf);
199     }
200   }
201 }