7fd59977 |
1 | // File GeomConvert.cxx |
2 | // Jean-Claude Vauthier Novembre 1991 |
3 | // Passage sur C1 Aout 1992 et ajout transformation Bezier->BSpline + Debug |
4 | // Modif JCV correction bug le 2/08/1993 |
5 | |
6 | #include <GeomConvert.ixx> |
7 | |
8 | #include <BSplCLib.hxx> |
9 | #include <Convert_ConicToBSplineCurve.hxx> |
10 | #include <Convert_CircleToBSplineCurve.hxx> |
11 | #include <Convert_EllipseToBSplineCurve.hxx> |
12 | #include <Convert_HyperbolaToBSplineCurve.hxx> |
13 | #include <Convert_ParabolaToBSplineCurve.hxx> |
14 | |
15 | |
16 | #include <gp.hxx> |
17 | |
18 | #include <gp_Circ2d.hxx> |
19 | #include <gp_Elips2d.hxx> |
20 | #include <gp_Parab2d.hxx> |
21 | #include <gp_Hypr2d.hxx> |
22 | #include <gp_Pnt2d.hxx> |
23 | #include <gp_Lin.hxx> |
24 | #include <gp_Ax3.hxx> |
25 | #include <gp_Trsf.hxx> |
26 | #include <gp_Vec.hxx> |
27 | #include <gp_Pnt.hxx> |
28 | |
29 | #include <Geom2d_BSplineCurve.hxx> |
30 | |
31 | #include <Geom_Curve.hxx> |
32 | #include <Geom_Line.hxx> |
33 | #include <GeomLProp.hxx> |
34 | #include <Geom_Circle.hxx> |
35 | #include <Geom_Ellipse.hxx> |
36 | #include <Geom_Hyperbola.hxx> |
37 | #include <Geom_Parabola.hxx> |
38 | #include <Geom_Geometry.hxx> |
39 | #include <Geom_BSplineCurve.hxx> |
40 | #include <Geom_BezierCurve.hxx> |
41 | #include <Geom_TrimmedCurve.hxx> |
42 | #include <Geom_Conic.hxx> |
43 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
44 | |
45 | #include <TColStd_Array1OfReal.hxx> |
46 | #include <TColStd_Array1OfInteger.hxx> |
47 | #include <TColStd_HArray1OfReal.hxx> |
48 | #include <TColStd_HArray1OfInteger.hxx> |
49 | #include <TColStd_Array1OfBoolean.hxx> |
50 | #include <TColgp_Array1OfPnt.hxx> |
51 | #include <TColgp_Array1OfPnt2d.hxx> |
52 | #include <TColGeom_Array1OfCurve.hxx> |
53 | |
54 | #include <Hermit.hxx> |
55 | |
56 | #include <PLib.hxx> |
57 | |
58 | #include <Precision.hxx> |
59 | |
60 | #include <Standard_DomainError.hxx> |
61 | #include <Standard_ConstructionError.hxx> |
62 | #include <Geom_OffsetCurve.hxx> |
63 | #include <GeomConvert_ApproxCurve.hxx> |
64 | |
65 | #include <ElCLib.hxx> |
66 | |
67 | //======================================================================= |
68 | //function : BSplineCurveBuilder |
69 | //purpose : |
70 | //======================================================================= |
71 | |
72 | static Handle(Geom_BSplineCurve) BSplineCurveBuilder |
73 | (const Handle(Geom_Conic)& TheConic, |
74 | const Convert_ConicToBSplineCurve& Convert) |
75 | |
76 | { |
77 | Handle(Geom_BSplineCurve) TheCurve; |
78 | Standard_Integer NbPoles = Convert.NbPoles(); |
79 | Standard_Integer NbKnots = Convert.NbKnots(); |
80 | TColgp_Array1OfPnt Poles (1, NbPoles); |
81 | TColStd_Array1OfReal Weights (1, NbPoles); |
82 | TColStd_Array1OfReal Knots (1, NbKnots); |
83 | TColStd_Array1OfInteger Mults (1, NbKnots); |
84 | Standard_Integer i; |
85 | gp_Pnt2d P2d; |
86 | gp_Pnt P3d; |
87 | for (i = 1; i <= NbPoles; i++) { |
88 | P2d = Convert.Pole (i); |
89 | P3d.SetCoord (P2d.X(), P2d.Y(), 0.0); |
90 | Poles (i) = P3d; |
91 | Weights (i) = Convert.Weight (i); |
92 | } |
93 | for (i = 1; i <= NbKnots; i++) { |
94 | Knots (i) = Convert.Knot (i); |
95 | Mults (i) = Convert.Multiplicity (i); |
96 | } |
97 | TheCurve = |
98 | new Geom_BSplineCurve (Poles, Weights, Knots, Mults, |
99 | Convert.Degree(), Convert.IsPeriodic()); |
100 | gp_Trsf T; |
101 | T.SetTransformation (TheConic->Position(), gp::XOY()); |
102 | Handle(Geom_BSplineCurve) Cres; |
103 | Cres = Handle(Geom_BSplineCurve)::DownCast(TheCurve->Transformed (T)); |
104 | return Cres; |
105 | } |
106 | |
107 | |
108 | |
109 | //======================================================================= |
110 | //function : SplitBSplineCurve |
111 | //purpose : |
112 | //======================================================================= |
113 | |
114 | Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve |
115 | (const Handle(Geom_BSplineCurve)& C, |
116 | const Standard_Integer FromK1, |
117 | const Standard_Integer ToK2, |
118 | const Standard_Boolean SameOrientation) |
119 | { |
120 | Standard_Integer TheFirst = C->FirstUKnotIndex (); |
121 | Standard_Integer TheLast = C->LastUKnotIndex (); |
122 | if (FromK1 == ToK2) Standard_DomainError::Raise(); |
123 | Standard_Integer FirstK = Min (FromK1, ToK2); |
124 | Standard_Integer LastK = Max (FromK1, ToK2); |
125 | if (FirstK < TheFirst || LastK > TheLast) Standard_DomainError::Raise(); |
126 | |
127 | Handle(Geom_BSplineCurve) C1 |
128 | = Handle(Geom_BSplineCurve)::DownCast(C->Copy ()); |
129 | |
130 | C1->Segment( C->Knot(FirstK),C->Knot(LastK)); |
131 | |
132 | if (C->IsPeriodic()) { |
133 | if (!SameOrientation) C1->Reverse(); |
134 | } |
135 | else { |
136 | if (FromK1 > ToK2) C1->Reverse(); |
137 | } |
138 | return C1; |
139 | } |
140 | |
141 | |
142 | //======================================================================= |
143 | //function : SplitBSplineCurve |
144 | //purpose : |
145 | //======================================================================= |
146 | |
147 | Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve |
148 | (const Handle(Geom_BSplineCurve)& C, |
149 | const Standard_Real FromU1, |
150 | const Standard_Real ToU2, |
151 | const Standard_Real , //ParametricTolerance, |
152 | const Standard_Boolean SameOrientation ) |
153 | { |
154 | Standard_Real FirstU = Min( FromU1, ToU2); |
155 | Standard_Real LastU = Max( FromU1, ToU2); |
156 | |
157 | Handle (Geom_BSplineCurve) C1 |
158 | = Handle(Geom_BSplineCurve)::DownCast(C->Copy()); |
159 | |
160 | C1->Segment(FirstU, LastU); |
161 | |
162 | if (C->IsPeriodic()) { |
163 | if (!SameOrientation) C1->Reverse(); |
164 | } |
165 | else { |
166 | if (FromU1 > ToU2) C1->Reverse(); |
167 | } |
168 | |
169 | return C1; |
170 | } |
171 | |
172 | |
173 | |
174 | |
175 | //======================================================================= |
176 | //function : CurveToBSplineCurve |
177 | //purpose : |
178 | //======================================================================= |
179 | |
180 | Handle(Geom_BSplineCurve) GeomConvert::CurveToBSplineCurve |
181 | (const Handle(Geom_Curve)& C, |
182 | const Convert_ParameterisationType Parameterisation) |
183 | { |
184 | Handle (Geom_BSplineCurve) TheCurve; |
185 | |
186 | if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { |
187 | Handle(Geom_Curve) Curv; |
188 | Handle(Geom_TrimmedCurve) Ctrim = Handle(Geom_TrimmedCurve)::DownCast(C); |
189 | Curv = Ctrim->BasisCurve(); |
190 | Standard_Real U1 = Ctrim->FirstParameter(); |
191 | Standard_Real U2 = Ctrim->LastParameter(); |
192 | |
193 | // Si la courbe n'est pas vraiment restreinte, on ne risque pas |
194 | // le Raise dans le BS->Segment. |
195 | if (!Curv->IsPeriodic()) { |
196 | if (U1 < Curv->FirstParameter()) |
197 | U1 = Curv->FirstParameter(); |
198 | if (U2 > Curv->LastParameter()) |
199 | U2 = Curv->LastParameter(); |
200 | } |
201 | |
202 | if (Curv->IsKind(STANDARD_TYPE(Geom_Line))) { |
203 | gp_Pnt Pdeb = Ctrim->StartPoint(); |
204 | gp_Pnt Pfin = Ctrim->EndPoint(); |
205 | TColgp_Array1OfPnt Poles (1, 2); |
206 | Poles (1) = Pdeb; |
207 | Poles (2) = Pfin; |
208 | TColStd_Array1OfReal Knots (1, 2); |
209 | Knots (1) = Ctrim->FirstParameter (); |
210 | Knots (2) = Ctrim->LastParameter (); |
211 | TColStd_Array1OfInteger Mults (1, 2); |
212 | Mults (1) = 2; |
213 | Mults (2) = 2; |
214 | Standard_Integer Degree = 1; |
215 | TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree); |
216 | } |
217 | |
218 | else if (Curv->IsKind(STANDARD_TYPE(Geom_Circle))) { |
219 | Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(Curv); |
220 | gp_Circ2d C2d (gp::OX2d(), TheConic->Radius()); |
221 | if(Parameterisation != Convert_RationalC1) { |
222 | Convert_CircleToBSplineCurve Convert (C2d, |
223 | U1, |
224 | U2, |
225 | Parameterisation); |
226 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
227 | } |
228 | else { |
229 | if(U2 - U1 < 6.) { |
230 | Convert_CircleToBSplineCurve Convert (C2d, |
231 | U1, |
232 | U2, |
233 | Parameterisation); |
234 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
235 | } |
236 | else { // split circle to avoide numerical |
237 | // overflow when U2 - U1 =~ 2*PI |
238 | |
239 | Standard_Real Umed = (U1 + U2) * .5; |
240 | Convert_CircleToBSplineCurve Convert1 (C2d, |
241 | U1, |
242 | Umed, |
243 | Parameterisation); |
244 | |
245 | Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1); |
246 | |
247 | Convert_CircleToBSplineCurve Convert2 (C2d, |
248 | Umed, |
249 | U2, |
250 | Parameterisation); |
251 | |
252 | Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2); |
253 | |
254 | GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1, |
255 | Parameterisation); |
256 | |
257 | CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True); |
258 | |
259 | |
260 | TheCurve = CCTBSpl.BSplineCurve(); |
261 | } |
262 | } |
263 | |
264 | } |
265 | |
266 | else if (Curv->IsKind(STANDARD_TYPE(Geom_Ellipse))) { |
267 | Handle(Geom_Ellipse) TheConic = Handle(Geom_Ellipse)::DownCast(Curv); |
268 | gp_Elips2d E2d (gp::OX2d(), |
269 | TheConic->MajorRadius(), |
270 | TheConic->MinorRadius()); |
271 | if(Parameterisation != Convert_RationalC1) { |
272 | Convert_EllipseToBSplineCurve Convert (E2d, |
273 | U1, |
274 | U2, |
275 | Parameterisation); |
276 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
277 | } |
278 | else { |
279 | if(U2 - U1 < 6.) { |
280 | Convert_EllipseToBSplineCurve Convert (E2d, |
281 | U1, |
282 | U2, |
283 | Parameterisation); |
284 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
285 | } |
286 | else { // split ellipse to avoide numerical |
287 | // overflow when U2 - U1 =~ 2*PI |
288 | |
289 | Standard_Real Umed = (U1 + U2) * .5; |
290 | Convert_EllipseToBSplineCurve Convert1 (E2d, |
291 | U1, |
292 | Umed, |
293 | Parameterisation); |
294 | |
295 | Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1); |
296 | |
297 | Convert_EllipseToBSplineCurve Convert2 (E2d, |
298 | Umed, |
299 | U2, |
300 | Parameterisation); |
301 | |
302 | Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2); |
303 | |
304 | GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1, |
305 | Parameterisation); |
306 | |
307 | CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True); |
308 | |
309 | |
310 | TheCurve = CCTBSpl.BSplineCurve(); |
311 | } |
312 | } |
313 | } |
314 | |
315 | else if (Curv->IsKind(STANDARD_TYPE(Geom_Hyperbola))) { |
316 | Handle(Geom_Hyperbola) TheConic = Handle(Geom_Hyperbola)::DownCast(Curv); |
317 | gp_Hypr2d H2d (gp::OX2d(), |
318 | TheConic->MajorRadius(), TheConic->MinorRadius()); |
319 | Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2); |
320 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
321 | } |
322 | |
323 | else if (Curv->IsKind(STANDARD_TYPE(Geom_Parabola))) { |
324 | Handle(Geom_Parabola) TheConic = Handle(Geom_Parabola)::DownCast(Curv); |
325 | gp_Parab2d Prb2d (gp::OX2d(), TheConic->Focal()); |
326 | Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2); |
327 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
328 | } |
329 | |
330 | else if (Curv->IsKind (STANDARD_TYPE(Geom_BezierCurve))) { |
331 | |
332 | Handle(Geom_BezierCurve) CBez |
333 | = Handle(Geom_BezierCurve)::DownCast(Curv->Copy()); |
334 | CBez->Segment (U1, U2); |
335 | Standard_Integer NbPoles = CBez->NbPoles(); |
336 | Standard_Integer Degree = CBez->Degree(); |
337 | TColgp_Array1OfPnt Poles (1, NbPoles); |
338 | TColStd_Array1OfReal Knots (1, 2); |
339 | TColStd_Array1OfInteger Mults (1, 2); |
340 | Knots (1) = 0.0; |
341 | Knots (2) = 1.0; |
342 | Mults (1) = Degree + 1; |
343 | Mults (2) = Degree + 1; |
344 | CBez->Poles (Poles); |
345 | if (CBez->IsRational()) { |
346 | TColStd_Array1OfReal Weights (1, NbPoles); |
347 | CBez->Weights (Weights); |
348 | TheCurve = |
349 | new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree); |
350 | } |
351 | else { |
352 | TheCurve = |
353 | new Geom_BSplineCurve (Poles, Knots, Mults, Degree); |
354 | } |
355 | } |
356 | else if (Curv->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) { |
357 | TheCurve = Handle(Geom_BSplineCurve)::DownCast(Curv->Copy()); |
358 | //// modified by jgv, 14.01.05 for OCC7355 //// |
359 | if (TheCurve->IsPeriodic()) |
360 | { |
361 | Standard_Real Uf = TheCurve->FirstParameter(); |
362 | Standard_Real Ul = TheCurve->LastParameter(); |
363 | ElCLib::AdjustPeriodic( Uf, Ul, Precision::Confusion(), U1, U2 ); |
364 | if (Abs(U1 - Uf) <= Precision::Confusion() && |
365 | Abs(U2 - Ul) <= Precision::Confusion()) |
366 | TheCurve->SetNotPeriodic(); |
367 | } |
368 | /////////////////////////////////////////////// |
369 | TheCurve->Segment(U1,U2); |
370 | } |
371 | else if (Curv->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) { |
372 | Standard_Real Tol3d = 1.e-4; |
373 | GeomAbs_Shape Order = GeomAbs_C2; |
374 | Standard_Integer MaxSegments = 16, MaxDegree = 14; |
375 | GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, |
376 | MaxSegments, MaxDegree); |
377 | if (ApprCOffs.HasResult()) |
378 | TheCurve = ApprCOffs.Curve(); |
379 | else Standard_ConstructionError::Raise(); |
380 | } |
381 | else { Standard_DomainError::Raise("No such curve"); } |
382 | } |
383 | |
384 | else { |
385 | if (C->IsKind(STANDARD_TYPE(Geom_Ellipse))) { |
386 | Handle(Geom_Ellipse) TheConic= Handle(Geom_Ellipse)::DownCast(C); |
387 | gp_Elips2d E2d (gp::OX2d(), |
388 | TheConic->MajorRadius(), TheConic->MinorRadius()); |
389 | /* if (Parameterisation == Convert_TgtThetaOver2_1 || |
390 | Parameterisation == Convert_TgtThetaOver2_2) { |
391 | Standard_DomainError::Raise(); } |
392 | |
393 | else if ( Parameterisation == Convert_QuasiAngular) { |
394 | Convert_EllipseToBSplineCurve Convert (E2d, |
395 | 0.0e0, |
c6541a0c |
396 | 2.0e0 * M_PI, |
7fd59977 |
397 | Parameterisation); |
398 | |
399 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
400 | TheCurve->SetPeriodic(); |
401 | } |
402 | else {*/ |
403 | Convert_EllipseToBSplineCurve Convert (E2d, |
404 | Parameterisation); |
405 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
406 | TheCurve->SetPeriodic(); // pour polynomial et quasi angular |
407 | // } |
408 | } |
409 | |
410 | else if (C->IsKind(STANDARD_TYPE(Geom_Circle))) { |
411 | Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(C); |
412 | gp_Circ2d C2d (gp::OX2d(), TheConic->Radius()); |
413 | /* if (Parameterisation == Convert_TgtThetaOver2_1 || |
414 | Parameterisation == Convert_TgtThetaOver2_2) { |
415 | Standard_DomainError::Raise(); } |
416 | |
417 | else if ( Parameterisation == Convert_QuasiAngular) { |
418 | Convert_CircleToBSplineCurve Convert (C2d, |
419 | 0.0e0, |
c6541a0c |
420 | 2.0e0 * M_PI, |
7fd59977 |
421 | Parameterisation); |
422 | |
423 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
424 | } |
425 | else {*/ |
426 | Convert_CircleToBSplineCurve Convert (C2d, |
427 | Parameterisation); |
428 | TheCurve = BSplineCurveBuilder (TheConic, Convert); |
429 | TheCurve->SetPeriodic(); |
430 | // } |
431 | } |
432 | |
433 | else if (C->IsKind (STANDARD_TYPE(Geom_BezierCurve))) { |
434 | Handle(Geom_BezierCurve) CBez= Handle(Geom_BezierCurve)::DownCast(C); |
435 | Standard_Integer NbPoles = CBez->NbPoles(); |
436 | Standard_Integer Degree = CBez->Degree(); |
437 | TColgp_Array1OfPnt Poles (1, NbPoles); |
438 | TColStd_Array1OfReal Knots (1, 2); |
439 | TColStd_Array1OfInteger Mults (1, 2); |
440 | Knots (1) = 0.0; |
441 | Knots (2) = 1.0; |
442 | Mults (1) = Degree + 1; |
443 | Mults (2) = Degree + 1; |
444 | CBez->Poles (Poles); |
445 | if (CBez->IsRational()) { |
446 | TColStd_Array1OfReal Weights (1, NbPoles); |
447 | CBez->Weights (Weights); |
448 | TheCurve = |
449 | new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree); |
450 | } |
451 | else { |
452 | TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree); |
453 | } |
454 | } |
455 | |
456 | else if (C->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) { |
457 | TheCurve = Handle(Geom_BSplineCurve)::DownCast(C->Copy()); |
458 | } |
459 | |
460 | else if (C->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) { |
461 | Standard_Real Tol3d = 1.e-4; |
462 | GeomAbs_Shape Order = GeomAbs_C2; |
463 | Standard_Integer MaxSegments = 16, MaxDegree = 14; |
464 | GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, |
465 | MaxSegments, MaxDegree); |
466 | if (ApprCOffs.HasResult()) |
467 | TheCurve = ApprCOffs.Curve(); |
468 | else Standard_ConstructionError::Raise(); |
469 | } |
470 | else { Standard_DomainError::Raise("No such curve"); } |
471 | } |
472 | |
473 | return TheCurve; |
474 | } |
475 | |
476 | |
477 | //======================================================================= |
478 | //function : law_evaluator |
479 | //purpose : usefull to estimate the value of a function |
480 | //======================================================================= |
481 | |
482 | static Handle(Geom2d_BSplineCurve) Ancore = NULL ; |
483 | |
484 | static void law_evaluator(const Standard_Integer DerivativeRequest, |
485 | const Standard_Real *StartEnd, |
486 | const Standard_Real Parameter, |
487 | Standard_Real & Result, |
488 | Standard_Integer & ErrorCode) |
489 | {ErrorCode = 0 ; |
490 | if (!Ancore.IsNull() && |
491 | Parameter >= StartEnd[0] && |
492 | Parameter <= StartEnd[1] && |
493 | DerivativeRequest == 0){ |
494 | gp_Pnt2d a_point ; |
495 | Ancore->D0(Parameter, |
496 | a_point) ; |
497 | Result = a_point.Coord(2) ; |
498 | } |
499 | else |
500 | ErrorCode = 1 ; |
501 | } |
502 | |
503 | //======================================================================= |
504 | //function : MultNumandDenom |
505 | //purpose : Multiply two BSpline curves to make one |
506 | //======================================================================= |
507 | |
508 | |
509 | static Handle(Geom_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a , |
510 | const Handle(Geom_BSplineCurve)& BS ) |
511 | |
512 | { TColStd_Array1OfReal aKnots(1,a->NbKnots()); |
513 | TColStd_Array1OfReal BSKnots(1,BS->NbKnots()); |
514 | TColStd_Array1OfReal BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1); |
515 | TColStd_Array1OfReal BSWeights(1,BS->NbPoles()); |
516 | TColStd_Array1OfInteger aMults(1,a->NbKnots()); |
517 | TColStd_Array1OfInteger BSMults(1,BS->NbKnots()); |
518 | TColgp_Array1OfPnt2d aPoles(1,a->NbPoles()); |
519 | TColgp_Array1OfPnt BSPoles(1,BS->NbPoles()); |
520 | Handle(Geom_BSplineCurve) res; |
521 | Handle(TColStd_HArray1OfReal) resKnots; |
522 | Handle(TColStd_HArray1OfInteger) resMults; |
523 | Standard_Real start_value,end_value; |
524 | Standard_Real tolerance=Precision::PConfusion(); |
525 | Standard_Integer resNbPoles,degree, |
526 | ii,jj, |
527 | Status; |
528 | |
529 | BS->Knots(BSKnots); //storage of the two BSpline |
530 | BS->Multiplicities(BSMults); //features |
531 | BS->Poles(BSPoles); |
532 | BS->Weights(BSWeights); |
533 | BS->KnotSequence(BSFlatKnots); |
534 | start_value = BSKnots(1); |
535 | end_value = BSKnots(BS->NbKnots()); |
536 | if ((end_value - start_value)/5 < tolerance) |
537 | tolerance = (end_value - start_value)/5; |
538 | |
539 | a->Knots(aKnots); |
540 | a->Poles(aPoles); |
541 | a->Multiplicities(aMults); |
542 | BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots); |
543 | Ancore= new Geom2d_BSplineCurve(aPoles,aKnots,aMults,a->Degree()); //call of the law-evaluator |
544 | |
545 | BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value, //merge of the knots |
546 | a->Degree(),aKnots,aMults, |
547 | BS->Degree(),BSKnots,BSMults, |
548 | resNbPoles,resKnots,resMults); |
549 | degree=BS->Degree()+a->Degree(); |
550 | TColgp_Array1OfPnt resNumPoles(1,resNbPoles); |
551 | TColStd_Array1OfReal resDenPoles(1,resNbPoles); |
552 | TColgp_Array1OfPnt resPoles(1,resNbPoles); |
553 | TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1); |
554 | BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots); |
555 | for (ii=1;ii<=BS->NbPoles();ii++) |
556 | for (jj=1;jj<=3;jj++) |
557 | BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii)); |
558 | //POP pour WNT |
559 | BSplCLib_EvaluatorFunction ev = law_evaluator; |
560 | |
561 | BSplCLib::FunctionMultiply(ev, |
562 | BS->Degree(), |
563 | BSFlatKnots, |
564 | BSPoles, |
565 | resFlatKnots, |
566 | degree, |
567 | resNumPoles, |
568 | Status); |
569 | |
570 | BSplCLib::FunctionMultiply(ev, |
571 | BS->Degree(), |
572 | BSFlatKnots, |
573 | BSWeights, |
574 | resFlatKnots, |
575 | degree, |
576 | resDenPoles, |
577 | Status); |
578 | for (ii=1;ii<=resNbPoles;ii++) |
579 | for(jj=1;jj<=3;jj++) |
580 | resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii)); |
581 | res = new Geom_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree); |
582 | return res; |
583 | } |
584 | |
585 | //======================================================================= |
586 | //function : Pretreatment |
587 | //purpose : Put the two first and two last weigths at one if they are |
588 | // equal |
589 | //======================================================================= |
590 | |
591 | static void Pretreatment(TColGeom_Array1OfBSplineCurve& tab) |
592 | |
593 | {Standard_Integer i,j; |
594 | Standard_Real a; |
595 | |
596 | for (i=0;i<=(tab.Length()-1);i++){ |
597 | if (tab(i)->IsRational()) { |
598 | a=tab(i)->Weight(1); |
599 | if ((tab(i)->Weight(2)==a)&& |
600 | (tab(i)->Weight(tab(i)->NbPoles()-1)==a)&& |
601 | (tab(i)->Weight(tab(i)->NbPoles())==a)) |
602 | |
603 | for (j=1;j<=tab(i)->NbPoles();j++) |
604 | tab(i)->SetWeight(j,tab(i)->Weight(j)/a); |
605 | } |
606 | } |
607 | } |
608 | |
609 | //======================================================================= |
610 | //function : NeedToBeTreated |
611 | //purpose : Say if the BSpline is rationnal and if the two first and two |
612 | // last weigths are different |
613 | //======================================================================= |
614 | |
615 | static Standard_Boolean NeedToBeTreated(const Handle(Geom_BSplineCurve)& BS) |
616 | |
617 | { |
618 | TColStd_Array1OfReal tabWeights(1,BS->NbPoles()); |
619 | if (BS->IsRational()) { |
620 | BS->Weights(tabWeights); |
621 | if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&& |
622 | ((BS->Weight(1)<(1-Precision::Confusion()))|| |
623 | (BS->Weight(1)>(1+Precision::Confusion()))|| |
624 | (BS->Weight(2)<(1-Precision::Confusion()))|| |
625 | (BS->Weight(2)>(1+Precision::Confusion()))|| |
626 | (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))|| |
627 | (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))|| |
628 | (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))|| |
629 | (BS->Weight(BS->NbPoles())>(1+Precision::Confusion())))) |
630 | return Standard_True; |
631 | else |
632 | return Standard_False; |
633 | } |
634 | else |
635 | return Standard_False ; |
636 | |
637 | } |
638 | |
639 | //======================================================================= |
640 | //function : Need2DegRepara |
641 | //purpose : in the case of wire closed G1 it says if you will to use a |
642 | // two degree reparametrisation to close it C1 |
643 | //======================================================================= |
644 | |
645 | static Standard_Boolean Need2DegRepara(const TColGeom_Array1OfBSplineCurve& tab) |
646 | |
647 | {Standard_Integer i; |
648 | gp_Vec Vec1,Vec2; |
649 | gp_Pnt Pint; |
650 | Standard_Real Rapport=1.0e0; |
651 | |
652 | for (i=0;i<=tab.Length()-2;i++){ |
653 | tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1); |
654 | tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2); |
655 | Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude(); |
656 | } |
657 | if ((Rapport<=(1.0e0+Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion()))) |
658 | return Standard_False; |
659 | else |
660 | return Standard_True; |
661 | } |
662 | |
663 | //======================================================================= |
664 | //function : Indexmin |
665 | //purpose : Give the index of the curve which has the lowest degree |
666 | //======================================================================= |
667 | |
668 | static Standard_Integer Indexmin(const TColGeom_Array1OfBSplineCurve& tab) |
669 | { |
670 | Standard_Integer i = 0, index = 0, degree = 0; |
671 | |
672 | degree=tab(0)->Degree(); |
673 | for (i=0;i<=tab.Length()-1;i++) |
674 | if (tab(i)->Degree()<=degree){ |
675 | degree=tab(i)->Degree(); |
676 | index=i; |
677 | } |
678 | return index; |
679 | } |
680 | |
681 | //======================================================================= |
682 | //function : NewTabClosedG1 |
683 | //purpose : Sort the array of BSplines to start at the nb_vertex_group0 index |
684 | //======================================================================= |
685 | |
686 | static void ReorderArrayOfG1Curves(TColGeom_Array1OfBSplineCurve& ArrayOfCurves, |
687 | TColStd_Array1OfReal& ArrayOfToler, |
688 | TColStd_Array1OfBoolean& tabG1, |
689 | const Standard_Integer StartIndex, |
690 | const Standard_Real ClosedTolerance) |
691 | |
692 | {Standard_Integer i; |
693 | TColGeom_Array1OfBSplineCurve ArraybisOfCurves(0,ArrayOfCurves.Length()-1); //temporary |
694 | TColStd_Array1OfReal ArraybisOfToler(0,ArrayOfToler.Length()-1); //arrays |
695 | TColStd_Array1OfBoolean tabbisG1(0,tabG1.Length()-1); |
696 | |
697 | for (i=0;i<=ArrayOfCurves.Length()-1;i++){ |
698 | if (i!=ArrayOfCurves.Length()-1){ |
699 | ArraybisOfCurves(i)=ArrayOfCurves(i); |
700 | ArraybisOfToler(i)=ArrayOfToler(i); |
701 | tabbisG1(i)=tabG1(i); |
702 | } |
703 | else |
704 | ArraybisOfCurves(i)=ArrayOfCurves(i); |
705 | } |
706 | |
707 | for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){ |
708 | ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1); |
709 | if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){ |
710 | ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1); |
711 | tabG1(i)=tabbisG1(i+StartIndex+1); |
712 | } |
713 | } |
714 | |
715 | ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance; |
716 | tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True; |
717 | |
718 | for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){ |
719 | if (i!=ArrayOfCurves.Length()-1){ |
720 | ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1))); |
721 | ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1))); |
722 | tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1))); |
723 | } |
724 | else |
725 | ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1))); |
726 | } |
727 | } |
728 | |
729 | //======================================================================= |
730 | //function :reparameterise_evaluator |
731 | //purpose : |
732 | //======================================================================= |
733 | |
734 | static Standard_Real polynomial_coefficient[3] ; |
735 | |
736 | static void reparameterise_evaluator( |
737 | const Standard_Integer DerivativeRequest, |
738 | // const Standard_Real *StartEnd, |
739 | const Standard_Real *, |
740 | const Standard_Real Parameter, |
741 | Standard_Real & Result, |
742 | Standard_Integer & ErrorCode) { |
743 | ErrorCode = 0 ; |
744 | PLib::EvalPolynomial(Parameter, |
745 | DerivativeRequest, |
746 | 2, |
747 | 1, |
748 | polynomial_coefficient[0], |
749 | Result) ; |
750 | } |
751 | |
752 | //======================================================================= |
753 | //function : ConcatG1 |
754 | //purpose : |
755 | //======================================================================= |
756 | |
757 | void GeomConvert::ConcatG1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves, |
758 | const TColStd_Array1OfReal& ArrayOfToler, |
759 | Handle(TColGeom_HArray1OfBSplineCurve) & ArrayOfConcatenated, |
760 | const Standard_Boolean ClosedG1Flag, |
761 | const Standard_Real ClosedTolerance) |
762 | |
763 | {Standard_Integer nb_curve=ArrayOfCurves.Length(), |
764 | nb_vertexG1=0, |
765 | nb_group=0, |
766 | index=0,i,ii,j,jj, |
767 | indexmin, |
768 | nb_vertex_group0=0; |
769 | Standard_Real lambda, //G1 coefficient |
770 | First; |
771 | Standard_Real PreLast = 0.; |
772 | GeomAbs_Shape Cont; |
773 | gp_Vec Vec1,Vec2; //concecutive tangential vectors |
774 | gp_Pnt Pint; |
775 | Handle(Geom_BSplineCurve) Curve1,Curve2; |
776 | TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //array of the G1 continuity at the intersections |
777 | TColStd_Array1OfReal local_tolerance(0, |
778 | ArrayOfToler.Length()-1) ; |
779 | |
780 | for (i=0 ; i < ArrayOfToler.Length() ; i++) { |
781 | local_tolerance(i) = ArrayOfToler(i) ; |
782 | } |
783 | for (i=0 ;i<nb_curve; i++){ |
784 | if (i >= 1){ |
785 | First=ArrayOfCurves(i)->FirstParameter(); |
786 | Cont = GeomLProp::Continuity(ArrayOfCurves(i-1), |
787 | ArrayOfCurves(i), |
788 | PreLast,First, |
789 | Standard_True,Standard_True); |
790 | if (Cont<GeomAbs_C0) |
791 | Standard_ConstructionError::Raise("GeomConvert curves not C0") ; |
792 | else{ |
793 | if (Cont>=GeomAbs_G1) |
794 | tabG1(i-1)=Standard_True; //True=G1 continuity |
795 | else |
796 | tabG1(i-1)=Standard_False; |
797 | } |
798 | } |
799 | PreLast=ArrayOfCurves(i)->LastParameter(); |
800 | } |
801 | |
802 | |
803 | while (index<=nb_curve-1){ //determination of the Wire features |
804 | nb_vertexG1=0; |
805 | while(((index+nb_vertexG1)<=nb_curve-2)&& |
806 | (tabG1(index+nb_vertexG1)==Standard_True)) |
807 | nb_vertexG1++; |
808 | nb_group++; |
809 | if (index==0) |
810 | nb_vertex_group0=nb_vertexG1; |
811 | index=index+1+nb_vertexG1; |
812 | } |
813 | |
814 | if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array |
815 | nb_group--; |
816 | ReorderArrayOfG1Curves(ArrayOfCurves, |
817 | local_tolerance, |
818 | tabG1, |
819 | nb_vertex_group0, |
820 | ClosedTolerance); |
821 | } |
822 | |
823 | ArrayOfConcatenated = new TColGeom_HArray1OfBSplineCurve(0,nb_group-1); |
824 | Standard_Boolean fusion; |
825 | |
826 | index=0; |
827 | Pretreatment(ArrayOfCurves); |
828 | |
829 | if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case |
830 | indexmin=Indexmin(ArrayOfCurves); |
831 | if (indexmin!=(ArrayOfCurves.Length()-1)) |
832 | ReorderArrayOfG1Curves(ArrayOfCurves, |
833 | local_tolerance, |
834 | tabG1, |
835 | indexmin, |
836 | ClosedTolerance); |
837 | Curve2=ArrayOfCurves(0); |
838 | for (j=1;j<=nb_curve-1;j++){ //secondary loop inside each group |
839 | Curve1=ArrayOfCurves(j); |
840 | if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ |
841 | Curve2->D1(Curve2->LastParameter(),Pint,Vec1); |
842 | Curve1->D1(Curve1->FirstParameter(),Pint,Vec2); |
843 | lambda=Vec2.Magnitude()/Vec1.Magnitude(); |
844 | TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots()); |
845 | Curve1->Knots(KnotC1); |
846 | Curve1->D1(Curve1->LastParameter(),Pint,Vec2); |
847 | ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1); |
848 | Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude(); |
849 | Standard_Real tmax,a,b,c, |
850 | umin=Curve1->FirstParameter(),umax=Curve1->LastParameter(); |
851 | tmax=2*lambda*(umax-umin)/(1+lambda*lambda2); |
852 | a=(lambda*lambda2-1)/(2*lambda*tmax); |
853 | polynomial_coefficient[2]=a; |
854 | b=(1/lambda); |
855 | polynomial_coefficient[1]=b; |
856 | c=umin; |
857 | polynomial_coefficient[0]=c; |
858 | TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1); |
859 | TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots()); |
860 | Curve1->Multiplicities(KnotC1Mults); |
861 | BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots); |
862 | KnotC1(1)=0.0; |
863 | for (ii=2;ii<=KnotC1.Length();ii++) { |
864 | // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); |
865 | KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667 |
866 | } |
867 | TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles()); |
868 | Curve1->Poles(Curve1Poles); |
869 | |
870 | for (ii=1;ii<=Curve1->NbKnots();ii++) |
871 | KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii)); |
872 | |
873 | TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots())); |
874 | |
875 | BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots); |
876 | TColgp_Array1OfPnt NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); |
877 | Standard_Integer Status; |
878 | TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles()); |
879 | Curve1->Weights(Curve1Weights); |
880 | for (ii=1;ii<=Curve1->NbPoles();ii++) |
881 | for (jj=1;jj<=3;jj++) |
882 | Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii)); |
883 | //POP pour WNT |
884 | BSplCLib_EvaluatorFunction ev = reparameterise_evaluator; |
885 | // BSplCLib::FunctionReparameterise(reparameterise_evaluator, |
886 | BSplCLib::FunctionReparameterise(ev, |
887 | Curve1->Degree(), |
888 | Curve1FlatKnots, |
889 | Curve1Poles, |
890 | FlatKnots, |
891 | 2*Curve1->Degree(), |
892 | NewPoles, |
893 | Status |
894 | ); |
895 | TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); |
896 | // BSplCLib::FunctionReparameterise(reparameterise_evaluator, |
897 | BSplCLib::FunctionReparameterise(ev, |
898 | Curve1->Degree(), |
899 | Curve1FlatKnots, |
900 | Curve1Weights, |
901 | FlatKnots, |
902 | 2*Curve1->Degree(), |
903 | NewWeights, |
904 | Status |
905 | ); |
906 | for (ii=1;ii<=NewPoles.Length();ii++) |
907 | for (jj=1;jj<=3;jj++) |
908 | NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii)); |
909 | Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree()); |
910 | } |
911 | GeomConvert_CompCurveToBSplineCurve C(Handle(Geom_BSplineCurve)::DownCast(Curve2)); |
912 | fusion=C.Add(Curve1, |
913 | local_tolerance(j-1)); //merge of two consecutive curves |
914 | if (fusion==Standard_False) |
915 | Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ; |
916 | Curve2=C.BSplineCurve(); |
917 | } |
918 | Standard_Boolean rm; |
919 | Curve2->SetPeriodic(); |
920 | rm=Curve2->RemoveKnot(Curve2->LastUKnotIndex(), |
921 | Curve2->Multiplicity(Curve2->LastUKnotIndex())-1, |
922 | Precision::Confusion()); |
923 | ArrayOfConcatenated->SetValue(0,Curve2); |
924 | } |
925 | |
926 | else |
927 | for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity |
928 | nb_vertexG1=0; //group |
929 | |
930 | while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) |
931 | nb_vertexG1++; |
932 | |
933 | for (j=index;j<=index+nb_vertexG1;j++){ //secondary loop inside each group |
934 | Curve1=ArrayOfCurves(j); |
935 | |
936 | if (index==j) //initialisation at the begining of the loop |
937 | ArrayOfConcatenated->SetValue(i,Curve1); |
938 | else{ |
939 | GeomConvert_CompCurveToBSplineCurve C(Handle(Geom_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i))); |
940 | fusion=C.Add(Curve1,ArrayOfToler(j-1)); //merge of two consecutive curves |
941 | if (fusion==Standard_False) |
942 | Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ; |
943 | ArrayOfConcatenated->SetValue(i,C.BSplineCurve()); |
944 | } |
945 | } |
946 | index=index+1+nb_vertexG1; |
947 | } |
948 | } |
949 | //======================================================================= |
950 | //function : ConcatC1 |
951 | //purpose : |
952 | //======================================================================= |
953 | |
954 | void GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves, |
955 | const TColStd_Array1OfReal& ArrayOfToler, |
956 | Handle(TColStd_HArray1OfInteger)& ArrayOfIndices, |
957 | Handle(TColGeom_HArray1OfBSplineCurve)& ArrayOfConcatenated, |
958 | const Standard_Boolean ClosedG1Flag, |
959 | const Standard_Real ClosedTolerance) |
960 | { |
961 | ConcatC1(ArrayOfCurves, |
962 | ArrayOfToler, |
963 | ArrayOfIndices, |
964 | ArrayOfConcatenated, |
965 | ClosedG1Flag, |
966 | ClosedTolerance, |
967 | Precision::Angular()) ; |
968 | } |
969 | //======================================================================= |
970 | //function : ConcatC1 |
971 | //purpose : |
972 | //======================================================================= |
973 | |
974 | void GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves, |
975 | const TColStd_Array1OfReal& ArrayOfToler, |
976 | Handle(TColStd_HArray1OfInteger)& ArrayOfIndices, |
977 | Handle(TColGeom_HArray1OfBSplineCurve)& ArrayOfConcatenated, |
978 | const Standard_Boolean ClosedG1Flag, |
979 | const Standard_Real ClosedTolerance, |
980 | const Standard_Real AngularTolerance) |
981 | |
982 | {Standard_Integer nb_curve=ArrayOfCurves.Length(), |
983 | nb_vertexG1, |
984 | nb_group=0, |
985 | index=0,i,ii,j,jj, |
986 | indexmin, |
987 | nb_vertex_group0=0; |
988 | Standard_Real lambda, //G1 coefficient |
989 | First; |
990 | Standard_Real PreLast = 0.; |
991 | |
992 | GeomAbs_Shape Cont; |
993 | gp_Vec Vec1,Vec2; //concecutive tangential vectors |
994 | gp_Pnt Pint; |
995 | Handle(Geom_BSplineCurve) Curve1,Curve2; |
996 | TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //array of the G1 continuity at the intersections |
997 | TColStd_Array1OfReal local_tolerance(0, |
998 | ArrayOfToler.Length()-1) ; |
999 | |
1000 | for (i=0 ; i < ArrayOfToler.Length() ; i++) { |
1001 | local_tolerance(i) = ArrayOfToler(i) ; |
1002 | } |
1003 | for (i=0 ;i<nb_curve; i++){ |
1004 | if (i >= 1){ |
1005 | First=ArrayOfCurves(i)->FirstParameter(); |
1006 | Cont = GeomLProp::Continuity(ArrayOfCurves(i-1), |
1007 | ArrayOfCurves(i), |
1008 | PreLast, |
1009 | First, |
1010 | Standard_True, |
1011 | Standard_True, |
1012 | local_tolerance(i-1), |
1013 | AngularTolerance); |
1014 | if (Cont<GeomAbs_C0) |
1015 | Standard_ConstructionError::Raise("GeomConvert curves not C0"); |
1016 | else{ |
1017 | if (Cont>=GeomAbs_G1) |
1018 | tabG1(i-1)=Standard_True; //True=G1 continuity |
1019 | else |
1020 | tabG1(i-1)=Standard_False; |
1021 | } |
1022 | } |
1023 | PreLast=ArrayOfCurves(i)->LastParameter(); |
1024 | } |
1025 | |
1026 | |
1027 | while (index<=nb_curve-1){ //determination of the Wire features |
1028 | nb_vertexG1=0; |
1029 | while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) |
1030 | nb_vertexG1++; |
1031 | nb_group++; |
1032 | if (index==0) |
1033 | nb_vertex_group0=nb_vertexG1; |
1034 | index=index+1+nb_vertexG1; |
1035 | } |
1036 | |
1037 | if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array |
1038 | nb_group--; |
1039 | ReorderArrayOfG1Curves(ArrayOfCurves, |
1040 | local_tolerance, |
1041 | tabG1, |
1042 | nb_vertex_group0, |
1043 | ClosedTolerance); |
1044 | } |
1045 | |
1046 | ArrayOfIndices = |
1047 | new TColStd_HArray1OfInteger(0,nb_group); |
1048 | ArrayOfConcatenated = |
1049 | new TColGeom_HArray1OfBSplineCurve(0,nb_group-1); |
1050 | |
1051 | Standard_Boolean fusion; |
1052 | Standard_Integer k=0; |
1053 | index=0; |
1054 | Pretreatment(ArrayOfCurves); |
1055 | |
1056 | if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case |
1057 | ArrayOfIndices->SetValue(0,0); |
1058 | ArrayOfIndices->SetValue(1,0); |
1059 | indexmin=Indexmin(ArrayOfCurves); |
1060 | if (indexmin!=(ArrayOfCurves.Length()-1)) |
1061 | ReorderArrayOfG1Curves(ArrayOfCurves, |
1062 | local_tolerance, |
1063 | tabG1, |
1064 | indexmin, |
1065 | ClosedTolerance); |
1066 | for (j=0;j<=nb_curve-1;j++){ //secondary loop inside each group |
1067 | if (NeedToBeTreated(ArrayOfCurves(j))) |
1068 | Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j)); |
1069 | else |
1070 | Curve1=ArrayOfCurves(j); |
1071 | |
1072 | if (j==0) //initialisation at the begining of the loop |
1073 | Curve2=Curve1; |
1074 | else{ |
1075 | if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ |
1076 | Curve2->D1(Curve2->LastParameter(),Pint,Vec1); |
1077 | Curve1->D1(Curve1->FirstParameter(),Pint,Vec2); |
1078 | lambda=Vec2.Magnitude()/Vec1.Magnitude(); |
1079 | TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots()); |
1080 | Curve1->Knots(KnotC1); |
1081 | Curve1->D1(Curve1->LastParameter(),Pint,Vec2); |
1082 | ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1); |
1083 | Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude(); |
1084 | Standard_Real tmax,a,b,c, |
1085 | umin=Curve1->FirstParameter(),umax=Curve1->LastParameter(); |
1086 | tmax=2*lambda*(umax-umin)/(1+lambda*lambda2); |
1087 | a=(lambda*lambda2-1)/(2*lambda*tmax); |
1088 | polynomial_coefficient[2]=a; |
1089 | b=(1/lambda); |
1090 | polynomial_coefficient[1]=b; |
1091 | c=umin; |
1092 | polynomial_coefficient[0]=c; |
1093 | TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1); |
1094 | TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots()); |
1095 | Curve1->Multiplicities(KnotC1Mults); |
1096 | BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots); |
1097 | KnotC1(1)=0.0; |
1098 | for (ii=2;ii<=KnotC1.Length();ii++) { |
1099 | // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); |
1100 | KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667 |
1101 | } |
1102 | TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles()); |
1103 | Curve1->Poles(Curve1Poles); |
1104 | |
1105 | for (ii=1;ii<=Curve1->NbKnots();ii++) |
1106 | KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii)); |
1107 | |
1108 | TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots())); |
1109 | |
1110 | BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots); |
1111 | TColgp_Array1OfPnt NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); |
1112 | Standard_Integer Status; |
1113 | TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles()); |
1114 | Curve1->Weights(Curve1Weights); |
1115 | for (ii=1;ii<=Curve1->NbPoles();ii++) |
1116 | for (jj=1;jj<=3;jj++) |
1117 | Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii)); |
1118 | //POP pour WNT |
1119 | BSplCLib_EvaluatorFunction ev = reparameterise_evaluator; |
1120 | |
1121 | BSplCLib::FunctionReparameterise(ev, |
1122 | Curve1->Degree(), |
1123 | Curve1FlatKnots, |
1124 | Curve1Poles, |
1125 | FlatKnots, |
1126 | 2*Curve1->Degree(), |
1127 | NewPoles, |
1128 | Status |
1129 | ); |
1130 | TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); |
1131 | |
1132 | BSplCLib::FunctionReparameterise(ev, |
1133 | Curve1->Degree(), |
1134 | Curve1FlatKnots, |
1135 | Curve1Weights, |
1136 | FlatKnots, |
1137 | 2*Curve1->Degree(), |
1138 | NewWeights, |
1139 | Status |
1140 | ); |
1141 | for (ii=1;ii<=NewPoles.Length();ii++) |
1142 | for (jj=1;jj<=3;jj++) |
1143 | NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii)); |
1144 | Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree()); |
1145 | } |
1146 | GeomConvert_CompCurveToBSplineCurve C(Handle(Geom_BSplineCurve)::DownCast(Curve2)); |
1147 | fusion=C.Add(Curve1, |
1148 | local_tolerance(j-1)); //merge of two consecutive curves |
1149 | if (fusion==Standard_False) |
1150 | Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ; |
1151 | Curve2=C.BSplineCurve(); |
1152 | } |
1153 | } |
1154 | Standard_Boolean rm; |
1155 | Curve2->SetPeriodic(); //only one C1 curve |
1156 | rm=Curve2->RemoveKnot(Curve2->LastUKnotIndex(), |
1157 | Curve2->Multiplicity(Curve2->LastUKnotIndex())-1, |
1158 | Precision::Confusion()); |
1159 | ArrayOfConcatenated->SetValue(0,Curve2); |
1160 | } |
1161 | |
1162 | else |
1163 | for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity |
1164 | nb_vertexG1=0; //group |
1165 | |
1166 | while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) |
1167 | nb_vertexG1++; |
1168 | |
1169 | if ((!ClosedG1Flag)||(nb_group==1)){ //filling of the array of index which are kept |
1170 | k++; |
1171 | ArrayOfIndices->SetValue(k-1,index); |
1172 | if (k==nb_group) |
1173 | ArrayOfIndices->SetValue(k,0); |
1174 | } |
1175 | else{ |
1176 | k++; |
1177 | ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1); |
1178 | if (k==nb_group) |
1179 | ArrayOfIndices->SetValue(k,nb_vertex_group0+1); |
1180 | } |
1181 | |
1182 | for (j=index;j<=index+nb_vertexG1;j++){ //secondary loop inside each group |
1183 | if (NeedToBeTreated(ArrayOfCurves(j))) |
1184 | Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j)); |
1185 | else |
1186 | Curve1=ArrayOfCurves(j); |
1187 | |
1188 | if (index==j) //initialisation at the begining of the loop |
1189 | ArrayOfConcatenated->SetValue(i,Curve1); |
1190 | else{ |
1191 | GeomConvert_CompCurveToBSplineCurve C(Handle(Geom_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i))); |
1192 | fusion=C.Add(Curve1, |
1193 | local_tolerance(j-1)); //merge of two consecutive curves |
1194 | if (fusion==Standard_False) |
1195 | Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ; |
1196 | ArrayOfConcatenated->SetValue(i,C.BSplineCurve()); |
1197 | } |
1198 | } |
1199 | index=index+1+nb_vertexG1; |
1200 | } |
1201 | } |
1202 | |
1203 | //======================================================================= |
1204 | //function : C0BSplineToC1BSplineCurve |
1205 | //purpose : |
1206 | //======================================================================= |
1207 | |
1208 | void GeomConvert::C0BSplineToC1BSplineCurve(Handle(Geom_BSplineCurve)& BS, |
1209 | const Standard_Real tolerance, |
1210 | const Standard_Real AngularTol) |
1211 | |
1212 | { |
1213 | Standard_Boolean fusion; |
1214 | Handle(TColGeom_HArray1OfBSplineCurve) ArrayOfConcatenated; |
1215 | //the array with the resulting curves |
1216 | |
1217 | GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS, ArrayOfConcatenated, |
1218 | AngularTol, tolerance); |
1219 | |
1220 | GeomConvert_CompCurveToBSplineCurve C |
1221 | (Handle(Geom_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(0))); |
1222 | if (ArrayOfConcatenated->Length()>=2){ |
1223 | Standard_Integer i; |
1224 | for (i=1;i<ArrayOfConcatenated->Length();i++){ |
1225 | fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance); |
1226 | if (fusion==Standard_False) |
1227 | Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ; |
1228 | } |
1229 | } |
1230 | BS=C.BSplineCurve(); |
1231 | } |
1232 | |
1233 | //======================================================================= |
1234 | //function : C0BSplineToArrayOfC1BSplineCurve |
1235 | //purpose : |
1236 | //======================================================================= |
1237 | |
1238 | void GeomConvert::C0BSplineToArrayOfC1BSplineCurve( |
1239 | const Handle(Geom_BSplineCurve) & BS, |
1240 | Handle(TColGeom_HArray1OfBSplineCurve) & tabBS, |
1241 | const Standard_Real tolerance) |
1242 | { |
1243 | C0BSplineToArrayOfC1BSplineCurve(BS, |
1244 | tabBS, |
1245 | Precision::Angular(), |
1246 | tolerance) ; |
1247 | } |
1248 | |
1249 | //======================================================================= |
1250 | //function : C0BSplineToArrayOfC1BSplineCurve |
1251 | //purpose : |
1252 | //======================================================================= |
1253 | |
1254 | void GeomConvert::C0BSplineToArrayOfC1BSplineCurve( |
1255 | const Handle(Geom_BSplineCurve) & BS, |
1256 | Handle(TColGeom_HArray1OfBSplineCurve) & tabBS, |
1257 | const Standard_Real AngularTolerance, |
1258 | const Standard_Real tolerance) |
1259 | |
1260 | {TColStd_Array1OfInteger BSMults(1,BS->NbKnots()); |
1261 | TColStd_Array1OfReal BSKnots(1,BS->NbKnots()); |
1262 | Standard_Integer i,j,nbcurveC1=1; |
1263 | Standard_Real U1,U2; |
1264 | Standard_Boolean closed_flag= Standard_False ; |
1265 | gp_Pnt point; |
1266 | gp_Vec V1,V2; |
1267 | // Standard_Boolean fusion; |
1268 | |
1269 | BS->Knots(BSKnots); |
1270 | BS->Multiplicities(BSMults); |
1271 | for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){ //give the number of C1 curves |
1272 | if (BSMults(i)==BS->Degree()) |
1273 | nbcurveC1++; |
1274 | } |
1275 | |
1276 | if (nbcurveC1>1){ |
1277 | TColGeom_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1); |
1278 | TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2); |
1279 | |
1280 | for (i=0;i<=nbcurveC1-2;i++) |
1281 | //filling of the array of tolerances |
1282 | ArrayOfToler(i)=tolerance; |
1283 | //with the variable tolerance |
1284 | U2=BS->FirstParameter() ; |
1285 | j=BS->FirstUKnotIndex() + 1; |
1286 | for (i=0;i<nbcurveC1;i++){ |
1287 | //filling of the array of curves |
1288 | U1=U2; |
1289 | //with the curves C1 segmented |
1290 | while (BSMults(j)<BS->Degree() && j < BS->LastUKnotIndex()) |
1291 | j++; |
1292 | U2=BSKnots(j); |
1293 | j++; |
1294 | Handle(Geom_BSplineCurve) |
1295 | BSbis=Handle(Geom_BSplineCurve::DownCast(BS->Copy())); |
1296 | BSbis->Segment(U1,U2); |
1297 | ArrayOfCurves(i)=BSbis; |
1298 | } |
1299 | |
1300 | Handle(TColStd_HArray1OfInteger) ArrayOfIndices; |
1301 | |
1302 | BS->D1(BS->FirstParameter(),point,V1); |
1303 | BS->D1(BS->LastParameter(),point,V2); |
1304 | |
1305 | if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance))){ |
1306 | //check if the BSpline is closed G1 |
1307 | closed_flag = Standard_True ; |
1308 | } |
1309 | |
1310 | GeomConvert::ConcatC1(ArrayOfCurves, |
1311 | ArrayOfToler, |
1312 | ArrayOfIndices, |
1313 | tabBS, |
1314 | closed_flag, |
1315 | tolerance, |
1316 | AngularTolerance); |
1317 | } |
1318 | else{ |
1319 | tabBS = new TColGeom_HArray1OfBSplineCurve(0,0); |
1320 | tabBS->SetValue(0,BS); |
1321 | } |
1322 | } |
1323 | |
1324 | |
1325 | |
1326 | |
1327 | |