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