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