0028966: Coding Rules - remove Adaptor2d_HCurve2d, Adaptor3d_HCurve and Adaptor3d_HSu...
[occt.git] / src / ShapeFix / ShapeFix_Wire.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586: 
15 //    in FixIntersectingEdges, do not cut edges because of influence on adjacent faces
16 // pdn 17.12.98: shifting whole wire in FixShifted
17 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: removing self-int loops on pcurves
18 // pdn 30.12.98: PRO10366 #210: shifting pcurve between two singularities
19 // pdn 05.01.98: renaming method FixLittle to FixSmall
20 //:l0 abv 10.01.99: remove unused code
21 //:n2 abv 22.01.99: ma-test5.igs: IGES read (pref3d): remove degen edge with no pcurve
22 //:o4 abv 17.02.99: r0301_db.stp #53082: using parameter isClosed in CheckOrder
23 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edges after shifting pcurves
24 //#67 rln 01.03.99 S4135: ims010.igs treatment of Geom_SphericalSurface together with V-closed surfaces
25 //:p7 abv 10.03.99 PRO18206: using method IsDegenerated() to detect singularity in FixLacking
26 //:r0 abv 19.03.99 PRO7226.stp #489490: remove degenerated edges if several
27 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
28 //#79 rln 15.03.99 S4135: bmarkmdl.igs: check for gap before shifting on singularities
29 //    pdn 17.03.99 S4135: implemented fixing not adjacent intersection
30 //#86 rln 22.03.99 S4135: repeat of fix self-intersection if it was fixed just before
31 //%15 pdn 06.04.99 CTS18546-2: fix of self-intersection is repeated while fixed
32 //#3  smh 01.04.99 S4163: Overflow   
33 //#4  szv          S4163: optimization
34 //:r7 abv 12.04.99 S4136: FixLk: extend cases of adding degenerated edge
35 //:r8 abv 12.04.99 PRO10107.stp #2241: try increasing tolerance of edge for fix IE
36 //:s2 abv 21.04.99 S4136, PRO7978.igs: FixLacking extended to be able to bend pcurves
37 //szv#9:S4244:19Aug99 Methods FixGaps3d and FixGaps2d were introduced
38 //#15 smh 03.04.2000 PRO19800. Checking degenerated point on a surface of revolution.
39 // sln 25.09.2001  checking order of 3d and 2d representation curves  
40 // van 19.10.2001  fix of non-adjacent self-intersection corrected to agree with BRepCheck
41 // skl 07.03.2002 fix for bug OCC180
42 // skl 15.05.2002 for OCC208 (if few edges have reference to 
43 //                one pcurve we make replace pcurve)
44 // PTV 26.06.2002  Remove regressions after fix OCC450
45
46 #include <ShapeFix_Wire.hxx>
47
48 #include <Adaptor3d_CurveOnSurface.hxx>
49 #include <Bnd_Array1OfBox2d.hxx>
50 #include <Bnd_Box2d.hxx>
51 #include <BndLib_Add2dCurve.hxx>
52 #include <BRep_Builder.hxx>
53 #include <BRep_GCurve.hxx>
54 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
55 #include <BRep_TEdge.hxx>
56 #include <BRep_Tool.hxx>
57 #include <BRepBuilderAPI_MakeEdge.hxx>
58 #include <BRepBuilderAPI_MakeVertex.hxx>
59 #include <BRepTools.hxx>
60 #include <Geom2d_BSplineCurve.hxx>
61 #include <Geom2d_Curve.hxx>
62 #include <Geom2d_Line.hxx>
63 #include <Geom2d_TrimmedCurve.hxx>
64 #include <Geom2dAdaptor_Curve.hxx>
65 #include <Geom2dConvert.hxx>
66 #include <Geom_BSplineCurve.hxx>
67 #include <Geom_Curve.hxx>
68 #include <Geom_OffsetCurve.hxx>
69 #include <Geom_Plane.hxx>
70 #include <Geom_SphericalSurface.hxx>
71 #include <Geom_Surface.hxx>
72 #include <Geom_SurfaceOfRevolution.hxx>
73 #include <Geom_TrimmedCurve.hxx>
74 #include <GeomAdaptor_Curve.hxx>
75 #include <GeomAdaptor_Surface.hxx>
76 #include <GeomAPI.hxx>
77 #include <GeomAPI_ProjectPointOnCurve.hxx>
78 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
79 #include <gp_Pln.hxx>
80 #include <IntRes2d_IntersectionPoint.hxx>
81 #include <IntRes2d_SequenceOfIntersectionPoint.hxx>
82 #include <Message_Msg.hxx>
83 #include <Precision.hxx>
84 #include <ShapeAnalysis.hxx>
85 #include <ShapeAnalysis_Curve.hxx>
86 #include <ShapeAnalysis_Edge.hxx>
87 #include <ShapeAnalysis_Surface.hxx>
88 #include <ShapeAnalysis_TransferParameters.hxx>
89 #include <ShapeAnalysis_TransferParametersProj.hxx>
90 #include <ShapeAnalysis_Wire.hxx>
91 #include <ShapeAnalysis_WireOrder.hxx>
92 #include <ShapeBuild_Edge.hxx>
93 #include <ShapeBuild_ReShape.hxx>
94 #include <ShapeBuild_Vertex.hxx>
95 #include <ShapeConstruct_ProjectCurveOnSurface.hxx>
96 #include <ShapeExtend.hxx>
97 #include <ShapeExtend_WireData.hxx>
98 #include <ShapeFix.hxx>
99 #include <ShapeFix_Edge.hxx>
100 #include <ShapeFix_IntersectionTool.hxx>
101 #include <ShapeFix_SplitTool.hxx>
102 #include <Standard_ErrorHandler.hxx>
103 #include <Standard_Failure.hxx>
104 #include <Standard_Type.hxx>
105 #include <TColgp_Array1OfPnt.hxx>
106 #include <TColgp_SequenceOfPnt.hxx>
107 #include <TColStd_Array1OfInteger.hxx>
108 #include <TColStd_Array1OfReal.hxx>
109 #include <TColStd_HSequenceOfReal.hxx>
110 #include <TopExp_Explorer.hxx>
111 #include <TopLoc_Location.hxx>
112 #include <TopoDS.hxx>
113 #include <TopoDS_Edge.hxx>
114 #include <TopoDS_Face.hxx>
115 #include <TopoDS_Vertex.hxx>
116 #include <TopoDS_Wire.hxx>
117 #include <TopTools_Array1OfShape.hxx>
118 #include <TopTools_HSequenceOfShape.hxx>
119
120 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wire,ShapeFix_Root)
121
122 //S4135
123 //#######################################################################
124 //  Constructors, initializations, modes, querying
125 //#######################################################################
126 //=======================================================================
127 //function : ShapeFix_Wire
128 //purpose  : 
129 //=======================================================================
130 ShapeFix_Wire::ShapeFix_Wire() : myMaxTailAngleSine(0), myMaxTailWidth(-1)
131 {
132   myFixEdge = new ShapeFix_Edge;
133   myAnalyzer = new ShapeAnalysis_Wire;
134   ClearModes();
135   ClearStatuses();
136   myStatusRemovedSegment = Standard_False;
137 }
138
139 //=======================================================================
140 //function : ShapeFix_Wire
141 //purpose  : 
142 //=======================================================================
143
144 ShapeFix_Wire::ShapeFix_Wire (
145   const TopoDS_Wire& wire,
146   const TopoDS_Face &face,
147   const Standard_Real prec) : myMaxTailAngleSine(0), myMaxTailWidth(-1)
148 {
149   myFixEdge = new ShapeFix_Edge;
150   myAnalyzer = new ShapeAnalysis_Wire;
151   ClearModes();
152   SetMaxTolerance ( prec );
153   myStatusRemovedSegment = Standard_False;
154   Init ( wire, face, prec );
155 }
156
157 //=======================================================================
158 //function : SetPrecision
159 //purpose  : 
160 //=======================================================================
161
162 void ShapeFix_Wire::SetPrecision (const Standard_Real prec) 
163 {
164   ShapeFix_Root::SetPrecision ( prec );
165   myAnalyzer->SetPrecision ( prec );
166 }
167  
168 //=======================================================================
169 //function : SetMaxTailAngle
170 //purpose  :
171 //=======================================================================
172 void ShapeFix_Wire::SetMaxTailAngle(const Standard_Real theMaxTailAngle)
173 {
174   myMaxTailAngleSine = Sin(theMaxTailAngle);
175   myMaxTailAngleSine = (myMaxTailAngleSine >= 0) ? myMaxTailAngleSine : 0;
176 }
177
178 //=======================================================================
179 //function : SetMaxTailWidth
180 //purpose  :
181 //=======================================================================
182 void ShapeFix_Wire::SetMaxTailWidth(const Standard_Real theMaxTailWidth)
183 {
184   myMaxTailWidth = theMaxTailWidth;
185 }
186
187 //=======================================================================
188 //function : ClearModes
189 //purpose  : 
190 //=======================================================================
191
192 void ShapeFix_Wire::ClearModes()
193 {
194   myTopoMode = Standard_False;
195   myGeomMode = Standard_True;
196   myClosedMode = Standard_True;
197   myPreference2d = Standard_True;
198   myFixGapsByRanges = Standard_False;
199
200   myRemoveLoopMode = -1;
201
202   myFixReversed2dMode = -1;
203   myFixRemovePCurveMode = -1;
204   myFixRemoveCurve3dMode = -1;
205   myFixAddPCurveMode = -1;
206   myFixAddCurve3dMode = -1;
207   myFixSeamMode = -1;
208   myFixShiftedMode = -1;
209   myFixSameParameterMode = -1;
210   myFixVertexToleranceMode = -1;
211
212   myFixNotchedEdgesMode = -1;
213   myFixSelfIntersectingEdgeMode = -1;
214   myFixIntersectingEdgesMode = -1;
215   myFixNonAdjacentIntersectingEdgesMode = -1;
216   myFixTailMode = 0;
217
218   myFixReorderMode = -1;
219   myFixSmallMode = -1;
220   myFixConnectedMode = -1;
221   myFixEdgeCurvesMode = -1;
222   myFixDegeneratedMode = -1;
223   myFixSelfIntersectionMode = -1;
224   myFixLackingMode = -1;
225   myFixGaps3dMode = -1;
226   myFixGaps2dMode = -1;
227 }
228
229 //=======================================================================
230 //function : ClearStatuses
231 //purpose  : 
232 //=======================================================================
233
234 void ShapeFix_Wire::ClearStatuses()
235 {
236   Standard_Integer emptyStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
237
238   myLastFixStatus          = emptyStatus;
239
240   myStatusReorder          = emptyStatus;
241   myStatusSmall            = emptyStatus;
242   myStatusConnected        = emptyStatus;
243   myStatusEdgeCurves       = emptyStatus;
244   myStatusDegenerated      = emptyStatus;
245   myStatusSelfIntersection = emptyStatus;
246   myStatusLacking          = emptyStatus;
247   myStatusGaps3d           = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
248   myStatusGaps2d           = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
249   myStatusClosed           = emptyStatus;
250   myStatusNotches = emptyStatus;
251   myStatusFixTails = emptyStatus;
252 }
253
254 //=======================================================================
255 //function : Init
256 //purpose  : 
257 //=======================================================================
258
259 void ShapeFix_Wire::Init (const TopoDS_Wire& wire, 
260                           const TopoDS_Face &face, const Standard_Real prec) 
261 {
262   Load ( wire );
263   SetFace ( face );
264   SetPrecision ( prec );
265 }
266
267 //=======================================================================
268 //function : Init
269 //purpose  : 
270 //=======================================================================
271
272 void ShapeFix_Wire::Init (const Handle(ShapeAnalysis_Wire)& saw) 
273 {
274   ClearStatuses();
275   myAnalyzer = saw;
276   myShape.Nullify();
277 //  SetPrecision ( saw.Precision() );
278 }
279
280 //=======================================================================
281 //function : Load
282 //purpose  : 
283 //=======================================================================
284
285 void ShapeFix_Wire::Load (const TopoDS_Wire& wire) 
286 {
287   ClearStatuses();
288
289   TopoDS_Wire W = wire;
290   if ( ! Context().IsNull() ) {
291     TopoDS_Shape S = Context()->Apply ( wire );
292     W = TopoDS::Wire ( S );
293   }
294
295   myAnalyzer->Load ( W );
296   myShape = wire;
297 }
298
299 //=======================================================================
300 //function : Load
301 //purpose  : 
302 //=======================================================================
303
304 void ShapeFix_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd) 
305 {
306   ClearStatuses();
307   myAnalyzer->Load ( sbwd );
308   if ( ! Context().IsNull() ) UpdateWire();
309   myShape.Nullify();
310 }
311
312 //=======================================================================
313 //function : NbEdges
314 //purpose  : 
315 //=======================================================================
316
317 Standard_Integer ShapeFix_Wire::NbEdges() const
318 {
319   Handle(ShapeExtend_WireData) sbwd = myAnalyzer->WireData();
320   return sbwd.IsNull() ? 0 : sbwd->NbEdges();
321 }
322
323 //#######################################################################
324 //  Fixing methods of API level
325 //#######################################################################
326   
327 //=======================================================================
328 //function : Perform
329 //purpose  : This method performs all the available fixes.
330 //           If some fix is turned on or off explicitly by the flag,
331 //           it is called or not depending on that flag
332 //           Else (i.e. if flag is default) fix is called depending on the 
333 //           situation: default is True, but some fixes are not called or
334 //           are limited if order of edges in the wire is not OK
335 //=======================================================================
336
337 Standard_Boolean ShapeFix_Wire::Perform() 
338 {
339   ClearStatuses();
340   if ( ! IsLoaded() ) return Standard_False;
341
342   if ( !Context().IsNull() )
343     myFixEdge->SetContext( Context() );
344
345   Standard_Boolean Fixed = Standard_False;
346   
347   // FixReorder is first, because as a rule wire is required to be ordered
348   // We shall analyze the order of edges in the wire and set appropriate 
349   // status even if FixReorder should not be called (if it is forbidden)
350
351   ShapeAnalysis_WireOrder sawo;
352   Standard_Boolean ReorderOK = ( myAnalyzer->CheckOrder ( sawo, myClosedMode ) ==0 );
353   if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) { 
354     if(FixReorder()) Fixed = Standard_True; 
355     ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
356   }
357
358   // FixSmall is allowed to change topology only if mode is set and FixReorder 
359   // did not failed
360   if ( NeedFix ( myFixSmallMode, myTopoMode ) ) {
361     if ( FixSmall ( ! myTopoMode || ! ReorderOK, MinTolerance() ) ) {
362       Fixed = Standard_True;
363       // retry reorder if necessary (after FixSmall it can work better)
364       if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) { 
365         FixReorder();
366         ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
367       }
368     }
369   }
370
371   if ( NeedFix ( myFixConnectedMode, ReorderOK ) ) {
372     if ( FixConnected() ) Fixed = Standard_True;
373   }
374
375   if ( NeedFix ( myFixEdgeCurvesMode ) ) {
376     Standard_Integer savFixShiftedMode = myFixShiftedMode;
377     // turn out FixShifted if reorder not done
378     if ( myFixShiftedMode == -1 && ! ReorderOK ) myFixShiftedMode = 0; 
379     if ( FixEdgeCurves() ) Fixed = Standard_True;
380     myFixShiftedMode = savFixShiftedMode;
381   }
382   
383   if ( NeedFix ( myFixDegeneratedMode ) ) {
384     if ( FixDegenerated() ) Fixed = Standard_True; // ?? if ! ReorderOK ??
385   }
386   
387   //pdn - temporary to test
388   if (myFixTailMode <= 0 && NeedFix(myFixNotchedEdgesMode, ReorderOK))
389   {
390     Fixed |= FixNotchedEdges();
391     if(Fixed) FixShifted(); //skl 07.03.2002 for OCC180
392   }
393     
394   if (myFixTailMode != 0)
395   {
396     if (FixTails())
397     {
398       Fixed =Standard_True;
399       FixShifted();
400     }
401   }
402
403   if ( NeedFix ( myFixSelfIntersectionMode, myClosedMode ) ) {
404     Standard_Integer savFixIntersectingEdgesMode = myFixIntersectingEdgesMode;
405     // switch off FixIntEdges if reorder not done
406     if ( myFixIntersectingEdgesMode == -1 && ! ReorderOK ) 
407          myFixIntersectingEdgesMode = 0; 
408     if ( FixSelfIntersection() ) Fixed = Standard_True;
409     FixReorder();
410     myFixIntersectingEdgesMode = savFixIntersectingEdgesMode;
411   }
412
413   if ( NeedFix ( myFixLackingMode, ReorderOK ) ) {
414     if ( FixLacking() ) Fixed = Standard_True;
415   }
416
417   // TEMPORARILY without special mode !!!
418   Handle(ShapeExtend_WireData) sbwd = WireData();
419   for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++)
420     if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge), Face()) ) 
421     {
422       Fixed = Standard_True;
423     }
424
425   if (  !Context().IsNull() )
426     UpdateWire();
427
428   return Fixed;
429 }
430
431 //=======================================================================
432 //function : FixReorder
433 //purpose  : 
434 //=======================================================================
435
436 Standard_Boolean ShapeFix_Wire::FixReorder() 
437 {
438   myStatusReorder = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
439   if ( ! IsLoaded() ) return Standard_False;
440
441   // fix in 3d
442   ShapeAnalysis_WireOrder sawo;
443   myAnalyzer->CheckOrder ( sawo, myClosedMode, Standard_True );
444   
445   //:abv revolCuts.sat -23: in case of bi-periodic surface check case
446   // of reversed wire specifically. This is necessary because degenerated
447   // cases are possible when direct evaluation will give bad result.
448   Standard_Boolean isReorder = Standard_False;
449   if ( sawo.Status() != 0 &&
450        ! myAnalyzer->Surface().IsNull() &&
451        myAnalyzer->Surface()->Surface()->IsUPeriodic() &&
452        myAnalyzer->Surface()->Surface()->IsVPeriodic() ) {
453     Handle(ShapeExtend_WireData) sbwd2 = new ShapeExtend_WireData;
454     for ( Standard_Integer i=WireData()->NbEdges(); i >=1; i-- )
455       sbwd2->Add ( WireData()->Edge(i) );
456     ShapeAnalysis_WireOrder sawo2;
457     ShapeAnalysis_Wire analyzer2 ( sbwd2, myAnalyzer->Face(), Precision() );
458     analyzer2.CheckOrder ( sawo2, myClosedMode, Standard_True );
459     if ( ( sawo2.Status() >=0 && sawo2.Status() < sawo.Status() ) || 
460          ( sawo.Status()   <0 && sawo2.Status() > sawo.Status() ) ) {
461       WireData()->Init ( sbwd2 );
462       sawo = sawo2;
463       isReorder = Standard_True;
464     }
465   }
466   
467   FixReorder ( sawo );
468   
469   if ( LastFixStatus ( ShapeExtend_FAIL ) )
470     myStatusReorder |= ShapeExtend::EncodeStatus ( LastFixStatus ( ShapeExtend_FAIL1 ) ? 
471                                                  ShapeExtend_FAIL1 : ShapeExtend_FAIL2 );
472   if ( ! LastFixStatus ( ShapeExtend_DONE )&& !isReorder ) return Standard_False;
473   
474   myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
475   if ( sawo.Status() ==2 || sawo.Status() ==-2 ) 
476     myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
477   if ( sawo.Status() <0 ) 
478     myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
479   if ( sawo.Status() == 3)
480     myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//only shifted
481   return Standard_True;
482 }
483
484 //=======================================================================
485 //function : FixSmall
486 //purpose  : 
487 //=======================================================================
488
489 Standard_Integer ShapeFix_Wire::FixSmall (const Standard_Boolean lockvtx,
490                                              const Standard_Real precsmall) 
491 {
492   myStatusSmall = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
493   if ( ! IsLoaded() ) return Standard_False;
494   
495   for ( Standard_Integer i = NbEdges(); i >0; i-- ) {
496     FixSmall ( i, lockvtx, precsmall );
497     myStatusSmall |= myLastFixStatus;
498   }
499
500   return StatusSmall ( ShapeExtend_DONE );
501
502 }
503
504 //=======================================================================
505 //function : FixConnected
506 //purpose  : 
507 //=======================================================================
508
509 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec) 
510 {
511   myStatusConnected = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
512   if ( ! IsLoaded() ) return Standard_False;
513   
514   Standard_Integer stop = ( myClosedMode ? 0 : 1 );
515   for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
516     FixConnected ( i, prec );
517     myStatusConnected |= myLastFixStatus;
518   }
519
520   return StatusConnected ( ShapeExtend_DONE );
521 }
522
523 //=======================================================================
524 //function : FixEdgeCurves
525 //purpose  : 
526 //=======================================================================
527
528 Standard_Boolean ShapeFix_Wire::FixEdgeCurves() 
529 {
530   myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
531   if ( ! IsLoaded() ) return Standard_False;
532   Standard_Boolean isReady = IsReady();
533
534   Handle(ShapeExtend_WireData) sbwd = WireData();
535   Standard_Integer i, nb = sbwd->NbEdges();
536   TopoDS_Face face = Face();
537   Handle(ShapeFix_Edge) theAdvFixEdge = myFixEdge;
538   if (theAdvFixEdge.IsNull()) myFixReversed2dMode = Standard_False;
539
540   // fix revesred 2d / 3d curves
541   if ( isReady && NeedFix ( myFixReversed2dMode ) ) {
542     for ( i=1; i <= nb; i++ ) {
543       theAdvFixEdge->FixReversed2d ( sbwd->Edge(i), face ); 
544       if ( theAdvFixEdge->Status ( ShapeExtend_DONE ) ) 
545         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
546       if ( theAdvFixEdge->Status ( ShapeExtend_FAIL ) ) 
547         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
548     }
549   }
550   
551   // add / remove pcurve
552   if ( isReady && NeedFix ( myFixRemovePCurveMode, Standard_False ) ) {
553     for ( i=1; i <= nb; i++ ) {
554       myFixEdge->FixRemovePCurve ( sbwd->Edge(i), face );
555       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
556         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
557       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
558         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
559     }
560   }
561
562   if ( isReady && NeedFix ( myFixAddPCurveMode ) ) {
563     Standard_Integer overdegen = 0; //:c0
564     for ( i=1; i <= nb; i++ ) {
565       myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i), 
566                          myAnalyzer->Surface(), Precision() );
567       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
568         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
569       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
570         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
571
572       //if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 )
573       //     && BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
574       if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 ) ) {
575         // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
576         if ( ! Context().IsNull() ) { 
577           ShapeBuild_Edge sbe;
578           TopoDS_Edge E = sbwd->Edge ( i );
579           ShapeAnalysis_Curve SAC;
580           Standard_Real a, b;
581           Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
582           Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
583           Standard_Integer nbs = S->NbSingularities(MinTolerance());
584           GeomAdaptor_Curve GAC ( C, a, b );
585           TColStd_SequenceOfReal seq;
586           for (Standard_Integer j=1; j <= nbs; j++) {
587             Standard_Real Preci;
588             gp_Pnt2d pd1, pd2;
589             gp_Pnt P3d, pr;
590             Standard_Real par1, par2, split;
591             Standard_Boolean tmpUIsoDeg;
592             S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
593             if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
594               if ( split - a > ::Precision::PConfusion() &&
595                    b - split > ::Precision::PConfusion() ) {
596                 Standard_Integer k;
597                 for ( k=1; k <= seq.Length(); k++ ) {
598                   if ( split < seq(k)-::Precision::PConfusion() ) {
599                     seq.InsertBefore ( k, split );
600                     break;
601                   }
602                   else if ( split < seq(k)+::Precision::PConfusion() ) break;
603                 }
604                 if ( k > seq.Length() ) seq.Append ( split );
605               }
606             }
607           }
608           if ( seq.Length() >0 ) { // supposed that edge is SP
609 #ifdef OCCT_DEBUG
610             std::cout << "Edge going over singularity detected; splitted" << std::endl;
611 #endif
612       Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
613       E.Orientation ( TopAbs_FORWARD );
614
615       //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
616       //  sbe.RemovePCurve ( E, face );
617
618       //10.04.2003 skl for using trimmed lines as pcurves
619       ShapeAnalysis_Edge sae;
620       if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
621         sbe.RemovePCurve ( E, face );
622       else {
623         if(sae.HasPCurve(E,face)) {
624           Handle(Geom2d_Curve) C2d;
625           Standard_Real fp2d,lp2d;
626           if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
627             if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
628               sbe.RemovePCurve(E,face);
629           }
630         }
631       }
632
633 //    myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
634       BRep_Builder B;
635       TopoDS_Vertex V1, V2, V;
636       //ShapeAnalysis_Edge sae;
637       V1 = sae.FirstVertex ( E );
638       V2 = sae.LastVertex ( E );
639         
640       Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
641       for ( Standard_Integer k=0; k <= seq.Length(); k++ )
642       {
643         Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
644         if ( k < seq.Length() )
645         {
646           B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
647           //try increase tolerance before splitting
648           Standard_Real aDist = BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V));
649           if (aDist < BRep_Tool::Tolerance(V1) * 1.01) {
650             B.UpdateVertex(V1, Max(aDist, BRep_Tool::Tolerance(V1)));
651             a = split;
652             V1 = V;
653             continue;
654           }
655           else
656           {
657             aDist = BRep_Tool::Pnt(V2).Distance(BRep_Tool::Pnt(V));
658             if (aDist < BRep_Tool::Tolerance(V2) * 1.01) {
659               B.UpdateVertex(V, Max(aDist, BRep_Tool::Tolerance(V2)));
660               b = split;
661               V2 = V;
662               continue;
663             }
664           }
665         }
666         else
667         {
668           V = V2;
669         }
670
671         TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
672         if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
673           //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
674           B.Range ( edge, a, split );
675           sw->Add ( edge );
676         }
677         else {
678           //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
679           Handle(ShapeAnalysis_TransferParameters) sftp =
680             new ShapeAnalysis_TransferParameters(E,face);
681           sftp->TransferRange(edge, a, split, Standard_False);
682           sw->Add(edge);
683         }
684         //sw->Add(edge);
685         a = split;
686         V1 = V;
687       }
688       if ( ! isFwd ) {
689         sw->Reverse();
690         E.Orientation ( TopAbs_REVERSED );
691       }
692       Context()->Replace ( E, sw->Wire() );
693       UpdateWire();
694       nb = sbwd->NbEdges();
695       i--;
696       continue;
697     }
698         }
699         
700         overdegen = i;
701       }
702     }
703
704     //:c0 abv 20 Feb 98: treat case of curve going over degenerated pole and seam
705     if ( overdegen && myAnalyzer->Surface()->IsUClosed(Precision()) ) {
706       ShapeBuild_Edge sbe;
707       Standard_Real URange, SUF, SUL, SVF, SVL;
708       myAnalyzer->Surface()->Bounds(SUF, SUL, SVF, SVL);
709       URange = (Abs(SUL - SUF));
710       gp_XY vec(0,0);
711       ShapeAnalysis_Edge sae;
712       Standard_Integer k;
713       for ( k = 1; k <= nb; k++) {
714         Standard_Real cf, cl;
715         Handle(Geom2d_Curve) c2d;
716         if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
717         vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
718       }
719       if ( k > nb && Abs ( Abs ( vec.X() ) - URange ) < 0.1 * URange ) {
720         sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
721         myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
722         myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
723       }
724 #ifdef OCCT_DEBUG
725       std::cout << "Edge going over singularity detected; pcurve adjusted" << std::endl;
726 #endif
727     }
728   }
729
730   // add / remove pcurve
731   if ( isReady && NeedFix ( myFixRemoveCurve3dMode, Standard_False ) ) {
732     for ( i=1; i <= nb; i++ ) {
733       myFixEdge->FixRemoveCurve3d ( sbwd->Edge(i) );
734       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
735         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
736       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
737         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
738     }
739   }
740   if ( NeedFix ( myFixAddCurve3dMode ) ) {
741     for ( i=1; i <= nb; i++ ) {
742       myFixEdge->FixAddCurve3d ( sbwd->Edge(i) );
743       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
744         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
745       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) {
746         //:abv 29.08.01: Spatial_firex_lofting.sat: if 3d curve cannot
747         // be built because edge has no pcurves either, remove that edge
748         Handle(Geom2d_Curve) C;
749         Handle(Geom_Surface) S;
750         TopLoc_Location L;
751         Standard_Real first = 0., last = 0.;
752         BRep_Tool::CurveOnSurface ( sbwd->Edge(i), C, S, L, first, last );
753         if ( C.IsNull() || Abs (last - first) < Precision::PConfusion())
754         {
755           SendWarning ( sbwd->Edge ( i ), Message_Msg ( "FixWire.FixCurve3d.Removed" ) );// Incomplete edge (with no pcurves or 3d curve) removed
756           sbwd->Remove ( i-- );
757           nb--;
758           myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
759           if (i == nb)
760           {
761             FixClosed (Precision());
762           }
763           else
764           {
765             FixConnected (i + 1, Precision());
766           }
767         }
768         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
769       }
770     }
771   }
772   
773   // fix seam
774   if ( isReady && NeedFix ( myFixSeamMode, Standard_False ) ) {
775     for ( i=1; i <= nb; i++ ) {
776       FixSeam ( i );
777       if ( LastFixStatus ( ShapeExtend_DONE ) ) 
778         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
779       if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
780         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
781     }
782   }
783
784   // fix shifted
785   if ( isReady && NeedFix ( myFixShiftedMode ) ) {
786     FixShifted();
787     if ( LastFixStatus ( ShapeExtend_DONE ) ) 
788       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
789     if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
790       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL7 );
791   }
792
793   // fix same parameter
794   if ( isReady && NeedFix ( myFixSameParameterMode ) ){
795     for ( i=1; i <= nb; i++ ) {
796       // skl 28.10.2004 for OCC6366 - check SameRange
797       ShapeAnalysis_Edge sae;
798       Standard_Real First, Last;
799       Handle(Geom_Curve) tmpc3d = BRep_Tool::Curve(sbwd->Edge(i), First, Last);
800       if(sae.HasPCurve(sbwd->Edge(i),face)) {
801         Handle(Geom2d_Curve) C2d;
802         Standard_Real fp2d,lp2d;
803         if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d, Standard_False)) {
804           if( fabs(First-fp2d)>Precision::PConfusion() ||
805               fabs(Last-lp2d)>Precision::PConfusion()    ) 
806           {
807             BRep_Builder B;
808             B.SameRange(sbwd->Edge(i),Standard_False);
809           }
810           else if(!sae.CheckPCurveRange(First, Last, C2d))
811           {
812             //Replace pcurve
813             TopLoc_Location L;
814             const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
815             ShapeBuild_Edge().RemovePCurve (sbwd->Edge(i),  S, L);
816             myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i), 
817                          myAnalyzer->Surface(), Precision() );
818             if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
819               myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
820             if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
821               myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
822           }
823         }
824       }
825       myFixEdge->FixSameParameter ( sbwd->Edge(i), Face());
826       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
827         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
828       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
829         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
830     }
831   }
832
833   //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
834   // Update with face is needed for plane surfaces (w/o stored pcurves)
835   if ( NeedFix ( myFixVertexToleranceMode ) )
836   {
837     for ( i=1; i <= nb; i++)
838     {
839       myFixEdge->FixVertexTolerance (sbwd->Edge (i), Face());
840       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
841         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
842       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
843         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
844     }
845     if (!Context().IsNull() )
846       UpdateWire();
847   }
848   
849
850   return StatusEdgeCurves ( ShapeExtend_DONE );
851 }
852
853 //=======================================================================
854 //function : FixDegenerated
855 //purpose  : 
856 //=======================================================================
857
858 Standard_Boolean ShapeFix_Wire::FixDegenerated() 
859 {
860   myStatusDegenerated = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
861   if ( ! IsReady() ) return Standard_False;
862   
863 //  if ( ! myAnalyzer->Surface()->HasSingularities ( Precision() ) ) return;
864
865   Standard_Integer lastcoded = -1, prevcoded = 0;
866   Standard_Integer stop = ( myClosedMode ? 0 : 1 );
867   for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
868     FixDegenerated ( i );
869     myStatusDegenerated |= myLastFixStatus;
870     //:r0 abv 19 Mar 99: PRO7226.stp #489490: remove duplicated degenerated edges
871     Standard_Integer coded = ( LastFixStatus ( ShapeExtend_DONE2 ) ? 1 : 0 );
872     if ( lastcoded ==-1 ) lastcoded = coded;
873     if ( coded && ( prevcoded || ( i ==1 && lastcoded ) ) && NbEdges() >1 ) {
874       Handle(ShapeExtend_WireData) sbwd = WireData();
875       BRep_Builder B;
876       sbwd->Remove ( i );
877       if ( ! prevcoded ) i = NbEdges();
878       B.Degenerated ( sbwd->Edge ( i++ ), Standard_False );
879       prevcoded = 0;
880     }
881     else prevcoded = coded; 
882   }
883
884   return StatusDegenerated ( ShapeExtend_DONE );
885 }
886
887
888 //=======================================================================
889 //function : FixSelfIntersection
890 //purpose  : Applies FixSelfIntersectingEdge and FixIntersectingEdges
891 //           and removes wrong edges
892 //=======================================================================
893
894 Standard_Boolean ShapeFix_Wire::FixSelfIntersection() 
895 {
896   myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
897   if ( ! IsReady() ) return Standard_False;
898
899   Handle(ShapeExtend_WireData) sbwd = WireData();
900   Standard_Integer nb = sbwd->NbEdges();
901   
902   if ( NeedFix ( myFixSelfIntersectingEdgeMode ) ) {
903     if (myRemoveLoopMode<1)
904       for ( Standard_Integer num=1; num <=nb; num++ ) 
905       {
906         FixSelfIntersectingEdge ( num );
907         myStatusSelfIntersection |= myLastFixStatus;
908       }
909     else if (myRemoveLoopMode==1)
910     {
911       for ( Standard_Integer num=1; num <=nb; num++ )
912       {
913         FixSelfIntersectingEdge ( num );
914         myStatusSelfIntersection |= myLastFixStatus;
915         if(nb<sbwd->NbEdges()) num--;
916         nb = sbwd->NbEdges();
917       }
918       FixClosed(Precision());
919     }
920   }
921   
922   if ( NeedFix ( myFixIntersectingEdgesMode ) )
923   {
924     Standard_Integer num = ( myClosedMode ? 1 : 2 );
925     for ( ; nb >1 && num <= nb; num++ )
926     {
927       FixIntersectingEdges ( num );
928       if ( LastFixStatus ( ShapeExtend_FAIL1 ) ) 
929         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
930       if ( LastFixStatus ( ShapeExtend_FAIL2 ) ) 
931         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
932       if ( ! LastFixStatus ( ShapeExtend_DONE ) ) continue;
933
934       if ( LastFixStatus ( ShapeExtend_DONE1 ) ) 
935         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
936       if ( LastFixStatus ( ShapeExtend_DONE2 ) ) 
937         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
938       if(LastFixStatus (ShapeExtend_DONE6))
939         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
940
941       if ( /*! myTopoMode ||*/ nb < 3 )
942       {
943         //#86 rln 22.03.99 sim2.igs, entity 4292: After fixing of self-intersecting
944         //BRepCheck finds one more self-intersection not found by ShapeAnalysis
945         //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
946         
947         // if the tolerance was modified we should recheck the result, if it was enough
948         if ( LastFixStatus ( ShapeExtend_DONE7 ) ) //num--;
949           FixIntersectingEdges ( num );
950         continue;
951       }
952
953       if ( LastFixStatus ( ShapeExtend_DONE4 ) ) sbwd->Remove ( num );
954       if ( LastFixStatus ( ShapeExtend_DONE3 ) ) sbwd->Remove ( num >1 ? num-1 : nb+num-1 );
955       if ( LastFixStatus ( ShapeExtend_DONE4 ) ||
956            LastFixStatus ( ShapeExtend_DONE3 ) )
957       {
958         myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
959         num = ( myClosedMode ? 1 : 2 );
960         nb = sbwd->NbEdges();
961 #ifdef OCCT_DEBUG
962         std::cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Edge removed" << std::endl;
963 #endif
964       }
965       else
966       {
967         //#86 rln 22.03.99
968         //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
969         FixIntersectingEdges ( num );
970         /*if ( LastFixStatus ( ShapeExtend_DONE7 ) )*/
971         // Always revisit the fixed edge
972         //num--;
973       }
974     }
975     if ( !Context().IsNull())
976       UpdateWire();
977   }
978
979
980   //pdn 17.03.99 S4135 to avoid regression fixing not adjacent intersection
981   if ( NeedFix ( myFixNonAdjacentIntersectingEdgesMode ) ) {
982
983     ShapeFix_IntersectionTool ITool(Context(),Precision());
984     Standard_Integer NbSplit=0, NbCut=0,NbRemoved=0;
985     if(ITool.FixSelfIntersectWire(sbwd,myAnalyzer->Face(),NbSplit,NbCut,NbRemoved)) {
986       myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//gka 06.09.04
987     }
988     if( NbSplit>0 || NbRemoved>0 ) {
989       if(NbRemoved>0) myStatusRemovedSegment = Standard_True;
990       //Load(sbwd); commented by skl 29.12.2004 for OCC7624, instead this
991       //            string inserted following three strings:
992       myAnalyzer->Load ( sbwd );
993       if ( ! Context().IsNull() ) UpdateWire();
994       myShape.Nullify();
995     }
996 #ifdef OCCT_DEBUG
997     if (StatusSelfIntersection (ShapeExtend_DONE5))
998       std::cout<<"Warning: ShapeFix_Wire::FixIntersection: Non-adjacent intersection fixed (split-"
999         <<NbSplit<<", cut-"<<NbCut<<", removed-"<<NbRemoved<<")"<<std::endl;
1000 #endif    
1001
1002 /*
1003     Bnd_Array1OfBox2d boxes(1,nb);
1004     TopLoc_Location L;
1005     const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L);
1006     Handle(Geom2d_Curve) c2d;
1007     Standard_Real cf,cl;
1008     ShapeAnalysis_Edge sae;
1009     for(Standard_Integer i = 1; i <= nb; i++){
1010       TopoDS_Edge E = sbwd->Edge (i);
1011       if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) {
1012         Bnd_Box2d box;
1013         Geom2dAdaptor_Curve gac;
1014         Standard_Real aFirst = c2d->FirstParameter();
1015         Standard_Real aLast = c2d->LastParameter();
1016         if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
1017            && (cf < aFirst || cl > aLast)) {
1018           //pdn avoiding problems with segment in Bnd_Box
1019           gac.Load(c2d);
1020         }
1021         else
1022           gac.Load(c2d,cf,cl);
1023         BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
1024         boxes(i) = box;
1025       }
1026     }
1027     
1028     Standard_Boolean isFail = Standard_False, isDone = Standard_False;
1029     for(Standard_Integer num1 = 1; num1 < nb-1; num1++) {
1030       Standard_Integer fin = (num1 == 1 ? nb-1 : nb);
1031       for(Standard_Integer num2 = num1+2; num2 <= fin; num2++) 
1032         if(!boxes(num1).IsOut(boxes(num2))){
1033           FixIntersectingEdges (num1, num2);
1034           isFail |= LastFixStatus ( ShapeExtend_FAIL1 );
1035           isDone |= LastFixStatus ( ShapeExtend_DONE1 );
1036         }
1037     }
1038     
1039     if(isFail)
1040       myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1041     if(isDone)
1042       myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
1043 #ifdef OCCT_DEBUG
1044     if (StatusSelfIntersection (ShapeExtend_DONE5))
1045       std::cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Non ajacent intersection fixed" << std::endl;
1046 #endif    
1047 */
1048   }
1049
1050   return StatusSelfIntersection ( ShapeExtend_DONE );
1051 }
1052
1053
1054 //=======================================================================
1055 //function : FixLacking
1056 //purpose  : 
1057 //=======================================================================
1058
1059 Standard_Boolean ShapeFix_Wire::FixLacking ( const Standard_Boolean force ) 
1060 {
1061   myStatusLacking = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1062   if ( ! IsReady() ) return Standard_False;
1063   
1064   Standard_Integer start = ( myClosedMode ? 1 : 2 );
1065   for ( Standard_Integer i = start; i <= NbEdges(); i++ ) {
1066     FixLacking ( i, force );
1067     myStatusLacking |= myLastFixStatus;
1068   }
1069   
1070   return StatusLacking ( ShapeExtend_DONE );
1071 }
1072
1073
1074 //=======================================================================
1075 //function : FixClosed
1076 //purpose  : 
1077 //=======================================================================
1078
1079 Standard_Boolean ShapeFix_Wire::FixClosed (const Standard_Real prec) 
1080 {
1081   myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1082   if ( ! IsLoaded() || NbEdges() <1 ) return Standard_False;
1083   
1084   FixConnected ( 1, prec );
1085   if ( LastFixStatus ( ShapeExtend_DONE ) ) 
1086     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1087   if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
1088     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1089
1090   FixDegenerated ( 1 );
1091   if ( LastFixStatus ( ShapeExtend_DONE ) ) 
1092     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1093   if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
1094     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1095
1096   FixLacking ( 1 );
1097   if ( LastFixStatus ( ShapeExtend_DONE ) ) 
1098     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1099   if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
1100     myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1101   
1102   return StatusClosed ( ShapeExtend_DONE );
1103 }
1104
1105
1106 //#######################################################################
1107 //  Fixing methods of advanced level
1108 //#######################################################################
1109   
1110 //=======================================================================
1111 //function : FixReorder
1112 //purpose  : 
1113 //=======================================================================
1114
1115 Standard_Boolean ShapeFix_Wire::FixReorder (const ShapeAnalysis_WireOrder& wi) 
1116 {
1117   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1118   if ( ! IsLoaded() ) return Standard_False;
1119   
1120   Standard_Integer status = wi.Status();
1121   if ( status ==0 ) return Standard_False;
1122   if ( status <=-10 ) {
1123     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1124     return Standard_False;
1125   }
1126
1127   Handle(ShapeExtend_WireData) sbwd = WireData();
1128   Standard_Integer i, nb = sbwd->NbEdges();
1129   if ( nb != wi.NbEdges() ) {  
1130     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1131     return Standard_False;  
1132   }
1133   // D abord on protege
1134   for (i = 1; i <= nb; i ++) {
1135     if ( wi.Ordered(i) == 0 ) {  
1136       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1137       return Standard_False;  
1138     }
1139   }
1140
1141   Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape();
1142   for ( i=1; i <= nb; i++ )
1143     newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) );
1144   for ( i=1; i <= nb; i++ ) 
1145     sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i );
1146   
1147   myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1148   return Standard_True;
1149 }
1150
1151
1152 //=======================================================================
1153 //function : FixSmall
1154 //purpose  : 
1155 //=======================================================================
1156
1157 Standard_Boolean ShapeFix_Wire::FixSmall (const Standard_Integer num,
1158                                           const Standard_Boolean lockvtx,
1159                                           const Standard_Real precsmall) 
1160 {
1161   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1162   if ( ! IsLoaded() || NbEdges() <=1 ) return Standard_False;
1163
1164   // analysis:
1165   Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
1166   if (theAdvAnalyzer.IsNull()) return Standard_False;
1167   Standard_Integer n = ( num >0 ? num : NbEdges() );
1168   theAdvAnalyzer->CheckSmall ( n, precsmall );
1169   if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1170     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1171 //:n2    return Standard_False;
1172   }
1173
1174   if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1175
1176   // OUI cette edge est NULLE
1177
1178   if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) ) {
1179     // edge is small, but vertices are not the same..
1180     if ( lockvtx || ! myTopoMode ) {
1181       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1182       return Standard_False;
1183     }
1184     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1185   }
1186   else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1187
1188   // action: remove edge
1189   if ( ! Context().IsNull() ) 
1190     Context()->Remove(WireData()->Edge(n));
1191   SendWarning ( WireData()->Edge ( n ), Message_Msg ( "FixAdvWire.FixSmall.MSG0" ) ); //Small edge(s) removed
1192   WireData()->Remove ( n );
1193   
1194   // call FixConnected in the case if vertices of the small edge were not the same
1195   if ( LastFixStatus ( ShapeExtend_DONE2 ) ) {
1196     Standard_Integer savLastFixStatus = myLastFixStatus;
1197     //#43 rln 20.11.98 S4054 CTS18544 entity 21734 removing last edge
1198     FixConnected ( n <= NbEdges() ? n : 1, precsmall );
1199     if ( LastFixStatus ( ShapeExtend_FAIL ) )
1200       savLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1201     myLastFixStatus = savLastFixStatus;
1202   }
1203
1204   return Standard_True;
1205 }
1206
1207
1208 //=======================================================================
1209 //function : FixConnected
1210 //purpose  : 
1211 //=======================================================================
1212
1213 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Integer num,
1214                                               const Standard_Real prec) 
1215 {
1216   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1217   if ( ! IsLoaded() || NbEdges() <=0 ) return Standard_False;
1218
1219   // analysis
1220   
1221   myAnalyzer->CheckConnected ( num, prec < 0 ? MaxTolerance() : prec );
1222   if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1223     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1224   }
1225   if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1226
1227   // action: replacing vertex
1228   
1229   Handle(ShapeExtend_WireData) sbwd = WireData();
1230   Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
1231   Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
1232   TopoDS_Edge E1 = sbwd->Edge(n1);
1233   TopoDS_Edge E2 = sbwd->Edge(n2);
1234   
1235   ShapeAnalysis_Edge sae;
1236   TopoDS_Vertex V1 = sae.LastVertex (E1);
1237   TopoDS_Vertex V2 = sae.FirstVertex (E2);
1238   TopoDS_Vertex V;
1239   
1240   if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ) { // absolutely confused
1241     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1242     //#40 rln 18.11.98 S4054 BUC60035 entity 2393 (2-nd sub-curve is edge with the same vertex)
1243     if ( V2.IsSame ( sae.LastVertex (E2) ) ) {
1244       V = V2;
1245       if ( ! Context().IsNull() ) 
1246         Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1247     }
1248     else {
1249       V = V1;
1250       if ( ! Context().IsNull() ) 
1251         Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1252     }
1253   } 
1254   else {    // on moyenne ...
1255     if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) )
1256       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1257     else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1258     ShapeBuild_Vertex sbv; 
1259     V = sbv.CombineVertex ( V1, V2, 1.0001 );
1260     if ( ! Context().IsNull() ) {
1261       Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1262       Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1263     }
1264   }
1265
1266   // replace vertices to a new one
1267   ShapeBuild_Edge sbe;
1268   if ( sbwd->NbEdges() <2 ) {
1269     if(E2.Free() && myTopoMode) {
1270       BRep_Builder B;
1271       B.Remove(E2,sae.FirstVertex(E2));
1272       B.Remove(E2,sae.LastVertex(E2));
1273       B.Add(E2,V.Oriented(TopAbs_FORWARD));
1274       B.Add(E2,V.Oriented(TopAbs_REVERSED));
1275     }
1276     else {
1277       TopoDS_Edge tmpE = sbe.CopyReplaceVertices ( E2, V, V );
1278       sbwd->Set ( tmpE, n2 );
1279       if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE);
1280     }
1281   }
1282   else {
1283     if(E2.Free() &&E1.Free() && myTopoMode) {
1284       BRep_Builder B;
1285       B.Remove(E2,sae.FirstVertex(E2));
1286       B.Add(E2,V.Oriented(TopAbs_FORWARD));
1287       if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1288           sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1289         B.Remove(E1,sae.LastVertex(E1));
1290         B.Add(E1,V.Oriented(TopAbs_REVERSED));
1291       }
1292     }
1293     else {
1294       TopoDS_Edge tmpE2 = sbe.CopyReplaceVertices ( E2, V, TopoDS_Vertex() );
1295       sbwd->Set ( tmpE2, n2 );
1296       if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE2);
1297       if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1298           sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1299         TopoDS_Edge tmpE1 = sbe.CopyReplaceVertices ( E1, TopoDS_Vertex(), V );
1300         sbwd->Set (tmpE1, n1 );
1301         if ( ! Context().IsNull() ) Context()->Replace(E1,tmpE1);
1302       }
1303     }
1304   }
1305   if ( ! Context().IsNull() ) UpdateWire();
1306   
1307   return Standard_True;
1308 }
1309
1310
1311 //=======================================================================
1312 //function : FixSeam
1313 //purpose  : 
1314 //=======================================================================
1315
1316 Standard_Boolean ShapeFix_Wire::FixSeam (const Standard_Integer num) 
1317 {
1318   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1319   if ( ! IsReady() ) return Standard_False;
1320
1321   Handle(Geom2d_Curve) C1, C2;
1322   Standard_Real cf, cl;
1323   if ( ! myAnalyzer->CheckSeam (num, C1, C2, cf, cl) ) return Standard_False;
1324
1325   BRep_Builder B;
1326   TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
1327   B.UpdateEdge (E, C2,C1, Face(), 0.); //:S4136: BRep_Tool::Tolerance(E)
1328   B.Range (E, Face(),cf,cl);
1329   myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1330   
1331   return Standard_True;
1332 }
1333
1334 //=======================================================================
1335 //function : FixShifted
1336 //purpose  : fix parametric curves which may be shifted
1337 // to whole parametric range of closed surface as result of recomputing
1338 // from 3d representation.
1339 // This can be a curve on a seam or near it.
1340 // This function is to be called before FixDegenerated.
1341 // LIMITATION: this function cannot fix cases when, e.g., closed wire is 
1342 // composed of two meridians of the sphere and one of them is seam.
1343 // NOTE: wire is supposed to be closed and sorted !
1344 //=======================================================================
1345
1346 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edge 
1347 static void UpdateEdgeUVPoints (TopoDS_Edge &E, const TopoDS_Face &F)
1348 {
1349   Standard_Real first, last;
1350   BRep_Tool::Range ( E, F, first, last );
1351   BRep_Builder().Range ( E, F, first, last );
1352 }
1353
1354
1355 //=======================================================================
1356 //function : FixShifted
1357 //purpose  : 
1358 //=======================================================================
1359
1360 Standard_Boolean ShapeFix_Wire::FixShifted() 
1361 {
1362   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1363   if ( ! IsReady() ) return Standard_False;
1364
1365   Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
1366   //#78 rln 12.03.99 S4135: checking spatial closure with Precision
1367   Standard_Boolean uclosed = surf->IsUClosed(Precision());
1368   Standard_Boolean vclosed = surf->IsVClosed(Precision()) || surf->Surface()->IsKind (STANDARD_TYPE(Geom_SphericalSurface));
1369   //#67 rln 01.03.99 S4135: ims010.igs entity D11900 (2D contour is 2*PI higher than V range [-pi/2,p/2])
1370   
1371   // PTV 26.06.2002 begin
1372   // CTS18546-2.igs entity 2222: base curve is periodic and 2dcurve is shifted
1373   Standard_Boolean IsVCrvClosed = Standard_False;
1374   Standard_Real VRange = 1.;
1375   if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1376     Handle(Geom_SurfaceOfRevolution) aSurOfRev = Handle(Geom_SurfaceOfRevolution)::DownCast(surf->Surface());
1377     Handle(Geom_Curve) aBaseCrv = aSurOfRev->BasisCurve();
1378     while ( (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1379            (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1380       if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1381         aBaseCrv = Handle(Geom_OffsetCurve)::DownCast(aBaseCrv)->BasisCurve();
1382       if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1383         aBaseCrv = Handle(Geom_TrimmedCurve)::DownCast(aBaseCrv)->BasisCurve();
1384     }
1385     if (aBaseCrv->IsPeriodic()) {
1386       vclosed = Standard_True;
1387       VRange = aBaseCrv->Period();
1388       IsVCrvClosed = Standard_True;
1389 #ifdef OCCT_DEBUG
1390       std::cout << "Warning: ShapeFix_Wire::FixShifted set vclosed True for Surface of Revolution" << std::endl;
1391 #endif
1392     }
1393   }
1394   // PTV 26.06.2002 end
1395   if ( ! uclosed && ! vclosed ) return Standard_False; 
1396   
1397   Standard_Real URange, /*VRange,*/ SUF, SUL, SVF, SVL;
1398   surf->Surface()->Bounds ( SUF, SUL, SVF, SVL );
1399   Standard_Real SUMid, SVMid;
1400   SUMid = 0.5*(SUF+SUL);
1401   SVMid = 0.5*(SVF+SVL);
1402   if (uclosed) URange = Abs ( SUL - SUF );
1403   else         URange = RealLast();
1404   if (!IsVCrvClosed) {
1405     if (vclosed) VRange = Abs ( SVL - SVF );
1406     else         VRange = RealLast();
1407   }
1408   Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
1409
1410   Handle(ShapeExtend_WireData) sbwdOring = WireData();
1411   ShapeAnalysis_Edge sae;
1412   Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData;
1413   for ( Standard_Integer i=1; i <= sbwdOring->NbEdges(); i++ ) {
1414     TopoDS_Edge E1 = sbwdOring->Edge ( i );
1415     if ( BRep_Tool::Degenerated(E1) && !sae.HasPCurve(E1,Face()))
1416       continue;
1417     
1418     sbwd->Add(E1);
1419   }
1420   
1421   ShapeBuild_Edge sbe;
1422   Standard_Integer nb = sbwd->NbEdges();
1423   Standard_Boolean end = (nb == 0), degstop = Standard_False;
1424   Standard_Integer stop = nb;
1425   Standard_Integer degn2 = 0;
1426   gp_Pnt pdeg;
1427   //pdn 17.12.98 r0901_ec 38237 to shift wire at 0
1428  
1429   //GeomAdaptor_Surface& GAS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface(); //SK
1430   Bnd_Box2d box;
1431   for ( Standard_Integer n2=1, n1=nb; ! end; n1 = n2++ ) {
1432     if ( n2 > nb ) n2 = 1;
1433     if ( n2 == stop ) end = Standard_True;
1434
1435     TopoDS_Edge E1 = sbwd->Edge ( n1 );
1436     TopoDS_Edge E2 = sbwd->Edge ( n2 );
1437
1438     if ( BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2) )
1439     {
1440       if ( ! degstop )
1441       {
1442         stop = n2;
1443         degstop = Standard_True;
1444       }
1445       continue;
1446     }
1447
1448     TopoDS_Vertex V = sae.FirstVertex ( E2 );
1449     if (V.IsNull())
1450       continue;
1451
1452     gp_Pnt p = BRep_Tool::Pnt ( V );
1453   
1454     Standard_Real a1 = 0., b1 = 0., a2 = 0., b2 = 0.;
1455     Handle(Geom2d_Curve) c2d1, c2d2;
1456
1457     //:abv 29.08.01: torCuts.sat: distinguish degeneration by U and by V;
1458     // only corresponding move is prohibited
1459 //    Standard_Boolean isDeg = surf->IsDegenerated ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ) );
1460     Standard_Integer isDeg = 0;
1461     gp_Pnt2d degP1, degP2;
1462     Standard_Real degT1, degT2;
1463     if ( surf->DegeneratedValues ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ),
1464                                    degP1, degP2, degT1, degT2 ) )
1465       isDeg = ( Abs ( degP1.X() - degP2.X() ) > Abs ( degP1.Y() - degP2.Y() ) ? 1 : 2 );
1466
1467     // abv 23 Feb 00: UKI60107-6 210: additional check for near-degenerated case
1468     //smh#15 PRO19800. Check if the surface is surface of revolution.
1469     if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1470       if ( ! isDeg && ! vclosed ) {
1471         if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1472         gp_Pnt2d p1 ( SUF, c2d1->Value(b1).Y() );
1473         gp_Pnt2d p2 ( SUL, c2d1->Value(b1).Y() );
1474         if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1475              ! surf->IsDegenerated ( c2d1->Value(a1), c2d1->Value(b1), MaxTolerance(), 10 ) ) // abv 31.07.00: trj4_pm1-ec-214.stp #31274: still allow work if edge already exists 
1476           isDeg = 1;
1477       }
1478       if ( ! isDeg && ! uclosed ) {
1479         if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1480         gp_Pnt2d p1 ( c2d1->Value(b1).X(), SVF );
1481         gp_Pnt2d p2 ( c2d1->Value(b1).X(), SVL );
1482         if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1483              ! surf->IsDegenerated ( c2d1->Value(a1), c2d1->Value(b1), MaxTolerance(), 10 ) ) // abv 31.07.00: trj4_pm1-ec-214.stp #31274: still allow work if edge already exists 
1484           isDeg = 2;
1485       }
1486     }
1487
1488     if ( isDeg )
1489     {
1490       if ( ! degstop )
1491       {
1492         stop = n2;
1493         degstop = Standard_True;
1494       }
1495
1496       if ( ! degn2 )
1497       {
1498         degn2 = n2;
1499         pdeg = p;
1500       }
1501       else
1502       {
1503         if ( pdeg.SquareDistance(p) < Precision() * Precision() )
1504         {
1505           degn2 = n2;
1506           //if ( stop < n2 ) { stop = n2; degstop = Standard_True; }
1507         }
1508         else
1509         {
1510           Standard_Real ax1 = 0., bx1 = 0., ax2 = 0., bx2 = 0.;
1511           Handle(Geom2d_Curve) cx1, cx2;
1512           if (  ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1513                 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ||
1514                 ! sae.PCurve ( sbwd->Edge ( degn2 >1 ? degn2-1 : nb ), Face(), cx1, ax1, bx1, Standard_True ) ||
1515                 ! sae.PCurve ( sbwd->Edge ( degn2 ), Face(), cx2, ax2, bx2, Standard_True ) )
1516           {
1517             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1518             continue;
1519           }
1520           gp_Pnt2d pd1 = cx1->Value ( bx1 );
1521           gp_Pnt2d pd2 = cx2->Value ( ax2 );
1522           gp_Pnt2d pn1 = c2d1->Value ( b1 );
1523           gp_Pnt2d pn2 = c2d2->Value ( a2 );
1524           gp_Vec2d x(0.,0.); // shift vector
1525           Standard_Real period;
1526           if ( uclosed ) { x.SetX ( 1. ); period = URange; }
1527           else { x.SetY ( 1. ); period = VRange; }
1528           Standard_Real rot1 = ( pn1.XY() - pd2.XY() ) ^ x.XY();
1529           Standard_Real rot2 = ( pd1.XY() - pn2.XY() ) ^ x.XY();
1530           Standard_Real scld = ( pd2.XY() - pd1.XY() ) * x.XY();
1531           Standard_Real scln = ( pn2.XY() - pn1.XY() ) * x.XY();
1532           if (  rot1 * rot2 < -::Precision::PConfusion() && 
1533                 scld * scln < -::Precision::PConfusion() && 
1534                 Abs ( scln ) > 0.1 * period && Abs ( scld ) > 0.1 * period && 
1535                 rot1 * scld > ::Precision::PConfusion() && 
1536                 rot2 * scln > ::Precision::PConfusion() )
1537           {
1538             // abv 02 Mar 00: trying more sophisticated analysis (ie_exhaust-A.stp #37520)
1539             Standard_Real sign = ( rot2 >0 ? 1. : -1. );
1540             Standard_Real deep1 = Min ( sign * ( pn2.XY() * x.XY() ),
1541                                   Min ( sign * ( pd1.XY() * x.XY() ),
1542                                   Min ( sign * ( c2d2->Value(b2 ).XY() * x.XY() ),
1543                                   Min ( sign * (  cx1->Value(ax1).XY() * x.XY() ),
1544                                   Min ( sign * ( c2d2->Value(0.5*(a2 +b2 )).XY() * x.XY() ),
1545                                         sign * (  cx1->Value(0.5*(ax1+bx1)).XY() * x.XY() ) ) ) ) ) );
1546             Standard_Real deep2 = Max ( sign * ( pn1.XY() * x.XY() ),
1547                                   Max ( sign * ( pd2.XY() * x.XY() ),
1548                                   Max ( sign * ( c2d1->Value(a1 ).XY() * x.XY() ),
1549                                   Max ( sign * (  cx2->Value(bx2).XY() * x.XY() ),
1550                                   Max ( sign * ( c2d1->Value(0.5*(a1 +b1 )).XY() * x.XY() ),
1551                                         sign * (  cx2->Value(0.5*(ax2+bx2)).XY() * x.XY() ) ) ) ) ) );
1552             Standard_Real deep = deep2 - deep1; // estimated current size of wire by x
1553             // pdn 30 Oct 00: trying correct period [0,period] (trj5_k1-tc-203.stp #4698)
1554             Standard_Real dx = ShapeAnalysis::AdjustToPeriod ( deep, ::Precision::PConfusion(), period+::Precision::PConfusion()); 
1555             x *= ( scld >0 ? -dx : dx );
1556             //x *= ( Abs(scld-scln) > 1.5 * period ? 2. : 1. ) *
1557             //     ( scld >0 ? -period : period );
1558             gp_Trsf2d Shift;
1559             Shift.SetTranslation ( x );
1560             for ( Standard_Integer k=degn2; ; k++ )
1561             {
1562               if ( k > nb ) k = 1;
1563               if ( k == n2 ) break;
1564               TopoDS_Edge edge = sbwd->Edge ( k );
1565               if ( ! sae.PCurve ( edge, Face(), cx1, ax1, bx1, Standard_True ) ) continue;
1566               //cx1->Transform ( Shift );
1567               // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1568               Handle(Geom2d_Curve) cx1new = Handle(Geom2d_Curve)::DownCast(cx1->Transformed(Shift));
1569               sbe.ReplacePCurve(edge,cx1new,Face());
1570               UpdateEdgeUVPoints ( edge, Face() );
1571             }
1572             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1573 #ifdef OCCT_DEBUG
1574             std::cout << "Info: ShapeFix_Wire::FixShifted(): bi - meridian case fixed" << std::endl;
1575 #endif
1576             continue;
1577           }
1578           //degn2 = n2; pdeg = p; // ie_exhaust-A.stp #37520
1579         }
1580       }
1581 /*
1582       // pdn to fix half sphere
1583       TopoDS_Vertex VE = sae.LastVertex ( E2 );
1584       gp_Pnt pe = BRep_Tool::Pnt ( VE );
1585       //pdn is second vertex on singular point ?
1586       if ( surf->IsDegenerated ( pe, Max ( Precision(), BRep_Tool::Tolerance(V) ) ) ) {
1587         if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1588              ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1589           myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1590           continue;
1591         }
1592         gp_Pnt2d p2d1 = c2d1->Value ( b1 ), p2f = c2d2->Value ( a2 ), p2l = c2d2->Value ( b2 );
1593         Standard_Real pres2 = ::Precision::PConfusion();
1594         Standard_Real du = 0.,dv = 0.;
1595         //#79 rln 15.03.99 S4135: bmarkmdl.igs entity 633 (incorrectly oriented contour) check for gap
1596         if(uclosed&&(Abs(p2f.X()-p2l.X())<pres2)&&Abs(p2d1.X()-p2f.X())>GAS.UResolution(Precision())) {
1597           if((Abs(p2f.X()-SUF)<pres2)&&(p2f.Y()<p2l.Y()))
1598             du = URange;
1599           if((Abs(p2f.X()-SUL)<pres2)&&(p2f.Y()>p2l.Y()))
1600             du = -URange;
1601         } 
1602         if(vclosed&&(Abs(p2f.Y()-p2l.Y())<pres2)&&Abs(p2d1.Y()-p2f.Y())>GAS.VResolution(Precision())) {
1603           if((Abs(p2f.Y()-SVF)<pres2)&&(p2f.X()>p2l.X()))
1604             dv = VRange;
1605           if((Abs(p2f.Y()-SVL)<pres2)&&(p2f.X()<p2l.X()))
1606             dv = -VRange;
1607         } 
1608         if ( du ==0. && dv == 0. ) continue;
1609         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1610         gp_Trsf2d Shift;
1611         Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1612         c2d2->Transform ( Shift );
1613         UpdateEdgeUVPoints ( E2, Face() );//rln 15.03.99 syntax correction :E1
1614       }
1615 */
1616 //:abv 29.08.01: torCuts.sat:      continue;
1617     }
1618
1619     if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1620          ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1621       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1622       continue;
1623     }
1624     gp_Pnt2d p2d1 = c2d1->Value ( b1 );
1625     gp_Pnt2d p2d2 = c2d2->Value ( a2 );
1626     box.Add ( p2d1 );
1627
1628     Standard_Real du=0., dv=0.;
1629     if ( uclosed && isDeg != 1 ) {
1630       Standard_Real dx = Abs ( p2d2.X() - p2d1.X() );
1631       if ( dx > URange - UTol ) 
1632         du = ShapeAnalysis::AdjustByPeriod ( p2d2.X(), p2d1.X(), URange );
1633       else if ( dx > UTol && stop == nb ) stop = n2; //:abv 29.08.01: torCuts2.stp
1634     }
1635     if ( vclosed && isDeg != 2 ) {
1636       Standard_Real dy = Abs ( p2d2.Y() - p2d1.Y() );
1637       if ( dy > VRange - VTol ) 
1638         dv = ShapeAnalysis::AdjustByPeriod ( p2d2.Y(), p2d1.Y(), VRange );
1639       else if ( dy > VTol && stop == nb ) stop = n2;
1640     }
1641     if ( du ==0. && dv == 0. ) continue;
1642
1643     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1644     gp_Trsf2d Shift;
1645     Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1646     //c2d2->Transform ( Shift );
1647     // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1648     Handle(Geom2d_Curve) c2d2new = Handle(Geom2d_Curve)::DownCast(c2d2->Transformed(Shift));
1649     sbe.ReplacePCurve(E2,c2d2new,Face());
1650     UpdateEdgeUVPoints ( E2, Face() );
1651   }
1652   if ( box.IsVoid() ) return Standard_False; //#3 smh 01.04.99. S4163: Overflow, when box is void.
1653
1654   Standard_Real umin, vmin, umax, vmax;
1655   box.Get ( umin, vmin, umax, vmax );
1656   if ( Abs ( umin + umax - SUF - SUL ) < URange &&
1657        Abs ( vmin + vmax - SVF - SVL ) < VRange &&
1658        ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
1659
1660   box.SetVoid();
1661   Standard_Integer n; // svv Jan11 2000 : porting on DEC
1662   for ( n=1; n <= nb; n++ ) {
1663     Standard_Real a, b;
1664     Handle(Geom2d_Curve) c2d;
1665     if ( ! sae.PCurve ( sbwd->Edge(n), Face(), c2d, a, b, Standard_True ) ) continue;
1666     box.Add ( c2d->Value ( a ) );
1667     box.Add ( c2d->Value ( 0.5 * ( a + b ) ) );
1668   }
1669   box.Get ( umin, vmin, umax, vmax );
1670
1671   Standard_Real du=0., dv=0.;
1672
1673   if ( uclosed ) {
1674     Standard_Real umid = 0.5 * ( umin + umax );
1675 //     du = ShapeAnalysis::AdjustToPeriod(umid, SUF, SUL);
1676     // PTV 26.06.2002 xloop torus-apple iges face mode
1677     du = ShapeAnalysis::AdjustByPeriod(umid, SUMid, URange);
1678   }
1679   if ( vclosed ) {
1680     Standard_Real vmid = 0.5 * ( vmin + vmax );
1681 //     dv = ShapeAnalysis::AdjustToPeriod(vmid, SVF, SVL);
1682     // PTV 26.06.2002 xloop torus-apple iges face mode
1683     dv = ShapeAnalysis::AdjustByPeriod(vmid, SVMid, VRange);
1684   }
1685
1686   if ( du ==0. && dv == 0. ) return Standard_True;
1687
1688   myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1689   
1690   gp_Trsf2d Shift;
1691   Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1692
1693   for ( n=1; n <= sbwdOring->NbEdges(); n++ ) {
1694     Standard_Real a, b;
1695     Handle(Geom2d_Curve) c2d;
1696     TopoDS_Edge ed = sbwdOring->Edge(n);
1697     if ( ! sae.PCurve ( ed, Face(), c2d, a, b, Standard_True ) ) continue;
1698     // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1699     Handle(Geom2d_Curve) c2d2 = Handle(Geom2d_Curve)::DownCast(c2d->Transformed(Shift));
1700     sbe.ReplacePCurve(ed,c2d2,Face());
1701     UpdateEdgeUVPoints ( ed, Face() );
1702   }
1703   return Standard_True;
1704 }
1705
1706 //=======================================================================
1707 //function : FixDegenerated
1708 //purpose  : 
1709 //=======================================================================
1710
1711 Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num) 
1712 {
1713   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1714   if ( ! IsReady() ) return Standard_False;
1715
1716   // analysis
1717   gp_Pnt2d p2d1, p2d2;
1718   myAnalyzer->CheckDegenerated ( num, p2d1, p2d2 );
1719   if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL1 ) ) {
1720     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1721   }
1722   //: abv 29.08.01: torHalf2.sat: if edge was encoded as degenerated but 
1723   //  has no pcurve and no singularity is found at that point, remove it
1724   if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL2 ) ) {
1725     WireData()->Remove ( num );
1726     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1727     return Standard_True;
1728   }
1729   if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1730   
1731   // action: create degenerated edge and insert it (or replace)
1732
1733   gp_Vec2d vect2d ( p2d1, p2d2 );
1734   gp_Dir2d dir2d ( vect2d );
1735   Handle(Geom2d_Line) line2d = new Geom2d_Line ( p2d1, dir2d );
1736
1737   TopoDS_Edge degEdge;
1738   BRep_Builder B;
1739   B.MakeEdge ( degEdge );
1740   B.Degenerated ( degEdge, Standard_True );
1741   B.UpdateEdge ( degEdge, line2d, Face(), ::Precision::Confusion() );
1742   B.Range ( degEdge, Face(), 0., vect2d.Magnitude() );
1743
1744   Handle(ShapeExtend_WireData) sbwd = WireData();
1745   Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
1746   Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
1747   
1748   Standard_Boolean lack = myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 );
1749   Standard_Integer n3 = ( lack ? n2 : ( n2 < sbwd->NbEdges() ? n2+1 : 1 ) );
1750   
1751   ShapeAnalysis_Edge sae;
1752   TopoDS_Vertex V1 = sae.LastVertex ( sbwd->Edge ( n1 ) );
1753   TopoDS_Vertex V2 = sae.FirstVertex ( sbwd->Edge ( n3 ) );
1754   
1755   V1.Orientation(TopAbs_FORWARD);
1756   V2.Orientation(TopAbs_REVERSED);
1757   B.Add(degEdge,V1);
1758   B.Add(degEdge,V2);
1759   degEdge.Orientation(TopAbs_FORWARD);
1760
1761   if ( lack ) {
1762     sbwd->Add ( degEdge, n2 );
1763     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1764   }
1765   else {
1766     sbwd->Set ( degEdge, n2 );
1767     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1768   }
1769
1770 //  commented to avoid extra messages
1771 //  SendWarning ( degEdge, Message_Msg ( "FixWire.FixDegenerated.MSG0" ) );// Degenerated edge(s) detected
1772
1773   return Standard_True;
1774 }
1775
1776 //=======================================================================
1777 //function : FixSelfIntersectingEdge
1778 //purpose  : Tests edge for self-intersection and updates tolerance of vertex
1779 //           if intersection is found
1780 //           Returns True if tolerance was increased
1781 //=======================================================================
1782
1783 // Create edge on basis of E with new pcurve and call FixSP
1784 // Return resulting tolerance and modified pcurve
1785 static Standard_Boolean TryNewPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
1786                                       Handle(Geom2d_Curve) &c2d,
1787                                       Standard_Real &first,
1788                                       Standard_Real &last,
1789                                       Standard_Real &tol)
1790 {
1791   Standard_Real f, l;
1792   Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1793   if ( crv.IsNull() ) return Standard_False;
1794
1795   // make temp edge and compute tolerance
1796   BRepBuilderAPI_MakeEdge mkedge ( crv, f, l );
1797
1798   ShapeBuild_Edge SBE;        //skl 17.07.2001
1799   SBE.SetRange3d(mkedge,f,l); //skl 17.07.2001
1800
1801   if ( ! mkedge.IsDone() ) return Standard_False;
1802
1803   TopoDS_Edge edge = mkedge;
1804   BRep_Builder B;
1805   B.UpdateEdge ( edge, c2d, face, 0. );
1806   B.Range ( edge, face, first, last );
1807   B.SameRange ( edge, Standard_False );
1808 // no call to BRepLib:  B.SameParameter ( edge, Standard_False );
1809
1810   Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1811   sfe->FixSameParameter ( edge, face ); 
1812   c2d = BRep_Tool::CurveOnSurface ( edge, face, first, last );
1813   tol = BRep_Tool::Tolerance ( edge );
1814   return Standard_True;
1815 }
1816   
1817 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: 
1818 // Try to cut out the loop on the pcurve and make new pcurve by concatenating
1819 // the parts.
1820 // If result is not SameParameter with prec, does nothing and returns False
1821 // Warning: resulting pcurve will be C0
1822
1823 //=======================================================================
1824 //function : howMuchPCurves
1825 //purpose  : OCC901
1826 //=======================================================================
1827 static Standard_Integer howMuchPCurves (const TopoDS_Edge &E)
1828 {
1829   Standard_Integer count = 0;
1830   BRep_ListIteratorOfListOfCurveRepresentation itcr
1831     ((*((Handle(BRep_TEdge)*)&E.TShape()))->ChangeCurves());
1832
1833   while (itcr.More()) {
1834     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1835     if ( cr->IsCurveOnSurface() )
1836       count++;
1837     itcr.Next();
1838   }
1839     
1840   return count;
1841 }
1842
1843
1844 //=======================================================================
1845 //function : RemoveLoop
1846 //purpose  : 
1847 //=======================================================================
1848 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1849                                     const IntRes2d_IntersectionPoint &IP,
1850                                     const Standard_Real tolfact,
1851                                     const Standard_Real prec,
1852                                     const Standard_Boolean RemoveLoop3d)
1853 {
1854   Standard_Boolean loopRemoved3d;
1855   if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1856   
1857   Standard_Real f, l;
1858   Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1859
1860   Standard_Real t1 = IP.ParamOnFirst();
1861   Standard_Real t2 = IP.ParamOnSecond();
1862   if ( t1 > t2 ) { Standard_Real t = t1; t1 = t2; t2 = t; }
1863
1864   ShapeAnalysis_Edge sae;
1865   Standard_Real a, b;
1866   Handle(Geom2d_Curve) c2d;
1867   if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) ) 
1868     return Standard_False;
1869
1870 #ifdef OCCT_DEBUG
1871   std::cout << "Cut Loop: params (" << t1 << ", " << t2;
1872 #endif
1873   GeomAdaptor_Curve GAC ( crv, f, l );
1874   Standard_Real dt = tolfact * GAC.Resolution(prec);
1875   t1 -= dt; //1e-3;//::Precision::PConfusion();
1876   t2 += dt; //1e-3;//::Precision::PConfusion();
1877 #ifdef OCCT_DEBUG
1878   std::cout << ") -> (" << t1 << ", " << t2 << ")" << std::endl;
1879 #endif
1880       
1881   if ( t1 <= a || t2 >= b ) { // should not be so, but to be sure ..
1882     return Standard_False;
1883   }
1884
1885   // direct construction causes error on osf system.
1886   gp_Pnt p(0,0,0);
1887   gp_Dir d(0,0,1);
1888   gp_Ax3 ax(p, d);
1889   gp_Pln Pln (ax);
1890   
1891   // PTV OCC884
1892   Handle(Geom_Plane) aPlaneSurf = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface(face) );
1893   Handle(Geom_Curve) pcurve3d = crv;
1894   if ( !aPlaneSurf.IsNull() ) {
1895     Pln =  aPlaneSurf->Pln();
1896   }
1897   else
1898     pcurve3d = GeomAPI::To3d ( c2d, Pln );
1899
1900   // first segment
1901   //Handle(Geom_Curve) pcurve3d = GeomAPI::To3d ( c2d, Pln );
1902   Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve (pcurve3d, a, t1);
1903   GeomConvert_CompCurveToBSplineCurve connect ( trim );
1904   
1905   // null-length segment patch instead of loop
1906   TColgp_Array1OfPnt Poles(1,2);
1907   TColStd_Array1OfReal Knots(1,2);
1908   TColStd_Array1OfInteger Mults(1,2);
1909
1910   Poles.SetValue(1,trim->Value(t1));
1911   Knots.SetValue(1,t1);
1912   Mults.SetValue(1,2);
1913
1914   trim = new Geom_TrimmedCurve (pcurve3d, t2, b);
1915   Poles.SetValue(2,trim->Value(t2));
1916   Knots.SetValue(2,t2);
1917   Mults.SetValue(2,2);
1918
1919   Handle(Geom_BSplineCurve) patch = new Geom_BSplineCurve ( Poles, Knots, Mults, 1 );
1920   if ( ! connect.Add (patch, ::Precision::PConfusion(), Standard_True, Standard_False) )
1921     return Standard_False;
1922   
1923   // last segment
1924   if ( ! connect.Add (trim, ::Precision::PConfusion(), Standard_True, Standard_False) )
1925     return Standard_False;
1926   // PTV OCC884
1927   // keep created 3d curve
1928   Handle(Geom_Curve) aNew3dCrv = connect.BSplineCurve();
1929   
1930   
1931   Handle(Geom2d_Curve) bs = GeomAPI::To2d ( aNew3dCrv, Pln );
1932   if ( bs.IsNull() ) return Standard_False;
1933   
1934   // make temp edge and compute tolerance
1935   BRep_Builder B;
1936
1937   if(!RemoveLoop3d) { // old variant (not remove loop 3d)
1938     Standard_Real newtol=0;
1939     // OCC901
1940     Standard_Integer nbC2d = howMuchPCurves( E );
1941     if ( nbC2d <= 1  && !aPlaneSurf.IsNull() )
1942       B.UpdateEdge ( E, bs, face, 0 );
1943     else
1944       if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1945   
1946     Standard_Real tol = BRep_Tool::Tolerance ( E );
1947 #ifdef OCCT_DEBUG
1948     std::cout << "Cut Loop: tol orig " << tol << ", prec " << prec << ", new tol " << newtol << std::endl;
1949 #endif
1950     if ( newtol > Max ( prec, tol ) ) return Standard_False;
1951     //:s2  bs = BRep_Tool::CurveOnSurface ( edge, face, a, b );
1952     if ( Abs ( a - f ) > ::Precision::PConfusion() || // smth strange, cancel
1953          Abs ( b - l ) > ::Precision::PConfusion() ) return Standard_False;
1954     // PTV OCC884
1955     if ( !aPlaneSurf.IsNull() ) {
1956       B.UpdateEdge ( E, aNew3dCrv, Max (newtol, tol) );
1957       // OCC901
1958       if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1959     }
1960     B.UpdateEdge ( E, bs, face, newtol );
1961     B.UpdateVertex ( sae.FirstVertex ( E ), newtol );
1962     B.UpdateVertex ( sae.LastVertex  ( E ), newtol );
1963     return Standard_True;
1964   }
1965
1966   //:q1
1967   TopLoc_Location L;
1968   Handle(Geom_Surface) S = BRep_Tool::Surface(face, L);
1969   Handle(Geom2dAdaptor_Curve) AC = new Geom2dAdaptor_Curve(c2d);
1970   Handle(GeomAdaptor_Surface) AS = new GeomAdaptor_Surface(S);
1971   
1972   Adaptor3d_CurveOnSurface ACS(AC,AS);
1973   gp_Pnt P1(ACS.Value(t1));
1974   gp_Pnt P2(ACS.Value(t2));
1975   gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1976   
1977   ShapeAnalysis_TransferParametersProj SFTP(E,face);
1978   Handle(TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1979   Seq2d->Append(t1);
1980   Seq2d->Append(t2);
1981   Seq2d->Append((t1+t2)/2);
1982   Handle(TColStd_HSequenceOfReal) Seq3d = SFTP.Perform(Seq2d,Standard_False);
1983   
1984   Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project 
1985   Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1986   Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1987   Standard_Real ftrim,ltrim;
1988   if(dist3>Max(dist1,dist2)) {
1989     loopRemoved3d = Standard_False;
1990   }
1991   else {
1992     loopRemoved3d = Standard_True;
1993   }
1994   
1995   Handle(Geom_Curve) bs1;
1996   
1997   if (!loopRemoved3d) {
1998     // create new 3d curve
1999     ftrim = Seq3d->Value(1);
2000     ltrim = Seq3d->Value(2);
2001     ftrim-=dt;
2002     ltrim+=dt;
2003     Handle(Geom_TrimmedCurve) trim1 = new Geom_TrimmedCurve (crv, f, ftrim);
2004     GeomConvert_CompCurveToBSplineCurve connect1 ( trim1 );
2005     TColgp_Array1OfPnt      Poles1(1,2);
2006     TColStd_Array1OfReal    Knots1(1,2);
2007     TColStd_Array1OfInteger Mults1(1,2);
2008     
2009     Poles1.SetValue(1,trim1->Value(ftrim));
2010     Knots1.SetValue(1,ftrim);
2011     Mults1.SetValue(1,2);
2012     
2013     trim1 = new Geom_TrimmedCurve (crv, ltrim, l);
2014     Poles1.SetValue(2,trim1->Value(ltrim));
2015     Knots1.SetValue(2,ltrim);
2016     Mults1.SetValue(2,2);
2017   
2018     // create b-spline curve
2019     Handle(Geom_BSplineCurve) patch1 = new Geom_BSplineCurve ( Poles1, Knots1, Mults1, 1 );
2020   
2021     if ( ! connect1.Add (patch1, ::Precision::PConfusion(), Standard_True, Standard_False) )
2022       return Standard_False;
2023     
2024     // last segment
2025     if ( ! connect1.Add (trim1, ::Precision::PConfusion(), Standard_True, Standard_False) )
2026       return Standard_False;
2027     
2028     bs1 = connect1.BSplineCurve();
2029     
2030     if ( bs1.IsNull() )
2031       return Standard_False;
2032   }
2033 //  Standard_Real oldtol = BRep_Tool::Tolerance ( E );
2034
2035   if (!loopRemoved3d)
2036     B.UpdateEdge ( E, bs1, L, 0. );
2037   B.UpdateEdge ( E, bs, face, 0. );
2038   B.Range ( E, face, f, l );
2039   B.SameRange ( E, Standard_False );
2040
2041   Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
2042   sfe->FixSameParameter ( E ); 
2043
2044   return Standard_True;
2045 }
2046
2047 //=======================================================================
2048 //function : RemoveLoop
2049 //purpose  : 
2050 //=======================================================================
2051 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
2052                                     const IntRes2d_IntersectionPoint &IP2d,
2053                                     TopoDS_Edge &E1,
2054                                     TopoDS_Edge &E2)
2055 {
2056 #ifdef OCCT_DEBUG
2057   std::cout<<"Info: ShapeFix_Wire::FixSelfIntersection : Try insert vertex"<<std::endl;
2058 #endif
2059
2060   if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
2061   
2062   Standard_Real f, l;
2063   Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
2064
2065   Standard_Real t1 = IP2d.ParamOnFirst();
2066   Standard_Real t2 = IP2d.ParamOnSecond();
2067   
2068   if ( t1 > t2 ) 
2069   { 
2070     Standard_Real t = t1; t1 = t2; t2 = t; 
2071   }
2072
2073   ShapeAnalysis_Edge sae;
2074   
2075   // define vertexes Vfirst , Vlast, Vmid
2076   TopoDS_Vertex Vfirst,Vlast,Vmid;
2077   // initialize Vfirst and Vlast
2078   Vfirst = sae.FirstVertex(E);
2079   Vlast  = sae.LastVertex(E); 
2080   
2081   // find a 2d curve and parameters from edge E
2082   Standard_Real a, b;
2083   Handle (Geom2d_Curve) c2d;
2084   if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) ) 
2085     return Standard_False;
2086
2087   // first segment for 2d curve
2088   Handle(Geom2d_TrimmedCurve) trim1;
2089   if( (t1-a)>Precision::PConfusion() )
2090     trim1 = new Geom2d_TrimmedCurve (c2d, a, t1);
2091   // second segment for 2d curve
2092   Handle(Geom2d_TrimmedCurve) trim2 = new Geom2d_TrimmedCurve (c2d, t2, b);
2093
2094 //  if ( trim1.IsNull() || trim2.IsNull()  ) 
2095   if(trim2.IsNull()) 
2096     return Standard_False;
2097
2098   TopLoc_Location L;
2099   Handle (Geom_Surface) S = BRep_Tool::Surface(face, L);
2100   Handle (Geom2dAdaptor_Curve) AC = new Geom2dAdaptor_Curve(c2d);
2101   Handle (GeomAdaptor_Surface) AS = new GeomAdaptor_Surface(S); 
2102   
2103   Adaptor3d_CurveOnSurface ACS(AC,AS);
2104   gp_Pnt P1(ACS.Value(t1));
2105   gp_Pnt P2(ACS.Value(t2));
2106   gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
2107   
2108   // transfer parameters from pcurve to 3d curve
2109   ShapeAnalysis_TransferParametersProj SFTP(E,face);
2110   Handle (TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
2111   Seq2d->Append(t1);
2112   Seq2d->Append(t2);
2113   Seq2d->Append((t1+t2)/2);
2114   Handle (TColStd_HSequenceOfReal) Seq3d = SFTP.Perform(Seq2d,Standard_False);
2115   
2116   Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project 
2117   Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
2118   Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
2119   Standard_Real ftrim,ltrim;
2120   if ( dist3 > Max(dist1, dist2)) { // is loop in 3d
2121     ftrim = Seq3d->Value(1);
2122     ltrim = Seq3d->Value(2);
2123   }
2124   else { // not loop in 3d
2125     ftrim = Seq3d->Value(3);
2126     ltrim = Seq3d->Value(3);
2127   }
2128   
2129 //  ftrim = Seq3d->Value(1);
2130 //  ltrim = Seq3d->Value(2);
2131   
2132   // trim for 3d curve 'crv' with parameters from 'f' to 'l' 
2133   Handle(Geom_TrimmedCurve) trim3;
2134   if(!trim1.IsNull())
2135     trim3 = new Geom_TrimmedCurve (crv, f, ftrim);
2136   // second segment for 3d curve
2137   Handle(Geom_TrimmedCurve) trim4 = new Geom_TrimmedCurve (crv, ltrim, l);
2138
2139 //  if ( trim3.IsNull() || trim4.IsNull()  ) 
2140   if(trim4.IsNull()) 
2141     return Standard_False;
2142   
2143   // create a point for middle vertex
2144   gp_Pnt pnt1 = crv->Value(ftrim);
2145   gp_Pnt pnt2 = crv->Value(ltrim);
2146   gp_Pnt Pmid((pnt1.X()+pnt2.X())/2,(pnt1.Y()+pnt2.Y())/2,(pnt1.Z()+pnt2.Z())/2);
2147     
2148   BRep_Builder B;
2149   
2150   // create new copies for E1 and E2
2151   if(!trim1.IsNull())
2152     E1=TopoDS::Edge(E.EmptyCopied());
2153   E2=TopoDS::Edge(E.EmptyCopied());
2154   
2155   // initialize middle vertex Vmid
2156   if(trim1.IsNull()) 
2157     B.MakeVertex(Vmid, pnt2, 0.);
2158   else
2159     B.MakeVertex(Vmid, Pmid, 0.);
2160   
2161   ShapeBuild_Edge sbe;
2162   
2163   // replace verteces for new edges E1 and E2
2164   if (E.Orientation()== TopAbs_FORWARD)
2165   {
2166     if(!E1.IsNull())
2167       E1=sbe.CopyReplaceVertices(E1,Vfirst,Vmid);
2168     E2=sbe.CopyReplaceVertices(E2,Vmid, Vlast);
2169   }
2170   else 
2171   {
2172     if(!E1.IsNull())
2173       E1=sbe.CopyReplaceVertices(E1,Vmid, Vlast);
2174     E2=sbe.CopyReplaceVertices(E2,Vfirst, Vmid);
2175   }
2176   
2177   // Update edges by 2d and 3d curves
2178   Handle(ShapeFix_Edge) mySfe = new ShapeFix_Edge;
2179   if(!E1.IsNull()) {
2180     B.UpdateEdge(E1, trim1, face, 0.);
2181     B.UpdateEdge(E1, trim3, 0.);
2182     B.Range(E1, f, ftrim);
2183     B.SameRange(E1,Standard_False);
2184 //    B.SameParameter(E1,Standard_False);
2185     mySfe->FixSameParameter(E1);
2186     mySfe->FixVertexTolerance(E1);
2187   }
2188   B.UpdateEdge(E2, trim2, face, 0.);
2189   B.UpdateEdge(E2, trim4, 0.);
2190   B.Range ( E2,ltrim,l     );
2191   B.SameRange(E2, Standard_False );
2192 //  B.SameParameter(E2, Standard_False);
2193   mySfe->FixSameParameter(E2);
2194   mySfe->FixVertexTolerance(E2);
2195
2196   return Standard_True;
2197 }
2198
2199
2200 //=======================================================================
2201 //function : FixSelfIntersectingEdge
2202 //purpose  : 
2203 //=======================================================================
2204
2205 Standard_Boolean ShapeFix_Wire::FixSelfIntersectingEdge (const Standard_Integer num) 
2206 {
2207   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2208   if ( ! IsReady() ) return Standard_False;
2209
2210   // analysis
2211   IntRes2d_SequenceOfIntersectionPoint points2d;
2212   TColgp_SequenceOfPnt points3d;
2213   Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2214   if (theAdvAnalyzer.IsNull()) return Standard_False;
2215   theAdvAnalyzer->CheckSelfIntersectingEdge ( num, points2d, points3d ); 
2216   if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2217     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2218   }
2219   if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2220   
2221   // action: increase tolerance of vertex
2222   
2223   TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
2224   
2225   ShapeAnalysis_Edge sae;
2226   TopoDS_Vertex V1 = sae.FirstVertex ( E );
2227   TopoDS_Vertex V2 = sae.LastVertex ( E );
2228   Standard_Real tol1 = BRep_Tool::Tolerance ( V1 );
2229   Standard_Real tol2 = BRep_Tool::Tolerance ( V2 );
2230   gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 );
2231   gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 );
2232
2233   // cycle is to verify fix in case of RemoveLoop
2234   Standard_Real tolfact = 0.1; // factor for shifting by parameter in RemoveLoop
2235   Standard_Real f2d = 0., l2d = 0.;
2236   Handle(Geom2d_Curve) c2d;
2237   Standard_Real newtol=0.; // = Precision();
2238
2239   if (myRemoveLoopMode<1) {
2240     for ( Standard_Integer iter=0; iter < 30; iter++ ) { 
2241       Standard_Boolean loopRemoved = Standard_False;
2242       Standard_Real prevFirst = 0 , prevLast = 0; 
2243       for ( Standard_Integer i=1; i<=points2d.Length(); i++ ) {
2244         gp_Pnt pint = points3d.Value(i);
2245         Standard_Real dist21 = pnt1.SquareDistance ( pint );
2246         Standard_Real dist22 = pnt2.SquareDistance ( pint );
2247         if ( dist21 < tol1 * tol1 || dist22 < tol2 * tol2 ) continue;
2248         newtol = 1.001 * Sqrt ( Min ( dist21, dist22 ) ); //:f8
2249
2250         //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2251         if ( myGeomMode ) {
2252           if ( c2d.IsNull() )
2253             sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2254           Standard_Real firstpar = points2d.Value(i).ParamOnFirst(); 
2255           Standard_Real lastpar = points2d.Value(i).ParamOnSecond();
2256           if(firstpar > prevFirst && lastpar < prevLast) continue;
2257           if ( RemoveLoop (E, Face(), points2d.Value(i), tolfact, 
2258                            Min( MaxTolerance(), Max(newtol,Precision()) ),
2259                            myRemoveLoopMode==0 ) ) {
2260             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2261             loopRemoved = Standard_True;
2262             prevFirst = firstpar;
2263             prevLast = lastpar;
2264             continue; // repeat of fix on that edge required (to be done by caller)
2265           }
2266         }
2267         if ( newtol < MaxTolerance() ) {
2268           myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2269           BRep_Builder B;
2270           if ( dist21 < dist22 ) B.UpdateVertex ( V1, tol1 = newtol );
2271           else                   B.UpdateVertex ( V2, tol2 = newtol );
2272         }
2273         else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2274       }
2275
2276       // after RemoveLoop, check that self-intersection disappeared
2277       if ( loopRemoved ) {
2278         IntRes2d_SequenceOfIntersectionPoint pnts2d;
2279         TColgp_SequenceOfPnt pnts3d;
2280         theAdvAnalyzer->CheckSelfIntersectingEdge ( num, pnts2d, pnts3d );
2281         if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) break;
2282         //points3d.Append(pnts3d);
2283         //points2d.Append(pnts2d);
2284         points3d = pnts3d;
2285         points2d = pnts2d;
2286         BRep_Builder B;
2287         B.UpdateEdge ( E, c2d, Face(), 0. );
2288         B.Range ( E, Face(), f2d, l2d );
2289         //newtol+=Precision();
2290       }
2291       else {
2292         break;
2293       }
2294     }
2295   }
2296   
2297   //===============================================
2298   // RemoveLoopMode = 1 , insert vertex 
2299   //===============================================
2300   if (myRemoveLoopMode == 1) {
2301     // after fixing will be nb+1 edges
2302     Standard_Boolean loopRemoved; 
2303     // create a sequence of resulting edges
2304     Handle (TopTools_HSequenceOfShape) TTSS = new TopTools_HSequenceOfShape;
2305     TopoDS_Edge E2;
2306     
2307     loopRemoved = Standard_False;
2308     //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2309     if ( myGeomMode ) {
2310       if ( c2d.IsNull() )
2311         sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2312       TopoDS_Edge E1;
2313       if ( RemoveLoop (E, Face(), points2d.Value(1),E1,E2) ) {
2314         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2315         loopRemoved = Standard_True;
2316         if(!E1.IsNull()) {
2317           TTSS->Append(E1);
2318           newtol = Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2));
2319         }
2320         else
2321           newtol = BRep_Tool::Tolerance(E2);
2322       }
2323     }
2324
2325     TTSS->Append(E2);
2326     
2327     if ( newtol > MaxTolerance() ) 
2328       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2329     
2330     ShapeExtend_WireData sewd;
2331     for (Standard_Integer i=1 ; i <= TTSS->Length(); i++) {
2332       sewd.Add(TopoDS::Edge(TTSS->Value(i)));
2333     }
2334     if (! Context().IsNull()) {
2335       Context()->Replace ( E, sewd.Wire() );
2336       UpdateWire();
2337     }
2338     else {
2339       WireData()->Remove(num >0 ? num : NbEdges());
2340       WireData()->Add(sewd.Wire(), num >0 ? num : NbEdges());
2341     }
2342     if (loopRemoved)
2343       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
2344     
2345   }
2346
2347   if ( LastFixStatus ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
2348     SendWarning ( E, Message_Msg ( "FixAdvWire.FixIntersection.MSG5" ) );// Edge was self-intersecting, corrected
2349   }
2350
2351   return LastFixStatus ( ShapeExtend_DONE );
2352 }
2353
2354
2355 //=======================================================================
2356 //function : ComputeLocalDeviation
2357 //purpose  : auxilary
2358 //=======================================================================
2359 static Standard_Real ComputeLocalDeviation (const TopoDS_Edge &edge, 
2360                                             const gp_Pnt &pint,const gp_Pnt &pnt,
2361                                             Standard_Real f, Standard_Real l,
2362                                             const TopoDS_Face &face )
2363 {
2364   ShapeAnalysis_Edge sae;
2365   Handle(Geom_Curve) c3d;
2366   Standard_Real a, b;
2367   if ( ! sae.Curve3d ( edge, c3d, a, b, Standard_False ) ) return RealLast();
2368   
2369   gp_Lin line ( pint, gp_Vec ( pint, pnt ) );
2370   
2371   Handle(Geom2d_Curve) Crv;
2372   Standard_Real fp,lp;
2373   if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
2374     if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
2375       Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
2376       if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
2377         f = a + (f-fp)*(b-a)/(lp-fp);
2378         l = a + (l-fp)*(b-a)/(lp-fp);
2379       }
2380     }
2381   }
2382
2383   const Standard_Integer NSEG = 10;
2384   Standard_Real step = ( l - f ) / NSEG;
2385   Standard_Real dev = 0.;
2386   for ( Standard_Integer i=1; i < NSEG; i++ ) {
2387     gp_Pnt p = c3d->Value ( f + i * step );
2388     Standard_Real d = line.Distance ( p );
2389     if ( dev < d ) dev = d;
2390   }
2391   return dev;
2392 }
2393
2394 //=======================================================================
2395 //function : FixIntersectingEdges
2396 //purpose  : 
2397 //=======================================================================
2398
2399 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num) 
2400 {
2401   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2402   if ( ! IsReady() || NbEdges() <2 ) return Standard_False;
2403
2404   // analysis
2405   IntRes2d_SequenceOfIntersectionPoint points2d;
2406   TColgp_SequenceOfPnt points3d;
2407   TColStd_SequenceOfReal errors;
2408   Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2409   if (theAdvAnalyzer.IsNull()) return Standard_False;
2410   theAdvAnalyzer->CheckIntersectingEdges ( num, points2d, points3d, errors );
2411   if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2412     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2413   }
2414   if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2415   
2416   //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge)
2417   //:l0  Standard_Boolean isLacking = myAnalyzer->CheckLacking ( num );
2418
2419   // action: increase tolerance of vertex
2420   
2421   Handle(ShapeExtend_WireData) sbwd = WireData();
2422   Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
2423   Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
2424   TopoDS_Edge E1 = sbwd->Edge(n1);
2425   TopoDS_Edge E2 = sbwd->Edge(n2);
2426   if ( !Context().IsNull() )
2427   {
2428     E1 = TopoDS::Edge(Context()->Apply(sbwd->Edge(n1))); 
2429     E2 = TopoDS::Edge(Context()->Apply(sbwd->Edge(n2))); 
2430   }
2431
2432   Standard_Boolean isForward1 = ( E1.Orientation() == TopAbs_FORWARD );
2433   Standard_Boolean isForward2 = ( E2.Orientation() == TopAbs_FORWARD );
2434   Standard_Real a1, b1, a2, b2;
2435   BRep_Tool::Range ( E1, Face(), a1, b1 );
2436   BRep_Tool::Range ( E2, Face(), a2, b2 );
2437
2438   ShapeAnalysis_Edge sae;
2439   TopoDS_Vertex Vp = sae.FirstVertex ( E1 );
2440   TopoDS_Vertex V1 = sae.LastVertex  ( E1 );
2441   TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2442   TopoDS_Vertex Vn = sae.LastVertex  ( E2 );
2443
2444   Standard_Real tol = BRep_Tool::Tolerance ( V1 );
2445   gp_Pnt pnt = BRep_Tool::Pnt ( V1 );
2446   
2447   Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast();
2448   Standard_Boolean cutEdge1 = Standard_False, cutEdge2 = Standard_False;
2449   Standard_Boolean IsCutLine = Standard_False;
2450   Standard_Boolean isChangedEdge = Standard_False;
2451
2452   BRep_Builder B;
2453
2454   Standard_Integer nb = points3d.Length();
2455   for ( Standard_Integer i=1; i <= nb; i++ ) {
2456     const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2457     Standard_Real param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() );
2458     Standard_Real param2 = ( num ==1 ? IP.ParamOnFirst()  : IP.ParamOnSecond() );
2459     
2460     Standard_Real newRange1 = Abs ( ( isForward1 ? a1 : b1 ) - param1 );
2461     Standard_Real newRange2 = Abs ( ( isForward2 ? b2 : a2 ) - param2 );
2462     if ( newRange1 > prevRange1 && newRange2 > prevRange2 ) continue;
2463     
2464     gp_Pnt pint = points3d.Value(i);
2465     Standard_Real rad = errors.Value(i);
2466     Standard_Real newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2467
2468     //GeomAdaptor_Surface& Ads = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
2469
2470     //:r8 abv 12 Apr 99: try increasing tolerance of edge
2471
2472     Standard_Boolean locMayEdit = myTopoMode;
2473     // Always try to modify the tolerance firstly as a better solution
2474     if ( /*! myTopoMode &&*/ newtol > tol )
2475     {
2476       Standard_Real te1 = rad + ComputeLocalDeviation (E1, pint, pnt,
2477         param1, ( isForward1 ? b1 : a1 ), Face() );
2478       Standard_Real te2 = rad + ComputeLocalDeviation (E2, pint, pnt, 
2479         ( isForward2 ? a2 : b2 ), param2, Face() );
2480       Standard_Real maxte = Max ( te1, te2 );
2481       if ( maxte < MaxTolerance() && maxte < newtol )
2482       {
2483         if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 )
2484         {
2485 #ifdef OCCT_DEBUG
2486           std::cout << "Warning: ShapeFix_Wire::FixIE: edges tolerance increased: (" <<
2487             te1 << ", " << te2 << ") / " << newtol << std::endl;
2488 #endif
2489
2490           // Make copy of edges.
2491           if (!Context().IsNull())
2492           {
2493              isChangedEdge = Standard_True; // To avoid double copying of vertexes.
2494
2495             // Intersection point of two base edges.
2496             ShapeBuild_Edge aSBE;
2497             TopoDS_Vertex VV1 = Context()->CopyVertex(V1);
2498
2499             TopoDS_Vertex VVp = Vp;
2500             TopoDS_Vertex VVn = Vn;
2501             if (Vp.IsSame(Vn))
2502             {
2503               // Should modify only one vertex.
2504               VVp = Context()->CopyVertex(Vp);
2505               VVn = VVp;
2506             }
2507             else
2508             {
2509               VVp = Context()->CopyVertex(Vp);
2510               VVn = Context()->CopyVertex(Vn);
2511             }
2512
2513             TopoDS_Edge EE1 = aSBE.CopyReplaceVertices(E1, VVp, VV1);
2514             TopoDS_Edge EE2 = aSBE.CopyReplaceVertices(E2, VV1, VVn);
2515
2516             Context()->Replace(E1, EE1);
2517             Context()->Replace(E2, EE2);
2518
2519             UpdateWire();
2520             E1 = sbwd->Edge(n1);
2521             E2 = sbwd->Edge(n2);
2522             Vp = sae.FirstVertex ( E1 );
2523             V1 = sae.LastVertex  ( E1 );
2524             V2 = sae.FirstVertex ( E2 );
2525             Vn = sae.LastVertex  ( E2 );
2526           }
2527
2528           B.UpdateEdge ( E1, 1.000001 * te1 );
2529           B.UpdateVertex ( sae.FirstVertex ( E1 ), 1.000001 * te1 );
2530           B.UpdateVertex ( sae.LastVertex  ( E1 ), 1.000001 * te1 );
2531           B.UpdateEdge ( E2, 1.000001 * te2 );
2532           B.UpdateVertex ( sae.FirstVertex ( E2 ), 1.000001 * te2 );
2533           B.UpdateVertex ( sae.LastVertex  ( E2 ), 1.000001 * te2 );
2534
2535           myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
2536           locMayEdit = Standard_False;
2537         }
2538         newtol = 1.000001 * maxte;
2539       }
2540     }
2541     
2542     if ( locMayEdit || newtol <= MaxTolerance() )
2543     {
2544       prevRange1 = newRange1; 
2545       prevRange2 = newRange2;
2546       if ( locMayEdit )
2547       {
2548         newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2549         //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586: do not cut edges because of influence on adjacent faces
2550         ShapeFix_SplitTool aTool;
2551         
2552         if ( ! aTool.CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2553           if ( V1.IsSame ( Vp ) )
2554             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2555           else locMayEdit = Standard_False;
2556         }
2557         else cutEdge1 = Standard_True; //:h4
2558         
2559         if ( ! aTool.CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2560           if ( V2.IsSame ( Vn ) ) 
2561             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2562           else locMayEdit = Standard_False;
2563         }
2564         else cutEdge2 = Standard_True; //:h4
2565       }
2566
2567       if (  locMayEdit &&
2568             newRange1 <= prevRange1 && newRange2 <= prevRange2 && //rln 09/01/98
2569             BRep_Tool::SameParameter ( E1 ) &&
2570             BRep_Tool::SameParameter ( E2 ) )
2571       {
2572         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2573         pnt = pint;
2574         if ( tol <= rad ) {
2575           myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2576           tol = 1.001 * rad;
2577         }
2578       }
2579       else
2580       {
2581         if(IsCutLine)
2582         {
2583           myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2584           pnt = pint;
2585           if ( tol <= rad ) {
2586             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2587             tol = 1.001 * rad;
2588           }
2589         }
2590         else
2591         { // else increase tolerance
2592           if (tol < newtol)
2593           { //rln 07.04.99 CCI60005-brep.igs
2594             myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2595             tol = newtol;
2596           }
2597         }
2598       }
2599     }
2600     else
2601     {
2602       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2603     }
2604   }
2605
2606   if ( ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
2607
2608   if (isChangedEdge)
2609   {
2610     B.UpdateVertex ( V1, pnt, tol );
2611     B.UpdateVertex ( V2, pnt, tol );
2612   }
2613   else
2614   {
2615     if ( !Context().IsNull() )
2616     {
2617       if (V1.IsSame(V2) )
2618       {
2619         Context()->CopyVertex(V1, pnt, tol);
2620       }
2621       else
2622       {
2623         Context()->CopyVertex(V1, pnt, tol);
2624         Context()->CopyVertex(V2, pnt, tol);
2625       }
2626     }
2627     else
2628     {
2629       B.UpdateVertex ( V1, pnt, tol );
2630       B.UpdateVertex ( V2, pnt, tol );
2631     }
2632   }
2633
2634   //:h4: make edges SP (after all cuts: t4mug.stp #3730+#6460)
2635   if ( cutEdge1 ) 
2636   {
2637     if ( !Context().IsNull() )
2638       E1 = TopoDS::Edge(Context()->Apply(E1));
2639     myFixEdge->FixSameParameter ( E1 );
2640   }
2641   if ( cutEdge2 && !IsCutLine )
2642   {
2643     if ( !Context().IsNull() )
2644       E2 = TopoDS::Edge(Context()->Apply(E2));
2645     myFixEdge->FixSameParameter ( E2 );
2646   }
2647   if ( cutEdge1 || cutEdge2 ) {
2648     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
2649   }
2650   if ( ! myShape.IsNull() ) {
2651     SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2652   }
2653   return Standard_True;
2654 }
2655
2656 //=======================================================================
2657 //function : FixIntersectingEdges
2658 //purpose  : 
2659 //=======================================================================
2660 //pdn 17.03.99 fixing non ajacent intersection by increasing tolerance of vertex
2661
2662 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num1,
2663                                                       const Standard_Integer num2)
2664 {
2665   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2666   if ( !IsReady() ) return Standard_False;
2667   IntRes2d_SequenceOfIntersectionPoint points2d;
2668   TColgp_SequenceOfPnt points3d;
2669   TColStd_SequenceOfReal errors;
2670   Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2671   if (theAdvAnalyzer.IsNull()) return Standard_False;
2672   theAdvAnalyzer->CheckIntersectingEdges ( num1, num2, points2d, points3d, errors);
2673   if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2674     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2675   }
2676   if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2677   TColgp_Array1OfPnt vertexPoints(1,4);
2678   TColStd_Array1OfReal vertexTolers(1,4);
2679   TColStd_Array1OfReal newTolers(1,4);
2680   TopTools_Array1OfShape vertices(1,4);
2681   newTolers.Init(0);
2682   
2683   Handle(ShapeExtend_WireData) sbwd = WireData();
2684   Standard_Integer n2 = ( num1 >0 ? num1  : sbwd->NbEdges() );
2685   Standard_Integer n1 = ( num2  >1 ? num2 : sbwd->NbEdges() );
2686   if(n1==n2) return Standard_False;
2687   
2688   TopoDS_Edge edge1 = sbwd->Edge(n1);
2689   TopoDS_Edge edge2 = sbwd->Edge(n2);
2690   
2691   ShapeAnalysis_Edge sae;
2692   vertices(1) = sae.FirstVertex(edge1);
2693   vertices(2) = sae.LastVertex(edge1);
2694   vertices(3) = sae.FirstVertex(edge2);
2695   vertices(4) = sae.LastVertex(edge2);
2696   
2697   Standard_Integer i; // svv Jan11 2000 : porting on DEC
2698   for (i = 1; i <=4; i++) {
2699     vertexPoints(i) = BRep_Tool::Pnt(TopoDS::Vertex(vertices(i)));
2700     vertexTolers(i) = BRep_Tool::Tolerance(TopoDS::Vertex(vertices(i)));
2701   }
2702    
2703   Standard_Real aNewTolEdge1 = 0.0, aNewTolEdge2 = 0.0;
2704   Standard_Integer nb = points3d.Length();
2705   for ( i=1; i <= nb; i++ ) {
2706     gp_Pnt pint = points3d.Value(i);
2707
2708     // searching for the nearest vertexies to the intersection point
2709     Standard_Real aVtx1Param=0., aVtx2Param=0.;
2710     Standard_Integer aVC1, aVC2;
2711     Standard_Real aMinDist = RealLast();
2712     gp_Pnt aNearestVertex;
2713     Standard_Real aNecessaryVtxTole = 0.0;
2714     for(aVC1 = 1; aVC1 <= 2; aVC1++) {
2715       for(aVC2 = 3; aVC2 <= 4; aVC2++) {
2716       
2717         Standard_Real aVtxIPDist = pint.Distance(vertexPoints(aVC1));
2718         Standard_Real aVtxVtxDist = vertexPoints(aVC1).Distance(vertexPoints(aVC2));
2719         if(aMinDist > aVtxIPDist && aVtxIPDist > aVtxVtxDist) {
2720           aNecessaryVtxTole = aVtxVtxDist;
2721           aNearestVertex = vertexPoints(aVC1);
2722           aMinDist = aVtxIPDist;
2723           aVtx1Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC1)),edge1);
2724           aVtx2Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC2)),edge2);
2725         }
2726       }
2727     }
2728     
2729     // calculation of necessary tolerances of edges
2730     const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2731     Standard_Real param1 = IP.ParamOnFirst(); 
2732     Standard_Real param2 = IP.ParamOnSecond();  
2733     Handle(Geom_Curve) aCurve1, aCurve2;
2734     Standard_Real f,l;
2735     TopLoc_Location L1, L2;
2736     aCurve1 = BRep_Tool::Curve(edge1, L1, f, l);
2737     aCurve2 = BRep_Tool::Curve(edge2, L2, f, l);
2738     
2739     // if aMinDist lower than resolution than the intersection point lyes inside the vertex
2740     if(aMinDist < gp::Resolution())
2741       continue;
2742     
2743     Standard_Real aMaxEdgeTol1 = 0.0, aMaxEdgeTol2 = 0.0;
2744     if(aMinDist < RealLast() && !aCurve1.IsNull() && !aCurve2.IsNull())
2745     {
2746       gp_Lin aLig(aNearestVertex, gp_Vec(aNearestVertex, pint));
2747       Standard_Integer aPointsC;
2748       Standard_Real du1 = 0.05*(param1 - aVtx1Param);
2749       Standard_Real du2 = 0.05*(param2 - aVtx2Param);
2750       Standard_Real tole1=BRep_Tool::Tolerance(edge1);
2751       Standard_Real tole2=BRep_Tool::Tolerance(edge2);
2752       for(aPointsC = 2; aPointsC < 19; aPointsC++)
2753       {
2754         Standard_Real u = aVtx1Param + aPointsC * du1;
2755         gp_Pnt P1 = aCurve1->Value(u);
2756         P1.Transform(L1.Transformation());
2757         Standard_Real d1 = aLig.Distance(P1) * 2.0000001;
2758         if(d1 > tole1 && d1 > aMaxEdgeTol1)
2759           aMaxEdgeTol1 = d1;
2760
2761         u = aVtx2Param + aPointsC * du2;
2762         gp_Pnt P2 = aCurve2->Value(u);
2763         P2.Transform(L2.Transformation());
2764         Standard_Real d2 = aLig.Distance(P2) * 2.0000001;
2765         if(d2 > tole2 && d2 > aMaxEdgeTol2)
2766           aMaxEdgeTol2 = d2;
2767       }
2768       if(aMaxEdgeTol1 == 0.0 && aMaxEdgeTol2 == 0.0) continue;
2769       // if the vertexies are far than tolerances so 
2770       // we do not need to increase edge tolerance
2771       if(aNecessaryVtxTole > Max(aMaxEdgeTol1, tole1) ||
2772          aNecessaryVtxTole > Max(aMaxEdgeTol2, tole2))
2773       {
2774         aMaxEdgeTol1 = 0.0;
2775         aMaxEdgeTol2 = 0.0;
2776       }
2777     }
2778     
2779     Standard_Real rad = errors.Value(i);
2780     Standard_Real finTol = RealLast();
2781     Standard_Integer rank=1;
2782     for(Standard_Integer j=1; j<=4; j++) {
2783       Standard_Real newtol = 1.0001 * ( pint.Distance (vertexPoints(j)) + rad );
2784       if(newtol<finTol) {
2785         rank = j;
2786         finTol = newtol;
2787       }
2788     }
2789     if(finTol <= MaxTolerance()) {
2790       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1);
2791       if(newTolers(rank) < finTol)
2792       {
2793         if(Max(aMaxEdgeTol1, aMaxEdgeTol2) < finTol && (aMaxEdgeTol1 > 0 || aMaxEdgeTol2 > 0))
2794         {
2795           aNewTolEdge1 = Max(aNewTolEdge1, aMaxEdgeTol1);
2796           aNewTolEdge2 = Max(aNewTolEdge2, aMaxEdgeTol2);
2797         }
2798         else
2799         {
2800           newTolers(rank) = finTol;
2801         }
2802       }
2803     } else {
2804       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2805     }
2806   }
2807   
2808   BRep_Builder B;
2809   // update of tolerances of edges 
2810   if(aNewTolEdge1 > 0)
2811   {
2812     for(i = 1; i <= 2; i++)
2813       if(aNewTolEdge1 > Max(vertexTolers(i), newTolers(i)))
2814         newTolers(i) = aNewTolEdge1;
2815     B.UpdateEdge(edge1, aNewTolEdge1);
2816   }
2817   if(aNewTolEdge2 > 0)
2818   {
2819     for(i = 3; i <= 4; i++)
2820       if(aNewTolEdge2 > Max(vertexTolers(i), newTolers(i)))
2821         newTolers(i) = aNewTolEdge2;
2822     B.UpdateEdge(edge2, aNewTolEdge2);
2823   }
2824     
2825   // update of tolerances of vertexies 
2826   for(i = 1; i <=4; i++)
2827     if(newTolers(i)>0) B.UpdateVertex(TopoDS::Vertex(vertices(i)),newTolers(i));
2828   
2829   if ( ! myShape.IsNull() ) {
2830     SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2831   }
2832   return Standard_True;
2833 }
2834
2835 //=======================================================================
2836 //function : FixLacking
2837 //purpose  : Test if two adjucent edges are disconnected in 2d (while connected 
2838 //           in 3d), and in that case either increase tolerance of the vertex or
2839 //           add a new edge (straight in 2d space), in order to close wire in 2d.
2840 //           Returns True if edge was added or tolerance was increased.
2841 //NOTE     : Is to be run after FixDegenerated
2842 //Algorithm: 1. Compute the 2d gap between edges and calculate a tolerance
2843 //              which should have vertex in order to comprise the gap
2844 //              (using GeomAdaptor_Surface); computed value is inctol
2845 //           2. If inctol < tol of vertex, return False (everything is OK)
2846 //           3. If inctol < Precision, just increase tolerance of vertex to inctol
2847 //           4. Else (if both edges are not degenerated) try to add new edge 
2848 //              with straight pcurve (in order to close the gap):
2849 //              a) if flag MayEdit is False
2850 //                 1. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2851 //                 2. else try to add degenerated edge (check that middle point of 
2852 //                    that pcurveis inside the vertex)
2853 //              b) if MayEdit is True
2854 //                 1. try to replace big vertex with two new small vertices 
2855 //                    connected by new edge. This is made if there is a 3d space
2856 //                    between ends of adjacent edges.
2857 //                 2. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2858 //                 3. else add either degenerated or closed edge (if middle point
2859 //                    of a pcurve of a new edge is inside the vertex, then
2860 //                    degenerated edge is added, else new edge is closed).
2861 //           5. If new edge cannot be added, but inctol < MaxTolerance,
2862 //              when increase tolerance of vertex to a value of inctol
2863 //Short list of some internal variables:
2864 // tol    - tolerance of vertex
2865 // tol2d  - tolerance in parametric space of the surface corresponding to 2*tol
2866 // dist2d - distance between ends of pcurves of edges (2d)
2867 // inctol - tolerance required for vertex to close 2d gap (=tol*dist2d/tol2d)
2868 // tol1, tol2 - tolerances of edges, tol0 = tol1 + tol2
2869 // p3d1, p3d2 - ends of 3d curves of edges
2870 //=======================================================================
2871 //:h2 abv 28 May 98: merged modifications by abv 22 Apr 98, gka 27 May 98 
2872 // and pdn 25 May 98 concerning lacking closed or degenerated edges
2873 // Example files: r0501_pe #107813, UKI60107-6 250, UKI60107-3 1577.
2874
2875 //:s2 abv 21 Apr 99: add functionality for bending pcurve
2876 static Standard_Boolean TryBendingPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
2877                                           const gp_Pnt2d p2d, const Standard_Boolean end,
2878                                           Handle(Geom2d_Curve) &c2d,
2879                                           Standard_Real &first, Standard_Real &last,
2880                                           Standard_Real &tol)
2881 {
2882   ShapeAnalysis_Edge sae;
2883   if ( ! sae.PCurve ( E, face, c2d, first, last, Standard_False ) ) return Standard_False;
2884   
2885   {
2886   try {
2887     OCC_CATCH_SIGNALS
2888     Handle(Geom2d_BSplineCurve) bs;
2889     if ( c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ) 
2890       bs = Handle(Geom2d_BSplineCurve)::DownCast(c2d->Copy());
2891     else // if ( c2d->IsKind(STANDARD_TYPE(Geom2d_Line)) ) 
2892     {
2893       Handle(Geom2d_TrimmedCurve) trim = new Geom2d_TrimmedCurve ( c2d, first, last );
2894       bs = Geom2dConvert::CurveToBSplineCurve ( trim );
2895     }
2896     if ( bs.IsNull() ) return Standard_False;
2897   
2898     Standard_Real par = ( end ? last : first );
2899     if ( fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2900         bs->Multiplicity(1) > bs->Degree() ) bs->SetPole ( 1, p2d );
2901     else if ( fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2902              bs->Multiplicity(bs->NbKnots()) > bs->Degree() ) bs->SetPole ( bs->NbPoles(), p2d );
2903     else {
2904       bs->Segment ( first, last );
2905       if (fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2906           bs->Multiplicity(1) > bs->Degree()) bs->SetPole ( 1, p2d );
2907       else if (fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2908                bs->Multiplicity(bs->NbKnots()) > bs->Degree()) bs->SetPole ( bs->NbPoles(), p2d );
2909       else return Standard_False;
2910     }
2911     c2d = bs;
2912
2913     if ( ! TryNewPCurve ( E, face, c2d, first, last, tol ) ) return Standard_False;
2914   }
2915   catch ( Standard_Failure const& ) {
2916 #ifdef OCCT_DEBUG
2917     std::cout << "Warning: ShapeFix_Wire::FixLacking: Exception in Geom2d_BSplineCurve::Segment()" << std::endl;
2918 #endif
2919     return Standard_False;
2920   }
2921   }
2922
2923   return Standard_True;
2924 }
2925
2926
2927 //=======================================================================
2928 //function : FixLacking
2929 //purpose  : 
2930 //=======================================================================
2931
2932 Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
2933                                             const Standard_Boolean force) 
2934 {
2935     myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2936   if ( ! IsReady() ) return Standard_False;
2937
2938   //=============
2939   // First phase: analysis whether the problem (gap) exists
2940   gp_Pnt2d p2d1, p2d2;
2941   myAnalyzer->CheckLacking ( num, ( force ? Precision() : 0. ), p2d1, p2d2 );
2942   if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2943     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2944   }
2945   if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2946   
2947   //=============
2948   // Second phase: collection of data necessary for further analysis
2949   
2950   Handle(ShapeExtend_WireData) sbwd = WireData();
2951   Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
2952   Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
2953   TopoDS_Edge E1 = sbwd->Edge(n1);
2954   TopoDS_Edge E2 = sbwd->Edge(n2);
2955   
2956   ShapeAnalysis_Edge sae;
2957   TopoDS_Vertex V1 = sae.LastVertex  ( E1 );
2958   TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2959   Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
2960   
2961   Standard_Real Prec = Precision();
2962   Standard_Real dist2d = myAnalyzer->MaxDistance2d();
2963   Standard_Real inctol = myAnalyzer->MaxDistance3d();
2964   
2965   TopoDS_Face face = myAnalyzer->Face();
2966   Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
2967
2968   gp_Pnt p3d1, p3d2;
2969   Standard_Real tol1=::Precision::Confusion(), tol2=::Precision::Confusion(); //SK
2970
2971   //=============
2972   //:s2 abv 21 Apr 99: Speculation: try bending pcurves
2973   Standard_Real bendtol1 = 0., bendtol2 = 0.;
2974   Handle(Geom2d_Curve) bendc1, bendc2;
2975   Standard_Real bendf1 = 0., bendl1 = 0., bendf2 = 0., bendl2 = 0.;
2976   if ( myGeomMode && ! BRep_Tool::IsClosed(E1,face) && ! BRep_Tool::IsClosed(E2,face) ) {
2977     gp_Pnt2d p2d = 0.5 * ( p2d1.XY() + p2d2.XY() );
2978     Standard_Boolean ok1 = TryBendingPCurve (E1, face, p2d, E1.Orientation() == TopAbs_FORWARD, 
2979                                              bendc1, bendf1, bendl1, bendtol1);
2980     Standard_Boolean ok2 = TryBendingPCurve (E2, face, p2d, E2.Orientation() == TopAbs_REVERSED, 
2981                                              bendc2, bendf2, bendl2, bendtol2);
2982     if ( ok1 && ! ok2 ) {
2983       bendtol2 = BRep_Tool::Tolerance(E2);
2984       ok1 = TryBendingPCurve (E1, face, p2d2, E1.Orientation() == TopAbs_FORWARD, 
2985                               bendc1, bendf1, bendl1, bendtol1);
2986     }
2987     else if ( ! ok1 && ok2 ) {
2988       bendtol1 = BRep_Tool::Tolerance(E1);
2989       ok2 = TryBendingPCurve (E2, face, p2d1, E2.Orientation() == TopAbs_FORWARD, 
2990                               bendc2, bendf2, bendl2, bendtol2);
2991     }
2992     if ( ! ok1 && ! ok2 ) bendc1.Nullify();
2993   }
2994   
2995   //=============
2996   // Third phase: analyse how to fix the problem
2997   
2998   // selector of solutions
2999   Standard_Boolean doIncrease  = Standard_False; // increase tolerance
3000   Standard_Boolean doAddLong   = Standard_False; // add long 3d edge in replacement of a vertex
3001   Standard_Boolean doAddClosed = Standard_False; // add closed 3d edge
3002   Standard_Boolean doAddDegen  = Standard_False; // add degenerated edge
3003   Standard_Boolean doBend      = Standard_False; //:s2 bend pcurves
3004
3005   // if bending is OK with existing tolerances of edges, take it
3006   if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3007        ( ( bendtol1 < BRep_Tool::Tolerance(E1) &&
3008            bendtol2 < BRep_Tool::Tolerance(E2) ) ||
3009          ( inctol < Prec && bendtol1 < inctol && bendtol2 < inctol ) ) ) 
3010        doBend = Standard_True;
3011   
3012   // is it OK just to increase tolerance (to a value less than preci)?
3013   else if ( inctol < Prec ) doIncrease = Standard_True;
3014
3015   // If increase is not OK or force, try to find other solutions (adding edge)
3016   else if ( ! BRep_Tool::Degenerated ( E2 ) && ! BRep_Tool::Degenerated ( E1 ) ) {
3017     
3018     // analyze the 3d space btw edges: is it enough to add long 3d edge?
3019     if ( myTopoMode ) {
3020       Handle(Geom_Curve) c3d;
3021       Standard_Real a, b;
3022       if ( ! sae.Curve3d ( E1, c3d, a, b, Standard_True ) ) { // cannot work
3023         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
3024         return Standard_False; 
3025       }
3026       p3d1 = c3d->Value ( b );
3027       Standard_Real dist2d3d1 = p3d1.Distance ( surf->Value ( p2d1 ) );
3028       if ( ! sae.Curve3d ( E2, c3d, a, b, Standard_True ) ) { // cannot work
3029         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
3030         return Standard_False; 
3031       }
3032       p3d2 = c3d->Value ( a );
3033       Standard_Real dist2d3d2 = p3d2.Distance ( surf->Value ( p2d2 ) );
3034
3035       tol1 = Max ( BRep_Tool::Tolerance ( E1 ), dist2d3d1 );
3036       tol2 = Max ( BRep_Tool::Tolerance ( E2 ), dist2d3d2 );
3037       //:c5  Standard_Real tol0 = Max ( tol1 + tol2, thepreci );
3038       Standard_Real tol0 = tol1 + tol2; //:c5 abv 26 Feb 98: CTS17806 #44418
3039       Standard_Real dist3d2 = p3d1.SquareDistance ( p3d2 );
3040
3041       // is it OK to add a long 3d edge?
3042       if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) && //:81 abv 20 Jan 98: don`t add back-going edges (zigzags)
3043            dist3d2 > 1.25 * tol0 * tol0 &&
3044            ( force || dist3d2 > Prec * Prec || inctol > MaxTolerance() ) ) {
3045         doAddLong = Standard_True;
3046       }
3047     }
3048     
3049     //:h6 abv 25 Jun 98: BUC40132 6361: try to increase tol up to MaxTol if not add
3050     if ( ! doAddLong && inctol < MaxTolerance() && 
3051          ! myAnalyzer->Surface()->IsDegenerated ( p2d1, p2d2, 2.*tol, 10. ) ) { //:p7
3052       if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3053            bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
3054       else doIncrease = Standard_True;
3055     }
3056     else 
3057       
3058     // else try to add either degenerated or closed edge
3059     if ( ! doAddLong ) {
3060       gp_Pnt pV = 0.5 * ( BRep_Tool::Pnt(V1).XYZ() + BRep_Tool::Pnt(V2).XYZ() );
3061       gp_Pnt pm = myAnalyzer->Surface()->Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) );
3062
3063       Standard_Real dist = pV.Distance ( pm );
3064       if ( dist <= tol ) doAddDegen = Standard_True;
3065       else if ( myTopoMode ) doAddClosed = Standard_True;
3066       else if ( dist <= MaxTolerance() ) { //:r7 abv 12 Apr 99: t3d_opt.stp #14245 after S4136
3067         doAddDegen = Standard_True;
3068         doIncrease = Standard_True;
3069         inctol = dist; 
3070       }
3071     }
3072   }
3073
3074   else if ( !BRep_Tool::Degenerated(E2) && BRep_Tool::Degenerated(E1) ) {
3075     // create new degenerated edge and replace E1 to new edge
3076   }
3077   else if ( BRep_Tool::Degenerated(E2) && !BRep_Tool::Degenerated(E1) ) {
3078     // create new degenerated edge and replace E2 to new edge
3079   }
3080   
3081   //=============
3082   // Third phase - do the fixes
3083   BRep_Builder B;
3084
3085   // add edge
3086   if ( doAddLong || doAddDegen || doAddClosed ) {
3087
3088     // construct new vertices
3089     TopoDS_Vertex newV1, newV2;
3090     if ( doAddLong ) {
3091       newV1 = BRepBuilderAPI_MakeVertex ( p3d1 );
3092       newV1.Reverse();
3093       newV2 = BRepBuilderAPI_MakeVertex ( p3d2 );
3094       B.UpdateVertex ( newV1, 1.001 * tol1 );
3095       B.UpdateVertex ( newV2, 1.001 * tol2 );
3096     }
3097     else {
3098       newV1 = V1;
3099       newV2 = V2;
3100     }
3101
3102     // prepare new edge
3103     TopoDS_Edge edge;
3104     B.MakeEdge ( edge );
3105     if ( doAddDegen ) B.Degenerated ( edge, Standard_True ); // sln: do it before adding curve
3106     gp_Vec2d v12 ( p2d1, p2d2 );
3107     Handle(Geom2d_Line) theLine2d = new Geom2d_Line ( p2d1, gp_Dir2d ( v12 ) );
3108     B.UpdateEdge ( edge, theLine2d, face, ::Precision::Confusion() );
3109     B.Range ( edge, face, 0, dist2d );
3110     B.Add ( edge, newV1.Oriented ( TopAbs_FORWARD ) );
3111     B.Add ( edge, newV2.Oriented ( TopAbs_REVERSED ) );
3112     ShapeBuild_Edge sbe;
3113     if ( ! doAddDegen && ! sbe.BuildCurve3d ( edge ) ) {
3114       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
3115       return Standard_False; 
3116     }
3117
3118     // if long edge is added, replace vertices of adjacent edges
3119     if ( doAddLong ) {
3120       
3121       // replace 1st edge (n1==n2 - special case: wire consists of one edge)
3122       TopoDS_Edge edge1 = sbe.CopyReplaceVertices ( E1, 
3123                           ( n1 == n2 ? newV2 : TopoDS_Vertex() ), newV1 );
3124       sbwd->Set ( edge1, n1 );
3125       if ( ! Context().IsNull() ) {
3126         Context()->Replace ( E1, edge1 );
3127         // actually, this will occur only in context of single face
3128         // hence, recording to ReShape is rather for tracking modifications
3129         // than for keeping sharing
3130         Context()->Replace ( V1, newV1.Oriented ( V1.Orientation() ) );
3131         if ( ! V1.IsSame ( V2 ) ) { 
3132           Context()->Replace ( V2, newV2.Oriented ( V2.Orientation() ) );
3133         }
3134       }
3135       // replace 2nd edge
3136       if ( n1 != n2 ) {
3137         TopoDS_Edge edge2 = sbe.CopyReplaceVertices ( E2, newV2, TopoDS_Vertex() );
3138         sbwd->Set ( edge2, n2 );
3139         if ( ! Context().IsNull() ) Context()->Replace ( E2, edge2 );
3140       }
3141       if ( ! Context().IsNull() ) UpdateWire();
3142     }
3143
3144     // insert new edge
3145     if ( doAddDegen ) {
3146       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
3147 #ifdef OCCT_DEBUG
3148       std::cout << "Warning: ShapeFix_Wire::FixLacking: degenerated edge added" << std::endl;
3149 #endif
3150     }
3151     else if ( ! doAddLong ) {
3152       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
3153     }
3154     sbwd->Add ( edge, n2 );
3155     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3156   }
3157   
3158   // else try to increase tol up to MaxTol
3159   else if ( inctol > tol && inctol < MaxTolerance() ) {
3160     if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3161          bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
3162     else doIncrease = Standard_True;
3163   }
3164   
3165   // bend pcurves
3166   if ( doBend ) { //:s2 abv 21 Apr 99
3167     B.UpdateEdge ( E1, bendc1, face, bendtol1 );
3168     B.Range ( E1, face, bendf1, bendl1 );
3169     B.UpdateEdge ( E2, bendc2, face, bendtol2 );
3170     B.Range ( E2, face, bendf2, bendl2 );
3171     B.UpdateVertex ( sae.FirstVertex(E1), bendtol1 );
3172     B.UpdateVertex ( sae.LastVertex(E1), bendtol1 );
3173     B.UpdateVertex ( sae.FirstVertex(E2), bendtol2 );
3174     B.UpdateVertex ( sae.LastVertex(E2), bendtol2 );
3175     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
3176     //:s3 abv 22 Apr 99: PRO7187 #11534: self-intersection not detected unitil curve is bent (!)
3177     FixSelfIntersectingEdge ( n1 );
3178     FixSelfIntersectingEdge ( n2 );
3179     FixIntersectingEdges ( n2 ); //skl 24.04.2003 for OCC58
3180 #ifdef OCCT_DEBUG
3181     std::cout << "Info: ShapeFix_Wire::FixLacking: Bending pcurves" << std::endl;
3182 #endif
3183     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
3184   }
3185   
3186   // increase vertex tolerance
3187   if ( doIncrease ) {
3188     B.UpdateVertex ( V1, 1.001 * inctol );
3189     B.UpdateVertex ( V2, 1.001 * inctol );
3190     myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3191   }
3192
3193   if ( LastFixStatus ( ShapeExtend_DONE ) ) return Standard_True;
3194
3195   myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
3196   return Standard_False;
3197 }
3198
3199 //=======================================================================
3200 //function : FixNotchedEdges
3201 //purpose  : 
3202 //=======================================================================
3203
3204 Standard_Boolean ShapeFix_Wire::FixNotchedEdges()
3205 {
3206   myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
3207   if ( ! IsReady() ) return Standard_False;
3208   
3209   Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
3210   TopoDS_Face face = Face();
3211   if ( ! Context().IsNull() ) UpdateWire();
3212   Handle(ShapeExtend_WireData) sewd = WireData();
3213   
3214   for (Standard_Integer i = 1; i <= NbEdges() && NbEdges() > 2; i++) {
3215     Standard_Real param;
3216     Standard_Integer toRemove;
3217     if(theAdvAnalyzer->CheckNotchedEdges(i,toRemove,param,MinTolerance())){
3218       Standard_Integer n2 = (i > 0)  ? i : NbEdges();
3219       Standard_Integer n1 = (n2 > 1) ? n2-1 : NbEdges();
3220       Standard_Boolean isRemoveFirst = (n1==toRemove);
3221       Standard_Integer toSplit = (n2==toRemove ? n1 : n2);
3222       TopoDS_Edge splitE =  sewd->Edge ( toSplit );
3223       ShapeAnalysis_Edge sae;
3224       Handle(Geom2d_Curve) c2d;
3225       Standard_Real a, b;
3226       sae.PCurve ( splitE, face, c2d, a, b, Standard_True );
3227       ShapeBuild_Edge sbe;
3228       TopAbs_Orientation orient = splitE.Orientation();
3229
3230       // check whether the whole edges should be removed - this is the case
3231       // when split point coincides with the end of the edge;
3232       // for closed edges split point may fall at the other end (see issue #0029780)
3233       if (Abs(param - (isRemoveFirst ? b : a)) <= ::Precision::PConfusion() ||
3234           (sae.IsClosed3d(splitE) && Abs(param - (isRemoveFirst ? a : b)) <= ::Precision::PConfusion()))
3235       {
3236         FixDummySeam(n1);
3237         // The seam edge is removed from the list. So, need to step back to avoid missing of edge processing
3238         i--;
3239       }
3240       else // perform splitting of the edge and adding to wire
3241       {
3242         //pdn check if it is necessary
3243         if( Abs((isRemoveFirst ? a : b)-param) < ::Precision::PConfusion() ) {
3244           continue;
3245         }
3246           
3247         Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
3248           new ShapeAnalysis_TransferParametersProj;
3249         transferParameters->SetMaxTolerance(MaxTolerance());
3250         transferParameters->Init(splitE,face);
3251         Standard_Real first, last;
3252         if (a < b ) {
3253           first = a; 
3254           last = b;
3255         }
3256         else {
3257           first = b; 
3258           last = a;
3259         }
3260         TopoDS_Vertex Vnew;
3261         BRep_Builder B;
3262         B.MakeVertex(Vnew,Analyzer()->Surface()->Value(c2d->Value(param)),::Precision::Confusion());
3263         TopoDS_Edge wE = splitE;
3264         wE.Orientation ( TopAbs_FORWARD );
3265         TopoDS_Shape aTmpShape = Vnew.Oriented(TopAbs_REVERSED); //for porting
3266         TopoDS_Edge newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
3267         sbe.CopyPCurves ( newE1, wE  );
3268         transferParameters->TransferRange(newE1,first,param,Standard_True);
3269         B.SameRange(newE1,Standard_False);
3270         B.SameParameter(newE1,Standard_False);
3271         aTmpShape = Vnew.Oriented(TopAbs_FORWARD);
3272         TopoDS_Edge newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
3273         sbe.CopyPCurves ( newE2, wE  );
3274         transferParameters->TransferRange(newE2,param,last,Standard_True);
3275         B.SameRange(newE2,Standard_False);
3276         B.SameParameter(newE2,Standard_False);
3277         
3278         if ( !Context().IsNull() ) {
3279           TopoDS_Wire wire;
3280           B.MakeWire(wire);
3281           B.Add(wire,newE1);
3282           B.Add(wire,newE2);
3283           Context()->Replace ( wE, wire );
3284         }
3285         
3286         newE1.Orientation(orient);
3287         newE2.Orientation(orient);
3288         if (orient==TopAbs_REVERSED){ TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;}
3289         
3290         Standard_Boolean isRemoveLast = ((n1==NbEdges())&&(n2==1));
3291         sewd->Set ( newE1, toSplit);
3292         sewd->Add ( newE2, (toSplit==NbEdges()  ? 0 : toSplit+1));
3293         
3294         FixDummySeam(isRemoveLast ? NbEdges() : toRemove);
3295         myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3296       }
3297   
3298       i--;
3299       if(!Context().IsNull()) //skl 07.03.2002 for OCC180
3300         UpdateWire();
3301       myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3302     }
3303   }
3304   myStatusNotches = myLastFixStatus;
3305   return LastFixStatus ( ShapeExtend_DONE );
3306 }
3307
3308 //=======================================================================
3309 //function : FixDummySeam
3310 //purpose  : 
3311 //=======================================================================
3312
3313 static void CopyReversePcurves(const TopoDS_Edge& toedge, 
3314                                const TopoDS_Edge& fromedge,
3315                                const Standard_Boolean reverse)
3316 {
3317   TopLoc_Location fromLoc = fromedge.Location();
3318   TopLoc_Location toLoc = toedge.Location();
3319   for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3320        ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3321     Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3322     if ( fromGC.IsNull() ) continue;
3323     if ( fromGC->IsCurveOnSurface() ) {
3324       Handle(Geom_Surface) surface = fromGC->Surface();
3325       TopLoc_Location L = fromGC->Location();
3326       Standard_Boolean found = Standard_False;
3327       BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3328       Handle(BRep_GCurve) toGC;
3329       for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3330         toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3331         if ( toGC.IsNull() || !toGC->IsCurveOnSurface() || 
3332             surface != toGC->Surface() || L != toGC->Location() ) continue;
3333         found = Standard_True;
3334         break;
3335       }
3336       if (!found) {
3337         Standard_Real fp = fromGC->First();
3338         Standard_Real lp = fromGC->Last();
3339         toGC = Handle(BRep_GCurve)::DownCast(fromGC->Copy());
3340         tolist.Append (toGC);
3341         Handle(Geom2d_Curve) pcurve = Handle(Geom2d_Curve)::DownCast( fromGC->PCurve()->Copy() );
3342         if (reverse) {
3343           fp = pcurve->ReversedParameter(fp);
3344           lp = pcurve->ReversedParameter(lp);
3345           pcurve->Reverse();
3346           Standard_Real tmp = fp;
3347           fp = lp;
3348           lp = tmp;
3349         }
3350         //bug OCC209 invalid location of pcurve in the edge after copying
3351         TopLoc_Location newLoc = (fromLoc*L).Predivided(toLoc);
3352         toGC->SetRange(fp,lp);  
3353         toGC->PCurve(pcurve);
3354         toGC->Location(newLoc);
3355         if ( fromGC->IsCurveOnClosedSurface() ) {
3356           pcurve = fromGC->PCurve2();
3357           toGC->PCurve2(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
3358         }
3359       }
3360     }
3361   }
3362 }
3363
3364 //=======================================================================
3365 //function : HasNewPCurves
3366 //purpose  : 
3367 //=======================================================================
3368 //  Note:    This function temporarily not used, because adress to it in
3369 //           function FixDummySeam() (see below line 2472) not used too
3370 //
3371 //static Standard_Boolean HasNewPCurves(const TopoDS_Edge& toedge, 
3372 //                                    const TopoDS_Edge& fromedge)
3373 //     
3374 //{
3375 //  for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3376 //       ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3377 //    Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3378 //    if ( fromGC.IsNull() ) continue;
3379 //    if ( fromGC->IsCurveOnSurface() ) {
3380 //      Handle(Geom_Surface) surface = fromGC->Surface();
3381 //      TopLoc_Location L = fromGC->Location();
3382 //      Standard_Boolean found = Standard_False;
3383 //      BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3384 //      Handle(BRep_GCurve) toGC;
3385 //      for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3386 //      toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3387 //      if ( toGC.IsNull() || !toGC->IsCurveOnSurface() || 
3388 //          surface != toGC->Surface() || L != toGC->Location() )  continue;
3389 //      found = Standard_True;
3390 //      break;
3391 //      }
3392 //      if (!found) 
3393 //      return Standard_True;
3394 //    }
3395 //  }
3396 //  return Standard_False;
3397 //}
3398
3399 //=======================================================================
3400 //function : FixDummySeam
3401 //purpose  : 
3402 //=======================================================================
3403
3404 void ShapeFix_Wire::FixDummySeam(const Standard_Integer num)
3405 {
3406   ShapeAnalysis_Edge sae;
3407   ShapeBuild_Edge sbe;
3408   ShapeBuild_Vertex sbv;
3409   Standard_Integer num1 = (num == NbEdges()) ? 1 : num+1;
3410   Handle(ShapeExtend_WireData) sewd = WireData();
3411   TopoDS_Edge E1 = sewd->Edge(num), E2 = sewd->Edge(num1);
3412   TopoDS_Vertex V1 = sae.FirstVertex(E1), V2 = sae.LastVertex(E2);
3413   TopoDS_Vertex Vm = sbv.CombineVertex ( V1, V2, 1.0001 );
3414   
3415   //pnd defining if new pcurves exists
3416   //pdn Temporary not removed
3417 //  Standard_Boolean toRemove = !(HasNewPCurves(E1,E2)||HasNewPCurves(E2,E1));
3418   Standard_Boolean toRemove = Standard_False;
3419   
3420   //creating new edge with pcurves and new vertex
3421   TopoDS_Vertex Vs = sae.FirstVertex(E2);
3422   if ( Vs.IsSame ( V1 ) || Vs.IsSame ( V2 ) ) Vs = Vm;
3423   TopoDS_Edge newEdge = sbe.CopyReplaceVertices ( E2, Vs, Vm );
3424   CopyReversePcurves(newEdge,E1,E1.Orientation()==E2.Orientation());
3425   BRep_Builder B;
3426   B.SameRange(newEdge,Standard_False);
3427   B.SameParameter(newEdge,Standard_False);
3428
3429   if ( !Context().IsNull() ) {
3430     if (toRemove) {
3431       Context()->Remove ( E2 );
3432       Context()->Remove ( E1 );
3433     }
3434     else {
3435       Context()->Replace ( E2, newEdge );
3436       Context()->Replace ( E1, newEdge.Reversed());
3437     }
3438     Context()->Replace ( V1, Vm.Oriented(V1.Orientation()) );
3439     Context()->Replace ( V2, Vm.Oriented(V2.Orientation()) );
3440   }
3441  
3442   Standard_Integer next = ( num1 == NbEdges()) ? 1 : num1+1;
3443   Standard_Integer prev = ( num > 1) ? num-1 : NbEdges();
3444   TopoDS_Edge prevE = sewd->Edge(prev), nextE = sewd->Edge(next);
3445   
3446   TopoDS_Edge tmpE1=sbe.CopyReplaceVertices( prevE, TopoDS_Vertex(), Vm);
3447   sewd->Set ( tmpE1,prev );
3448   if ( !Context().IsNull() ) Context()->Replace ( prevE, tmpE1);
3449   
3450   tmpE1  =  sbe.CopyReplaceVertices ( nextE, Vm, TopoDS_Vertex());
3451   sewd->Set ( tmpE1,next );
3452   if ( !Context().IsNull() ) Context()->Replace ( nextE, tmpE1);
3453   
3454   //removing edges from wire
3455   Standard_Integer n1, n2;
3456   if ( num < num1 ) {
3457     n1 = num; n2 = num1;
3458   } else {
3459     n1 = num1; n2 = num;
3460   }
3461   sewd->Remove(n2);
3462   sewd->Remove(n1);
3463 }
3464
3465 //=======================================================================
3466 //function : UpdateWire
3467 //purpose  : 
3468 //=======================================================================
3469
3470 void ShapeFix_Wire::UpdateWire () 
3471 {
3472   Handle(ShapeExtend_WireData) sbwd = WireData();
3473   for ( Standard_Integer i=1; i <= sbwd->NbEdges(); i++ ) {
3474     TopoDS_Edge E = sbwd->Edge(i);
3475     TopoDS_Shape S = Context()->Apply ( E );
3476     if ( S == E ) continue;
3477     for ( TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next() )
3478       sbwd->Add ( exp.Current(), i++ );
3479     sbwd->Remove ( i-- );
3480   }
3481 }
3482
3483 //=======================================================================
3484 //function : FixTails
3485 //purpose  :
3486 //=======================================================================
3487 Standard_Boolean ShapeFix_Wire::FixTails()
3488 {
3489   if (myMaxTailWidth < 0 || !IsReady())
3490   {
3491     return Standard_False;
3492   }
3493
3494   myLastFixStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
3495   if (!Context().IsNull())
3496   {
3497     UpdateWire();
3498   }
3499   Handle(ShapeExtend_WireData) aSEWD = WireData();
3500   Standard_Integer aECount = NbEdges(), aENs[] = {aECount, 1};
3501   Standard_Boolean aCheckAngle = Standard_True;
3502   while (aECount >= 2 && aENs[1] <= aECount)
3503   {
3504     const TopoDS_Edge aEs[] = {aSEWD->Edge(aENs[0]), aSEWD->Edge(aENs[1])};
3505     TopoDS_Edge aEParts[2][2];
3506     if (!myAnalyzer->CheckTail(aEs[0], aEs[1],
3507       aCheckAngle ? myMaxTailAngleSine : -1, myMaxTailWidth, MaxTolerance(),
3508       aEParts[0][0], aEParts[0][1], aEParts[1][0], aEParts[1][1]))
3509     {
3510       aENs[0] = aENs[1]++;
3511       aCheckAngle = Standard_True;
3512       continue;
3513     }
3514
3515     // Provide not less than 1 edge in the result wire.
3516     Standard_Integer aSplitCounts[] =
3517       {aEParts[0][1].IsNull() ? 0 : 1, aEParts[1][1].IsNull() ? 0 : 1};
3518     const Standard_Integer aRemoveCount =
3519       (aEParts[0][0].IsNull() ? 0 : 1) + (aEParts[1][0].IsNull() ? 0 : 1);
3520     if (aECount + aSplitCounts[0] + aSplitCounts[1] < 1 + aRemoveCount)
3521     {
3522       aENs[0] = aENs[1]++;
3523       aCheckAngle = Standard_True;
3524       continue;
3525     }
3526
3527     // Split the edges.
3528     for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
3529     {
3530       if (aSplitCounts[aEI] == 0)
3531       {
3532         continue;
3533       }
3534
3535       // Replace the edge by the wire of its parts in the shape.
3536       const TopoDS_Edge aE = aEs[aEI];
3537       if (!Context().IsNull())
3538       {
3539         TopoDS_Wire aEWire;
3540         BRep_Builder().MakeWire(aEWire);
3541         BRep_Builder().Add(aEWire, aEParts[aEI][0]);
3542         BRep_Builder().Add(aEWire, aEParts[aEI][1]);
3543         TopoDS_Edge aFE = TopoDS::Edge(aE.Oriented(TopAbs_FORWARD));
3544         Context()->Replace(aFE, aEWire);
3545       }
3546
3547       // Replace the edge by its parts in the edge wire.
3548       const TopAbs_Orientation aOrient = aE.Orientation();
3549       aEParts[aEI][0].Orientation(aOrient);
3550       aEParts[aEI][1].Orientation(aOrient);
3551       const Standard_Integer aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
3552       const Standard_Integer aAdd =
3553         (aEI == 0 || aENs[1] < aENs[0]) ? 0 : aSplitCounts[0];
3554       aSEWD->Set(aEParts[aEI][aFirstPI], aENs[aEI] + aAdd);
3555       aSEWD->Add(aEParts[aEI][1 - aFirstPI], aENs[aEI] + 1 + aAdd);
3556     }
3557
3558     // Remove the tail.
3559     if (aRemoveCount == 2)
3560     {
3561       aCheckAngle = Standard_True;
3562       FixDummySeam(aENs[0] + aSplitCounts[0] +
3563         ((aENs[0] < aENs[1]) ? 0 : aSplitCounts[1]));
3564       if (!Context().IsNull())
3565       {
3566         UpdateWire();
3567       }
3568       myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
3569
3570       if (aSplitCounts[0] + aSplitCounts[1] == 2)
3571       {
3572         aENs[0] = aENs[1]++;
3573         continue;
3574       }
3575
3576       if (aSplitCounts[0] == aSplitCounts[1])
3577       {
3578         aECount -= 2;
3579         if (aENs[1] >= 3)
3580         {
3581           --aENs[0];
3582           --aENs[1];
3583         }
3584         else
3585         {
3586           aENs[0] = aECount;
3587           aENs[1] = 1;
3588         }
3589         aCheckAngle = Standard_False;
3590       }
3591       else
3592       {
3593         --aECount;
3594         if (aSplitCounts[0] != 0)
3595         {
3596           aENs[0] = (aENs[0] <= aECount) ? aENs[0] : aECount;
3597         }
3598         else
3599         {
3600           if (aENs[1] >= 3)
3601           {
3602             --aENs[0];
3603             --aENs[1];
3604           }
3605           else
3606           {
3607             aENs[0] = aECount;
3608             aENs[1] = 1;
3609           }
3610         }
3611       }
3612     }
3613     else
3614     {
3615       aCheckAngle = Standard_False;
3616       --aECount;
3617       const Standard_Integer aRI = aEParts[0][0].IsNull() ? 1 : 0;
3618       if (aSplitCounts[aRI] != 0)
3619       {
3620         if (aRI == 0)
3621         {
3622           if (aENs[1] >= 3)
3623           {
3624             --aENs[0];
3625             --aENs[1];
3626           }
3627           else
3628           {
3629             aENs[0] = aECount;
3630             aENs[1] = 1;
3631           }
3632         }
3633         else
3634         {
3635           aENs[0] = (aENs[1] > 1) ? aENs[0] : aECount;
3636         }
3637       }
3638       aSEWD->Remove(aENs[aRI] + ((aRI != 0 || aSplitCounts[0] == 0) ? 0 : 1));
3639       if (!Context().IsNull())
3640       {
3641         Context()->Remove(aEs[aRI].Oriented(TopAbs_FORWARD));
3642         UpdateWire();
3643       }
3644       myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
3645     }
3646   }
3647   myStatusNotches = myLastFixStatus;
3648   return ShapeExtend::DecodeStatus(myLastFixStatus, ShapeExtend_DONE);
3649 }