0026377: Passing Handle objects as arguments to functions as non-const reference...
[occt.git] / src / Geom2dConvert / Geom2dConvert.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15//Jean-Claude Vauthier Novembre 1991
16//Passage sur C1 Aout 1992 et ajout transformation Bezier->BSpline
17
42cf5bc1 18#include <BSplCLib.hxx>
7fd59977 19#include <Convert_CircleToBSplineCurve.hxx>
42cf5bc1 20#include <Convert_ConicToBSplineCurve.hxx>
7fd59977 21#include <Convert_EllipseToBSplineCurve.hxx>
22#include <Convert_HyperbolaToBSplineCurve.hxx>
23#include <Convert_ParabolaToBSplineCurve.hxx>
42cf5bc1 24#include <Geom2d_BezierCurve.hxx>
25#include <Geom2d_BSplineCurve.hxx>
7fd59977 26#include <Geom2d_Circle.hxx>
42cf5bc1 27#include <Geom2d_Conic.hxx>
28#include <Geom2d_Curve.hxx>
7fd59977 29#include <Geom2d_Ellipse.hxx>
42cf5bc1 30#include <Geom2d_Geometry.hxx>
7fd59977 31#include <Geom2d_Hyperbola.hxx>
42cf5bc1 32#include <Geom2d_Line.hxx>
33#include <Geom2d_OffsetCurve.hxx>
7fd59977 34#include <Geom2d_Parabola.hxx>
7fd59977 35#include <Geom2d_TrimmedCurve.hxx>
42cf5bc1 36#include <Geom2dConvert.hxx>
7fd59977 37#include <Geom2dConvert_ApproxCurve.hxx>
42cf5bc1 38#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
7fd59977 39#include <GeomAbs_Shape.hxx>
42cf5bc1 40#include <gp.hxx>
41#include <gp_Circ2d.hxx>
42#include <gp_Dir2d.hxx>
43#include <gp_Elips2d.hxx>
44#include <gp_Hypr2d.hxx>
45#include <gp_Lin.hxx>
46#include <gp_Parab2d.hxx>
47#include <gp_Pnt2d.hxx>
48#include <gp_Trsf2d.hxx>
49#include <gp_Vec2d.hxx>
7fd59977 50#include <Hermit.hxx>
7fd59977 51#include <PLib.hxx>
42cf5bc1 52#include <Precision.hxx>
53#include <Standard_ConstructionError.hxx>
54#include <Standard_DomainError.hxx>
55#include <Standard_OutOfRange.hxx>
56#include <TColgp_Array1OfPnt2d.hxx>
7fd59977 57#include <TColStd_Array1OfBoolean.hxx>
7fd59977 58#include <TColStd_Array1OfInteger.hxx>
42cf5bc1 59#include <TColStd_Array1OfReal.hxx>
60#include <TColStd_HArray1OfReal.hxx>
7fd59977 61
62typedef gp_Circ2d Circ2d;
63typedef gp_Elips2d Elips2d;
64typedef gp_Hypr2d Hypr2d;
65typedef gp_Parab2d Parab2d;
66typedef gp_Pnt2d Pnt2d;
67typedef gp_Trsf2d Trsf2d;
7fd59977 68typedef Geom2d_Curve Curve;
69typedef Geom2d_BSplineCurve BSplineCurve;
7fd59977 70typedef TColStd_Array1OfReal Array1OfReal;
71typedef TColStd_Array1OfInteger Array1OfInteger;
72typedef TColgp_Array1OfPnt2d Array1OfPnt2d;
73
7fd59977 74//=======================================================================
75//function : BSplineCurveBuilder
76//purpose :
77//=======================================================================
78
c04c30b3 79static Handle(Geom2d_BSplineCurve) BSplineCurveBuilder (
7fd59977 80
c04c30b3 81const Handle(Geom2d_Conic)& TheConic,
7fd59977 82const Convert_ConicToBSplineCurve& Convert
83) {
84
c04c30b3 85 Handle(Geom2d_BSplineCurve) TheCurve;
7fd59977 86 Standard_Integer NbPoles = Convert.NbPoles();
87 Standard_Integer NbKnots = Convert.NbKnots();
88 Array1OfPnt2d Poles (1, NbPoles);
89 Array1OfReal Weights (1, NbPoles);
90 Array1OfReal Knots (1, NbKnots);
91 Array1OfInteger Mults (1, NbKnots);
92 Standard_Integer i;
93 for (i = 1; i <= NbPoles; i++) {
94 Poles (i) = Convert.Pole (i);
95 Weights (i) = Convert.Weight (i);
96 }
97 for (i = 1; i <= NbKnots; i++) {
98 Knots (i) = Convert.Knot (i);
99 Mults (i) = Convert.Multiplicity (i);
100 }
101 TheCurve = new BSplineCurve (
102 Poles, Weights, Knots, Mults,
103 Convert.Degree(), Convert.IsPeriodic());
104
105 gp_Ax22d Axis = TheConic->Position();
106 if ( ( Axis.XDirection() ^ Axis.YDirection()) < 0.) {
107 // Then the axis is left-handed, apply a symetry to the curve.
108 gp_Trsf2d Sym;
109 Sym.SetMirror(gp::OX2d());
110 TheCurve->Transform(Sym);
111 }
112
113 Trsf2d T;
114 T.SetTransformation (TheConic->XAxis(), gp::OX2d());
c04c30b3 115 Handle(Geom2d_BSplineCurve) Cres =
116 Handle(Geom2d_BSplineCurve)::DownCast(TheCurve->Transformed (T));
7fd59977 117 return Cres;
118}
119
120
121//=======================================================================
122//function : SplitBSplineCurve
123//purpose :
124//=======================================================================
125
c04c30b3 126Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve (
7fd59977 127
c04c30b3 128const Handle(Geom2d_BSplineCurve)& C,
7fd59977 129const Standard_Integer FromK1,
130const Standard_Integer ToK2,
131const Standard_Boolean SameOrientation
132) {
133
134 Standard_Integer TheFirst = C->FirstUKnotIndex ();
135 Standard_Integer TheLast = C->LastUKnotIndex ();
136 if (FromK1 == ToK2) Standard_DomainError::Raise();
137 Standard_Integer FirstK = Min (FromK1, ToK2);
138 Standard_Integer LastK = Max (FromK1, ToK2);
139 if (FirstK < TheFirst || LastK > TheLast) Standard_OutOfRange::Raise();
140
c04c30b3 141 Handle(Geom2d_BSplineCurve) NewCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
7fd59977 142
143 NewCurve->Segment(C->Knot(FirstK),C->Knot(LastK));
144
145 if (C->IsPeriodic()) {
146 if (!SameOrientation) NewCurve->Reverse();
147 }
148 else {
149 if (FromK1 > ToK2) NewCurve->Reverse();
150 }
151 return NewCurve;
152}
153
154
155//=======================================================================
156//function : SplitBSplineCurve
157//purpose :
158//=======================================================================
159
c04c30b3 160Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve (
7fd59977 161
c04c30b3 162const Handle(Geom2d_BSplineCurve)& C,
7fd59977 163const Standard_Real FromU1,
164const Standard_Real ToU2,
165const Standard_Real, // ParametricTolerance,
166const Standard_Boolean SameOrientation
167)
168{
169 Standard_Real FirstU = Min( FromU1, ToU2);
170 Standard_Real LastU = Max( FromU1, ToU2);
171
172 Handle (Geom2d_BSplineCurve) C1
173 = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
174
175 C1->Segment(FirstU, LastU);
176
177 if (C->IsPeriodic()) {
178 if (!SameOrientation) C1->Reverse();
179 }
180 else {
181 if (FromU1 > ToU2) C1->Reverse();
182 }
183
184 return C1;
185}
186
187
188//=======================================================================
189//function : CurveToBSplineCurve
190//purpose :
191//=======================================================================
192
c04c30b3 193Handle(Geom2d_BSplineCurve) Geom2dConvert::CurveToBSplineCurve (
7fd59977 194
c04c30b3 195const Handle(Geom2d_Curve)& C,
7fd59977 196const Convert_ParameterisationType Parameterisation)
197{
198
199 Handle (BSplineCurve) TheCurve;
200
201 if (C->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
202 Handle (Curve) Curv;
c04c30b3 203 Handle(Geom2d_TrimmedCurve) Ctrim = Handle(Geom2d_TrimmedCurve)::DownCast(C);
7fd59977 204 Curv = Ctrim->BasisCurve();
205 Standard_Real U1 = Ctrim->FirstParameter();
206 Standard_Real U2 = Ctrim->LastParameter();
207
208 // Si la courbe n'est pas vraiment restreinte, on ne risque pas
209 // le Raise dans le BS->Segment.
210 if (!Curv->IsPeriodic()) {
211 if (U1 < Curv->FirstParameter())
212 U1 = Curv->FirstParameter();
213 if (U2 > Curv->LastParameter())
214 U2 = Curv->LastParameter();
215 }
216
217 if (Curv->IsKind(STANDARD_TYPE(Geom2d_Line))) {
218 gp_Pnt2d Pdeb = Ctrim->StartPoint();
219 gp_Pnt2d Pfin = Ctrim->EndPoint();
220 Array1OfPnt2d Poles (1, 2);
221 Poles (1) = Pdeb;
222 Poles (2) = Pfin;
223 Array1OfReal Knots (1, 2);
224 Knots (1) = Ctrim->FirstParameter ();
225 Knots (2) = Ctrim->LastParameter();
226 Array1OfInteger Mults (1, 2);
227 Mults (1) = 2;
228 Mults (2) = 2;
229 Standard_Integer Degree = 1;
230 TheCurve = new Geom2d_BSplineCurve (Poles, Knots, Mults, Degree);
231 }
232
233 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
c04c30b3 234 Handle(Geom2d_Circle) TheConic= Handle(Geom2d_Circle)::DownCast(Curv);
7fd59977 235 Circ2d C2d (gp::OX2d(), TheConic->Radius());
236 if(Parameterisation != Convert_RationalC1) {
237 Convert_CircleToBSplineCurve Convert (C2d,
238 U1,
239 U2,
240 Parameterisation);
241 TheCurve = BSplineCurveBuilder (TheConic, Convert);
242 }
243 else {
244 if(U2 - U1 < 6.) {
245 Convert_CircleToBSplineCurve Convert (C2d,
246 U1,
247 U2,
248 Parameterisation);
249 TheCurve = BSplineCurveBuilder (TheConic, Convert);
250 }
251 else { // split circle to avoide numerical
252 // overflow when U2 - U1 =~ 2*PI
253
254 Standard_Real Umed = (U1 + U2) * .5;
255 Convert_CircleToBSplineCurve Convert1 (C2d,
256 U1,
257 Umed,
258 Parameterisation);
259
260 Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
261
262 Convert_CircleToBSplineCurve Convert2 (C2d,
263 Umed,
264 U2,
265 Parameterisation);
266
267 Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
268
269 Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
270 Parameterisation);
271
272 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
273
274
275 TheCurve = CCTBSpl.BSplineCurve();
276 }
277 }
278 }
279
280 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
c04c30b3 281 Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(Curv);
7fd59977 282
283 Elips2d E2d (gp::OX2d(),
284 TheConic->MajorRadius(),
285 TheConic->MinorRadius());
286 if(Parameterisation != Convert_RationalC1) {
287 Convert_EllipseToBSplineCurve Convert (E2d,
288 U1,
289 U2,
290 Parameterisation);
291 TheCurve = BSplineCurveBuilder (TheConic, Convert);
292 }
293 else {
294 if(U2 - U1 < 6.) {
295 Convert_EllipseToBSplineCurve Convert (E2d,
296 U1,
297 U2,
298 Parameterisation);
299 TheCurve = BSplineCurveBuilder (TheConic, Convert);
300 }
301 else { // split ellipse to avoide numerical
302 // overflow when U2 - U1 =~ 2*PI
303
304 Standard_Real Umed = (U1 + U2) * .5;
305 Convert_EllipseToBSplineCurve Convert1 (E2d,
306 U1,
307 Umed,
308 Parameterisation);
309
310 Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
311
312 Convert_EllipseToBSplineCurve Convert2 (E2d,
313 Umed,
314 U2,
315 Parameterisation);
316
317 Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
318
319 Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
320 Parameterisation);
321
322 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
323
324
325 TheCurve = CCTBSpl.BSplineCurve();
326 }
327 }
328 }
329
330 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) {
c04c30b3 331 Handle(Geom2d_Hyperbola) TheConic = Handle(Geom2d_Hyperbola)::DownCast(Curv);
7fd59977 332
333 Hypr2d H2d (gp::OX2d(),
334 TheConic->MajorRadius(), TheConic->MinorRadius());
335 Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
336 TheCurve = BSplineCurveBuilder (TheConic, Convert);
337 }
338
339 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
c04c30b3 340 Handle(Geom2d_Parabola) TheConic = Handle(Geom2d_Parabola)::DownCast(Curv);
7fd59977 341
342 Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
343 Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
344 TheCurve = BSplineCurveBuilder (TheConic, Convert);
345 }
346
347 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
348
c04c30b3 349 Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(Curv->Copy());
7fd59977 350
351 CBez->Segment (U1, U2);
352 Standard_Integer NbPoles = CBez->NbPoles();
353 Standard_Integer Degree = CBez->Degree();
354 Array1OfPnt2d Poles (1, NbPoles);
355 Array1OfReal Knots (1, 2);
356 Array1OfInteger Mults (1, 2);
357 Knots (1) = 0.0;
358 Knots (2) = 1.0;
359 Mults (1) = Degree + 1;
360 Mults (2) = Degree + 1;
361 CBez->Poles (Poles);
362 if (CBez->IsRational()) {
363 Array1OfReal Weights (1, NbPoles);
364 CBez->Weights (Weights);
365 TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
366 }
367 else {
368 TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
369 }
370 }
371
372 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
373 TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(Curv->Copy());
374 TheCurve->Segment(U1,U2);
375 }
376
377 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
378
379 Standard_Real Tol2d = 1.e-4;
380 GeomAbs_Shape Order = GeomAbs_C2;
381 Standard_Integer MaxSegments = 16, MaxDegree = 14;
382 Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order,
383 MaxSegments, MaxDegree);
384 if (ApprCOffs.HasResult())
385 TheCurve = ApprCOffs.Curve();
386 else Standard_ConstructionError::Raise();
387 }
388
389 else { Standard_DomainError::Raise("No such curve"); }
390
391 }
392
393
394 else {
395
396 if (C->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
c04c30b3 397 Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(C);
7fd59977 398
399 Elips2d E2d (gp::OX2d(),
400 TheConic->MajorRadius(), TheConic->MinorRadius());
401 Convert_EllipseToBSplineCurve Convert (E2d,
402 Parameterisation);
403 TheCurve = BSplineCurveBuilder (TheConic, Convert);
404 TheCurve->SetPeriodic();
405 }
406
407 else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
c04c30b3 408 Handle(Geom2d_Circle) TheConic = Handle(Geom2d_Circle)::DownCast(C);
7fd59977 409
410 Circ2d C2d (gp::OX2d(), TheConic->Radius());
411 Convert_CircleToBSplineCurve Convert (C2d,
412 Parameterisation);
413 TheCurve = BSplineCurveBuilder (TheConic, Convert);
414 TheCurve->SetPeriodic();
415 }
416
417 else if (C->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
c04c30b3 418 Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(C);
7fd59977 419
420 Standard_Integer NbPoles = CBez->NbPoles();
421 Standard_Integer Degree = CBez->Degree();
422 Array1OfPnt2d Poles (1, NbPoles);
423 Array1OfReal Knots (1, 2);
424 Array1OfInteger Mults (1, 2);
425 Knots (1) = 0.0;
426 Knots (2) = 1.0;
427 Mults (1) = Degree + 1;
428 Mults (2) = Degree + 1;
429 CBez->Poles (Poles);
430 if (CBez->IsRational()) {
431 Array1OfReal Weights (1, NbPoles);
432 CBez->Weights (Weights);
433 TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
434 }
435 else {
436 TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
437 }
438 }
439 else if (C->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
440 TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
441 }
442
443 else if (C->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
444
445 Standard_Real Tol2d = 1.e-4;
446 GeomAbs_Shape Order = GeomAbs_C2;
447 Standard_Integer MaxSegments = 16, MaxDegree = 14;
448 Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order,
449 MaxSegments, MaxDegree);
450 if (ApprCOffs.HasResult())
451 TheCurve = ApprCOffs.Curve();
452 else Standard_ConstructionError::Raise();
453 }
454
455 else { Standard_DomainError::Raise(); }
456 }
457
458 return TheCurve;
459}
460
7fd59977 461 //=======================================================================
41194117 462//class : law_evaluator
7fd59977 463//purpose :
464//=======================================================================
465
41194117
K
466class Geom2dConvert_law_evaluator : public BSplCLib_EvaluatorFunction
467{
468
469public:
470
471 Geom2dConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
472 : myAncore (theAncore) {}
473
474 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
475 const Standard_Real* theStartEnd,
476 const Standard_Real theParameter,
477 Standard_Real& theResult,
478 Standard_Integer& theErrorCode) const
479 {
480 theErrorCode = 0;
481 if (!myAncore.IsNull() &&
482 theParameter >= theStartEnd[0] &&
483 theParameter <= theStartEnd[1] &&
484 theDerivativeRequest == 0)
485 {
486 gp_Pnt2d aPoint;
487 myAncore->D0 (theParameter, aPoint);
488 theResult = aPoint.Coord (2);
489 }
490 else
491 theErrorCode = 1;
492 }
493
494private:
495
496 Handle(Geom2d_BSplineCurve) myAncore;
497
498};
499
7fd59977 500
501//=======================================================================
502//function : MultNumandDenom
503//purpose : Multiply two BSpline curves to make one
504//=======================================================================
505
506
507static Handle(Geom2d_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
508 const Handle(Geom2d_BSplineCurve)& BS )
509
510{ TColStd_Array1OfReal aKnots(1,a->NbKnots());
511 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
512 TColStd_Array1OfReal BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1);
513 TColStd_Array1OfReal BSWeights(1,BS->NbPoles());
514 TColStd_Array1OfInteger aMults(1,a->NbKnots());
515 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
516 TColgp_Array1OfPnt2d aPoles(1,a->NbPoles());
517 TColgp_Array1OfPnt2d BSPoles(1,BS->NbPoles());
518 Handle(Geom2d_BSplineCurve) res;
519 Handle(TColStd_HArray1OfReal) resKnots;
520 Handle(TColStd_HArray1OfInteger) resMults;
521 Standard_Real start_value,end_value;
522 Standard_Real tolerance=Precision::Confusion();
523 Standard_Integer resNbPoles,degree,
524 ii,jj,
525 Status;
526
527 BS->Knots(BSKnots);
528 BS->Multiplicities(BSMults);
529 BS->Poles(BSPoles);
530 BS->Weights(BSWeights);
531 BS->KnotSequence(BSFlatKnots);
532 start_value = BSKnots(1);
533 end_value = BSKnots(BS->NbKnots());
534
535 a->Knots(aKnots);
536 a->Poles(aPoles);
537 a->Multiplicities(aMults);
538 BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
41194117 539 Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
7fd59977 540
541 BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value,
542 a->Degree(),aKnots,aMults,
543 BS->Degree(),BSKnots,BSMults,
544 resNbPoles,resKnots,resMults);
545 degree=BS->Degree()+a->Degree();
546 TColgp_Array1OfPnt2d resNumPoles(1,resNbPoles);
547 TColStd_Array1OfReal resDenPoles(1,resNbPoles);
548 TColgp_Array1OfPnt2d resPoles(1,resNbPoles);
549 TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
550 BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
551 for (ii=1;ii<=BS->NbPoles();ii++)
552 for (jj=1;jj<=2;jj++)
553 BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
554//POP pour NT
41194117 555 Geom2dConvert_law_evaluator ev (anAncore);
7fd59977 556 BSplCLib::FunctionMultiply(ev,
557 BS->Degree(),
558 BSFlatKnots,
559 BSPoles,
560 resFlatKnots,
561 degree,
562 resNumPoles,
563 Status);
564 BSplCLib::FunctionMultiply(ev,
565 BS->Degree(),
566 BSFlatKnots,
567 BSWeights,
568 resFlatKnots,
569 degree,
570 resDenPoles,
571 Status);
572// BSplCLib::FunctionMultiply(law_evaluator,
573// BS->Degree(),
574// BSFlatKnots,
575// BSPoles,
576// resFlatKnots,
577// degree,
578// resNumPoles,
579// Status);
580// BSplCLib::FunctionMultiply(law_evaluator,
581// BS->Degree(),
582// BSFlatKnots,
583// BSWeights,
584// resFlatKnots,
585// degree,
586// resDenPoles,
587// Status);
588 for (ii=1;ii<=resNbPoles;ii++)
589 for(jj=1;jj<=2;jj++)
590 resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
591 res = new Geom2d_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
592 return res;
593}
594
595//=======================================================================
596//function : Pretreatment
597//purpose : Put the two first and two last weigths at one if they are
598// equal
599//=======================================================================
600
601static void Pretreatment(TColGeom2d_Array1OfBSplineCurve& tab)
602
603{Standard_Integer i,j;
604 Standard_Real a;
605
606 for (i=0;i<=(tab.Length()-1);i++){
607 if (tab(i)->IsRational()) {
608 a=tab(i)->Weight(1) ;
609 if ((tab(i)->Weight(2)==a)&&
610 (tab(i)->Weight(tab(i)->NbPoles()-1)==a) &&
611 (tab(i)->Weight(tab(i)->NbPoles())==a))
612
613 for (j=1;j<=tab(i)->NbPoles();j++)
614 tab(i)->SetWeight(j,tab(i)->Weight(j)/a) ;
615 }
616 }
617}
618
619//=======================================================================
620//function : NeedToBeTreated
621//purpose : Say if the BSpline is rationnal and if the two first and two
622// last weigths are different
623//=======================================================================
624
625static Standard_Boolean NeedToBeTreated(const Handle(Geom2d_BSplineCurve)& BS)
626
627{
628 TColStd_Array1OfReal tabWeights(1,BS->NbPoles());
629 if (BS->IsRational()) {
630 BS->Weights(tabWeights);
631 if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
632 ((BS->Weight(1)<(1-Precision::Confusion()))||
633 (BS->Weight(1)>(1+Precision::Confusion()))||
634 (BS->Weight(2)<(1-Precision::Confusion()))||
635 (BS->Weight(2)>(1+Precision::Confusion()))||
636 (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
637 (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
638 (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
639 (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
640 return Standard_True;
641 else
642 return Standard_False;
643 }
644 else
645 return Standard_False ;
646
647}
648
649//=======================================================================
650//function : Need2DegRepara
651//purpose : in the case of wire closed G1 it says if you will to use a
652// two degree reparametrisation to close it C1
653//=======================================================================
654
655static Standard_Boolean Need2DegRepara(const TColGeom2d_Array1OfBSplineCurve& tab)
656
657{Standard_Integer i;
658 gp_Vec2d Vec1,Vec2;
659 gp_Pnt2d Pint;
660 Standard_Real Rapport=1.0e0;
661
662 for (i=0;i<=tab.Length()-2;i++){
663 tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
664 tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
665 Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
666 }
667 if ((Rapport<=(1.0e0 +Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
668 return Standard_False;
669 else
670 return Standard_True;
671}
672
673//=======================================================================
674//function : Indexmin
675//purpose : Give the index of the curve which has the lowest degree
676//=======================================================================
677
678static Standard_Integer Indexmin(const TColGeom2d_Array1OfBSplineCurve& tab)
679{
680 Standard_Integer i,index=0,degree;
681
682 degree=tab(0)->Degree();
683 for (i=0;i<=tab.Length()-1;i++)
684 if (tab(i)->Degree()<=degree){
685 degree=tab(i)->Degree();
686 index=i;
687 }
688 return index;
689}
690
691//=======================================================================
692//function : NewTabClosedG1
693//purpose :
694//=======================================================================
695
696static void ReorderArrayOfG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
697 TColStd_Array1OfReal& ArrayOfToler,
698 TColStd_Array1OfBoolean& tabG1,
699 const Standard_Integer StartIndex,
700 const Standard_Real ClosedTolerance)
701
702{Standard_Integer i;
703 TColGeom2d_Array1OfBSplineCurve ArraybisOfCurves(0,ArrayOfCurves.Length()-1);
704 TColStd_Array1OfReal ArraybisOfToler(0,ArrayOfToler.Length()-1);
705 TColStd_Array1OfBoolean tabbisG1(0,tabG1.Length()-1);
706
707 for (i=0;i<=ArrayOfCurves.Length()-1;i++){
708 if (i!=ArrayOfCurves.Length()-1){
709 ArraybisOfCurves(i)=ArrayOfCurves(i);
710 ArraybisOfToler(i)=ArrayOfToler(i);
711 tabbisG1(i)=tabG1(i);
712 }
713 else
714 ArraybisOfCurves(i)=ArrayOfCurves(i);
715 }
716
717 for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
718 ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
719 if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
720 ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
721 tabG1(i)=tabbisG1(i+StartIndex+1);
722 }
723 }
724
725 ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
726 tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
727
728 for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
729 if (i!=ArrayOfCurves.Length()-1){
730 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
731 ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
732 tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
733 }
734 else
735 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
736 }
737}
738
739//=======================================================================
740//function : GeomAbsToInteger
741//purpose :
742//=======================================================================
743
744static Standard_Integer GeomAbsToInteger(const GeomAbs_Shape gcont)
745{
746 Standard_Integer cont=0 ;
747 switch (gcont) {
748 case GeomAbs_C0 :
749 cont = 0 ;
750 break ;
751 case GeomAbs_G1 :
752 cont = 1 ;
753 break ;
754 case GeomAbs_C1 :
755 cont = 2 ;
756 break ;
757 case GeomAbs_G2 :
758 cont = 3 ;
759 break ;
760 case GeomAbs_C2 :
761 cont = 4 ;
762 break ;
763 case GeomAbs_C3 :
764 cont = 5 ;
765 break ;
766 case GeomAbs_CN :
767 cont = 6 ;
768 break ;
769 }
770 return cont ;
771}
772//=======================================================================
773//function : Continuity
774//purpose :
775//=======================================================================
776
777static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1,
778 const Handle(Geom2d_Curve)& C2,
779 const Standard_Real u1,
780 const Standard_Real u2,
781 const Standard_Boolean r1,
782 const Standard_Boolean r2,
783 const Standard_Real tl,
784 const Standard_Real ta)
785{
786 GeomAbs_Shape cont = GeomAbs_C0;
787 Standard_Integer index1,
788 index2 ;
789 Standard_Real tolerance,value ;
790// Standard_Boolean fini = Standard_False;
791 gp_Vec2d d1,d2;
792// gp_Dir2d dir1,dir2;
793 gp_Pnt2d point1, point2 ;
794 Standard_Integer cont1, cont2 ;
795 GeomAbs_Shape gcont1 = C1->Continuity(), gcont2 = C2->Continuity();
796 cont1 = GeomAbsToInteger(gcont1) ;
797 cont2 = GeomAbsToInteger(gcont2) ;
798
799 Handle(Geom2d_Curve) aCurve1 = C1 ;
800 Handle(Geom2d_Curve) aCurve2 = C2 ;
801 if (C1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
802 Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve1) ;
803 aCurve1 = aTrimmed->BasisCurve() ;
804 }
805 if (C2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
806 Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve2) ;
807 aCurve2 = aTrimmed->BasisCurve() ;
808 }
809 if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
810 Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1) ;
811 BSplineCurve->Resolution(tl,
812 tolerance) ;
813 BSplineCurve->LocateU(u1,
814 tolerance,
815 index1,
816 index2) ;
817
818 if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
819 cont1 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
820 }
821 else {
822 cont1 = 5 ;
823 }
824 }
825 if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
826 Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve2) ;
827 BSplineCurve->Resolution(tl,
828 tolerance) ;
829 BSplineCurve->LocateU(u2,
830 tolerance,
831 index1,
832 index2) ;
833
834 if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
835 cont2 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
836 }
837 else {
838 cont2 = 5 ;
839 }
840 }
841 aCurve1->D1(u1,
842 point1,
843 d1) ;
844 aCurve2->D1(u2,
845 point2,
846 d2) ;
847 if (point1.SquareDistance(point2) <= tl * tl) {
848 if (cont1 != 0 &&
849 cont2 != 0) {
850
851 if (d1.SquareMagnitude() >= tl * tl &&
852 d2.SquareMagnitude() >= tl * tl) {
853 if (r1) {
854 d1.SetCoord(-d1.X(),-d1.Y()) ;
855 }
856 if (r2) {
857 d2.SetCoord(-d2.X(),-d2.Y()) ;
858 }
859 value = d1.Dot(d2) ;
860 if ((d1.Magnitude()<=(d2.Magnitude()+tl))&&
861 (d1.Magnitude()>=(d2.Magnitude()-tl))&&
862 (value/(d1.Magnitude()*d2.Magnitude()) >= 1.0e0 - ta * ta)) {
863 cont = GeomAbs_C1 ;
864 }
865 else {
866 d1.Normalize() ;
867 d2.Normalize() ;
868 value = Abs(d1.Dot(d2)) ;
869 if (value >= 1.0e0 - ta * ta) {
870 cont = GeomAbs_G1 ;
871 }
872 }
873
874 }
875 }
876 }
877 else
878 Standard_Failure::Raise("Courbes non jointives");
879 return cont ;
880}
881
882//=======================================================================
883//function : Continuity
884//purpose :
885//=======================================================================
886
887static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1,
888 const Handle(Geom2d_Curve)& C2,
889 const Standard_Real u1,
890 const Standard_Real u2,
891 const Standard_Boolean r1,
892 const Standard_Boolean r2)
893{
894 return Continuity(C1,C2,u1,u2,r1,r2,
895 Precision::Confusion(),Precision::Angular());
896}
897
898//=======================================================================
41194117 899//class :reparameterise_evaluator
7fd59977 900//purpose :
901//=======================================================================
902
41194117
K
903class Geom2dConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
904{
905
906public:
907
908 Geom2dConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
909 {
910 memcpy(myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
911 }
912
913 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
914 const Standard_Real* /*theStartEnd*/,
915 const Standard_Real theParameter,
916 Standard_Real& theResult,
917 Standard_Integer& theErrorCode) const
918 {
919 theErrorCode = 0;
920 PLib::EvalPolynomial (theParameter,
921 theDerivativeRequest,
922 2,
923 1,
924 *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
925 theResult);
926 }
927
928private:
929
930 Standard_Real myPolynomialCoefficient[3];
931
932};
7fd59977 933
934//=======================================================================
935//function : ConcatG1
936//purpose :
937//=======================================================================
938
939void Geom2dConvert::ConcatG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
940 const TColStd_Array1OfReal& ArrayOfToler,
941 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
942 const Standard_Boolean ClosedFlag,
943 const Standard_Real ClosedTolerance)
944
945{Standard_Integer nb_curve=ArrayOfCurves.Length(),
946 nb_vertexG1,
947 nb_group=0,
948 index=0,i,ii,j,jj,
949 indexmin,
950 nb_vertex_group0=0;
951 Standard_Real lambda, //coeff de raccord G1
952 First,PreLast=0;
953 gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs
954 gp_Pnt2d Pint;
955 Handle(Geom2d_BSplineCurve) Curve1,Curve2;
956 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords
957 TColStd_Array1OfReal local_tolerance(0,
958 ArrayOfToler.Length()-1) ;
959
960 for (i= 0; i < ArrayOfToler.Length() ; i++) {
961 local_tolerance(i) = ArrayOfToler(i) ;
962 }
963 for (i=0 ;i<nb_curve; i++){
964 if (i >= 1){
965 First=ArrayOfCurves(i)->FirstParameter();
966 if (Continuity(ArrayOfCurves(i-1),
967 ArrayOfCurves(i),
968 PreLast,First,
969 Standard_True,
970 Standard_True)<GeomAbs_C0)
971 Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ; //renvoi d'une erreur
972 else{
973 if (Continuity(ArrayOfCurves(i-1),
974 ArrayOfCurves(i),
975 PreLast,First,
976 Standard_True,
977 Standard_True)>=GeomAbs_G1)
978 tabG1(i-1)=Standard_True; //True=Continuite G1
979 else
980 tabG1(i-1)=Standard_False;
981 }
982 }
983 PreLast=ArrayOfCurves(i)->LastParameter();
984 }
985
986
987 while (index<=nb_curve-1){ //determination des caracteristiques du Wire
988 nb_vertexG1=0;
989 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
990 nb_vertexG1++;
991 nb_group++;
992 if (index==0)
993 nb_vertex_group0=nb_vertexG1;
994 index=index+1+nb_vertexG1;
995 }
996
997 if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau
998 nb_group--;
999 ReorderArrayOfG1(ArrayOfCurves,
1000 local_tolerance,
1001 tabG1,
1002 nb_vertex_group0,
1003 ClosedTolerance);
1004 }
1005
1006 ArrayOfConcatenated = new
1007 TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1008
1009 Standard_Boolean fusion;
1010// Standard_Integer k=0;
1011 index=0;
1012 Pretreatment(ArrayOfCurves);
1013
41194117
K
1014 Standard_Real aPolynomialCoefficient[3];
1015
7fd59977 1016 if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier
1017 indexmin=Indexmin(ArrayOfCurves);
1018 if (indexmin!=(ArrayOfCurves.Length()-1))
1019 ReorderArrayOfG1(ArrayOfCurves,
1020 local_tolerance,
1021 tabG1,
1022 indexmin,
1023 ClosedTolerance);
1024 Curve2=ArrayOfCurves(0);
1025 for (j=1;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe
1026 Curve1=ArrayOfCurves(j);
1027 if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){
1028 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1029 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1030 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1031 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1032 Curve1->Knots(KnotC1);
1033 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1034 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1035 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1036 Standard_Real tmax,a,b,c,
1037 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1038 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1039 a=(lambda*lambda2-1)/(2*lambda*tmax);
41194117 1040 aPolynomialCoefficient[2] = a;
7fd59977 1041 b=(1/lambda);
41194117 1042 aPolynomialCoefficient[1] = b;
7fd59977 1043 c=umin;
41194117 1044 aPolynomialCoefficient[0] = c;
7fd59977 1045 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1046 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1047 Curve1->Multiplicities(KnotC1Mults);
1048 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1049 KnotC1(1)=0.0;
1050 for (ii=2;ii<=KnotC1.Length();ii++) {
1051// KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1052 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1053 }
1054 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1055 Curve1->Poles(Curve1Poles);
1056
1057 for (ii=1;ii<=Curve1->NbKnots();ii++)
1058 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1059
1060 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1061
1062 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1063 TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1064 Standard_Integer Status;
1065 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1066 Curve1->Weights(Curve1Weights);
1067 for (ii=1;ii<=Curve1->NbPoles();ii++)
1068 for (jj=1;jj<=2;jj++)
1069 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1070//POP pour NT
41194117 1071 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
7fd59977 1072 BSplCLib::FunctionReparameterise(ev,
1073 Curve1->Degree(),
1074 Curve1FlatKnots,
1075 Curve1Poles,
1076 FlatKnots,
1077 2*Curve1->Degree(),
1078 NewPoles,
1079 Status
1080 );
1081 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1082 BSplCLib::FunctionReparameterise(ev,
1083 Curve1->Degree(),
1084 Curve1FlatKnots,
1085 Curve1Weights,
1086 FlatKnots,
1087 2*Curve1->Degree(),
1088 NewWeights,
1089 Status
1090 );
1091// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1092// Curve1->Degree(),
1093// Curve1FlatKnots,
1094// Curve1Poles,
1095// FlatKnots,
1096// 2*Curve1->Degree(),
1097// NewPoles,
1098// Status
1099// );
1100// TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1101// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1102// Curve1->Degree(),
1103// Curve1FlatKnots,
1104// Curve1Weights,
1105// FlatKnots,
1106// 2*Curve1->Degree(),
1107// NewWeights,
1108// Status
1109// );
1110 for (ii=1;ii<=NewPoles.Length();ii++)
1111 for (jj=1;jj<=2;jj++)
1112 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1113 Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1114 }
1115 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1116 fusion=C.Add(Curve1,
1117 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1118 if (fusion==Standard_False)
1119 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1120 Curve2=C.BSplineCurve();
1121 }
7fd59977 1122 Curve2->SetPeriodic(); //1 seule courbe C1
96a95605 1123 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
7fd59977 1124 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1125 Precision::Confusion());
1126 ArrayOfConcatenated->SetValue(0,Curve2);
1127 }
1128
1129 else
1130 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1131 nb_vertexG1=0; //continuite interne G1
1132
1133 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1134 nb_vertexG1++;
1135
1136 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1137 Curve1=ArrayOfCurves(j);
1138
1139 if (index==j) //initialisation en debut de groupe
1140 ArrayOfConcatenated->SetValue(i,Curve1);
1141 else{
1142 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1143 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1144 if (fusion==Standard_False)
1145 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1146 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1147 }
1148 }
1149 index=index+1+nb_vertexG1;
1150 }
1151}
1152//=======================================================================
1153//function : ConcatC1
1154//purpose :
1155//=======================================================================
1156
1157void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1158 const TColStd_Array1OfReal& ArrayOfToler,
1159 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1160 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1161 const Standard_Boolean ClosedFlag,
1162 const Standard_Real ClosedTolerance)
1163{
1164 ConcatC1(ArrayOfCurves,
1165 ArrayOfToler,
1166 ArrayOfIndices,
1167 ArrayOfConcatenated,
1168 ClosedFlag,
1169 ClosedTolerance,
1170 Precision::Angular()) ;
1171}
1172//=======================================================================
1173//function : ConcatC1
1174//purpose :
1175//=======================================================================
1176
1177void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1178 const TColStd_Array1OfReal& ArrayOfToler,
1179 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1180 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1181 const Standard_Boolean ClosedFlag,
1182 const Standard_Real ClosedTolerance,
1183 const Standard_Real AngularTolerance)
1184
1185{Standard_Integer nb_curve=ArrayOfCurves.Length(),
1186 nb_vertexG1,
1187 nb_group=0,
1188 index=0,i,ii,j,jj,
1189 indexmin,
1190 nb_vertex_group0=0;
1191 Standard_Real lambda, //coeff de raccord G1
1192 First,PreLast=0;
1193 gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs
1194 gp_Pnt2d Pint;
1195 Handle(Geom2d_BSplineCurve) Curve1,Curve2;
1196 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords
1197 TColStd_Array1OfReal local_tolerance(0,
1198 ArrayOfToler.Length()-1) ;
1199
1200
1201
1202 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1203 local_tolerance(i) = ArrayOfToler(i) ;
1204 }
1205 for (i=0 ;i<nb_curve; i++){
1206 if (i >= 1){
1207 First=ArrayOfCurves(i)->FirstParameter();
1208 if (Continuity(ArrayOfCurves(i-1),
1209 ArrayOfCurves(i),
1210 PreLast,First,
1211 Standard_True,
1212 Standard_True,
1213 ArrayOfToler(i-1),
1214 AngularTolerance)<GeomAbs_C0)
1215 Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ; //renvoi d'une erreur
1216 else{
1217 if (Continuity(ArrayOfCurves(i-1),
1218 ArrayOfCurves(i),
1219 PreLast,
1220 First,
1221 Standard_True,
1222 Standard_True,
1223 ArrayOfToler(i-1),
1224 AngularTolerance)>=GeomAbs_G1)
1225 tabG1(i-1)=Standard_True; //True=Continuite G1
1226 else
1227 tabG1(i-1)=Standard_False;
1228 }
1229 }
1230 PreLast=ArrayOfCurves(i)->LastParameter();
1231 }
1232
1233
1234 while (index<=nb_curve-1){ //determination des caracteristiques du Wire
1235 nb_vertexG1=0;
1236 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1237 nb_vertexG1++;
1238 nb_group++;
1239 if (index==0)
1240 nb_vertex_group0=nb_vertexG1;
1241 index=index+1+nb_vertexG1;
1242 }
1243
1244 if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau
1245 nb_group--;
1246 ReorderArrayOfG1(ArrayOfCurves,
1247 local_tolerance,
1248 tabG1,
1249 nb_vertex_group0,
1250 ClosedTolerance);
1251 }
1252
1253 ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group);
1254 ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1255
1256 Standard_Boolean fusion;
1257 Standard_Integer k=0;
1258 index=0;
1259 Pretreatment(ArrayOfCurves);
41194117 1260 Standard_Real aPolynomialCoefficient[3];
7fd59977 1261
1262 if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier
1263 ArrayOfIndices->SetValue(0,0);
1264 ArrayOfIndices->SetValue(1,0);
1265 indexmin=Indexmin(ArrayOfCurves);
1266 if (indexmin!=(ArrayOfCurves.Length()-1))
1267 ReorderArrayOfG1(ArrayOfCurves,
1268 local_tolerance,
1269 tabG1,
1270 indexmin,
1271 ClosedTolerance);
1272 for (j=0;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe
1273 if (NeedToBeTreated(ArrayOfCurves(j))) {
1274 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1275 }
1276 else
1277 Curve1=ArrayOfCurves(j);
1278
1279 if (j==0) //initialisation en debut de groupe
1280 Curve2=Curve1;
1281 else{
1282 if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){
1283 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1284 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1285 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1286 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1287 Curve1->Knots(KnotC1);
1288 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1289 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1290 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1291 Standard_Real tmax,a,b,c,
1292 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1293 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1294 a=(lambda*lambda2-1)/(2*lambda*tmax);
41194117 1295 aPolynomialCoefficient[2] = a;
7fd59977 1296 b=(1/lambda);
41194117 1297 aPolynomialCoefficient[1] = b;
7fd59977 1298 c=umin;
41194117 1299 aPolynomialCoefficient[0] = c;
7fd59977 1300 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1301 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1302 Curve1->Multiplicities(KnotC1Mults);
1303 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1304 KnotC1(1)=0.0;
1305 for (ii=2;ii<=KnotC1.Length();ii++) {
1306// KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1307 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1308 }
1309 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1310 Curve1->Poles(Curve1Poles);
1311
1312 for (ii=1;ii<=Curve1->NbKnots();ii++)
1313 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1314
1315 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1316
1317 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1318 TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1319 Standard_Integer Status;
1320 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1321 Curve1->Weights(Curve1Weights);
1322 for (ii=1;ii<=Curve1->NbPoles();ii++)
1323 for (jj=1;jj<=2;jj++)
1324 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1325//POP pour NT
41194117 1326 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
7fd59977 1327// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1328 BSplCLib::FunctionReparameterise(ev,
1329 Curve1->Degree(),
1330 Curve1FlatKnots,
1331 Curve1Poles,
1332 FlatKnots,
1333 2*Curve1->Degree(),
1334 NewPoles,
1335 Status
1336 );
1337 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1338// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1339 BSplCLib::FunctionReparameterise(ev,
1340 Curve1->Degree(),
1341 Curve1FlatKnots,
1342 Curve1Weights,
1343 FlatKnots,
1344 2*Curve1->Degree(),
1345 NewWeights,
1346 Status
1347 );
1348 for (ii=1;ii<=NewPoles.Length();ii++) {
1349 for (jj=1;jj<=2;jj++)
1350 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1351 }
1352 Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1353 }
1354 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1355 fusion=C.Add(Curve1,
1356 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1357 if (fusion==Standard_False)
1358 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1359 Curve2=C.BSplineCurve();
1360 }
1361 }
7fd59977 1362 Curve2->SetPeriodic(); //1 seule courbe C1
96a95605 1363 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
7fd59977 1364 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1365 Precision::Confusion());
1366 ArrayOfConcatenated->SetValue(0,Curve2);
1367 }
1368
1369 else
1370 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1371 nb_vertexG1=0; //continuite interne G1
1372
1373 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1374 nb_vertexG1++;
1375
1376 if ((!ClosedFlag)||(nb_group==1)){ //remplissage du tableau des indices conserves
1377 k++;
1378 ArrayOfIndices->SetValue(k-1,index);
1379 if (k==nb_group)
1380 ArrayOfIndices->SetValue(k,0);
1381 }
1382 else{
1383 k++;
1384 ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1385 if (k==nb_group)
1386 ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1387 }
1388
1389 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1390 if (NeedToBeTreated(ArrayOfCurves(j)))
1391 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1392 else
1393 Curve1=ArrayOfCurves(j);
1394
1395 if (index==j) //initialisation en debut de groupe
1396 ArrayOfConcatenated->SetValue(i,Curve1);
1397 else{
1398 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1399 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1400 if (fusion==Standard_False)
1401 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1402 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1403 }
1404 }
1405 index=index+1+nb_vertexG1;
1406 }
1407}
1408
1409//=======================================================================
1410//function : C0BSplineToC1BSplineCurve
1411//purpose :
1412//=======================================================================
1413
1414void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS,
1415 const Standard_Real tolerance)
1416
1417{
1418 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1419 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1420 Standard_Integer i,j,nbcurveC1=1;
1421 Standard_Real U1,U2;
1422 Standard_Boolean closed_flag = Standard_False ;
1423 gp_Pnt2d point;
1424 gp_Vec2d V1,V2;
1425 Standard_Boolean fusion;
1426
1427 BS->Knots(BSKnots);
1428 BS->Multiplicities(BSMults);
9e20ed57 1429 for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){
7fd59977 1430 if (BSMults(i)==BS->Degree())
1431 nbcurveC1++;
1432 }
1433
1434 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1435
1436 if (nbcurveC1>1){
1437 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1438 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1439
1440 for (i=0;i<=nbcurveC1-2;i++)
1441 ArrayOfToler(i)=tolerance;
1442 U2=BS->FirstParameter() ;
1443 j=BS->FirstUKnotIndex() + 1 ;
1444 for (i=0;i<nbcurveC1;i++){
1445 U1=U2;
1446
9e20ed57 1447 while (j < BS->LastUKnotIndex() && BSMults(j) < BS->Degree())
1448 j++;
7fd59977 1449
1450 U2=BSKnots(j);
1451 j++;
c04c30b3 1452 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
7fd59977 1453 BSbis->Segment(U1,U2);
1454 ArrayOfCurves(i)=BSbis;
1455 }
1456 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1457 Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated;
1458
1459 BS->D1(BS->FirstParameter(),point,V1); //a verifier
1460 BS->D1(BS->LastParameter(),point,V2);
1461
1462 if ((BS->IsClosed())&&(V1.IsParallel(V2,Precision::Confusion())))
1463 closed_flag = Standard_True ;
1464
1465 Geom2dConvert::ConcatC1(ArrayOfCurves,
1466 ArrayOfToler,
1467 ArrayOfIndices,
1468 ArrayOfConcatenated,
1469 closed_flag,
1470 tolerance);
1471
1472 Geom2dConvert_CompCurveToBSplineCurve
1473 C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(0)));
1474 if (ArrayOfConcatenated->Length()>=2){
1475 for (i=1;i<ArrayOfConcatenated->Length();i++){
1476 fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1477 if (fusion==Standard_False)
1478 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1479 }
1480 }
1481 BS=C.BSplineCurve();
1482 }
1483}
1484//=======================================================================
1485//function : C0BSplineToArrayOfC1BSplineCurve
1486//purpose :
1487//=======================================================================
1488
1489void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1490 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1491 const Standard_Real tolerance)
1492 {
1493 C0BSplineToArrayOfC1BSplineCurve(BS,
1494 tabBS,
1495 tolerance,
1496 Precision::Angular());
1497 }
1498//=======================================================================
1499//function : C0BSplineToArrayOfC1BSplineCurve
1500//purpose :
1501//=======================================================================
1502
1503void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1504 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1505 const Standard_Real AngularTolerance,
1506 const Standard_Real Tolerance)
1507
1508{
1509 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1510 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1511 Standard_Integer i,j,nbcurveC1=1;
1512 Standard_Real U1,U2;
1513 Standard_Boolean closed_flag = Standard_False ;
1514 gp_Pnt2d point;
1515 gp_Vec2d V1,V2;
1516// Standard_Boolean fusion;
1517
1518 BS->Knots(BSKnots);
1519 BS->Multiplicities(BSMults);
1520 for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){
1521 if (BSMults(i)==BS->Degree())
1522 nbcurveC1++;
1523 }
1524
1525 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1526
1527 if (nbcurveC1>1){
1528 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1529 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1530
1531 for (i=0;i<=nbcurveC1-2;i++)
1532 ArrayOfToler(i)=Tolerance;
1533 U2=BS->FirstParameter() ;
1534 j=BS->FirstUKnotIndex()+ 1 ;
1535 for (i=0;i<nbcurveC1;i++){
1536 U1=U2;
1537 while (j < BS->LastUKnotIndex() && BSMults(j)<BS->Degree())
1538 j++;
1539 U2=BSKnots(j);
1540 j++;
c04c30b3 1541 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
7fd59977 1542 BSbis->Segment(U1,U2);
1543 ArrayOfCurves(i)=BSbis;
1544 }
1545
1546 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1547
1548 BS->D1(BS->FirstParameter(),point,V1);
1549 BS->D1(BS->LastParameter(),point,V2);
1550
1551 if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance)))
1552 closed_flag = Standard_True ;
1553
1554 Geom2dConvert::ConcatC1(ArrayOfCurves,
1555 ArrayOfToler,
1556 ArrayOfIndices,
1557 tabBS,
1558 closed_flag,
1559 Tolerance,
1560 AngularTolerance) ;
1561 }
1562 else{
1563 tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0);
1564 tabBS->SetValue(0,BS);
1565 }
1566}
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608