0023024: Update headers of OCCT files
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_Wire.cxx
1 // Created on: 2000-01-20
2 // Created by: data exchange team
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 //:pdn 11.12.98: FixDegenerated improved
22 //:pdn 05.01.99: renaming method CheckLittle to CheckSmall
23 //:l0 abv 10.01.99: CATIA01 #1727: fix intersecting edges always if edge is lacking
24 //:n2 abv 22.01.99: ma-test5.igs: IGES read (pref3d): remove degen edge with no pcurve
25 //:o4 abv 17.02.99: r0301_db.stp #53082: adding parameter isClosed to CheckOrder
26 //    rln 03.03.99  S4135: using updated ShapeAnalysis_Surface for checking of singularities
27 //:p9 abv 11.03.99: PRO7226 #489490: fix :i9 moved to allow fixing a set of degenerated edges
28 //#77 rln 11.03.99: S4135: using singularity which has minimum gap between singular point and input 3D point
29 //#84 rln 18.03.99: inserting degenerated edge between ends of pcurves
30 //pdn 12.03.99 S4135 check degenerated applies minimal tolerance first.
31 //pdn 16.03.99 S4135 adding check of non adjacent edjes.
32 //#83 rln 19.03.99: processing segments in intersection as in BRepCheck
33 //%15 pdn 15.03.99  checking of small area wire added
34 //#2 smh 26.03.99  S4163 Zero divide
35 //#4 szv           S4163 optimizing
36 //:r6 abv 08.04.99: protect FixIE against working out of curve range
37 //:s1 abv 22.04.99: PRO7226 #489490: ensure fixing of degenerated edge
38 //#9 smh 14.12.99 BUC60615 Using tolerance of verteces during checking degenerated edge.
39
40 #include <ShapeAnalysis_Wire.ixx>
41
42 #include <Precision.hxx>
43
44 #include <Geom_Curve.hxx>
45 #include <Geom2d_Curve.hxx>
46 #include <GeomAdaptor_HSurface.hxx>
47 #include <Geom2dAdaptor_Curve.hxx>
48 #include <Geom2dInt_GInter.hxx>
49 #include <IntRes2d_Domain.hxx>
50 #include <IntRes2d_Transition.hxx>
51 #include <IntRes2d_IntersectionPoint.hxx>
52 #include <IntRes2d_IntersectionSegment.hxx>
53
54 #include <TopoDS_Edge.hxx>
55 #include <TopoDS_Vertex.hxx>
56 #include <BRep_Builder.hxx>
57 #include <BRep_Tool.hxx>
58 #include <BRepTools.hxx>
59
60 #include <ShapeExtend.hxx>
61 #include <ShapeAnalysis.hxx>
62 #include <ShapeAnalysis_Curve.hxx>
63 #include <ShapeAnalysis_Edge.hxx>
64
65 #include <TopoDS.hxx>
66 #include <Precision.hxx>
67 #include <TColgp_Array1OfPnt.hxx>
68 #include <TColStd_Array1OfReal.hxx>
69 #include <Bnd_Array1OfBox2d.hxx>
70 #include <BndLib_Add2dCurve.hxx>
71 #include <Bnd_Box2d.hxx>
72
73 //szvsh addition
74 #include <Geom2dAdaptor_HCurve.hxx>
75 #include <Adaptor3d_CurveOnSurface.hxx>
76 #include <TColgp_SequenceOfPnt.hxx>
77 #include <ShapeAnalysis_Surface.hxx>
78 #include <TopoDS_Wire.hxx>
79 #include <ShapeAnalysis.hxx>
80 #include <Geom_Plane.hxx>
81 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
82 #include <TopoDS_Iterator.hxx>
83 #include <TopTools_DataMapOfShapeListOfShape.hxx>
84 #include <TopTools_ListOfShape.hxx>
85 #include <TopTools_IndexedMapOfShape.hxx>
86 #include <TopTools_ListIteratorOfListOfShape.hxx>
87 #include <TopExp.hxx>
88
89 //=======================================================================
90 //function : ShapeAnalysis_Wire
91 //purpose  : 
92 //=======================================================================
93
94 ShapeAnalysis_Wire::ShapeAnalysis_Wire()
95 {
96   ClearStatuses();
97   myPrecision = ::Precision::Confusion();
98 }
99
100 //=======================================================================
101 //function : ShapeAnalysis_Wire
102 //purpose  : 
103 //=======================================================================
104
105 ShapeAnalysis_Wire::ShapeAnalysis_Wire (const TopoDS_Wire& wire,
106                                         const TopoDS_Face& face,
107                                         const Standard_Real precision)
108 {
109   Init (wire, face, precision);
110 }
111
112 //=======================================================================
113 //function : ShapeAnalysis_Wire
114 //purpose  : 
115 //=======================================================================
116
117 ShapeAnalysis_Wire::ShapeAnalysis_Wire (const Handle(ShapeExtend_WireData)& sbwd,
118                                         const TopoDS_Face& face,
119                                         const Standard_Real precision)
120 {
121   Init (sbwd, face, precision);
122 }
123
124 //=======================================================================
125 //function : Init
126 //purpose  : 
127 //=======================================================================
128
129 void ShapeAnalysis_Wire::Init (const TopoDS_Wire& wire,
130                                const TopoDS_Face& face, const Standard_Real precision) 
131 {
132   Init (new ShapeExtend_WireData (wire), face, precision);
133 }
134
135 //=======================================================================
136 //function : Init
137 //purpose  : 
138 //=======================================================================
139
140 void ShapeAnalysis_Wire::Init (const Handle(ShapeExtend_WireData)& sbwd,
141                                const TopoDS_Face& face, const Standard_Real precision) 
142 {
143   Load (sbwd);
144   SetFace (face);
145   SetPrecision (precision);
146 }
147
148 //=======================================================================
149 //function : Load
150 //purpose  : 
151 //=======================================================================
152
153 void ShapeAnalysis_Wire::Load (const TopoDS_Wire& wire) 
154 {
155   ClearStatuses();
156   myWire = new ShapeExtend_WireData (wire);
157 }
158
159 //=======================================================================
160 //function : Load
161 //purpose  : 
162 //=======================================================================
163
164 void ShapeAnalysis_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd) 
165 {
166   ClearStatuses();
167   myWire = sbwd;
168 }
169
170 //=======================================================================
171 //function : SetFace
172 //purpose  : 
173 //=======================================================================
174
175 void ShapeAnalysis_Wire::SetFace(const TopoDS_Face& face) 
176 {
177   myFace = face;
178   if(!face.IsNull())
179     mySurf = new ShapeAnalysis_Surface ( BRep_Tool::Surface ( myFace ) );
180 }
181
182 //=======================================================================
183 //function : SetSurface
184 //purpose  : 
185 //=======================================================================
186
187 void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface) 
188 {
189   SetSurface ( surface, TopLoc_Location() );
190 }
191
192 //=======================================================================
193 //function : SetSurface
194 //purpose  : 
195 //=======================================================================
196
197 void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface,
198                                      const TopLoc_Location& location) 
199 {
200   BRep_Builder B;
201   TopoDS_Face face;
202   B.MakeFace ( face, surface, location, ::Precision::Confusion() );
203   SetFace ( face );
204 }
205
206 //=======================================================================
207 //function : SetPrecision
208 //purpose  : 
209 //=======================================================================
210
211  void ShapeAnalysis_Wire::SetPrecision(const Standard_Real precision) 
212 {
213   myPrecision = precision;
214 }
215
216 //=======================================================================
217 //function : ClearStatuses
218 //purpose  : 
219 //=======================================================================
220
221  void ShapeAnalysis_Wire::ClearStatuses()
222 {
223   myStatusOrder = myStatusConnected =
224     myStatusEdgeCurves = myStatusDegenerated =
225       myStatusClosed = myStatusLacking =
226         myStatusSelfIntersection = myStatusSmall =
227           myStatusGaps3d = myStatusGaps2d =
228             myStatusCurveGaps = myStatusLoop = myStatus = 0;
229
230   myMin3d = myMin2d = myMax3d = myMax2d = 0.;
231 }
232
233 //=======================================================================
234 //function : Perform
235 //purpose  : 
236 //=======================================================================
237
238  Standard_Boolean ShapeAnalysis_Wire::Perform() 
239 {
240   Standard_Boolean result = Standard_False;
241   result |= CheckOrder();
242   result |= CheckSmall();
243   result |= CheckConnected();
244   result |= CheckEdgeCurves();
245   result |= CheckDegenerated();
246   result |= CheckSelfIntersection();
247   result |= CheckLacking();
248   result |= CheckClosed();
249   return result;
250 }
251
252 //=======================================================================
253 //function : CheckOrder
254 //purpose  : 
255 //=======================================================================
256
257  Standard_Boolean ShapeAnalysis_Wire::CheckOrder (const Standard_Boolean isClosed,
258                                                   const Standard_Boolean mode3d) 
259 {
260   ShapeAnalysis_WireOrder sawo;
261   CheckOrder (sawo, isClosed, mode3d);
262   myStatusOrder = myStatus;
263   return StatusOrder (ShapeExtend_DONE);
264 }
265
266 //=======================================================================
267 //function : CheckSmall
268 //purpose  : 
269 //=======================================================================
270
271  Standard_Boolean ShapeAnalysis_Wire::CheckSmall(const Standard_Real precsmall) 
272 {
273   for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) {
274     CheckSmall (i, precsmall);
275     myStatusSmall |= myStatus;
276   }
277   return StatusSmall (ShapeExtend_DONE);
278 }
279
280 //=======================================================================
281 //function : CheckConnected
282 //purpose  : 
283 //=======================================================================
284
285  Standard_Boolean ShapeAnalysis_Wire::CheckConnected(const Standard_Real prec) 
286 {
287   for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) {
288     CheckConnected ( i, prec );
289     myStatusConnected |= myStatus;
290   }
291   return StatusConnected (ShapeExtend_DONE);
292 }
293
294 //=======================================================================
295 //function : CheckEdgeCurves
296 //purpose  : 
297 //=======================================================================
298
299  Standard_Boolean ShapeAnalysis_Wire::CheckEdgeCurves() 
300 {
301   myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
302   if ( ! IsReady() ) return Standard_False;
303   
304   Standard_Integer i, nb = myWire->NbEdges();
305   ShapeAnalysis_Edge SAE;
306   
307   for (i = 1; i <= nb; i++) {
308     TopoDS_Edge E = myWire->Edge (i);
309
310     SAE.CheckCurve3dWithPCurve (E, myFace);
311     if (SAE.Status (ShapeExtend_DONE))
312       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
313     if (SAE.Status ( ShapeExtend_FAIL)) 
314       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
315
316     SAE.CheckVerticesWithPCurve (E, myFace);
317     if (SAE.Status (ShapeExtend_DONE))
318       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
319     if (SAE.Status ( ShapeExtend_FAIL)) 
320       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
321
322     SAE.CheckVerticesWithCurve3d (E);
323     if (SAE.Status (ShapeExtend_DONE))
324       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
325     if (SAE.Status ( ShapeExtend_FAIL)) 
326       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
327
328     CheckSeam (i);
329     if (LastCheckStatus (ShapeExtend_DONE)) 
330       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE4);
331     if (LastCheckStatus (ShapeExtend_FAIL)) 
332       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL4);
333
334     CheckGap3d (i);
335     if (LastCheckStatus (ShapeExtend_DONE)) 
336       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE5);
337     if (LastCheckStatus (ShapeExtend_FAIL)) 
338       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL5);
339
340     CheckGap2d (i);
341     if (LastCheckStatus (ShapeExtend_DONE)) 
342       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE6);
343     if (LastCheckStatus (ShapeExtend_FAIL)) 
344       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL6);
345
346     Standard_Real maxdev = 0.0;
347     SAE.CheckSameParameter (myWire->Edge (i), maxdev);
348     if (SAE.Status (ShapeExtend_DONE))
349       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE7);
350     if (SAE.Status ( ShapeExtend_FAIL)) 
351       myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL7);
352   }
353   return StatusEdgeCurves (ShapeExtend_DONE);
354 }
355
356 //=======================================================================
357 //function : CheckDegenerated
358 //purpose  : 
359 //=======================================================================
360
361  Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated() 
362 {
363   for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) {
364     CheckDegenerated (i);
365     myStatusDegenerated |= myStatus;
366   }
367   return StatusDegenerated (ShapeExtend_DONE);
368 }
369
370 //=======================================================================
371 //function : CheckSelfIntersection
372 //purpose  : 
373 //=======================================================================
374
375  Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersection() 
376 {
377   myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
378   if (!IsReady()) return Standard_False;
379   Standard_Integer i, nb = myWire->NbEdges();
380   for (i = 1; i <= nb; i++) {
381     CheckSelfIntersectingEdge (i);
382     if (LastCheckStatus (ShapeExtend_DONE))
383       myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
384     if (LastCheckStatus (ShapeExtend_FAIL)) 
385       myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
386
387     CheckIntersectingEdges (i);
388     if (LastCheckStatus (ShapeExtend_DONE))
389       myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
390     if (LastCheckStatus (ShapeExtend_FAIL)) 
391       myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
392   }
393   
394   Bnd_Array1OfBox2d boxes(1,nb);
395   TopLoc_Location L;
396   const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L);
397   Handle(Geom2d_Curve) c2d;
398   Standard_Real cf,cl;
399   ShapeAnalysis_Edge sae;
400   Handle(ShapeExtend_WireData) sbwd = WireData();
401   for(i = 1; i <= nb; i++){
402     TopoDS_Edge E = sbwd->Edge (i);
403     if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) {
404       Bnd_Box2d box;
405       Geom2dAdaptor_Curve gac(c2d,cf,cl);
406       BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
407       boxes(i) = box;
408     }
409   }
410   
411   Standard_Boolean isFail = Standard_False, isDone = Standard_False;
412   for(Standard_Integer num1 = 1; num1 < nb-1; num1++) {
413     Standard_Integer fin = nb;
414     if (CheckClosed(Precision::Confusion()) && 1 == num1)
415       fin = nb-1;
416     for(Standard_Integer num2 = num1+2; num2 <= fin; num2++) 
417       if(!boxes(num1).IsOut(boxes(num2))){
418         CheckIntersectingEdges(num1, num2);
419         isFail |= LastCheckStatus ( ShapeExtend_FAIL1 );
420         isDone |= LastCheckStatus ( ShapeExtend_DONE1 );
421       }
422   }
423   if(isFail)
424     myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
425   if(isDone)
426     myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
427   
428   return StatusSelfIntersection (ShapeExtend_DONE);
429 }
430
431 //=======================================================================
432 //function : CheckLacking
433 //purpose  : 
434 //=======================================================================
435
436  Standard_Boolean ShapeAnalysis_Wire::CheckLacking() 
437 {
438   if (!IsReady() || NbEdges() < 2) return Standard_False; 
439   for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) {
440     CheckLacking (i);
441     myStatusLacking |= myStatus;
442   }
443   return StatusLacking (ShapeExtend_DONE);
444 }
445
446 //=======================================================================
447 //function : CheckClosed
448 //purpose  : 
449 //=======================================================================
450
451  Standard_Boolean ShapeAnalysis_Wire::CheckClosed(const Standard_Real prec) 
452 {
453   myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
454   if (!IsReady() || NbEdges() < 1) return Standard_False;
455   
456   CheckConnected (1, prec);
457   if ( LastCheckStatus ( ShapeExtend_DONE ) ) 
458     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
459   if ( LastCheckStatus ( ShapeExtend_FAIL ) ) 
460     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
461
462   CheckDegenerated ( 1 );
463   if ( LastCheckStatus ( ShapeExtend_DONE ) ) 
464     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
465   if ( LastCheckStatus ( ShapeExtend_FAIL ) ) 
466     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
467
468   return StatusClosed ( ShapeExtend_DONE );
469 }
470
471 //=======================================================================
472 //function : CheckGaps3d
473 //purpose  : 
474 //=======================================================================
475
476  Standard_Boolean ShapeAnalysis_Wire::CheckGaps3d ()
477 {
478   myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
479   if (!IsLoaded() || NbEdges() < 1) return Standard_False; //gka IsLoaded
480   
481   Standard_Real dist, maxdist = 0.;
482   
483   for (Standard_Integer i = 1; i <= NbEdges(); i++) {
484     CheckGap3d(i);
485     myStatusGaps3d |= myStatus;
486     if (!LastCheckStatus(ShapeExtend_FAIL1)) {
487       dist = MinDistance3d();
488       if (maxdist<dist) maxdist = dist;
489     }
490   }
491   myMin3d = myMax3d = maxdist;
492
493   return StatusGaps3d ( ShapeExtend_DONE );
494 }
495
496 //=======================================================================
497 //function : CheckGaps2d
498 //purpose  : 
499 //=======================================================================
500
501  Standard_Boolean ShapeAnalysis_Wire::CheckGaps2d ()
502 {
503   myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
504   if (!IsReady() || NbEdges() < 1) return Standard_False;
505   
506   Standard_Real dist, maxdist = 0.;
507
508   for (Standard_Integer i = 1; i <= NbEdges(); i++) {
509     CheckGap2d(i);
510     myStatusGaps2d |= myStatus;
511     if (!LastCheckStatus(ShapeExtend_FAIL1)) {
512       dist = MinDistance2d();
513       if (maxdist<dist) maxdist = dist;
514     }
515   }
516   myMin2d = myMax2d = maxdist;
517
518   return StatusGaps2d ( ShapeExtend_DONE );
519 }
520
521 //=======================================================================
522 //function : CheckCurveGaps
523 //purpose  : 
524 //=======================================================================
525
526  Standard_Boolean ShapeAnalysis_Wire::CheckCurveGaps ()
527 {
528   myStatusCurveGaps = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
529   if (!IsReady() || NbEdges() < 1) return Standard_False;
530   
531   Standard_Real dist, maxdist = 0.;
532
533   for (Standard_Integer i = 1; i <= NbEdges(); i++) {
534     CheckCurveGap(i);
535     myStatusCurveGaps |= myStatus;
536     if (!LastCheckStatus(ShapeExtend_FAIL1)) {
537       dist = MinDistance3d();
538       if (maxdist<dist) maxdist = dist;
539     }
540   }
541   myMin3d = myMax3d = maxdist;
542
543   return StatusCurveGaps ( ShapeExtend_DONE );
544 }
545
546 //=======================================================================
547 //function : CheckOrder
548 //purpose  : 
549 //=======================================================================
550
551 Standard_Boolean ShapeAnalysis_Wire::CheckOrder(ShapeAnalysis_WireOrder& sawo,
552                                                 const Standard_Boolean isClosed,
553                                                 const Standard_Boolean mode3d) 
554 {
555   if ( ! mode3d && myFace.IsNull() ) {
556     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); 
557     return Standard_False;
558   }
559   
560   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
561   sawo.SetMode ( mode3d, ( mode3d ? myPrecision : ::Precision::PConfusion() ) );
562   Standard_Integer i, nb = myWire->NbEdges();
563   ShapeAnalysis_Edge EA;
564   for (i = 1; i <= nb; i ++) {
565     TopoDS_Edge E = myWire->Edge(i);
566     if ( mode3d ) {
567       TopoDS_Vertex V1 = EA.FirstVertex (E); 
568       TopoDS_Vertex V2 = EA.LastVertex  (E); 
569       if (V1.IsNull() || V2.IsNull())
570       {
571         myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
572         return Standard_False;
573       }
574       gp_Pnt p1 = BRep_Tool::Pnt (V1);
575       gp_Pnt p2 = BRep_Tool::Pnt (V2);
576       sawo.Add (p1.XYZ(),p2.XYZ());
577     }
578     else {
579       Standard_Real f,l;
580       Handle(Geom2d_Curve) c2d;
581       TopoDS_Shape tmpF = myFace.Oriented(TopAbs_FORWARD);
582       if ( ! EA.PCurve(E,TopoDS::Face(tmpF),c2d,f,l) ) {
583         myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
584         return Standard_False;
585       }
586       sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
587     }
588   }
589   sawo.Perform(isClosed);
590   Standard_Integer stat = sawo.Status();
591   switch (stat) {
592   case   0: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);    break;
593   case   1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break;
594   case   2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break;
595   case  -1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); break;
596   case  -2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break;
597   case -10: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); break;
598   }
599   return LastCheckStatus (ShapeExtend_DONE);
600 }
601
602 //=======================================================================
603 //function : CheckConnected
604 //purpose  : 
605 //=======================================================================
606
607 Standard_Boolean ShapeAnalysis_Wire::CheckConnected (const Standard_Integer num,
608                                                      const Standard_Real prec) 
609 {
610   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
611   if ( ! IsLoaded() || NbEdges() < 1 ) return Standard_False;
612
613   Standard_Integer n2 = ( num >0 ? num  : NbEdges() );
614   Standard_Integer n1 = ( n2  >1 ? n2-1 : NbEdges() );
615 //  if (n1 == n2) return 0;
616
617   TopoDS_Edge E1 = WireData()->Edge ( n1 );
618   TopoDS_Edge E2 = WireData()->Edge ( n2 );
619   
620   ShapeAnalysis_Edge sae;
621   TopoDS_Vertex V1 = sae.LastVertex (E1);
622   TopoDS_Vertex V2 = sae.FirstVertex (E2);
623   if (V1.IsNull() || V2.IsNull())
624   {
625     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
626     return Standard_False;
627   }
628   if (V1.IsSame(V2)) return Standard_False;
629
630   gp_Pnt p1 = BRep_Tool::Pnt (V1);
631   gp_Pnt p2 = BRep_Tool::Pnt (V2);
632   myMin3d = p1.Distance(p2);
633   if ( myMin3d <= gp::Resolution() ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
634   else if ( myMin3d <= myPrecision ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
635   else if ( myMin3d <= prec )        myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
636   else {
637     // et en inversant la derniere edge ?
638     if ( n1 == n2 ) myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
639     else {
640       V2 = sae.LastVertex (E2);
641       p2 = BRep_Tool::Pnt (V2);
642       Standard_Real dist = p1.Distance(p2);
643       if ( dist > myPrecision ) myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
644       else {
645         myMin3d = dist;
646         myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
647       }
648     }
649     return Standard_False;
650   }
651   return Standard_True;
652 }
653
654 //=======================================================================
655 //function : CheckSmall
656 //purpose  : 
657 //=======================================================================
658
659 Standard_Boolean ShapeAnalysis_Wire::CheckSmall (const Standard_Integer num,
660                                                  const Standard_Real precsmall) 
661 {
662   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
663   if ( ! IsLoaded() || NbEdges() <= 1 ) return Standard_False;
664
665   //Standard_Integer n = ( num ? num : NbEdges() ); //szv#4:S4163:12Mar99 not needed
666   TopoDS_Edge E = myWire->Edge ( num ? num : NbEdges() );
667   ShapeAnalysis_Edge sae;
668
669   if ( BRep_Tool::Degenerated ( E ) ) {
670     //:n2 abv 22 Jan 99: ma-test5.igs -> IGES (brep) -> read (pref3d):
671     // degen edge with no pcurve should be removed
672     if ( ! myFace.IsNull() && sae.HasPCurve ( E, Face() ) ) return Standard_False;
673     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
674   }
675   
676   TopoDS_Vertex V1 = sae.FirstVertex (E);
677   TopoDS_Vertex V2 = sae.LastVertex (E);
678   gp_Pnt p1 = BRep_Tool::Pnt (V1);
679   gp_Pnt p2 = BRep_Tool::Pnt (V2);
680   Standard_Real dist = p1.Distance(p2);
681   Standard_Real prec = precsmall;//Min ( myPrecision, precsmall );
682   //Standard_Real prec = Min(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2)); //skl
683   if (dist > prec) return Standard_False;  // pas nulle
684   
685   // La courbe 3D a present : est-elle FERMEE ou DE LONGUEUR NULLE ... ???
686   // Pour cela on prend le point milieu (y a-t-il mieux)
687   // Si pas de C3D, on essaie la C2D ...
688
689   gp_Pnt Pm;
690   Standard_Real cf,cl;
691   Handle(Geom_Curve) c3d;    
692   if ( sae.Curve3d (E,c3d,cf,cl,Standard_False) ) Pm = c3d->Value ( (cf+cl)/2. );
693   else {
694     Handle(Geom2d_Curve) c2d;
695     if ( ! myFace.IsNull() && sae.PCurve (E,myFace,c2d,cf,cl,Standard_False)) {
696       gp_Pnt2d p2m = c2d->Value ( (cf+cl)/2. );
697       Pm = mySurf->Value (p2m);
698     }
699     else {
700       myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
701       Pm = p1;
702 //:n2      return Standard_False;
703     }
704   }
705   if ( Pm.Distance(p1) > prec || Pm.Distance(p2) > prec ) return Standard_False;
706
707   myStatus |= ShapeExtend::EncodeStatus ( V1.IsSame(V2) ? ShapeExtend_DONE1 : ShapeExtend_DONE2 );
708   return Standard_True;
709 }
710
711 //=======================================================================
712 //function : CheckSeam
713 //purpose  : 
714 //=======================================================================
715
716  Standard_Boolean ShapeAnalysis_Wire::CheckSeam(const Standard_Integer num,
717                                                 Handle(Geom2d_Curve)& C1,
718                                                 Handle(Geom2d_Curve)& C2,
719                                                 Standard_Real& cf,
720                                                 Standard_Real& cl) 
721 {
722   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
723   if (!IsReady()) return Standard_False;
724   Standard_Integer n = num;    if (n == 0) n = NbEdges();
725   TopoDS_Edge E = myWire->Edge (n);
726   if ( ! ShapeAnalysis_Edge().IsSeam ( E, myFace ) ) return Standard_False;
727   // Extract the Two PCurves of the Seam 
728   TopoDS_Face ForwardFace = myFace; ForwardFace.Orientation (TopAbs_FORWARD);
729   //szv#4:S4163:12Mar99 SGI warns
730   TopoDS_Shape EF = E.Oriented(TopAbs_FORWARD);
731   TopoDS_Shape ER = E.Oriented(TopAbs_REVERSED);
732   C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(EF), ForwardFace, cf, cl);
733   C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(ER), ForwardFace, cf, cl);
734   if (C1.IsNull() || C2.IsNull()) return Standard_False;
735
736 //  SelectForward est destine a devenir un outil distinct
737
738   Standard_Integer theCurveIndice = ShapeAnalysis_Curve().SelectForwardSeam (C1,C2);
739   if ( theCurveIndice != 2 ) return Standard_False;
740
741   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
742   return Standard_True;
743 }
744
745 //=======================================================================
746 //function : CheckSeam
747 //purpose  : 
748 //=======================================================================
749
750   Standard_Boolean ShapeAnalysis_Wire::CheckSeam(const Standard_Integer num) 
751 {
752   Handle(Geom2d_Curve) C1, C2;
753   Standard_Real cf, cl;
754   return CheckSeam (num, C1, C2, cf, cl);
755 }
756
757 //=======================================================================
758 //function : CheckDegenerated
759 //purpose  : 
760 //=======================================================================
761
762 Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num,
763                                                        gp_Pnt2d& p2d1, gp_Pnt2d& p2d2) 
764 {
765   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
766   if ( ! IsReady() || NbEdges() < 1 ) return Standard_False;
767
768   Standard_Integer n2 = (num > 0)? num : NbEdges();
769   Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges();
770   Standard_Integer n3 = (n2 < NbEdges())? n2+1 : 1;
771   TopoDS_Edge E1 = myWire->Edge ( n1 );
772   TopoDS_Edge E2 = myWire->Edge ( n2 );
773   TopoDS_Edge E3 = myWire->Edge ( n3 );
774   
775   ShapeAnalysis_Edge sae;
776   
777   // skip if edge is already marked as degenerated and has pcurve
778   if ( BRep_Tool::Degenerated ( E2 ) && sae.HasPCurve ( E2, Face() ) ) {
779     // skl 30.12.2004 for OCC7630 - we have to check pcurve
780     if( sae.HasPCurve(E1,Face()) && sae.HasPCurve(E3,Face()) ) {
781       Handle(Geom2d_Curve) c2d;
782       Standard_Real fp,lp;
783       sae.PCurve ( E2, myFace, c2d, fp, lp, Standard_True );
784       gp_Pnt2d p21 = c2d->Value(fp);
785       gp_Pnt2d p22 = c2d->Value(lp);
786       sae.PCurve ( E1, myFace, c2d, fp, lp, Standard_True );
787       gp_Pnt2d p12 = c2d->Value(lp);
788       sae.PCurve ( E3, myFace, c2d, fp, lp, Standard_True );
789       gp_Pnt2d p31 = c2d->Value(fp);
790       if( fabs(p12.Distance(p31)-p21.Distance(p22)) > 2*Precision::PConfusion() ) {
791         // pcurve is bad => we can remove this edge in ShapeFix
792         // if set needed status
793         myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
794       }
795     }
796     return Standard_False;
797   }
798   
799   //pdn allows to insert two sequences of degenerated edges (on separate bounds of surfaces)
800   if ( n1 != n2 && BRep_Tool::Degenerated ( E1 ) && 
801        ! sae.HasPCurve ( E1, Face() ) ) {
802     //:abv 13.05.02: OCC320 - fail (to remove edge) if two consequtive degenerated edges w/o pcurves
803     if ( BRep_Tool::Degenerated ( E2 ) )
804       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
805     return Standard_False;
806   }
807 //:i8  if ( BRep_Tool::Degenerated ( E1 ) || 
808 //:i8       BRep_Tool::Degenerated ( E2 ) ) return Standard_False;  // deja OK
809   
810   TopoDS_Vertex Vp = sae.FirstVertex (E1); //:i9
811   TopoDS_Vertex V0 = sae.LastVertex  (E1);
812   TopoDS_Vertex V1 = sae.FirstVertex (E2);
813   TopoDS_Vertex V2 = sae.LastVertex  (E2);
814   gp_Pnt pp = BRep_Tool::Pnt (Vp); //:i9
815   gp_Pnt p0 = BRep_Tool::Pnt (V0);
816   gp_Pnt p1 = BRep_Tool::Pnt (V1);
817   gp_Pnt p2 = BRep_Tool::Pnt (V2);
818   Standard_Real par1, par2;
819   Standard_Boolean lack = Standard_False;
820   Standard_Boolean dgnr = Standard_False;
821   //pdn 12.03.99 minimal value processing first
822   Standard_Real precFirst = Min(myPrecision,BRep_Tool::Tolerance(V1));
823   Standard_Real precFin   = Max(myPrecision,BRep_Tool::Tolerance(V1));
824   Standard_Real precVtx   = (myPrecision<BRep_Tool::Tolerance(V1) ? 2*precFin : precFin);
825   //  forward : si Edge <num> FWD/REV. Si LACK, toujours True
826   Standard_Boolean forward = ( E2.Orientation() == TopAbs_FORWARD );
827   //  FIX FEV 1998 : recompute singularity according precision
828
829   if (p1.Distance(p2) <= precFirst) { // edge DGNR
830     dgnr = mySurf->DegeneratedValues ( p1, precVtx, p2d1, p2d2, par1, par2, forward ); //smh#9
831     if ( dgnr ) { // abv 24 Feb 00: trj3_as1-ac-214.stp #6065: avoid making closed edge degenerated
832       Standard_Real a, b;
833       Handle(Geom_Curve) C3d = BRep_Tool::Curve ( E2, a, b );
834       if ( ! C3d.IsNull() ) {
835         gp_Pnt p = C3d->Value ( 0.5 * ( a + b ) );
836         if ( p.SquareDistance ( p1 ) > precVtx * precVtx ) dgnr = Standard_False;
837       }
838     }
839   }
840   if ( ! dgnr ) {
841     //:i9 abv 23 Sep 98: CTS20315-2 #63231: check that previous edge is not degenerated
842     if ( n1 != n2 && p1.Distance(pp) <= precFirst &&
843          mySurf->IsDegenerated ( pp, precFirst ) && 
844          ! BRep_Tool::Degenerated ( E1 ) ) return Standard_False;
845     //rln S4135 ShapeAnalysis_Surface new algorithms for singularities
846     //:45 by abv 16 Dec 97: BUC60035 2659: precision increased to vertex tolerance
847     //Standard_Real prec = Max ( myPrecision, BRep_Tool::Tolerance(V1) );
848     //:51 abv 22 Dec 97: recompute singularities if necessary
849     //rln S4135 if ( prec > myPrecision ) mySurf->ComputeSingularities ( 2 * prec ); //:51 //:74 abv 15 Jan 97: *2
850
851     if ( p0.Distance ( p1 ) <= precFin ) {// ou DGNR manquante ?
852       //rln S4135 singularity with precision = 2 * prec, but distance <= prec
853       //lack = mySurf->DegeneratedValues ( p1, prec, p2d1, p2d2, par1, par2, forward);
854       Standard_Real tmpPreci;
855       gp_Pnt tmpP3d;
856       Standard_Boolean tmpUIsoDeg;
857       //#77 rln S4135: using singularity which has minimum gap between singular point and input 3D point
858       Standard_Integer indMin = -1;
859       Standard_Real gapMin2 = RealLast();
860       for (Standard_Integer i = 1; i <= mySurf->NbSingularities (precVtx); i++) {
861         mySurf->Singularity (i, tmpPreci, tmpP3d, p2d1, p2d2, par1, par2, tmpUIsoDeg);
862         Standard_Real gap2 = p1.SquareDistance (tmpP3d);
863         if (gap2 <= precVtx * precVtx)
864           if (gapMin2 > gap2) {
865             gapMin2 = gap2;
866             indMin = i;
867           }
868       }
869       if (indMin >= 1) {
870         mySurf->Singularity (indMin, tmpPreci, tmpP3d, p2d1, p2d2, par1, par2, tmpUIsoDeg);
871         lack = Standard_True;
872       }
873     }
874
875     //rln S4135 if ( prec > myPrecision ) mySurf->ComputeSingularities ( myPrecision ); //:51
876   }
877
878   //  voila, on a soit dgnr soit lack
879   if ( ! lack && ! dgnr ) {
880     //:abv 29.08.01: if singularity not detected but edge is marked 
881     // as degenerated, report fail
882     if ( BRep_Tool::Degenerated ( E2 ) && ! sae.HasPCurve ( E2, Face() ) )
883       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
884     return Standard_False;
885   }
886   
887   // OK, degenerated case detected; we will find its start and end in 2d
888   
889   if ( lack ) forward = Standard_True;
890
891   //:24 by abv 28 Nov 97: 
892   // make degenerative pcurve parametrized exactly from end of pcurve of the 
893   // previous edge to the start of the next one
894   if ( lack || n1 != n2 ) { //:i8 abv 18 Sep 98: ProSTEP TR9 r0501-ug.stp #182180: single degedge is a wire at apex of a cone
895     Standard_Real a, b;
896     Handle(Geom2d_Curve) c2d;
897     if ( sae.PCurve ( E1, myFace, c2d, a, b, Standard_True ) ) {
898       p2d1 = c2d->Value ( b );
899       //#84 rln gp_Pnt2d p2d = c2d->Value ( b );
900       //#84 rln par1 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY();
901     }
902     else myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
903     //pdn pcurves (fixing regression in f0 in degenerated case) 
904     if ( sae.PCurve ( ( dgnr ? E3 : E2 ), myFace, c2d, a, b, Standard_True ) ) {
905       p2d2 = c2d->Value ( a );
906       //#84 rln gp_Pnt2d p2d = c2d->Value ( a );
907       //#84 rln par2 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY();
908     }
909     else myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
910   }
911 /*  
912   if ( par2 < par1 ) {
913     par1 = -par1;
914     par2 = -par2;
915     theDir2d.Reverse();
916   }
917 */
918   
919   //#84 rln 18.03.99 if pcurve is not degenerate anymore, the fix is postponned
920   //to ShapeFix_Wire::FixLacking
921   if ( ! mySurf->IsDegenerated ( p2d1, p2d2, precVtx, 10. ) ) { //:s1 abv 22 Apr 99: PRO7226 #489490 //smh#9
922     //:abv 24.05.02: OCC320 - fail (to remove edge) if two consequtive degenerated edges w/o pcurves
923     if ( BRep_Tool::Degenerated ( E2 ) )
924       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
925     return Standard_False;
926   }
927
928   //added by rln 18/12/97 CSR# CTS18544 entity 13638
929   //the situation when degenerated edge already exists but flag is not set
930   //(i.e. the parametric space is closed)
931   GeomAdaptor_Surface& Ads = mySurf->Adaptor3d()->ChangeSurface();
932   Standard_Real max = Max ( Ads.UResolution(myPrecision), 
933                             Ads.VResolution(myPrecision) );
934   if ( p2d1.Distance (p2d2) /*Abs (par1 - par2)*/ <= max + gp::Resolution() ) return Standard_False;
935
936   //#84 rln p2d1 = aP2d.XY() + par1 * theDir2d.XY();
937   //#84 rln p2d2 = aP2d.XY() + par2 * theDir2d.XY();
938   myStatus = ShapeExtend::EncodeStatus ( dgnr ? ShapeExtend_DONE2 : ShapeExtend_DONE1 );
939   return Standard_True;
940 }
941
942 //=======================================================================
943 //function : CheckDegenerated
944 //purpose  : 
945 //=======================================================================
946
947 Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num)
948 {
949   gp_Pnt2d p2d1, p2d2;
950   return CheckDegenerated ( num, p2d1, p2d2 );
951 }
952
953 //=======================================================================
954 //function : CheckGap3d
955 //purpose  : 
956 //=======================================================================
957
958  Standard_Boolean ShapeAnalysis_Wire::CheckGap3d(const Standard_Integer num) 
959 {
960   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
961   //szv#4:S4163:12Mar99 optimized
962   if ( !IsLoaded() || NbEdges() < 1 ) return Standard_False; //szvsh was nbedges < 2
963   Standard_Integer n2 = ( num >0 ? num  : NbEdges() );
964   Standard_Integer n1 = ( n2  >1 ? n2-1 : NbEdges() );
965   TopoDS_Edge E1 = myWire->Edge(n1);
966   TopoDS_Edge E2 = myWire->Edge(n2);
967   Standard_Real uf1,ul1,uf2,ul2;
968   Handle(Geom_Curve) C1,C2;
969   ShapeAnalysis_Edge SAE;
970   if (!SAE.Curve3d (E1,C1,uf1,ul1) || !SAE.Curve3d (E2,C2,uf2,ul2)) {
971     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
972     return Standard_False;
973   }
974   gp_Pnt p1 = C1->Value (ul1);
975   gp_Pnt p2 = C2->Value (uf2);
976   myMin3d = myMax3d = p1.Distance (p2);
977   if (myMin3d > myPrecision)
978     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
979   return LastCheckStatus (ShapeExtend_DONE);
980 }
981
982 //=======================================================================
983 //function : CheckGap2d
984 //purpose  : 
985 //=======================================================================
986
987  Standard_Boolean ShapeAnalysis_Wire::CheckGap2d(const Standard_Integer num) 
988 {
989   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
990   //szv#4:S4163:12Mar99 optimized
991   if ( !IsReady() || NbEdges() < 1 ) return Standard_False; //szvsh was nbedges < 2
992   Standard_Integer n2 = ( num >0 ? num  : NbEdges() );
993   Standard_Integer n1 = ( n2  >1 ? n2-1 : NbEdges() );
994   TopoDS_Edge E1 = myWire->Edge(n1);
995   TopoDS_Edge E2 = myWire->Edge(n2);
996   Standard_Real uf1,ul1,uf2,ul2;
997   Handle(Geom2d_Curve) C1,C2;
998   ShapeAnalysis_Edge SAE;
999   if (!SAE.PCurve (E1,myFace,C1,uf1,ul1) || !SAE.PCurve (E2,myFace,C2,uf2,ul2)) {
1000     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1001     return Standard_False;
1002   }
1003   gp_Pnt2d p1 = C1->Value (ul1);
1004   gp_Pnt2d p2 = C2->Value (uf2);
1005   myMin2d = myMax2d = p1.Distance (p2);
1006   GeomAdaptor_Surface& SA = mySurf->Adaptor3d()->ChangeSurface();
1007   if (myMin2d > (Max (SA.UResolution (myPrecision), SA.VResolution (myPrecision)) + Precision::PConfusion()))
1008     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1009   return LastCheckStatus (ShapeExtend_DONE);
1010 }
1011
1012 //=======================================================================
1013 //function : CheckCurveGap
1014 //purpose  : 
1015 //=======================================================================
1016
1017  Standard_Boolean ShapeAnalysis_Wire::CheckCurveGap(const Standard_Integer num)
1018 {
1019   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1020   if ( !IsLoaded() || NbEdges() < 1 ) return Standard_False;
1021   Standard_Integer n = ( num >0 ? num  : NbEdges() );
1022   TopoDS_Edge E = myWire->Edge(n);
1023   Standard_Real cuf,cul,pcuf,pcul;
1024   Handle(Geom_Curve) c;
1025   ShapeAnalysis_Edge SAE;
1026   if (!SAE.Curve3d (E,c,cuf,cul,Standard_False)) {
1027     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1028     return Standard_False;
1029   }
1030   Handle(Geom2d_Curve) pc;
1031   if (!SAE.PCurve (E,myFace,pc,pcuf,pcul,Standard_False)) {
1032     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1033     return Standard_False;
1034   }
1035   Handle(Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(pc,pcuf,pcul);
1036   Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(mySurf->Surface());
1037   Adaptor3d_CurveOnSurface ACS(AC,AS);
1038   gp_Pnt cpnt, pcpnt;
1039   Standard_Integer nbp = 45;
1040   Standard_Real dist, maxdist=0.;
1041   for (Standard_Integer i=0; i<nbp; i++) {
1042     cpnt = c->Value(cuf + i*(cul-cuf)/(nbp-1));
1043     pcpnt = ACS.Value(pcuf + i*(pcul-pcuf)/(nbp-1));
1044     dist = cpnt.SquareDistance(pcpnt);
1045     if (maxdist<dist) maxdist = dist;
1046   }
1047   myMin3d = myMax3d = Sqrt(maxdist);
1048   if (myMin3d > myPrecision)
1049     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1050   return LastCheckStatus (ShapeExtend_DONE);
1051 }
1052
1053 //=======================================================================
1054 //function : CheckSelfIntersectingEdge
1055 //purpose  : 
1056 //=======================================================================
1057
1058 // auxiliary function
1059 //:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken 
1060 // from 3d curve (but only if edge is SameParameter)
1061 static gp_Pnt GetPointOnEdge ( const TopoDS_Edge &edge, 
1062                                const Handle(ShapeAnalysis_Surface) &surf,
1063                                const Handle(Geom2d_Curve) &Crv2d, 
1064                                const Standard_Real param )
1065 {
1066   if ( BRep_Tool::SameParameter ( edge ) ) {
1067     Standard_Real f,l;
1068     TopLoc_Location L;
1069     const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
1070     if ( ! ConS.IsNull() )
1071       return ConS->Value ( param ).Transformed ( L.Transformation() );
1072   }
1073   return surf->Value ( Crv2d->Value ( param ) );
1074 }
1075
1076 //=======================================================================
1077 //function : CheckSelfIntersectingEdge
1078 //purpose  : 
1079 //=======================================================================
1080
1081 Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersectingEdge (const Standard_Integer num,
1082                                                                 IntRes2d_SequenceOfIntersectionPoint& points2d,
1083                                                                 TColgp_SequenceOfPnt& points3d) 
1084 {
1085   points2d.Clear();
1086   points3d.Clear();
1087   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1088   if ( ! IsReady() ) return Standard_False;
1089
1090   TopoDS_Edge edge = WireData()->Edge ( num >0 ? num : NbEdges() );
1091   ShapeAnalysis_Edge sae;
1092
1093   Standard_Real a, b;
1094   Handle(Geom2d_Curve) Crv;
1095   if ( ! sae.PCurve ( edge, myFace, Crv, a, b, Standard_False ) ) {
1096     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1097     return Standard_False;
1098   }
1099   if ( Abs ( a - b ) <= ::Precision::PConfusion() ) return Standard_False;
1100   
1101   Standard_Real tolint = 1.0e-10; 
1102   //szv#4:S4163:12Mar99 warning
1103   IntRes2d_Domain domain ( Crv->Value ( a ), a, tolint, Crv->Value ( b ), b, tolint );
1104   Geom2dAdaptor_Curve AC ( Crv );
1105   Geom2dInt_GInter Inter ( AC, domain, tolint, tolint );
1106
1107   if ( ! Inter.IsDone() ) return Standard_False;
1108
1109   TopoDS_Vertex V1 = sae.FirstVertex ( edge );
1110   TopoDS_Vertex V2 = sae.LastVertex ( edge );
1111   if ( V1.IsNull() || V2.IsNull() ) {
1112     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1113     return Standard_False;
1114   }
1115   Standard_Real tol1 = BRep_Tool::Tolerance ( V1 );
1116   Standard_Real tol2 = BRep_Tool::Tolerance ( V2 );
1117
1118   gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 );
1119   gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 );
1120
1121   for ( Standard_Integer i=1; i <= Inter.NbPoints(); i++ ) {
1122     const IntRes2d_IntersectionPoint &IP = Inter.Point ( i );
1123     const IntRes2d_Transition &Tr1 = IP.TransitionOfFirst();
1124     const IntRes2d_Transition &Tr2 = IP.TransitionOfSecond();
1125     if ( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1126          Tr2.PositionOnCurve() != IntRes2d_Middle ) continue;
1127     gp_Pnt pint = GetPointOnEdge ( edge, mySurf, Crv, IP.ParamOnFirst() );
1128     Standard_Real dist21 = pnt1.SquareDistance ( pint );
1129     Standard_Real dist22 = pnt2.SquareDistance ( pint );
1130     if ( dist21 > tol1 * tol1 && dist22 > tol2 * tol2 ) {
1131       points2d.Append ( IP );
1132       points3d.Append ( pint );
1133       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1134     }
1135   }
1136
1137   return LastCheckStatus ( ShapeExtend_DONE );
1138 }
1139
1140 //=======================================================================
1141 //function : CheckSelfIntersectingEdge
1142 //purpose  : 
1143 //=======================================================================
1144
1145 Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersectingEdge (const Standard_Integer num)
1146 {
1147   IntRes2d_SequenceOfIntersectionPoint points2d;
1148   TColgp_SequenceOfPnt points3d;
1149   return CheckSelfIntersectingEdge ( num, points2d, points3d );
1150 }
1151
1152 //=======================================================================
1153 //function : CheckIntersectingEdges
1154 //purpose  : Test if two consequent edges are intersecting 
1155 //           It is made in accordance with the following check in BRepCheck:
1156 //         - in BRepCheck_Wire::Orientation(), test for self-intersection
1157 //=======================================================================
1158
1159 Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num,
1160                                                              IntRes2d_SequenceOfIntersectionPoint& points2d,
1161                                                              TColgp_SequenceOfPnt& points3d,
1162                                                              TColStd_SequenceOfReal& errors)
1163 {
1164   points2d.Clear();
1165   points3d.Clear();
1166   errors.Clear();
1167   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1168   if ( ! IsReady() || NbEdges() <2 ) return Standard_False;
1169   
1170   //szv#4:S4163:12Mar99 optimized
1171   Standard_Integer n2 = (num > 0)? num : NbEdges();
1172   Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges();
1173   TopoDS_Edge edge1 = myWire->Edge ( n1 );
1174   TopoDS_Edge edge2 = myWire->Edge ( n2 );
1175
1176   ShapeAnalysis_Edge sae;
1177   TopoDS_Vertex V1 = sae.LastVertex ( edge1 );
1178   TopoDS_Vertex V2 = sae.FirstVertex ( edge2 );
1179   if ( V1.IsNull() || V2.IsNull() ) {
1180     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1181     return Standard_False;
1182   }
1183   if ( ! BRepTools::Compare ( V1, V2 ) ) {
1184     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1185     return Standard_False;
1186   }
1187
1188   TopoDS_Vertex Vp = sae.FirstVertex ( edge1 );
1189   TopoDS_Vertex Vn = sae.LastVertex ( edge2 );
1190
1191   Standard_Real a1, b1, a2, b2;
1192   Handle(Geom2d_Curve) Crv1, Crv2;
1193   if ( ! sae.PCurve ( edge1, myFace, Crv1, a1, b1, Standard_False ) ) {
1194     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1195     return Standard_False;
1196   }
1197   if ( ! sae.PCurve ( edge2, myFace, Crv2, a2, b2, Standard_False ) ) {
1198     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1199     return Standard_False;
1200   }
1201   if ( Abs ( a1 - b1 ) <= ::Precision::PConfusion() ||
1202        Abs ( a2 - b2 ) <= ::Precision::PConfusion() ) return Standard_False; //:f7 abv 6 May 98: BUC50070 on #42276
1203
1204   Standard_Boolean isForward1 = ( edge1.Orientation() == TopAbs_FORWARD );
1205   Standard_Boolean isForward2 = ( edge2.Orientation() == TopAbs_FORWARD );
1206
1207   Standard_Real tol0 = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
1208   Standard_Real tol = tol0;
1209
1210   gp_Pnt pnt = BRep_Tool::Pnt ( V1 );
1211
1212 //  Standard_Boolean Status = Standard_False;
1213
1214   Standard_Real tolint = 1.0e-10; 
1215
1216   //szv#4:S4163:12Mar99 warning
1217   IntRes2d_Domain d1 ( Crv1->Value ( a1 ), a1, tolint, 
1218                        Crv1->Value ( b1 ), b1, tolint );
1219   IntRes2d_Domain d2 ( Crv2->Value ( a2 ), a2, tolint, 
1220                        Crv2->Value ( b2 ), b2, tolint );
1221   Geom2dAdaptor_Curve C1 ( Crv1 ), C2 ( Crv2 );
1222
1223   //:64 abv 25 Dec 97: Attention!
1224   // Since Intersection algorithm is not symmetrical, for consistency with BRepCheck 
1225   // edge with lower order number shoud be intersecting with edge with higher one
1226   // i.e., for intersection of last and first edges, they should go in reversed order
1227   // Example: entity #38285 from bug CSR #CTS17806
1228   // NOTE: Tr1 and Tr2 are not reordered because they are used in the same manner
1229   Geom2dInt_GInter Inter;
1230   if ( num ==1 ) Inter.Perform ( C2, d2, C1, d1, tolint, tolint );
1231   else           Inter.Perform ( C1, d1, C2, d2, tolint, tolint );
1232   if ( ! Inter.IsDone() ) return Standard_False;
1233
1234   //:86 abv 22 Jan 98: fix self-intersection even if tolerance of vertex is enough
1235   // to annihilate it. This is done to prevent wrong effects if vertex tolerance 
1236   // will be decreased (e.g., in FixLacking)
1237   Standard_Real tole = Max ( ( BRep_Tool::SameParameter ( edge1 ) ? 
1238                                BRep_Tool::Tolerance ( edge1 ) : tol0 ),
1239                              ( BRep_Tool::SameParameter ( edge2 ) ? 
1240                                BRep_Tool::Tolerance ( edge2 ) : tol0 ) );
1241   Standard_Real tolt = Min ( tol, Max ( tole, myPrecision ) );
1242   //Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast(); //SK
1243   Standard_Integer isLacking = -1; //:l0 abv: CATIA01 #1727: protect against adding lacking
1244   //#83 rln 19.03.99 sim2.igs, entity 4292
1245   //processing also segments as in BRepCheck
1246   Standard_Integer NbPoints = Inter.NbPoints(), NbSegments = Inter.NbSegments();
1247   for ( Standard_Integer i=1; i <= NbPoints + NbSegments; i++ ) {
1248     IntRes2d_IntersectionPoint IP;
1249     IntRes2d_Transition Tr1, Tr2;
1250     if (i <= NbPoints)
1251       IP = Inter.Point ( i );
1252     else {
1253       const IntRes2d_IntersectionSegment &Seg = Inter.Segment ( i - NbPoints );
1254       if (!Seg.HasFirstPoint() || !Seg.HasLastPoint()) continue;
1255       IP = Seg.FirstPoint();
1256       Tr1 = IP.TransitionOfFirst();
1257       Tr2 = IP.TransitionOfSecond();
1258       if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle)
1259         IP = Seg.LastPoint();
1260     }
1261     Tr1 = IP.TransitionOfFirst();
1262     Tr2 = IP.TransitionOfSecond();      
1263
1264     if ( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1265          Tr2.PositionOnCurve() != IntRes2d_Middle ) continue;
1266     Standard_Real param1, param2;
1267     param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() ); 
1268     param2 = ( num ==1 ? IP.ParamOnFirst()  : IP.ParamOnSecond() );
1269     
1270     //:r6 abv 8 Apr 99: r_47-sd.stp #173850: protect against working out of curve range
1271     if ( a1-param1 > ::Precision::PConfusion() || 
1272          param1-b1 > ::Precision::PConfusion() || 
1273          a2-param2 > ::Precision::PConfusion() || 
1274          param2-b2 > ::Precision::PConfusion() ) continue;
1275
1276     //:82 abv 21 Jan 98: point of intersection on Crv1 and Crv2 is different
1277     gp_Pnt pi1 = GetPointOnEdge ( edge1, mySurf, Crv1, param1 ); //:h0: thesurf.Value ( Crv1->Value ( param1 ) );
1278     gp_Pnt pi2 = GetPointOnEdge ( edge2, mySurf, Crv2, param2 ); //:h0: thesurf.Value ( Crv2->Value ( param2 ) );
1279     gp_Pnt pint = 0.5 * ( pi1.XYZ() + pi2.XYZ() );
1280     Standard_Real di1 = pi1.SquareDistance ( pnt );
1281     Standard_Real di2 = pi2.SquareDistance ( pnt );
1282     Standard_Real dist2 = Max ( di1, di2 );
1283
1284     //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge)
1285     if ( isLacking <0 ) { //:l0
1286       gp_Pnt2d end1 = Crv1->Value ( isForward1 ? b1 : a1 );
1287       gp_Pnt2d end2 = Crv2->Value ( isForward2 ? a2 : b2 );
1288 //:l0      Standard_Real distab2 = mySurf->Value ( end1 ).SquareDistance ( mySurf->Value ( end2 ) );
1289       //:l0: test like in BRepCheck
1290       GeomAdaptor_Surface& Ads = mySurf->Adaptor3d()->ChangeSurface();
1291       Standard_Real tol2d = 2 * Max ( Ads.UResolution(tol), Ads.VResolution(tol) );
1292       isLacking = ( end1.SquareDistance(end2) >= tol2d * tol2d );
1293     }
1294       
1295     if ( ( dist2 > tolt * tolt || //:86: tol -> tolt
1296            isLacking ) && //:l0
1297 //:l0      distab2 > BRep_Tool::Tolerance ( edge1 ) + BRep_Tool::Tolerance ( edge2 ) ) && //rln
1298          ( ! BRepTools::Compare ( Vp, Vn ) ||                          //:63
1299            dist2 < pint.SquareDistance ( BRep_Tool::Pnt ( Vp ) ) ) ) { //:63
1300       points2d.Append ( IP );
1301       points3d.Append ( pint );
1302       errors.Append ( 0.5 * pi1.Distance ( pi2 ) );
1303       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1304     }
1305   }
1306
1307   return LastCheckStatus ( ShapeExtend_DONE );
1308 }
1309
1310 //=======================================================================
1311 //function : CheckIntersectingEdges
1312 //purpose  : 
1313 //=======================================================================
1314
1315 Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num)
1316 {
1317   IntRes2d_SequenceOfIntersectionPoint points2d;
1318   TColgp_SequenceOfPnt points3d;
1319   TColStd_SequenceOfReal errors;
1320   return CheckIntersectingEdges ( num, points2d, points3d, errors );
1321 }
1322
1323 //=======================================================================
1324 //function : CheckIntersectingEdges
1325 //purpose  : 
1326 //=======================================================================
1327
1328 Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges(const Standard_Integer num1,
1329                                                             const Standard_Integer num2,
1330                                                             IntRes2d_SequenceOfIntersectionPoint& points2d,
1331                                                             TColgp_SequenceOfPnt& points3d,
1332                                                             TColStd_SequenceOfReal& errors)
1333 {
1334   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1335   if ( ! IsReady() ) return Standard_False;
1336   Handle(ShapeExtend_WireData) sbwd = WireData();
1337   Standard_Integer n2 = ( num2 >0 ? num2  : sbwd->NbEdges() );
1338   Standard_Integer n1 = ( num1 >0 ? num1  : sbwd->NbEdges() );
1339   
1340   TopoDS_Edge edge1 = sbwd->Edge ( n1 );
1341   TopoDS_Edge edge2 = sbwd->Edge ( n2 );
1342   
1343   ShapeAnalysis_Edge sae;
1344   Standard_Real a1, b1, a2, b2;
1345   Handle(Geom2d_Curve) Crv1, Crv2;
1346   if(!sae.PCurve ( edge1, myFace, Crv1, a1, b1, Standard_False )){
1347     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1348     return Standard_False;
1349   }
1350     
1351   if(!sae.PCurve ( edge2, myFace, Crv2, a2, b2, Standard_False )){
1352     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1353     return Standard_False;
1354   }
1355   
1356   if ( Abs ( a1 - b1 ) <= ::Precision::PConfusion() ||
1357        Abs ( a2 - b2 ) <= ::Precision::PConfusion() ) return Standard_False;
1358   
1359   points2d.Clear();
1360   points3d.Clear();
1361   errors.Clear();
1362   TColgp_Array1OfPnt vertexPoints(1,4);
1363   TColStd_Array1OfReal vertexTolers(1,4);
1364   vertexPoints(1) = BRep_Tool::Pnt(sae.FirstVertex(edge1));
1365   vertexTolers(1) = BRep_Tool::Tolerance(sae.FirstVertex(edge1));
1366   vertexPoints(2) = BRep_Tool::Pnt(sae.LastVertex(edge1));
1367   vertexTolers(2) = BRep_Tool::Tolerance(sae.LastVertex(edge1));
1368   vertexPoints(3) = BRep_Tool::Pnt(sae.FirstVertex(edge2));
1369   vertexTolers(3) = BRep_Tool::Tolerance(sae.FirstVertex(edge2));
1370   vertexPoints(4) = BRep_Tool::Pnt(sae.LastVertex(edge2));
1371   vertexTolers(4) = BRep_Tool::Tolerance(sae.LastVertex(edge2));
1372   
1373   Standard_Real tolint = 1.0e-10; 
1374
1375   IntRes2d_Domain d1 ( Crv1->Value ( a1 ), a1, tolint, 
1376                        Crv1->Value ( b1 ), b1, tolint );
1377   IntRes2d_Domain d2 ( Crv2->Value ( a2 ), a2, tolint, 
1378                        Crv2->Value ( b2 ), b2, tolint );
1379   Geom2dAdaptor_Curve C1 ( Crv1 ), C2 ( Crv2 );
1380   
1381   Geom2dInt_GInter Inter;
1382   Inter.Perform ( C1, d1, C2, d2, tolint, tolint );
1383   if ( ! Inter.IsDone() ) return Standard_False;
1384   
1385   //#83 rln 19.03.99 sim2.igs, entity 4292
1386   //processing also segments as in BRepCheck
1387   Standard_Integer NbPoints = Inter.NbPoints(), NbSegments = Inter.NbSegments();
1388   for ( Standard_Integer i=1; i <= NbPoints + NbSegments; i++ ) {
1389     IntRes2d_IntersectionPoint IP;
1390     IntRes2d_Transition Tr1, Tr2;
1391     if (i <= NbPoints)
1392       IP = Inter.Point ( i );
1393     else {
1394       const IntRes2d_IntersectionSegment &Seg = Inter.Segment ( i - NbPoints );
1395       if (!Seg.HasFirstPoint() || !Seg.HasLastPoint()) continue;
1396       IP = Seg.FirstPoint();
1397       Tr1 = IP.TransitionOfFirst();
1398       Tr2 = IP.TransitionOfSecond();
1399       if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle)
1400         IP = Seg.LastPoint();
1401     }
1402     Tr1 = IP.TransitionOfFirst();
1403     Tr2 = IP.TransitionOfSecond();      
1404     if ( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1405          Tr2.PositionOnCurve() != IntRes2d_Middle ) continue;
1406     Standard_Real param1 = IP.ParamOnFirst(); 
1407     Standard_Real param2 = IP.ParamOnSecond();
1408     gp_Pnt pi1 = GetPointOnEdge ( edge1, mySurf, Crv1, param1 ); //:h0: thesurf.Value ( Crv1->Value ( param1 ) );
1409     gp_Pnt pi2 = GetPointOnEdge ( edge2, mySurf, Crv2, param2 );
1410     Standard_Boolean OK = Standard_False;
1411     for(Standard_Integer j=1; (j<=4)&&!OK; j++) {
1412       Standard_Real di1 = pi1.SquareDistance (vertexPoints(j));
1413       Standard_Real di2 = pi2.SquareDistance (vertexPoints(j));
1414       Standard_Real dist2 = Max ( di1, di2 );
1415       if(dist2 < vertexTolers(j) * vertexTolers(j))
1416         OK = Standard_True;
1417     }
1418     if(!OK) {
1419       gp_Pnt pint = 0.5 * ( pi1.XYZ() + pi2.XYZ() );
1420       points2d.Append ( IP );
1421       points3d.Append ( pint );
1422       errors.Append ( 0.5 * pi1.Distance ( pi2 ) );
1423       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);   
1424     }
1425   }
1426   return LastCheckStatus ( ShapeExtend_DONE );
1427 }
1428
1429 //=======================================================================
1430 //function : CheckIntersectingEdges
1431 //purpose  : 
1432 //=======================================================================
1433
1434 Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num1,
1435                                                              const Standard_Integer num2)
1436 {
1437   IntRes2d_SequenceOfIntersectionPoint points2d;
1438   TColgp_SequenceOfPnt points3d;
1439   TColStd_SequenceOfReal errors;
1440   return CheckIntersectingEdges(num1, num2, points2d, points3d, errors);
1441 }
1442
1443 //=======================================================================
1444 //function : CheckLacking
1445 //purpose  : Test if two edges are disconnected in 2d according to the 
1446 //           Adaptor_Surface::Resolution
1447 //=======================================================================
1448
1449 Standard_Boolean ShapeAnalysis_Wire::CheckLacking (const Standard_Integer num,
1450                                                    const Standard_Real Tolerance,
1451                                                    gp_Pnt2d &p2d1, gp_Pnt2d &p2d2) 
1452 {
1453   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1454   if ( ! IsReady() ) return Standard_False;
1455   
1456   //szv#4:S4163:12Mar99 optimized
1457   Standard_Integer n2 = (num > 0)? num : NbEdges();
1458   Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges();
1459   TopoDS_Edge E1 = myWire->Edge ( n1 );
1460   TopoDS_Edge E2 = myWire->Edge ( n2 );
1461   
1462   ShapeAnalysis_Edge sae;
1463   TopoDS_Vertex V1 = sae.LastVertex ( E1 );
1464   TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
1465   // CKY 4 MAR 1998 : protection against null vertex
1466   if ( V1.IsNull() || V2.IsNull() ) {
1467     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1468     return Standard_False;
1469   }
1470   if ( ! BRepTools::Compare ( V1, V2 ) ) {
1471     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1472     return Standard_False;
1473   }
1474
1475   Standard_Real a, b;
1476   gp_Vec2d v1, v2, v12;
1477   Handle(Geom2d_Curve) c2d;
1478   if ( ! sae.PCurve ( E1, myFace, c2d, a, b, Standard_True ) ) {
1479     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1480     return Standard_False;
1481   }
1482   c2d->D1 ( b, p2d1, v1 ); 
1483   if ( E1.Orientation() == TopAbs_REVERSED ) v1.Reverse();
1484   if ( ! sae.PCurve ( E2, myFace, c2d, a, b, Standard_True ) ) {
1485     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1486     return Standard_False;
1487   }
1488   c2d->D1 ( a, p2d2, v2 );
1489   if ( E2.Orientation() == TopAbs_REVERSED ) v2.Reverse();
1490   v12 = p2d2.XY() - p2d1.XY();
1491   myMax2d = v12.SquareMagnitude();
1492
1493   // test like in BRepCheck
1494   Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
1495   tol = ( Tolerance > gp::Resolution() && Tolerance < tol ? Tolerance : tol );
1496   GeomAdaptor_Surface& Ads = mySurf->Adaptor3d()->ChangeSurface();
1497   Standard_Real tol2d = 2 * Max ( Ads.UResolution(tol), Ads.VResolution(tol) );
1498   if ( // tol2d < gp::Resolution() || //#2 smh 26.03.99 S4163 Zero divide
1499        myMax2d < tol2d * tol2d ) return Standard_False;
1500
1501   myMax2d = Sqrt ( myMax2d );
1502   myMax3d = tol * myMax2d / Max ( tol2d, gp::Resolution() );
1503   myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1504
1505   if ( myMax2d < Precision::PConfusion() || //:abv 03.06.02 CTS21866.stp
1506        ( v1.SquareMagnitude() > gp::Resolution() && Abs ( v12.Angle ( v1 ) ) > 0.9 * M_PI ) ||
1507        ( v2.SquareMagnitude() > gp::Resolution() && Abs ( v12.Angle ( v2 ) ) > 0.9 * M_PI ) ) 
1508        myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1509   return Standard_True;
1510 }
1511
1512 //=======================================================================
1513 //function : CheckLacking
1514 //purpose  :
1515 //          
1516 //=======================================================================
1517
1518 Standard_Boolean ShapeAnalysis_Wire::CheckLacking (const Standard_Integer num,
1519                                                    const Standard_Real Tolerance)
1520 {
1521   gp_Pnt2d p1, p2;
1522   return CheckLacking (num, Tolerance, p1, p2);
1523 }
1524
1525 //=======================================================================
1526 //function : CheckOuterBound
1527 //purpose  : 
1528 //=======================================================================
1529
1530  Standard_Boolean ShapeAnalysis_Wire::CheckOuterBound(const Standard_Boolean APIMake)
1531 {
1532   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1533   if ( ! IsReady() ) return Standard_False;
1534
1535   TopoDS_Wire wire;
1536   if (APIMake) wire = myWire->WireAPIMake();
1537   else         wire = myWire->Wire();
1538   
1539   TopoDS_Shape sh = myFace.EmptyCopied(); //szv#4:S4163:12Mar99 SGI warns
1540   TopoDS_Face face = TopoDS::Face(sh);
1541   BRep_Builder B;
1542   B.Add (face, wire);
1543   if (ShapeAnalysis::IsOuterBound (face)) return Standard_False;
1544   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1545   return Standard_True;
1546 }
1547
1548 //=======================================================================
1549 //function : CheckNotchedEdges
1550 //purpose  : 
1551 //=======================================================================
1552
1553 static Standard_Real ProjectInside(const Adaptor3d_CurveOnSurface AD,
1554                                    const gp_Pnt pnt,
1555                                    const Standard_Real preci,
1556                                    gp_Pnt& proj,
1557                                    Standard_Real& param,
1558                                    const Standard_Boolean adjustToEnds = Standard_True)
1559 {
1560   ShapeAnalysis_Curve sac;
1561   Standard_Real dist = sac.Project(AD,pnt,preci,proj,param,adjustToEnds);
1562   Standard_Real uFirst = AD.FirstParameter();
1563   Standard_Real uLast = AD.LastParameter();
1564   if(param<uFirst) {
1565     param = uFirst;
1566     proj = AD.Value(uFirst);
1567     return proj.Distance(pnt);
1568   }
1569   
1570   if(param>uLast) {
1571     param = uLast;
1572     proj = AD.Value(uLast);
1573     return proj.Distance(pnt);
1574   }
1575   return dist;
1576 }
1577   
1578 Standard_Boolean ShapeAnalysis_Wire::CheckNotchedEdges(const Standard_Integer num,
1579                                                        Standard_Integer& shortNum,
1580                                                        Standard_Real& param,
1581                                                        const Standard_Real Tolerance)
1582 {
1583   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1584   if ( ! IsReady() ) return Standard_False;
1585   
1586   Standard_Integer n2 = (num > 0)? num : NbEdges();
1587   Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges();
1588   TopoDS_Edge E1 = myWire->Edge ( n1 );
1589   TopoDS_Edge E2 = myWire->Edge ( n2 );
1590   
1591   if(BRep_Tool::Degenerated(E1)||BRep_Tool::Degenerated(E2))
1592     return Standard_False;
1593   
1594   ShapeAnalysis_Edge sae;
1595   TopoDS_Vertex V1 = sae.LastVertex ( E1 );
1596   TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
1597   
1598   if ( V1.IsNull() || V2.IsNull() ) {
1599     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1600     return Standard_False;
1601   }
1602   if ( ! BRepTools::Compare ( V1, V2 ) ) {
1603     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1604     return Standard_False;
1605   }
1606
1607   Standard_Real a1, b1, a2, b2;
1608   gp_Pnt2d p2d1, p2d2;
1609   gp_Vec2d v1, v2;
1610   Handle(Geom2d_Curve) c2d1, c2d2;
1611   if ( ! sae.PCurve ( E1, myFace, c2d1, a1, b1, Standard_False ) ) {
1612     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1613     return Standard_False;
1614   }
1615   
1616   if(E1.Orientation()==TopAbs_REVERSED)
1617     c2d1->D1 ( a1, p2d1, v1 );
1618   else {
1619     c2d1->D1 ( b1, p2d1, v1 );
1620     v1.Reverse();
1621   }
1622   
1623   if ( ! sae.PCurve ( E2, myFace, c2d2, a2, b2, Standard_False ) ) {
1624     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
1625     return Standard_False;
1626   }
1627   if(E2.Orientation()==TopAbs_REVERSED) {
1628     c2d2->D1 ( b2, p2d2, v2 );
1629     v2.Reverse();
1630   }
1631   else 
1632     c2d2->D1 ( a2, p2d2, v2 );
1633   
1634   if ( v2.Magnitude() < gp::Resolution() || v1.Magnitude() < gp::Resolution())
1635     return Standard_False;
1636   
1637   if ( Abs ( v2.Angle ( v1 ) ) > 0.1 || p2d1.Distance(p2d2) > Tolerance)
1638     return Standard_False;
1639   
1640   Handle(Geom2dAdaptor_HCurve) AC2d1  = new Geom2dAdaptor_HCurve(c2d1,a1,b1);
1641   Handle(GeomAdaptor_HSurface) AdS1 = new GeomAdaptor_HSurface(new Geom_Plane(gp_Pln()));
1642   Adaptor3d_CurveOnSurface Ad1(AC2d1,AdS1);
1643   
1644   Handle(Geom2dAdaptor_HCurve) AC2d2  = new Geom2dAdaptor_HCurve(c2d2,a2,b2);
1645   Handle(GeomAdaptor_HSurface) AdS2 = new GeomAdaptor_HSurface(new Geom_Plane(gp_Pln()));
1646   Adaptor3d_CurveOnSurface Ad2(AC2d2,AdS2);
1647   
1648   Adaptor3d_CurveOnSurface longAD, shortAD;
1649   Standard_Real lenP, firstP;
1650   
1651   ShapeAnalysis_Curve sac;
1652   
1653   gp_Pnt Proj1, Proj2;
1654   Standard_Real param1 = 0., param2 = 0.;
1655   p2d2=c2d2->Value(E2.Orientation()==TopAbs_FORWARD ? b2 : a2);
1656   p2d1=c2d1->Value(E1.Orientation()==TopAbs_FORWARD ? a1 : b1);
1657   Standard_Real dist1 = ProjectInside(Ad1,gp_Pnt(p2d2.X(),p2d2.Y(),0),Tolerance,Proj1,param1,Standard_False);
1658   Standard_Real dist2 = ProjectInside(Ad2,gp_Pnt(p2d1.X(),p2d1.Y(),0),Tolerance,Proj2,param2,Standard_False);
1659   
1660   if ( dist1 > Tolerance && dist2 > Tolerance)
1661     return Standard_False;
1662   
1663   if (dist1 < dist2 ) {
1664     shortAD = Ad2;
1665     longAD = Ad1;
1666     lenP = b2 - a2;
1667     firstP = a2;
1668     shortNum=n2;
1669     param=param1;
1670     
1671   }
1672   else {
1673     shortAD = Ad1;
1674     longAD = Ad2;
1675     lenP = b1 - a1;
1676     firstP = a1;
1677     shortNum=n1;
1678     param=param2;
1679   }
1680   
1681   Standard_Real step = lenP/23;
1682   for (Standard_Integer i = 1; i < 23; i++,firstP+=step) {
1683     Standard_Real d1 = sac.Project(longAD,shortAD.Value(firstP),Tolerance,Proj1,param1);
1684     if (d1 > Tolerance) {
1685       return Standard_False;
1686     }
1687   }
1688   
1689   return Standard_True; 
1690 }
1691
1692 //=======================================================================
1693 //function : CheckSmallArea
1694 //purpose  : 
1695 //=======================================================================
1696
1697 Standard_Boolean ShapeAnalysis_Wire::CheckSmallArea(const Standard_Real prec2d)
1698 {
1699   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1700   Standard_Integer NbEdges = myWire->NbEdges();
1701   if ( !IsReady() || NbEdges <1 ) return Standard_False;
1702   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
1703   
1704   Standard_Integer NbControl=23;
1705   Standard_Real area=0;
1706   gp_XY prev, cont;
1707   for (Standard_Integer nbe = 1; nbe <= NbEdges; nbe++) {
1708     Standard_Real First, Last;
1709     Handle(Geom2d_Curve) c2d;
1710     ShapeAnalysis_Edge sae;
1711     if (!sae.PCurve(myWire->Edge(nbe),myFace,c2d,First,Last)) {
1712       myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1713       return Standard_False;
1714     }
1715     
1716     Standard_Integer ibeg = 0;
1717     if( nbe == 1 ) {
1718       gp_Pnt2d pntIni = c2d->Value(First);
1719       prev = pntIni.XY();
1720       cont = prev;
1721       ibeg = 1;
1722     }
1723     for ( Standard_Integer i = ibeg; i < NbControl; i++) {
1724       Standard_Real prm = ((NbControl-1-i)*First + i*Last)/(NbControl-1);
1725       gp_Pnt2d pntCurr = c2d->Value(prm);
1726       gp_XY curr = pntCurr.XY();
1727       area += curr ^ prev;
1728       prev = curr;
1729     }
1730   }
1731   area +=  cont ^ prev;
1732   if ( Abs(area) < 2*prec2d*prec2d ) {
1733     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1734     return Standard_True;
1735   }
1736   return Standard_False;
1737 }
1738
1739 //=======================================================================
1740 //function : CheckShapeConnect
1741 //purpose  : 
1742 //=======================================================================
1743
1744  Standard_Boolean ShapeAnalysis_Wire::CheckShapeConnect(const TopoDS_Shape& shape,const Standard_Real prec) 
1745 {
1746   Standard_Real tailhead, tailtail, headhead, headtail;
1747   return CheckShapeConnect (tailhead, tailtail, headtail, headhead, shape, prec);
1748 }
1749
1750 //=======================================================================
1751 //function : CheckShapeConnect
1752 //purpose  : 
1753 //=======================================================================
1754
1755  Standard_Boolean ShapeAnalysis_Wire::CheckShapeConnect(Standard_Real& tailhead, Standard_Real& tailtail,
1756                                                         Standard_Real& headtail, Standard_Real& headhead,
1757                                                         const TopoDS_Shape& shape, const Standard_Real prec) 
1758 {
1759     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
1760   if (!IsLoaded () || shape.IsNull()) return Standard_False;
1761   TopoDS_Vertex V1,V2;
1762   TopoDS_Edge E;  TopoDS_Wire W;
1763   ShapeAnalysis_Edge SAE;
1764   if (shape.ShapeType() == TopAbs_EDGE) {
1765     E = TopoDS::Edge (shape);
1766     V1 = SAE.FirstVertex (E);    V2 = SAE.LastVertex  (E);
1767   } else if (shape.ShapeType() == TopAbs_WIRE) {
1768     W = TopoDS::Wire (shape);
1769     ShapeAnalysis::FindBounds (W,V1,V2); 
1770   }
1771   else return Standard_False;
1772   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1773 //  on va comparer les points avec ceux de thevfirst et thevlast
1774   gp_Pnt p1 = BRep_Tool::Pnt(V1);
1775   gp_Pnt p2 = BRep_Tool::Pnt(V2);
1776
1777   TopoDS_Vertex vfirst = SAE.FirstVertex (myWire->Edge (1)),
1778                 vlast  = SAE.LastVertex (myWire->Edge (NbEdges()));
1779   gp_Pnt pf = BRep_Tool::Pnt(vfirst);
1780   gp_Pnt pl = BRep_Tool::Pnt(vlast);
1781
1782   tailhead = p1.Distance(pl);
1783   tailtail = p2.Distance(pl);
1784   headhead = p1.Distance(pf);
1785   headtail = p2.Distance(pf);
1786   Standard_Real dm1 = tailhead, dm2 = headtail;
1787   Standard_Integer res1 = 0, res2 = 0;
1788
1789   if (tailhead > tailtail) {res1 = 1; dm1 = tailtail;}
1790   if (headtail > headhead) {res2 = 1; dm2 = headhead;}
1791   Standard_Integer result = res1;
1792   myMin3d = Min (dm1, dm2);
1793   myMax3d = Max (dm1, dm2);
1794   if (dm1 > dm2) {dm1 = dm2; result = res2 + 2;}
1795   switch (result) {
1796   case 1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break;
1797   case 2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); break;
1798   case 3: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break;
1799   }
1800   if (!res1) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE5);
1801   if (!res2) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE6);
1802
1803   if (myMin3d > Max (myPrecision, prec))
1804     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
1805   return LastCheckStatus (ShapeExtend_DONE);
1806 }
1807
1808 //=======================================================================
1809 //function : CheckLoop
1810 //purpose  : 
1811 //=======================================================================
1812 Standard_Boolean isMultiVertex(const TopTools_ListOfShape& alshape,
1813                                const TopTools_MapOfShape& aMapSmallEdges,
1814                                const TopTools_MapOfShape& aMapSeemEdges)
1815 {
1816   TopTools_ListIteratorOfListOfShape lIt1(alshape);
1817   Standard_Integer nbNotAccount =0;
1818   
1819   for( ; lIt1.More() ; lIt1.Next()) 
1820   {
1821     if(aMapSmallEdges.Contains(lIt1.Value()))
1822       nbNotAccount++;
1823     else if(aMapSeemEdges.Contains(lIt1.Value()))
1824       nbNotAccount++;
1825   }
1826   return ((alshape.Extent() -nbNotAccount) >2); 
1827 }
1828  Standard_Boolean ShapeAnalysis_Wire::CheckLoop(TopTools_IndexedMapOfShape& aMapLoopVertices,
1829                                                 TopTools_DataMapOfShapeListOfShape& aMapVertexEdges,
1830                                                 TopTools_MapOfShape& aMapSmallEdges,
1831                                                 TopTools_MapOfShape& aMapSeemEdges) 
1832 {
1833   myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
1834   if (!IsLoaded() || NbEdges() < 2) return Standard_False;
1835   Standard_Real aSavPreci = Precision();
1836   SetPrecision(Precision::Infinite());
1837   Standard_Integer i =1;
1838  
1839   for( ; i <= myWire->NbEdges(); i++) {
1840     TopoDS_Edge aedge = myWire->Edge(i);
1841     TopoDS_Vertex aV1,aV2;
1842     TopExp::Vertices(aedge,aV1,aV2);
1843     Standard_Boolean isSame = aV1.IsSame(aV2);
1844     if(myWire->IsSeam(i))
1845       aMapSeemEdges.Add(aedge); ///continue;
1846     else if(BRep_Tool::Degenerated(aedge))
1847       aMapSmallEdges.Add(aedge);
1848     else if(isSame && CheckSmall(i,BRep_Tool::Tolerance(aV1)))
1849       aMapSmallEdges.Add(aedge);
1850
1851     if(!aMapVertexEdges.IsBound(aV1)) {
1852       TopTools_ListOfShape alshape;
1853       aMapVertexEdges.Bind(aV1,alshape);
1854     }
1855     if(!aMapVertexEdges.IsBound(aV2)) {
1856       TopTools_ListOfShape alshape;
1857       aMapVertexEdges.Bind(aV2,alshape);
1858     }
1859     if(isSame)
1860     {
1861       TopTools_ListOfShape& alshape =  aMapVertexEdges.ChangeFind(aV1);
1862       alshape.Append(aedge);
1863       alshape.Append(aedge);
1864       if(alshape.Extent() >2 && isMultiVertex( alshape,aMapSmallEdges,aMapSeemEdges))
1865         aMapLoopVertices.Add(aV1);
1866     }
1867     else {
1868       TopTools_ListOfShape& alshape =  aMapVertexEdges.ChangeFind(aV1);
1869       alshape.Append(aedge);
1870       if(alshape.Extent() >2 && isMultiVertex( alshape,aMapSmallEdges,aMapSeemEdges))
1871         aMapLoopVertices.Add(aV1);
1872       TopTools_ListOfShape& alshape2 =  aMapVertexEdges.ChangeFind(aV2);
1873       alshape2.Append(aedge);
1874       if(alshape2.Extent() >2 && isMultiVertex( alshape2,aMapSmallEdges,aMapSeemEdges))
1875         aMapLoopVertices.Add(aV2);
1876     }
1877   }
1878   SetPrecision(aSavPreci);
1879   if(aMapLoopVertices.Extent())
1880   {
1881     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
1882     myStatusLoop |= myStatus;
1883     return Standard_True;
1884   }
1885   return Standard_False;
1886 }