1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
18 //:r5 abv 06.04.99: ec_turbine-A.stp, #4313: protect against null curve
19 // abv 09.04.99 S4136: add parameter preci (to eliminate BRepAPI::Precision)
20 #include <ShapeFix_EdgeProjAux.ixx>
22 #include <Standard_ErrorHandler.hxx>
23 #include <Standard_Failure.hxx>
27 #include <Adaptor3d_CurveOnSurface.hxx>
28 #include <Geom2dAdaptor_Curve.hxx>
29 #include <Geom2dAdaptor_HCurve.hxx>
30 #include <GeomAdaptor_Surface.hxx>
31 #include <GeomAdaptor_HSurface.hxx>
33 #include <Geom2d_Curve.hxx>
34 #include <Geom2d_BSplineCurve.hxx>
35 #include <Geom2d_Line.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <Geom_SphericalSurface.hxx>
40 #include <BRep_Tool.hxx>
41 #include <Precision.hxx>
42 #include <TopoDS_Vertex.hxx>
45 #include <ShapeAnalysis.hxx>
46 #include <ShapeAnalysis_Curve.hxx>
47 #include <ShapeAnalysis_Edge.hxx>
48 #include <ShapeAnalysis_Surface.hxx>
50 #include <Extrema_ExtPC.hxx>
53 //=======================================================================
54 //function : ShapeFix_EdgeProjAux
56 //=======================================================================
58 ShapeFix_EdgeProjAux::ShapeFix_EdgeProjAux ()
60 myFirstDone = myLastDone = Standard_False;
63 //=======================================================================
64 //function : ShapeFix_EdgeProjAux
66 //=======================================================================
68 ShapeFix_EdgeProjAux::ShapeFix_EdgeProjAux (const TopoDS_Face& F,
74 //=======================================================================
77 //=======================================================================
79 void ShapeFix_EdgeProjAux::Init (const TopoDS_Face& F,
84 myFirstDone = myLastDone = Standard_False;
87 //=======================================================================
90 //=======================================================================
92 void ShapeFix_EdgeProjAux::Compute (const Standard_Real preci)
94 myFirstDone = myLastDone = Standard_False;
96 // Project Point3d on Surface
97 // TEMPORARY Call ShapeFix_EdgeProjAux
100 if (IsFirstDone() && IsLastDone()) {
101 Standard_Real U1 = FirstParam();
102 Standard_Real U2 = LastParam();
105 cout << "Parametres inverses ... " << endl;
107 Standard_Real tmp = U1;
111 myFirstDone = Standard_True;
113 myLastDone = Standard_True;
117 //=======================================================================
118 //function : IsFirstDone
120 //=======================================================================
122 Standard_Boolean ShapeFix_EdgeProjAux::IsFirstDone() const
127 //=======================================================================
128 //function : IsLastDone
130 //=======================================================================
132 Standard_Boolean ShapeFix_EdgeProjAux::IsLastDone() const
137 //=======================================================================
138 //function : FirstParam
140 //=======================================================================
142 Standard_Real ShapeFix_EdgeProjAux::FirstParam() const
147 //=======================================================================
148 //function : LastParam
150 //=======================================================================
152 Standard_Real ShapeFix_EdgeProjAux::LastParam() const
157 //=======================================================================
160 //=======================================================================
162 Standard_Boolean ShapeFix_EdgeProjAux::IsIso (const Handle(Geom2d_Curve)& /*theCurve2d*/)
164 // Until an ISO is recognized by Adaptor3d_Curve
166 if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
167 Handle(Geom2d_Line) theLine2d = Handle(Geom2d_Line)::DownCast(theCurve2d);
168 gp_Dir2d theDir2d = theLine2d->Direction();
170 gp_Dir2d dir1(0.,1.);
171 gp_Dir2d dir2(0.,-1.);
173 return (theDir2d.IsEqual(dir1,Precision::Angular()) ||
174 theDir2d.IsEqual(dir2,Precision::Angular()) ||
175 theDir2d.IsNormal(dir1,Precision::Angular()) ||
176 theDir2d.IsNormal(dir2,Precision::Angular()) );
179 return Standard_False;
182 // ----------------------------------------------------------------------------
183 // static : FindParameterWithExt
184 // Purpose : Computes the trimming parameter of Pt1 on COnS
185 // ----------------------------------------------------------------------------
187 static Standard_Boolean FindParameterWithExt (const gp_Pnt& Pt1,
188 const Adaptor3d_CurveOnSurface& COnS,
189 const Standard_Real Uinf,
190 const Standard_Real Usup,
191 const Standard_Real preci,
194 try { // et allez donc !
196 Extrema_ExtPC myExtPC (Pt1, COnS, Uinf, Usup, preci);
198 //ShapeFix_ExtPCOnS myExtPCOnS1 =
199 //ShapeFix_ExtPCOnS(Pt1, COnS, Uinf, Usup, preci);
201 if (myExtPC.IsDone()) {
202 Standard_Integer NbExt1 = myExtPC.NbExt();
203 for (Standard_Integer i=1; i<=NbExt1; i++) {
204 if (myExtPC.IsMin(i)) {
205 //Standard_Real dist = myExtPC.Value(i); //szv#4:S4163:12Mar99 debug mode only
206 w1 = myExtPC.Point(i).Parameter();
209 return Standard_True;
211 else return Standard_False;
213 catch(Standard_Failure) {
215 cout << "Warning: ShapeFix_EdgeProjAux, FindParameterWithExt(): Exception: ";
216 Standard_Failure::Caught()->Print(cout); cout << endl;
218 return Standard_False;
222 //=======================================================================
225 //=======================================================================
227 void ShapeFix_EdgeProjAux::Init2d (const Standard_Real preci)
229 Standard_Real cl, cf;
231 // Extract Geometries
232 Handle(Geom_Surface) theSurface = BRep_Tool::Surface(myFace);
233 Handle(Geom2d_Curve) theCurve2d = BRep_Tool::CurveOnSurface(myEdge, myFace, cf, cl);
234 if ( theCurve2d.IsNull() ) return; //:r5 abv 6 Apr 99: ec_turbine-A.stp, #4313
237 TopExp::Vertices(myEdge, V1, V2);
239 // pdn 28.12.98: r_39-db.stp #605: use ends of 3d curve instead of vertices
240 ShapeAnalysis_Edge sae;
242 Handle(Geom_Curve) C3d;
243 if(sae.Curve3d(myEdge,C3d,a,b,Standard_False)) {
248 Pt1 = BRep_Tool::Pnt(V1);
249 Pt2 = BRep_Tool::Pnt(V2);
251 //:S4136 Standard_Real preci = BRepAPI::Precision();
252 //pdn to manage degenerated case
254 Handle(ShapeAnalysis_Surface) stsu = new ShapeAnalysis_Surface (theSurface);
256 Standard_Real firstpar,lastpar;
257 if (stsu->DegeneratedValues(Pt1,preci,aPt1,aPt2,firstpar,lastpar)){
259 if(theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
260 if (aPt1.IsEqual(theCurve2d->Value(firstpar),preci) &&
261 aPt2.IsEqual(theCurve2d->Value(lastpar),preci)){
262 myFirstParam = firstpar;
263 myLastParam = lastpar;
264 myFirstDone = myLastDone = Standard_True;
269 else cout <<"Other type of deg curve"<<endl;
275 Standard_Boolean parU = Standard_False, parV = Standard_False;
276 GeomAdaptor_Surface SA = GeomAdaptor_Surface(theSurface);
277 Handle(GeomAdaptor_HSurface) myHSur = new GeomAdaptor_HSurface(SA);
279 cf = theCurve2d->FirstParameter();
280 cl = theCurve2d->LastParameter();
281 //pdn cutting pcurve by suface bounds
282 if (Precision::IsInfinite(cf)||Precision::IsInfinite(cl)) {
283 if(theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
284 Standard_Real uf,ul,vf,vl;
285 theSurface->Bounds(uf,ul,vf,vl);
286 if(!Precision::IsInfinite(uf)&&!Precision::IsInfinite(ul)&&
287 !Precision::IsInfinite(vf)&&!Precision::IsInfinite(vl)) {
288 Standard_Real cfi,cli;
289 Handle(Geom2d_Line) lin = Handle(Geom2d_Line)::DownCast(theCurve2d);
290 gp_Pnt2d pnt = lin->Location();
291 gp_Dir2d dir = lin->Direction();
293 parU = Standard_True;
294 cfi = (uf-pnt.X())/dir.X();
295 cli = (ul-pnt.X())/dir.X();
297 else if (dir.X()==0) {
298 parV = Standard_True;
299 cfi = (vf-pnt.Y())/dir.Y();
300 cli = (vl-pnt.Y())/dir.Y();
303 Standard_Real xfi, xli, yfi, yli;
304 xfi = (uf-pnt.X())/dir.X();
305 xli = (ul-pnt.X())/dir.X();
306 yfi = (vf-pnt.Y())/dir.Y();
307 yli = (vl-pnt.Y())/dir.Y();
308 if (dir.X()*dir.Y() > 0) {
309 cfi = (Abs(xli-xfi) < Abs(xli-yfi)? xfi : yfi);
310 cli = (Abs(xfi-xli) < Abs(xfi-yli)? xli : yli);
312 cfi = (Abs(xli-xfi) < Abs(xli-yli)? xfi : yli);
313 cli = (Abs(yli-xli) < Abs(yli-yfi)? xli : yfi);
316 if (cfi < cli) { cf = cfi; cl = cli; }
317 else { cf = cli; cl = cfi; }
319 else if(!Precision::IsInfinite(uf)&&!Precision::IsInfinite(ul)){
320 Handle(Geom2d_Line) lin = Handle(Geom2d_Line)::DownCast(theCurve2d);
321 gp_Dir2d dir = lin->Direction();
323 if (dir.Y()==0) parU = Standard_True;
324 gp_Pnt2d pnt = lin->Location(); //szv#4:S4163:12Mar99 moved
325 Standard_Real cfi = (uf-pnt.X())/dir.X();
326 Standard_Real cli = (ul-pnt.X())/dir.X();
327 if (cfi < cli) { cf = cfi; cl = cli; }
328 else { cf = cli; cl = cfi; }
338 //pdn not cutted by bounds
340 cout<<"Infinite Surface"<<endl;
345 //pdn not linear case not managed
349 cout<<"Some infinite curve"<<endl;
354 Geom2dAdaptor_Curve CA = Geom2dAdaptor_Curve(theCurve2d,cf,cl);
355 Handle(Geom2dAdaptor_HCurve) myHCur = new Geom2dAdaptor_HCurve(CA);
357 Adaptor3d_CurveOnSurface COnS = Adaptor3d_CurveOnSurface(myHCur, myHSur);
359 // ----------------------------------------------
360 // --- topological limit == geometric limit ? ---
361 // ----------------------------------------------
362 Standard_Real Uinf = COnS.FirstParameter();
363 Standard_Real Usup = COnS.LastParameter();
366 ShapeAnalysis_Curve sac;
368 Standard_Real dist = sac.Project(COnS,Pt1,preci,pnt,w1,Standard_False);
369 if (dist > preci) return;
370 dist = sac.Project(COnS,Pt2,preci,pnt,w2,Standard_False);
371 if (dist > preci) return;
375 myFirstDone = myLastDone = Standard_True;
376 if ( myFirstParam == Uinf && myLastParam == Usup ) return;
377 if ( myFirstParam == Usup && myLastParam == Uinf ) {
378 myFirstParam = theCurve2d->ReversedParameter(Usup);
379 myLastParam = theCurve2d->ReversedParameter(Uinf);
380 theCurve2d->Reverse();
382 cout << "Warning: ShapeFix_EdgeProjAux: pcurve reversed" << endl;
386 //:abv 29.08.01: SAT: fix for closed case
387 if ( COnS.Value(Uinf).Distance ( COnS.Value(Usup) ) < Precision::Confusion() ) {
388 // 18.11.2002 SKL OCC630 compare values with tolerance Precision::PConfusion() instead of "=="
389 if ( Abs(myFirstParam-Uinf) < ::Precision::PConfusion() &&
390 Abs(myLastParam-Uinf) < ::Precision::PConfusion() )
391 myLastParam = w2 = Usup;
392 // 18.11.2002 SKL OCC630 compare values with tolerance Precision::PConfusion() instead of "=="
393 else if ( Abs(myFirstParam-Usup) < ::Precision::PConfusion() &&
394 Abs(myLastParam-Usup) < ::Precision::PConfusion() )
395 myFirstParam = w1 = Uinf;
398 //pdn adjust parameters in periodic case
400 Standard_Real uf,ul,vf,vl;
401 theSurface->Bounds(uf,ul,vf,vl);
402 Standard_Real period = (parU ? ul-uf : vl-vf);
403 w1+=ShapeAnalysis::AdjustToPeriod(w1,0,period);
405 w2+=ShapeAnalysis::AdjustToPeriod(w2,0,period);
407 Handle(Geom_Curve) C3d1;
408 if(!sae.Curve3d (myEdge, C3d1, cf, cl, Standard_False )) {
409 UpdateParam2d(theCurve2d);
412 gp_Pnt mid = C3d1->Value((cf+cl)/2);
414 sac.Project(COnS,mid,preci,pnt,wmid,Standard_False);
415 wmid+=ShapeAnalysis::AdjustToPeriod(wmid,0,period);
417 if(w2 > wmid) myFirstParam -= period;
419 UpdateParam2d(theCurve2d);
423 cout <<" Added"<<endl;
429 myLastParam -=period;
430 UpdateParam2d(theCurve2d);
432 cout <<" Added & Inverted"<<endl;
434 } else if (w2 < wmid) {
435 myFirstParam += period;
436 UpdateParam2d(theCurve2d);
440 UpdateParam2d(theCurve2d);
444 //=======================================================================
447 //=======================================================================
449 void ShapeFix_EdgeProjAux::Init3d (const Standard_Real preci)
451 Standard_Real cl, cf;
453 // Extract Geometries
454 Handle(Geom_Surface) theSurface = BRep_Tool::Surface(myFace);
455 Handle(Geom2d_Curve) theCurve2d = BRep_Tool::CurveOnSurface(myEdge, myFace, cf, cl);
456 if ( theCurve2d.IsNull() ) return; //:r5 abv 6 Apr 99: ec_turbine-A.stp, #4313
459 V1 = TopExp::FirstVertex(myEdge);
460 V2 = TopExp::LastVertex(myEdge);
461 gp_Pnt Pt1 = BRep_Tool::Pnt(V1);
462 gp_Pnt Pt2 = BRep_Tool::Pnt(V2);
465 GeomAdaptor_Surface SA = GeomAdaptor_Surface(theSurface);
466 Handle(GeomAdaptor_HSurface) myHSur = new GeomAdaptor_HSurface(SA);
468 Geom2dAdaptor_Curve CA = Geom2dAdaptor_Curve(theCurve2d);
469 Handle(Geom2dAdaptor_HCurve) myHCur = new Geom2dAdaptor_HCurve(CA);
471 Adaptor3d_CurveOnSurface COnS = Adaptor3d_CurveOnSurface(myHCur, myHSur);
473 //:S4136 Standard_Real preci = BRepAPI::Precision();
474 Standard_Real Uinf = theCurve2d->FirstParameter();
475 Standard_Real Usup = theCurve2d->LastParameter();
477 // ----------------------------------------------
478 // --- topological limit == geometric limit ? ---
479 // ----------------------------------------------
481 if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve))) {
483 gp_Pnt Pdeb = COnS.Value(Uinf);
484 gp_Pnt Pfin = COnS.Value(Usup);
486 //szv#4:S4163:12Mar99 optimized
487 if ( Pdeb.IsEqual(Pt1, preci) && Pfin.IsEqual(Pt2, preci) ) {
490 myFirstDone = myLastDone = Standard_True;
495 // ------------------------------------------
496 // --- The CurveOnSurface is not infinite ---
497 // --- Try with Extrema ---
498 // ------------------------------------------
500 Standard_Real w1 = COnS.FirstParameter();
501 Standard_Real w2 = COnS.LastParameter();
503 if ((!Precision::IsInfinite(w1) &&
504 !Precision::IsInfinite(w2) &&
505 theCurve2d->Continuity() != GeomAbs_C0) ||
508 //szv#4:S4163:12Mar99 optimized
509 if ( FindParameterWithExt(Pt1, COnS, Uinf, Usup, preci, w1) &&
510 FindParameterWithExt(Pt2, COnS, Uinf, Usup, preci, w2) ) {
513 UpdateParam2d(theCurve2d);
514 myFirstDone = myLastDone = Standard_True;
518 myFirstDone = myLastDone = Standard_True;
521 //=======================================================================
522 //function : UpdateParam2d
524 //=======================================================================
526 void ShapeFix_EdgeProjAux::UpdateParam2d (const Handle(Geom2d_Curve)& theCurve2d)
528 if (myFirstParam < myLastParam) return;
530 Standard_Real cf = theCurve2d->FirstParameter();
531 Standard_Real cl = theCurve2d->LastParameter();
532 //:S4136 Standard_Real preci = BRepAPI::Precision();
533 Standard_Real preci2d = Precision::PConfusion(); //:S4136: Parametric(preci, 0.01);
535 // 15.11.2002 PTV OCC966
536 if (ShapeAnalysis_Curve::IsPeriodic(theCurve2d)) {
537 ElCLib::AdjustPeriodic(cf,cl,preci2d,myFirstParam,myLastParam);
539 else if (theCurve2d->IsClosed()) {
540 //szv#4:S4163:12Mar99 optimized
541 if ( Abs ( myFirstParam - cl ) <= preci2d ) myFirstParam = cf;
542 else if ( Abs ( myLastParam - cf ) <= preci2d ) myLastParam = cl;
545 cout << "Error : curve 2d range crossing non periodic curve origin";
552 // the curve is closed within the 'file' 2D tolerance
553 else if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
554 Handle(Geom2d_BSplineCurve) aBSpline2d =
555 Handle(Geom2d_BSplineCurve)::DownCast(theCurve2d);
556 if (aBSpline2d->StartPoint().Distance(aBSpline2d->EndPoint()) <= preci2d) {
557 if ( Abs ( myFirstParam - cl ) <= preci2d ) myFirstParam = cf;
558 else if ( Abs ( myLastParam - cf ) <= preci2d ) myLastParam = cl;
563 cout << "Warning : non increasing parameters for 2d curve." << endl;
564 cout << " update parameter 2d uncertain." << endl;
566 Standard_Real tmp1 = myFirstParam, tmp2 = myLastParam;
567 myFirstParam = theCurve2d->ReversedParameter(tmp1);
568 myLastParam = theCurve2d->ReversedParameter(tmp2);
569 theCurve2d->Reverse();
570 //cout<<"Reversed case 2"<<endl;