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