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