0024921: ShapeAnalysis_Curve::ValidateRange doesn't adjust the range for periodic...
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_Curve.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14// pdn 04.12.98 Add method using Adaptor_Curve
15//:j8 abv 10.12.98 TR10 r0501_db.stp #9423
16//pdn 25.12.98 private method ProjectAct
17//szv#4 S4163
18//:s5 abv 22.04.99 Adding debug printouts in catch {} blocks
19// abv 14.05.99 S4174: Adding method for exact computing of the boundary box
20// gka 21.06.99 S4208: adding method NextProject(Adaptor_Curve)
21// msv 30.05.00 correct IsPlanar for a conic curve
22#include <ShapeAnalysis_Curve.ixx>
23
24#include <ElCLib.hxx>
25
26#include <Geom2d_BoundedCurve.hxx>
27#include <Geom2d_Line.hxx>
28#include <Geom_BSplineCurve.hxx>
29#include <GeomAdaptor_Curve.hxx>
30
31#include <Precision.hxx>
32
33#include <Standard_ErrorHandler.hxx>
34#include <Standard_Failure.hxx>
35#include <Adaptor3d_Curve.hxx>
36#include <Extrema_ExtPC.hxx>
37#include <ShapeAnalysis.hxx>
38#include <TColgp_SequenceOfPnt.hxx>
39#include <Geom_Line.hxx>
40#include <Geom_Conic.hxx>
41#include <Geom_TrimmedCurve.hxx>
42#include <Geom_OffsetCurve.hxx>
43#include <Geom_BezierCurve.hxx>
44#include <ShapeExtend_ComplexCurve.hxx>
45#include <Geom2d_Conic.hxx>
46#include <Geom2d_TrimmedCurve.hxx>
47#include <Geom2d_BSplineCurve.hxx>
48#include <Geom2d_BezierCurve.hxx>
49
50#include <Geom2d_OffsetCurve.hxx>
51#include <Geom2dInt_Geom2dCurveTool.hxx>
52#include <Geom2dAdaptor_Curve.hxx>
53#include <Geom_Circle.hxx>
a9ae57b9 54#include <Extrema_LocateExtPC.hxx>
7fd59977 55
56//=======================================================================
57//function : ProjectOnSegments
58//purpose :
59//=======================================================================
60
61static void ProjectOnSegments (const Adaptor3d_Curve& AC, const gp_Pnt& P3D,
62 const Standard_Integer nbseg,
63 Standard_Real& uMin, Standard_Real& uMax,
64 Standard_Real& distmin, gp_Pnt& proj, Standard_Real& param)
65{
66 // On considere <nbseg> points sur [uMin,uMax]
67 // Quel est le plus proche. Et quel est le nouvel intervalle
68 // (il ne peut pas deborder l ancien)
96a85238
RL
69 Standard_Real u, dist2, delta = (nbseg == 0)? 0 : (uMax-uMin)/nbseg; //szv#4:S4163:12Mar99 anti-exception
70 Standard_Real distmin2 = distmin * distmin;
71 Standard_Boolean aHasChanged = Standard_False;
7fd59977 72 for (Standard_Integer i = 0; i <= nbseg; i ++) {
73 u = uMin + (delta * i);
74 gp_Pnt PU = AC.Value (u);
96a85238
RL
75 dist2 = PU.SquareDistance (P3D);
76 if (dist2 < distmin2) { distmin2 = dist2; proj = PU; param = u; aHasChanged = Standard_True; }
7fd59977 77 }
96a85238
RL
78 if (aHasChanged)
79 distmin = Sqrt (distmin2);
7fd59977 80#ifdef DEBUG
81 cout<<"ShapeAnalysis_Geom:Project, param="<<param<<" -> distmin="<<distmin<<endl;
82#endif
83
84 uMax = Min (uMax, param+delta);
85 uMin = Max (uMin, param-delta);
86}
87
88
7fd59977 89//=======================================================================
90//function : Project
91//purpose :
92//=======================================================================
93
94Standard_Real ShapeAnalysis_Curve::Project(const Handle(Geom_Curve)& C3D,
95 const gp_Pnt& P3D,
96 const Standard_Real preci,
97 gp_Pnt& proj,
98 Standard_Real& param,
99 const Standard_Boolean AdjustToEnds) const
100{
101 Standard_Real uMin = C3D->FirstParameter();
102 Standard_Real uMax = C3D->LastParameter();
103 if (uMin < uMax) return Project (C3D,P3D,preci,proj,param,uMin,uMax,AdjustToEnds);
104 else return Project (C3D,P3D,preci,proj,param,uMax,uMin,AdjustToEnds);
105}
106
107//=======================================================================
108//function : Project
109//purpose :
110//=======================================================================
111
112Standard_Real ShapeAnalysis_Curve::Project(const Handle(Geom_Curve)& C3D,
113 const gp_Pnt& P3D,
114 const Standard_Real preci,
115 gp_Pnt& proj,
116 Standard_Real& param,
117 const Standard_Real cf,
118 const Standard_Real cl,
119 const Standard_Boolean AdjustToEnds) const
120{
121 Standard_Real distmin;
122 Standard_Real uMin = (cf < cl ? cf : cl);
123 Standard_Real uMax = (cf < cl ? cl : cf);
124
125 if (C3D->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
126 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
127 gp_Pnt LowBound = C3D->Value(uMin);
128 gp_Pnt HigBound = C3D->Value(uMax);
129 distmin = LowBound.Distance(P3D);
130 if (distmin <= prec) {
131 param = uMin;
132 proj = LowBound;
133 return distmin;
134 }
135 distmin = HigBound.Distance(P3D);
136 if (distmin <= prec) {
137 param = uMax;
138 proj = HigBound;
139 return distmin;
140 }
141 }
142
143 GeomAdaptor_Curve GAC(C3D, uMin, uMax);
144 if (!C3D->IsClosed()) {
145 //modified by rln on 16/12/97 after CSR# PRO11641 entity 20767
146 //the VIso was not closed (according to C3D->IsClosed()) while it "almost"
147 //was (the distance between ends of the curve was a little bit more than
148 //Precision::Confusion())
149 //in that case value 0.1 was too much and this method returned not correct parameter
150 //uMin = uMin - 0.1;
151 //uMax = uMax + 0.1;
152 // modified by pdn on 01.07.98 after BUC60195 entity 1952 (Min() added)
153 Standard_Real delta = Min (GAC.Resolution (preci), (uMax - uMin) * 0.1);
154 uMin -= delta;
155 uMax += delta;
156 GAC.Load(C3D, uMin, uMax);
157 }
158
159 return ProjectAct(GAC, P3D, preci, proj, param);
160}
161
162//=======================================================================
163//function : Project
164//purpose :
165//=======================================================================
166
167Standard_Real ShapeAnalysis_Curve::Project(const Adaptor3d_Curve& C3D,
168 const gp_Pnt& P3D,
169 const Standard_Real preci,
170 gp_Pnt& proj,
171 Standard_Real& param,
172 const Standard_Boolean AdjustToEnds) const
173
174{
62f22593 175
7fd59977 176 Standard_Real uMin = C3D.FirstParameter();
177 Standard_Real uMax = C3D.LastParameter();
62f22593 178
179 if (Precision::IsInfinite(uMin) && Precision::IsInfinite(uMax))
180 return ProjectAct(C3D, P3D, preci, proj, param);
181
182 Standard_Real distmin_L = Precision::Infinite(), distmin_H = Precision::Infinite();
183 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
184 gp_Pnt LowBound = C3D.Value(uMin);
185 gp_Pnt HigBound = C3D.Value(uMax);
186 distmin_L = LowBound.Distance(P3D);
187 distmin_H = HigBound.Distance(P3D);
188
189 if (distmin_L <= prec) {
190 param = uMin;
191 proj = LowBound;
192 return distmin_L;
7fd59977 193 }
62f22593 194
195 if (distmin_H <= prec) {
196 param = uMax;
197 proj = HigBound;
198 return distmin_H;
199 }
200
201 Standard_Real distProj = ProjectAct(C3D, P3D, preci, proj, param);
202 if( distProj < distmin_L + Precision::Confusion() && distProj < distmin_H + Precision::Confusion())
203 return distProj;
204
205 if( distmin_L < distmin_H)
206 {
207 param = uMin;
208 proj = LowBound;
209 return distmin_L;
210 }
211 param = uMax;
212 proj = HigBound;
213 return distmin_H;
214
7fd59977 215}
216
217//=======================================================================
218//function : ProjectAct
219//purpose :
220//=======================================================================
221
222Standard_Real ShapeAnalysis_Curve::ProjectAct(const Adaptor3d_Curve& C3D,
223 const gp_Pnt& P3D,
224 const Standard_Real preci,
225 gp_Pnt& proj,
226 Standard_Real& param) const
227
228{
7fd59977 229 Standard_Boolean OK = Standard_False;
62f22593 230 param = 0.;
a9ae57b9 231 try {
232 OCC_CATCH_SIGNALS
233 Extrema_ExtPC myExtPC(P3D,C3D);
234 if ( myExtPC.IsDone() && ( myExtPC.NbExt() > 0) ) {
235 Standard_Real dist2, dist2Min = myExtPC.SquareDistance(1);
236 Standard_Integer index = 1;
237 for ( Standard_Integer i = 2; i <= myExtPC.NbExt(); i++) {
238 dist2 = myExtPC.SquareDistance(i);
239 if ( dist2 < dist2Min) { dist2Min = dist2; index = i; }
7fd59977 240 }
a9ae57b9 241 param = (myExtPC.Point(index)).Parameter();
242 proj = (myExtPC.Point(index)).Value();
243 OK = Standard_True;
7fd59977 244 }
a9ae57b9 245 }
246 catch(Standard_Failure) {
247 OK = Standard_False;
7fd59977 248#ifdef DEB //:s5
a9ae57b9 249 cout << "\nWarning: ShapeAnalysis_Curve::ProjectAct(): Exception in Extrema_ExtPC: ";
250 Standard_Failure::Caught()->Print(cout); cout << endl;
7fd59977 251#endif
7fd59977 252 }
62f22593 253
7fd59977 254 //szv#4:S4163:12Mar99 moved
255 Standard_Real uMin = C3D.FirstParameter(), uMax = C3D.LastParameter();
256 Standard_Boolean closed = Standard_False; // si on franchit les bornes ...
62f22593 257 Standard_Real distmin = Precision::Infinite(), valclosed = 0.;
7fd59977 258 Standard_Real aModParam = param;
259 Standard_Real aModMin = distmin;
260
261 // PTV 29.05.2002 remember the old solution, cause it could be better
262 Standard_Real anOldParam =0.;
263 Standard_Boolean IsHaveOldSol = Standard_False;
264 gp_Pnt anOldProj;
265 if (OK) {
266 IsHaveOldSol = Standard_True;
267 anOldProj = proj;
268 anOldParam = param;
269 distmin = proj.Distance (P3D);
270 aModMin = distmin;
271 if (distmin > preci) OK = Standard_False;
272 // Cas TrimmedCurve a cheval. Voir la courbe de base.
273 // Si fermee, passer une periode
274 if (C3D.IsClosed()) {
275 closed = Standard_True;
276 valclosed = uMax - uMin; //szv#4:S4163:12Mar99 optimized
277 }
278 }
279
280 if (!OK) {
281 // BUG NICOLAS - Si le point est sur la courbe 0 Solutions
282 // Cela fonctionne avec ElCLib
283
284 // D une facon generale, on essaie de TOUJOURS retourner un resultat
285 // MEME PAS BIEN BON. L appelant pourra decider alors quoi faire
286 param = 0.;
287
288 switch(C3D.GetType()) {
289 case GeomAbs_Circle:
290 {
291 const gp_Circ& aCirc = C3D.Circle();
292 proj = aCirc.Position().Location();
293 if(aCirc.Radius() <= gp::Resolution() ||
294 P3D.SquareDistance(proj) <= gp::Resolution() ) {
295 param = C3D.FirstParameter();
296 proj = proj.XYZ() + aCirc.XAxis().Direction().XYZ() * aCirc.Radius();
297 }
298 else {
299 param = ElCLib::Parameter(aCirc, P3D);
300 proj = ElCLib::Value(param, aCirc);
301 }
302 closed = Standard_True;
c6541a0c 303 valclosed = 2.*M_PI;
7fd59977 304 }
305 break;
306 case GeomAbs_Hyperbola:
307 {
308 param = ElCLib::Parameter(C3D.Hyperbola(), P3D);
309 proj = ElCLib::Value(param, C3D.Hyperbola());
310 }
311 break;
312 case GeomAbs_Parabola:
313 {
314 param = ElCLib::Parameter(C3D.Parabola(), P3D);
315 proj = ElCLib::Value(param, C3D.Parabola());
316 }
317 break;
318 case GeomAbs_Line:
319 {
320 param = ElCLib::Parameter(C3D.Line(), P3D);
321 proj = ElCLib::Value(param, C3D.Line());
322 }
323 break;
324 case GeomAbs_Ellipse:
325 {
326 param = ElCLib::Parameter(C3D.Ellipse(), P3D);
327 proj = ElCLib::Value(param, C3D.Ellipse());
328 closed = Standard_True;
c6541a0c 329 valclosed = 2.*M_PI;
7fd59977 330
331 }
332 break;
333 default:
334 {
335 // on ne va quand meme pas se laisser abattre ... ???
336 // on tente ceci : 21 points sur la courbe, quel est le plus proche
337 distmin = Precision::Infinite();
338 ProjectOnSegments (C3D,P3D,25,uMin,uMax,distmin,proj,param);
a9ae57b9 339 if (distmin <= preci)
340 return distmin;
341 Extrema_LocateExtPC aProjector (P3D, C3D, param/*U0*/, uMin, uMax, preci/*TolU*/);
342 if (aProjector.IsDone())
343 {
344 param = aProjector.Point().Parameter();
345 proj = aProjector.Point().Value();
7fd59977 346 Standard_Real aDistNewton = P3D.Distance(proj);
a9ae57b9 347 if (aDistNewton < aModMin)
7fd59977 348 return aDistNewton;
a9ae57b9 349 }
7fd59977 350 // cout <<"newton failed"<<endl;
351 ProjectOnSegments (C3D,P3D,40,uMin,uMax,distmin,proj,param);
352 if (distmin <= preci) return distmin;
353 ProjectOnSegments (C3D,P3D,20,uMin,uMax,distmin,proj,param);
354 if (distmin <= preci) return distmin;
355 ProjectOnSegments (C3D,P3D,25,uMin,uMax,distmin,proj,param);
356 if (distmin <= preci) return distmin;
357 ProjectOnSegments (C3D,P3D,40,uMin,uMax,distmin,proj,param);
358 if (distmin <= preci) return distmin;
359 // soyons raisonnable ...
360 if(distmin > aModMin) {
361 distmin = aModMin;
362 param = aModParam;
363 }
364
365 return distmin;
366 }
367 }
368 }
369
370 // p = PPOC.LowerDistanceParameter(); cf try
371 if ( closed && ( param < uMin || param > uMax ) )
372 param += ShapeAnalysis::AdjustByPeriod ( param, 0.5 * ( uMin + uMax ), valclosed );
373
374 if (IsHaveOldSol) {
375 // PTV 29.05.2002 Compare old solution and new;
376 Standard_Real adist1, adist2;
377 adist1 = anOldProj.SquareDistance(P3D);
378 adist2 = proj.SquareDistance (P3D);
379 if (adist1 < adist2) {
380 proj = anOldProj;
381 param = anOldParam;
382 }
383 }
384 return proj.Distance (P3D);
385}
386
387
388//=======================================================================
389//function : NextProject
390//purpose : Newton algo for projecting point on curve (S4030)
391//=======================================================================
392
393Standard_Real ShapeAnalysis_Curve::NextProject(const Standard_Real paramPrev,
394 const Handle(Geom_Curve)& C3D,
395 const gp_Pnt& P3D,
396 const Standard_Real preci,
397 gp_Pnt& proj,
398 Standard_Real& param,
399 const Standard_Real cf,
400 const Standard_Real cl,
401 const Standard_Boolean AdjustToEnds) const
402{
403 Standard_Real uMin = (cf < cl ? cf : cl);
404 Standard_Real uMax = (cf < cl ? cl : cf);
62f22593 405 Standard_Real distmin = Precision::Infinite();
7fd59977 406 if (C3D->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
407 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
408 gp_Pnt LowBound = C3D->Value(uMin);
409 gp_Pnt HigBound = C3D->Value(uMax);
410 distmin = LowBound.Distance(P3D);
411 if (distmin <= prec) {
412 param = uMin;
413 proj = LowBound;
414 return distmin;
415 }
416 distmin = HigBound.Distance(P3D);
417 if (distmin <= prec) {
418 param = uMax;
419 proj = HigBound;
420 return distmin;
421 }
422 }
423
424 GeomAdaptor_Curve GAC(C3D, uMin, uMax);
425 if (!C3D->IsClosed()) {
426 //modified by rln on 16/12/97 after CSR# PRO11641 entity 20767
427 //the VIso was not closed (according to C3D->IsClosed()) while it "almost"
428 //was (the distance between ends of the curve was a little bit more than
429 //Precision::Confusion())
430 //in that case value 0.1 was too much and this method returned not correct parameter
431 //uMin = uMin - 0.1;
432 //uMax = uMax + 0.1;
433 // modified by pdn on 01.07.98 after BUC60195 entity 1952 (Min() added)
434 Standard_Real delta = Min (GAC.Resolution (preci), (uMax - uMin) * 0.1);
435 uMin -= delta;
436 uMax += delta;
437 GAC.Load(C3D, uMin, uMax);
438 }
439 return NextProject ( paramPrev, GAC, P3D, preci, proj, param );
440}
441
442//=======================================================================
443//function : NextProject
444//purpose :
445//=======================================================================
446
447Standard_Real ShapeAnalysis_Curve::NextProject(const Standard_Real paramPrev,
448 const Adaptor3d_Curve& C3D,
449 const gp_Pnt& P3D,
450 const Standard_Real preci,
451 gp_Pnt& proj,
452 Standard_Real& param) const
453{
454 Standard_Real uMin = C3D.FirstParameter();
455 Standard_Real uMax = C3D.LastParameter();
456
a9ae57b9 457 Extrema_LocateExtPC aProjector (P3D, C3D, paramPrev/*U0*/, uMin, uMax, preci/*TolU*/);
458 if (aProjector.IsDone()){
459 param = aProjector.Point().Parameter();
460 proj = aProjector.Point().Value();
7fd59977 461 return P3D.Distance(proj);
462 }
a9ae57b9 463 return Project(C3D, P3D, preci, proj, param, Standard_False);
7fd59977 464}
465
466//=======================================================================
467//function : AdjustParameters
468//purpose : Copied from StepToTopoDS_GeometricTuul::UpdateParam3d (Aug 2001)
469//=======================================================================
470
471Standard_Boolean ShapeAnalysis_Curve::ValidateRange (const Handle(Geom_Curve)& theCurve,
472 Standard_Real& First, Standard_Real& Last,
473 const Standard_Real preci) const
474{
475 // First et/ou Last peuvent etre en dehors des bornes naturelles de la courbe.
476 // On donnera alors la valeur en bout a First et/ou Last
477
478 Standard_Real cf = theCurve->FirstParameter();
479 Standard_Real cl = theCurve->LastParameter();
480// Standard_Real preci = BRepAPI::Precision();
481
482 if (theCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && !theCurve->IsClosed()) {
483 if (First < cf) {
484#ifdef DEBUG
485 cout << "Update Edge First Parameter to Curve First Parameter" << endl;
486#endif
487 First = cf;
488 }
489 else if (First > cl) {
490#ifdef DEBUG
491 cout << "Update Edge First Parameter to Curve Last Parameter" << endl;
492#endif
493 First = cl;
494 }
495 if (Last < cf) {
496#ifdef DEBUG
497 cout << "Update Edge Last Parameter to Curve First Parameter" << endl;
498#endif
499 Last = cf;
500 }
501 else if (Last > cl) {
502#ifdef DEBUG
503 cout << "Update Edge Last Parameter to Curve Last Parameter" << endl;
504#endif
505 Last = cl;
506 }
507 }
508
7fd59977 509 // 15.11.2002 PTV OCC966
72952ef2 510 if (ShapeAnalysis_Curve::IsPeriodic(theCurve)) {
7fd59977 511 ElCLib::AdjustPeriodic(cf,cl,Precision::PConfusion(),First,Last); //:a7 abv 11 Feb 98: preci -> PConfusion()
72952ef2 512 }
513 else if (First < Last) {
514 // nothing to fix
515 }
7fd59977 516 else if (theCurve->IsClosed()) {
517 // l'un des points projecte se trouve sur l'origine du parametrage
518 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
519 // DANGER precision 3d applique a une espace 1d
520
521 // Last = cf au lieu de Last = cl
522 if (Abs(Last - cf) < Precision::PConfusion() /*preci*/) Last = cl ;
523 // First = cl au lieu de First = cf
524 else if (Abs(First - cl) < Precision::PConfusion() /*preci*/) First = cf;
525
526 // on se trouve dans un cas ou l origine est traversee
527 // illegal sur une courbe fermee non periodique
528 // on inverse quand meme les parametres !!!!!!
529 else {
530 //:S4136 abv 20 Apr 99: r0701_ug.stp #6230: add check in 3d
531 if ( theCurve->Value(First).Distance(theCurve->Value(cf)) < preci ) First = cf;
532 if ( theCurve->Value(Last).Distance(theCurve->Value(cl)) < preci ) Last = cl;
533 if ( First > Last ) {
534#ifdef DEBUG
535 cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
536#endif
537 Standard_Real tmp = First;
538 First = Last;
539 Last = tmp;
540 }
541 }
542 }
543 // The curve is closed within the 3D tolerance
544 else if (theCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
545 Handle(Geom_BSplineCurve) aBSpline =
546 Handle(Geom_BSplineCurve)::DownCast(theCurve);
547 if (aBSpline->StartPoint().Distance(aBSpline->EndPoint()) <= preci ) {
548//:S4136 <= BRepAPI::Precision()) {
549 // l'un des points projecte se trouve sur l'origine du parametrage
550 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
551 // DANGER precision 3d applique a une espace 1d
552
553 // Last = cf au lieu de Last = cl
554 if (Abs(Last - cf) < Precision::PConfusion() /*preci*/) Last = cl ;
555 // First = cl au lieu de First = cf
556 else if (Abs(First - cl) < Precision::PConfusion() /*preci*/) First = cf;
557
558 // on se trouve dans un cas ou l origine est traversee
559 // illegal sur une courbe fermee non periodique
560 // on inverse quand meme les parametres !!!!!!
561 else {
562#ifdef DEBUG
563 cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
564#endif
565 Standard_Real tmp = First;
566 First = Last;
567 Last = tmp;
568 }
569 }
570 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
571 else if ( First > Last ) {
572#ifdef DEBUG
573 cout << "Warning: parameter range is bad; curve reversed" << endl;
574#endif
575 First = theCurve->ReversedParameter ( First );
576 Last = theCurve->ReversedParameter ( Last );
577 theCurve->Reverse();
578 }
579//:j9 abv 11 Dec 98: PRO7747 #4875, after :j8: else
580 if (First == Last) { //gka 10.07.1998 file PRO7656 entity 33334
581 First = cf; Last = cl;
582 return Standard_False;
583 }
584 }
585 else {
586#ifdef DEBUG
587 cout << "UpdateParam3d Failed" << endl;
588 cout << " - Curve Type : " << theCurve->DynamicType() << endl;
589 cout << " - Param 1 : " << First << endl;
590 cout << " - Param 2 : " << Last << endl;
591#endif
592 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
593 if ( First > Last ) {
594#ifdef DEBUG
595 cout << "Warning: parameter range is bad; curve reversed" << endl;
596#endif
597 First = theCurve->ReversedParameter ( First );
598 Last = theCurve->ReversedParameter ( Last );
599 theCurve->Reverse();
600 }
601 //pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
602 if (First == Last) {
603 First -= Precision::PConfusion();
604 Last += Precision::PConfusion();
605 }
606 return Standard_False;
607 }
608 return Standard_True;
609}
610
611//=======================================================================
612//function : FillBndBox
613//purpose : WORK-AROUND for methods brom BndLib which give not exact bounds
614//=======================================================================
615
616// search for extremum using Newton
617static Standard_Integer SearchForExtremum (const Handle(Geom2d_Curve)& C2d,
618 const Standard_Real First,
619 const Standard_Real Last,
620 const gp_Vec2d &dir,
621 Standard_Real &par,
622 gp_Pnt2d &res)
623{
624 Standard_Real prevpar;
625 for ( Standard_Integer i=0; i <10; i++ ) {
626 prevpar = par;
627
628 gp_Vec2d D1, D2;
629 C2d->D2 ( par, res, D1, D2 );
630 Standard_Real Det = ( D2 * dir );
631 if ( Abs ( Det ) < 1e-10 ) return Standard_True;
632
633 par -= ( D1 * dir ) / Det;
634 if ( Abs ( par - prevpar ) < Precision::PConfusion() ) return Standard_True;
635
636 if ( First - par >= Precision::PConfusion() ||
637 par - Last >= Precision::PConfusion() ) return Standard_False;
638 }
639 return Standard_True;
640}
641
642void ShapeAnalysis_Curve::FillBndBox (const Handle(Geom2d_Curve)& C2d,
643 const Standard_Real First,
644 const Standard_Real Last,
645 const Standard_Integer NPoints,
646 const Standard_Boolean Exact,
647 Bnd_Box2d &Box) const
648{
649 Standard_Integer nseg = ( NPoints <2 ? 1 : NPoints-1 );
650 Standard_Real step = ( Last - First ) / nseg;
651 for ( Standard_Integer i=0; i <= nseg; i++ ) {
652 Standard_Real par = First + i * step;
653 gp_Pnt2d pnt = C2d->Value ( par );
654 Box.Add ( pnt );
655 if ( ! Exact ) continue;
656
657 gp_Pnt2d pextr;
658 Standard_Real parextr = par;
659 if ( SearchForExtremum ( C2d, Max(First,par-2.*step), Min(Last,par+2.*step),
660 gp_Vec2d(1,0), parextr, pextr ) ) {
661 Box.Add ( pextr );
662 }
663 parextr = par;
664 if ( SearchForExtremum ( C2d, Max(First,par-2.*step), Min(Last,par+2.*step),
665 gp_Vec2d(0,1), parextr, pextr ) ) {
666 Box.Add ( pextr );
667 }
668 }
669}
670
671//=======================================================================
672//function : SelectForwardSeam
673//purpose :
674//=======================================================================
675
676Standard_Integer ShapeAnalysis_Curve::SelectForwardSeam(const Handle(Geom2d_Curve)& C1,
677 const Handle(Geom2d_Curve)& C2) const
678{
679 // SelectForward est destine a devenir un outil distinct
680 // Il est sans doute optimisable !
681
682 Standard_Integer theCurveIndice = 0;
683
684 Handle(Geom2d_Line) L1 = Handle(Geom2d_Line)::DownCast(C1);
685 if (L1.IsNull()) {
686 // if we have BoundedCurve, create a line from C1
687 Handle(Geom2d_BoundedCurve) BC1 = Handle(Geom2d_BoundedCurve)::DownCast(C1);
688 if (BC1.IsNull()) return theCurveIndice;
689 gp_Pnt2d StartBC1 = BC1->StartPoint();
690 gp_Pnt2d EndBC1 = BC1->EndPoint();
691 gp_Vec2d VecBC1(StartBC1, EndBC1);
692 L1 = new Geom2d_Line(StartBC1, VecBC1);
693 }
694
695 Handle(Geom2d_Line) L2 = Handle(Geom2d_Line)::DownCast(C2);
696 if (L2.IsNull()) {
697 // if we have BoundedCurve, creates a line from C2
698 Handle(Geom2d_BoundedCurve) BC2 = Handle(Geom2d_BoundedCurve)::DownCast(C2);
699 if (BC2.IsNull()) return theCurveIndice;
700 gp_Pnt2d StartBC2 = BC2->StartPoint();
701 gp_Pnt2d EndBC2 = BC2->EndPoint();
702 gp_Vec2d VecBC2(StartBC2, EndBC2);
703 L2 = new Geom2d_Line(StartBC2, VecBC2);
704 }
705
706 Standard_Boolean UdirPos, UdirNeg, VdirPos, VdirNeg;
707 UdirPos = UdirNeg = VdirPos = VdirNeg = Standard_False;
708
709 gp_Dir2d theDir = L1->Direction();
710 gp_Pnt2d theLoc1 = L1->Location();
711 gp_Pnt2d theLoc2 = L2->Location();
712
713 if (theDir.X() > 0.) {
714 UdirPos = Standard_True; //szv#4:S4163:12Mar99 Udir unused
715 } else if (theDir.X() < 0.) {
716 UdirNeg = Standard_True; //szv#4:S4163:12Mar99 Udir unused
717 } else if (theDir.Y() > 0.) {
718 VdirPos = Standard_True; //szv#4:S4163:12Mar99 Vdir unused
719 } else if (theDir.Y() < 0.) {
720 VdirNeg = Standard_True; //szv#4:S4163:12Mar99 Vdir unused
721 }
722
723 if (VdirPos) {
724 // max of Loc1.X() Loc2.X()
725 if (theLoc1.X() > theLoc2.X()) theCurveIndice = 1;
726 else theCurveIndice = 2;
727 } else if (VdirNeg) {
728 if (theLoc1.X() > theLoc2.X()) theCurveIndice = 2;
729 else theCurveIndice = 1;
730 } else if (UdirPos) {
731 // min of Loc1.X() Loc2.X()
732 if (theLoc1.Y() < theLoc2.Y()) theCurveIndice = 1;
733 else theCurveIndice = 2;
734 } else if (UdirNeg) {
735 if (theLoc1.Y() < theLoc2.Y()) theCurveIndice = 2;
736 else theCurveIndice = 1;
737 }
738
739 return theCurveIndice;
740}
741
742//%11 pdn 12.01.98
743//=============================================================================
744// Static methods for IsPlanar
745// IsPlanar
746//=============================================================================
747
748static gp_XYZ GetAnyNormal ( gp_XYZ orig )
749{
750 gp_XYZ Norm;
751 if ( Abs ( orig.Z() ) < Precision::Confusion() )
752 Norm.SetCoord ( 0, 0, 1 );
753 else {
754 Norm.SetCoord ( orig.Z(), 0, -orig.X() );
755 Standard_Real nrm = Norm.Modulus();
756 if ( nrm < Precision::Confusion() ) Norm.SetCoord ( 0, 0, 1 );
757 else Norm = Norm / nrm;
758 }
759 return Norm;
760}
761
762//=======================================================================
763//function : GetSamplePoints
764//purpose :
765//=======================================================================
766static void AppendControlPoles (TColgp_SequenceOfPnt& seq,
767 const Handle(Geom_Curve) curve)
768{
769 if ( curve->IsKind(STANDARD_TYPE(Geom_Line))) {
770 seq.Append(curve->Value(0));
771 seq.Append(curve->Value(1));
772 } else if ( curve->IsKind(STANDARD_TYPE(Geom_Conic))) {
773 seq.Append(curve->Value(0));
c6541a0c
D
774 seq.Append(curve->Value(M_PI/2));
775 seq.Append(curve->Value(M_PI));
7fd59977 776 } else if ( curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
777 //DeclareAndCast(Geom_TrimmedCurve, Trimmed, curve);
778 Handle(Geom_TrimmedCurve) Trimmed = *((Handle(Geom_TrimmedCurve) *) &curve);
779// AppendControlPoles(seq,Trimmed->BasisCurve());
780 Handle(Geom_Curve) aBaseCrv = Trimmed->BasisCurve();
781 Standard_Boolean done = Standard_False;
782 if ( aBaseCrv->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
783 try {
784 OCC_CATCH_SIGNALS
785 Handle(Geom_Geometry) Ctmp = aBaseCrv->Copy();
786 Handle(Geom_BSplineCurve) bslp = Handle(Geom_BSplineCurve)::DownCast(Ctmp);
787 bslp->Segment(curve->FirstParameter(), curve->LastParameter());
788 AppendControlPoles(seq,bslp);
789 done = Standard_True;
790 }
791 catch (Standard_Failure) {
792 }
793 }
794 else if ( aBaseCrv->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
795 try {
796 OCC_CATCH_SIGNALS
797 Handle(Geom_Geometry) Ctmp = aBaseCrv->Copy();
798 Handle(Geom_BezierCurve) bz = Handle(Geom_BezierCurve)::DownCast(Ctmp);
799 bz->Segment(curve->FirstParameter(), curve->LastParameter());
800 AppendControlPoles(seq,bz);
801 done = Standard_True;
802 }
803 catch (Standard_Failure) {
804 }
805 }
806 if (!done) {
807 seq.Append(curve->Value(curve->FirstParameter()));
808 seq.Append(curve->Value((curve->FirstParameter() + curve->LastParameter())/2.));
809 seq.Append(curve->Value(curve->LastParameter()));
810 }
811 } else if ( curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
812 //DeclareAndCast(Geom_OffsetCurve, OffsetC, curve);
813 Handle(Geom_OffsetCurve) OffsetC = *((Handle(Geom_OffsetCurve) *) &curve);
814// AppendControlPoles(seq,OffsetC->BasisCurve());
815 seq.Append(curve->Value(curve->FirstParameter()));
816 seq.Append(curve->Value((curve->FirstParameter() + curve->LastParameter())/2.));
817 seq.Append(curve->Value(curve->LastParameter()));
818 } else if ( curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
819 //DeclareAndCast(Geom_BSplineCurve, BSpline, curve);
820 Handle(Geom_BSplineCurve) BSpline = *((Handle(Geom_BSplineCurve) *) &curve);
821 TColgp_Array1OfPnt Poles(1,BSpline->NbPoles());
822 BSpline->Poles(Poles);
823 for(Standard_Integer i = 1; i <= BSpline->NbPoles(); i++)
824 seq.Append(Poles(i));
825 } else if ( curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
826 //DeclareAndCast(Geom_BezierCurve, Bezier, curve);
827 //Handle(Geom_BezierCurve) Bezier = Handle(Geom_BezierCurve)::DownCast(curve);
828 Handle(Geom_BezierCurve) Bezier = *((Handle(Geom_BezierCurve) *) &curve);
829 TColgp_Array1OfPnt Poles(1,Bezier->NbPoles());
830 Bezier->Poles(Poles);
831 for(Standard_Integer i = 1; i <= Bezier->NbPoles(); i++)
832 seq.Append(Poles(i));
833 }
834}
835
836//%11 pdn 12.01.98
837//szv modified
838//=======================================================================
839//function : IsPlanar
840//purpose : Detects if points lie in some plane and returns normal
841//=======================================================================
842
843Standard_Boolean ShapeAnalysis_Curve::IsPlanar (const TColgp_Array1OfPnt& pnts,
844 gp_XYZ& Normal,
845 const Standard_Real preci)
846{
847 Standard_Real precision = (preci > 0.0)? preci : Precision::Confusion();
848 Standard_Boolean noNorm = (Normal.SquareModulus() == 0);
849
850 if (pnts.Length() < 3) {
851 gp_XYZ N1 = pnts(1).XYZ()-pnts(2).XYZ();
852 if (noNorm) {
853 Normal = GetAnyNormal(N1);
854 return Standard_True;
855 }
856 return Abs(N1*Normal) < Precision::Confusion();
857 }
858
859 gp_XYZ aMaxDir;
860 if (noNorm) {
861 //define a center point
862 gp_XYZ aCenter(0,0,0);
863 Standard_Integer i = 1;
864 for (; i <= pnts.Length(); i++)
865 aCenter += pnts(i).XYZ();
866 aCenter/=pnts.Length();
867
868
869 aMaxDir = pnts(1).XYZ() - aCenter;
870 Normal = (pnts(pnts.Length()).XYZ() - aCenter) ^ aMaxDir;
871
872 for ( i = 1; i < pnts.Length(); i++) {
873 gp_XYZ aTmpDir = pnts(i+1).XYZ() - aCenter;
874 if(aTmpDir.SquareModulus() > aMaxDir.SquareModulus())
875 aMaxDir = aTmpDir;
876
877 gp_XYZ aDelta = (pnts(i).XYZ() - aCenter) ^ (pnts(i+1).XYZ() - aCenter);
878 if(Normal*aDelta < 0)
879 aDelta*=-1;
880 Normal += aDelta;
881 }
882 }
883
884 // check if points are linear
885 Standard_Real nrm = Normal.Modulus();
886 if ( nrm < Precision::Confusion() ) {
887 Normal = GetAnyNormal(aMaxDir);
888 return Standard_True;
889 }
890 Normal = Normal / nrm;
891
892 Standard_Real mind = RealLast(), maxd = -RealLast(), dev;
893 for (Standard_Integer i = 1; i <= pnts.Length(); i++) {
894 dev = pnts(i).XYZ() * Normal;
895 if (dev < mind) mind = dev;
896 if (dev > maxd) maxd = dev;
897 }
898
899 return ((maxd - mind) <= precision);
900}
901
902
903//=======================================================================
904//function : IsPlanar
905//purpose :
906//=======================================================================
907
908 Standard_Boolean ShapeAnalysis_Curve::IsPlanar (const Handle(Geom_Curve)& curve,
909 gp_XYZ& Normal,
910 const Standard_Real preci)
911{
912 Standard_Real precision = (preci > 0.0)? preci : Precision::Confusion();
913 Standard_Boolean noNorm = (Normal.SquareModulus() == 0);
914
915 if (curve->IsKind(STANDARD_TYPE(Geom_Line))) {
916 //DeclareAndCast(Geom_Line, Line, curve);
917 Handle(Geom_Line) Line = *((Handle(Geom_Line) *) &curve);
918 gp_XYZ N1 = Line->Position().Direction().XYZ();
919 if (noNorm) {
920 Normal = GetAnyNormal(N1);
921 return Standard_True;
922 }
923 return Abs(N1*Normal) < Precision::Confusion();
924 }
925
926 if (curve->IsKind(STANDARD_TYPE(Geom_Conic))) {
927 //DeclareAndCast(Geom_Conic, Conic, curve);
928 Handle(Geom_Conic) Conic = *((Handle(Geom_Conic) *) &curve);
929 gp_XYZ N1 = Conic->Axis().Direction().XYZ();
930 if (noNorm) {
931 Normal = N1;
932 return Standard_True;
933 }
934 gp_XYZ aVecMul = N1^Normal;
08cd2f6b 935 return aVecMul.SquareModulus() < Precision::SquareConfusion();
7fd59977 936 }
937
938 if (curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
939 //DeclareAndCast(Geom_TrimmedCurve, Trimmed, curve);
940 Handle(Geom_TrimmedCurve) Trimmed = *((Handle(Geom_TrimmedCurve) *) &curve);
941 return IsPlanar(Trimmed->BasisCurve(),Normal,precision);
942 }
943
944 if (curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
945 //DeclareAndCast(Geom_OffsetCurve, OffsetC, curve);
946 Handle(Geom_OffsetCurve) OffsetC = *((Handle(Geom_OffsetCurve) *) &curve);
947 return IsPlanar(OffsetC->BasisCurve(),Normal,precision);
948 }
949
950 if (curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
951 //DeclareAndCast(Geom_BSplineCurve, BSpline, curve);
952 Handle(Geom_BSplineCurve) BSpline = *((Handle(Geom_BSplineCurve) *) &curve);
953 TColgp_Array1OfPnt Poles(1,BSpline->NbPoles());
954 BSpline->Poles(Poles);
955 return IsPlanar(Poles,Normal,precision);
956 }
957
958 if (curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
959 //DeclareAndCast(Geom_BezierCurve, Bezier, curve);
960 Handle(Geom_BezierCurve) Bezier = *((Handle(Geom_BezierCurve) *) &curve);
961 TColgp_Array1OfPnt Poles(1,Bezier->NbPoles());
962 Bezier->Poles(Poles);
963 return IsPlanar(Poles,Normal,precision);
964 }
965
966 if (curve->IsKind(STANDARD_TYPE(ShapeExtend_ComplexCurve))) {
967 //DeclareAndCast(ShapeExtend_ComplexCurve, Complex, curve);
968 Handle(ShapeExtend_ComplexCurve) Complex = *((Handle(ShapeExtend_ComplexCurve) *) &curve);
969 TColgp_SequenceOfPnt sequence;
970 Standard_Integer i; // svv Jan11 2000 : porting on DEC
971 for (i = 1; i <= Complex->NbCurves(); i++)
972 AppendControlPoles(sequence,Complex->Curve(i));
973 TColgp_Array1OfPnt Poles(1,sequence.Length());
974 for (i=1; i <= sequence.Length(); i++) Poles(i) = sequence(i);
975 return IsPlanar(Poles,Normal,precision);
976 }
977
978 return Standard_False;
979}
980
981//=======================================================================
982//function : GetSamplePoints
983//purpose :
984//=======================================================================
985
986Standard_Boolean ShapeAnalysis_Curve::GetSamplePoints (const Handle(Geom_Curve)& curve,
987 const Standard_Real first,
988 const Standard_Real last,
989 TColgp_SequenceOfPnt& seq)
990{
991 Standard_Real adelta = curve->LastParameter() - curve->FirstParameter();
992 if(!adelta )
993 return Standard_False;
994
995 Standard_Integer aK = (Standard_Integer)ceil ((last - first) / adelta);
996 Standard_Integer nbp =100*aK;
997 if(curve->IsKind(STANDARD_TYPE(Geom_Line)))
998 nbp =2;
999 else if(curve->IsKind(STANDARD_TYPE(Geom_Circle)))
1000 nbp =360*aK;
1001
1002 else if (curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
1003 Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(curve);
1004
1005 nbp = aBspl->NbKnots() * aBspl->Degree()*aK;
1006 if(nbp < 2.0) nbp=2;
1007 }
1008 else if (curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
1009 Handle(Geom_BezierCurve) aB = Handle(Geom_BezierCurve)::DownCast(curve);
1010 nbp = 3 + aB->NbPoles();
1011 }
1012 else if(curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
1013 Handle(Geom_OffsetCurve) aC = Handle(Geom_OffsetCurve)::DownCast(curve);
1014 return GetSamplePoints(aC->BasisCurve(),first,last,seq);
1015 }
1016 else if(curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1017 Handle(Geom_TrimmedCurve) aC = Handle(Geom_TrimmedCurve)::DownCast(curve);
1018 return GetSamplePoints(aC->BasisCurve(),first,last,seq);
1019 }
1020 Standard_Real step = ( last - first ) / (Standard_Real)( nbp - 1 );
1021 Standard_Real par = first, stop = last - 0.5 * step;
1022 for ( ; par < stop; par += step )
1023 seq.Append(curve->Value(par));
1024 seq.Append(curve->Value(last));
1025 return Standard_True;
1026}
1027//=======================================================================
1028//function : GetSamplePoints
1029//purpose :
1030//=======================================================================
1031
1032Standard_Boolean ShapeAnalysis_Curve::GetSamplePoints (const Handle(Geom2d_Curve)& curve,
1033 const Standard_Real first,
1034 const Standard_Real last,
1035 TColgp_SequenceOfPnt2d& seq)
1036{
1037 //:abv 05.06.02: TUBE.stp
1038 // Use the same distribution of points as BRepTopAdaptor_FClass2d for consistency
1039 Geom2dAdaptor_Curve C ( curve, first, last );
1040 Standard_Integer nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
1041 //-- Attention aux bsplines rationnelles de degree 3. (bouts de cercles entre autres)
1042 if (nbs > 2) nbs*=4;
1043 Standard_Real step = ( last - first ) / (Standard_Real)( nbs - 1 );
1044 Standard_Real par = first, stop = last - 0.5 * step;
1045 for ( ; par < stop; par += step )
1046 seq.Append(curve->Value(par));
1047 seq.Append(curve->Value(last));
1048 return Standard_True;
1049/*
1050 Standard_Integer i;
1051 Standard_Real step;
1052 gp_Pnt2d Ptmp;
1053 if ( curve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
1054 seq.Append(curve->Value(first));
1055 seq.Append(curve->Value(last));
1056 return Standard_True;
1057 }
1058 else if(curve->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
c6541a0c 1059 step = Min ( M_PI, last-first ) / 19; //:abv 05.06.02 TUBE.stp #19209...: M_PI/16
7fd59977 1060// if( step>(last-first) ) {
1061// seq.Append(curve->Value(first));
1062// seq.Append(curve->Value((last+first)/2));
1063// seq.Append(curve->Value(last));
1064// return Standard_True;
1065// }
1066// else {
1067 Standard_Real par=first;
1068 for(i=0; par<last; i++) {
1069 seq.Append(curve->Value(par));
1070 par += step;
1071 }
1072 seq.Append(curve->Value(last));
1073 return Standard_True;
1074// }
1075 }
1076 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
1077 DeclareAndCast(Geom2d_TrimmedCurve, Trimmed, curve);
1078 return GetControlPoints(Trimmed->BasisCurve(), seq, first, last);
1079 }
1080 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
1081 DeclareAndCast(Geom2d_BSplineCurve, aBs, curve);
1082 TColStd_SequenceOfReal aSeqParam;
1083 if(!aBs.IsNull()) {
1084 aSeqParam.Append(first);
1085 for(i=1; i<=aBs->NbKnots(); i++) {
1086 if( aBs->Knot(i)>first && aBs->Knot(i)<last )
1087 aSeqParam.Append(aBs->Knot(i));
1088 }
1089 aSeqParam.Append(last);
1090 Standard_Integer NbPoints=aBs->Degree();
1091 if( (aSeqParam.Length()-1)*NbPoints>10 ) {
1092 for(i=1; i<aSeqParam.Length(); i++) {
1093 Standard_Real FirstPar = aSeqParam.Value(i);
1094 Standard_Real LastPar = aSeqParam.Value(i+1);
1095 step = (LastPar-FirstPar)/NbPoints;
1096 for(Standard_Integer k=0; k<NbPoints; k++ ) {
1097 aBs->D0(FirstPar+step*k, Ptmp);
1098 seq.Append(Ptmp);
1099 }
1100 }
1101 aBs->D0(last, Ptmp);
1102 seq.Append(Ptmp);
1103 return Standard_True;
1104 }
1105 else {
1106 step = (last-first)/10;
1107 for(Standard_Integer k=0; k<=10; k++ ) {
1108 aBs->D0(first+step*k, Ptmp);
1109 seq.Append(Ptmp);
1110 }
1111 return Standard_True;
1112 }
1113 }
1114 }
1115 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
1116 DeclareAndCast(Geom2d_BezierCurve, aBz, curve);
1117 if(!aBz.IsNull()) {
1118 Standard_Integer NbPoints=aBz->Degree();
1119 step = (last-first)/NbPoints;
1120 for(Standard_Integer k=0; k<NbPoints; k++ ) {
1121 aBz->D0(first+step*k, Ptmp);
1122 seq.Append(Ptmp);
1123 }
1124 aBz->D0(last, Ptmp);
1125 seq.Append(Ptmp);
1126 return Standard_True;
1127 }
1128 }
1129 return Standard_False;
1130*/
1131}
1132
1133//=======================================================================
1134//function : IsClosed
1135//purpose :
1136//=======================================================================
1137
1138Standard_Boolean ShapeAnalysis_Curve::IsClosed(const Handle(Geom_Curve)& theCurve,
1139 const Standard_Real preci)
1140{
1141 if (theCurve->IsClosed())
1142 return Standard_True;
1143
1144 Standard_Real prec = Max (preci, Precision::Confusion());
1145
1146 Standard_Real f, l;
1147 f = theCurve->FirstParameter();
1148 l = theCurve->LastParameter();
1149
1150 if (Precision::IsInfinite (f) || Precision::IsInfinite (l))
1151 return Standard_False;
1152
1153 Standard_Real aClosedVal = theCurve->Value(f).SquareDistance(theCurve->Value(l));
1154 Standard_Real preci2 = prec*prec;
1155
1156 return (aClosedVal <= preci2);
1157}
1158//=======================================================================
1159//function : IsPeriodic
1160//purpose : OCC996
1161//=======================================================================
1162
1163Standard_Boolean ShapeAnalysis_Curve::IsPeriodic(const Handle(Geom_Curve)& theCurve)
1164{
1165 // 15.11.2002 PTV OCC966
1166 // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
1167 // ask IsPeriodic on BasisCurve
1168 Handle(Geom_Curve) aTmpCurve = theCurve;
1169 while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1170 (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1171 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1172 aTmpCurve = Handle(Geom_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
1173 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1174 aTmpCurve = Handle(Geom_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
1175 }
1176 return aTmpCurve->IsPeriodic();
1177}
1178
1179Standard_Boolean ShapeAnalysis_Curve::IsPeriodic(const Handle(Geom2d_Curve)& theCurve)
1180{
1181 // 15.11.2002 PTV OCC966
1182 // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
1183 // ask IsPeriodic on BasisCurve
1184 Handle(Geom2d_Curve) aTmpCurve = theCurve;
1185 while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) ||
1186 (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ) {
1187 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
1188 aTmpCurve = Handle(Geom2d_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
1189 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1190 aTmpCurve = Handle(Geom2d_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
1191 }
1192 return aTmpCurve->IsPeriodic();
1193}