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