0025122: Expose internal static function ComputeDeviation from ShapeAnalysis_Edge.cxx
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_Edge.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
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
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.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //:o8 abv 19.02.99: CTS18541.stp #18559: coeff 1.0001 added in CheckVertexTol
15 //:p1 abv 22.02.99: protection against edges with no vertices (infinite)
16 //szv#4 S4163
17 //:s1 abv 22.04.99: PRO7226 #489490: protect against Null 3d curve
18 //:s4 abv 26.04.99: sim6049.igs 21677: copy of curve is necessary to get True SP
19 //    abv 06.05.99: S4137: adding methods GetTangent2d()
20 #include <ShapeAnalysis_Edge.ixx>
21
22 #include <Standard_ErrorHandler.hxx>
23 #include <Standard_Failure.hxx>
24
25 #include <Precision.hxx>
26
27 #include <GCPnts_AbscissaPoint.hxx>
28 #include <Adaptor3d_Curve.hxx>
29 #include <Adaptor3d_CurveOnSurface.hxx>
30 #include <Geom2dAdaptor_HCurve.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <GeomAdaptor_HSurface.hxx>
33 #include <BRepAdaptor_Curve.hxx>
34 #include <BRepExtrema_DistShapeShape.hxx>
35
36 #include <BRep_Tool.hxx>
37 #include <BRep_TEdge.hxx>
38 #include <BRep_GCurve.hxx>
39 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
40 #include <BRep_Builder.hxx>
41
42 #include <Extrema_LocateExtPC.hxx>
43
44 #include <ShapeExtend.hxx>
45 #include <TopExp.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <Geom_Plane.hxx>
48
49
50 //=======================================================================
51 //function : ShapeAnalysis_Edge
52 //purpose  : 
53 //=======================================================================
54
55 ShapeAnalysis_Edge::ShapeAnalysis_Edge()
56 {
57   myStatus = 0;//ShapeExtend::EncodeStatus (ShapeExtend_OK);
58 }
59
60
61 //=======================================================================
62 //function : BoundUV
63 //purpose  : 
64 //=======================================================================
65
66 Standard_Boolean ShapeAnalysis_Edge::BoundUV (const TopoDS_Edge& edge,
67                                               const TopoDS_Face& face,
68                                               gp_Pnt2d& first, gp_Pnt2d& last) const
69 {
70   TopLoc_Location L;
71   const Handle(Geom_Surface) S = BRep_Tool::Surface(face, L);
72   return BoundUV (edge, S, L, first, last);
73 }
74
75
76 //=======================================================================
77 //function : BoundUV
78 //purpose  : 
79 //=======================================================================
80
81 Standard_Boolean ShapeAnalysis_Edge::BoundUV (const TopoDS_Edge& edge,
82                                               const Handle(Geom_Surface)& surface,
83                                               const TopLoc_Location& location,
84                                               gp_Pnt2d& first, gp_Pnt2d& last) const
85 {
86   Handle(Geom2d_Curve) c2d;
87   Standard_Real uf,ul;
88   if (!PCurve (edge, surface, location, c2d, uf, ul)) return Standard_False;
89   first = c2d->Value (uf);
90   last  = c2d->Value (ul);
91   return Standard_True;
92 }
93
94
95 //=======================================================================
96 //function : HasCurve3d
97 //purpose  : 
98 //=======================================================================
99
100 Standard_Boolean ShapeAnalysis_Edge::HasCurve3d (const TopoDS_Edge& edge) const
101 {
102   Standard_Real cf, cl;
103   Handle(Geom_Curve) c3d = BRep_Tool::Curve (edge, cf, cl);
104   return !c3d.IsNull();
105 }
106
107
108 //=======================================================================
109 //function : Curve3d
110 //purpose  : 
111 //=======================================================================
112
113 Standard_Boolean ShapeAnalysis_Edge::Curve3d (const TopoDS_Edge& edge,
114                                               Handle(Geom_Curve)& C3d,
115                                               Standard_Real& cf, Standard_Real& cl,
116                                               const Standard_Boolean orient) const
117 {
118   TopLoc_Location L;
119   C3d = BRep_Tool::Curve (edge, L, cf, cl);
120   if( !C3d.IsNull() && !L.IsIdentity() ) {
121     C3d = Handle(Geom_Curve)::DownCast(C3d->Transformed(L.Transformation()));
122     cf = C3d->TransformedParameter(cf, L.Transformation());
123     cl = C3d->TransformedParameter(cl, L.Transformation());
124   }
125   if (orient) {
126     if (edge.Orientation() == TopAbs_REVERSED)
127       {Standard_Real tmp = cf; cf = cl; cl = tmp;}
128   }
129   return !C3d.IsNull();
130 }
131
132
133 //=======================================================================
134 //function : IsClosed3d
135 //purpose  : 
136 //=======================================================================
137
138 Standard_Boolean ShapeAnalysis_Edge::IsClosed3d (const TopoDS_Edge& edge) const
139 {
140   Standard_Real cf,cl;
141   Handle(Geom_Curve) c3d = BRep_Tool::Curve (edge,cf,cl);
142   if (c3d.IsNull()) return Standard_False;
143   if (!c3d->IsClosed()) return Standard_False;
144   return FirstVertex (edge).IsSame (LastVertex (edge));
145 }
146
147
148 //=======================================================================
149 //function : HasPCurve
150 //purpose  : 
151 //=======================================================================
152
153 Standard_Boolean ShapeAnalysis_Edge::HasPCurve (const TopoDS_Edge& edge,
154                                                 const TopoDS_Face& face) const
155 {
156   TopLoc_Location L;
157   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
158   return HasPCurve (edge, S, L);
159 }
160
161
162 //=======================================================================
163 //function : HasPCurve
164 //purpose  : 
165 //=======================================================================
166
167 Standard_Boolean ShapeAnalysis_Edge::HasPCurve (const TopoDS_Edge& edge,
168                                                 const Handle(Geom_Surface)& surface,
169                                                 const TopLoc_Location& location) const
170 {
171   //try { //szv#4:S4163:12Mar99 waste try
172     Standard_Real cf, cl;
173     Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface (edge, surface, location, cf, cl);
174     return !c2d.IsNull();
175   /* }
176   catch (Standard_Failure) {
177   }
178   return Standard_False; */
179 }
180
181
182 //=======================================================================
183 //function : PCurve
184 //purpose  : 
185 //=======================================================================
186
187 Standard_Boolean ShapeAnalysis_Edge::PCurve (const TopoDS_Edge& edge,
188                                              const TopoDS_Face& face,
189                                              Handle(Geom2d_Curve)& C2d,
190                                              Standard_Real& cf, Standard_Real& cl,
191                                              const Standard_Boolean orient) const
192 {
193   //:abv 20.05.02: take into account face orientation
194   // COMMENTED BACK - NEEDS MORE CHANGES IN ALL SHAPEHEALING
195 //   C2d = BRep_Tool::CurveOnSurface (edge, face, cf, cl);
196 //   if (orient && edge.Orientation() == TopAbs_REVERSED) {
197 //     Standard_Real tmp = cf; cf = cl; cl = tmp;
198 //   }
199 //   return !C2d.IsNull();
200   TopLoc_Location L;
201   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
202   return PCurve (edge, S, L, C2d, cf, cl, orient);
203 }
204
205
206 //=======================================================================
207 //function : PCurve
208 //purpose  : 
209 //=======================================================================
210
211 Standard_Boolean ShapeAnalysis_Edge::PCurve (const TopoDS_Edge& edge,
212                                              const Handle(Geom_Surface)& surface,
213                                              const TopLoc_Location& location,
214                                              Handle(Geom2d_Curve)& C2d,
215                                              Standard_Real& cf, Standard_Real& cl,
216                                              const Standard_Boolean orient) const
217 {
218   C2d = BRep_Tool::CurveOnSurface (edge, surface, location, cf, cl);
219   if ( orient && edge.Orientation() == TopAbs_REVERSED ) {
220     Standard_Real tmp = cf; cf = cl; cl = tmp;
221   }
222   return !C2d.IsNull();
223 }
224
225
226 //=======================================================================
227 //function : IsSeam
228 //purpose  : 
229 //=======================================================================
230
231 Standard_Boolean ShapeAnalysis_Edge::IsSeam (const TopoDS_Edge& edge,
232                                              const TopoDS_Face& face) const
233 {
234   return BRep_Tool::IsClosed (edge, face);
235 }
236
237
238 //=======================================================================
239 //function : IsSeam
240 //purpose  : 
241 //=======================================================================
242
243 Standard_Boolean ShapeAnalysis_Edge::IsSeam (const TopoDS_Edge& edge,
244                                              const Handle(Geom_Surface)& surface,
245                                              const TopLoc_Location& location) const
246 {
247   return BRep_Tool::IsClosed (edge, surface, location);
248 }
249
250
251 //=======================================================================
252 //function : FirstVertex
253 //purpose  : 
254 //=======================================================================
255
256 TopoDS_Vertex ShapeAnalysis_Edge::FirstVertex (const TopoDS_Edge& edge) const
257 {
258   TopoDS_Vertex V;
259   if (edge.Orientation() == TopAbs_REVERSED) {
260     V = TopExp::LastVertex(edge);
261     V.Reverse();
262   }
263   else {
264     V = TopExp::FirstVertex (edge);
265   }
266   return V;
267 }
268
269
270 //=======================================================================
271 //function : LastVertex
272 //purpose  : 
273 //=======================================================================
274
275 TopoDS_Vertex ShapeAnalysis_Edge::LastVertex (const TopoDS_Edge& edge) const
276 {
277   TopoDS_Vertex V;
278   if (edge.Orientation() == TopAbs_REVERSED) {
279     V = TopExp::FirstVertex(edge);
280     V.Reverse();
281   }
282   else {
283     V = TopExp::LastVertex (edge);
284   }
285   return V;
286 }
287
288
289 //=======================================================================
290 //function : Status
291 //purpose  : 
292 //=======================================================================
293
294 Standard_Boolean ShapeAnalysis_Edge::Status (const ShapeExtend_Status Status) const
295 {
296   return ShapeExtend::DecodeStatus (myStatus, Status);
297 }
298
299
300 //=======================================================================
301 //function : GetEndTangent2d
302 //purpose  : 
303 //=======================================================================
304
305 Standard_Boolean ShapeAnalysis_Edge::GetEndTangent2d (const TopoDS_Edge &edge, 
306                                                       const TopoDS_Face &face,
307                                                       const Standard_Boolean atend1, /* skl : change "atend" to "atend1" */ 
308                                                       gp_Pnt2d &pnt, 
309                                                       gp_Vec2d &v,
310                                                       const Standard_Real dparam) const
311 {
312   TopLoc_Location L;
313   const Handle(Geom_Surface) S = BRep_Tool::Surface ( face, L );
314   return GetEndTangent2d ( edge, S, L, atend1, pnt, v, dparam );
315 }
316
317
318 //=======================================================================
319 //function : GetEndTangent2d
320 //purpose  : 
321 //=======================================================================
322
323 Standard_Boolean ShapeAnalysis_Edge::GetEndTangent2d (const TopoDS_Edge &edge, 
324                                                       const Handle(Geom_Surface)& S,
325                                                       const TopLoc_Location& L,
326                                                       const Standard_Boolean atend2, /* skl : change "atend" to "atend2" */
327                                                       gp_Pnt2d &pnt, 
328                                                       gp_Vec2d &v,
329                                                       const Standard_Real dparam) const
330 {
331   Standard_Real cf, cl;
332   Handle(Geom2d_Curve) c2d;
333   if ( ! PCurve ( edge, S, L, c2d, cf, cl ) ) {
334     v = gp_Vec2d(0,0);
335     return Standard_False;
336   }
337   Standard_Real dpnew = dparam;
338
339   if(dpnew>Precision::Confusion()) {
340     gp_Pnt2d ptmp;
341     Standard_Real par1,par2,delta=(cl-cf)*dpnew;
342     if(Abs(delta)<Precision::PConfusion()) {
343       dpnew=0.0;
344     }
345     else {
346       if(atend2) {
347         par1 = cl;
348         par2 = cl - delta;
349         c2d->D0(par1,pnt);
350         c2d->D0(par2,ptmp);
351         v = pnt.XY() - ptmp.XY();
352       }
353       else {
354         par1 = cf;
355         par2 = cf + delta;
356         c2d->D0(par1,pnt);
357         c2d->D0(par2,ptmp);
358         v = ptmp.XY() - pnt.XY();
359       }
360       if( v.SquareMagnitude() < Precision::PConfusion()*Precision::PConfusion() ) {
361         dpnew=0.0;
362       }
363     }
364   }
365   
366   if(dpnew<=Precision::Confusion()) {
367     // get non-null tangency searching until 3rd derivative, or as straight btw ends
368     Standard_Real par = ( atend2 ? cl : cf );
369     c2d->D1 ( par, pnt, v );
370     if ( v.SquareMagnitude() < Precision::PConfusion()*Precision::PConfusion() ) {
371       gp_Vec2d d1;
372       c2d->D2 ( par, pnt, d1, v );
373       if ( v.SquareMagnitude() < Precision::PConfusion()*Precision::PConfusion() ) {
374         gp_Vec2d d2;
375         c2d->D3 ( par, pnt, d1, d2, v );
376         if ( v.SquareMagnitude() < Precision::PConfusion()*Precision::PConfusion() ) {
377           gp_Pnt2d p2;
378           c2d->D0 ( ( atend2 ? cf : cl ), p2 );
379           v = p2.XY() - pnt.XY();
380           if ( v.SquareMagnitude() < Precision::PConfusion()*Precision::PConfusion() )
381             return Standard_False;
382         }
383       }
384     }
385     if ( edge.Orientation() == TopAbs_REVERSED ) v.Reverse();
386   }
387
388   //if ( edge.Orientation() == TopAbs_REVERSED ) v.Reverse();
389   return Standard_True;
390 }
391             
392
393 //=======================================================================
394 //function : CheckCurve3dWithPCurve
395 //purpose  : 
396 //=======================================================================
397
398 Standard_Boolean ShapeAnalysis_Edge::CheckCurve3dWithPCurve (const TopoDS_Edge& edge,
399                                                              const TopoDS_Face& face) 
400 {
401   TopLoc_Location L;
402   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
403   return CheckCurve3dWithPCurve (edge, S, L);
404 }
405
406
407 //=======================================================================
408 //function : CheckCurve3dWithPCurve
409 //purpose  : 
410 //=======================================================================
411
412 Standard_Boolean ShapeAnalysis_Edge::CheckCurve3dWithPCurve (const TopoDS_Edge& edge,
413                                                              const Handle(Geom_Surface)& surface,
414                                                              const TopLoc_Location& location) 
415 {
416   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
417
418   if(surface->IsKind(STANDARD_TYPE(Geom_Plane)))
419      return Standard_False;
420   
421   Handle (Geom2d_Curve) c2d;
422   Standard_Real f2d, l2d; //szv#4:S4163:12Mar99 moved down f3d, l3d
423   if (!PCurve (edge, surface, location, c2d, f2d ,l2d, Standard_False)) {
424     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
425     return Standard_False;
426   }
427
428   Handle (Geom_Curve) c3d; //szv#4:S4163:12Mar99 moved
429   Standard_Real f3d, l3d; //szv#4:S4163:12Mar99 moved
430   if (!Curve3d (edge, c3d, f3d, l3d, Standard_False)) {
431     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
432     return Standard_False;
433   }
434
435   TopoDS_Vertex aFirstVert = FirstVertex (edge);
436   TopoDS_Vertex aLastVert  = LastVertex (edge);
437
438   if (aFirstVert.IsNull() || aLastVert.IsNull())
439     return Standard_False;
440
441   Standard_Real preci1 = BRep_Tool::Tolerance (aFirstVert),
442                 preci2 = BRep_Tool::Tolerance (aLastVert);
443
444   gp_Pnt2d p2d1 = c2d->Value (f2d),
445            p2d2 = c2d->Value (l2d);
446
447   //#39 rln 17.11.98 S4054, annie_surf.igs entity 39
448   return CheckPoints (c3d->Value (f3d)/*.Transformed (location.Transformation())*/,
449                       c3d->Value (l3d)/*.Transformed (location.Transformation())*/,
450                       surface->Value (p2d1.X(), p2d1.Y()).Transformed (location.Transformation()),
451                       surface->Value (p2d2.X(), p2d2.Y()).Transformed (location.Transformation()),
452                       preci1, preci2);
453 }
454
455
456 //=======================================================================
457 //function : CheckPoints
458 //purpose  : 
459 //=======================================================================
460
461 Standard_Boolean ShapeAnalysis_Edge::CheckPoints (const gp_Pnt& P1A,
462                                                   const gp_Pnt& P1B,
463                                                   const gp_Pnt& P2A,
464                                                   const gp_Pnt& P2B,
465                                                   const Standard_Real preci1,
466                                                   const Standard_Real preci2) 
467 {
468   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
469   if (P1A.SquareDistance (P2A) <= preci1 * preci1 &&
470       P1B.SquareDistance (P2B) <= preci2 * preci2)
471     return Standard_False;
472   else if (P1A.Distance (P2B) + (P1B.Distance (P2A)) <
473            P1A.Distance (P2A) + (P1B.Distance (P2B)))
474     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
475   return Standard_True;
476 }
477
478
479 //=======================================================================
480 //function : CheckVerticesWithCurve3d
481 //purpose  : 
482 //=======================================================================
483
484 Standard_Boolean ShapeAnalysis_Edge::CheckVerticesWithCurve3d (const TopoDS_Edge& edge,
485                                                                const Standard_Real preci,
486                                                                const Standard_Integer vtx)
487 {
488   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
489
490   TopoDS_Vertex V1 = FirstVertex (edge);
491   TopoDS_Vertex V2 = LastVertex (edge);
492   gp_Pnt p1v = BRep_Tool::Pnt (V1);
493   gp_Pnt p2v = BRep_Tool::Pnt (V2);
494
495   Standard_Real cf,cl;
496   Handle(Geom_Curve) c3d;
497   if ( ! Curve3d (edge,c3d,cf,cl) ) {
498     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
499     return Standard_False;
500   }
501
502   //  on va faire les checks ...
503   if (vtx != 2) {
504     //  1er VTX
505     gp_Pnt p13d = c3d->Value(cf);
506     //szv#4:S4163:12Mar99 optimized
507     if (p1v.Distance(p13d) > (preci < 0 ? BRep_Tool::Tolerance (V1) : preci))
508       myStatus |= ShapeExtend_DONE1;
509   }
510
511   if (vtx != 1) {
512     //  2me VTX
513     gp_Pnt p23d = c3d->Value(cl);
514     //szv#4:S4163:12Mar99 optimized
515     if (p2v.Distance(p23d) > (preci < 0 ? BRep_Tool::Tolerance (V2) : preci))
516       myStatus |= ShapeExtend_DONE2;
517   }
518
519   return Status ( ShapeExtend_DONE );
520 }
521
522
523 //=======================================================================
524 //function : CheckVerticesWithPCurve
525 //purpose  : 
526 //=======================================================================
527
528 Standard_Boolean ShapeAnalysis_Edge::CheckVerticesWithPCurve (const TopoDS_Edge& edge,
529                                                               const TopoDS_Face& face,
530                                                               const Standard_Real preci,
531                                                               const Standard_Integer vtx)
532 {
533   TopLoc_Location L;
534   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
535   return CheckVerticesWithPCurve (edge, S, L, preci, vtx); //szv#4:S4163:12Mar99 `vtx,preci` wrong parameters order
536 }
537
538
539 //=======================================================================
540 //function : CheckVerticesWithPCurve
541 //purpose  : 
542 //=======================================================================
543
544 Standard_Boolean ShapeAnalysis_Edge::CheckVerticesWithPCurve (const TopoDS_Edge& edge,
545                                                               const Handle(Geom_Surface)& surf,
546                                                               const TopLoc_Location& loc,
547                                                               const Standard_Real preci,
548                                                               const Standard_Integer vtx)
549 {
550   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
551
552   TopoDS_Vertex V1 = FirstVertex (edge);
553   TopoDS_Vertex V2 = LastVertex (edge);
554   gp_Pnt p1v = BRep_Tool::Pnt (V1);
555   gp_Pnt p2v = BRep_Tool::Pnt (V2);
556
557   Standard_Real cf, cl;
558   Handle(Geom2d_Curve) c2d;
559   if ( ! PCurve ( edge, surf, loc, c2d, cf, cl ) ) {
560     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
561     return Standard_False;
562   }
563
564   // on va faire les checks ...
565   if (vtx != 2) { //  1er VTX
566     gp_Pnt2d p1uv = c2d->Value (cf);  
567     gp_Pnt p12d = surf->Value (p1uv.X(), p1uv.Y());
568     // szv#4:S4163:12Mar99 optimized
569     if ( p1v.Distance(p12d) > (preci < 0 ? BRep_Tool::Tolerance (V1) : preci) )
570       myStatus |= ShapeExtend_DONE1;
571   }
572
573   if (vtx != 1) { //  2me VTX
574     gp_Pnt2d p2uv = c2d->Value (cl);  
575     gp_Pnt p22d = surf->Value (p2uv.X(), p2uv.Y());
576     // szv#4:S4163:12Mar99 optimized
577     if ( p2v.Distance(p22d) > (preci < 0 ? BRep_Tool::Tolerance (V2) : preci) )
578       myStatus |= ShapeExtend_DONE2;
579   }
580
581   return Status ( ShapeExtend_DONE );
582 }
583
584
585 //=======================================================================
586 //function : CheckVertexTolerance
587 //purpose  : 
588 //=======================================================================
589
590 static Standard_Integer CheckVertexTolerance(const TopoDS_Edge& edge,
591                                              const TopoDS_Face& face,
592                                              const Standard_Boolean checkAll,
593                                              Standard_Real& toler1,
594                                              Standard_Real& toler2)
595 {
596   Standard_Integer Status = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
597
598   ShapeAnalysis_Edge sae;
599   TopoDS_Vertex V1 = sae.FirstVertex (edge);
600   TopoDS_Vertex V2 = sae.LastVertex (edge);
601   if ( V1.IsNull() || V2.IsNull() ) { //:p1 abv 22 Feb 99: r76sy.stp
602     Status |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
603     return Status;
604   }
605
606   Standard_Real old1 = BRep_Tool::Tolerance (V1);
607   Standard_Real old2 = BRep_Tool::Tolerance (V2);
608   gp_Pnt pnt1 = BRep_Tool::Pnt (V1);
609   gp_Pnt pnt2 = BRep_Tool::Pnt (V2);
610
611   Standard_Real a, b;
612   Handle(Geom_Curve) c3d;
613   if ( ! sae.Curve3d(edge, c3d, a, b, Standard_True)) {
614     if ( ! BRep_Tool::Degenerated ( edge ) ) 
615       Status |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
616     toler1 = toler2 = 0.;
617 //    return Standard_False;
618   }
619   else {
620     toler1 = pnt1.SquareDistance (c3d->Value (a));
621     toler2 = pnt2.SquareDistance (c3d->Value (b));
622   }
623
624   if ( checkAll ) {
625     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&edge.TShape());
626     for (BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves()); itcr.More(); itcr.Next() ) {
627       Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
628       if (GC.IsNull() || !GC->IsCurveOnSurface()) continue;
629       Handle(Geom2d_Curve) pcurve;
630       Handle(Geom_Surface) S = GC->Surface();
631       TopLoc_Location L = edge.Location() * GC->Location();
632       sae.PCurve (edge, S, L, pcurve, a, b, Standard_True);
633       gp_Pnt2d p1 = pcurve->Value (a);
634       gp_Pnt2d p2 = pcurve->Value (b);
635       gp_Pnt P1 = S->Value (p1.X(), p1.Y()).Transformed (L.Transformation());
636       gp_Pnt P2 = S->Value (p2.X(), p2.Y()).Transformed (L.Transformation());
637       toler1 = Max (toler1, pnt1.SquareDistance (P1));
638       toler2 = Max (toler2, pnt2.SquareDistance (P2));
639     }
640   }
641   //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp)
642   // Check with given face is needed for plane surfaces (if no stored pcurves)
643   else if ( ! face.IsNull() ) {
644     Handle(Geom2d_Curve) pcurve;
645     TopLoc_Location L;
646     const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
647     if ( sae.PCurve(edge, S, L, pcurve, a, b, Standard_True)) {
648       gp_Pnt2d p1 = pcurve->Value (a);
649       gp_Pnt2d p2 = pcurve->Value (b);
650       gp_Pnt P1 = S->Value (p1.X(), p1.Y()).Transformed (L.Transformation());
651       gp_Pnt P2 = S->Value (p2.X(), p2.Y()).Transformed (L.Transformation());
652       toler1 = Max (toler1, pnt1.SquareDistance (P1));
653       toler2 = Max (toler2, pnt2.SquareDistance (P2));
654     }
655     else Status |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
656   }
657
658   //:o8 abv 19 Feb 99: CTS18541.stp #18559: coeff 1.0001 added
659   //szv 18 Aug 99: edge tolerance is taken in consideration
660   Standard_Real tole = BRep_Tool::Tolerance (edge);
661   toler1 = Max (1.0000001 * Sqrt (toler1), tole);
662   toler2 = Max (1.0000001 * Sqrt (toler2), tole);
663   if ( toler1 > old1) 
664     Status |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
665   if ( toler2 > old2) 
666     Status |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
667
668   return Status;
669 }
670
671
672 //=======================================================================
673 //function : CheckVertexTolerance
674 //purpose  : 
675 //=======================================================================
676
677 Standard_Boolean ShapeAnalysis_Edge::CheckVertexTolerance(const TopoDS_Edge& edge,
678                                                           const TopoDS_Face& face,
679                                                           Standard_Real& toler1,
680                                                           Standard_Real& toler2)
681 {
682   myStatus = ::CheckVertexTolerance ( edge, face, Standard_False, toler1, toler2 );
683   return Status ( ShapeExtend_DONE );
684 }
685
686
687 //=======================================================================
688 //function : CheckVertexTolerance
689 //purpose  : 
690 //=======================================================================
691
692 Standard_Boolean ShapeAnalysis_Edge::CheckVertexTolerance(const TopoDS_Edge& edge,
693                                                           Standard_Real& toler1,
694                                                           Standard_Real& toler2)
695 {
696   TopoDS_Face F;
697   myStatus = ::CheckVertexTolerance ( edge, F, Standard_True, toler1, toler2 );
698   return Status ( ShapeExtend_DONE );
699 }
700
701
702 //=======================================================================
703 //static : Validate
704 //purpose: For SameParameter: compute it for two curves
705 //note: This function is made from Validate() in BRepCheck_Edge.cxx
706 //=======================================================================
707
708 Standard_Boolean ShapeAnalysis_Edge::ComputeDeviation (const Adaptor3d_Curve& CRef,
709                                                        const Adaptor3d_Curve& Other,
710                                                        const Standard_Boolean SameParameter,
711                                                        Standard_Real &dev,
712                                                        const Standard_Integer NCONTROL)
713 {
714   Standard_Boolean OK = Standard_True;
715   Standard_Real dev2 = dev*dev;
716   
717   Standard_Real First = CRef.FirstParameter(), Last = CRef.LastParameter();
718   Standard_Real OFirst = Other.FirstParameter(), OLast  = Other.LastParameter(); //szv#4:S4163:12Mar99 moved
719
720   Standard_Boolean proj = (!SameParameter || First != OFirst || Last != OLast); //szv#4:S4163:12Mar99 optimized
721
722   Standard_Integer NCtrl = ( NCONTROL < 1 )? 1 : NCONTROL; //szv#4:S4163:12Mar99 anti-exception
723
724   if (!proj) {
725     for (Standard_Integer i = 0; i <= NCtrl; i++) {
726       Standard_Real prm = ((NCtrl-i)*First + i*Last)/NCtrl;
727       gp_Pnt pref = CRef.Value(prm);
728       gp_Pnt pother = Other.Value(prm);
729       Standard_Real dist2 = pref.SquareDistance(pother);
730       if ( dev2 < dist2 ) dev2 = dist2; 
731     }
732     dev = Sqrt ( dev2 );
733   }
734   else {
735     gp_Pnt pd = CRef.Value(First);
736     gp_Pnt pdo = Other.Value(OFirst);
737     Standard_Real dist2 = pd.SquareDistance(pdo);
738     if ( dev2 < dist2 ) dev = Sqrt ( dev2 = dist2 );
739
740     pd = CRef.Value(Last);
741     pdo = Other.Value(OLast);
742     dist2 = pd.SquareDistance(pdo);
743     if ( dev2 < dist2 ) dev = Sqrt ( dev2 = dist2 );
744
745     Extrema_LocateExtPC refd, otherd; //szv#4:S4163:12Mar99 warning
746     refd.Initialize(CRef,First,Last,Precision::PConfusion());
747     otherd.Initialize(Other,OFirst,OLast,Precision::PConfusion());
748
749     for (Standard_Integer i = 1; i < NCtrl; i++) { //szv#4:S4163:12Mar99 was bug
750       Standard_Real rprm = ((NCtrl-i)*First + i*Last)/NCtrl;
751       gp_Pnt pref = CRef.Value(rprm);
752       Standard_Real oprm = ((NCtrl-i)*OFirst + i*OLast)/NCtrl;
753       gp_Pnt pother = Other.Value(oprm);
754
755       refd.Perform(pother,rprm);
756       if ( ! refd.IsDone() ) OK = Standard_False;
757       else if ( dev2 < refd.SquareDistance() ) {dev2 = refd.SquareDistance(); dev = sqrt (dev2);}
758
759       otherd.Perform(pref,oprm);
760       if ( ! otherd.IsDone() ) OK = Standard_False;
761       else if ( dev2 < otherd.SquareDistance() ) {dev2 = otherd.SquareDistance(); dev = sqrt (dev2);}
762     }
763   }
764   dev *= 1.00001;//ims007 entity 8067 edge 3; 1e-07USA60022 (4255, 4-th edge) SA_Check and BRepCh find distinct points001; // ensure that dev*dev >= dev2
765   
766   return OK;
767 }
768
769
770 //=======================================================================
771 //function : CheckSameParameter
772 //purpose  : 
773 //=======================================================================
774
775 Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge,
776                                                             Standard_Real& maxdev,
777                                                             const Standard_Integer NbControl)
778 {
779   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
780   if (BRep_Tool::Degenerated (edge)) return Standard_False;
781
782   maxdev = 0;
783   
784   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&edge.TShape());
785   Standard_Boolean SameParameter = TE->SameParameter();
786
787   GeomAdaptor_Curve AC3d;
788
789   // find 3d curve
790   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
791   for ( ; itcr.More(); itcr.Next() ) {
792     Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
793     if ( GC.IsNull() || ! GC->IsCurve3D() ) continue;
794     Handle(Geom_Curve) C3d = GC->Curve3D();
795     if ( C3d.IsNull() ) continue; //:s1 abv 22 Apr 99: PRO7226 #489490
796     TopLoc_Location loc = GC->Location();
797     if ( ! loc.IsIdentity() )
798       C3d = Handle(Geom_Curve)::DownCast ( C3d->Transformed ( loc ) );
799     else C3d = Handle(Geom_Curve)::DownCast ( C3d->Copy() ); //:s4 abv 26 Apr 99: sim6049.igs 21677: necessary to get True SP (!!?)
800     Standard_Real First, Last;
801     GC->Range ( First, Last );
802     AC3d.Load ( C3d, First, Last );
803     break;
804   }
805
806   if ( ! itcr.More() ) {
807     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
808     return Standard_False;
809   }
810
811   // iterate on pcurves
812   itcr.Initialize ( TE->Curves() );
813   for ( ; itcr.More(); itcr.Next() ) {
814     Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
815     if ( GC.IsNull() || ! GC->IsCurveOnSurface() ) continue;
816
817     Standard_Real f, l;
818     GC->Range ( f, l );
819     Handle(Geom_Surface) Su = GC->Surface();
820     TopLoc_Location loc = GC->Location();
821     if (!loc.IsIdentity())
822       Su = Handle(Geom_Surface)::DownCast ( Su->Transformed ( loc ) );
823     Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(Su);
824     
825     Handle(Geom2d_Curve) PC = GC->PCurve();
826     Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(PC,f,l);
827     //Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
828     Adaptor3d_CurveOnSurface ACS;
829     ACS.Load(GHPC);
830     ACS.Load(GAHS);
831     if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) ) {
832       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
833     }
834
835     if ( GC->IsCurveOnClosedSurface() ) {
836       GHPC->ChangeCurve2d().Load ( GC->PCurve2(), f, l ); // same bounds
837       ACS.Load(GAHS); // sans doute inutile
838       ACS.Load(GHPC); // meme remarque...
839       if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) ) {
840         myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
841       }
842     }
843   }
844   
845   if ( maxdev > TE->Tolerance() ) 
846     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
847   if ( ! SameParameter ) 
848     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
849
850   return Status ( ShapeExtend_DONE );
851 }
852
853
854 //=======================================================================
855 //function : IsOverlapPartEdges
856 //purpose  : 
857 //=======================================================================
858
859 static Standard_Boolean IsOverlapPartEdges(const TopoDS_Edge& theFirstEdge,
860                                            const TopoDS_Edge& theSecEdge,
861                                            const Standard_Real& theTolerance,
862                                            const Standard_Real& theStep,
863                                            const Standard_Real& theStartLength,
864                                            const Standard_Real& theEndLenght)
865 {
866   TColStd_SequenceOfInteger aSeqIntervals;
867   BRepAdaptor_Curve aAdCurve1(theFirstEdge);
868
869   BRepExtrema_DistShapeShape aMinDist;
870   aMinDist.LoadS1(theSecEdge);
871
872   for(Standard_Real aS = theStartLength; aS <= theEndLenght; aS+=theStep/2) {
873     
874     gp_Pnt aPoint;
875     if(aS <= Precision::Confusion()) {
876       TopoDS_Vertex V1 =  TopExp::FirstVertex(theFirstEdge,Standard_True);
877       aPoint = BRep_Tool::Pnt(V1);
878     }
879     else {
880       GCPnts_AbscissaPoint aAbsPoint(Precision::Confusion(),aAdCurve1,aS,aAdCurve1.FirstParameter());
881       if(aAbsPoint.IsDone()) 
882         aAdCurve1.D0(aAbsPoint.Parameter(),aPoint);
883       else continue;
884     }
885     BRep_Builder aB;
886     TopoDS_Vertex aV;
887     aB.MakeVertex(aV,aPoint,Precision::Confusion());
888     aMinDist.LoadS2(aV);
889     aMinDist.Perform();
890     if( aMinDist.IsDone() && aMinDist.Value() >= theTolerance)
891       return Standard_False;
892   }
893   return Standard_True;
894 }
895
896
897 //=======================================================================
898 //function : CheckOverlapping
899 //purpose  : 
900 //=======================================================================
901
902 Standard_Boolean ShapeAnalysis_Edge::CheckOverlapping(const TopoDS_Edge& theEdge1,
903                                                       const TopoDS_Edge& theEdge2,
904                                                       Standard_Real& theTolOverlap,
905                                                       const Standard_Real theDomainDist) 
906 {
907   Standard_Boolean isOverlap = Standard_False;
908   BRepAdaptor_Curve aAdCurve1(theEdge1);
909   Standard_Real aLength1 = GCPnts_AbscissaPoint::Length (aAdCurve1);
910   BRepAdaptor_Curve aAdCurve2(theEdge2);
911   Standard_Real aLength2 = GCPnts_AbscissaPoint::Length (aAdCurve2);
912   TopoDS_Edge aFirstEdge = (aLength1 >= aLength2 ? theEdge2: theEdge1);
913   TopoDS_Edge aSecEdge = (aLength1 >= aLength2 ? theEdge1: theEdge2);
914   Standard_Real aLength = Min(aLength1,aLength2);
915   
916   //check overalpping between edges on whole edges
917   Standard_Real aStep = Min(aLength1,aLength2)/2;
918   isOverlap = IsOverlapPartEdges(aFirstEdge,aSecEdge,theTolOverlap,aStep,0.,Min(aLength1,aLength2)); 
919   
920   if(isOverlap)    {
921     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3);
922     return isOverlap;
923   }
924   if(theDomainDist ==0.0)
925     return isOverlap;
926   
927   //check overalpping between edges on segment with length less than theDomainDist
928   
929   Standard_Real aDomainTol = (theDomainDist > Min( aLength1,aLength2) ? Min( aLength1,aLength2) :theDomainDist);
930   BRepExtrema_DistShapeShape aMinDist(aFirstEdge,aSecEdge,theTolOverlap);
931   Standard_Real aresTol = theTolOverlap;
932   if(aMinDist.IsDone()) {
933     aresTol = aMinDist.Value();
934     if(aresTol >= theTolOverlap) return Standard_False;
935     Standard_Integer NbSol = aMinDist.NbSolution();
936     for(Standard_Integer i =1; i<= NbSol && !isOverlap; i++) {
937       BRepExtrema_SupportType aType1 = aMinDist.SupportTypeShape1(i);
938       Standard_Real aEndLength, aStartLength, aLengthP; 
939       if(aType1 == BRepExtrema_IsVertex) {
940         TopoDS_Shape aSupportShape1 = aMinDist.SupportOnShape1(i);
941         TopoDS_Vertex aV1,aV2;
942         TopExp::Vertices (aFirstEdge, aV1, aV2, Standard_True);
943         if( aV1.IsSame(aSupportShape1)) 
944           aLengthP = 0.0;
945         else
946           aLengthP =aLength;
947       }
948       else if(aType1 == BRepExtrema_IsOnEdge) {
949         Standard_Real aParam1, aFirst, aLast;
950         aMinDist.ParOnEdgeS1 ( i, aParam1 );
951         BRep_Tool::Range(aFirstEdge,aFirst,aLast);
952         BRepAdaptor_Curve anAdaptor(aFirstEdge);
953         aLengthP = GCPnts_AbscissaPoint::Length(anAdaptor,aFirst,aParam1);
954       }
955       else continue;
956       aStartLength = aLengthP - aDomainTol/2;
957       if( aStartLength <0.0) {
958         aStartLength =0;
959         aEndLength = aDomainTol;
960       }
961       aEndLength = aLengthP + aDomainTol/2;
962       if(aEndLength > aLength) {
963         aEndLength = aLength;
964         aStartLength = aEndLength - aDomainTol;
965       }
966       aStep = (aEndLength - aStartLength)/5;
967       isOverlap = (IsOverlapPartEdges(aFirstEdge,aSecEdge,theTolOverlap,aStep,aStartLength,aEndLength));
968     }
969   }
970   if(isOverlap)    
971     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4);
972    
973   theTolOverlap = aresTol;
974    return isOverlap;
975 }