0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / GeomFill / GeomFill_Sweep.cxx
1 // Created on: 1997-11-21
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1997-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 //  Modified by skv - Fri Feb  6 11:44:48 2004 OCC5073
18
19 #include <GeomFill_Sweep.ixx>
20 #include <GeomFill_SweepFunction.hxx>
21 #include <GeomFill_LocFunction.hxx>
22
23 #include <Standard_ErrorHandler.hxx>
24
25 #include <gp_Pnt2d.hxx>
26 #include <gp_Dir2d.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Dir.hxx>
29 #include <gp_Lin.hxx>
30 #include <gp_Circ.hxx>
31 #include <gp_GTrsf.hxx>
32 #include <gp_Mat.hxx>
33 #include <gp_Ax2.hxx>
34 #include <gp_Sphere.hxx>
35
36 #include <TColgp_Array1OfPnt.hxx>
37 #include <TColgp_Array2OfPnt.hxx>
38 #include <TColgp_HArray2OfPnt.hxx>
39 //#include <GeomLib_Array1OfMat.hxx>
40 #include <TColStd_Array1OfInteger.hxx>
41 #include <TColStd_Array1OfReal.hxx>
42 #include <TColStd_Array2OfReal.hxx>
43
44 #include <GeomAbs_CurveType.hxx>
45 #include <GeomAdaptor_Curve.hxx>
46 #include <GeomLib.hxx>
47
48 #include <Geom2d_Line.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_TrimmedCurve.hxx>
51
52 #include <Geom_Circle.hxx>
53 #include <Geom_Line.hxx>
54 #include <Geom_BSplineSurface.hxx>
55 #include <Geom_Plane.hxx>
56 #include <Geom_SurfaceOfLinearExtrusion.hxx>
57 #include <Geom_CylindricalSurface.hxx>
58 #include <Geom_ConicalSurface.hxx>
59 #include <Geom_ToroidalSurface.hxx>
60 #include <Geom_SphericalSurface.hxx>
61 #include <Geom_SurfaceOfRevolution.hxx>
62 #include <Geom_RectangularTrimmedSurface.hxx>
63 #include <Geom_TrimmedCurve.hxx>
64
65 #include <Approx_SweepApproximation.hxx>
66 #include <AdvApprox_PrefAndRec.hxx>
67 #include <AdvApprox_ApproxAFunction.hxx>
68 #include <GeomConvert_ApproxSurface.hxx>
69
70 #include <Precision.hxx>
71 #include <ElCLib.hxx>
72 #include <ElSLib.hxx>
73
74 //=======================================================================
75 //class : GeomFill_Sweep_Eval
76 //purpose: The evaluator for curve approximation
77 //=======================================================================
78
79 class GeomFill_Sweep_Eval : public AdvApprox_EvaluatorFunction
80 {
81  public:
82   GeomFill_Sweep_Eval (GeomFill_LocFunction& theTool)
83     : theAncore(theTool) {}
84   
85   virtual void Evaluate (Standard_Integer *Dimension,
86                          Standard_Real     StartEnd[2],
87                          Standard_Real    *Parameter,
88                          Standard_Integer *DerivativeRequest,
89                          Standard_Real    *Result, // [Dimension]
90                          Standard_Integer *ErrorCode);
91   
92  private:
93   GeomFill_LocFunction& theAncore;
94 };
95
96 void GeomFill_Sweep_Eval::Evaluate (Standard_Integer *,/*Dimension*/
97                                     Standard_Real     StartEnd[2],
98                                     Standard_Real    *Parameter,
99                                     Standard_Integer *DerivativeRequest,
100                                     Standard_Real    *Result,// [Dimension]
101                                     Standard_Integer *ErrorCode)
102 {
103   theAncore.DN (*Parameter,
104                 StartEnd[0],
105                 StartEnd[1],
106                 *DerivativeRequest, 
107                 Result[0],
108                 ErrorCode[0]);
109 }
110
111 //===============================================================
112 // Function : Create
113 // Purpose :
114 //===============================================================
115 GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
116                                const Standard_Boolean WithKpart)
117 {
118   done = Standard_False;
119
120   myLoc =  Location;
121   myKPart =  WithKpart;
122   SetTolerance(1.e-4);
123   myForceApproxC1 = Standard_False;
124
125   myLoc->GetDomain(First, Last);
126   SFirst = SLast = 30.081996;
127   SError = RealLast();
128 }
129
130 //===============================================================
131 // Function : SetDomain
132 // Purpose :
133 //===============================================================
134  void GeomFill_Sweep::SetDomain(const Standard_Real LocFirst,
135                                 const Standard_Real LocLast,
136                                 const Standard_Real SectionFirst,
137                                 const Standard_Real SectionLast) 
138 {
139   First = LocFirst;
140   Last =  LocLast;
141   SFirst = SectionFirst;
142   SLast = SectionLast;
143 }
144
145 //===============================================================
146 // Function : SetTolerance
147 // Purpose :
148 //===============================================================
149  void GeomFill_Sweep::SetTolerance(const Standard_Real Tolerance3d,
150                                    const Standard_Real BoundTolerance,
151                                    const Standard_Real Tolerance2d,
152                                    const Standard_Real ToleranceAngular) 
153 {
154   Tol3d = Tolerance3d;
155   BoundTol = BoundTolerance;
156   Tol2d =Tolerance2d;
157   TolAngular = ToleranceAngular;
158 }
159
160 //=======================================================================
161 //Function : SetForceApproxC1
162 //Purpose  : Set the flag that indicates attempt to approximate
163 //           a C1-continuous surface if a swept surface proved
164 //           to be C0.
165 //=======================================================================
166  void GeomFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
167 {
168   myForceApproxC1 = ForceApproxC1;
169 }
170
171
172 //===============================================================
173 // Function : ExchangeUV
174 // Purpose :
175 //===============================================================
176  Standard_Boolean GeomFill_Sweep::ExchangeUV() const
177 {
178   return myExchUV;
179 }
180
181 //===============================================================
182 // Function : UReversed
183 // Purpose :
184 //===============================================================
185  Standard_Boolean GeomFill_Sweep::UReversed() const
186 {
187   return isUReversed;
188 }
189
190 //===============================================================
191 // Function : VReversed
192 // Purpose :
193 //===============================================================
194  Standard_Boolean GeomFill_Sweep::VReversed() const
195 {
196   return isVReversed;
197 }
198
199 //===============================================================
200 // Function : Build
201 // Purpose :
202 //===============================================================
203  void GeomFill_Sweep::Build(const Handle(GeomFill_SectionLaw)& Section,        
204                             const GeomFill_ApproxStyle Methode,
205                             const GeomAbs_Shape Continuity,
206                             const Standard_Integer Degmax,
207                             const Standard_Integer Segmax) 
208 {
209   // Inits
210   done = Standard_False;
211   myExchUV = Standard_False;
212   isUReversed = isVReversed = Standard_False;
213   mySec =  Section;
214
215   if ((SFirst == SLast) &&  (SLast == 30.081996)) {
216     mySec->GetDomain(SFirst, SLast);
217   }
218    
219   Standard_Boolean isKPart = Standard_False, 
220                    isProduct  = Standard_False;
221  
222  // Traitement des KPart
223  if (myKPart)  isKPart = BuildKPart();
224  
225  // Traitement des produits Formelles
226  if ((!isKPart) && (Methode == GeomFill_Location)) {
227      Handle(Geom_BSplineSurface) BS;
228      BS = mySec->BSplineSurface();
229      if (! BS.IsNull()) {
230       // Approx de la loi
231 //    isProduct = BuildProduct(Continuity, Degmax, Segmax);
232      }
233    }
234
235  if (isKPart || isProduct) {
236  // Approx du 2d
237    done =  Build2d(Continuity, Degmax, Segmax);
238  }
239   else {
240  // Approx globale
241     done =  BuildAll(Continuity, Degmax, Segmax);
242   }
243 }
244
245 //===============================================================
246 // Function ::Build2d
247 // Purpose :A venir...
248 //===============================================================
249 // Standard_Boolean GeomFill_Sweep::Build2d(const GeomAbs_Shape Continuity,
250  Standard_Boolean GeomFill_Sweep::Build2d(const GeomAbs_Shape ,
251 //                                        const Standard_Integer Degmax,
252                                           const Standard_Integer ,
253 //                                        const Standard_Integer Segmax) 
254                                           const Standard_Integer ) 
255 {
256   Standard_Boolean Ok = Standard_False;
257   if (myLoc->Nb2dCurves() == 0) {
258     Ok = Standard_True;
259   }
260   return Ok;
261 }
262
263 //===============================================================
264 // Function : BuildAll
265 // Purpose :
266 //===============================================================
267  Standard_Boolean GeomFill_Sweep::BuildAll(const GeomAbs_Shape Continuity,
268                                            const Standard_Integer Degmax,
269                                            const Standard_Integer Segmax) 
270 {
271   Standard_Boolean Ok = Standard_False;
272
273   Handle(GeomFill_SweepFunction) Func 
274     = new (GeomFill_SweepFunction) (mySec, myLoc, First, SFirst,
275                                    (SLast-SFirst)/(Last-First) );
276   Approx_SweepApproximation Approx( Func );
277
278   Approx.Perform(First,  Last,
279                  Tol3d,  BoundTol,  Tol2d,  TolAngular,
280                  Continuity, Degmax,  Segmax);
281
282   if (Approx.IsDone()) {
283     Ok = Standard_True;
284
285 #ifdef OCCT_DEBUG
286     Approx.Dump(cout);
287 #endif
288     
289     // La surface
290     Standard_Integer UDegree,VDegree,NbUPoles,
291                      NbVPoles,NbUKnots,NbVKnots;
292     Approx.SurfShape(UDegree,VDegree,NbUPoles,
293                      NbVPoles,NbUKnots,NbVKnots);
294
295     TColgp_Array2OfPnt Poles(1,NbUPoles, 1,NbVPoles);
296     TColStd_Array2OfReal Weights(1,NbUPoles, 1,NbVPoles);
297     TColStd_Array1OfReal UKnots(1, NbUKnots),VKnots(1, NbVKnots); 
298     TColStd_Array1OfInteger UMults(1, NbUKnots), VMults(1, NbVKnots);
299
300     Approx.Surface(Poles, Weights,
301                    UKnots,VKnots,
302                    UMults,VMults);
303
304     mySurface = new (Geom_BSplineSurface)
305                    (Poles, Weights,
306                     UKnots,VKnots,
307                     UMults,VMults,
308                     Approx.UDegree(),  Approx.VDegree(),
309                     mySec->IsUPeriodic());
310     SError = Approx. MaxErrorOnSurf();
311
312     if (myForceApproxC1 && !mySurface->IsCNv(1))
313     {
314       Standard_Real theTol = 1.e-4;
315       GeomAbs_Shape theUCont = GeomAbs_C1, theVCont = GeomAbs_C1;
316       Standard_Integer degU = 14, degV = 14;
317       Standard_Integer nmax = 16;
318       Standard_Integer thePrec = 1;  
319       
320       GeomConvert_ApproxSurface ConvertApprox(mySurface,theTol,theUCont,theVCont,
321                                               degU,degV,nmax,thePrec);
322       if (ConvertApprox.HasResult())
323       {
324         mySurface = ConvertApprox.Surface();
325         myCurve2d = new  (TColGeom2d_HArray1OfCurve) (1, 2);
326         CError =  new (TColStd_HArray2OfReal) (1,2, 1,2);
327
328         Handle(Geom_BSplineSurface) BSplSurf (Handle(Geom_BSplineSurface)::DownCast(mySurface));
329         
330         gp_Dir2d D(0., 1.);
331         gp_Pnt2d P(BSplSurf->UKnot(1), 0);
332         Handle(Geom2d_Line) LC1 = new (Geom2d_Line) (P, D);
333         Handle(Geom2d_TrimmedCurve) TC1 =
334           new (Geom2d_TrimmedCurve) (LC1, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
335         
336         myCurve2d->SetValue(1, TC1);
337         CError->SetValue(1, 1, 0.);
338         CError->SetValue(2, 1, 0.);
339  
340         P.SetCoord(BSplSurf->UKnot(BSplSurf->NbUKnots()), 0);
341         Handle(Geom2d_Line) LC2 = new (Geom2d_Line) (P, D);
342         Handle(Geom2d_TrimmedCurve) TC2 = 
343           new (Geom2d_TrimmedCurve) (LC2, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
344         
345         myCurve2d->SetValue(myCurve2d->Length(), TC2);
346         CError->SetValue(1, myCurve2d->Length(), 0.);
347         CError->SetValue(2, myCurve2d->Length(), 0.);
348         
349         SError = theTol;
350       }
351     } //if (!mySurface->IsCNv(1))
352     
353     // Les Courbes 2d
354     if (myCurve2d.IsNull())
355     {
356       myCurve2d = new  (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
357       CError =  new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
358       Standard_Integer kk,ii, ifin = 1, ideb;
359       
360       if (myLoc->HasFirstRestriction()) {
361         ideb = 1;
362       }
363       else {
364         ideb = 2;
365       }
366       ifin += myLoc->TraceNumber();
367       if (myLoc->HasLastRestriction()) ifin++;
368       
369       for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
370         Handle(Geom2d_BSplineCurve) C 
371           = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
372                                        Approx.Curves2dKnots(),
373                                        Approx.Curves2dMults(),
374                                        Approx.Curves2dDegree());
375         myCurve2d->SetValue(ii, C);
376         CError->SetValue(1, ii,  Approx.Max2dError(kk));
377         CError->SetValue(2, ii,  Approx.Max2dError(kk));
378       }
379       
380       // Si les courbes de restriction, ne sont pas calcules, on prend
381       // les iso Bords.
382       if (! myLoc->HasFirstRestriction()) {
383         gp_Dir2d D(0., 1.);
384         gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
385         Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
386         Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
387           (LC, First, Last);
388         
389         myCurve2d->SetValue(1, TC);
390         CError->SetValue(1, 1, 0.);
391         CError->SetValue(2, 1, 0.);
392       }
393       
394       if (! myLoc->HasLastRestriction()) {
395         gp_Dir2d D(0., 1.);
396         gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
397         Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
398         Handle(Geom2d_TrimmedCurve) TC = 
399           new (Geom2d_TrimmedCurve) (LC, First, Last);
400         myCurve2d->SetValue(myCurve2d->Length(), TC);
401         CError->SetValue(1, myCurve2d->Length(), 0.);
402         CError->SetValue(2, myCurve2d->Length(), 0.);
403       }
404     } //if (myCurve2d.IsNull())
405   } 
406   return Ok;
407 }
408
409 //===============================================================
410 // Function : BuildProduct
411 // Purpose : A venir...
412 //===============================================================
413  Standard_Boolean GeomFill_Sweep::BuildProduct(const GeomAbs_Shape Continuity,
414                                           const Standard_Integer Degmax,
415                                           const Standard_Integer Segmax) 
416 {
417   Standard_Boolean Ok = Standard_False;
418
419   Handle(Geom_BSplineSurface) BSurf;
420   BSurf = Handle(Geom_BSplineSurface)::DownCast(
421            mySec->BSplineSurface()->Copy());
422   if (BSurf.IsNull()) return Ok; // Ce mode de construction est impossible  
423
424
425   Standard_Integer NbIntervalC2,  NbIntervalC3;
426   GeomFill_LocFunction Func(myLoc);
427
428   NbIntervalC2 = myLoc->NbIntervals(GeomAbs_C2);
429   NbIntervalC3 = myLoc->NbIntervals(GeomAbs_C3);
430   TColStd_Array1OfReal Param_de_decoupeC2 (1, NbIntervalC2+1);
431   myLoc->Intervals(Param_de_decoupeC2, GeomAbs_C2);
432   TColStd_Array1OfReal Param_de_decoupeC3 (1, NbIntervalC3+1);
433   myLoc->Intervals(Param_de_decoupeC3, GeomAbs_C3);
434
435
436   AdvApprox_PrefAndRec Preferentiel(Param_de_decoupeC2,
437                                      Param_de_decoupeC3);
438    
439   Handle(TColStd_HArray1OfReal) ThreeDTol = new (TColStd_HArray1OfReal) (1,4);
440   ThreeDTol->Init(Tol3d); // A Affiner...
441
442   GeomFill_Sweep_Eval eval (Func);
443   AdvApprox_ApproxAFunction Approx(0, 0, 4,
444                                    ThreeDTol,
445                                    ThreeDTol,
446                                    ThreeDTol,
447                                    First,
448                                    Last, 
449                                    Continuity,
450                                    Degmax,
451                                    Segmax, 
452                                    eval,
453                                    Preferentiel);
454 #ifdef OCCT_DEBUG
455   Approx.Dump(cout);
456 #endif
457
458   Ok = Approx.HasResult();
459   if (Ok) {
460 /*    TColgp_Array1OfMat TM(1, nbpoles);
461     Handle(TColgp_HArray2OfPnt) ResPoles;
462     ResPoles = Approx.Poles();
463
464     // Produit Tensoriel
465     for (ii=1; ii<=nbpoles; ii++) {
466       TM(ii).SetCols(ResPoles->Value(ii,2).XYZ(), 
467                      ResPoles->Value(ii,3).XYZ(),  
468                      ResPoles->Value(ii,4).XYZ());
469       TR(ii) = ResPoles->Value(ii,1);
470     }
471     GeomLib::TensorialProduct(BSurf, TM, TR,
472                               Approx.Knots()->Array1(), 
473                               Approx.Multiplicities()->Array1());
474
475     // Somme
476     TColgp_Array1OfPnt TPoles(1, nbpoles);
477     for (ii=1; ii<=nbpoles; ii++) {
478       TPoles(ii) = ResPoles->Value(ii,1);
479     }
480     Handle(Geom_BsplineCurve) BS = 
481       new (Geom_BsplineCurve) (Poles, 
482                                Approx.Knots()->Array1(), 
483                                Approx.Multiplicities()->Array1(),
484                                Approx.Degree());
485     for (ii=1; ii<=BSurf->NbVKnots(); ii++)
486       BS->InsertKnot( BSurf->VKnot(ii), 
487                      BSurf->VMultiplicity(ii), 
488                      Precision::Confusion());
489    TColgp_Array2OfPnt SurfPoles (1, BSurf->NbUPoles());
490    for (ii=1; 
491         
492 */
493     mySurface = BSurf;
494   }
495   return Ok;
496 }
497
498 //  Modified by skv - Thu Feb  5 18:05:03 2004 OCC5073 Begin
499 //  Conditions:
500 //     * theSec should be constant
501 //     * the type of section should be a line
502 //     * theLoc should represent a translation.
503
504 static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw) &theLoc,
505                              const Handle(GeomFill_SectionLaw)  &theSec,
506                              const Standard_Real                 theTol)
507 {
508   // Get the first and last transformations of the location
509   Standard_Real aFirst;
510   Standard_Real aLast;
511   gp_Vec        VBegin;
512   gp_Vec        VEnd;
513   gp_Mat        M;
514   gp_GTrsf      GTfBegin;
515   gp_Trsf       TfBegin;
516   gp_GTrsf      GTfEnd;
517   gp_Trsf       TfEnd;
518
519   theLoc->GetDomain(aFirst, aLast);
520
521 // Get the first transformation
522   theLoc->D0(aFirst, M, VBegin);
523
524   GTfBegin.SetVectorialPart(M);
525   GTfBegin.SetTranslationPart(VBegin.XYZ());
526
527   TfBegin.SetValues(GTfBegin(1,1), GTfBegin(1,2), GTfBegin(1,3), GTfBegin(1,4),
528                     GTfBegin(2,1), GTfBegin(2,2), GTfBegin(2,3), GTfBegin(2,4),
529                     GTfBegin(3,1), GTfBegin(3,2), GTfBegin(3,3), GTfBegin(3,4));
530
531 // Get the last transformation
532   theLoc->D0(aLast, M, VEnd);
533
534   GTfEnd.SetVectorialPart(M);
535   GTfEnd.SetTranslationPart(VEnd.XYZ());
536
537   TfEnd.SetValues(GTfEnd(1,1), GTfEnd(1,2), GTfEnd(1,3), GTfEnd(1,4),
538                   GTfEnd(2,1), GTfEnd(2,2), GTfEnd(2,3), GTfEnd(2,4),
539                   GTfEnd(3,1), GTfEnd(3,2), GTfEnd(3,3), GTfEnd(3,4));
540
541   Handle(Geom_Surface) aSurf = theSec->BSplineSurface();
542   Standard_Real Umin;
543   Standard_Real Umax;
544   Standard_Real Vmin;
545   Standard_Real Vmax;
546
547   aSurf->Bounds(Umin, Umax, Vmin, Vmax);
548
549   // Get and transform the first section
550   Handle(Geom_Curve) FirstSection = theSec->ConstantSection();
551   GeomAdaptor_Curve  ACFirst(FirstSection);
552
553   Standard_Real UFirst = ACFirst.FirstParameter();
554   gp_Lin        L      = ACFirst.Line();
555
556   L.Transform(TfBegin);
557
558   // Get and transform the last section
559   Handle(Geom_Curve) aLastSection    = aSurf->VIso(Vmax);
560   Standard_Real      aFirstParameter = aLastSection->FirstParameter();
561   gp_Pnt             aPntLastSec     = aLastSection->Value(aFirstParameter);
562
563   aPntLastSec.Transform(TfEnd);
564
565   gp_Pnt        aPntFirstSec = ElCLib::Value( UFirst, L );
566   gp_Vec        aVecSec( aPntFirstSec, aPntLastSec );
567   gp_Vec        aVecSpine = VEnd - VBegin;
568
569   Standard_Boolean isParallel = aVecSec.IsParallel(aVecSpine, theTol);
570
571   return isParallel;
572 }
573 //  Modified by skv - Thu Feb  5 18:05:01 2004 OCC5073 End
574
575 //===============================================================
576 // Function : BuildKPart
577 // Purpose :
578 //===============================================================
579  Standard_Boolean GeomFill_Sweep::BuildKPart() 
580 {
581   Standard_Boolean Ok = Standard_False;
582   Standard_Boolean isUPeriodic = Standard_False;
583   Standard_Boolean isVPeriodic = Standard_False;
584   Standard_Boolean IsTrsf = Standard_True;
585
586   isUPeriodic = mySec->IsUPeriodic();
587   Handle(Geom_Surface) S;
588   GeomAbs_CurveType SectionType;
589   gp_Vec V;
590   gp_Mat M;
591   Standard_Real levier, error = 0 ;
592   Standard_Real UFirst=0, VFirst=First, ULast=0, VLast=Last;
593   Standard_Real Tol = Min (Tol3d, BoundTol);
594
595   // (1) Trajectoire Rectilignes -------------------------
596   if (myLoc->IsTranslation(error)) {
597     // Donne de la translation
598     gp_Vec DP, DS;
599     myLoc->D0(1, M, DS);
600     myLoc->D0(0, M, V);
601     DP = DS - V;
602     DP.Normalize();
603     gp_GTrsf Tf;
604     gp_Trsf Tf2;
605     Tf.SetVectorialPart(M);
606     Tf.SetTranslationPart(V.XYZ());
607     try { // Pas joli mais il n'y as pas d'autre moyens de tester SetValues
608       OCC_CATCH_SIGNALS
609       Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
610                     Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
611                     Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4));
612     }
613     catch (Standard_ConstructionError) {
614       IsTrsf = Standard_False;
615     }
616     if (!IsTrsf) {
617       return Standard_False;
618     }
619
620     // (1.1) Cas Extrusion
621     if (mySec->IsConstant(error)) {
622       Handle(Geom_Curve) Section;
623       Section = mySec->ConstantSection();
624       GeomAdaptor_Curve AC(Section);
625       SectionType = AC.GetType();
626       UFirst = AC.FirstParameter();
627       ULast  = AC.LastParameter();
628   // (1.1.a) Cas Plan
629       if ( (SectionType == GeomAbs_Line) && IsTrsf) {
630 //  Modified by skv - Thu Feb  5 11:39:06 2004 OCC5073 Begin
631         if (!IsSweepParallelSpine(myLoc, mySec, Tol))
632           return Standard_False;
633 //  Modified by skv - Thu Feb  5 11:39:08 2004 OCC5073 End
634         gp_Lin L = AC.Line();
635         L.Transform(Tf2);
636         DS.SetXYZ(L.Position().Direction().XYZ());
637         DS.Normalize();
638         levier = Abs(DS.Dot(DP));
639         SError = error + levier * Abs(Last-First);
640         if (SError <= Tol) {
641           Ok = Standard_True;
642           gp_Ax2 AxisOfPlane (L.Location(), DS^DP, DS);
643           S = new (Geom_Plane) (AxisOfPlane);
644         }
645         else SError = 0.;
646       }
647     
648   // (1.1.b) Cas Cylindrique
649       if ( (SectionType == GeomAbs_Circle) && IsTrsf) {
650         const Standard_Real TolProd = 1.e-6;
651         
652         gp_Circ C = AC.Circle();
653         C.Transform(Tf2);
654         
655         DS.SetXYZ (C.Position().Direction().XYZ());
656         DS.Normalize();
657         levier = Abs(DS.CrossMagnitude(DP)) * C.Radius();
658         SError = levier * Abs(Last - First);
659         if (SError <= TolProd) {
660           Ok = Standard_True;
661           gp_Ax3 axe (C.Location(), DP, C.Position().XDirection());
662           S = new (Geom_CylindricalSurface) 
663             (axe, C.Radius());
664             if (C.Position().Direction().
665                 IsOpposite(axe.Direction(), 0.1) ) {
666               Standard_Real f, l;
667               // L'orientation parametrique est inversee
668               l = 2*M_PI - UFirst;
669               f = 2*M_PI - ULast;
670               UFirst = f;
671               ULast  = l;
672               isUReversed = Standard_True;
673             }
674         }
675         else SError = 0.;
676       }
677
678   // (1.1.c) C'est bien une extrusion
679       if (!Ok) {
680         if (IsTrsf) {
681           Section->Transform(Tf2);
682           S = new (Geom_SurfaceOfLinearExtrusion)
683             (Section, DP);
684           SError = 0.;
685           Ok = Standard_True;
686         }
687         else { // extrusion sur BSpline
688           
689         }
690       }
691     }
692   
693   // (1.2) Cas conique
694    else if (mySec->IsConicalLaw(error)) {
695
696      gp_Pnt P1, P2, Centre0, Centre1, Centre2;
697      gp_Vec dsection;
698      Handle(Geom_Curve) Section;
699      GeomAdaptor_Curve AC;
700      gp_Circ C;
701      Standard_Real R1, R2;
702
703
704      Section = mySec->CirclSection(SLast);
705      Section->Transform(Tf2);
706      Section->Translate(Last*DP);
707      AC.Load(Section);
708      C = AC.Circle();
709      Centre2 = C.Location();
710      AC.D1(0, P2, dsection);
711      R2 = C.Radius();
712     
713      Section = mySec->CirclSection(SFirst);
714      Section->Transform(Tf2);
715      Section->Translate(First*DP);
716      AC.Load(Section);
717      C =  AC.Circle();
718      Centre1 = C.Location();
719      P1 = AC.Value(0);
720      R1 = C.Radius();
721
722      Section = mySec->CirclSection(SFirst - First*(SLast-SFirst)/(Last-First));
723      Section->Transform(Tf2);
724      AC.Load(Section);
725      C =  AC.Circle();     
726      Centre0 = C.Location();
727      
728      Standard_Real Angle;
729      gp_Vec  N(Centre1, P1);
730      if (N.Magnitude() < 1.e-9) {
731        gp_Vec Bis(Centre2, P2);
732        N = Bis;
733      }
734      gp_Vec  L(P1, P2), Dir(Centre1,Centre2);
735
736      Angle = L.Angle(Dir);
737      if ((Angle > 0.01) && (Angle < M_PI/2-0.01)) {
738        if (R2<R1) Angle = -Angle;
739        SError = error;
740        gp_Ax3 Axis(Centre0, Dir, N);
741        S = new (Geom_ConicalSurface) 
742          (Axis, Angle, C.Radius());
743        // Calcul du glissement parametrique
744        VFirst = First / Cos(Angle);
745        VLast  = Last  / Cos(Angle);
746
747        // Bornes en U
748        UFirst = AC.FirstParameter();
749        ULast  = AC.LastParameter();
750        gp_Vec diso;
751        gp_Pnt pbis;
752        S->VIso(VLast)->D1(0, pbis, diso);
753        if (diso.Magnitude()>1.e-9 && dsection.Magnitude()>1.e-9)
754          isUReversed = diso.IsOpposite(dsection, 0.1);
755        if (isUReversed ) {
756          Standard_Real f, l;
757          // L'orientation parametrique est inversee
758          l = 2*M_PI - UFirst;
759          f = 2*M_PI - ULast;
760          UFirst = f;
761          ULast  = l;
762        } 
763
764        // C'est un cone
765        Ok = Standard_True;
766      }
767    }
768   }
769
770   // (2) Trajectoire Circulaire
771   if (myLoc->IsRotation(error)) {
772     if (mySec->IsConstant(error)) {
773       // La trajectoire
774       gp_Pnt Centre;
775       isVPeriodic = (Abs(Last-First -2*M_PI) < 1.e-15);
776       Standard_Real RotRadius;
777       gp_Vec DP, DS, DN;
778       myLoc->D0(0.1, M, DS);
779       myLoc->D0(0, M, V);
780       myLoc->Rotation(Centre);
781
782       DP = DS - V;
783       DS.SetXYZ(V.XYZ() - Centre.XYZ());   
784       RotRadius = DS.Magnitude();
785       if (RotRadius > 1.e-15) DS.Normalize();
786       else return Standard_False; // Pas de KPart, rotation degeneree
787       DN = DS ^ DP;
788       DN.Normalize();
789       DP = DN ^ DS;
790       DP.Normalize();
791
792       gp_GTrsf Tf;
793       gp_Trsf Tf2;
794       Tf.SetVectorialPart(M);
795       Tf.SetTranslationPart(V.XYZ());
796 //      try { // Pas joli mais il n'y as pas d'autre moyens de tester SetValues
797 //        OCC_CATCH_SIGNALS
798         Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
799                       Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
800                       Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4));
801 //      }
802 //      catch (Standard_ConstructionError) {
803 //      IsTrsf = Standard_False;
804 //      }
805       // La section
806       Handle(Geom_Curve) Section;
807       Section = mySec->ConstantSection();
808       GeomAdaptor_Curve AC(Section);
809       SectionType = AC.GetType();
810       UFirst = AC.FirstParameter();
811       ULast  = AC.LastParameter();
812
813       // (2.1) Tore/Sphere ?
814       if ((SectionType == GeomAbs_Circle) && IsTrsf) {
815         gp_Circ C = AC.Circle();
816         Standard_Real Radius;
817         Standard_Boolean IsGoodSide = Standard_True;;
818         C.Transform(Tf2);
819         gp_Vec DC;
820         // On calcul le centre eventuel
821         DC.SetXYZ(C.Location().XYZ() - Centre.XYZ());
822         Centre.ChangeCoord() += (DC.Dot(DN))*DN.XYZ();
823         DC.SetXYZ(C.Location().XYZ() - Centre.XYZ());
824         Radius = DC.Magnitude(); //grand Rayon du tore
825         if ((Radius > Tol) && (DC.Dot(DS) < 0)) IsGoodSide = Standard_False;
826         if (Radius < Tol/100) DC = DS; // Pour definir le tore
827
828         // On verifie d'abord que le plan de la section est // a 
829         // l'axe de rotation
830         gp_Vec NC;
831         NC.SetXYZ (C.Position().Direction().XYZ());
832         NC.Normalize();
833         error =  Abs(NC.Dot(DN));
834         // Puis on evalue l'erreur commise sur la section, 
835         // en pivotant son plan ( pour contenir l'axe de rotation)
836         error += Abs(NC.Dot(DS));
837         error *= C.Radius();
838         if (error <= Tol) {
839           SError = error;
840           error += Radius + Abs(RotRadius - C.Radius())/2;
841           if (error <= Tol) {
842             // (2.1.a) Sphere
843             Standard_Real f = UFirst , l =  ULast;
844             SError = error;
845             Centre.BaryCenter(1.0, C.Location(), 1.0); 
846             gp_Ax3 AxisOfSphere(Centre, DN, DS);
847             gp_Sphere theSphere( AxisOfSphere, (RotRadius + C.Radius())/2 );
848             S = new Geom_SphericalSurface(theSphere);
849             // Pour les spheres on ne peut pas controler le parametre
850             // V (donc U car  myExchUV = Standard_True)
851             // Il faut donc modifier UFirst, ULast...
852             Standard_Real fpar = AC.FirstParameter();
853             Standard_Real lpar = AC.LastParameter();
854             Handle(Geom_Curve) theSection = new Geom_TrimmedCurve(Section, fpar, lpar);
855             theSection->Transform(Tf2);
856             gp_Pnt FirstPoint = theSection->Value(theSection->FirstParameter());
857             gp_Pnt LastPoint  = theSection->Value(theSection->LastParameter());
858             Standard_Real UfirstOnSec, VfirstOnSec, UlastOnSec, VlastOnSec;
859             ElSLib::Parameters(theSphere, FirstPoint, UfirstOnSec, VfirstOnSec);
860             ElSLib::Parameters(theSphere, LastPoint, UlastOnSec, VlastOnSec);
861             if (VfirstOnSec < VlastOnSec)
862             {
863               f = VfirstOnSec;
864               l = VlastOnSec;
865             }
866             else
867             {
868               // L'orientation parametrique est inversee
869               f = VlastOnSec;
870               l = VfirstOnSec;
871               isUReversed = Standard_True;
872             }
873
874             if ( (f >= -M_PI/2) && (l <= M_PI/2)) {
875               Ok = Standard_True;
876               myExchUV = Standard_True;
877               UFirst = f;
878               ULast  = l;
879             }
880             else { // On restaure ce qu'il faut
881               isUReversed = Standard_False;
882             }
883           }
884           else if (IsGoodSide) {         
885             // (2.1.b) Tore
886             gp_Ax3 AxisOfTore(Centre, DN, DC);
887             S = new (Geom_ToroidalSurface) (AxisOfTore, 
888                    Radius , C.Radius());
889         
890             // Pour les tores on ne peut pas controler le parametre
891             // V (donc U car  myExchUV = Standard_True)
892             // Il faut donc modifier UFirst, ULast...
893             Handle(Geom_Circle) Iso;
894             Iso =  Handle(Geom_Circle)::DownCast(S->UIso(0.));
895             gp_Ax2 axeiso;
896             axeiso = Iso->Circ().Position();
897               
898             if (C.Position().Direction().
899                 IsOpposite(axeiso.Direction(), 0.1) ) {
900               Standard_Real f, l;
901               // L'orientation parametrique est inversee
902               l = 2*M_PI - UFirst;
903               f = 2*M_PI - ULast;
904               UFirst = f;
905               ULast  = l;
906               isUReversed = Standard_True;
907             }
908             // On calcul le "glissement" parametrique.
909             Standard_Real rot; 
910             rot = C.Position().XDirection().AngleWithRef
911               (axeiso.XDirection(), axeiso.Direction());
912             UFirst -= rot;
913             ULast  -= rot;
914
915             myExchUV = Standard_True;
916             // Attention l'arete de couture dans le cas periodique 
917             // n'est peut etre pas a la bonne place...
918             if (isUPeriodic && Abs(UFirst)>Precision::PConfusion()) 
919               isUPeriodic = Standard_False; //Pour trimmer la surface...
920             Ok = Standard_True;
921           }
922         }
923         else {
924           SError = 0.;
925         }
926       }
927       // (2.2) Cone / Cylindre
928       if ((SectionType == GeomAbs_Line) && IsTrsf)  {
929         gp_Lin L =  AC.Line();
930         L.Transform(Tf2);
931         gp_Vec DL;
932         DL.SetXYZ(L.Direction().XYZ());
933         levier = Max(Abs(AC.FirstParameter()), AC.LastParameter());
934         // si la line est ortogonale au cercle de rotation  
935         SError = error + levier * Abs(DL.Dot(DP));
936         if (SError <= Tol) {
937           Standard_Boolean reverse;
938           gp_Lin Dir(Centre, DN);
939           Standard_Real aux;
940           aux = DL.Dot(DN);
941           reverse = (aux < 0);  // On choisit ici le sens de parametrisation
942             
943           // Calcul du centre du vecteur supportant la "XDirection"
944           gp_Pnt CentreOfSurf;
945           gp_Vec O1O2(Centre, L.Location()), trans;
946           trans = DN;
947           trans *= DN.Dot(O1O2);
948           CentreOfSurf = Centre.Translated(trans);
949           DS.SetXYZ(L.Location().XYZ() - CentreOfSurf.XYZ());
950
951           error = SError;
952           error += (DL.XYZ()).CrossMagnitude(DN.XYZ())*levier;
953           if (error <= Tol) {
954             // (2.2.a) Cylindre
955             // si la line est orthogonale au plan de rotation
956             SError = error;
957             gp_Ax3 Axis(CentreOfSurf, Dir.Direction(), DS);
958             S = new (Geom_CylindricalSurface) 
959                     (Axis, L.Distance(CentreOfSurf));
960             Ok = Standard_True;
961             myExchUV = Standard_True;
962           }
963           else {
964             // On evalue l'angle du cone
965             Standard_Real Angle = Abs(Dir.Angle(L));
966             if (Angle > M_PI/2) Angle = M_PI -Angle;
967             if (reverse) Angle = -Angle;
968             aux = DS.Dot(DL);
969             if (aux < 0) {
970               Angle = - Angle;
971             }
972             if (Abs(Abs(Angle) - M_PI/2) > 0.01) {
973               // (2.2.b) Cone
974               // si les 2 droites ne sont pas orthogonales
975               Standard_Real Radius = CentreOfSurf.Distance(L.Location());
976               gp_Ax3 Axis(CentreOfSurf, Dir.Direction(), DS);
977               S = new (Geom_ConicalSurface) 
978                     (Axis, Angle, Radius);
979               myExchUV = Standard_True;
980               Ok = Standard_True;
981             }
982             else {
983               // On n'as pas conclue, on remet l'erreur a 0.
984               SError = 0.;
985             }
986           }
987           if (Ok && reverse) {
988             // On reverse le parametre
989             Standard_Real uf, ul;
990             Handle(Geom_Line) CL = new (Geom_Line)(L);
991             uf = CL->ReversedParameter(ULast);
992             ul = CL->ReversedParameter(UFirst);
993             UFirst = uf;
994             ULast = ul;
995             isUReversed = Standard_True;
996           }
997         }
998         else SError = 0.;
999       }
1000   
1001       // (2.3) Revolution
1002       if (!Ok) {
1003         if (IsTrsf) { 
1004           Section->Transform(Tf2);
1005           gp_Ax1 Axis (Centre, DN);
1006           S = new (Geom_SurfaceOfRevolution)
1007             (Section, Axis);
1008           myExchUV = Standard_True;
1009           SError = 0.;
1010           Ok = Standard_True;
1011         }
1012       }
1013     }
1014   }
1015
1016
1017   if (Ok) { // On trimme la surface
1018     if (myExchUV) {
1019       Standard_Boolean b;
1020       b = isUPeriodic; isUPeriodic = isVPeriodic;  isVPeriodic = b;
1021       Standard_Real r;
1022       r = UFirst; UFirst = VFirst; VFirst = r;
1023       r = ULast; ULast = VLast; VLast = r;
1024     }
1025
1026     if (!isUPeriodic && !isVPeriodic)
1027       mySurface = new (Geom_RectangularTrimmedSurface)
1028         (S, UFirst, ULast, VFirst, VLast);
1029     else if (isUPeriodic) {
1030       if (isVPeriodic) mySurface = S;
1031       else mySurface = new (Geom_RectangularTrimmedSurface)
1032         (S, VFirst, VLast, Standard_False);
1033     }
1034     else
1035       mySurface = new (Geom_RectangularTrimmedSurface)
1036         (S,UFirst, ULast, Standard_True);
1037
1038 #ifdef OCCT_DEBUG
1039   if (isUPeriodic && !mySurface->IsUPeriodic()) 
1040     cout<<"Pb de periodicite en U" << endl;
1041   if (isUPeriodic && !mySurface->IsUClosed())
1042     cout<<"Pb de fermeture en U" << endl;
1043   if (isVPeriodic && !mySurface->IsVPeriodic()) 
1044     cout << "Pb de periodicite en V" << endl;
1045   if (isVPeriodic && !mySurface->IsVClosed())
1046     cout<<"Pb de fermeture en V" << endl;
1047 #endif
1048   }
1049
1050
1051   return Ok;
1052 }
1053
1054 //===============================================================
1055 // Function : IsDone
1056 // Purpose :
1057 //===============================================================
1058  Standard_Boolean GeomFill_Sweep::IsDone() const
1059 {
1060   return done;
1061 }
1062
1063 //===============================================================
1064 // Function :ErrorOnSurface
1065 // Purpose :
1066 //===============================================================
1067  Standard_Real GeomFill_Sweep::ErrorOnSurface() const
1068 {
1069   return SError;
1070 }
1071
1072 //===============================================================
1073 // Function ::ErrorOnRestriction
1074 // Purpose :
1075 //===============================================================
1076  void GeomFill_Sweep::ErrorOnRestriction(const Standard_Boolean IsFirst,
1077                                          Standard_Real& UError,
1078                                          Standard_Real& VError) const
1079 {
1080   Standard_Integer ind;
1081   if (IsFirst) ind=1;
1082   else ind = myCurve2d->Length();
1083
1084   UError =  CError->Value(1, ind);
1085   VError =  CError->Value(2, ind);
1086 }
1087
1088 //===============================================================
1089 // Function :ErrorOnTrace
1090 // Purpose :
1091 //===============================================================
1092  void GeomFill_Sweep::ErrorOnTrace(const Standard_Integer IndexOfTrace,
1093                                    Standard_Real& UError,
1094                                    Standard_Real& VError) const
1095 {
1096   Standard_Integer ind = IndexOfTrace+1;
1097   if (IndexOfTrace > myLoc->TraceNumber())
1098     Standard_OutOfRange::Raise(" GeomFill_Sweep::ErrorOnTrace");
1099
1100   UError =  CError->Value(1, ind);
1101   VError =  CError->Value(2, ind);
1102 }
1103
1104 //===============================================================
1105 // Function :Surface
1106 // Purpose :
1107 //===============================================================
1108  Handle(Geom_Surface) GeomFill_Sweep::Surface() const
1109 {
1110   return mySurface;
1111 }
1112
1113 //===============================================================
1114 // Function ::Restriction
1115 // Purpose :
1116 //===============================================================
1117  Handle(Geom2d_Curve) GeomFill_Sweep::Restriction(const Standard_Boolean IsFirst) const
1118 {
1119   if (IsFirst)
1120     return  myCurve2d->Value(1);
1121   return  myCurve2d->Value(myCurve2d->Length());
1122  
1123 }
1124
1125 //===============================================================
1126 // Function :
1127 // Purpose :
1128 //===============================================================
1129  Standard_Integer GeomFill_Sweep::NumberOfTrace() const
1130 {
1131   return myLoc->TraceNumber();
1132 }
1133
1134 //===============================================================
1135 // Function : 
1136 // Purpose :
1137 //===============================================================
1138  Handle(Geom2d_Curve) 
1139      GeomFill_Sweep::Trace(const Standard_Integer IndexOfTrace) const
1140 {
1141   Standard_Integer ind = IndexOfTrace+1;
1142   if (IndexOfTrace > myLoc->TraceNumber())
1143     Standard_OutOfRange::Raise(" GeomFill_Sweep::Trace");
1144   return  myCurve2d->Value(ind);  
1145 }