b311480e |
1 | // Created on: 1997-12-19 |
2 | // Created by: Roman BORISOV /Philippe MANGIN |
3 | // Copyright (c) 1997-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
973c2be1 |
8 | // This library is free software; you can redistribute it and / or modify it |
9 | // under the terms of the GNU Lesser General Public version 2.1 as published |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
17 | #include <stdio.h> |
18 | |
19 | #include <GeomFill_CorrectedFrenet.ixx> |
20 | #include <GeomAbs_CurveType.hxx> |
21 | #include <Adaptor3d_HCurve.hxx> |
22 | #include <gp_Trsf.hxx> |
23 | #include <Precision.hxx> |
24 | #include <TColStd_HArray1OfReal.hxx> |
25 | #include <Law_Interpolate.hxx> |
26 | #include <TColStd_SequenceOfReal.hxx> |
27 | #include <gp_Vec2d.hxx> |
28 | #include <BndLib_Add3dCurve.hxx> |
29 | #include <Bnd_Box.hxx> |
30 | #include <GeomLib.hxx> |
31 | #include <Law_Composite.hxx> |
32 | #include <Law_Constant.hxx> |
33 | #include <Law_BSpFunc.hxx> |
34 | #include <Law_BSpline.hxx> |
35 | #include <GeomFill_SnglrFunc.hxx> |
36 | //Patch |
37 | #include <Geom_Plane.hxx> |
38 | #include <Geom_BezierCurve.hxx> |
39 | #include <Geom_BSplineCurve.hxx> |
40 | #include <TColgp_HArray1OfPnt.hxx> |
41 | |
a31abc03 |
42 | |
7fd59977 |
43 | #ifdef DEB |
44 | static Standard_Boolean Affich=0; |
45 | #endif |
46 | |
47 | #ifdef DRAW |
48 | static Standard_Integer CorrNumber = 0; |
49 | #include <Draw_Appli.hxx> |
50 | #include <DrawTrSurf.hxx> |
51 | #include <Draw_Segment2D.hxx> |
52 | //#include <Draw.hxx> |
53 | #include <TColgp_Array1OfPnt.hxx> |
54 | #include <TColStd_Array1OfReal.hxx> |
55 | #include <TColStd_HArray1OfInteger.hxx> |
56 | #endif |
57 | |
58 | #ifdef DRAW |
59 | static void draw(const Handle(Law_Function)& law) |
60 | { |
61 | Standard_Real Step, u, v, tmin; |
62 | Standard_Integer NbInt, i, j, jmax; |
63 | NbInt = law->NbIntervals(GeomAbs_C3); |
64 | TColStd_Array1OfReal Int(1, NbInt+1); |
65 | law->Intervals(Int, GeomAbs_C3); |
66 | gp_Pnt2d old; |
67 | Handle(Draw_Segment2D) tg2d; |
68 | |
69 | for(i = 1; i <= NbInt; i++){ |
70 | tmin = Int(i); |
71 | Step = (Int(i+1)-Int(i))/4; |
72 | if (i == NbInt) jmax = 4; |
73 | else jmax = 3; |
74 | for (j=1; j<=jmax; j++) { |
75 | u = tmin + (j-1)*Step; |
76 | v = law->Value(u); |
77 | gp_Pnt2d point2d(u,v); |
78 | if ((i>1)||(j>1)) { |
79 | tg2d = new Draw_Segment2D(old, point2d,Draw_kaki); |
80 | dout << tg2d; |
81 | } |
82 | old = point2d; |
83 | } |
84 | } |
85 | dout.Flush(); |
86 | } |
87 | #endif |
88 | |
a31abc03 |
89 | |
90 | static Standard_Real ComputeTorsion(const Standard_Real Param, |
91 | const Handle(Adaptor3d_HCurve)& aCurve) |
92 | { |
93 | Standard_Real Torsion; |
94 | |
95 | gp_Pnt aPoint; |
96 | gp_Vec DC1, DC2, DC3; |
97 | aCurve->D3(Param, aPoint, DC1, DC2, DC3); |
98 | gp_Vec DC1crossDC2 = DC1 ^ DC2; |
99 | Standard_Real Norm_DC1crossDC2 = DC1crossDC2.Magnitude(); |
100 | |
101 | Standard_Real DC1DC2DC3 = DC1crossDC2 * DC3 ; //mixed product |
102 | |
103 | Standard_Real Tol = gp::Resolution(); |
104 | Standard_Real SquareNorm_DC1crossDC2 = Norm_DC1crossDC2 * Norm_DC1crossDC2; |
105 | if (SquareNorm_DC1crossDC2 <= Tol) |
106 | Torsion = 0.; |
107 | else |
108 | Torsion = DC1DC2DC3 / SquareNorm_DC1crossDC2 ; |
109 | |
110 | return Torsion; |
111 | } |
112 | |
7fd59977 |
113 | //=============================================================== |
114 | // Function : smoothlaw |
115 | // Purpose : to smooth a law : Reduce the number of knots |
116 | //=============================================================== |
117 | static void smoothlaw(Handle(Law_BSpline)& Law, |
118 | const Handle(TColStd_HArray1OfReal)& Points, |
119 | const Handle(TColStd_HArray1OfReal)& Param, |
120 | const Standard_Real Tol) |
121 | { |
122 | Standard_Real tol, d; |
123 | Standard_Integer ii, Nbk; |
124 | Standard_Boolean B, Ok; |
125 | Handle(Law_BSpline) BS = Law->Copy(); |
126 | |
127 | Nbk = BS->NbKnots(); |
128 | tol = Tol/10; |
129 | Ok = Standard_False; |
130 | |
131 | for (ii=Nbk-1; ii>1; ii--) { // Une premiere passe tolerance serres |
132 | B = BS->RemoveKnot(ii, 0, tol); |
133 | if (B) Ok = Standard_True; |
134 | } |
135 | |
136 | if (Ok) { // controle |
137 | tol = 0.; |
138 | for (ii=1; ii<=Param->Length() && Ok; ii++) { |
139 | d = Abs(BS->Value(Param->Value(ii))-Points->Value(ii)); |
140 | if (d > tol) tol = d; |
141 | Ok = (tol <= Tol); |
142 | } |
143 | if (Ok) |
144 | tol = (Tol-tol)/2; |
145 | else { |
146 | #if DEB |
147 | cout << "smooth law echec" << endl; |
148 | #endif |
149 | return; // Echec |
150 | } |
151 | } |
152 | else { |
153 | tol = Tol/2; |
154 | } |
155 | |
156 | |
157 | if (Ok) Law = BS; |
158 | |
159 | Ok = Standard_False; // Une deuxieme passe tolerance desserre |
160 | Nbk = BS->NbKnots(); |
161 | for (ii=Nbk-1; ii>1; ii--) { |
162 | B = BS->RemoveKnot(ii, 0, tol); |
163 | if (B) Ok = Standard_True; |
164 | } |
165 | |
166 | if (Ok) { // controle |
167 | tol = 0.; |
168 | for (ii=1; ii<=Param->Length() && Ok; ii++) { |
169 | d = Abs(BS->Value(Param->Value(ii))-Points->Value(ii)); |
170 | if (d > tol) tol = d; |
171 | Ok = (tol <= Tol); |
172 | } |
173 | if (!Ok) { |
174 | #if DEB |
175 | cout << "smooth law echec" << endl; |
176 | #endif |
177 | } |
178 | } |
179 | if (Ok) Law = BS; |
180 | |
181 | #if DEB |
182 | if (Affich) { |
183 | cout << "Knots Law : " << endl; |
184 | for (ii=1; ii<=BS->NbKnots(); ii++) { |
185 | cout << ii << " : " << BS->Knot(ii) << endl; |
186 | } |
187 | } |
188 | #endif |
189 | } |
190 | |
191 | //=============================================================== |
192 | // Function : FindPlane |
193 | // Purpose : |
194 | //=============================================================== |
195 | static Standard_Boolean FindPlane ( const Handle(Adaptor3d_HCurve)& c, |
196 | Handle( Geom_Plane )& P ) |
197 | { |
198 | Standard_Boolean found = Standard_True; |
199 | Handle(TColgp_HArray1OfPnt) TabP; |
200 | |
201 | switch (c->GetType()) { |
202 | |
203 | case GeomAbs_Line: |
204 | { |
205 | found = Standard_False; |
206 | } |
207 | break; |
208 | |
209 | case GeomAbs_Circle: |
210 | P = new Geom_Plane(gp_Ax3(c->Circle().Position())); |
211 | break; |
212 | |
213 | case GeomAbs_Ellipse: |
214 | P = new Geom_Plane(gp_Ax3(c->Ellipse().Position())); |
215 | break; |
216 | |
217 | case GeomAbs_Hyperbola: |
218 | P = new Geom_Plane(gp_Ax3(c->Hyperbola().Position())); |
219 | break; |
220 | |
221 | case GeomAbs_Parabola: |
222 | P = new Geom_Plane(gp_Ax3(c->Parabola().Position())); |
223 | break; |
224 | |
225 | case GeomAbs_BezierCurve: |
226 | { |
227 | Handle(Geom_BezierCurve) GC = c->Bezier(); |
228 | Standard_Integer nbp = GC->NbPoles(); |
229 | if ( nbp < 2) |
230 | found = Standard_False; |
231 | else if ( nbp == 2) { |
232 | found = Standard_False; |
233 | } |
234 | else { |
235 | TabP = new (TColgp_HArray1OfPnt) (1, nbp); |
236 | GC->Poles(TabP->ChangeArray1()); |
237 | } |
238 | } |
239 | break; |
240 | |
241 | case GeomAbs_BSplineCurve: |
242 | { |
243 | Handle(Geom_BSplineCurve) GC = c->BSpline(); |
244 | Standard_Integer nbp = GC->NbPoles(); |
245 | if ( nbp < 2) |
246 | found = Standard_False; |
247 | else if ( nbp == 2) { |
248 | found = Standard_False; |
249 | } |
250 | else { |
251 | TabP = new (TColgp_HArray1OfPnt) (1, nbp); |
252 | GC->Poles(TabP->ChangeArray1()); |
253 | } |
254 | } |
255 | break; |
256 | |
257 | default: |
258 | { // On utilise un echantillonage |
259 | Standard_Integer nbp = 15 + c->NbIntervals(GeomAbs_C3); |
260 | Standard_Real f, l, t, inv; |
261 | Standard_Integer ii; |
262 | f = c->FirstParameter(); |
263 | l = c->LastParameter(); |
264 | inv = 1./(nbp-1); |
265 | for (ii=1; ii<=nbp; ii++) { |
266 | t = ( f*(nbp-ii) + l*(ii-1)); |
267 | t *= inv; |
268 | TabP->SetValue(ii, c->Value(t)); |
269 | } |
270 | } |
271 | } |
272 | |
273 | if (! TabP.IsNull()) { // Recherche d'un plan moyen et controle |
274 | Standard_Boolean issingular; |
275 | gp_Ax2 inertia; |
276 | GeomLib::AxeOfInertia(TabP->Array1(), inertia, issingular); |
277 | if (issingular) { |
278 | found = Standard_False; |
279 | } |
280 | else { |
281 | P = new Geom_Plane(inertia); |
282 | } |
283 | if (found) |
284 | { |
285 | //control = Controle(TabP->Array1(), P, myTolerance); |
286 | // Standard_Boolean isOnPlane; |
287 | Standard_Real a,b,c,d, dist; |
288 | Standard_Integer ii; |
289 | P->Coefficients(a,b,c,d); |
290 | for (ii=1; ii<=TabP->Length() && found; ii++) { |
291 | const gp_XYZ& xyz = TabP->Value(ii).XYZ(); |
292 | dist = a*xyz.X() + b*xyz.Y() + c*xyz.Z() + d; |
293 | found = (Abs(dist) <= Precision::Confusion()); |
294 | } |
295 | return found; |
296 | } |
297 | } |
298 | |
299 | return found; |
300 | } |
301 | |
302 | //=============================================================== |
a31abc03 |
303 | // Function : Constructor |
7fd59977 |
304 | // Purpose : |
305 | //=============================================================== |
306 | GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet() |
307 | : isFrenet(Standard_False) |
308 | { |
309 | frenet = new GeomFill_Frenet(); |
a31abc03 |
310 | myForEvaluation = Standard_False; |
311 | } |
312 | |
313 | //=============================================================== |
314 | // Function : Constructor |
315 | // Purpose : |
316 | //=============================================================== |
317 | GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet(const Standard_Boolean ForEvaluation) |
318 | : isFrenet(Standard_False) |
319 | { |
320 | frenet = new GeomFill_Frenet(); |
321 | myForEvaluation = ForEvaluation; |
7fd59977 |
322 | } |
323 | |
324 | Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const |
325 | { |
326 | Handle(GeomFill_CorrectedFrenet) copy = new (GeomFill_CorrectedFrenet)(); |
327 | if (!myCurve.IsNull()) copy->SetCurve(myCurve); |
328 | return copy; |
329 | } |
330 | |
331 | void GeomFill_CorrectedFrenet::SetCurve(const Handle(Adaptor3d_HCurve)& C) |
332 | { |
333 | |
334 | GeomFill_TrihedronLaw::SetCurve(C); |
335 | if (! C.IsNull()) { |
336 | frenet->SetCurve(C); |
337 | |
338 | GeomAbs_CurveType type; |
339 | type = C->GetType(); |
340 | switch (type) { |
341 | case GeomAbs_Circle: |
342 | case GeomAbs_Ellipse: |
343 | case GeomAbs_Hyperbola: |
344 | case GeomAbs_Parabola: |
345 | case GeomAbs_Line: |
346 | { |
347 | // No probleme isFrenet |
348 | isFrenet = Standard_True; |
a31abc03 |
349 | break; |
7fd59977 |
350 | } |
351 | default : |
352 | { |
353 | // We have to search singulaties |
354 | isFrenet = Standard_True; |
355 | Init(); |
356 | } |
357 | } |
358 | } |
359 | } |
360 | |
361 | |
362 | //=============================================================== |
363 | // Function : Init |
364 | // Purpose : Compute angle's law |
365 | //=============================================================== |
366 | void GeomFill_CorrectedFrenet::Init() |
367 | { |
368 | EvolAroundT = new Law_Composite(); |
369 | Standard_Integer NbI = frenet->NbIntervals(GeomAbs_C0), i; |
370 | TColStd_Array1OfReal T(1, NbI + 1); |
371 | frenet->Intervals(T, GeomAbs_C0); |
372 | Handle(Law_Function) Func; |
373 | //OCC78 |
374 | TColStd_SequenceOfReal SeqPoles, SeqAngle; |
375 | TColgp_SequenceOfVec SeqTangent, SeqNormal; |
376 | |
377 | gp_Vec Tangent, Normal, BN; |
378 | frenet->D0(myTrimmed->FirstParameter(), Tangent, Normal, BN); |
379 | Standard_Integer NbStep; |
380 | // Standard_Real StartAng = 0, AvStep, Step, t; |
381 | Standard_Real StartAng = 0, AvStep, Step; |
382 | |
383 | #if DRAW |
384 | Standard_Real t; |
385 | |
386 | if (Affich) { // Display the curve C'^C''(t) |
387 | GeomFill_SnglrFunc CS(myCurve); |
388 | NbStep = 99; |
389 | AvStep = (myTrimmed->LastParameter() - |
390 | myTrimmed->FirstParameter())/NbStep; |
391 | TColgp_Array1OfPnt TabP(1, NbStep+1); |
392 | |
393 | TColStd_Array1OfReal TI(1, NbStep+1); |
394 | TColStd_Array1OfInteger M(1,NbStep+1); |
395 | M.Init(1); |
396 | M(1) = M(NbStep+1) = 2; |
397 | for (i=1; i<=NbStep+1; i++) { |
398 | t = (myTrimmed->FirstParameter()+ (i-1)*AvStep); |
399 | CS.D0(t, TabP(i)); |
400 | TI(i) = t; |
401 | } |
402 | char tname[100]; |
403 | Standard_CString name = tname ; |
404 | sprintf(name,"Binorm_%d", ++CorrNumber); |
405 | Handle(Geom_BSplineCurve) BS = new |
406 | (Geom_BSplineCurve) (TabP, TI, M, 1); |
407 | // DrawTrSurf::Set(&name[0], BS); |
408 | DrawTrSurf::Set(name, BS); |
409 | } |
410 | #endif |
411 | |
412 | |
413 | NbStep = 10; |
414 | AvStep = (myTrimmed->LastParameter() - myTrimmed->FirstParameter())/NbStep; |
415 | for(i = 1; i <= NbI; i++) { |
416 | NbStep = Max(Standard_Integer((T(i+1) - T(i))/AvStep), 3); |
417 | Step = (T(i+1) - T(i))/NbStep; |
a31abc03 |
418 | if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func, |
419 | SeqPoles, SeqAngle, SeqTangent, SeqNormal)) |
420 | { |
421 | if(isFrenet) |
422 | isFrenet = Standard_False; |
423 | } |
7fd59977 |
424 | Handle(Law_Composite)::DownCast(EvolAroundT)->ChangeLaws().Append(Func); |
425 | } |
426 | if(myTrimmed->IsPeriodic()) |
427 | Handle(Law_Composite)::DownCast(EvolAroundT)->SetPeriodic(); |
428 | |
429 | TLaw = EvolAroundT; |
430 | //OCC78 |
431 | Standard_Integer iEnd = SeqPoles.Length(); |
432 | HArrPoles = new TColStd_HArray1OfReal(1, iEnd); |
433 | HArrAngle = new TColStd_HArray1OfReal(1, iEnd); |
434 | HArrTangent = new TColgp_HArray1OfVec(1, iEnd); |
435 | HArrNormal = new TColgp_HArray1OfVec(1, iEnd); |
436 | for(i = 1; i <= iEnd; i++){ |
437 | HArrPoles->ChangeValue(i) = SeqPoles(i); |
438 | HArrAngle->ChangeValue(i) = SeqAngle(i); |
439 | HArrTangent->ChangeValue(i) = SeqTangent(i); |
440 | HArrNormal->ChangeValue(i) = SeqNormal(i); |
441 | }; |
a31abc03 |
442 | |
7fd59977 |
443 | #if DRAW |
444 | if (Affich) { |
445 | draw(EvolAroundT); |
446 | } |
447 | #endif |
448 | } |
449 | |
450 | //=============================================================== |
451 | // Function : InitInterval |
452 | // Purpose : Compute the angle law on a span |
453 | //=============================================================== |
454 | Standard_Boolean GeomFill_CorrectedFrenet:: |
455 | InitInterval(const Standard_Real First, const Standard_Real Last, |
456 | const Standard_Real Step, |
457 | Standard_Real& startAng, gp_Vec& prevTangent, |
458 | gp_Vec& prevNormal, gp_Vec& aT, gp_Vec& aN, |
459 | Handle(Law_Function)& FuncInt, |
460 | TColStd_SequenceOfReal& SeqPoles, |
461 | TColStd_SequenceOfReal& SeqAngle, |
462 | TColgp_SequenceOfVec& SeqTangent, |
463 | TColgp_SequenceOfVec& SeqNormal) const |
464 | { |
465 | Bnd_Box Boite; |
466 | gp_Vec Tangent, Normal, BN, cross; |
467 | TColStd_SequenceOfReal parameters; |
468 | TColStd_SequenceOfReal EvolAT; |
96a95605 |
469 | Standard_Real Param = First, L, norm; |
7fd59977 |
470 | Standard_Boolean isZero = Standard_True, isConst = Standard_True; |
a31abc03 |
471 | const Standard_Real minnorm = 1.e-16; |
7fd59977 |
472 | Standard_Integer i; |
473 | gp_Pnt PonC; |
474 | gp_Vec D1; |
475 | |
476 | frenet->SetInterval(First, Last); //To have the rigth evaluation at bounds |
477 | GeomFill_SnglrFunc CS(myCurve); |
478 | BndLib_Add3dCurve::Add(CS, First, Last, 1.e-2, Boite); |
7fd59977 |
479 | |
480 | aT = gp_Vec(0, 0, 0); |
481 | aN = gp_Vec(0, 0, 0); |
482 | |
1d47d8d0 |
483 | Standard_Real angleAT = 0., currParam, currStep = Step; |
7fd59977 |
484 | |
485 | Handle( Geom_Plane ) aPlane; |
a31abc03 |
486 | Standard_Boolean isPlanar = Standard_False; |
487 | if (!myForEvaluation) |
488 | isPlanar = FindPlane( myCurve, aPlane ); |
7fd59977 |
489 | |
490 | i = 1; |
491 | currParam = Param; |
492 | Standard_Real DLast = Last - Precision::PConfusion(); |
493 | |
494 | while (Param < Last) { |
495 | if (currParam > DLast) { |
496 | currStep = DLast - Param; |
497 | currParam = Last; |
498 | } |
499 | if (isPlanar) |
500 | currParam = Last; |
501 | |
502 | frenet->D0(currParam, Tangent, Normal, BN); |
c6541a0c |
503 | if (prevTangent.Angle(Tangent) < M_PI/3 || i == 1) { |
7fd59977 |
504 | parameters.Append(currParam); |
505 | //OCC78 |
506 | SeqPoles.Append(Param); |
507 | SeqAngle.Append(i > 1? EvolAT(i-1) : startAng); |
508 | SeqTangent.Append(prevTangent); |
509 | SeqNormal.Append(prevNormal); |
510 | angleAT = CalcAngleAT(Tangent,Normal,prevTangent,prevNormal); |
511 | |
512 | if(isConst && i > 1) |
513 | if(Abs(angleAT) > Precision::PConfusion()) |
514 | isConst = Standard_False; |
515 | |
516 | angleAT += (i > 1) ? EvolAT(i-1) : startAng; |
517 | EvolAT.Append(angleAT); |
518 | prevNormal = Normal; |
519 | |
520 | if(isZero) |
521 | if(Abs(angleAT) > Precision::PConfusion()) |
522 | isZero = Standard_False; |
523 | |
524 | aT += Tangent; |
525 | cross = Tangent.Crossed(Normal); |
526 | aN.SetLinearForm(Sin(angleAT), cross, |
527 | 1 - Cos(angleAT), Tangent.Crossed(cross), |
528 | Normal+aN); |
529 | prevTangent = Tangent; |
530 | Param = currParam; |
531 | i++; |
532 | |
533 | //Evaluate the Next step |
534 | CS.D1(Param, PonC, D1); |
a31abc03 |
535 | |
536 | L = PonC.XYZ().Modulus()/2; |
7fd59977 |
537 | norm = D1.Magnitude(); |
a31abc03 |
538 | if (norm <= gp::Resolution()) |
539 | { |
540 | //norm = 2.*gp::Resolution(); |
541 | norm = minnorm; |
7fd59977 |
542 | } |
543 | currStep = L / norm; |
a31abc03 |
544 | if (currStep <= gp::Resolution()) //L = 0 => curvature = 0, linear segment |
545 | currStep = Step; |
546 | if (currStep < Precision::Confusion()) //too small step |
547 | currStep = Precision::Confusion(); |
548 | if (currStep > Step) //too big step |
549 | currStep = Step;//default value |
7fd59977 |
550 | } |
551 | else |
552 | currStep /= 2; // Step too long ! |
553 | |
554 | currParam = Param + currStep; |
555 | } |
556 | |
557 | if (! isPlanar) |
558 | { |
559 | aT /= parameters.Length() - 1; |
560 | aN /= parameters.Length() - 1; |
561 | } |
562 | startAng = angleAT; |
563 | |
564 | // Interpolation |
565 | if (isConst || isPlanar) { |
566 | FuncInt = new Law_Constant(); |
567 | Handle(Law_Constant)::DownCast(FuncInt)->Set( angleAT, First, Last ); |
568 | } |
569 | |
570 | else { |
571 | Standard_Integer Length = parameters.Length(); |
572 | Handle(TColStd_HArray1OfReal) pararr = |
573 | new TColStd_HArray1OfReal(1, Length); |
574 | Handle(TColStd_HArray1OfReal) angleATarr = |
575 | new TColStd_HArray1OfReal(1, Length); |
576 | |
577 | |
578 | for (i = 1; i <= Length; i++) { |
579 | pararr->ChangeValue(i) = parameters(i); |
580 | angleATarr->ChangeValue(i) = EvolAT(i); |
581 | } |
582 | |
583 | #if DEB |
584 | if (Affich) { |
585 | cout<<"NormalEvolution"<<endl; |
586 | for (i = 1; i <= Length; i++) { |
587 | cout<<"("<<pararr->Value(i)<<", "<<angleATarr->Value(i)<<")" << endl; |
588 | } |
589 | cout<<endl; |
590 | } |
591 | #endif |
592 | |
593 | Law_Interpolate lawAT(angleATarr, pararr, |
594 | Standard_False, Precision::PConfusion()); |
595 | lawAT.Perform(); |
596 | Handle(Law_BSpline) BS = lawAT.Curve(); |
597 | smoothlaw(BS, angleATarr, pararr, 0.1); |
598 | |
599 | FuncInt = new Law_BSpFunc(BS, First, Last); |
600 | } |
601 | return isZero; |
602 | } |
603 | //=============================================================== |
604 | // Function : CalcAngleAT (OCC78) |
605 | // Purpose : Calculate angle of rotation of trihedron normal and its derivatives relative |
606 | // at any position on his curve |
607 | //=============================================================== |
608 | Standard_Real GeomFill_CorrectedFrenet::CalcAngleAT(const gp_Vec& Tangent, const gp_Vec& Normal, |
609 | const gp_Vec& prevTangent, const gp_Vec& prevNormal) const |
610 | { |
611 | Standard_Real angle; |
612 | gp_Vec Normal_rot, cross; |
613 | angle = Tangent.Angle(prevTangent); |
614 | if (Abs(angle) > Precision::Angular()) { |
615 | cross = Tangent.Crossed(prevTangent).Normalized(); |
616 | Normal_rot = Normal + sin(angle)*cross.Crossed(Normal) + |
617 | (1 - cos(angle))*cross.Crossed(cross.Crossed(Normal)); |
618 | } |
619 | else |
620 | Normal_rot = Normal; |
621 | Standard_Real angleAT = Normal_rot.Angle(prevNormal); |
c6541a0c |
622 | if(angleAT > Precision::Angular() && M_PI - angleAT > Precision::Angular()) |
7fd59977 |
623 | if (Normal_rot.Crossed(prevNormal).IsOpposite(prevTangent, Precision::Angular())) |
624 | angleAT = -angleAT; |
625 | return angleAT; |
626 | }; |
627 | //=============================================================== |
628 | // Function : ... (OCC78) |
629 | // Purpose : This family of functions produce conversion of angle utility |
630 | //=============================================================== |
7fd59977 |
631 | static Standard_Real corr2PI_PI(Standard_Real Ang){ |
c6541a0c |
632 | return Ang = (Ang < M_PI? Ang: Ang-2*M_PI); |
7fd59977 |
633 | }; |
634 | static Standard_Real diffAng(Standard_Real A, Standard_Real Ao){ |
c6541a0c |
635 | Standard_Real dA = (A-Ao) - Floor((A-Ao)/2.0/M_PI)*2.0*M_PI; |
7fd59977 |
636 | return dA = dA >= 0? corr2PI_PI(dA): -corr2PI_PI(-dA); |
637 | }; |
638 | //=============================================================== |
639 | // Function : CalcAngleAT (OCC78) |
640 | // Purpose : Calculate angle of rotation of trihedron normal and its derivatives relative |
641 | // at any position on his curve |
642 | //=============================================================== |
643 | Standard_Real GeomFill_CorrectedFrenet::GetAngleAT(const Standard_Real Param) const{ |
644 | // Search index of low margin from poles of TLaw by bisection method |
645 | Standard_Integer iB = 1, iE = HArrPoles->Length(), iC = (iE+iB)/2; |
646 | if(Param == HArrPoles->Value(iB)) return TLaw->Value(Param); |
647 | if(Param > HArrPoles->Value(iE)) iC = iE; |
648 | if(iC < iE){ |
649 | while(!(HArrPoles->Value(iC) <= Param && Param <= HArrPoles->Value(iC+1))){ |
650 | if(HArrPoles->Value(iC) < Param) iB = iC; else iE = iC; |
651 | iC = (iE+iB)/2; |
652 | }; |
653 | if(HArrPoles->Value(iC) == Param || Param == HArrPoles->Value(iC+1)) return TLaw->Value(Param); |
654 | }; |
7fd59977 |
655 | // Calculate differenciation between apporoximated and local values of AngleAT |
656 | Standard_Real AngP = TLaw->Value(Param), AngPo = HArrAngle->Value(iC), dAng = AngP - AngPo; |
657 | gp_Vec Tangent, Normal, BN; |
658 | frenet->D0(Param, Tangent, Normal, BN); |
659 | Standard_Real DAng = CalcAngleAT(Tangent, Normal, HArrTangent->Value(iC), HArrNormal->Value(iC)); |
660 | Standard_Real DA = diffAng(DAng,dAng); |
661 | // The correction (there is core of OCC78 bug) |
c6541a0c |
662 | if(Abs(DA) > M_PI/2.0){ |
7fd59977 |
663 | AngP = AngPo + DAng; |
664 | }; |
665 | return AngP; |
666 | }; |
667 | //=============================================================== |
668 | // Function : D0 |
669 | // Purpose : |
670 | //=============================================================== |
671 | Standard_Boolean GeomFill_CorrectedFrenet::D0(const Standard_Real Param, |
672 | gp_Vec& Tangent, |
673 | gp_Vec& Normal, |
674 | gp_Vec& BiNormal) |
675 | { |
676 | frenet->D0(Param, Tangent, Normal, BiNormal); |
677 | if (isFrenet) return Standard_True; |
678 | |
679 | Standard_Real angleAT; |
680 | //angleAT = TLaw->Value(Param); |
681 | angleAT = GetAngleAT(Param); //OCC78 |
682 | |
683 | // rotation around Tangent |
684 | gp_Vec cross; |
685 | cross = Tangent.Crossed(Normal); |
686 | Normal.SetLinearForm(Sin(angleAT), cross, |
687 | (1 - Cos(angleAT)), Tangent.Crossed(cross), |
688 | Normal); |
689 | BiNormal = Tangent.Crossed(Normal); |
690 | |
691 | return Standard_True; |
692 | } |
693 | |
694 | //=============================================================== |
695 | // Function : D1 |
696 | // Purpose : |
697 | //=============================================================== |
698 | |
699 | Standard_Boolean GeomFill_CorrectedFrenet::D1(const Standard_Real Param, |
700 | gp_Vec& Tangent, |
701 | gp_Vec& DTangent, |
702 | gp_Vec& Normal, |
703 | gp_Vec& DNormal, |
704 | gp_Vec& BiNormal, |
705 | gp_Vec& DBiNormal) |
706 | { |
707 | frenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal); |
708 | if (isFrenet) return Standard_True; |
709 | |
710 | Standard_Real angleAT, d_angleAT; |
711 | Standard_Real sina, cosa; |
712 | |
713 | TLaw->D1(Param, angleAT, d_angleAT); |
714 | angleAT = GetAngleAT(Param); //OCC78 |
715 | |
716 | gp_Vec cross, dcross, tcross, dtcross, aux; |
717 | sina = Sin(angleAT); |
718 | cosa = Cos(angleAT); |
719 | |
720 | cross = Tangent.Crossed(Normal); |
721 | dcross.SetLinearForm(1, DTangent.Crossed(Normal), |
722 | Tangent.Crossed(DNormal)); |
723 | |
724 | tcross = Tangent.Crossed(cross); |
725 | dtcross.SetLinearForm(1, DTangent.Crossed(cross), |
726 | Tangent.Crossed(dcross)); |
727 | |
728 | aux.SetLinearForm(sina, dcross, |
729 | cosa*d_angleAT, cross); |
730 | aux.SetLinearForm(1 - cosa, dtcross, |
731 | sina*d_angleAT, tcross, |
732 | aux); |
733 | DNormal+=aux; |
734 | |
735 | Normal.SetLinearForm( sina, cross, |
736 | (1 - cosa), tcross, |
737 | Normal); |
738 | |
739 | BiNormal = Tangent.Crossed(Normal); |
740 | |
741 | DBiNormal.SetLinearForm(1, DTangent.Crossed(Normal), |
742 | Tangent.Crossed(DNormal)); |
743 | |
744 | // for test |
745 | /* gp_Vec FDN, Tf, Nf, BNf; |
746 | Standard_Real h; |
747 | h = 1.0e-8; |
748 | if (Param + h > myTrimmed->LastParameter()) h = -h; |
749 | D0(Param + h, Tf, Nf, BNf); |
750 | FDN = (Nf - Normal)/h; |
751 | cout<<"Param = "<<Param<<endl; |
752 | cout<<"DN = ("<<DNormal.X()<<", "<<DNormal.Y()<<", "<<DNormal.Z()<<")"<<endl; |
753 | cout<<"FDN = ("<<FDN.X()<<", "<<FDN.Y()<<", "<<FDN.Z()<<")"<<endl; |
754 | */ |
755 | |
756 | return Standard_True; |
757 | } |
758 | |
759 | //=============================================================== |
760 | // Function : D2 |
761 | // Purpose : |
762 | //=============================================================== |
763 | Standard_Boolean GeomFill_CorrectedFrenet::D2(const Standard_Real Param, |
764 | gp_Vec& Tangent, |
765 | gp_Vec& DTangent, |
766 | gp_Vec& D2Tangent, |
767 | gp_Vec& Normal, |
768 | gp_Vec& DNormal, |
769 | gp_Vec& D2Normal, |
770 | gp_Vec& BiNormal, |
771 | gp_Vec& DBiNormal, |
772 | gp_Vec& D2BiNormal) |
773 | { |
774 | frenet->D2(Param, Tangent, DTangent, D2Tangent, |
775 | Normal, DNormal, D2Normal, |
776 | BiNormal, DBiNormal, D2BiNormal); |
777 | if (isFrenet) return Standard_True; |
778 | |
779 | Standard_Real angleAT, d_angleAT, d2_angleAT; |
780 | Standard_Real sina, cosa; |
781 | TLaw->D2(Param, angleAT, d_angleAT, d2_angleAT); |
782 | angleAT = GetAngleAT(Param); //OCC78 |
783 | |
784 | gp_Vec cross, dcross, d2cross, tcross, dtcross, d2tcross, aux; |
785 | sina = Sin(angleAT); |
786 | cosa = Cos(angleAT); |
787 | cross = Tangent.Crossed(Normal); |
788 | dcross.SetLinearForm(1, DTangent.Crossed(Normal), |
789 | Tangent.Crossed(DNormal)); |
790 | d2cross.SetLinearForm(1, D2Tangent.Crossed(Normal), |
791 | 2, DTangent.Crossed(DNormal), |
792 | Tangent.Crossed(D2Normal)); |
793 | |
794 | |
795 | tcross = Tangent.Crossed(cross); |
796 | dtcross.SetLinearForm(1, DTangent.Crossed(cross), |
797 | Tangent.Crossed(dcross)); |
798 | d2tcross.SetLinearForm(1, D2Tangent.Crossed(cross), |
799 | 2, DTangent.Crossed(dcross), |
800 | Tangent.Crossed(d2cross)); |
801 | |
802 | |
803 | aux.SetLinearForm(sina, d2cross, |
804 | 2*cosa*d_angleAT, dcross, |
805 | cosa*d2_angleAT - sina*d_angleAT*d_angleAT, cross); |
806 | |
807 | aux.SetLinearForm(1 - cosa, d2tcross, |
808 | 2*sina*d_angleAT, dtcross, |
809 | cosa*d_angleAT*d_angleAT + sina*d2_angleAT, tcross, |
810 | aux); |
811 | D2Normal += aux; |
812 | |
813 | /* D2Normal += sina*(D2Tangent.Crossed(Normal) + 2*DTangent.Crossed(DNormal) + Tangent.Crossed(D2Normal)) + |
814 | 2*cosa*d_angleAT*(DTangent.Crossed(Normal) + Tangent.Crossed(DNormal)) + |
815 | (cosa*d2_angleAT - sina*d_angleAT*d_angleAT)*Tangent.Crossed(Normal) + |
816 | 2*sina*d_angleAT*(DTangent.Crossed(Tangent.Crossed(Normal)) + Tangent.Crossed(DTangent.Crossed(Normal)) + Tangent.Crossed(Tangent.Crossed(DNormal))) + |
817 | (1 - cosa)*(D2Tangent.Crossed(Tangent.Crossed(Normal)) + Tangent.Crossed(D2Tangent.Crossed(Normal)) + Tangent.Crossed(Tangent.Crossed(D2Normal)) + 2*DTangent.Crossed(DTangent.Crossed(Normal)) + 2*DTangent.Crossed(Tangent.Crossed(DNormal)) + 2*Tangent.Crossed(DTangent.Crossed(DNormal))) |
818 | + |
819 | (cosa*d_angleAT*d_angleAT + sina*d2_angleAT)*Tangent.Crossed(Tangent.Crossed(Normal));*/ |
820 | |
821 | |
822 | aux.SetLinearForm(sina, dcross, |
823 | cosa*d_angleAT, cross); |
824 | aux.SetLinearForm(1 - cosa, dtcross, |
825 | sina*d_angleAT, tcross, |
826 | aux); |
827 | DNormal+=aux; |
828 | |
829 | |
830 | Normal.SetLinearForm( sina, cross, |
831 | (1 - cosa), tcross, |
832 | Normal); |
833 | |
834 | BiNormal = Tangent.Crossed(Normal); |
835 | |
836 | DBiNormal.SetLinearForm(1, DTangent.Crossed(Normal), |
837 | Tangent.Crossed(DNormal)); |
838 | |
839 | D2BiNormal.SetLinearForm(1, D2Tangent.Crossed(Normal), |
840 | 2, DTangent.Crossed(DNormal), |
841 | Tangent.Crossed(D2Normal)); |
842 | |
843 | // for test |
844 | /* gp_Vec FD2N, FD2T, FD2BN, Tf, DTf, Nf, DNf, BNf, DBNf; |
845 | Standard_Real h; |
846 | h = 1.0e-8; |
847 | if (Param + h > myTrimmed->LastParameter()) h = -h; |
848 | D1(Param + h, Tf, DTf, Nf, DNf, BNf, DBNf); |
849 | FD2N = (DNf - DNormal)/h; |
850 | FD2T = (DTf - DTangent)/h; |
851 | FD2BN = (DBNf - DBiNormal)/h; |
852 | cout<<"Param = "<<Param<<endl; |
853 | cout<<"D2N = ("<<D2Normal.X()<<", "<<D2Normal.Y()<<", "<<D2Normal.Z()<<")"<<endl; |
854 | cout<<"FD2N = ("<<FD2N.X()<<", "<<FD2N.Y()<<", "<<FD2N.Z()<<")"<<endl<<endl; |
855 | cout<<"D2T = ("<<D2Tangent.X()<<", "<<D2Tangent.Y()<<", "<<D2Tangent.Z()<<")"<<endl; |
856 | cout<<"FD2T = ("<<FD2T.X()<<", "<<FD2T.Y()<<", "<<FD2T.Z()<<")"<<endl<<endl; |
857 | cout<<"D2BN = ("<<D2BiNormal.X()<<", "<<D2BiNormal.Y()<<", "<<D2BiNormal.Z()<<")"<<endl; |
858 | cout<<"FD2BN = ("<<FD2BN.X()<<", "<<FD2BN.Y()<<", "<<FD2BN.Z()<<")"<<endl<<endl; |
859 | */ |
860 | // |
861 | return Standard_True; |
862 | } |
863 | |
864 | //=============================================================== |
865 | // Function : NbIntervals |
866 | // Purpose : |
867 | //=============================================================== |
868 | Standard_Integer GeomFill_CorrectedFrenet::NbIntervals(const GeomAbs_Shape S) const |
869 | { |
870 | Standard_Integer NbFrenet, NbLaw; |
871 | NbFrenet = frenet->NbIntervals(S); |
872 | if (isFrenet) return NbFrenet; |
873 | |
874 | NbLaw = EvolAroundT->NbIntervals(S); |
875 | if (NbFrenet == 1) |
876 | return NbLaw; |
877 | |
878 | TColStd_Array1OfReal FrenetInt(1, NbFrenet + 1); |
879 | TColStd_Array1OfReal LawInt(1, NbLaw + 1); |
880 | TColStd_SequenceOfReal Fusion; |
881 | |
882 | frenet->Intervals(FrenetInt, S); |
883 | EvolAroundT->Intervals(LawInt, S); |
884 | GeomLib::FuseIntervals(FrenetInt, LawInt, Fusion); |
885 | |
886 | return Fusion.Length()-1; |
887 | } |
888 | |
889 | //=============================================================== |
890 | // Function : Intervals |
891 | // Purpose : |
892 | //=============================================================== |
893 | void GeomFill_CorrectedFrenet::Intervals(TColStd_Array1OfReal& T, |
894 | const GeomAbs_Shape S) const |
895 | { |
896 | Standard_Integer NbFrenet, NbLaw; |
897 | if (isFrenet) { |
898 | frenet->Intervals(T, S); |
899 | return; |
900 | } |
901 | |
902 | NbFrenet = frenet->NbIntervals(S); |
903 | if(NbFrenet==1) { |
904 | EvolAroundT->Intervals(T, S); |
905 | } |
906 | |
907 | NbLaw = EvolAroundT->NbIntervals(S); |
908 | |
909 | TColStd_Array1OfReal FrenetInt(1, NbFrenet + 1); |
910 | TColStd_Array1OfReal LawInt(1, NbLaw + 1); |
911 | TColStd_SequenceOfReal Fusion; |
912 | |
913 | frenet->Intervals(FrenetInt, S); |
914 | EvolAroundT->Intervals(LawInt, S); |
915 | GeomLib::FuseIntervals(FrenetInt, LawInt, Fusion); |
916 | |
917 | for(Standard_Integer i = 1; i <= Fusion.Length(); i++) |
918 | T.ChangeValue(i) = Fusion.Value(i); |
919 | } |
920 | |
921 | //=============================================================== |
922 | // Function : SetInterval |
923 | // Purpose : |
924 | //=============================================================== |
925 | void GeomFill_CorrectedFrenet::SetInterval(const Standard_Real First, |
926 | const Standard_Real Last) |
927 | { |
928 | GeomFill_TrihedronLaw::SetInterval(First, Last); |
929 | frenet->SetInterval(First, Last); |
930 | if (!isFrenet) TLaw = EvolAroundT->Trim(First, Last, |
931 | Precision::PConfusion()/2); |
932 | } |
933 | |
934 | //=============================================================== |
a31abc03 |
935 | // Function : EvaluateBestMode |
936 | // Purpose : |
937 | //=============================================================== |
938 | GeomFill_Trihedron GeomFill_CorrectedFrenet::EvaluateBestMode() |
939 | { |
940 | if (EvolAroundT.IsNull()) |
941 | return GeomFill_IsFrenet; //Frenet |
942 | |
943 | const Standard_Real MaxAngle = 3.*M_PI/4.; |
944 | const Standard_Real MaxTorsion = 100.; |
945 | |
946 | Standard_Real Step, u, v, tmin, tmax; |
947 | Standard_Integer NbInt, i, j, k = 1; |
948 | NbInt = EvolAroundT->NbIntervals(GeomAbs_CN); |
949 | TColStd_Array1OfReal Int(1, NbInt+1); |
950 | EvolAroundT->Intervals(Int, GeomAbs_CN); |
951 | gp_Pnt2d old; |
952 | gp_Vec2d aVec, PrevVec; |
953 | |
954 | Standard_Integer NbSamples = 10; |
955 | for(i = 1; i <= NbInt; i++){ |
956 | tmin = Int(i); |
957 | tmax = Int(i+1); |
958 | Standard_Real Torsion = ComputeTorsion(tmin, myTrimmed); |
959 | if (Abs(Torsion) > MaxTorsion) |
960 | return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron |
961 | |
962 | Handle(Law_Function) trimmedlaw = EvolAroundT->Trim(tmin, tmax, Precision::PConfusion()/2); |
963 | Step = (Int(i+1)-Int(i))/NbSamples; |
964 | for (j = 0; j <= NbSamples; j++) { |
965 | u = tmin + j*Step; |
966 | v = trimmedlaw->Value(u); |
967 | gp_Pnt2d point2d(u,v); |
968 | if (j != 0) |
969 | { |
970 | aVec.SetXY(point2d.XY() - old.XY()); |
971 | if (k > 2) |
972 | { |
973 | Standard_Real theAngle = PrevVec.Angle(aVec); |
974 | if (Abs(theAngle) > MaxAngle) |
975 | return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron |
976 | } |
977 | PrevVec = aVec; |
978 | } |
979 | old = point2d; |
980 | k++; |
981 | } |
982 | } |
983 | |
984 | return GeomFill_IsCorrectedFrenet; //CorrectedFrenet |
985 | } |
986 | |
987 | //=============================================================== |
7fd59977 |
988 | // Function : GetAverageLaw |
989 | // Purpose : |
990 | //=============================================================== |
991 | void GeomFill_CorrectedFrenet::GetAverageLaw(gp_Vec& ATangent, |
992 | gp_Vec& ANormal, |
993 | gp_Vec& ABiNormal) |
994 | { |
995 | if (isFrenet) frenet->GetAverageLaw(ATangent, ANormal, ABiNormal); |
996 | else { |
997 | ATangent = AT; |
998 | ANormal = AN; |
999 | ABiNormal = ATangent; |
1000 | ABiNormal.Cross(ANormal); |
1001 | } |
1002 | } |
1003 | |
1004 | //=============================================================== |
1005 | // Function : IsConstant |
1006 | // Purpose : |
1007 | //=============================================================== |
1008 | Standard_Boolean GeomFill_CorrectedFrenet::IsConstant() const |
1009 | { |
1010 | return (myCurve->GetType() == GeomAbs_Line); |
1011 | } |
1012 | |
1013 | //=============================================================== |
1014 | // Function : IsOnlyBy3dCurve |
1015 | // Purpose : |
1016 | //=============================================================== |
1017 | Standard_Boolean GeomFill_CorrectedFrenet::IsOnlyBy3dCurve() const |
1018 | { |
1019 | return Standard_True; |
1020 | } |