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