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 | |
55 | ShapeCustom_Surface::ShapeCustom_Surface() : myGap (0) |
56 | { |
57 | } |
58 | |
59 | //======================================================================= |
60 | //function : ShapeCustom_Surface |
61 | //purpose : |
62 | //======================================================================= |
63 | |
64 | ShapeCustom_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 | |
75 | void ShapeCustom_Surface::Init (const Handle(Geom_Surface)& S) |
76 | { |
77 | mySurf = S; |
78 | } |
79 | |
80 | //======================================================================= |
81 | //function : ConvertToAnalytical |
82 | //purpose : |
83 | //======================================================================= |
84 | |
85 | Handle(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 |
398 | Handle(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 | } |