0026329: Restore floating point signals handling in DRAW
[occt.git] / src / BRepCheck / BRepCheck_Edge.cxx
1 // Created on: 1995-12-11
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License 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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Adaptor3d_CurveOnSurface.hxx>
19 #include <Adaptor3d_HCurve.hxx>
20 #include <Adaptor3d_HCurveOnSurface.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BRep_CurveOnSurface.hxx>
23 #include <BRep_CurveRepresentation.hxx>
24 #include <BRep_GCurve.hxx>
25 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
26 #include <BRep_ListOfCurveRepresentation.hxx>
27 #include <BRep_PolygonOnTriangulation.hxx>
28 #include <BRep_TEdge.hxx>
29 #include <BRep_TFace.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRepAdaptor_Curve.hxx>
32 #include <BRepCheck.hxx>
33 #include <BRepCheck_Edge.hxx>
34 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
35 #include <BRepCheck_ListOfStatus.hxx>
36 #include <Extrema_LocateExtPC.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <Geom2dAdaptor.hxx>
39 #include <Geom2dAdaptor_HCurve.hxx>
40 #include <Geom_Curve.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Geom_TrimmedCurve.hxx>
45 #include <GeomAdaptor_Curve.hxx>
46 #include <GeomAdaptor_HCurve.hxx>
47 #include <GeomAdaptor_HSurface.hxx>
48 #include <GeomProjLib.hxx>
49 #include <Poly_PolygonOnTriangulation.hxx>
50 #include <Poly_Triangulation.hxx>
51 #include <Precision.hxx>
52 #include <ProjLib_ProjectedCurve.hxx>
53 #include <Standard_Type.hxx>
54 #include <TColStd_Array1OfTransient.hxx>
55 #include <TColStd_HArray1OfReal.hxx>
56 #include <TopAbs_ShapeEnum.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopoDS.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Face.hxx>
61 #include <TopoDS_Shape.hxx>
62
63 IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_Edge,BRepCheck_Result)
64
65 //modified by NIZNHY-PKV Thu May 05 09:01:57 2011f
66 static 
67   Standard_Boolean Validate(const Adaptor3d_Curve&,
68   const Adaptor3d_CurveOnSurface&,
69   const Standard_Real,
70   const Standard_Boolean);
71 static
72   void PrintProblematicPoint(const gp_Pnt&,
73   const Standard_Real,
74   const Standard_Real);
75
76 static
77   Standard_Real Prec(const Adaptor3d_Curve& aAC3D,
78   const Adaptor3d_CurveOnSurface& aACS);
79 static
80   Standard_Real PrecCurve(const Adaptor3d_Curve& aAC3D);
81 static
82   Standard_Real PrecSurface(const Adaptor3d_CurveOnSurface& aACS);
83
84 //static Standard_Boolean Validate(const Adaptor3d_Curve&,
85 //                               const Adaptor3d_Curve&,
86 //                               const Standard_Real,
87 //                               const Standard_Boolean);
88 //modified by NIZNHY-PKV Thu May 05 09:02:01 2011t
89
90 static const Standard_Integer NCONTROL=23;
91
92 //=======================================================================
93 //function : BRepCheck_Edge
94 //purpose  : 
95 //=======================================================================
96
97 BRepCheck_Edge::BRepCheck_Edge(const TopoDS_Edge& E)
98 {
99   Init(E);
100   myGctrl = Standard_True;
101 }
102
103 //=======================================================================
104 //function : Minimum
105 //purpose  : 
106 //=======================================================================
107
108 void BRepCheck_Edge::Minimum()
109 {
110
111   if (!myMin) {
112     BRepCheck_ListOfStatus thelist;
113     myMap.Bind(myShape, thelist);
114     BRepCheck_ListOfStatus& lst = myMap(myShape);
115     myCref.Nullify();
116
117     // Existence et unicite d`une representation 3D
118     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&myShape.TShape());
119     BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
120     Standard_Boolean exist = Standard_False;
121     Standard_Boolean unique = Standard_True;
122     // Search for a 3D reference. If no existent one, creates it with the 
123     // first encountered CurveOnSurf; if multiple, chooses the first one...
124
125     Standard_Boolean Degenerated = TE->Degenerated();
126     Standard_Boolean SameParameter = TE->SameParameter();
127     Standard_Boolean SameRange = TE->SameRange();
128     if (!SameRange && SameParameter) {
129       BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
130     }
131     //    Handle(Geom_Curve) C3d;
132
133     while (itcr.More()) {
134       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
135       if (cr->IsCurve3D()) {
136         if (!exist) {
137           exist = Standard_True;
138         }
139         else {
140           unique = Standard_False;
141         }
142         if (myCref.IsNull() && !cr->Curve3D().IsNull()) {
143           myCref = cr;
144         }
145       }
146       itcr.Next();
147     }
148
149     if (!exist) {
150       BRepCheck::Add(lst,BRepCheck_No3DCurve);
151       // myCref est nulle
152     }
153     else if (!unique) {
154       BRepCheck::Add(lst,BRepCheck_Multiple3DCurve);
155     }
156
157     if (myCref.IsNull() && !Degenerated) {
158       itcr.Initialize(TE->Curves());
159       while (itcr.More()) {
160         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
161         if (cr->IsCurveOnSurface()) {
162           myCref = cr;
163           break;
164         }
165         itcr.Next();
166       }
167     }
168     else if (!myCref.IsNull() && Degenerated){
169       BRepCheck::Add(lst,BRepCheck_InvalidDegeneratedFlag);
170     }
171
172     if (!myCref.IsNull()) {
173       Handle(BRep_GCurve) GCref (Handle(BRep_GCurve)::DownCast (myCref));
174       Standard_Real First,Last;
175       GCref->Range(First,Last);
176       if (Last<=First) {
177         myCref.Nullify();
178         BRepCheck::Add(lst,BRepCheck_InvalidRange);
179       }
180       else {
181         if (myCref->IsCurve3D()) {
182           // eap 6 Jun 2002 occ332
183           // better transform C3d instead of transforming Surf upto C3d initial location,
184           // on transformed BSpline surface 'same parameter' may seem wrong
185           TopLoc_Location L = myShape.Location() * myCref->Location();
186           Handle(Geom_Curve) C3d = Handle(Geom_Curve)::DownCast
187             (myCref->Curve3D()->Transformed
188             (/*myCref->Location()*/L.Transformation()));
189           GeomAdaptor_Curve GAC3d(C3d, C3d->TransformedParameter(First, L.Transformation()),
190                                        C3d->TransformedParameter(Last, L.Transformation()));
191           myHCurve = new GeomAdaptor_HCurve(GAC3d);
192         }
193         else { // curve on surface
194           Handle(Geom_Surface) Sref = myCref->Surface();
195           Sref = Handle(Geom_Surface)::DownCast
196             (Sref->Transformed(myCref->Location().Transformation()));
197           const Handle(Geom2d_Curve)& PCref = myCref->PCurve();
198           Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
199           Handle(Geom2dAdaptor_HCurve) GHPCref = 
200             new Geom2dAdaptor_HCurve(PCref,First,Last);
201           Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
202           myHCurve = new Adaptor3d_HCurveOnSurface(ACSref);
203         }
204       }
205     }
206     if (lst.IsEmpty()) {
207       lst.Append(BRepCheck_NoError);
208     }
209     myMin = Standard_True;
210   }
211 }
212
213
214 //=======================================================================
215 //function : InContext
216 //purpose  : 
217 //=======================================================================
218
219 void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
220 {
221   if (myMap.IsBound(S)) {
222     return;
223   }
224   BRepCheck_ListOfStatus thelist;
225   myMap.Bind(S, thelist);
226   BRepCheck_ListOfStatus& lst = myMap(S);
227
228   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&myShape.TShape());
229   Standard_Real Tol = BRep_Tool::Tolerance(TopoDS::Edge(myShape));
230
231   TopAbs_ShapeEnum styp = S.ShapeType();
232   //  for (TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next()) {
233   TopExp_Explorer exp(S,TopAbs_EDGE) ;
234   for ( ; exp.More(); exp.Next()) {
235     if (exp.Current().IsSame(myShape)) {
236       break;
237     }
238   }
239   if (!exp.More()) {
240     BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
241     return;
242   }
243
244   switch (styp) 
245   {
246   case TopAbs_WIRE:
247     {
248     }
249     break;
250
251   case TopAbs_FACE:
252     if (!myCref.IsNull()) {
253
254       Standard_Boolean SameParameter = TE->SameParameter();
255       Standard_Boolean SameRange = TE->SameRange();
256       //  Modified by skv - Tue Apr 27 11:48:13 2004 Begin
257       if (!SameParameter || !SameRange) {
258         if (!SameParameter)
259           BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
260         if (!SameRange)
261           BRepCheck::Add(lst,BRepCheck_InvalidSameRangeFlag);
262
263         return;
264       }
265       //  Modified by skv - Tue Apr 27 11:48:14 2004 End
266       Standard_Real First = myHCurve->FirstParameter();
267       Standard_Real Last  = myHCurve->LastParameter();
268
269       Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape());
270       const TopLoc_Location& Floc = S.Location();
271       const TopLoc_Location& TFloc = TF->Location();
272       const Handle(Geom_Surface)& Su = TF->Surface();
273       TopLoc_Location L = (Floc * TFloc).Predivided(myShape.Location());
274       TopLoc_Location LE = myShape.Location() * myCref->Location();
275       const gp_Trsf& Etrsf = LE.Transformation();
276       Standard_Boolean pcurvefound = Standard_False;
277
278       BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
279       while (itcr.More()) {
280         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
281         if (cr != myCref && cr->IsCurveOnSurface(Su,L)) {
282           pcurvefound = Standard_True;
283           Handle(BRep_GCurve) GC (Handle(BRep_GCurve)::DownCast (cr));
284           Standard_Real f,l;
285           GC->Range(f,l);
286           Standard_Real ff = f, ll = l;
287           if(myCref->IsCurve3D())
288           {
289             ff = myCref->Curve3D()->TransformedParameter(f, Etrsf);
290             ll = myCref->Curve3D()->TransformedParameter(l, Etrsf);
291           }
292           // gka OCC
293           //  Modified by skv - Tue Apr 27 11:50:35 2004 Begin
294           if (Abs(ff-First) > Precision::PConfusion() ||
295               Abs(ll-Last)  > Precision::PConfusion()) {
296               BRepCheck::Add(lst,BRepCheck_InvalidSameRangeFlag);
297               BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
298           }
299           //  Modified by skv - Tue Apr 27 11:50:37 2004 End
300           if (myGctrl) {
301             Handle(Geom_Surface) Sb = cr->Surface();
302             Sb = Handle(Geom_Surface)::DownCast
303               //              (Su->Transformed(L.Transformation()));
304               (Su->Transformed(/*L*/(Floc * TFloc).Transformation()));
305             Handle(Geom2d_Curve) PC = cr->PCurve();
306             Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(Sb);
307             Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(PC,f,l);
308             Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
309             Standard_Boolean ok = 
310               Validate(myHCurve->Curve() ,ACS,Tol,SameParameter);
311             if (!ok) {
312               if (cr->IsCurveOnClosedSurface()) {
313                 BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
314               }
315               else {
316                 BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
317               }
318               //  Modified by skv - Tue Apr 27 11:53:00 2004 Begin
319               BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
320               //              if (SameParameter) {
321               //                BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
322               //              }
323               //  Modified by skv - Tue Apr 27 11:53:01 2004 End
324             }
325             if (cr->IsCurveOnClosedSurface()) {
326               GHPC->ChangeCurve2d().Load(cr->PCurve2(),f,l); // same bounds
327               ACS.Load(GHPC, GAHS); // sans doute inutile
328               ok = Validate(myHCurve->Curve(),ACS,Tol,SameParameter);
329               if (!ok) {
330                 BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
331                 //  Modified by skv - Tue Apr 27 11:53:20 2004 Begin
332                 if (SameParameter) {
333                   BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
334                 }
335                 //  Modified by skv - Tue Apr 27 11:53:23 2004 End
336               }
337             }
338           }
339         }
340         itcr.Next();
341       }
342
343       if (!pcurvefound) {
344         Handle(Geom_Plane) P;
345         Handle(Standard_Type) dtyp = Su->DynamicType();
346         if (dtyp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
347           P = Handle(Geom_Plane)::DownCast
348             (Handle(Geom_RectangularTrimmedSurface)::
349             DownCast(Su)->BasisSurface());
350         }
351         else {
352           P = Handle(Geom_Plane)::DownCast(Su);
353         }
354         if (P.IsNull()) { // not a plane
355           BRepCheck::Add(lst,BRepCheck_NoCurveOnSurface);
356         }
357         else { // on fait la projection a la volee, comme BRep_Tool
358           // plan en position
359           if (myGctrl) {
360             P = Handle(Geom_Plane)::
361               DownCast(P->Transformed(/*L*/(Floc * TFloc).Transformation()));// eap occ332
362             //on projette Cref sur ce plan
363             Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(P);
364
365             // Dub - Normalement myHCurve est une GeomAdaptor_HCurve
366             GeomAdaptor_Curve& Gac = 
367               Handle(GeomAdaptor_HCurve)::DownCast(myHCurve)->ChangeCurve();
368             Handle(Geom_Curve) C3d = Gac.Curve();
369             Handle(Geom_Curve) ProjOnPlane = 
370               GeomProjLib::ProjectOnPlane(new Geom_TrimmedCurve(C3d,First,Last),
371               P, P->Position().Direction(),
372               Standard_True);
373             Handle(GeomAdaptor_HCurve) aHCurve = 
374               new GeomAdaptor_HCurve(ProjOnPlane);
375
376             ProjLib_ProjectedCurve proj(GAHS,aHCurve);
377             Handle(Geom2d_Curve) PC = Geom2dAdaptor::MakeCurve(proj);
378             Handle(Geom2dAdaptor_HCurve) GHPC = 
379               new Geom2dAdaptor_HCurve(PC,
380               myHCurve->FirstParameter(),
381               myHCurve->LastParameter());
382
383             Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
384
385             Standard_Boolean ok = Validate(myHCurve->Curve(),ACS,
386               Tol,Standard_True); // voir dub...
387             if (!ok) {
388               BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
389             }
390           }
391         }
392       }
393     }
394     break;
395   case TopAbs_SOLID:
396     {
397       // on verifie que l`edge est bien connectee 2 fois (pas de bord libre)
398       Standard_Integer nbconnection = 0;
399       //TopExp_Explorer exp;
400       for (exp.Init(S,TopAbs_FACE); exp.More(); exp.Next()) {
401         const TopoDS_Face& fac = TopoDS::Face(exp.Current());
402         TopExp_Explorer exp2;
403         for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
404           if (exp2.Current().IsSame(myShape)) {
405             nbconnection++;
406           }
407         }
408       }
409       if (nbconnection < 2 && !TE->Degenerated()) {
410         BRepCheck::Add(myMap(S),BRepCheck_FreeEdge);
411       }
412       else if (nbconnection > 2) {
413         BRepCheck::Add(myMap(S),BRepCheck_InvalidMultiConnexity);
414       }
415       else {
416         BRepCheck::Add(myMap(S),BRepCheck_NoError);
417       }
418     }
419     break;
420   default:
421     break;
422   }
423   if (myMap(S).IsEmpty()) {
424     myMap(S).Append(BRepCheck_NoError);
425   }
426 }
427
428
429 //=======================================================================
430 //function : Blind
431 //purpose  : 
432 //=======================================================================
433
434 void BRepCheck_Edge::Blind()
435 {
436   //  Modified by skv - Tue Apr 27 11:36:01 2004 Begin
437   // The body of this function is removed because of its useless.
438   if (!myBlind) {
439     myBlind = Standard_True;
440   }
441   //  Modified by skv - Tue Apr 27 11:36:02 2004 End
442 }
443
444
445 //=======================================================================
446 //function : GeometricControls
447 //purpose  : 
448 //=======================================================================
449
450 void BRepCheck_Edge::GeometricControls(const Standard_Boolean B)
451 {
452   myGctrl = B;
453 }
454
455
456 //=======================================================================
457 //function : GeometricControls
458 //purpose  : 
459 //=======================================================================
460
461 Standard_Boolean BRepCheck_Edge::GeometricControls() const
462 {
463   return myGctrl;
464 }
465
466 //=======================================================================
467 //function :   SetStatus
468 //purpose  : 
469 //=======================================================================
470 void BRepCheck_Edge::SetStatus(const BRepCheck_Status theStatus)
471 {
472   BRepCheck::Add(myMap(myShape),theStatus);
473 }
474
475
476 //=======================================================================
477 //function : Tolerance
478 //purpose  : 
479 //=======================================================================
480
481 Standard_Real BRepCheck_Edge::Tolerance()
482 {
483   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&myShape.TShape());
484   Standard_Integer it, iRep=1, nbRep=(TE->Curves()).Extent();
485   if (nbRep<=1) {
486     return Precision::Confusion();
487   }
488   TColStd_Array1OfTransient theRep(1, nbRep*2);
489   Standard_Real First, Last;
490   if (!myHCurve.IsNull()) {
491     First = myHCurve->FirstParameter();
492     Last=  myHCurve->LastParameter();
493   }
494   else {
495     BRep_Tool::Range(TopoDS::Edge(myShape), First, Last);
496   }
497
498   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
499   for (; itcr.More(); itcr.Next()) {
500     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
501     if (cr->IsCurve3D() && !TE->Degenerated()) {
502       //// modified by jgv, 20.03.03 ////
503       TopLoc_Location Loc = myShape.Location() * cr->Location();
504       Handle(Geom_Curve) C3d = Handle(Geom_Curve)::DownCast
505         (cr->Curve3D()->Transformed( Loc.Transformation() ));
506       ///////////////////////////////////
507       GeomAdaptor_Curve GAC3d(C3d,First,Last);
508       it=iRep;
509       if (iRep>1) {
510         theRep(iRep)=theRep(1);
511         it=1;
512       }
513       theRep(it) = new GeomAdaptor_HCurve(GAC3d);
514       iRep++;
515     }
516     else if (cr->IsCurveOnSurface()) {
517       {
518         Handle(Geom_Surface) Sref = cr->Surface();
519         //// modified by jgv, 20.03.03 ////
520         TopLoc_Location Loc = myShape.Location() * cr->Location();
521         Sref = Handle(Geom_Surface)::DownCast
522           (Sref->Transformed( Loc.Transformation() ));
523         ///////////////////////////////////
524         const Handle(Geom2d_Curve)& PCref = cr->PCurve();
525         Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
526         Handle(Geom2dAdaptor_HCurve) GHPCref = 
527           new Geom2dAdaptor_HCurve(PCref,First,Last);
528         Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
529         theRep(iRep) = new Adaptor3d_HCurveOnSurface(ACSref);
530         iRep++;
531       }
532       if (cr->IsCurveOnClosedSurface()) {
533         Handle(Geom_Surface) Sref = cr->Surface();
534         Sref = Handle(Geom_Surface)::DownCast
535           (Sref->Transformed(cr->Location().Transformation()));
536         const Handle(Geom2d_Curve)& PCref = cr->PCurve2();
537         Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
538         Handle(Geom2dAdaptor_HCurve) GHPCref = 
539           new Geom2dAdaptor_HCurve(PCref,First,Last);
540         Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
541         theRep(iRep) = new Adaptor3d_HCurveOnSurface(ACSref);
542         iRep++;
543         nbRep++;
544       }
545     }
546     else {
547       nbRep--;
548     }
549   }
550
551   Standard_Real dist2, tol2, tolCal=0., prm;
552   gp_Pnt center, othP;
553   Standard_Integer i;
554   for (i= 0; i< NCONTROL; i++) {
555     prm = ((NCONTROL-1-i)*First + i*Last)/(NCONTROL-1);
556     tol2=dist2=0.;
557     center=(*(Handle(Adaptor3d_HCurve)*)&theRep(1))->Value(prm);
558     if(Precision::IsInfinite(center.X()) || Precision::IsInfinite(center.Y()) 
559        || Precision::IsInfinite(center.Z()))
560     {
561       return Precision::Infinite();
562     }
563     for (iRep=2; iRep<=nbRep; iRep++) {
564       othP=(*(Handle(Adaptor3d_HCurve)*)&theRep(iRep))->Value(prm);
565       if(Precision::IsInfinite(othP.X()) || Precision::IsInfinite(othP.Y()) 
566         || Precision::IsInfinite(othP.Z()))
567       {
568         return Precision::Infinite();
569       }
570       dist2=center.SquareDistance(othP);
571       if (dist2>tolCal) tolCal=dist2;
572     }
573     if (tol2>tolCal) {
574       tolCal=tol2;
575     }
576   }
577   // On prend 5% de marge car au dessus on crontrole severement
578   return sqrt(tolCal)*1.05;
579 }
580
581
582 //=======================================================================
583 //function : CheckPolygonOnTriangulation
584 //purpose  : 
585 //=======================================================================
586 BRepCheck_Status BRepCheck_Edge::
587   CheckPolygonOnTriangulation(const TopoDS_Edge& theEdge)
588 {
589   BRep_ListOfCurveRepresentation& aListOfCR = 
590     (*((Handle(BRep_TEdge)*) &theEdge.TShape()))->ChangeCurves();
591   BRep_ListIteratorOfListOfCurveRepresentation anITCR(aListOfCR);
592
593   BRepAdaptor_Curve aBC;
594   aBC.Initialize(theEdge);
595
596   if(!aBC.Is3DCurve())
597     return BRepCheck_NoError;
598
599   while (anITCR.More())
600   {
601     if(!anITCR.Value()->IsPolygonOnTriangulation())
602     {
603       anITCR.Next();
604       continue;
605     }
606
607     const Handle(BRep_CurveRepresentation) aCR = anITCR.Value();
608     Handle(BRep_PolygonOnTriangulation) aPT (Handle(BRep_PolygonOnTriangulation)::DownCast(aCR));
609
610     const TopLoc_Location aLL = theEdge.Location() * aPT->Location();
611
612     const Handle(Poly_Triangulation) aTriang =  aCR->Triangulation();
613     const Handle(Poly_PolygonOnTriangulation) aPOnTriag = 
614       aCR->IsPolygonOnClosedTriangulation() ? 
615       aCR->PolygonOnTriangulation2() : 
616     aCR->PolygonOnTriangulation();
617     const TColStd_Array1OfInteger& anIndices = aPOnTriag->Nodes();
618     const TColgp_Array1OfPnt& Nodes = aTriang->Nodes();
619     const Standard_Integer aNbNodes = anIndices.Length();
620
621     const Standard_Real aTol = aPOnTriag->Deflection() +
622       BRep_Tool::Tolerance(theEdge);
623
624     if(aPOnTriag->HasParameters())
625     {
626       for(Standard_Integer i = aPOnTriag->Parameters()->Lower();
627         i <= aPOnTriag->Parameters()->Upper(); i++)
628       {
629         const Standard_Real aParam = aPOnTriag->Parameters()->Value(i);
630         const gp_Pnt  aPE(aBC.Value(aParam)), 
631           aPnt(Nodes(anIndices(i)).Transformed(aLL));
632
633         const Standard_Real aSQDist = aPE.SquareDistance(aPnt);
634         if(aSQDist > aTol*aTol)
635         {
636           return BRepCheck_InvalidPolygonOnTriangulation;
637         }
638       }
639     }
640     else
641     {
642       //If aPOnTriag does not have any parameters we will check if it
643       //inscribes into Bounding box, which is built on the edge triangulation.
644
645       Bnd_Box aB;
646
647       for (Standard_Integer i = 1; i <= aNbNodes; i++)
648       {
649         if (aLL.IsIdentity())
650           aB.Add(Nodes(anIndices(i)));
651         else
652           aB.Add(Nodes(anIndices(i)).Transformed(aLL));
653       }
654
655       aB.Enlarge(aTol);
656
657       Standard_Real aFP = aBC.FirstParameter();
658       Standard_Real aLP = aBC.LastParameter();
659
660       const Standard_Real aStep = (aLP - aFP)/IntToReal(NCONTROL);
661       gp_Pnt aP;
662       Standard_Real aPar = aFP;
663
664       for(Standard_Integer i = 1; i < NCONTROL; i ++)
665       {
666         aBC.D0(aPar, aP);
667         if(aB.IsOut(aP))
668         {
669           return BRepCheck_InvalidPolygonOnTriangulation;
670         }
671
672         aPar += aStep;
673       }
674
675       aBC.D0(aLP, aP);
676       if(aB.IsOut(aP))
677       {
678         return BRepCheck_InvalidPolygonOnTriangulation;
679       }
680     }
681
682     anITCR.Next();
683   }
684
685   return BRepCheck_NoError;
686 }
687
688 //=======================================================================
689 //function : Validate
690 //purpose  : 
691 //=======================================================================
692 Standard_Boolean Validate(const Adaptor3d_Curve& CRef,
693   const Adaptor3d_CurveOnSurface& Other,
694   const Standard_Real Tol,
695   const Standard_Boolean SameParameter)
696 {
697   Standard_Boolean  Status, proj; 
698   Standard_Real aPC, First, Last, Error;
699   gp_Pnt  problematic_point ;
700   //
701   Status = Standard_True;
702   Error = 0.;
703   First = CRef.FirstParameter();
704   Last  = CRef.LastParameter();
705
706   aPC=Precision::PConfusion();
707   proj = (!SameParameter || 
708     Abs(Other.FirstParameter()-First) > aPC || 
709     Abs( Other.LastParameter()-Last) > aPC);
710   if (!proj)
711   {
712     Standard_Integer i;
713     Standard_Real Tol2, prm, dD;
714     gp_Pnt pref, pother;
715     //modified by NIZNHY-PKV Thu May 05 09:06:41 2011f
716     //OCC22428
717     dD=Prec(CRef, Other);//3.e-15;
718     Tol2=Tol+dD;
719     Tol2=Tol2*Tol2;
720     //Tol2=Tol*Tol;
721     //modified by NIZNHY-PKV Thu May 05 09:06:47 2011t
722
723     for (i = 0; i < NCONTROL; ++i) {
724       prm = ((NCONTROL-1-i)*First + i*Last)/(NCONTROL-1);
725       pref = CRef.Value(prm);
726       pother = Other.Value(prm);
727       if (pref.SquareDistance(pother) > Tol2) {
728         problematic_point = pref ;
729         Status = Standard_False;
730         Error  = pref.Distance(pother);
731         PrintProblematicPoint(problematic_point, Error, Tol);
732         return Status;
733         //goto FINISH ;
734       }
735     }
736   }
737   else {
738     Extrema_LocateExtPC refd,otherd;
739     Standard_Real OFirst = Other.FirstParameter();
740     Standard_Real OLast  = Other.LastParameter();
741     gp_Pnt pd = CRef.Value(First);
742     gp_Pnt pdo = Other.Value(OFirst);
743     Standard_Real distt = pd.SquareDistance(pdo);
744     if (distt > Tol*Tol) {
745       problematic_point = pd ;
746       Status = Standard_False ;
747       Error = Sqrt(distt);
748       PrintProblematicPoint(problematic_point, Error, Tol);
749       return Status;
750       //goto FINISH ;
751     }
752     pd = CRef.Value(Last);
753     pdo = Other.Value(OLast);
754     distt = pd.SquareDistance(pdo);
755     if (distt > Tol*Tol) {
756       problematic_point = pd ;
757       Status = Standard_False ;
758       Error = Sqrt(distt);
759       PrintProblematicPoint(problematic_point, Error, Tol);
760       return Status;
761       //goto FINISH ;
762     }
763
764     refd.Initialize(CRef,First,Last,CRef.Resolution(Tol));
765     otherd.Initialize(Other,OFirst,OLast,Other.Resolution(Tol));
766     for (Standard_Integer i = 2; i< NCONTROL-1; i++) {
767       Standard_Real rprm = ((NCONTROL-1-i)*First + i*Last)/(NCONTROL-1);
768       gp_Pnt pref = CRef.Value(rprm);
769       Standard_Real oprm = ((NCONTROL-1-i)*OFirst + i*OLast)/(NCONTROL-1);
770       gp_Pnt pother = Other.Value(oprm);
771       refd.Perform(pother,rprm);
772       if (!refd.IsDone() || refd.SquareDistance() > Tol * Tol) {
773         problematic_point = pref ;
774         Status = Standard_False ;
775         if (refd.IsDone()) {
776           Error = sqrt (refd.SquareDistance());
777         }
778         else {
779           Error = RealLast();
780         }
781         PrintProblematicPoint(problematic_point, Error, Tol);
782         return Status;
783         //goto FINISH ;
784       }
785       otherd.Perform(pref,oprm);
786       if (!otherd.IsDone() || otherd.SquareDistance() > Tol * Tol) {
787         problematic_point = pref ;
788         Status = Standard_False ;
789         if (otherd.IsDone()) {
790           Error = sqrt (otherd.SquareDistance());
791         }
792         else {
793           Error = RealLast();
794         }
795         PrintProblematicPoint(problematic_point, Error, Tol);
796         return Status;
797         //goto FINISH ;
798       }
799     }
800   }
801
802   return Status ;
803
804 }
805 //=======================================================================
806 //function : Prec
807 //purpose  : 
808 //=======================================================================
809 Standard_Real Prec(const Adaptor3d_Curve& aAC3D,
810   const Adaptor3d_CurveOnSurface& aACS)
811 {
812   Standard_Real aXEmax, aXC, aXS;
813   //
814   aXC=PrecCurve(aAC3D);
815   aXS=PrecSurface(aACS);
816   aXEmax=(aXC>aXS) ? aXC: aXS;
817   return aXEmax;
818 }
819 //=======================================================================
820 //function : PrecCurve
821 //purpose  : 
822 //=======================================================================
823 Standard_Real PrecCurve(const Adaptor3d_Curve& aAC3D)
824 {
825   Standard_Real aXEmax;
826   GeomAbs_CurveType aCT;
827   //
828   aXEmax=RealEpsilon(); 
829   //
830   aCT=aAC3D.GetType();
831   if (aCT==GeomAbs_Ellipse) {
832     Standard_Integer i;
833     Standard_Real aX[5], aXE;
834     //
835     gp_Elips aEL3D=aAC3D.Ellipse();
836     aEL3D.Location().Coord(aX[0], aX[1], aX[2]);
837     aX[3]=aEL3D.MajorRadius();
838     aX[4]=aEL3D.MinorRadius();
839     aXEmax=-1.;
840     for (i=0; i<5; ++i) {
841       if (aX[i]<0.) {
842         aX[i]=-aX[i];
843       }
844       aXE=Epsilon(aX[i]);
845       if (aXE>aXEmax) {
846         aXEmax=aXE;
847       }
848     }
849   }//if (aCT=GeomAbs_Ellipse) {
850   //
851   return aXEmax;
852 }
853 //=======================================================================
854 //function : PrecSurface
855 //purpose  : 
856 //=======================================================================
857 Standard_Real PrecSurface(const Adaptor3d_CurveOnSurface& aACS)
858 {
859   Standard_Real aXEmax;
860   GeomAbs_SurfaceType aST;
861   //
862   aXEmax=RealEpsilon(); 
863   //
864   const Handle(Adaptor3d_HSurface)& aAHS=aACS.GetSurface();
865   aST=aAHS->GetType();
866   if (aST==GeomAbs_Cone) {
867     gp_Cone aCone=aAHS->Cone();
868     Standard_Integer i;
869     Standard_Real aX[4], aXE;
870     //
871     aCone.Location().Coord(aX[0], aX[1], aX[2]);
872     aX[3]=aCone.RefRadius();
873     aXEmax=-1.;
874     for (i=0; i<4; ++i) {
875       if (aX[i]<0.) {
876         aX[i]=-aX[i];
877       }
878       aXE=Epsilon(aX[i]);
879       if (aXE>aXEmax) {
880         aXEmax=aXE;
881       }
882     }
883   }//if (aST==GeomAbs_Cone) {
884   return aXEmax;
885 }
886 //=======================================================================
887 //function : PrintProblematicPoint
888 //purpose  : 
889 //=======================================================================
890 #ifdef OCCT_DEBUG
891 void PrintProblematicPoint(const gp_Pnt& problematic_point,
892   const Standard_Real Error,
893   const Standard_Real Tol)
894 {
895   cout << " **** probleme de SameParameter au point :" << endl;
896   cout << "         " << problematic_point.Coord(1) << " " 
897     << problematic_point.Coord(2) << " " << problematic_point.Coord(3) << endl ;
898   cout << "   Erreur detectee :" << Error << " Tolerance :" << Tol << endl;
899 }
900 #else
901 void PrintProblematicPoint(const gp_Pnt&,
902   const Standard_Real,
903   const Standard_Real)
904 {
905 }
906 #endif