Warnings on vc14 were eliminated
[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 ();
9775fa61 136 if (FromK1 == ToK2) throw Standard_DomainError();
7fd59977 137 Standard_Integer FirstK = Min (FromK1, ToK2);
138 Standard_Integer LastK = Max (FromK1, ToK2);
9775fa61 139 if (FirstK < TheFirst || LastK > TheLast) throw Standard_OutOfRange();
7fd59977 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();
9775fa61 386 else throw Standard_ConstructionError();
7fd59977 387 }
388
9775fa61 389 else { throw Standard_DomainError("No such curve"); }
7fd59977 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();
9775fa61 452 else throw Standard_ConstructionError();
7fd59977 453 }
454
9775fa61 455 else { throw Standard_DomainError(); }
7fd59977 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
9775fa61 878 throw Standard_Failure("Courbes non jointives");
7fd59977 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)
9775fa61 971 throw Standard_ConstructionError("Geom2dConvert curves not C0") ; //renvoi d'une erreur
7fd59977 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))){
d30895f5 1028 const Standard_Integer aNewCurveDegree = Min(2 * Curve1->Degree(), Geom2d_BSplineCurve::MaxDegree());
7fd59977 1029 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1030 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1031 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1032 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1033 Curve1->Knots(KnotC1);
1034 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1035 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1036 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1037 Standard_Real tmax,a,b,c,
1038 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1039 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1040 a=(lambda*lambda2-1)/(2*lambda*tmax);
41194117 1041 aPolynomialCoefficient[2] = a;
7fd59977 1042 b=(1/lambda);
41194117 1043 aPolynomialCoefficient[1] = b;
7fd59977 1044 c=umin;
41194117 1045 aPolynomialCoefficient[0] = c;
7fd59977 1046 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1047 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1048 Curve1->Multiplicities(KnotC1Mults);
1049 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1050 KnotC1(1)=0.0;
1051 for (ii=2;ii<=KnotC1.Length();ii++) {
1052// KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1053 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1054 }
1055 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1056 Curve1->Poles(Curve1Poles);
1057
1058 for (ii=1;ii<=Curve1->NbKnots();ii++)
1059 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1060
1061 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1062
1063 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1064 TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1065 Standard_Integer Status;
1066 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1067 Curve1->Weights(Curve1Weights);
1068 for (ii=1;ii<=Curve1->NbPoles();ii++)
1069 for (jj=1;jj<=2;jj++)
1070 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1071//POP pour NT
41194117 1072 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
7fd59977 1073 BSplCLib::FunctionReparameterise(ev,
1074 Curve1->Degree(),
1075 Curve1FlatKnots,
1076 Curve1Poles,
1077 FlatKnots,
d30895f5 1078 aNewCurveDegree,
7fd59977 1079 NewPoles,
1080 Status
1081 );
1082 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1083 BSplCLib::FunctionReparameterise(ev,
1084 Curve1->Degree(),
1085 Curve1FlatKnots,
1086 Curve1Weights,
1087 FlatKnots,
d30895f5 1088 aNewCurveDegree,
7fd59977 1089 NewWeights,
1090 Status
1091 );
1092// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1093// Curve1->Degree(),
1094// Curve1FlatKnots,
1095// Curve1Poles,
1096// FlatKnots,
1097// 2*Curve1->Degree(),
1098// NewPoles,
1099// Status
1100// );
1101// TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1102// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1103// Curve1->Degree(),
1104// Curve1FlatKnots,
1105// Curve1Weights,
1106// FlatKnots,
1107// 2*Curve1->Degree(),
1108// NewWeights,
1109// Status
1110// );
1111 for (ii=1;ii<=NewPoles.Length();ii++)
1112 for (jj=1;jj<=2;jj++)
1113 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
d30895f5 1114 Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree);
7fd59977 1115 }
a9dde4a3 1116 Geom2dConvert_CompCurveToBSplineCurve C(Curve2);
7fd59977 1117 fusion=C.Add(Curve1,
1118 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1119 if (fusion==Standard_False)
9775fa61 1120 throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
7fd59977 1121 Curve2=C.BSplineCurve();
1122 }
7fd59977 1123 Curve2->SetPeriodic(); //1 seule courbe C1
96a95605 1124 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
7fd59977 1125 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1126 Precision::Confusion());
1127 ArrayOfConcatenated->SetValue(0,Curve2);
1128 }
1129
1130 else
1131 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1132 nb_vertexG1=0; //continuite interne G1
1133
1134 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1135 nb_vertexG1++;
1136
1137 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1138 Curve1=ArrayOfCurves(j);
1139
1140 if (index==j) //initialisation en debut de groupe
1141 ArrayOfConcatenated->SetValue(i,Curve1);
1142 else{
a9dde4a3 1143 Geom2dConvert_CompCurveToBSplineCurve C(ArrayOfConcatenated->Value(i));
7fd59977 1144 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1145 if (fusion==Standard_False)
9775fa61 1146 throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
7fd59977 1147 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1148 }
1149 }
1150 index=index+1+nb_vertexG1;
1151 }
1152}
1153//=======================================================================
1154//function : ConcatC1
1155//purpose :
1156//=======================================================================
1157
1158void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1159 const TColStd_Array1OfReal& ArrayOfToler,
1160 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1161 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1162 const Standard_Boolean ClosedFlag,
1163 const Standard_Real ClosedTolerance)
1164{
1165 ConcatC1(ArrayOfCurves,
1166 ArrayOfToler,
1167 ArrayOfIndices,
1168 ArrayOfConcatenated,
1169 ClosedFlag,
1170 ClosedTolerance,
1171 Precision::Angular()) ;
1172}
1173//=======================================================================
1174//function : ConcatC1
1175//purpose :
1176//=======================================================================
1177
1178void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1179 const TColStd_Array1OfReal& ArrayOfToler,
1180 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1181 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1182 const Standard_Boolean ClosedFlag,
1183 const Standard_Real ClosedTolerance,
1184 const Standard_Real AngularTolerance)
1185
1186{Standard_Integer nb_curve=ArrayOfCurves.Length(),
1187 nb_vertexG1,
1188 nb_group=0,
1189 index=0,i,ii,j,jj,
1190 indexmin,
1191 nb_vertex_group0=0;
1192 Standard_Real lambda, //coeff de raccord G1
1193 First,PreLast=0;
1194 gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs
1195 gp_Pnt2d Pint;
1196 Handle(Geom2d_BSplineCurve) Curve1,Curve2;
1197 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords
1198 TColStd_Array1OfReal local_tolerance(0,
1199 ArrayOfToler.Length()-1) ;
1200
1201
1202
1203 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1204 local_tolerance(i) = ArrayOfToler(i) ;
1205 }
1206 for (i=0 ;i<nb_curve; i++){
1207 if (i >= 1){
1208 First=ArrayOfCurves(i)->FirstParameter();
1209 if (Continuity(ArrayOfCurves(i-1),
1210 ArrayOfCurves(i),
1211 PreLast,First,
1212 Standard_True,
1213 Standard_True,
1214 ArrayOfToler(i-1),
1215 AngularTolerance)<GeomAbs_C0)
9775fa61 1216 throw Standard_ConstructionError("Geom2dConvert curves not C0") ; //renvoi d'une erreur
7fd59977 1217 else{
1218 if (Continuity(ArrayOfCurves(i-1),
1219 ArrayOfCurves(i),
1220 PreLast,
1221 First,
1222 Standard_True,
1223 Standard_True,
1224 ArrayOfToler(i-1),
1225 AngularTolerance)>=GeomAbs_G1)
1226 tabG1(i-1)=Standard_True; //True=Continuite G1
1227 else
1228 tabG1(i-1)=Standard_False;
1229 }
1230 }
1231 PreLast=ArrayOfCurves(i)->LastParameter();
1232 }
1233
1234
1235 while (index<=nb_curve-1){ //determination des caracteristiques du Wire
1236 nb_vertexG1=0;
1237 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1238 nb_vertexG1++;
1239 nb_group++;
1240 if (index==0)
1241 nb_vertex_group0=nb_vertexG1;
1242 index=index+1+nb_vertexG1;
1243 }
1244
1245 if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau
1246 nb_group--;
1247 ReorderArrayOfG1(ArrayOfCurves,
1248 local_tolerance,
1249 tabG1,
1250 nb_vertex_group0,
1251 ClosedTolerance);
1252 }
1253
1254 ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group);
1255 ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1256
1257 Standard_Boolean fusion;
1258 Standard_Integer k=0;
1259 index=0;
1260 Pretreatment(ArrayOfCurves);
41194117 1261 Standard_Real aPolynomialCoefficient[3];
7fd59977 1262
1263 if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier
1264 ArrayOfIndices->SetValue(0,0);
1265 ArrayOfIndices->SetValue(1,0);
1266 indexmin=Indexmin(ArrayOfCurves);
1267 if (indexmin!=(ArrayOfCurves.Length()-1))
1268 ReorderArrayOfG1(ArrayOfCurves,
1269 local_tolerance,
1270 tabG1,
1271 indexmin,
1272 ClosedTolerance);
1273 for (j=0;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe
1274 if (NeedToBeTreated(ArrayOfCurves(j))) {
1275 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1276 }
1277 else
1278 Curve1=ArrayOfCurves(j);
1279
d30895f5 1280 const Standard_Integer aNewCurveDegree = Min(2 * Curve1->Degree(), Geom2d_BSplineCurve::MaxDegree());
1281
7fd59977 1282 if (j==0) //initialisation en debut de groupe
1283 Curve2=Curve1;
1284 else{
1285 if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){
1286 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1287 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1288 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1289 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1290 Curve1->Knots(KnotC1);
1291 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1292 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1293 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1294 Standard_Real tmax,a,b,c,
1295 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1296 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1297 a=(lambda*lambda2-1)/(2*lambda*tmax);
41194117 1298 aPolynomialCoefficient[2] = a;
7fd59977 1299 b=(1/lambda);
41194117 1300 aPolynomialCoefficient[1] = b;
7fd59977 1301 c=umin;
41194117 1302 aPolynomialCoefficient[0] = c;
7fd59977 1303 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1304 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1305 Curve1->Multiplicities(KnotC1Mults);
1306 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1307 KnotC1(1)=0.0;
1308 for (ii=2;ii<=KnotC1.Length();ii++) {
1309// KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1310 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1311 }
1312 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1313 Curve1->Poles(Curve1Poles);
1314
1315 for (ii=1;ii<=Curve1->NbKnots();ii++)
1316 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1317
1318 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1319
1320 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
d30895f5 1321 TColgp_Array1OfPnt2d NewPoles(1, FlatKnots.Length() - (aNewCurveDegree + 1));
7fd59977 1322 Standard_Integer Status;
1323 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1324 Curve1->Weights(Curve1Weights);
1325 for (ii=1;ii<=Curve1->NbPoles();ii++)
1326 for (jj=1;jj<=2;jj++)
1327 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1328//POP pour NT
41194117 1329 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
7fd59977 1330// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1331 BSplCLib::FunctionReparameterise(ev,
1332 Curve1->Degree(),
1333 Curve1FlatKnots,
1334 Curve1Poles,
1335 FlatKnots,
d30895f5 1336 aNewCurveDegree,
7fd59977 1337 NewPoles,
1338 Status
1339 );
d30895f5 1340 TColStd_Array1OfReal NewWeights(1, FlatKnots.Length() - (aNewCurveDegree + 1));
7fd59977 1341// BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1342 BSplCLib::FunctionReparameterise(ev,
1343 Curve1->Degree(),
1344 Curve1FlatKnots,
1345 Curve1Weights,
1346 FlatKnots,
d30895f5 1347 aNewCurveDegree,
7fd59977 1348 NewWeights,
1349 Status
1350 );
1351 for (ii=1;ii<=NewPoles.Length();ii++) {
1352 for (jj=1;jj<=2;jj++)
1353 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1354 }
d30895f5 1355 Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree);
7fd59977 1356 }
a9dde4a3 1357 Geom2dConvert_CompCurveToBSplineCurve C(Curve2);
7fd59977 1358 fusion=C.Add(Curve1,
1359 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1360 if (fusion==Standard_False)
9775fa61 1361 throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
7fd59977 1362 Curve2=C.BSplineCurve();
1363 }
1364 }
7fd59977 1365 Curve2->SetPeriodic(); //1 seule courbe C1
96a95605 1366 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
7fd59977 1367 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1368 Precision::Confusion());
1369 ArrayOfConcatenated->SetValue(0,Curve2);
1370 }
1371
1372 else
1373 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1374 nb_vertexG1=0; //continuite interne G1
1375
1376 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1377 nb_vertexG1++;
1378
1379 if ((!ClosedFlag)||(nb_group==1)){ //remplissage du tableau des indices conserves
1380 k++;
1381 ArrayOfIndices->SetValue(k-1,index);
1382 if (k==nb_group)
1383 ArrayOfIndices->SetValue(k,0);
1384 }
1385 else{
1386 k++;
1387 ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1388 if (k==nb_group)
1389 ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1390 }
1391
1392 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1393 if (NeedToBeTreated(ArrayOfCurves(j)))
1394 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1395 else
1396 Curve1=ArrayOfCurves(j);
1397
1398 if (index==j) //initialisation en debut de groupe
1399 ArrayOfConcatenated->SetValue(i,Curve1);
1400 else{
a9dde4a3 1401 Geom2dConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
7fd59977 1402 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1403 if (fusion==Standard_False)
9775fa61 1404 throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
7fd59977 1405 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1406 }
1407 }
1408 index=index+1+nb_vertexG1;
1409 }
1410}
1411
1412//=======================================================================
1413//function : C0BSplineToC1BSplineCurve
1414//purpose :
1415//=======================================================================
1416
1417void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS,
1418 const Standard_Real tolerance)
1419
1420{
1421 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1422 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1423 Standard_Integer i,j,nbcurveC1=1;
1424 Standard_Real U1,U2;
1425 Standard_Boolean closed_flag = Standard_False ;
d30895f5 1426 gp_Pnt2d point1, point2;
7fd59977 1427 gp_Vec2d V1,V2;
1428 Standard_Boolean fusion;
1429
1430 BS->Knots(BSKnots);
1431 BS->Multiplicities(BSMults);
9e20ed57 1432 for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){
7fd59977 1433 if (BSMults(i)==BS->Degree())
1434 nbcurveC1++;
1435 }
1436
1437 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1438
1439 if (nbcurveC1>1){
1440 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1441 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1442
1443 for (i=0;i<=nbcurveC1-2;i++)
1444 ArrayOfToler(i)=tolerance;
1445 U2=BS->FirstParameter() ;
1446 j=BS->FirstUKnotIndex() + 1 ;
1447 for (i=0;i<nbcurveC1;i++){
1448 U1=U2;
1449
9e20ed57 1450 while (j < BS->LastUKnotIndex() && BSMults(j) < BS->Degree())
1451 j++;
7fd59977 1452
1453 U2=BSKnots(j);
1454 j++;
c04c30b3 1455 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
7fd59977 1456 BSbis->Segment(U1,U2);
1457 ArrayOfCurves(i)=BSbis;
1458 }
d30895f5 1459
1460 const Standard_Real anAngularToler = 1.0e-7;
7fd59977 1461 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1462 Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated;
1463
d30895f5 1464 BS->D1(BS->FirstParameter(),point1,V1); //a verifier
1465 BS->D1(BS->LastParameter(),point2,V2);
7fd59977 1466
d30895f5 1467 if ((point1.SquareDistance(point2) < gp::Resolution()) &&
1468 (V1.IsParallel(V2, anAngularToler)))
1469 {
1470 closed_flag = Standard_True;
1471 }
1472
7fd59977 1473 Geom2dConvert::ConcatC1(ArrayOfCurves,
1474 ArrayOfToler,
1475 ArrayOfIndices,
1476 ArrayOfConcatenated,
1477 closed_flag,
1478 tolerance);
1479
a9dde4a3 1480 Geom2dConvert_CompCurveToBSplineCurve C(ArrayOfConcatenated->Value(0));
7fd59977 1481 if (ArrayOfConcatenated->Length()>=2){
1482 for (i=1;i<ArrayOfConcatenated->Length();i++){
2dad173d 1483 fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance, Standard_True);
7fd59977 1484 if (fusion==Standard_False)
9775fa61 1485 throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
7fd59977 1486 }
1487 }
1488 BS=C.BSplineCurve();
1489 }
1490}
1491//=======================================================================
1492//function : C0BSplineToArrayOfC1BSplineCurve
1493//purpose :
1494//=======================================================================
1495
1496void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1497 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1498 const Standard_Real tolerance)
1499 {
1500 C0BSplineToArrayOfC1BSplineCurve(BS,
1501 tabBS,
1502 tolerance,
1503 Precision::Angular());
1504 }
1505//=======================================================================
1506//function : C0BSplineToArrayOfC1BSplineCurve
1507//purpose :
1508//=======================================================================
1509
1510void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1511 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1512 const Standard_Real AngularTolerance,
1513 const Standard_Real Tolerance)
1514
1515{
1516 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1517 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1518 Standard_Integer i,j,nbcurveC1=1;
1519 Standard_Real U1,U2;
1520 Standard_Boolean closed_flag = Standard_False ;
d30895f5 1521 gp_Pnt2d point1, point2;
7fd59977 1522 gp_Vec2d V1,V2;
1523// Standard_Boolean fusion;
1524
1525 BS->Knots(BSKnots);
1526 BS->Multiplicities(BSMults);
1527 for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){
1528 if (BSMults(i)==BS->Degree())
1529 nbcurveC1++;
1530 }
1531
1532 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1533
1534 if (nbcurveC1>1){
1535 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1536 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1537
1538 for (i=0;i<=nbcurveC1-2;i++)
1539 ArrayOfToler(i)=Tolerance;
1540 U2=BS->FirstParameter() ;
1541 j=BS->FirstUKnotIndex()+ 1 ;
1542 for (i=0;i<nbcurveC1;i++){
1543 U1=U2;
1544 while (j < BS->LastUKnotIndex() && BSMults(j)<BS->Degree())
1545 j++;
1546 U2=BSKnots(j);
1547 j++;
c04c30b3 1548 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
7fd59977 1549 BSbis->Segment(U1,U2);
1550 ArrayOfCurves(i)=BSbis;
1551 }
1552
1553 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1554
d30895f5 1555 BS->D1(BS->FirstParameter(),point1,V1);
1556 BS->D1(BS->LastParameter(),point2,V2);
7fd59977 1557
d30895f5 1558 if (((point1.SquareDistance(point2) < gp::Resolution())) &&
1559 (V1.IsParallel(V2, AngularTolerance)))
1560 {
1561 closed_flag = Standard_True;
1562 }
7fd59977 1563
1564 Geom2dConvert::ConcatC1(ArrayOfCurves,
1565 ArrayOfToler,
1566 ArrayOfIndices,
1567 tabBS,
1568 closed_flag,
1569 Tolerance,
1570 AngularTolerance) ;
1571 }
1572 else{
1573 tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0);
1574 tabBS->SetValue(0,BS);
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
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618