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