0024738: BRepOffsetAPI_MakePipe algorithm fails on circular path and section (the...
[occt.git] / src / GeomFill / GeomFill_Sweep.cxx
CommitLineData
b311480e 1// Created on: 1997-11-21
2// Created by: Philippe MANGIN
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 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>
9ba2c30f 34#include <gp_Sphere.hxx>
7fd59977 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>
9ba2c30f 63#include <Geom_TrimmedCurve.hxx>
7fd59977 64
65#include <Approx_SweepApproximation.hxx>
66#include <AdvApprox_PrefAndRec.hxx>
67#include <AdvApprox_ApproxAFunction.hxx>
a31abc03 68#include <GeomConvert_ApproxSurface.hxx>
7fd59977 69
70#include <Precision.hxx>
71#include <ElCLib.hxx>
9ba2c30f 72#include <ElSLib.hxx>
7fd59977 73
74//=======================================================================
75//class : GeomFill_Sweep_Eval
76//purpose: The evaluator for curve approximation
77//=======================================================================
78
79class 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
96void 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//===============================================================
115GeomFill_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);
a31abc03 123 myForceApproxC1 = Standard_False;
7fd59977 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
a31abc03 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
7fd59977 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;
7fd59977 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#if DEB
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();
a31abc03 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 const Handle(Geom_BSplineSurface)& BSplSurf =
329 Handle(Geom_BSplineSurface)::DownCast(mySurface);
330
331 gp_Dir2d D(0., 1.);
332 gp_Pnt2d P(BSplSurf->UKnot(1), 0);
333 Handle(Geom2d_Line) LC1 = new (Geom2d_Line) (P, D);
334 Handle(Geom2d_TrimmedCurve) TC1 =
335 new (Geom2d_TrimmedCurve) (LC1, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
336
337 myCurve2d->SetValue(1, TC1);
338 CError->SetValue(1, 1, 0.);
339 CError->SetValue(2, 1, 0.);
340
341 P.SetCoord(BSplSurf->UKnot(BSplSurf->NbUKnots()), 0);
342 Handle(Geom2d_Line) LC2 = new (Geom2d_Line) (P, D);
343 Handle(Geom2d_TrimmedCurve) TC2 =
344 new (Geom2d_TrimmedCurve) (LC2, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
345
346 myCurve2d->SetValue(myCurve2d->Length(), TC2);
347 CError->SetValue(1, myCurve2d->Length(), 0.);
348 CError->SetValue(2, myCurve2d->Length(), 0.);
349
350 SError = theTol;
351 }
352 } //if (!mySurface->IsCNv(1))
7fd59977 353
354 // Les Courbes 2d
a31abc03 355 if (myCurve2d.IsNull())
356 {
357 myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
358 CError = new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
359 Standard_Integer kk,ii, ifin = 1, ideb;
360
361 if (myLoc->HasFirstRestriction()) {
362 ideb = 1;
363 }
364 else {
365 ideb = 2;
366 }
367 ifin += myLoc->TraceNumber();
368 if (myLoc->HasLastRestriction()) ifin++;
369
370 for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
371 Handle(Geom2d_BSplineCurve) C
372 = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
373 Approx.Curves2dKnots(),
374 Approx.Curves2dMults(),
375 Approx.Curves2dDegree());
376 myCurve2d->SetValue(ii, C);
377 CError->SetValue(1, ii, Approx.Max2dError(kk));
378 CError->SetValue(2, ii, Approx.Max2dError(kk));
379 }
380
381 // Si les courbes de restriction, ne sont pas calcules, on prend
382 // les iso Bords.
383 if (! myLoc->HasFirstRestriction()) {
384 gp_Dir2d D(0., 1.);
385 gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
386 Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
387 Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
388 (LC, First, Last);
389
390 myCurve2d->SetValue(1, TC);
391 CError->SetValue(1, 1, 0.);
392 CError->SetValue(2, 1, 0.);
393 }
394
395 if (! myLoc->HasLastRestriction()) {
396 gp_Dir2d D(0., 1.);
397 gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
398 Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
399 Handle(Geom2d_TrimmedCurve) TC =
400 new (Geom2d_TrimmedCurve) (LC, First, Last);
401 myCurve2d->SetValue(myCurve2d->Length(), TC);
402 CError->SetValue(1, myCurve2d->Length(), 0.);
403 CError->SetValue(2, myCurve2d->Length(), 0.);
404 }
405 } //if (myCurve2d.IsNull())
7fd59977 406 }
407 return Ok;
408}
409
410//===============================================================
411// Function : BuildProduct
412// Purpose : A venir...
413//===============================================================
414 Standard_Boolean GeomFill_Sweep::BuildProduct(const GeomAbs_Shape Continuity,
415 const Standard_Integer Degmax,
416 const Standard_Integer Segmax)
417{
418 Standard_Boolean Ok = Standard_False;
419
420 Handle(Geom_BSplineSurface) BSurf;
421 BSurf = Handle(Geom_BSplineSurface)::DownCast(
422 mySec->BSplineSurface()->Copy());
423 if (BSurf.IsNull()) return Ok; // Ce mode de construction est impossible
424
425
426 Standard_Integer NbIntervalC2, NbIntervalC3;
427 GeomFill_LocFunction Func(myLoc);
428
429 NbIntervalC2 = myLoc->NbIntervals(GeomAbs_C2);
430 NbIntervalC3 = myLoc->NbIntervals(GeomAbs_C3);
431 TColStd_Array1OfReal Param_de_decoupeC2 (1, NbIntervalC2+1);
432 myLoc->Intervals(Param_de_decoupeC2, GeomAbs_C2);
433 TColStd_Array1OfReal Param_de_decoupeC3 (1, NbIntervalC3+1);
434 myLoc->Intervals(Param_de_decoupeC3, GeomAbs_C3);
435
436
437 AdvApprox_PrefAndRec Preferentiel(Param_de_decoupeC2,
438 Param_de_decoupeC3);
439
440 Handle(TColStd_HArray1OfReal) ThreeDTol = new (TColStd_HArray1OfReal) (1,4);
441 ThreeDTol->Init(Tol3d); // A Affiner...
442
443 GeomFill_Sweep_Eval eval (Func);
444 AdvApprox_ApproxAFunction Approx(0, 0, 4,
445 ThreeDTol,
446 ThreeDTol,
447 ThreeDTol,
448 First,
449 Last,
450 Continuity,
451 Degmax,
452 Segmax,
453 eval,
454 Preferentiel);
455#if DEB
456 Approx.Dump(cout);
457#endif
458
459 Ok = Approx.HasResult();
460 if (Ok) {
461/* TColgp_Array1OfMat TM(1, nbpoles);
462 Handle(TColgp_HArray2OfPnt) ResPoles;
463 ResPoles = Approx.Poles();
464
465 // Produit Tensoriel
466 for (ii=1; ii<=nbpoles; ii++) {
467 TM(ii).SetCols(ResPoles->Value(ii,2).XYZ(),
468 ResPoles->Value(ii,3).XYZ(),
469 ResPoles->Value(ii,4).XYZ());
470 TR(ii) = ResPoles->Value(ii,1);
471 }
472 GeomLib::TensorialProduct(BSurf, TM, TR,
473 Approx.Knots()->Array1(),
474 Approx.Multiplicities()->Array1());
475
476 // Somme
477 TColgp_Array1OfPnt TPoles(1, nbpoles);
478 for (ii=1; ii<=nbpoles; ii++) {
479 TPoles(ii) = ResPoles->Value(ii,1);
480 }
481 Handle(Geom_BsplineCurve) BS =
482 new (Geom_BsplineCurve) (Poles,
483 Approx.Knots()->Array1(),
484 Approx.Multiplicities()->Array1(),
485 Approx.Degree());
486 for (ii=1; ii<=BSurf->NbVKnots(); ii++)
487 BS->InsertKnot( BSurf->VKnot(ii),
488 BSurf->VMultiplicity(ii),
489 Precision::Confusion());
490 TColgp_Array2OfPnt SurfPoles (1, BSurf->NbUPoles());
491 for (ii=1;
492
493*/
494 mySurface = BSurf;
495 }
496 return Ok;
497}
498
499// Modified by skv - Thu Feb 5 18:05:03 2004 OCC5073 Begin
500// Conditions:
501// * theSec should be constant
502// * the type of section should be a line
503// * theLoc should represent a translation.
504
505static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw) &theLoc,
506 const Handle(GeomFill_SectionLaw) &theSec,
507 const Standard_Real theTol)
508{
509 // Get the first and last transformations of the location
510 Standard_Real aFirst;
511 Standard_Real aLast;
512 gp_Vec VBegin;
513 gp_Vec VEnd;
514 gp_Mat M;
515 gp_GTrsf GTfBegin;
516 gp_Trsf TfBegin;
517 gp_GTrsf GTfEnd;
518 gp_Trsf TfEnd;
519
520 theLoc->GetDomain(aFirst, aLast);
521
522// Get the first transformation
523 theLoc->D0(aFirst, M, VBegin);
524
525 GTfBegin.SetVectorialPart(M);
526 GTfBegin.SetTranslationPart(VBegin.XYZ());
527
528 TfBegin.SetValues(GTfBegin(1,1), GTfBegin(1,2), GTfBegin(1,3), GTfBegin(1,4),
529 GTfBegin(2,1), GTfBegin(2,2), GTfBegin(2,3), GTfBegin(2,4),
530 GTfBegin(3,1), GTfBegin(3,2), GTfBegin(3,3), GTfBegin(3,4),
531 1.e-12, 1.e-14);
532
533// Get the last transformation
534 theLoc->D0(aLast, M, VEnd);
535
536 GTfEnd.SetVectorialPart(M);
537 GTfEnd.SetTranslationPart(VEnd.XYZ());
538
539 TfEnd.SetValues(GTfEnd(1,1), GTfEnd(1,2), GTfEnd(1,3), GTfEnd(1,4),
540 GTfEnd(2,1), GTfEnd(2,2), GTfEnd(2,3), GTfEnd(2,4),
541 GTfEnd(3,1), GTfEnd(3,2), GTfEnd(3,3), GTfEnd(3,4),
542 1.e-12, 1.e-14);
543
544 Handle(Geom_Surface) aSurf = theSec->BSplineSurface();
545 Standard_Real Umin;
546 Standard_Real Umax;
547 Standard_Real Vmin;
548 Standard_Real Vmax;
549
550 aSurf->Bounds(Umin, Umax, Vmin, Vmax);
551
552 // Get and transform the first section
553 Handle(Geom_Curve) FirstSection = theSec->ConstantSection();
554 GeomAdaptor_Curve ACFirst(FirstSection);
555
556 Standard_Real UFirst = ACFirst.FirstParameter();
557 gp_Lin L = ACFirst.Line();
558
559 L.Transform(TfBegin);
560
561 // Get and transform the last section
562 Handle(Geom_Curve) aLastSection = aSurf->VIso(Vmax);
563 Standard_Real aFirstParameter = aLastSection->FirstParameter();
564 gp_Pnt aPntLastSec = aLastSection->Value(aFirstParameter);
565
566 aPntLastSec.Transform(TfEnd);
567
568 gp_Pnt aPntFirstSec = ElCLib::Value( UFirst, L );
569 gp_Vec aVecSec( aPntFirstSec, aPntLastSec );
570 gp_Vec aVecSpine = VEnd - VBegin;
571
572 Standard_Boolean isParallel = aVecSec.IsParallel(aVecSpine, theTol);
573
574 return isParallel;
575}
576// Modified by skv - Thu Feb 5 18:05:01 2004 OCC5073 End
577
578//===============================================================
579// Function : BuildKPart
580// Purpose :
581//===============================================================
582 Standard_Boolean GeomFill_Sweep::BuildKPart()
583{
584 Standard_Boolean Ok = Standard_False;
585 Standard_Boolean isUPeriodic = Standard_False;
586 Standard_Boolean isVPeriodic = Standard_False;
587 Standard_Boolean IsTrsf = Standard_True;
588
589 isUPeriodic = mySec->IsUPeriodic();
590 Handle(Geom_Surface) S;
591 GeomAbs_CurveType SectionType;
592 gp_Vec V;
593 gp_Mat M;
594 Standard_Real levier, error = 0 ;
595 Standard_Real UFirst=0, VFirst=First, ULast=0, VLast=Last;
596 Standard_Real Tol = Min (Tol3d, BoundTol);
597
598 // (1) Trajectoire Rectilignes -------------------------
599 if (myLoc->IsTranslation(error)) {
600 // Donne de la translation
601 gp_Vec DP, DS;
602 myLoc->D0(1, M, DS);
603 myLoc->D0(0, M, V);
604 DP = DS - V;
605 DP.Normalize();
606 gp_GTrsf Tf;
607 gp_Trsf Tf2;
608 Tf.SetVectorialPart(M);
609 Tf.SetTranslationPart(V.XYZ());
610 try { // Pas joli mais il n'y as pas d'autre moyens de tester SetValues
611 OCC_CATCH_SIGNALS
612 Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
613 Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
614 Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4),
615 1.e-12, 1.e-14);
616 }
617 catch (Standard_ConstructionError) {
618 IsTrsf = Standard_False;
619 }
620 if (!IsTrsf) {
621 return Standard_False;
622 }
623
624 // (1.1) Cas Extrusion
625 if (mySec->IsConstant(error)) {
626 Handle(Geom_Curve) Section;
627 Section = mySec->ConstantSection();
628 GeomAdaptor_Curve AC(Section);
629 SectionType = AC.GetType();
630 UFirst = AC.FirstParameter();
631 ULast = AC.LastParameter();
632 // (1.1.a) Cas Plan
633 if ( (SectionType == GeomAbs_Line) && IsTrsf) {
634// Modified by skv - Thu Feb 5 11:39:06 2004 OCC5073 Begin
635 if (!IsSweepParallelSpine(myLoc, mySec, Tol))
636 return Standard_False;
637// Modified by skv - Thu Feb 5 11:39:08 2004 OCC5073 End
638 gp_Lin L = AC.Line();
639 L.Transform(Tf2);
640 DS.SetXYZ(L.Position().Direction().XYZ());
641 DS.Normalize();
642 levier = Abs(DS.Dot(DP));
643 SError = error + levier * Abs(Last-First);
644 if (SError <= Tol) {
645 Ok = Standard_True;
646 gp_Ax2 AxisOfPlane (L.Location(), DS^DP, DS);
647 S = new (Geom_Plane) (AxisOfPlane);
648 }
649 else SError = 0.;
650 }
651
652 // (1.1.b) Cas Cylindrique
653 if ( (SectionType == GeomAbs_Circle) && IsTrsf) {
654 gp_Circ C = AC.Circle();
655 C.Transform(Tf2);
656
657 DS.SetXYZ (C.Position().Direction().XYZ());
658 DS.Normalize();
659 levier = Abs(DS.CrossMagnitude(DP)) * C.Radius();
660 SError = levier * Abs(Last - First);
661 if (SError <= Tol) {
662 Ok = Standard_True;
663 gp_Ax3 axe (C.Location(), DP, C.Position().XDirection());
664 S = new (Geom_CylindricalSurface)
665 (axe, C.Radius());
666 if (C.Position().Direction().
667 IsOpposite(axe.Direction(), 0.1) ) {
668 Standard_Real f, l;
669 // L'orientation parametrique est inversee
c6541a0c
D
670 l = 2*M_PI - UFirst;
671 f = 2*M_PI - ULast;
7fd59977 672 UFirst = f;
673 ULast = l;
674 isUReversed = Standard_True;
675 }
676 }
677 else SError = 0.;
678 }
679
680 // (1.1.c) C'est bien une extrusion
681 if (!Ok) {
682 if (IsTrsf) {
683 Section->Transform(Tf2);
684 S = new (Geom_SurfaceOfLinearExtrusion)
685 (Section, DP);
686 SError = 0.;
687 Ok = Standard_True;
688 }
689 else { // extrusion sur BSpline
690
691 }
692 }
693 }
694
695 // (1.2) Cas conique
696 else if (mySec->IsConicalLaw(error)) {
697
698 gp_Pnt P1, P2, Centre0, Centre1, Centre2;
699 gp_Vec dsection;
700 Handle(Geom_Curve) Section;
701 GeomAdaptor_Curve AC;
702 gp_Circ C;
703 Standard_Real R1, R2;
704
705
706 Section = mySec->CirclSection(SLast);
707 Section->Transform(Tf2);
708 Section->Translate(Last*DP);
709 AC.Load(Section);
710 C = AC.Circle();
711 Centre2 = C.Location();
712 AC.D1(0, P2, dsection);
713 R2 = C.Radius();
714
715 Section = mySec->CirclSection(SFirst);
716 Section->Transform(Tf2);
717 Section->Translate(First*DP);
718 AC.Load(Section);
719 C = AC.Circle();
720 Centre1 = C.Location();
721 P1 = AC.Value(0);
722 R1 = C.Radius();
723
724 Section = mySec->CirclSection(SFirst - First*(SLast-SFirst)/(Last-First));
725 Section->Transform(Tf2);
726 AC.Load(Section);
727 C = AC.Circle();
728 Centre0 = C.Location();
729
730 Standard_Real Angle;
731 gp_Vec N(Centre1, P1);
732 if (N.Magnitude() < 1.e-9) {
733 gp_Vec Bis(Centre2, P2);
734 N = Bis;
735 }
736 gp_Vec L(P1, P2), Dir(Centre1,Centre2);
737
738 Angle = L.Angle(Dir);
c6541a0c 739 if ((Angle > 0.01) && (Angle < M_PI/2-0.01)) {
7fd59977 740 if (R2<R1) Angle = -Angle;
741 SError = error;
742 gp_Ax3 Axis(Centre0, Dir, N);
743 S = new (Geom_ConicalSurface)
744 (Axis, Angle, C.Radius());
745 // Calcul du glissement parametrique
746 VFirst = First / Cos(Angle);
747 VLast = Last / Cos(Angle);
748
749 // Bornes en U
750 UFirst = AC.FirstParameter();
751 ULast = AC.LastParameter();
752 gp_Vec diso;
753 gp_Pnt pbis;
754 S->VIso(VLast)->D1(0, pbis, diso);
755 if (diso.Magnitude()>1.e-9 && dsection.Magnitude()>1.e-9)
756 isUReversed = diso.IsOpposite(dsection, 0.1);
757 if (isUReversed ) {
758 Standard_Real f, l;
759 // L'orientation parametrique est inversee
c6541a0c
D
760 l = 2*M_PI - UFirst;
761 f = 2*M_PI - ULast;
7fd59977 762 UFirst = f;
763 ULast = l;
764 }
765
766 // C'est un cone
767 Ok = Standard_True;
768 }
769 }
770 }
771
772 // (2) Trajectoire Circulaire
773 if (myLoc->IsRotation(error)) {
774 if (mySec->IsConstant(error)) {
775 // La trajectoire
776 gp_Pnt Centre;
c6541a0c 777 isVPeriodic = (Abs(Last-First -2*M_PI) < 1.e-15);
7fd59977 778 Standard_Real RotRadius;
779 gp_Vec DP, DS, DN;
780 myLoc->D0(0.1, M, DS);
781 myLoc->D0(0, M, V);
782 myLoc->Rotation(Centre);
783
784 DP = DS - V;
785 DS.SetXYZ(V.XYZ() - Centre.XYZ());
786 RotRadius = DS.Magnitude();
787 if (RotRadius > 1.e-15) DS.Normalize();
788 else return Standard_False; // Pas de KPart, rotation degeneree
789 DN = DS ^ DP;
790 DN.Normalize();
791 DP = DN ^ DS;
792 DP.Normalize();
793
794 gp_GTrsf Tf;
795 gp_Trsf Tf2;
796 Tf.SetVectorialPart(M);
797 Tf.SetTranslationPart(V.XYZ());
798// try { // Pas joli mais il n'y as pas d'autre moyens de tester SetValues
799// OCC_CATCH_SIGNALS
800 Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
801 Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
802 Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4),
803 1.e-14, 1.e-15);
804// }
805// catch (Standard_ConstructionError) {
806// IsTrsf = Standard_False;
807// }
808 // La section
809 Handle(Geom_Curve) Section;
810 Section = mySec->ConstantSection();
811 GeomAdaptor_Curve AC(Section);
812 SectionType = AC.GetType();
813 UFirst = AC.FirstParameter();
814 ULast = AC.LastParameter();
815
816 // (2.1) Tore/Sphere ?
817 if ((SectionType == GeomAbs_Circle) && IsTrsf) {
818 gp_Circ C = AC.Circle();
819 Standard_Real Radius;
820 Standard_Boolean IsGoodSide = Standard_True;;
821 C.Transform(Tf2);
822 gp_Vec DC;
823 // On calcul le centre eventuel
824 DC.SetXYZ(C.Location().XYZ() - Centre.XYZ());
825 Centre.ChangeCoord() += (DC.Dot(DN))*DN.XYZ();
826 DC.SetXYZ(C.Location().XYZ() - Centre.XYZ());
827 Radius = DC.Magnitude(); //grand Rayon du tore
828 if ((Radius > Tol) && (DC.Dot(DS) < 0)) IsGoodSide = Standard_False;
829 if (Radius < Tol/100) DC = DS; // Pour definir le tore
830
831 // On verifie d'abord que le plan de la section est // a
832 // l'axe de rotation
833 gp_Vec NC;
834 NC.SetXYZ (C.Position().Direction().XYZ());
835 NC.Normalize();
836 error = Abs(NC.Dot(DN));
837 // Puis on evalue l'erreur commise sur la section,
838 // en pivotant son plan ( pour contenir l'axe de rotation)
839 error += Abs(NC.Dot(DS));
840 error *= C.Radius();
841 if (error <= Tol) {
842 SError = error;
843 error += Radius + Abs(RotRadius - C.Radius())/2;
844 if (error <= Tol) {
845 // (2.1.a) Sphere
846 Standard_Real f = UFirst , l = ULast;
847 SError = error;
848 Centre.BaryCenter(1.0, C.Location(), 1.0);
9ba2c30f 849 gp_Ax3 AxisOfSphere(Centre, DN, DS);
850 gp_Sphere theSphere( AxisOfSphere, (RotRadius + C.Radius())/2 );
851 S = new Geom_SphericalSurface(theSphere);
7fd59977 852 // Pour les spheres on ne peut pas controler le parametre
853 // V (donc U car myExchUV = Standard_True)
854 // Il faut donc modifier UFirst, ULast...
9ba2c30f 855 Standard_Real fpar = AC.FirstParameter();
856 Standard_Real lpar = AC.LastParameter();
857 Handle(Geom_Curve) theSection = new Geom_TrimmedCurve(Section, fpar, lpar);
858 theSection->Transform(Tf2);
859 gp_Pnt FirstPoint = theSection->Value(theSection->FirstParameter());
860 gp_Pnt LastPoint = theSection->Value(theSection->LastParameter());
861 Standard_Real UfirstOnSec, VfirstOnSec, UlastOnSec, VlastOnSec;
862 ElSLib::Parameters(theSphere, FirstPoint, UfirstOnSec, VfirstOnSec);
863 ElSLib::Parameters(theSphere, LastPoint, UlastOnSec, VlastOnSec);
864 if (VfirstOnSec < VlastOnSec)
865 {
866 f = VfirstOnSec;
867 l = VlastOnSec;
868 }
869 else
870 {
7fd59977 871 // L'orientation parametrique est inversee
9ba2c30f 872 f = VlastOnSec;
873 l = VfirstOnSec;
7fd59977 874 isUReversed = Standard_True;
875 }
7fd59977 876
c6541a0c 877 if ( (f >= -M_PI/2) && (l <= M_PI/2)) {
7fd59977 878 Ok = Standard_True;
879 myExchUV = Standard_True;
880 UFirst = f;
881 ULast = l;
882 }
883 else { // On restaure ce qu'il faut
884 isUReversed = Standard_False;
885 }
886 }
887 else if (IsGoodSide) {
888 // (2.1.b) Tore
889 gp_Ax3 AxisOfTore(Centre, DN, DC);
890 S = new (Geom_ToroidalSurface) (AxisOfTore,
891 Radius , C.Radius());
892
893 // Pour les tores on ne peut pas controler le parametre
894 // V (donc U car myExchUV = Standard_True)
895 // Il faut donc modifier UFirst, ULast...
896 Handle(Geom_Circle) Iso;
897 Iso = Handle(Geom_Circle)::DownCast(S->UIso(0.));
898 gp_Ax2 axeiso;
899 axeiso = Iso->Circ().Position();
900
901 if (C.Position().Direction().
902 IsOpposite(axeiso.Direction(), 0.1) ) {
903 Standard_Real f, l;
904 // L'orientation parametrique est inversee
c6541a0c
D
905 l = 2*M_PI - UFirst;
906 f = 2*M_PI - ULast;
7fd59977 907 UFirst = f;
908 ULast = l;
909 isUReversed = Standard_True;
910 }
911 // On calcul le "glissement" parametrique.
912 Standard_Real rot;
913 rot = C.Position().XDirection().AngleWithRef
914 (axeiso.XDirection(), axeiso.Direction());
915 UFirst -= rot;
916 ULast -= rot;
917
918 myExchUV = Standard_True;
919 // Attention l'arete de couture dans le cas periodique
920 // n'est peut etre pas a la bonne place...
921 if (isUPeriodic && Abs(UFirst)>Precision::PConfusion())
922 isUPeriodic = Standard_False; //Pour trimmer la surface...
923 Ok = Standard_True;
924 }
925 }
926 else {
927 SError = 0.;
928 }
929 }
930 // (2.2) Cone / Cylindre
931 if ((SectionType == GeomAbs_Line) && IsTrsf) {
932 gp_Lin L = AC.Line();
933 L.Transform(Tf2);
934 gp_Vec DL;
935 DL.SetXYZ(L.Direction().XYZ());
936 levier = Max(Abs(AC.FirstParameter()), AC.LastParameter());
937 // si la line est ortogonale au cercle de rotation
938 SError = error + levier * Abs(DL.Dot(DP));
939 if (SError <= Tol) {
940 Standard_Boolean reverse;
941 gp_Lin Dir(Centre, DN);
942 Standard_Real aux;
943 aux = DL.Dot(DN);
944 reverse = (aux < 0); // On choisit ici le sens de parametrisation
945
946 // Calcul du centre du vecteur supportant la "XDirection"
947 gp_Pnt CentreOfSurf;
948 gp_Vec O1O2(Centre, L.Location()), trans;
949 trans = DN;
950 trans *= DN.Dot(O1O2);
951 CentreOfSurf = Centre.Translated(trans);
952 DS.SetXYZ(L.Location().XYZ() - CentreOfSurf.XYZ());
953
954 error = SError;
955 error += (DL.XYZ()).CrossMagnitude(DN.XYZ())*levier;
956 if (error <= Tol) {
957 // (2.2.a) Cylindre
958 // si la line est orthogonale au plan de rotation
959 SError = error;
960 gp_Ax3 Axis(CentreOfSurf, Dir.Direction(), DS);
961 S = new (Geom_CylindricalSurface)
962 (Axis, L.Distance(CentreOfSurf));
963 Ok = Standard_True;
964 myExchUV = Standard_True;
965 }
966 else {
967 // On evalue l'angle du cone
968 Standard_Real Angle = Abs(Dir.Angle(L));
c6541a0c 969 if (Angle > M_PI/2) Angle = M_PI -Angle;
7fd59977 970 if (reverse) Angle = -Angle;
971 aux = DS.Dot(DL);
972 if (aux < 0) {
973 Angle = - Angle;
974 }
c6541a0c 975 if (Abs(Abs(Angle) - M_PI/2) > 0.01) {
7fd59977 976 // (2.2.b) Cone
977 // si les 2 droites ne sont pas orthogonales
978 Standard_Real Radius = CentreOfSurf.Distance(L.Location());
979 gp_Ax3 Axis(CentreOfSurf, Dir.Direction(), DS);
980 S = new (Geom_ConicalSurface)
981 (Axis, Angle, Radius);
982 myExchUV = Standard_True;
983 Ok = Standard_True;
984 }
985 else {
986 // On n'as pas conclue, on remet l'erreur a 0.
987 SError = 0.;
988 }
989 }
990 if (Ok && reverse) {
991 // On reverse le parametre
992 Standard_Real uf, ul;
993 Handle(Geom_Line) CL = new (Geom_Line)(L);
994 uf = CL->ReversedParameter(ULast);
995 ul = CL->ReversedParameter(UFirst);
996 UFirst = uf;
997 ULast = ul;
998 isUReversed = Standard_True;
999 }
1000 }
1001 else SError = 0.;
1002 }
1003
1004 // (2.3) Revolution
1005 if (!Ok) {
1006 if (IsTrsf) {
1007 Section->Transform(Tf2);
1008 gp_Ax1 Axis (Centre, DN);
1009 S = new (Geom_SurfaceOfRevolution)
1010 (Section, Axis);
1011 myExchUV = Standard_True;
1012 SError = 0.;
1013 Ok = Standard_True;
1014 }
1015 }
1016 }
1017 }
1018
1019
1020 if (Ok) { // On trimme la surface
1021 if (myExchUV) {
1022 Standard_Boolean b;
1023 b = isUPeriodic; isUPeriodic = isVPeriodic; isVPeriodic = b;
1024 Standard_Real r;
1025 r = UFirst; UFirst = VFirst; VFirst = r;
1026 r = ULast; ULast = VLast; VLast = r;
1027 }
1028
1029 if (!isUPeriodic && !isVPeriodic)
1030 mySurface = new (Geom_RectangularTrimmedSurface)
1031 (S, UFirst, ULast, VFirst, VLast);
1032 else if (isUPeriodic) {
1033 if (isVPeriodic) mySurface = S;
1034 else mySurface = new (Geom_RectangularTrimmedSurface)
1035 (S, VFirst, VLast, Standard_False);
1036 }
1037 else
1038 mySurface = new (Geom_RectangularTrimmedSurface)
1039 (S,UFirst, ULast, Standard_True);
1040
1041#if DEB
1042 if (isUPeriodic && !mySurface->IsUPeriodic())
1043 cout<<"Pb de periodicite en U" << endl;
1044 if (isUPeriodic && !mySurface->IsUClosed())
1045 cout<<"Pb de fermeture en U" << endl;
1046 if (isVPeriodic && !mySurface->IsVPeriodic())
1047 cout << "Pb de periodicite en V" << endl;
1048 if (isVPeriodic && !mySurface->IsVClosed())
1049 cout<<"Pb de fermeture en V" << endl;
1050#endif
1051 }
1052
1053
1054 return Ok;
1055}
1056
1057//===============================================================
1058// Function : IsDone
1059// Purpose :
1060//===============================================================
1061 Standard_Boolean GeomFill_Sweep::IsDone() const
1062{
1063 return done;
1064}
1065
1066//===============================================================
1067// Function :ErrorOnSurface
1068// Purpose :
1069//===============================================================
1070 Standard_Real GeomFill_Sweep::ErrorOnSurface() const
1071{
1072 return SError;
1073}
1074
1075//===============================================================
1076// Function ::ErrorOnRestriction
1077// Purpose :
1078//===============================================================
1079 void GeomFill_Sweep::ErrorOnRestriction(const Standard_Boolean IsFirst,
1080 Standard_Real& UError,
1081 Standard_Real& VError) const
1082{
1083 Standard_Integer ind;
1084 if (IsFirst) ind=1;
1085 else ind = myCurve2d->Length();
1086
1087 UError = CError->Value(1, ind);
1088 VError = CError->Value(2, ind);
1089}
1090
1091//===============================================================
1092// Function :ErrorOnTrace
1093// Purpose :
1094//===============================================================
1095 void GeomFill_Sweep::ErrorOnTrace(const Standard_Integer IndexOfTrace,
1096 Standard_Real& UError,
1097 Standard_Real& VError) const
1098{
1099 Standard_Integer ind = IndexOfTrace+1;
1100 if (IndexOfTrace > myLoc->TraceNumber())
1101 Standard_OutOfRange::Raise(" GeomFill_Sweep::ErrorOnTrace");
1102
1103 UError = CError->Value(1, ind);
1104 VError = CError->Value(2, ind);
1105}
1106
1107//===============================================================
1108// Function :Surface
1109// Purpose :
1110//===============================================================
1111 Handle(Geom_Surface) GeomFill_Sweep::Surface() const
1112{
1113 return mySurface;
1114}
1115
1116//===============================================================
1117// Function ::Restriction
1118// Purpose :
1119//===============================================================
1120 Handle(Geom2d_Curve) GeomFill_Sweep::Restriction(const Standard_Boolean IsFirst) const
1121{
1122 if (IsFirst)
1123 return myCurve2d->Value(1);
1124 return myCurve2d->Value(myCurve2d->Length());
1125
1126}
1127
1128//===============================================================
1129// Function :
1130// Purpose :
1131//===============================================================
1132 Standard_Integer GeomFill_Sweep::NumberOfTrace() const
1133{
1134 return myLoc->TraceNumber();
1135}
1136
1137//===============================================================
1138// Function :
1139// Purpose :
1140//===============================================================
1141 Handle(Geom2d_Curve)
1142 GeomFill_Sweep::Trace(const Standard_Integer IndexOfTrace) const
1143{
1144 Standard_Integer ind = IndexOfTrace+1;
1145 if (IndexOfTrace > myLoc->TraceNumber())
1146 Standard_OutOfRange::Raise(" GeomFill_Sweep::Trace");
1147 return myCurve2d->Value(ind);
1148}