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