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