57c9a01fe9ea518f0bb20a5374d408b5cc1b55c9
[occt.git] / src / GeomFill / GeomFill_BSplineCurves.cxx
1 // Created on: 1993-10-06
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BSplCLib.hxx>
19 #include <Geom_BSplineCurve.hxx>
20 #include <Geom_BSplineSurface.hxx>
21 #include <GeomFill_BSplineCurves.hxx>
22 #include <GeomFill_Coons.hxx>
23 #include <GeomFill_Curved.hxx>
24 #include <GeomFill_Filling.hxx>
25 #include <GeomFill_Stretch.hxx>
26 #include <Precision.hxx>
27 #include <Standard_ConstructionError.hxx>
28 #include <Standard_NotImplemented.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColgp_Array2OfPnt.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33 #include <TColStd_Array2OfReal.hxx>
34
35 //=======================================================================
36 //function : Arrange
37 //purpose  : Internal Use Only
38 //           This function is used to prepare the Filling: The Curves
39 //           are arranged in this way:
40 //                      CC3
41 //                  ----->-----
42 //                 |           |
43 //                 |           |
44 //                 |           |
45 //             CC4 ^           ^ CC2
46 //                 |           |
47 //                 |           |
48 //                  ----->-----
49 //                   CC1 = C1
50 //=======================================================================
51 Standard_Boolean Arrange(const Handle(Geom_BSplineCurve)& C1,
52                          const Handle(Geom_BSplineCurve)& C2,
53                          const Handle(Geom_BSplineCurve)& C3,
54                          const Handle(Geom_BSplineCurve)& C4,
55                                Handle(Geom_BSplineCurve)& CC1,
56                                Handle(Geom_BSplineCurve)& CC2,
57                                Handle(Geom_BSplineCurve)& CC3,
58                                Handle(Geom_BSplineCurve)& CC4,
59                          const Standard_Real Tol             )
60 {
61   Handle(Geom_BSplineCurve) GC[4];
62   Handle(Geom_BSplineCurve) Dummy;
63   GC[0] = Handle(Geom_BSplineCurve)::DownCast(C1->Copy());
64   GC[1] = Handle(Geom_BSplineCurve)::DownCast(C2->Copy());
65   GC[2] = Handle(Geom_BSplineCurve)::DownCast(C3->Copy());
66   GC[3] = Handle(Geom_BSplineCurve)::DownCast(C4->Copy());
67   
68   Standard_Integer i,j;
69   Standard_Boolean Trouve;
70
71   for (i=1; i<=3; i++) {
72     Trouve = Standard_False;
73     for ( j=i; j<=3 && !Trouve; j++) {
74       if (GC[j]->StartPoint().Distance( GC[i-1]->EndPoint()) < Tol) {
75         Dummy  = GC[i];
76         GC[i]  = GC[j];
77         GC[j]  = Dummy;
78         Trouve = Standard_True;
79       }
80       else if (GC[j]->EndPoint().Distance( GC[i-1]->EndPoint()) < Tol) {
81         GC[j]  = Handle(Geom_BSplineCurve)::DownCast(GC[j]->Reversed());
82         Dummy  = GC[i];
83         GC[i]  = GC[j];
84         GC[j]  = Dummy;
85         Trouve = Standard_True;
86       }
87     }
88     if (!Trouve) return Standard_False;
89   }
90
91   CC1 = GC[0];
92   CC2 = GC[1];
93   CC3 = Handle(Geom_BSplineCurve)::DownCast( GC[2]->Reversed());
94   CC4 = Handle(Geom_BSplineCurve)::DownCast( GC[3]->Reversed());
95
96   return Standard_True;
97 }
98
99
100
101 //=======================================================================
102 //function : SetSameDistribution
103 //purpose  : Internal Use Only
104 //=======================================================================
105
106 Standard_Integer SetSameDistribution(Handle(Geom_BSplineCurve)& C1,
107                                      Handle(Geom_BSplineCurve)& C2 )
108 {
109   Standard_Integer nbp1 = C1->NbPoles();
110   Standard_Integer nbk1 = C1->NbKnots();
111   TColgp_Array1OfPnt      P1(1,nbp1);
112   TColStd_Array1OfReal    W1(1,nbp1);
113   W1.Init(1.);
114   TColStd_Array1OfReal    K1(1,nbk1);
115   TColStd_Array1OfInteger M1(1,nbk1);
116   
117   C1->Poles(P1);
118   if( C1->IsRational()) 
119     C1->Weights(W1);
120   C1->Knots(K1);
121   C1->Multiplicities(M1);
122   
123   Standard_Integer nbp2 = C2->NbPoles();
124   Standard_Integer nbk2 = C2->NbKnots();
125   TColgp_Array1OfPnt      P2(1,nbp2);
126   TColStd_Array1OfReal    W2(1,nbp2);
127   W2.Init(1.);
128   TColStd_Array1OfReal    K2(1,nbk2);
129   TColStd_Array1OfInteger M2(1,nbk2);
130   
131   C2->Poles(P2);
132   if( C2->IsRational()) 
133     C2->Weights(W2);
134   C2->Knots(K2);
135   C2->Multiplicities(M2);
136   
137   Standard_Real K11 = K1( 1  );
138   Standard_Real K12 = K1(nbk1);
139   Standard_Real K21 = K2( 1  );
140   Standard_Real K22 = K2(nbk2);
141   
142   if ( (K12-K11) > (K22-K21)) {
143     BSplCLib::Reparametrize( K11, K12, K2);
144     C2->SetKnots(K2);
145   }
146   else if ( (K12-K11) < (K22-K21)) {
147     BSplCLib::Reparametrize( K21, K22, K1);
148     C1->SetKnots(K1);
149   }
150   else if(Abs(K12-K11) > Precision::PConfusion()) {
151     BSplCLib::Reparametrize( K11, K12, K2);
152     C2->SetKnots(K2);
153   }    
154   
155   Standard_Integer NP,NK;
156   if ( BSplCLib::PrepareInsertKnots(C1->Degree(),Standard_False,
157                                     K1,M1,K2,&M2,NP,NK,Precision::PConfusion(),
158                                     Standard_False)) {
159     TColgp_Array1OfPnt      NewP(1, NP);
160     TColStd_Array1OfReal    NewW(1, NP);
161     TColStd_Array1OfReal    NewK(1, NK);
162     TColStd_Array1OfInteger NewM(1, NK);
163     BSplCLib::InsertKnots(C1->Degree(),Standard_False,
164                           P1,&W1,K1,M1,K2,&M2,
165                           NewP,&NewW,NewK,NewM,Precision::PConfusion(),
166                           Standard_False);
167     if ( C1->IsRational()) {
168       C1 = new Geom_BSplineCurve(NewP,NewW,NewK,NewM,C1->Degree());
169     }
170     else {
171       C1 = new Geom_BSplineCurve(NewP,NewK,NewM,C1->Degree());
172     }
173     BSplCLib::InsertKnots(C2->Degree(),Standard_False,
174                           P2,&W2,K2,M2,K1,&M1,
175                           NewP,&NewW,NewK,NewM,Precision::PConfusion(),
176                           Standard_False);
177     if ( C2->IsRational()) {
178       C2 = new Geom_BSplineCurve(NewP,NewW,NewK,NewM,C2->Degree());
179     }
180     else {
181       C2 = new Geom_BSplineCurve(NewP,NewK,NewM,C2->Degree());
182     }
183   }
184   else {
185     throw Standard_ConstructionError(" ");
186   }
187   
188   return C1->NbPoles();
189 }
190
191
192 //=======================================================================
193 //function : GeomFill_BSplineCurves
194 //purpose  : 
195 //=======================================================================
196
197 GeomFill_BSplineCurves::GeomFill_BSplineCurves()
198 {
199 }
200
201
202 //=======================================================================
203 //function : GeomFill_BSplineCurves
204 //purpose  : 
205 //=======================================================================
206
207 GeomFill_BSplineCurves::GeomFill_BSplineCurves
208   (const Handle(Geom_BSplineCurve)& C1, 
209    const Handle(Geom_BSplineCurve)& C2, 
210    const Handle(Geom_BSplineCurve)& C3, 
211    const Handle(Geom_BSplineCurve)& C4, 
212    const GeomFill_FillingStyle Type      )
213 {
214   Init( C1, C2, C3, C4, Type);
215 }
216
217
218 //=======================================================================
219 //function : GeomFill_BSplineCurves
220 //purpose  : 
221 //=======================================================================
222
223 GeomFill_BSplineCurves::GeomFill_BSplineCurves
224   (const Handle(Geom_BSplineCurve)& C1, 
225    const Handle(Geom_BSplineCurve)& C2, 
226    const Handle(Geom_BSplineCurve)& C3, 
227    const GeomFill_FillingStyle Type      )
228 {
229   Init( C1, C2, C3, Type);
230 }
231
232
233 //=======================================================================
234 //function : GeomFill_BSplineCurves
235 //purpose  : 
236 //=======================================================================
237
238 GeomFill_BSplineCurves::GeomFill_BSplineCurves
239   (const Handle(Geom_BSplineCurve)& C1, 
240    const Handle(Geom_BSplineCurve)& C2,
241    const GeomFill_FillingStyle Type      )
242 {
243   Init( C1, C2, Type);
244 }
245
246
247 //=======================================================================
248 //function : Init
249 //purpose  : 
250 //=======================================================================
251
252 void  GeomFill_BSplineCurves::Init
253   (const Handle(Geom_BSplineCurve)& C1, 
254    const Handle(Geom_BSplineCurve)& C2, 
255    const Handle(Geom_BSplineCurve)& C3, 
256    const Handle(Geom_BSplineCurve)& C4, 
257    const GeomFill_FillingStyle Type      )
258 {
259   // On ordonne les courbes
260   Handle(Geom_BSplineCurve) CC1, CC2, CC3, CC4;
261   
262   Standard_Real Tol = Precision::Confusion();
263 #ifndef No_Exception
264   Standard_Boolean IsOK =
265 #endif
266     Arrange( C1, C2, C3, C4, CC1, CC2, CC3, CC4, Tol);
267   
268   Standard_ConstructionError_Raise_if 
269     (!IsOK, " GeomFill_BSplineCurves: Courbes non jointives");
270
271   // Mise en conformite des degres
272   Standard_Integer Deg1 = CC1->Degree();
273   Standard_Integer Deg2 = CC2->Degree();
274   Standard_Integer Deg3 = CC3->Degree();
275   Standard_Integer Deg4 = CC4->Degree();
276   Standard_Integer DegU = Max( Deg1, Deg3);
277   Standard_Integer DegV = Max( Deg2, Deg4);
278   if ( Deg1 < DegU) CC1->IncreaseDegree(DegU);
279   if ( Deg2 < DegV) CC2->IncreaseDegree(DegV);
280   if ( Deg3 < DegU) CC3->IncreaseDegree(DegU);
281   if ( Deg4 < DegV) CC4->IncreaseDegree(DegV);
282
283   // Mise en conformite des distributions de noeuds
284   Standard_Integer NbUPoles = SetSameDistribution(CC1,CC3);
285   Standard_Integer NbVPoles = SetSameDistribution(CC2,CC4);
286
287   if(Type == GeomFill_CoonsStyle) {
288     if(NbUPoles < 4 || NbVPoles < 4)
289       throw Standard_ConstructionError("GeomFill_BSplineCurves: invalid filling style");
290   }
291
292   TColgp_Array1OfPnt P1(1,NbUPoles);
293   TColgp_Array1OfPnt P2(1,NbVPoles);
294   TColgp_Array1OfPnt P3(1,NbUPoles);
295   TColgp_Array1OfPnt P4(1,NbVPoles);
296   CC1->Poles(P1);
297   CC2->Poles(P2);
298   CC3->Poles(P3);
299   CC4->Poles(P4);
300
301   // Traitement des courbes rationelles
302   Standard_Boolean isRat = ( CC1->IsRational() || CC2->IsRational() ||
303                              CC3->IsRational() || CC4->IsRational()   );
304
305   TColStd_Array1OfReal W1(1,NbUPoles);
306   TColStd_Array1OfReal W3(1,NbUPoles);
307   TColStd_Array1OfReal W2(1,NbVPoles);
308   TColStd_Array1OfReal W4(1,NbVPoles);
309   W1.Init(1.);
310   W2.Init(1.);
311   W3.Init(1.);
312   W4.Init(1.);
313   if ( isRat) {
314     if (CC1->IsRational()) {
315       CC1->Weights(W1);
316     }
317     if (CC2->IsRational()) {
318       CC2->Weights(W2);
319     }
320     if (CC3->IsRational()) {
321       CC3->Weights(W3);
322     }
323     if (CC4->IsRational()) {
324       CC4->Weights(W4);
325     }
326   }
327   
328   GeomFill_Filling Caro;
329   if (isRat) {
330     switch (Type)
331       {
332       case GeomFill_StretchStyle :
333         Caro = GeomFill_Stretch( P1, P2, P3, P4, W1, W2, W3, W4); 
334         break;
335       case GeomFill_CoonsStyle   :
336         Caro = GeomFill_Coons  ( P1, P4, P3, P2, W1, W4, W3, W2); 
337         break;
338       case GeomFill_CurvedStyle  :
339         Caro = GeomFill_Curved ( P1, P2, P3, P4, W1, W2, W3, W4); 
340         break;
341       }
342   }
343   else {
344     switch (Type) 
345       {
346       case GeomFill_StretchStyle :
347         Caro = GeomFill_Stretch( P1, P2, P3, P4); 
348         break;
349       case GeomFill_CoonsStyle   :
350         Caro = GeomFill_Coons  ( P1, P4, P3, P2); 
351         break;
352       case GeomFill_CurvedStyle  :
353         Caro = GeomFill_Curved ( P1, P2, P3, P4); 
354         break;
355       }
356   }
357   
358   NbUPoles = Caro.NbUPoles();
359   NbVPoles = Caro.NbVPoles();
360   TColgp_Array2OfPnt Poles(1,NbUPoles,1,NbVPoles);
361   
362   
363   // Creation de la surface
364   Standard_Integer NbUKnot = CC1->NbKnots();
365   TColStd_Array1OfReal    UKnots(1,NbUKnot);
366   TColStd_Array1OfInteger UMults(1,NbUKnot);
367   CC1->Knots(UKnots);
368   CC1->Multiplicities(UMults);
369
370   Standard_Integer NbVKnot = CC2->NbKnots();
371   TColStd_Array1OfReal    VKnots(1,NbVKnot);
372   TColStd_Array1OfInteger VMults(1,NbVKnot);
373   CC2->Knots(VKnots);
374   CC2->Multiplicities(VMults);
375
376   Caro.Poles(Poles);
377   
378   if (Caro.isRational()) {
379     TColStd_Array2OfReal Weights(1,NbUPoles, 1,NbVPoles);
380     Caro.Weights(Weights);
381     mySurface = new Geom_BSplineSurface(Poles        , Weights,
382                                         UKnots       , VKnots,
383                                         UMults       , VMults,
384                                         CC1->Degree(), CC2->Degree());
385   }
386   else {
387     mySurface = new Geom_BSplineSurface(Poles        ,
388                                         UKnots       , VKnots,
389                                         UMults       , VMults,
390                                         CC1->Degree(), CC2->Degree());
391   }
392   
393 }
394
395
396 //=======================================================================
397 //function : Init
398 //purpose  : 
399 //=======================================================================
400
401 void  GeomFill_BSplineCurves::Init
402   (const Handle(Geom_BSplineCurve)& C1, 
403    const Handle(Geom_BSplineCurve)& C2, 
404    const Handle(Geom_BSplineCurve)& C3, 
405    const GeomFill_FillingStyle Type      )
406 {
407   Handle(Geom_BSplineCurve) C4;
408   TColgp_Array1OfPnt      Poles(1,2);
409   TColStd_Array1OfReal    Knots(1,2);
410   TColStd_Array1OfInteger Mults(1,2);
411   Standard_Real Tol = Precision::Confusion();
412   Tol = Tol * Tol; 
413   if(C1->StartPoint().SquareDistance(C2->StartPoint()) > Tol &&
414      C1->StartPoint().SquareDistance(C2->EndPoint()) > Tol )
415     Poles( 1) = C1->StartPoint();
416   else 
417     Poles( 1) = C1->EndPoint();
418
419   if(C3->StartPoint().SquareDistance(C2->StartPoint()) > Tol &&
420      C3->StartPoint().SquareDistance(C2->EndPoint()) > Tol )
421     Poles( 2) = C3->StartPoint();
422   else 
423     Poles( 2) = C3->EndPoint();
424
425   Knots( 1) = C2->Knot(C2->FirstUKnotIndex());
426   Knots( 2) = C2->Knot(C2->LastUKnotIndex());
427   Mults( 1) = Mults( 2) = 2;
428   C4 = new Geom_BSplineCurve( Poles, Knots, Mults, 1);
429   Init( C1, C2, C3, C4, Type);
430 }
431
432
433 //=======================================================================
434 //function : Init
435 //purpose  : 
436 //=======================================================================
437
438 void  GeomFill_BSplineCurves::Init
439   (const Handle(Geom_BSplineCurve)& C1, 
440    const Handle(Geom_BSplineCurve)& C2,
441    const GeomFill_FillingStyle Type      ) 
442 {
443   Handle(Geom_BSplineCurve) 
444     CC1 = Handle(Geom_BSplineCurve)::DownCast(C1->Copy());
445   Handle(Geom_BSplineCurve) 
446     CC2 = Handle(Geom_BSplineCurve)::DownCast(C2->Copy());
447   
448   Standard_Integer Deg1 = CC1->Degree();
449   Standard_Integer Deg2 = CC2->Degree();
450
451   Standard_Boolean isRat = ( CC1->IsRational() || CC2->IsRational());
452
453   if ( Type != GeomFill_CurvedStyle) {
454     Standard_Integer DegU = Max( Deg1, Deg2);
455     
456     if ( CC1->Degree() < DegU )  CC1->IncreaseDegree(DegU);
457     if ( CC2->Degree() < DegU )  CC2->IncreaseDegree(DegU);
458     
459     // Mise en conformite des distributions de noeuds
460     Standard_Integer NbPoles = SetSameDistribution(CC1,CC2);
461     TColgp_Array2OfPnt Poles(1,NbPoles, 1,2);
462     TColgp_Array1OfPnt P1( 1, NbPoles);
463     TColgp_Array1OfPnt P2( 1, NbPoles);
464     CC1->Poles(P1);
465     CC2->Poles(P2);
466     Standard_Integer i;
467     for (i=1; i<=NbPoles; i++) {
468       Poles(i, 1) = P1(i);
469       Poles(i, 2) = P2(i);
470     }
471     Standard_Integer NbUKnots = CC1->NbKnots();
472     TColStd_Array1OfReal UKnots( 1, NbUKnots);
473     TColStd_Array1OfInteger UMults( 1, NbUKnots);
474     CC1->Knots(UKnots);
475     CC1->Multiplicities(UMults);
476 //    Standard_Integer NbVKnots = 2;
477     TColStd_Array1OfReal VKnots( 1, 2);
478     TColStd_Array1OfInteger VMults( 1, 2);
479     VKnots( 1) = 0;
480     VKnots( 2) = 1;
481     VMults( 1) = 2;
482     VMults( 2) = 2;
483     
484     
485     // Traitement des courbes rationelles
486     if (isRat) {
487       TColStd_Array2OfReal Weights(1,NbPoles, 1,2);
488       TColStd_Array1OfReal W1(1,NbPoles);
489       TColStd_Array1OfReal W2(1,NbPoles);
490       W1.Init(1.);
491       W2.Init(1.);
492
493       if ( isRat) {
494         if (CC1->IsRational()) {
495           CC1->Weights(W1);
496         }
497         if (CC2->IsRational()) {
498           CC2->Weights(W2);
499         }
500         for (i=1; i<=NbPoles; i++) {
501           Weights(i, 1) = W1( i);
502           Weights(i, 2) = W2( i);
503         }
504       }
505       mySurface = new Geom_BSplineSurface(Poles        , Weights,
506                                           UKnots       , VKnots, 
507                                           UMults       , VMults,
508                                           CC1->Degree(), 1,
509                                           CC1->IsPeriodic(), 
510                                           Standard_False);
511     }
512     else {
513       mySurface = new Geom_BSplineSurface(Poles        ,
514                                           UKnots       , VKnots, 
515                                           UMults       , VMults,
516                                           CC1->Degree(), 1);
517     }
518   }
519   else {
520     Standard_Real Eps = Precision::Confusion();
521     Standard_Boolean IsOK = Standard_False;
522     if ( CC1->StartPoint().IsEqual(CC2->StartPoint(),Eps)) {
523       IsOK = Standard_True;
524     }
525     else if ( CC1->StartPoint().IsEqual(CC2->EndPoint(),Eps)) {
526       CC2->Reverse();
527       IsOK = Standard_True;
528     }
529     else if ( CC1->EndPoint().IsEqual(CC2->StartPoint(),Eps)) {
530       C1->Reverse();
531       IsOK = Standard_True;
532     }
533     else if ( CC1->EndPoint().IsEqual(CC2->EndPoint(),Eps)) {
534       CC1->Reverse();
535       CC2->Reverse();
536       IsOK = Standard_True;
537     }
538     
539     if(!IsOK)
540       throw Standard_OutOfRange("GeomFill_BSplineCurves: Courbes non jointives");
541
542     Standard_Integer NbUPoles = CC1->NbPoles();
543     Standard_Integer NbVPoles = CC2->NbPoles();
544     TColgp_Array1OfPnt P1(1,NbUPoles);
545     TColgp_Array1OfPnt P2(1,NbVPoles);
546     CC1->Poles(P1);
547     CC2->Poles(P2);
548
549     Standard_Integer NbUKnots = CC1->NbKnots();
550     Standard_Integer NbVKnots = CC2->NbKnots();
551     TColStd_Array1OfReal UKnots(1,NbUKnots);
552     TColStd_Array1OfReal VKnots(1,NbVKnots);
553     TColStd_Array1OfInteger UMults(1,NbUKnots);
554     TColStd_Array1OfInteger VMults(1,NbVKnots);
555     CC1->Knots(UKnots);
556     CC1->Multiplicities(UMults);
557     CC2->Knots(VKnots);
558     CC2->Multiplicities(VMults);
559
560     TColStd_Array1OfReal W1(1,NbUPoles);
561     TColStd_Array1OfReal W2(1,NbVPoles);
562     W1.Init(1.);
563     W2.Init(1.);
564
565     GeomFill_Filling Caro;
566     if ( isRat) {
567       if (CC1->IsRational()) {
568         CC1->Weights(W1);
569       }
570       if (CC2->IsRational()) {
571         CC2->Weights(W2);
572       }
573       Caro = GeomFill_Curved( P1, P2, W1, W2);
574     }
575     else {
576       Caro = GeomFill_Curved( P1, P2);
577     }
578
579     NbUPoles = Caro.NbUPoles();
580     NbVPoles = Caro.NbVPoles();
581     TColgp_Array2OfPnt Poles(1,NbUPoles,1,NbVPoles);
582     
583     Caro.Poles(Poles);
584     
585     if (Caro.isRational()) {
586       TColStd_Array2OfReal Weights(1,NbUPoles, 1,NbVPoles);
587       Caro.Weights(Weights);
588       mySurface = new Geom_BSplineSurface(Poles         , Weights,
589                                           UKnots        , VKnots,
590                                           UMults        , VMults,
591                                           Deg1          , Deg2,
592                                           Standard_False, Standard_False);
593     }
594     else {
595       mySurface = new Geom_BSplineSurface(Poles         ,
596                                           UKnots        , VKnots,
597                                           UMults        , VMults,
598                                           Deg1          , Deg2,
599                                           Standard_False, Standard_False);
600     }
601   }
602 }
603
604