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