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