0024059: Eliminate compiler warning C4701 in MSVC++ with warning level 4
[occt.git] / src / ShapeCustom / ShapeCustom_Surface.cxx
CommitLineData
b311480e 1// Copyright (c) 1999-2012 OPEN CASCADE SAS
2//
3// The content of this file is subject to the Open CASCADE Technology Public
4// License Version 6.5 (the "License"). You may not use the content of this file
5// except in compliance with the License. Please obtain a copy of the License
6// at http://www.opencascade.org and read it completely before using this file.
7//
8// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10//
11// The Original Code and all software distributed under the License is
12// distributed on an "AS IS" basis, without warranty of any kind, and the
13// Initial Developer hereby disclaims all such warranties, including without
14// limitation, any warranties of merchantability, fitness for a particular
15// purpose or non-infringement. Please see the License for the specific terms
16// and conditions governing the rights and limitations under the License.
17
7fd59977 18//abv 06.01.99 fix of misprint
19//:p6 abv 26.02.99: make ConvertToPeriodic() return Null if nothing done
20#include <ShapeCustom_Surface.ixx>
21
22#include <gp_Ax3.hxx>
23#include <gp_Pnt.hxx>
24#include <gp_Vec.hxx>
25#include <gp_Pln.hxx>
26#include <gp_Cylinder.hxx>
27
28#include <ElSLib.hxx>
29#include <TColgp_Array1OfPnt.hxx>
30#include <TColStd_Array1OfReal.hxx>
31#include <TColgp_Array2OfPnt.hxx>
32#include <TColStd_Array2OfReal.hxx>
33#include <TColStd_Array1OfInteger.hxx>
34
35#include <Geom_Curve.hxx>
36#include <Geom_Plane.hxx>
37#include <Geom_BSplineSurface.hxx>
38#include <Geom_BezierSurface.hxx>
39#include <Geom_SphericalSurface.hxx>
40#include <Geom_CylindricalSurface.hxx>
41#include <Geom_ConicalSurface.hxx>
42#include <Geom_ToroidalSurface.hxx>
43#include <GeomAdaptor_HSurface.hxx>
44#include <GeomAdaptor_Surface.hxx>
45#include <GeomAbs_SurfaceType.hxx>
46
47#include <ShapeAnalysis_Geom.hxx>
48#include <ShapeAnalysis_Surface.hxx>
49
50//=======================================================================
51//function : ShapeCustom_Surface
52//purpose :
53//=======================================================================
54
55ShapeCustom_Surface::ShapeCustom_Surface() : myGap (0)
56{
57}
58
59//=======================================================================
60//function : ShapeCustom_Surface
61//purpose :
62//=======================================================================
63
64ShapeCustom_Surface::ShapeCustom_Surface (const Handle(Geom_Surface)& S)
65 : myGap (0)
66{
67 Init ( S );
68}
69
70//=======================================================================
71//function : Init
72//purpose :
73//=======================================================================
74
75void ShapeCustom_Surface::Init (const Handle(Geom_Surface)& S)
76{
77 mySurf = S;
78}
79
80//=======================================================================
81//function : ConvertToAnalytical
82//purpose :
83//=======================================================================
84
85Handle(Geom_Surface) ShapeCustom_Surface::ConvertToAnalytical (const Standard_Real tol,
86 const Standard_Boolean substitute)
87{
88 Handle(Geom_Surface) newSurf;
89
90 Standard_Integer nUP, nVP, nCP, i, j , UDeg, VDeg;
91 Standard_Real U1, U2, V1, V2, C1, C2, DU, DV, U=0, V=0;
92 Handle(Geom_Curve) iso;
93 Standard_Boolean uClosed = Standard_True;
94
95 // seuls cas traites : BSpline et Bezier
96 Handle(Geom_BSplineSurface) theBSplneS =
97 Handle(Geom_BSplineSurface)::DownCast(mySurf);
98 if (theBSplneS.IsNull()) {
99 Handle(Geom_BezierSurface) theBezierS =
100 Handle(Geom_BezierSurface)::DownCast(mySurf);
101 if (!theBezierS.IsNull()) { // Bezier :
102 nUP = theBezierS->NbUPoles();
103 nVP = theBezierS->NbVPoles();
104 UDeg = theBezierS->UDegree();
105 VDeg = theBezierS->VDegree();
106 }
107 else return newSurf; // non reconnu : terminus
108 }
109 else { // BSpline :
110 nUP = theBSplneS->NbUPoles();
111 nVP = theBSplneS->NbVPoles();
112 UDeg = theBSplneS->UDegree();
113 VDeg = theBSplneS->VDegree();
114 }
115
116
117 mySurf->Bounds(U1, U2, V1, V2);
118// mySurf->Bounds(U1, U2, V1, V2);
119 TColgp_Array1OfPnt p1(1, 3), p2(1, 3), p3(1, 3);
120 TColStd_Array1OfReal R(1,3);
121 gp_Pnt origPnt, resPnt;
122 gp_Vec origD1U, resD1U, resD1V;
123
124 Standard_Boolean aCySpCo = Standard_False;
125 Standard_Boolean aToroid = Standard_False;
126 Standard_Boolean aPlanar = Standard_False;
127
128 if (nUP == 2 && nVP == 2) {
129 if (UDeg == 1 && VDeg == 1) aPlanar = Standard_True;
130 } else if (mySurf->IsUClosed()) { // VRAI IsUClosed
131 if (mySurf->IsVClosed()) aToroid = Standard_True;
132 else aCySpCo = Standard_True;
133 } else {
134 if(mySurf->IsVClosed()) { // VRAI IsVClosed
135 aCySpCo = Standard_True;
136 uClosed = Standard_False;
137 }
138 }
139
140 if (aPlanar) {
141// NearestPlane ...
142 TColgp_Array1OfPnt Pnts(1,4);
143 Pnts.SetValue(1,mySurf->Value(U1,V1));
144 Pnts.SetValue(2,mySurf->Value(U2,V1));
145 Pnts.SetValue(3,mySurf->Value(U1,V2));
146 Pnts.SetValue(4,mySurf->Value(U2,V2));
147 gp_Pln aPln;// Standard_Real Dmax;
148 Standard_Integer It = ShapeAnalysis_Geom::NearestPlane (Pnts,aPln,myGap/*Dmax*/);
149
150// ICI, on fabrique le plan, et zou
151 if (It == 0 || myGap/*Dmax*/ > tol) return newSurf; // pas un plan
152
153// IL RESTE a verifier l orientation ...
154// On regarde sur chaque surface les vecteurs P(U0->U1),P(V0->V1)
155// On prend la normale : les deux normales doivent etre dans le meme sens
156// Sinon, inverser la normale (pas le Pln entier !) et refaire la Plane
157 newSurf = new Geom_Plane (aPln);
158 gp_Vec uold (Pnts(1),Pnts(2));
159 gp_Vec vold (Pnts(1),Pnts(3));
160 gp_Vec nold = uold.Crossed (vold);
161 gp_Vec unew (newSurf->Value(U1,V1), newSurf->Value(U2,V1));
162 gp_Vec vnew (newSurf->Value(U1,V1), newSurf->Value(U1,V2));
163 gp_Vec nnew = unew.Crossed (vnew);
164 if (nold.Dot (nnew) < 0.0) {
165 gp_Ax3 ax3 = aPln.Position();
166 ax3.ZReverse();
167 ax3.XReverse();
168 aPln = gp_Pln (ax3);
169 newSurf = new Geom_Plane (aPln);
170 }
171
172 if (substitute) {
173 Init (newSurf);
174 }
175 return newSurf;
176
177
178 } else if (aCySpCo) {
179 if (!uClosed) {
180 C1 = U1; C2 = U2;
181 U1 = V1; U2 = V2;
182 V1 = C1; V2 = C2;
183 nCP = nUP; nUP = nVP; nVP = nCP;
184 }
185
186 for (i=1; i<=3; i++) {
187 if (i==1) V = V1;
188 else if (i==2) V = V2;
189 else if (i==3) V = 0.5*(V1+V2);
190
191 if(uClosed) iso = mySurf->VIso(V);
192 else iso = mySurf->UIso(V);
193
194 iso->D0(U1, p1(i));
195 iso->D0(0.5*(U1+U2), p2(i));
196 p3(i).SetCoord(0.5*(p1(i).X()+p2(i).X()),
197 0.5*(p1(i).Y()+p2(i).Y()),
198 0.5*(p1(i).Z()+p2(i).Z()));
199 R(i) = p3(i).Distance(p1(i));
200// cout<<"sphere, i="<<i<<" V="<<V<<" R="<<R(i)<<" p1="<<p1(i).X()<<","<<p1(i).Y()<<","<<p1(i).Z()<<" p2="<<p2(i).X()<<","<<p2(i).Y()<<","<<p2(i).Z()<<" p3="<<p3(i).X()<<","<<p3(i).Y()<<","<<p3(i).Z()<<endl;
201 }
202
203 iso->D1 (0.,origPnt,origD1U);
204 gp_Vec xVec(p3(3), p1(3));
205 gp_Vec aVec(p3(1), p3(2));
206// gp_Dir xDir(xVec); ne sert pas. Null si R3 = 0
207 gp_Dir aDir(aVec);
208 gp_Ax3 aAx3 (p3(1),aDir,xVec);
209 // CKY 3-FEV-1997 : verification du sens de description
210 //gp_Dir AXY = aAx3.YDirection(); // AXY not used (skl)
211 if (aAx3.YDirection().Dot (origD1U) < 0) {
212#ifdef DEBUG
213 cout<<" Surface Analytique : sens a inverser"<<endl;
214#endif
215 aAx3.YReverse(); // mais X reste !
216 }
217
218 if (nVP > 2) {
219 if ((Abs(R(1)) < tol) &&
220 (Abs(R(2)) < tol) &&
221 (Abs(R(3)) > tol)) {
222// deja fait gp_Ax3 aAx3(p3(1), aDir, xVec);
223 //gp_Ax3 aAx3(p3(3), aDir);
224 Handle(Geom_SphericalSurface) anObject =
225 new Geom_SphericalSurface(aAx3, R(3));
226 if (!uClosed) anObject->UReverse();
227 newSurf = anObject;
228 }
229 }
230 else if (nVP == 2) {
231
232// deja fait gp_Ax3 aAx3(p3(1), aDir, xVec);
233 //gp_Ax3 aAx3(p3(1), aDir);
234
235 if (Abs(R(2)-R(1)) < tol) {
236 Handle(Geom_CylindricalSurface) anObject =
237 new Geom_CylindricalSurface(aAx3, R(1));
238 if (!uClosed) anObject->UReverse();
239 newSurf = anObject;
240 }
241 else {
242 gp_Vec aVec2(p1(1), p1(2));
243 Standard_Real angle = aVec.Angle(aVec2);
244 if (R(1) < R(2)) {
245 Handle(Geom_ConicalSurface) anObject =
246 new Geom_ConicalSurface(aAx3, angle, R(1));
247 //if (!uClosed) anObject->UReverse();
248 anObject->UReverse();
249 newSurf = anObject;
250 }
251 else {
252 aDir.Reverse();
253 gp_Vec anotherXVec(p3(2), p1(2));
254 gp_Dir anotherXDir(anotherXVec);
255 gp_Ax3 anotherAx3(p3(2), aDir, anotherXDir);
256 Handle(Geom_ConicalSurface) anObject =
257 new Geom_ConicalSurface(anotherAx3, angle, R(2));
258 //if (!uClosed) anObject->UReverse();
259 anObject->UReverse();
260 newSurf = anObject;
261 }
262 }
263 }
264 }
265 else if (aToroid) {
266 // test by iso U and isoV
267 Standard_Boolean isFound = Standard_False;
268 for (j=1; (j<=2) && !isFound; j++) {
269 if (j==2) {
270 C1 = U1; C2 = U2;
271 U1 = V1; U2 = V2;
272 V1 = C1; V2 = C2;
273 }
274 for (i=1; i<=3; i++) {
275 if (i==1) U = U1;
276 else if (i==2) U = 0.5*(U1+U2);
277 else if (i==3) U = 0.25*(U1+U2);
278
279 iso = mySurf->UIso(U);
280
281 iso->D0(V1, p1(i));
282 iso->D0(0.5*(V1+V2), p2(i));
283 p3(i).SetCoord(0.5*(p1(i).X()+p2(i).X()),
284 0.5*(p1(i).Y()+p2(i).Y()),
285 0.5*(p1(i).Z()+p2(i).Z()));
286 R(i) = p3(i).Distance(p1(i));
287 }
288 if ((Abs(R(1)-R(2))< tol) &&
289 (Abs(R(1)-R(3))< tol)) {
290 gp_Pnt p10(0.5*(p3(1).X()+p3(2).X()),
291 0.5*(p3(1).Y()+p3(2).Y()),
292 0.5*(p3(1).Z()+p3(2).Z()));
293 gp_Vec aVec(p10, p3(1));
294 gp_Vec aVec2(p10, p3(3));
295 Standard_Real RR1 = R(1), RR2 = R(2), RR3;
296 aVec ^= aVec2;
297
298 if (aVec.Magnitude() <= gp::Resolution()) aVec.SetCoord(0., 0., 1.);
299
300 gp_Dir aDir(aVec);
301
302 gp_Ax3 aAx3(p10, aDir);
303 RR1 = p10.Distance(p3(1));
304// modif empirique (pourtant NON DEMONTREE) : inverser roles RR1,RR2
305// CKY, 24-JAN-1997
306 if (RR1 < RR2) { RR3 = RR1; RR1 = RR2; RR2 = RR3; }
307 Handle(Geom_ToroidalSurface) anObject =
308 new Geom_ToroidalSurface(aAx3, RR1, RR2);
309 if (j==2) anObject->UReverse();
310 anObject->D1 (0.,0.,resPnt,resD1U,resD1V);
311#ifdef DEBUG
312 if (resD1U.Dot(origD1U) < 0 && j != 2)
313 cout<<" Tore a inverser !"<<endl;
314#endif
315 newSurf = anObject;
316 isFound = Standard_True;
317 }
318 }
319 }
320 if (newSurf.IsNull()) return newSurf;
321
322 //---------------------------------------------------------------------
323 // verification
324 //---------------------------------------------------------------------
325
326 Handle(GeomAdaptor_HSurface) NHS = new GeomAdaptor_HSurface (newSurf);
327 GeomAdaptor_Surface& SurfAdapt = NHS->ChangeSurface();
328
329 const Standard_Integer NP = 21;
1d47d8d0 330 Standard_Real S = 0., T = 0.; // U,V deja fait
7fd59977 331 gp_Pnt P3d, P3d2;
332 Standard_Boolean onSurface = Standard_True;
333
334 Standard_Real dis; myGap = 0.;
335
336 DU = (U2-U1)/(NP-1);
337 DV = (V2-V1)/(NP-1);
338 for (j=1; (j<=NP) && onSurface; j++) {
339 V = V1 + DV*(j-1);
340
341 if(uClosed) iso = mySurf->VIso(V);
342 else iso = mySurf->UIso(V);
343
344 for (i=1; i<=NP; i++) {
345 U = U1 + DU*(i-1);
346 iso->D0(U, P3d);
347 switch (SurfAdapt.GetType()){
348
349 case GeomAbs_Cylinder :
350 {
351 gp_Cylinder Cylinder = SurfAdapt.Cylinder();
352 ElSLib::Parameters( Cylinder, P3d, S, T);
353 break;
354 }
355 case GeomAbs_Cone :
356 {
357 gp_Cone Cone = SurfAdapt.Cone();
358 ElSLib::Parameters( Cone, P3d, S, T);
359 break;
360 }
361 case GeomAbs_Sphere :
362 {
363 gp_Sphere Sphere = SurfAdapt.Sphere();
364 ElSLib::Parameters( Sphere, P3d, S, T);
365 break;
366 }
367 case GeomAbs_Torus :
368 {
369 gp_Torus Torus = SurfAdapt.Torus();
370 ElSLib::Parameters( Torus, P3d, S, T);
371 break;
372 }
373 default:
374 break;
375 }
376
377 newSurf->D0(S, T, P3d2);
378
379 dis = P3d.Distance(P3d2);
380 if (dis > myGap) myGap = dis;
381
382 if (dis > tol) {
383 onSurface = Standard_False;
384 newSurf.Nullify();
385 // The presumption is rejected
386 break;
387 }
388 }
389 }
390 if (substitute && !NHS.IsNull()) {
391 Init (newSurf);
392 }
393 return newSurf;
394}
395
396//%pdn 30 Nov 98: converting bspline surfaces with degree+1 at ends to periodic
397// UKI60591, entity 48720
398Handle(Geom_Surface) ShapeCustom_Surface::ConvertToPeriodic (const Standard_Boolean substitute,
399 const Standard_Real preci)
400{
401 Handle(Geom_Surface) newSurf;
402 Handle(Geom_BSplineSurface) BSpl = Handle(Geom_BSplineSurface)::DownCast(mySurf);
403 if (BSpl.IsNull()) return newSurf;
404
405 ShapeAnalysis_Surface sas(mySurf);
406 Standard_Boolean uclosed = sas.IsUClosed(preci);
407 Standard_Boolean vclosed = sas.IsVClosed(preci);
408
409 if ( ! uclosed && ! vclosed ) return newSurf;
410
411 Standard_Boolean converted = Standard_False; //:p6
412
413 if ( uclosed && ! BSpl->IsUPeriodic() && BSpl->NbUPoles() >3 ) {
414 Standard_Boolean set = Standard_True;
415 // if degree+1 at ends, first change it to 1 by rearranging knots
416 if ( BSpl->UMultiplicity(1) == BSpl->UDegree() + 1 &&
417 BSpl->UMultiplicity(BSpl->NbUKnots()) == BSpl->UDegree() + 1 ) {
418 Standard_Integer nbUPoles = BSpl->NbUPoles();
419 Standard_Integer nbVPoles = BSpl->NbVPoles();
420 TColgp_Array2OfPnt oldPoles(1,nbUPoles,1,nbVPoles);
421 TColStd_Array2OfReal oldWeights(1,nbUPoles,1,nbVPoles);
422 Standard_Integer nbUKnots = BSpl->NbUKnots();
423 Standard_Integer nbVKnots = BSpl->NbVKnots();
424 TColStd_Array1OfReal oldUKnots(1,nbUKnots);
425 TColStd_Array1OfReal oldVKnots(1,nbVKnots);
426 TColStd_Array1OfInteger oldUMults(1,nbUKnots);
427 TColStd_Array1OfInteger oldVMults(1,nbVKnots);
428
429 BSpl->Poles(oldPoles);
430 BSpl->Weights(oldWeights);
431 BSpl->UKnots(oldUKnots);
432 BSpl->VKnots(oldVKnots);
433 BSpl->UMultiplicities(oldUMults);
434 BSpl->VMultiplicities(oldVMults);
435
436 TColStd_Array1OfReal newUKnots (1,nbUKnots+2);
437 TColStd_Array1OfInteger newUMults(1,nbUKnots+2);
438 Standard_Real a = 0.5 * ( BSpl->UKnot(2) - BSpl->UKnot(1) +
439 BSpl->UKnot(nbUKnots) - BSpl->UKnot(nbUKnots-1) );
440
441 newUKnots(1) = oldUKnots(1) - a;
442 newUKnots(nbUKnots+2) = oldUKnots(nbUKnots) + a;
443 newUMults(1) = newUMults(nbUKnots+2) = 1;
444 for (Standard_Integer i = 2; i<=nbUKnots+1; i++) {
445 newUKnots(i) = oldUKnots(i-1);
446 newUMults(i) = oldUMults(i-1);
447 }
448 newUMults(2) = newUMults(nbUKnots+1) = BSpl->UDegree();
449 Handle(Geom_BSplineSurface) res = new Geom_BSplineSurface(oldPoles,
450 oldWeights,
451 newUKnots,oldVKnots,
452 newUMults,oldVMults,
453 BSpl->UDegree(),BSpl->VDegree(),
454 BSpl->IsUPeriodic(),BSpl->IsVPeriodic());
455 BSpl = res;
456 }
457 else if ( BSpl->UMultiplicity(1) > BSpl->UDegree() ||
458 BSpl->UMultiplicity(BSpl->NbUKnots()) > BSpl->UDegree() + 1 ) set = Standard_False;
459 if ( set ) {
460 BSpl->SetUPeriodic(); // make periodic
461 converted = Standard_True;
462 }
463 }
464
465 if ( vclosed && ! BSpl->IsVPeriodic() && BSpl->NbVPoles() >3 ) {
466 Standard_Boolean set = Standard_True;
467 // if degree+1 at ends, first change it to 1 by rearranging knots
468 if ( BSpl->VMultiplicity(1) == BSpl->VDegree() + 1 &&
469 BSpl->VMultiplicity(BSpl->NbVKnots()) == BSpl->VDegree() + 1 ) {
470 Standard_Integer nbUPoles = BSpl->NbUPoles();
471 Standard_Integer nbVPoles = BSpl->NbVPoles();
472 TColgp_Array2OfPnt oldPoles(1,nbUPoles,1,nbVPoles);
473 TColStd_Array2OfReal oldWeights(1,nbUPoles,1,nbVPoles);
474 Standard_Integer nbUKnots = BSpl->NbUKnots();
475 Standard_Integer nbVKnots = BSpl->NbVKnots();
476 TColStd_Array1OfReal oldUKnots(1,nbUKnots);
477 TColStd_Array1OfReal oldVKnots(1,nbVKnots);
478 TColStd_Array1OfInteger oldUMults(1,nbUKnots);
479 TColStd_Array1OfInteger oldVMults(1,nbVKnots);
480
481 BSpl->Poles(oldPoles);
482 BSpl->Weights(oldWeights);
483 BSpl->UKnots(oldUKnots);
484 BSpl->VKnots(oldVKnots);
485 BSpl->UMultiplicities(oldUMults);
486 BSpl->VMultiplicities(oldVMults);
487
488 TColStd_Array1OfReal newVKnots (1,nbVKnots+2);
489 TColStd_Array1OfInteger newVMults(1,nbVKnots+2);
490 Standard_Real a = 0.5 * ( BSpl->VKnot(2) - BSpl->VKnot(1) +
491 BSpl->VKnot(nbVKnots) - BSpl->VKnot(nbVKnots-1) );
492
493 newVKnots(1) = oldVKnots(1) - a;
494 newVKnots(nbVKnots+2) = oldVKnots(nbVKnots) + a;
495 newVMults(1) = newVMults(nbVKnots+2) = 1;
496 for (Standard_Integer i = 2; i<=nbVKnots+1; i++) {
497 newVKnots(i) = oldVKnots(i-1);
498 newVMults(i) = oldVMults(i-1);
499 }
500 newVMults(2) = newVMults(nbVKnots+1) = BSpl->VDegree();
501 Handle(Geom_BSplineSurface) res = new Geom_BSplineSurface(oldPoles,
502 oldWeights,
503 oldUKnots,newVKnots,
504 oldUMults,newVMults,
505 BSpl->UDegree(),BSpl->VDegree(),
506 BSpl->IsUPeriodic(),BSpl->IsVPeriodic());
507 BSpl = res;
508 }
509 else if ( BSpl->VMultiplicity(1) > BSpl->VDegree() ||
510 BSpl->VMultiplicity(BSpl->NbVKnots()) > BSpl->VDegree() + 1 ) set = Standard_False;
511 if ( set ) {
512 BSpl->SetVPeriodic(); // make periodic
513 converted = Standard_True;
514 }
515 }
516
517#ifdef DEBUG
518 cout << "Warning: ShapeCustom_Surface: Closed BSplineSurface is caused to be periodic" << endl;
519#endif
520 if ( ! converted ) return newSurf;
521 newSurf = BSpl;
522 if ( substitute ) mySurf = newSurf;
523 return newSurf;
524}