3be3e1d1d4e7a3c64e52d2496cfe67a0af67f493
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_Sewing.cxx
1 // Created on: 1995-03-24
2 // Created by: Jing Cheng MEI
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // dcl          CCI60011 : Correction of degeneratedSection
18 //              Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
19 // dcl          Thu Aug 20 09:24:49 1998
20 //              Suppression of little faces.
21 // dcl          Fri Aug  7 15:27:46 1998
22 //                Refection of function SameParameter Edge.
23 //              Merge on the edge which has the less of poles.
24 //              Suppression of the Connected Edge function.
25 // dcl          Tue Jun  9 14:21:53 1998
26 //              Do not merge edge if they belong the same face
27 //              Tolerance management in VerticesAssembling
28 //              Tolerance management in Cutting
29 // dcl          Thu May 14 15:51:46 1998
30 //              optimization of cutting
31 // dcl          Thu May 7  15:51:46 1998
32 //              Add of cutting option
33 //              Add of SameParameter call
34
35
36 //-- lbr April 1 97
37 //-- dpf December 10 1997 Processing of pcurve collections
38
39 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode 
40 //rln 02.02.99 BUC60449 Protection against exception on NT
41
42 #define TEST 1
43
44
45 #include <Bnd_Box.hxx>
46 #include <Bnd_Box2d.hxx>
47 #include <Bnd_HArray1OfBox.hxx>
48 #include <BndLib_Add2dCurve.hxx>
49 #include <BndLib_Add3dCurve.hxx>
50 #include <BRep_Builder.hxx>
51 #include <BRep_ListOfPointRepresentation.hxx>
52 #include <BRep_PointOnCurve.hxx>
53 #include <BRep_Tool.hxx>
54 #include <BRep_TVertex.hxx>
55 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
56 #include <BRepBuilderAPI_CellFilter.hxx>
57 #include <BRepBuilderAPI_Sewing.hxx>
58 #include <BRepBuilderAPI_VertexInspector.hxx>
59 #include <BRepLib.hxx>
60 #include <BRepTools.hxx>
61 #include <BRepTools_Quilt.hxx>
62 #include <BRepTools_ReShape.hxx>
63 #include <BSplCLib.hxx>
64 #include <Extrema_ExtPC.hxx>
65 #include <GCPnts_AbscissaPoint.hxx>
66 #include <GCPnts_UniformAbscissa.hxx>
67 #include <GCPnts_UniformDeflection.hxx>
68 #include <Geom2d_BezierCurve.hxx>
69 #include <Geom2d_BSplineCurve.hxx>
70 #include <Geom2d_Curve.hxx>
71 #include <Geom2d_Line.hxx>
72 #include <Geom2d_TrimmedCurve.hxx>
73 #include <Geom2dAdaptor_Curve.hxx>
74 #include <Geom2dConvert.hxx>
75 #include <Geom_BezierCurve.hxx>
76 #include <Geom_BSplineCurve.hxx>
77 #include <Geom_Curve.hxx>
78 #include <Geom_Line.hxx>
79 #include <Geom_OffsetSurface.hxx>
80 #include <Geom_RectangularTrimmedSurface.hxx>
81 #include <Geom_Surface.hxx>
82 #include <GeomAdaptor_Curve.hxx>
83 #include <GeomAdaptor_Surface.hxx>
84 #include <GeomLib.hxx>
85 #include <gp_Pnt.hxx>
86 #include <gp_Vec.hxx>
87 #include <Message_ProgressIndicator.hxx>
88 #include <Message_ProgressSentry.hxx>
89 #include <NCollection_UBTreeFiller.hxx>
90 #include <Precision.hxx>
91 #include <Standard_ErrorHandler.hxx>
92 #include <Standard_Failure.hxx>
93 #include <Standard_NoSuchObject.hxx>
94 #include <Standard_OutOfRange.hxx>
95 #include <Standard_Type.hxx>
96 #include <TColgp_Array1OfVec.hxx>
97 #include <TColgp_SequenceOfPnt.hxx>
98 #include <TColStd_Array1OfInteger.hxx>
99 #include <TColStd_Array1OfReal.hxx>
100 #include <TColStd_Array2OfReal.hxx>
101 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
102 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
103 #include <TColStd_IndexedMapOfInteger.hxx>
104 #include <TColStd_ListIteratorOfListOfInteger.hxx>
105 #include <TColStd_ListOfInteger.hxx>
106 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
107 #include <TColStd_MapOfInteger.hxx>
108 #include <TColStd_SequenceOfReal.hxx>
109 #include <TopAbs.hxx>
110 #include <TopExp.hxx>
111 #include <TopExp_Explorer.hxx>
112 #include <TopLoc_Location.hxx>
113 #include <TopoDS.hxx>
114 #include <TopoDS_Compound.hxx>
115 #include <TopoDS_Edge.hxx>
116 #include <TopoDS_Face.hxx>
117 #include <TopoDS_Iterator.hxx>
118 #include <TopoDS_Shape.hxx>
119 #include <TopoDS_Shell.hxx>
120 #include <TopoDS_Vertex.hxx>
121 #include <TopoDS_Wire.hxx>
122 #include <TopTools_Array1OfShape.hxx>
123 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
124 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
125 #include <TopTools_DataMapOfShapeInteger.hxx>
126 #include <TopTools_DataMapOfShapeListOfShape.hxx>
127 #include <TopTools_ListIteratorOfListOfShape.hxx>
128 #include <TopTools_ListOfShape.hxx>
129 #include <TopTools_MapIteratorOfMapOfShape.hxx>
130 #include <TopTools_MapOfShape.hxx>
131 #include <TopTools_SequenceOfShape.hxx>
132
133 IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_Sewing,MMgt_TShared)
134
135 //#include <LocalAnalysis_SurfaceContinuity.hxx>
136 //=======================================================================
137 //function : SameRange
138 //purpose  : 
139 //=======================================================================
140 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
141                                                 const Standard_Real FirstOnCurve,
142                                                 const Standard_Real LastOnCurve,
143                                                 const Standard_Real RequestedFirst,
144                                                 const Standard_Real RequestedLast) const
145 {
146   Handle(Geom2d_Curve) NewCurvePtr;
147   try {
148     
149     GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
150                        RequestedFirst,RequestedLast,NewCurvePtr);
151   }
152   catch (Standard_Failure) {
153 #ifdef OCCT_DEBUG
154     cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
155     Standard_Failure::Caught()->Print(cout); cout << endl;
156 #endif
157   }
158   return NewCurvePtr;
159 }
160
161 //=======================================================================
162 //function : WhichFace
163 //purpose  : Give the face whose edge is the border
164 //=======================================================================
165
166 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
167 {
168   TopoDS_Shape bound = theEdg;
169   if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
170   if (myBoundFaces.Contains(bound)) {
171     Standard_Integer i = 1;
172     TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
173     for (; itf.More(); itf.Next(), i++)
174       if (i == index) return TopoDS::Face(itf.Value());
175   }
176   return TopoDS_Face();
177 }
178
179 //=======================================================================
180 //function : IsClosedShape
181 //purpose  : 
182 //=======================================================================
183
184 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
185                                       const TopoDS_Shape& v1, const TopoDS_Shape& v2)
186 {
187   Standard_Real TotLength = 0.0;
188   TopExp_Explorer aexp;
189   for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
190     TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
191     if (aedge.IsNull()) continue;
192     TopoDS_Vertex ve1,ve2;
193     TopExp::Vertices(aedge,ve1,ve2);
194     if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
195     if (BRep_Tool::Degenerated(aedge)) continue;
196     Standard_Real first,last;
197     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
198     if (!c3d.IsNull()) {
199       GeomAdaptor_Curve cAdapt(c3d);
200       Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
201       TotLength += length;
202       if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
203     }
204   }
205   if (TotLength > 0.0) {
206     gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
207     gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
208     return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
209   }
210   return Standard_False;
211 }
212
213 //=======================================================================
214 //function : IsClosedByIsos
215 //purpose  : 
216 //=======================================================================
217 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
218                                        const Handle(Geom2d_Curve)& acrv2d,
219                                        const Standard_Real f2d,
220                                        const  Standard_Real l2d,
221                                        const Standard_Boolean isUIsos) 
222 {
223   Standard_Boolean isClosed = Standard_False;
224  
225   gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ? 
226                      acrv2d->Value(f2d) :  acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
227   gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ? 
228                      acrv2d->Value(l2d) :  acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
229   Handle(Geom_Curve) aCrv1;
230   Handle(Geom_Curve) aCrv2;
231   if(isUIsos) {
232     aCrv1 = thesurf->UIso(psurf1.X());
233     aCrv2 = thesurf->UIso(psurf2.X());
234   }
235   else {
236     aCrv1 = thesurf->VIso(psurf1.Y());
237     aCrv2 = thesurf->VIso(psurf2.Y());
238   }
239   gp_Pnt p11,p1m,p12,p21,p2m,p22;
240   Standard_Real af1 = aCrv1->FirstParameter();
241   Standard_Real al1 = aCrv1->LastParameter();
242   Standard_Real af2 = aCrv2->FirstParameter();
243   Standard_Real al2 = aCrv2->LastParameter();
244   aCrv1->D0(af1,p11);
245   aCrv1->D0((af1+al1)*0.5,p1m);
246   aCrv1->D0(al1,p12);
247   aCrv2->D0(af2,p21);
248   aCrv2->D0((af2+al2)*0.5,p2m);
249   aCrv2->D0(al2,p22);
250   isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() < 
251                (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
252               ((p21.XYZ() - p22.XYZ()).Modulus() < 
253                (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
254   return isClosed;
255 }
256 //=======================================================================
257 //function : IsUClosedSurface
258 //purpose  : 
259 //=======================================================================
260
261 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
262                                                    const TopoDS_Shape& theEdge,
263                                                    const TopLoc_Location& theloc) const
264 {
265   Handle(Geom_Surface) tmpsurf = surf;
266   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
267     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
268   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
269     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
270   else {
271     Standard_Boolean isClosed = tmpsurf->IsUClosed();
272     if(!isClosed) {
273       Standard_Real f2d, l2d;
274       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
275       if(!acrv2d.IsNull())
276         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
277       
278     }
279     return isClosed;
280   }
281   return IsUClosedSurface(tmpsurf,theEdge,theloc);
282   //return surf->IsUClosed();
283 }
284
285 //=======================================================================
286 //function : IsVClosedSurface
287 //purpose  : 
288 //=======================================================================
289
290 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
291                                                    const TopoDS_Shape& theEdge,
292                                                    const TopLoc_Location& theloc) const
293 {
294   Handle(Geom_Surface) tmpsurf = surf;
295   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
296     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
297   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
298     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
299   else {
300     Standard_Boolean isClosed = tmpsurf->IsVClosed();
301     if(!isClosed) {
302       Standard_Real f2d, l2d;
303       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
304       if(!acrv2d.IsNull())
305         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
306     }
307     return isClosed;
308   }
309   return IsVClosedSurface(tmpsurf,theEdge,theloc);
310   //return surf->IsVClosed();
311 }
312
313 //=======================================================================
314 //function : SameParameter
315 //purpose  : internal use
316 //=======================================================================
317
318 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
319 {
320   try {
321     
322     BRepLib::SameParameter(edge);
323   }
324   catch (Standard_Failure) {
325 #ifdef OCCT_DEBUG
326     cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
327     Standard_Failure::Caught()->Print(cout); cout << endl;
328 #endif
329   }
330 }
331
332 //=======================================================================
333 //function : SameParameterEdge
334 //purpose  : internal use
335 //           Merge the Sequence Of Section on one edge.
336 //           This function keep the curve3d,curve2d,range and parametrization
337 //           from the first section, and report and made sameparameter the
338 //           pcurves of the other function.
339 //           This function works when the are not more than two Pcurves
340 //           on a same face.
341 //=======================================================================
342
343 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
344                                                const TopTools_SequenceOfShape& seqEdges,
345                                                const TColStd_SequenceOfInteger& seqForward,
346                                                TopTools_MapOfShape& mapMerged,
347                                                const Handle(BRepTools_ReShape)& locReShape)
348 {
349   // Retrieve reference section
350   TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
351   TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
352   aTmpShape = locReShape->Apply(Edge1);
353   if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
354   Standard_Boolean isDone = Standard_False;
355
356   // Create data structures for temporary merged edges
357   TopTools_ListOfShape listFaces1;
358   TopTools_MapOfShape MergedFaces;
359
360   if (mySewing) {
361
362     // Fill MergedFaces with faces of Edge1
363     TopoDS_Shape bnd1 = edge;
364     if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
365     if (myBoundFaces.Contains(bnd1)) {
366       TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
367       for (; itf.More(); itf.Next())
368         if (MergedFaces.Add(itf.Value()))
369           listFaces1.Append(itf.Value());
370     }
371   }
372   else {
373
374     // Create presentation edge
375     TopoDS_Vertex V1, V2;
376     TopExp::Vertices(Edge1,V1,V2);
377     if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
378     if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
379
380     TopoDS_Edge NewEdge = Edge1;
381     NewEdge.EmptyCopy();
382
383     // Add the vertices
384     BRep_Builder aBuilder;
385     TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
386     aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
387     aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
388
389     Edge1 = NewEdge;
390   }
391
392   Standard_Boolean isForward = Standard_True;
393
394   // Merge candidate sections
395   for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
396
397     // Retrieve candidate section
398     TopoDS_Shape oedge2 = seqEdges(i);
399
400     if (mySewing) {
401
402       aTmpShape = myReShape->Apply(oedge2); //for porting
403       TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
404       aTmpShape = locReShape->Apply(Edge2);
405       if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
406
407       // Calculate relative orientation
408       Standard_Integer Orientation = seqForward(i);
409       if (!isForward) Orientation = (Orientation? 0 : 1);
410
411       // Retrieve faces information for the second edge
412       TopoDS_Shape bnd2 = oedge2;
413       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
414       if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
415       const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
416
417       Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
418       TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
419       if (NewEdge.IsNull()) continue;
420
421       // Record faces information for the temporary merged edge
422       TopTools_ListIteratorOfListOfShape itf(listFaces2);
423       for (; itf.More(); itf.Next())
424         if (MergedFaces.Add(itf.Value()))
425           listFaces1.Append(itf.Value());
426
427       // Record merged section orientation
428       if (!Orientation && whichSec != 1)
429         isForward = isForward? Standard_False : Standard_True;
430       Edge1 = NewEdge;
431     }
432
433     // Append actually merged edge
434     mapMerged.Add(oedge2);
435     isDone = Standard_True;
436
437     if (!myNonmanifold) break;
438   }
439
440   if (isDone) {
441     // Change result orientation
442     Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
443   }
444   else Edge1.Nullify();
445
446   return Edge1;
447 }
448
449 //=======================================================================
450 //function : SameParameterEdge
451 //purpose  : internal use
452 //=======================================================================
453 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
454                                        TopTools_SequenceOfShape& theSeqNMVert,
455                                        TColStd_SequenceOfReal& theSeqPars)
456 {
457   TopoDS_Iterator aItV(theEdge,Standard_False);
458   for( ; aItV.More(); aItV.Next()) {
459     if(aItV.Value().Orientation() == TopAbs_INTERNAL || 
460         aItV.Value().Orientation() == TopAbs_EXTERNAL)
461     theSeqNMVert.Append(aItV.Value());
462   }
463   Standard_Integer nbV = theSeqNMVert.Length();
464   if(!nbV)
465     return Standard_False;
466   Standard_Real first, last;
467   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
468   GeomAdaptor_Curve GAC(c3d);
469   Extrema_ExtPC locProj;
470   locProj.Initialize(GAC, first, last);
471   gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
472
473   
474   for (Standard_Integer i = 1; i <= nbV; i++) {
475     TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
476     gp_Pnt pt = BRep_Tool::Pnt(aV);
477     
478     Standard_Real distF2 = pfirst.SquareDistance(pt);
479     Standard_Real distL2 = plast.SquareDistance(pt);
480     Standard_Real apar = (distF2 > distL2 ? last : first);
481     // Project current point on curve
482     locProj.Perform(pt);
483     if (locProj.IsDone() && locProj.NbExt() > 0) {
484           Standard_Real dist2Min = Min(distF2,distL2);
485           Standard_Integer ind, indMin = 0;
486           for (ind = 1; ind <= locProj.NbExt(); ind++) {
487             Standard_Real dProj2 = locProj.SquareDistance(ind);
488             if (dProj2 < dist2Min) { 
489           indMin = ind; dist2Min = dProj2; 
490         }
491       }
492       if(indMin) 
493         apar = locProj.Point(indMin).Parameter();
494          
495       theSeqPars.Append(apar);  
496         
497     }
498   }
499   return Standard_True;
500 }
501
502 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
503                                    TopoDS_Vertex& theNewV)
504 {
505   Standard_Integer m, n;
506   Standard_Real aR[2], dR, aD, aEps;
507   TopoDS_Vertex aV[2];
508   gp_Pnt aP[2];
509   BRep_Builder aBB;
510   //
511   aEps = RealEpsilon();
512   aV[0] = theV1;
513   aV[1] = theV2;
514   for (m = 0; m < 2; ++m) {
515     aP[m] = BRep_Tool::Pnt(aV[m]);
516     aR[m] = BRep_Tool::Tolerance(aV[m]);
517     }  
518     //
519   m=0; // max R
520   n=1; // min R
521   if (aR[0] < aR[1]) {
522     m=1;
523     n=0;
524   }
525   //
526   dR = aR[m] - aR[n]; // dR >= 0.
527   gp_Vec aVD(aP[m], aP[n]);
528   aD = aVD.Magnitude();
529   //
530   if (aD <= dR || aD < aEps) { 
531     aBB.MakeVertex (theNewV, aP[m], aR[m]);
532   }
533   else {
534     Standard_Real aRr;
535     gp_XYZ aXYZr;
536     gp_Pnt aPr;
537     //
538     aRr = 0.5 * (aR[m] + aR[n] + aD);
539     aXYZr = 0.5 * (aP[m].XYZ() + aP[n].XYZ() - aVD.XYZ() * (dR/aD));
540     aPr.SetXYZ(aXYZr);
541     //
542     aBB.MakeVertex (theNewV, aPr, aRr);
543   }
544   return;
545 }
546
547 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
548                                    TopoDS_Vertex theV3, TopoDS_Vertex& theNewV)
549 {
550   Standard_Real aDi, aDmax;
551   gp_Pnt aCenter;
552   gp_Pnt aP[3];
553   Standard_Real aR[3];
554   TopoDS_Vertex aV[3];
555   gp_XYZ aXYZ(0.,0.,0.);
556   aV[0] = theV1;
557   aV[1] = theV2;
558   aV[2] = theV3;
559   for (Standard_Integer i = 0; i < 3; ++i) {
560     aP[i] = BRep_Tool::Pnt(aV[i]);
561     aR[i] = BRep_Tool::Tolerance(aV[i]);
562     aXYZ = aXYZ + aP[i].XYZ();
563   }
564   //
565   aXYZ.Divide(3.0);
566   aCenter.SetXYZ(aXYZ);
567   //
568   aDmax=-1.;
569   for ( Standard_Integer i = 0; i < 3; ++i) {
570     aDi = aCenter.Distance(aP[i]);
571     aDi += aR[i];
572     if (aDi > aDmax)
573       aDmax = aDi;
574   }
575
576   BRep_Builder aBB;
577   aBB.MakeVertex (theNewV, aCenter, aDmax);
578   return;
579 }
580
581 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
582                                                const TopoDS_Edge& edgeLast,
583                                                const TopTools_ListOfShape& listFacesFirst,
584                                                const TopTools_ListOfShape& listFacesLast,
585                                                const Standard_Boolean secForward, 
586                                                Standard_Integer& whichSec,
587                                                const Standard_Boolean firstCall)
588 {
589   // Do not process floating edges
590   if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
591
592   // Sort input edges
593   TopoDS_Edge edge1, edge2;
594   if (firstCall) {
595     // Take the longest edge as first
596     Standard_Real f, l;
597     Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
598     GeomAdaptor_Curve cAdapt1(c3d1);
599     Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
600     Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
601     GeomAdaptor_Curve cAdapt2(c3d2);
602     Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
603     if (len1 < len2) {
604       edge1 = edgeLast;
605       edge2 = edgeFirst;
606       whichSec = 2;
607     }
608     else {
609       edge1 = edgeFirst;
610       edge2 = edgeLast;
611       whichSec = 1;
612     }
613   }
614   else {
615     if (whichSec == 1) {
616       edge1 = edgeLast;
617       edge2 = edgeFirst;
618       whichSec = 2;
619     }
620     else {
621       edge1 = edgeFirst;
622       edge2 = edgeLast;
623       whichSec = 1;
624     }
625   }
626
627   Standard_Real first, last;
628   BRep_Tool::Range(edge1, first, last);
629   BRep_Builder aBuilder;
630
631   //To keep NM vertices on edge
632   TopTools_SequenceOfShape aSeqNMVert;
633   TColStd_SequenceOfReal aSeqNMPars;
634   findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
635   findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
636
637   // Create new edge
638   TopoDS_Edge edge;
639   aBuilder.MakeEdge(edge);
640   edge.Orientation( edge1.Orientation());
641  
642
643   // Retrieve edge curve
644   TopLoc_Location loc3d;
645   Standard_Real first3d, last3d;
646   Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
647   if (!loc3d.IsIdentity()) {
648     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
649     c3d->Transform(loc3d.Transformation());
650   }
651   aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
652   aBuilder.Range(edge, first, last);
653   aBuilder.SameRange(edge, Standard_False); //Standard_True
654   aBuilder.SameParameter(edge, Standard_False);
655   // Create and add new vertices
656   {
657     TopoDS_Vertex V1New, V2New;
658
659     // Retrieve original vertices from edges
660     TopoDS_Vertex V11,V12,V21,V22;
661     TopExp::Vertices(edge1,V11,V12);
662     TopExp::Vertices(edge2,V21,V22);
663
664     //check that edges merged valid way (for edges having length less than specified
665     //tolerance
666     // Check if edges are closed
667     Standard_Boolean isClosed1 = V11.IsSame(V12);
668     Standard_Boolean isClosed2 = V21.IsSame(V22);
669     if(!isClosed1 && !isClosed2)
670     {
671       if(secForward )
672       {
673         if( V11.IsSame(V22) || V12.IsSame(V21) )
674           return TopoDS_Edge();
675       }
676       else
677       {
678         if( V11.IsSame(V21) || V12.IsSame(V22) )
679           return TopoDS_Edge();
680       }
681     }
682
683     //szv: do not reshape here!!!
684     //V11 = TopoDS::Vertex(myReShape->Apply(V11));
685     //V12 = TopoDS::Vertex(myReShape->Apply(V12));
686     //V21 = TopoDS::Vertex(myReShape->Apply(V21));
687     //V22 = TopoDS::Vertex(myReShape->Apply(V22));
688
689     //Standard_Boolean isRev = Standard_False;
690     if (isClosed1 || isClosed2) {
691       // at least one of the edges is closed
692       if (isClosed1 && isClosed2) {
693         // both edges are closed
694         ComputeToleranceVertex(V11, V21, V1New);
695       }
696       else if (isClosed1) {
697         // only first edge is closed
698         ComputeToleranceVertex(V22, V21, V11, V1New);
699       }
700       else {
701         // only second edge is closed
702         ComputeToleranceVertex(V11, V12, V21, V1New);
703       }
704       V2New = V1New;
705     }
706     else {
707       // both edges are open
708       Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) :  V11.IsSame(V22) );
709       Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
710       if (secForward) {
711         //case if vertices already sewed
712         if(!isOldFirst)
713         {
714           ComputeToleranceVertex(V11, V21, V1New);
715         }
716         if(!isOldLast)
717         {
718           ComputeToleranceVertex(V12, V22, V2New);
719         }
720       }
721       else {
722         if(!isOldFirst)
723         {
724           ComputeToleranceVertex(V11, V22, V1New);
725         }
726         if(!isOldLast)
727         {
728           ComputeToleranceVertex(V12, V21, V2New);
729         }
730       }
731       if(isOldFirst)
732         V1New = V11;
733
734       if(isOldLast)
735         V2New = V12;
736     }
737     // Add the vertices in the good sense
738     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
739     TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
740     aBuilder.Add(anEdge,aLocalEdge);
741     aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
742     aBuilder.Add(anEdge,aLocalEdge);
743
744     Standard_Integer k =1;
745     for( ; k <= aSeqNMVert.Length(); k++)
746       aBuilder.Add(anEdge,aSeqNMVert.Value(k));
747
748   }
749
750   // Retrieve second PCurves
751   TopLoc_Location loc2;
752   Handle(Geom_Surface) surf2;
753   
754   //Handle(Geom2d_Curve) c2d2, c2d21;
755   //  Standard_Real firstOld, lastOld;
756
757   TopTools_ListIteratorOfListOfShape itf2;
758   if (whichSec == 1) itf2.Initialize(listFacesLast);
759   else               itf2.Initialize(listFacesFirst);
760   Standard_Boolean isResEdge = Standard_False;
761   TopoDS_Face fac2;
762   for (; itf2.More(); itf2.Next()) {
763     Handle(Geom2d_Curve) c2d2, c2d21;
764     Standard_Real firstOld, lastOld;
765     fac2 = TopoDS::Face(itf2.Value());
766
767     surf2 = BRep_Tool::Surface(fac2, loc2);
768     Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
769       BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
770     if (isSeam2) {
771       if (!myNonmanifold) return TopoDS_Edge();
772       TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
773       c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
774     }
775     c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
776     if (c2d2.IsNull() && c2d21.IsNull()) continue;
777
778     if (!c2d21.IsNull()) {
779       c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
780       if (!secForward) {
781         if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
782           c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
783         Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
784         Standard_Real last2d = lastOld;   //c2dTmp->LastParameter();
785         firstOld = c2d21->ReversedParameter(last2d);
786         lastOld = c2d21->ReversedParameter(first2d);
787         c2d21->Reverse();
788       }
789       c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
790     }
791
792     // Make second PCurve sameRange with the 3d curve
793     c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
794     
795     if (!secForward) {
796       if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
797         c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
798       Standard_Real first2d = firstOld; 
799       Standard_Real last2d = lastOld;   
800       firstOld = c2d2->ReversedParameter(last2d);
801       lastOld = c2d2->ReversedParameter(first2d);
802       c2d2->Reverse();
803     }
804
805     c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
806     if (c2d2.IsNull()) continue;
807
808     // Add second PCurve
809     Standard_Boolean isSeam = Standard_False;
810     TopAbs_Orientation Ori = TopAbs_FORWARD;
811     //Handle(Geom2d_Curve) c2d1, c2d11;
812
813     TopTools_ListIteratorOfListOfShape itf1;
814     if (whichSec == 1) itf1.Initialize(listFacesFirst);
815     else               itf1.Initialize(listFacesLast);
816     for (; itf1.More() && !isSeam; itf1.Next()) {
817       Handle(Geom2d_Curve) c2d1, c2d11;
818       const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
819
820       TopLoc_Location loc1;
821       Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
822       
823       Standard_Real first2d, last2d;
824       Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
825         BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
826       c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
827       Ori = edge1.Orientation();
828       if (fac1.Orientation() == TopAbs_REVERSED) 
829         Ori = TopAbs::Reverse(Ori);
830
831       if (isSeam1) {
832         if (!myNonmanifold) return TopoDS_Edge();
833         TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
834         c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
835         //if(fac1.Orientation() == TopAbs_REVERSED) //
836         if(Ori == TopAbs_FORWARD)
837           aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
838         else
839           aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
840       }
841       else  aBuilder.UpdateEdge(edge,c2d1,fac1,0);
842
843       if (c2d1.IsNull() && c2d11.IsNull()) continue;
844
845       if (surf2 == surf1) {
846         // Merge sections which are on the same face
847         if (!loc2.IsDifferent(loc1)) {
848           Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
849           Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
850           if (uclosed || vclosed) {
851             Standard_Real pf = c2d1->FirstParameter();
852             //      Standard_Real pl = c2d1->LastParameter();
853             gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
854             //      gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
855             gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
856             gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
857             Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
858             Standard_Real U1, U2, V1, V2;
859             surf2->Bounds(U1, U2, V1, V2);
860             isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
861               (vclosed && aDist > 0.75*(fabs(V2-V1))));
862             if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
863           }
864         }
865       }
866
867       isResEdge = Standard_True;
868       if (isSeam) {
869         if (Ori == TopAbs_FORWARD)
870           aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
871         else
872           aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
873       }
874       else if (isSeam2) {
875         TopAbs_Orientation InitOri  = edge2.Orientation();
876         TopAbs_Orientation SecOri  = edge.Orientation();
877         if (fac2.Orientation() == TopAbs_REVERSED) {
878
879           InitOri = TopAbs::Reverse(InitOri);
880           SecOri = TopAbs::Reverse(SecOri);
881         }
882         if(!secForward)
883           InitOri = TopAbs::Reverse(InitOri);
884
885         if (InitOri == TopAbs_FORWARD)
886           aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
887         else
888           aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
889       } 
890       else {
891         aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
892       }
893
894     }
895   }
896   Standard_Real tolReached = Precision::Infinite();
897   Standard_Boolean isSamePar = Standard_False; 
898   try
899   {
900     if( isResEdge)
901       SameParameter(edge);
902     
903
904     if( BRep_Tool::SameParameter(edge))
905     {
906       isSamePar = Standard_True;
907       tolReached = BRep_Tool::Tolerance(edge);
908     }
909   }
910   
911   catch(Standard_Failure)
912   {
913     isSamePar = Standard_False;
914   }
915  
916  
917   if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
918     Standard_Integer whichSecn = whichSec;
919     // Try to merge on the second section
920     Standard_Boolean second_ok = Standard_False;
921     TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
922       secForward,whichSecn,Standard_False);
923     if( !s_edge.IsNull())
924     {
925       Standard_Real tolReached_2  = BRep_Tool::Tolerance(s_edge);
926       second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
927       if( second_ok)
928       {
929         edge = s_edge;
930         whichSec = whichSecn;
931         tolReached = tolReached_2;
932       }
933     }
934
935     if (!second_ok && !edge.IsNull()) {
936
937       GeomAdaptor_Curve c3dAdapt(c3d);
938
939       // Discretize edge curve
940       Standard_Integer i, j, nbp = 23;
941       Standard_Real deltaT = (last3d - first3d) / (nbp -1);
942       TColgp_Array1OfPnt c3dpnt(1,nbp);
943       for (i = 1; i <= nbp; i++) 
944         c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT);
945
946       Standard_Real dist = 0., maxTol = -1.0;
947       Standard_Boolean more = Standard_True;
948
949       for (j = 1; more; j++) {
950         Handle(Geom2d_Curve) c2d2;
951         BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
952             
953         more = !c2d2.IsNull();
954         if (more) {
955           Handle(Geom_Surface) aS = surf2;
956           if(!loc2.IsIdentity())
957             aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
958
959           Standard_Real dist2 = 0.;
960           deltaT = (last - first) / (nbp - 1);
961           for (i = 1; i <= nbp; i++) {
962             gp_Pnt2d aP2d =  c2d2->Value(first + (i -1)*deltaT);
963             gp_Pnt aP2(0.,0.,0.);
964             aS->D0(aP2d.X(),aP2d.Y(), aP2);
965             gp_Pnt aP1 = c3dpnt(i);
966             dist = aP2.SquareDistance(aP1);
967             if (dist > dist2) 
968               dist2 = dist;
969           }
970           maxTol = Max(sqrt(dist2), Precision::Confusion());
971         }
972       }
973       if(maxTol >= 0. && maxTol < tolReached)
974         aBuilder.UpdateEdge(edge, maxTol);
975       aBuilder.SameParameter(edge,Standard_True);
976     }
977   }
978
979   BRepLib::EncodeRegularity(edge,0.01);
980   Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
981   if (tolEdge1 > MaxTolerance()) edge.Nullify();
982   return edge;
983 }
984
985 //=======================================================================
986 // function : EvaluateAngulars
987 // purpose  : internal use
988 //=======================================================================
989
990 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
991                                        TColStd_Array1OfBoolean& secForward,
992                                        TColStd_Array1OfReal& tabAng,
993                                        const Standard_Integer indRef) const
994 {
995   tabAng.Init(-1.0);
996
997   Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
998
999   TopoDS_Edge edge;
1000   TopoDS_Face face;
1001   TopLoc_Location loc;
1002   Standard_Real first, last;
1003   Handle(Geom_Curve) c3d;
1004   Handle(Geom2d_Curve) c2d;
1005   Handle(Geom_Surface) surf;
1006   TColgp_Array1OfVec normRef(1,npt);
1007
1008   for (i = indRef; i <= lengSec; i++) {
1009
1010     edge = TopoDS::Edge(sequenceSec(i));
1011
1012     TopoDS_Shape bnd = edge;
1013     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1014     if (myBoundFaces.Contains(bnd)) {
1015       face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
1016       surf = BRep_Tool::Surface(face,loc);
1017       if (!loc.IsIdentity()) {
1018         surf = Handle(Geom_Surface)::DownCast(surf->Copy());
1019         surf->Transform(loc.Transformation());
1020       }
1021       c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
1022     }
1023     else if (i == indRef) return;
1024     else continue;
1025
1026     c3d = BRep_Tool::Curve(edge, loc, first, last);
1027     if (!loc.IsIdentity()) {
1028       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1029       c3d->Transform(loc.Transformation());
1030     }
1031
1032     GeomAdaptor_Curve adapt(c3d);
1033     GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1034
1035     Standard_Real cumulateAngular = 0.0;
1036     Standard_Integer nbComputedAngle = 0;
1037
1038     for (j = 1; j <= npt; j++) {
1039       gp_Pnt2d P;
1040       c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1041       gp_Vec w1, w2;
1042       gp_Pnt unused;
1043       surf->D1(P.X(), P.Y(), unused, w1, w2);
1044       gp_Vec n = w1^w2; // Compute the normal vector
1045       if (i == indRef) normRef(j) = n;
1046       else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1047         nbComputedAngle++;
1048         Standard_Real angular = n.Angle(normRef(j));
1049         if (angular > M_PI/2.) angular = M_PI - angular;
1050         cumulateAngular += angular;
1051       }
1052     }
1053
1054     if (nbComputedAngle)
1055       tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1056   }
1057 }
1058
1059 //=======================================================================
1060 // function : EvaluateDistances
1061 // purpose  : internal use
1062 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1063 // Remarks (lengSec - indRef) must be >= 1 
1064 //=======================================================================
1065 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1066                                               TColStd_Array1OfBoolean& secForward,
1067                                               TColStd_Array1OfReal& tabDst,
1068                                               TColStd_Array1OfReal& arrLen,
1069                                               TColStd_Array1OfReal& tabMinDist,
1070                                               const Standard_Integer indRef) const
1071 {
1072   secForward.Init(Standard_True);
1073   tabDst.Init(-1.0);
1074   arrLen.Init(0.);
1075   tabMinDist.Init(Precision::Infinite());
1076   const Standard_Integer npt = 8; // Number of points for curve discretization
1077   TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1078
1079   Standard_Integer i, j, lengSec = sequenceSec.Length();
1080   TColgp_SequenceOfPnt seqSec;
1081
1082   Handle(Geom_Curve) c3dRef;
1083   Standard_Real firstRef=0., lastRef=0.;
1084   
1085   for (i = indRef; i <= lengSec; i++) {
1086
1087     // reading of the edge (attention for the first one: reference)
1088     const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1089
1090     TopLoc_Location loc;
1091     Standard_Real first, last;
1092     Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1093     if (c3d.IsNull()) continue;
1094     if (!loc.IsIdentity()) {
1095       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1096       c3d->Transform(loc.Transformation());
1097     }
1098
1099     if (i == indRef) {
1100       c3dRef = c3d; firstRef = first; lastRef = last;
1101     }
1102
1103     Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1104     Standard_Real aMinDist = Precision::Infinite();
1105
1106     Standard_Real T, deltaT = (last - first) / (npt - 1);
1107     Standard_Real aLenSec2 = 0.;
1108    
1109     Standard_Integer nbFound = 0;
1110     for (j = 1; j <= npt; j++) {
1111
1112       // Uniform parameter on curve
1113       if (j == 1) T = first;
1114       else if (j == npt) T = last;
1115       else T = first + (j - 1) * deltaT;
1116
1117       // Take point on curve
1118       gp_Pnt pt = c3d->Value(T);
1119      
1120       if (i == indRef) {
1121         ptsRef(j) = pt;
1122         if(j > 1)
1123           aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1124       }
1125       else {
1126         ptsSec(j) = pt;
1127         //protection to avoid merging with small sections
1128         if(j > 1)
1129           aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1130         // To evaluate mutual orientation and distance
1131         dist = pt.Distance(ptsRef(j));
1132         if(aMinDist > dist)
1133           aMinDist = dist;
1134         if (distFor < dist) distFor = dist;
1135         dist = pt.Distance(ptsRef(npt-j+1));
1136    
1137         if(aMinDist > dist)
1138           aMinDist = dist;
1139         if (distRev < dist) distRev = dist;
1140
1141         // Check that point lays between vertices of reference curve
1142         const gp_Pnt &p11 = ptsRef(1);
1143         const gp_Pnt &p12 = ptsRef(npt);
1144         const gp_Vec aVec1(pt,p11);
1145         const gp_Vec aVec2(pt,p12);
1146         const gp_Vec aVecRef(p11,p12);
1147         if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1148           nbFound++;
1149       }
1150     }
1151
1152     Standard_Real aLenSec = sqrt(aLenSec2);
1153     
1154     //if(aLenSec < myMinTolerance )
1155      // continue;
1156     arrLen.SetValue(i,aLenSec);
1157     // Record mutual orientation
1158     Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1159     secForward(i) = isForward;
1160
1161     dist = (isForward? distFor : distRev);
1162     if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1163     {
1164       tabDst(i) = dist;
1165       tabMinDist(i) = aMinDist;
1166     }
1167     else
1168     {
1169       nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1170       TColgp_Array1OfPnt arrProj(1, npt);
1171       TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1172       if( arrLen(indRef) >= arrLen(i)) 
1173         ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1174       else
1175         ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1176       for( j = 1; j <= npt; j++ )
1177       {
1178         if(arrDist(j) < 0.)
1179           continue;
1180         if(dist < arrDist(j))
1181           dist = arrDist(j);
1182         if( aMinDist > arrDist(j))
1183           aMinDist = arrDist(j);
1184         nbFound++;
1185       }
1186       if(nbFound > 1)
1187       {
1188         tabDst(i) = dist;
1189         tabMinDist(i) =  aMinDist;
1190       }
1191     }
1192   }
1193
1194   /*
1195   // Project distant points
1196   Standard_Integer nbFailed = seqSec.Length();
1197   if (!nbFailed) return;
1198
1199   TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1200   for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1201   TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1202
1203   ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1204
1205   // Process distant sections
1206   Standard_Integer idx1 = 1;
1207   for (i = indRef + 1; i <= lengSec; i++) {
1208
1209     // Skip section if already evaluated
1210     if (tabDst(i) >= 0.0) continue;
1211
1212     Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1213
1214     Standard_Integer idx2 = (idx1 - 1)*npt;
1215
1216     for (j = 1; j <= npt; j++) {
1217
1218       dist = arrDist(idx2 + j);
1219       // If point is not projected - stop evaluation
1220       if (dist < 0.0) { distMax = -1.0; break; }
1221       if (distMax < dist) distMax = dist;
1222       if(aMinDist > dist) aMinDist = dist;
1223     }
1224
1225     // If section is close - record distance
1226     if (distMax >= 0.0) {
1227       if (secForward(i)) {
1228         dist = arrPnt(idx2+1).Distance(ptsRef(1));
1229         if (distMax < dist) distMax = dist;
1230         if(aMinDist > dist) aMinDist = dist;
1231         dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1232         if (distMax < dist) distMax = dist;
1233         if(aMinDist > dist) aMinDist = dist;
1234       }
1235       else {
1236         dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1237         if (distMax < dist) distMax = dist;
1238         if(aMinDist > dist) aMinDist = dist;
1239         dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1240         if (distMax < dist) distMax = dist;
1241         if(aMinDist > dist) aMinDist = dist;
1242       }
1243
1244       if (distMax < myTolerance) 
1245       {
1246         tabDst(i) = distMax;
1247         tabMinDist(i) = aMinDist;
1248       }
1249     }
1250
1251     idx1++; // To the next distant curve
1252   }*/
1253 }
1254
1255 //=======================================================================
1256 //function : IsMergedClosed
1257 //purpose  :  internal use
1258 //=======================================================================
1259
1260 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1261                                                  const TopoDS_Edge& Edge2,
1262                                                  const TopoDS_Face& face) const
1263 {
1264   // Check for closed surface
1265   TopLoc_Location loc;
1266   Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1267   Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1268   Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1269   if (!isUClosed && !isVClosed) return Standard_False;
1270   // Check condition on closed surface
1271   /*
1272   Standard_Real first1,last1,first2,last2;
1273   Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1274   Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1275   if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1276   */
1277   Standard_Real first2d1,last2d1,first2d2,last2d2;
1278   Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1279   Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1280   if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1281   /*
1282   gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1283   gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1284   Standard_Real dist = p1.Distance(p2);
1285   gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1286   gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1287   Standard_Real dist2d = p12d.Distance(p22d);
1288   GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1289   Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1290   return (dist2d*0.2 >= distSurf);
1291   */
1292   Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1293   Standard_Real SUmin, SUmax, SVmin, SVmax;
1294   Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1295   Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1296   { //szv: Use brackets to destroy local variables
1297     Bnd_Box2d B1, B2;
1298     Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1299     BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1300     BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1301     B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1302     B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1303     Standard_Real du, dv;
1304     du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1305     isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1306     du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1307     isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1308     surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1309   }
1310   if (isUClosed && isVLongC1 && isVLongC2) {
1311     // Do not merge if not overlapped by V
1312     Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1313     if (dist < 0.0) {
1314       Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1315       Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1316       if (distOuter <= distInner) return Standard_True;
1317     }
1318   }
1319   if (isVClosed && isULongC1 && isULongC2) {
1320     // Do not merge if not overlapped by U
1321     Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1322     if (dist < 0.0) {
1323       Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1324       Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1325       if (distOuter <= distInner) return Standard_True;
1326     }
1327   }
1328   return Standard_False;
1329 }
1330
1331 //=======================================================================
1332 //function : AnalysisNearestEdges
1333 //purpose  : 
1334 //=======================================================================
1335
1336 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1337                                                  TColStd_SequenceOfInteger& seqIndCandidate,
1338                                                  TColStd_SequenceOfInteger& seqOrientations,
1339                                                  const Standard_Boolean evalDist)
1340 {
1341
1342   Standard_Integer workIndex = seqIndCandidate.First();
1343   TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1344   TopoDS_Shape bnd = workedge;
1345   TopTools_ListOfShape workfaces;
1346   if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1347   if (myBoundFaces.Contains(bnd)) 
1348     workfaces = myBoundFaces.FindFromKey(bnd);
1349   if(workfaces.IsEmpty()) return;
1350   TopTools_MapOfShape mapFaces;
1351   TopTools_ListIteratorOfListOfShape lIt;
1352   for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1353     mapFaces.Add(lIt.Value());
1354   TColStd_SequenceOfInteger seqNotCandidate;
1355   TColStd_SequenceOfInteger seqNewForward;
1356   // Separates edges belonging the same face as work edge 
1357   // for exception of edges belonging closed faces 
1358
1359   seqNotCandidate.Append(workIndex);
1360   for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1361     Standard_Integer index = seqIndCandidate.Value(i);
1362     Standard_Boolean isRemove = Standard_False;
1363     if(index == workIndex) {
1364       seqIndCandidate.Remove(i);
1365       seqOrientations.Remove(i);
1366       isRemove = Standard_True;
1367     }
1368     if(!isRemove) {
1369       TopoDS_Shape bnd2 = sequenceSec.Value(index);
1370       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1371
1372       if(myBoundFaces.Contains(bnd2)) {
1373         const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1374         Standard_Boolean isMerged = Standard_True;
1375         for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1376           if(mapFaces.Contains(lIt.Value())) {
1377             TopLoc_Location loc;
1378             Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1379             isMerged = ((IsUClosedSurface(surf,bnd2,loc) ||  IsVClosedSurface(surf,bnd2,loc)) && 
1380               IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1381           }
1382         }
1383         if(!isMerged) {
1384           seqNotCandidate.Append(index);
1385           seqIndCandidate.Remove(i);
1386           seqOrientations.Remove(i);
1387           isRemove = Standard_True;
1388         }
1389       }
1390       else {
1391         seqIndCandidate.Remove(i);
1392         seqOrientations.Remove(i);
1393         isRemove = Standard_True;
1394       }
1395     }
1396     if(!isRemove) i++;  
1397   }
1398   if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1399   if(!evalDist) return;
1400   TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1401   TColStd_MapOfInteger MapIndex;
1402   TColStd_SequenceOfInteger seqForward;
1403
1404   // Definition and removing edges wich are not candidate for work edge 
1405   // ( they have other nearest edges belonging to the work face) 
1406   for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1407     Standard_Integer index1 = seqNotCandidate.Value(k);
1408     TopoDS_Shape edge = sequenceSec.Value(index1);
1409     TopTools_SequenceOfShape tmpSeq;
1410     tmpSeq.Append(edge);
1411     for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++) 
1412       tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1413
1414     Standard_Integer lengSec = tmpSeq.Length();
1415     TColStd_Array1OfBoolean tabForward(1,lengSec);
1416     TColStd_Array1OfReal tabDist(1,lengSec);
1417     TColStd_Array1OfReal arrLen(1,lengSec);
1418     TColStd_Array1OfReal tabMinDist(1,lengSec);
1419     for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++) 
1420       tabDist(i1) =-1;
1421
1422     EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1423     if(k == 1) {
1424       for(Standard_Integer n = 1; n < lengSec; n++) {
1425         if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1426           MapIndex.Add(n);
1427           continue;
1428         }
1429         TotTabDist(k,n) = tabDist(n+1 );
1430         seqForward.Append(tabForward(n+1) ? 1:0);
1431       }
1432     }
1433     else {
1434       for(Standard_Integer n = 1; n < lengSec; n++) {
1435         if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1436         if(tabDist(n+1) < TotTabDist(1,n)) {
1437           MapIndex.Add(n);
1438         }
1439       }
1440     }
1441
1442   }
1443
1444   Standard_Integer i2 = seqIndCandidate.Length();
1445   for( ; i2 >=1 ; i2--)
1446   {
1447     if(MapIndex.Contains(i2))
1448     { 
1449       seqIndCandidate.Remove(i2);
1450       seqOrientations.Remove(i2);
1451     }
1452
1453   }
1454   //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1455   //  seqIndCandidate.Remove(IMap.Key());
1456   //  seqOrientations.Remove(IMap.Key());
1457   //}
1458 }
1459
1460 //=======================================================================
1461 //function : FindCandidates
1462 //purpose  : internal use
1463 //=======================================================================
1464
1465 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1466                                                        TColStd_IndexedMapOfInteger& mapReference,
1467                                                        TColStd_SequenceOfInteger& seqCandidates,
1468                                                        TColStd_SequenceOfInteger& seqOrientations)
1469 {
1470   Standard_Integer i, nbSections = seqSections.Length();
1471   if(nbSections <= 1)
1472     return Standard_False;
1473   // Retrieve last reference index
1474   Standard_Integer indReference = mapReference(mapReference.Extent());
1475   Standard_Integer nbCandidates = 0;
1476   TopTools_MapOfShape Faces1;
1477   //if (nbSections > 1) {
1478
1479   TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1480
1481   // Retrieve faces for reference section
1482
1483   { //szv: Use brackets to destroy local variables
1484     TopoDS_Shape bnd = Edge1;
1485     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1486     if (myBoundFaces.Contains(bnd)) {
1487       TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1488       for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1489     }
1490   }
1491
1492   // Check merging conditions for candidates and remove unsatisfactory
1493   TopTools_SequenceOfShape seqSectionsNew;
1494   TColStd_SequenceOfInteger seqCandidatesNew;
1495   for (i = 1; i <= nbSections; i++) {
1496     if (i == indReference) {
1497       seqSectionsNew.Prepend(Edge1);
1498       seqCandidatesNew.Prepend(i);
1499     }
1500     else {
1501       const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1502       seqSectionsNew.Append(Edge2);
1503       seqCandidatesNew.Append(i);
1504     }
1505   }
1506
1507   Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1508   if (nbSectionsNew > 1) {
1509     
1510     // Evaluate distances between reference and other sections
1511     TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1512     TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1513     TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1514     TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1515     EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1516     
1517     // Fill sequence of candidate indices sorted by distance
1518     for (i = 2; i <= nbSectionsNew; i++) {
1519       Standard_Real aMaxDist = arrDistance(i);
1520       if (aMaxDist >= 0.0 && aMaxDist <= myTolerance &&  arrLen(i) > myMinTolerance) {
1521         
1522         // Reference section is connected to section #i
1523         Standard_Boolean isInserted = Standard_False;
1524         Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1525         for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1526           Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1527           
1528           if( aDelta < Precision::Confusion()) {
1529
1530             if(fabs(aDelta) > RealSmall() || 
1531               arrMinDist(i) < arrMinDist(seqCandidates.Value(j))) 
1532             {
1533               seqCandidates.InsertBefore(j,i);
1534               seqOrientations.InsertBefore(j,ori);
1535               isInserted = Standard_True;
1536             }
1537           }
1538         }
1539         if (!isInserted) {
1540           seqCandidates.Append(i);
1541           seqOrientations.Append(ori);
1542         }
1543       }
1544     }
1545    
1546     nbCandidates = seqCandidates.Length();
1547     if (!nbCandidates) 
1548       return Standard_False; // Section has no candidates to merge
1549     
1550     // Replace candidate indices
1551    
1552     for (i = 1; i <= nbCandidates; i++)
1553       seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1554     
1555   }
1556   
1557   if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1558
1559   if (myNonmanifold && nbCandidates >1) {
1560     TColStd_SequenceOfInteger seqNewCandidates;
1561     TColStd_SequenceOfInteger seqOrientationsNew;
1562     seqCandidates.Prepend(1);
1563     seqOrientations.Prepend(1);
1564     for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1565       AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1566       if(k == 1 && !seqCandidates.Length()) return Standard_False;
1567       if(seqCandidates.Length()) {
1568         seqNewCandidates.Append(seqCandidates.First());
1569         seqOrientationsNew.Append(seqOrientations.First()); 
1570       }
1571     }
1572     seqCandidates.Prepend(seqNewCandidates);
1573     seqOrientations.Prepend(seqOrientationsNew);
1574     return Standard_True;
1575   }
1576   else {
1577
1578     // For manifold case leave only one candidate from equidistant candidates
1579     /*Standard_Integer minIndex = seqCandidateIndex.First();
1580     Standard_Real minDistance = arrDistance(minIndex);
1581
1582     // Find equidistant candidates
1583     TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1584     for (i = 2; i <= nbCandidates; i++) {
1585     Standard_Integer index = seqCandidateIndex(i);
1586     if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1587     seqEqDistantIndex.Append(index);
1588     }
1589
1590     Standard_Integer eqLen = seqEqDistantIndex.Length();
1591     if (eqLen > 2) {
1592
1593     // Fill map of faces which equidistant sections belong to
1594     TopTools_MapOfShape mapFace;
1595     for (i = 1; i <= eqLen; i++) {
1596     Standard_Integer index = seqEqDistantIndex.Value(i);
1597     if (isCandidate(index)) {
1598     mapFace.Add(arrFace(index));
1599     }
1600     }
1601
1602     // Non Manifold case
1603     // Edges are merged by pair among a face continuity C1 criterion
1604     if (mapFace.Extent() == eqLen) {
1605
1606     tabDist.Init(-1);
1607     tabMinInd.Init(-1);
1608     min=10000000.;
1609     //indMin = -1;
1610     Standard_Integer indMin = -1;// To check if the edge can be merged.
1611     // Computation of distances between the edges.
1612     TopTools_SequenceOfShape seqSh;
1613     Standard_Integer nbInd = EqDistSeq.Length();
1614     TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1615     seqSh.Append(sequenceSec.Value(1));
1616     for (j = 2; j <= EqDistSeq.Length(); j++) {
1617     Standard_Integer index = EqDistSeq.Value(j);
1618     tmptabForward(j) = tabForward(index);
1619     seqSh.Append(sequenceSec.Value(index));
1620     }
1621
1622     EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1623
1624     for(j=2; j <= seqSh.Length(); j++) {
1625     if (tabDist(j) > -1.) {  // if edge(j) is connected to edge(i)
1626     if (min > tabDist(j)) {
1627     min = tabDist(j);
1628     indMin = j;
1629     }
1630     }
1631     }
1632
1633     //  Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1634     if (indMin > 0) {
1635     seqSh.Remove(indMin);
1636     for(j =2; j <= tmpSeq.Length(); ) {
1637     TopoDS_Shape sh = tmpSeq.Value(j);
1638     Standard_Boolean isRem = Standard_False;
1639     for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1640     if(seqSh.Value(k) == sh) {
1641     isRem = Standard_True;
1642     break;
1643     }
1644     }
1645     if(isRem) {
1646     tmpSeq.Remove(j);
1647     tabMinForward.Remove(j); // = -1;
1648     } 
1649     else j++;
1650     }
1651     }
1652     }
1653     }*/
1654
1655     // Find the best approved candidate
1656     while (nbCandidates) {
1657       // Retrieve first candidate
1658       Standard_Integer indCandidate = seqCandidates.First();
1659       // Candidate is approved if it is in the map
1660       if (mapReference.Contains(indCandidate)) break;
1661       // Find candidates for candidate #indCandidate
1662       mapReference.Add(indCandidate); // Push candidate in the map
1663       TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1664       Standard_Boolean isFound =
1665         FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1666       mapReference.RemoveLast(); // Pop candidate from the map
1667       if (isFound) isFound = (seqCandidates1.Length() > 0);
1668       if (isFound) {
1669         Standard_Integer indCandidate1 = seqCandidates1.First();
1670         // If indReference is the best candidate for indCandidate
1671         // then indCandidate is the best candidate for indReference
1672         if (indCandidate1 == indReference) break;
1673         // If some other reference in the map is the best candidate for indCandidate
1674         // then assume that reference is the best candidate for indReference
1675         if (mapReference.Contains(indCandidate1)) {
1676           seqCandidates.Prepend(indCandidate1);
1677           nbCandidates++;
1678           break;
1679         }
1680         isFound = Standard_False;
1681       }
1682       if (!isFound) {
1683         // Remove candidate #1
1684         seqCandidates.Remove(1);
1685         seqOrientations.Remove(1);
1686         nbCandidates--;
1687       }
1688     }
1689   }
1690   //gka
1691   if(nbCandidates > 0)
1692   {
1693     Standard_Integer anInd = seqCandidates.Value(1);
1694     TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1695     TopoDS_Shape bnd = Edge2;
1696     if (mySectionBound.IsBound(bnd)) 
1697       bnd = mySectionBound(bnd);
1698     //gka
1699     if (myBoundFaces.Contains(bnd)) {
1700       Standard_Boolean isOK = Standard_True;
1701       TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1702       for (; itf2.More() && isOK; itf2.Next()) {
1703         const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1704         // Check whether condition is satisfied
1705         isOK = !Faces1.Contains(Face2);
1706         if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1707       }
1708       if(!isOK)
1709         return Standard_False;
1710     }
1711   }
1712   return (nbCandidates > 0);
1713 }
1714
1715 //=======================================================================
1716 //function : Constructor
1717 //purpose  : 
1718 //=======================================================================
1719
1720 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1721                                  const Standard_Boolean optionSewing,
1722                                  const Standard_Boolean optionAnalysis,
1723                                  const Standard_Boolean optionCutting,
1724                                  const Standard_Boolean optionNonmanifold)
1725 {
1726   myReShape = new BRepTools_ReShape;
1727   Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1728 }
1729
1730 //=======================================================================
1731 //function : Init
1732 //purpose  : Initialise Talerance, and options sewing, faceAnalysis and cutting
1733 //=======================================================================
1734
1735 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1736                            const Standard_Boolean optionSewing,
1737                            const Standard_Boolean optionAnalysis,
1738                            const Standard_Boolean optionCutting,
1739                            const Standard_Boolean optionNonmanifold)
1740 {
1741   // Set tolerance and Perform options
1742   myTolerance      = Max (tolerance, Precision::Confusion());
1743   mySewing         = optionSewing;
1744   myAnalysis       = optionAnalysis;
1745   myCutting        = optionCutting;
1746   myNonmanifold    = optionNonmanifold;
1747   // Set min and max tolerances
1748   myMinTolerance   = myTolerance * 1e-4; //szv: proposal
1749   if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1750   myMaxTolerance   = Precision::Infinite();
1751   // Set other modes
1752   myFaceMode           = Standard_True;
1753   myFloatingEdgesMode  = Standard_False;
1754   //myCuttingFloatingEdgesMode = Standard_False; //gka
1755   mySameParameterMode  = Standard_True;
1756   myLocalToleranceMode = Standard_False;
1757   mySewedShape.Nullify();
1758   // Load empty shape
1759   Load(TopoDS_Shape());
1760 }
1761
1762 //=======================================================================
1763 //function : Load
1764 //purpose  : Loads the context shape
1765 //=======================================================================
1766
1767 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1768 {
1769   myReShape->Clear();
1770   if (theShape.IsNull()) myShape.Nullify();
1771   else myShape = myReShape->Apply(theShape);
1772   mySewedShape.Nullify();
1773   // Nullify flags and counters
1774   myNbShapes = myNbEdges = myNbVertices = 0;
1775   // Clear all maps
1776   myOldShapes.Clear();
1777   //myOldFaces.Clear();
1778   myDegenerated.Clear();
1779   myFreeEdges.Clear();
1780   myMultipleEdges.Clear();
1781   myContigousEdges.Clear();
1782   myContigSecBound.Clear();
1783   myBoundFaces.Clear();
1784   myBoundSections.Clear();
1785   myVertexNode.Clear();
1786   myVertexNodeFree.Clear();
1787   myNodeSections.Clear();
1788   myCuttingNode.Clear();
1789   mySectionBound.Clear();
1790   myLittleFace.Clear();
1791 }
1792
1793 //=======================================================================
1794 //function : Add
1795 //purpose  : 
1796 //=======================================================================
1797
1798 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1799 {
1800   if (aShape.IsNull()) return;
1801   TopoDS_Shape oShape = myReShape->Apply(aShape);
1802   myOldShapes.Add(aShape,oShape);
1803   myNbShapes = myOldShapes.Extent();
1804 }
1805
1806 //=======================================================================
1807 //function : Perform
1808 //purpose  : 
1809 //=======================================================================
1810
1811 #ifdef OCCT_DEBUG
1812 #include <OSD_Timer.hxx>
1813 #endif
1814
1815 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1816 {
1817   const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1818   Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1819 #ifdef OCCT_DEBUG
1820   Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1821   OSD_Chronometer chr_total, chr_local;
1822   chr_total.Reset();
1823   chr_total.Start();
1824 #endif
1825
1826   // face analysis
1827   if (myAnalysis)
1828   {
1829 #ifdef OCCT_DEBUG
1830     cout << "Begin face analysis..." << endl;
1831     chr_local.Reset();
1832     chr_local.Start();
1833 #endif
1834     FaceAnalysis (thePI);
1835     if (!aPS.More())
1836       return;
1837     aPS.Next();
1838 #ifdef OCCT_DEBUG
1839     chr_local.Stop();
1840     chr_local.Show(t_analysis);
1841     cout << "Face analysis finished after " << t_analysis << " s" << endl;
1842 #endif
1843   }
1844
1845   if (myNbShapes || !myShape.IsNull())
1846   {
1847
1848     FindFreeBoundaries();
1849
1850     if (myBoundFaces.Extent())
1851     {
1852
1853 #ifdef OCCT_DEBUG
1854       cout << "Begin vertices assembling..." << endl;
1855       chr_local.Reset();
1856       chr_local.Start();
1857 #endif
1858       VerticesAssembling (thePI);
1859       if (!aPS.More())
1860         return;
1861       aPS.Next();
1862 #ifdef OCCT_DEBUG
1863       chr_local.Stop();
1864       chr_local.Show(t_assembling);
1865       cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1866 #endif
1867       if (myCutting)
1868       {
1869 #ifdef OCCT_DEBUG
1870         cout << "Begin cutting..." << endl;
1871         chr_local.Reset();
1872         chr_local.Start();
1873 #endif
1874         Cutting (thePI);
1875         if (!aPS.More())
1876           return;
1877         aPS.Next();
1878 #ifdef OCCT_DEBUG
1879         chr_local.Stop();
1880         chr_local.Show(t_cutting);
1881         cout << "Cutting finished after " << t_cutting << " s" << endl;
1882 #endif
1883       }
1884 #ifdef OCCT_DEBUG
1885       cout << "Begin merging..." << endl;
1886       chr_local.Reset();
1887       chr_local.Start();
1888 #endif
1889       Merging (Standard_True, thePI);
1890       if (!aPS.More())
1891         return;
1892       aPS.Next();
1893 #ifdef OCCT_DEBUG
1894       chr_local.Stop();
1895       chr_local.Show(t_merging);
1896       cout << "Merging finished after " << t_merging << " s" << endl;
1897 #endif
1898     }
1899     else
1900     {
1901       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1902       if (myCutting)
1903         aPS.Next( 1, Handle(TCollection_HAsciiString)());
1904       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1905       if (!aPS.More())
1906         return;
1907     }
1908
1909     if (mySewing)
1910     {
1911
1912 #ifdef OCCT_DEBUG
1913       cout << "Creating sewed shape..." << endl;
1914 #endif
1915       // examine the multiple edges if any and process sameparameter for edges if necessary
1916       EdgeProcessing (thePI);
1917       if (!aPS.More())
1918         return;
1919       CreateSewedShape();
1920       if (!aPS.More())
1921       {
1922         mySewedShape.Nullify();
1923         return;
1924       }
1925       if (mySameParameterMode && myFaceMode)
1926         SameParameterShape();
1927       if (!aPS.More())
1928       {
1929         mySewedShape.Nullify();
1930         return;
1931       }
1932 #ifdef OCCT_DEBUG
1933       cout << "Sewed shape created" << endl;
1934 #endif
1935     }
1936
1937     // create edge informations for output
1938     CreateOutputInformations();
1939     if (!aPS.More())
1940     {
1941       mySewedShape.Nullify();
1942       return;
1943     }
1944   }
1945 #ifdef OCCT_DEBUG
1946   chr_total.Stop();
1947   chr_total.Show(t_total);
1948   cout << "Sewing finished!" << endl;
1949   cout << " analysis time   : " << t_analysis << " s" << endl;
1950   cout << " assembling time : " << t_assembling << " s" << endl;
1951   cout << " cutting time    : " << t_cutting << " s" << endl;
1952   cout << " merging time    : " << t_merging << " s" << endl;
1953   cout << "Total time       : " << t_total << " s" << endl;
1954 #endif
1955 }
1956
1957 //=======================================================================
1958 //function : SewedShape
1959 //purpose  : give the sewed shape
1960 //           if a null shape, reasons:
1961 //             -- no useable input shapes : all input shapes are degenerated
1962 //             -- has multiple edges
1963 //=======================================================================
1964
1965 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1966 {
1967   return mySewedShape;
1968 }
1969
1970 //=======================================================================
1971 //function : NbFreeEdges
1972 //purpose  : 
1973 //=======================================================================
1974
1975 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1976 {
1977   return myFreeEdges.Extent();
1978 }
1979
1980 //=======================================================================
1981 //function : FreeEdge
1982 //purpose  : 
1983 //=======================================================================
1984
1985 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1986 {
1987   Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1988   return TopoDS::Edge(myFreeEdges(index));
1989 }
1990
1991 //=======================================================================
1992 //function : NbMultipleEdges
1993 //purpose  : 
1994 //=======================================================================
1995
1996 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1997 {
1998   return myMultipleEdges.Extent();
1999 }
2000
2001 //=======================================================================
2002 //function : MultipleEdge
2003 //purpose  : 
2004 //=======================================================================
2005
2006 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
2007 {
2008   Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
2009   return TopoDS::Edge(myMultipleEdges(index));
2010 }
2011
2012 //=======================================================================
2013 //function : NbContigousEdges
2014 //purpose  : 
2015 //=======================================================================
2016
2017 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
2018 {
2019   return myContigousEdges.Extent();
2020 }
2021
2022 //=======================================================================
2023 //function : ContigousEdge
2024 //purpose  : 
2025 //=======================================================================
2026
2027 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
2028 {
2029   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
2030   return TopoDS::Edge(myContigousEdges.FindKey(index));
2031 }
2032
2033 //=======================================================================
2034 //function : ContigousEdgeCouple
2035 //purpose  : 
2036 //=======================================================================
2037
2038 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2039 {
2040   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2041   return myContigousEdges(index);
2042 }
2043
2044 //=======================================================================
2045 //function : IsSectionBound
2046 //purpose  : 
2047 //=======================================================================
2048
2049 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2050 {
2051   if(myContigSecBound.IsBound(section)) {
2052     return Standard_True;
2053   }
2054   else {
2055     return Standard_False;
2056   }
2057 }
2058
2059 //=======================================================================
2060 //function : SectionToBoundary
2061 //purpose  : 
2062 //=======================================================================
2063
2064 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2065 {
2066   Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2067   return TopoDS::Edge(myContigSecBound(section));
2068 }
2069 //=======================================================================
2070 //function : NbDeletedFaces
2071 //purpose  : 
2072 //=======================================================================
2073  Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2074 {
2075   return myLittleFace.Extent();
2076 }
2077
2078 //=======================================================================
2079 //function : DeletedFace
2080 //purpose  : 
2081 //=======================================================================
2082 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2083 {
2084   Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2085   return TopoDS::Face(myLittleFace(index));
2086 }
2087
2088 //=======================================================================
2089 //function : NbDegeneratedShapes
2090 //purpose  : 
2091 //=======================================================================
2092
2093 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2094 {
2095   return myDegenerated.Extent();
2096 }
2097
2098 //=======================================================================
2099 //function : DegeneratedShape
2100 //purpose  : 
2101 //=======================================================================
2102
2103 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2104 {
2105   Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2106   return myDegenerated(index);
2107 }
2108
2109 //=======================================================================
2110 //function : IsDegenerated
2111 //purpose  : 
2112 //=======================================================================
2113
2114 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2115 {
2116   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2117   // Degenerated face
2118   if (aShape.ShapeType() == TopAbs_FACE)
2119     return NewShape.IsNull();
2120   if (NewShape.IsNull()) return Standard_False;
2121   // Degenerated edge
2122   if (NewShape.ShapeType() == TopAbs_EDGE)
2123     return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2124   // Degenerated wire
2125   if (NewShape.ShapeType() == TopAbs_WIRE) {
2126     Standard_Boolean isDegenerated = Standard_True;
2127     for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2128       isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2129     return isDegenerated;
2130   }
2131   return Standard_False;
2132 }
2133   
2134 //=======================================================================
2135 //function : IsModified
2136 //purpose  : 
2137 //=======================================================================
2138
2139 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2140 {
2141   TopoDS_Shape NewShape = aShape;
2142   if (myOldShapes.Contains(aShape)) 
2143     NewShape = myOldShapes.FindFromKey(aShape);
2144   if(!NewShape.IsSame(aShape)) return Standard_True;
2145   return Standard_False;
2146 }
2147
2148 //=======================================================================
2149 //function : Modified
2150 //purpose  : 
2151 //=======================================================================
2152
2153 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2154
2155   if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2156   //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2157   return aShape;
2158 }
2159
2160 //=======================================================================
2161 //function : IsModifiedSubShape
2162 //purpose  : 
2163 //=======================================================================
2164
2165 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2166 {
2167   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2168   if(!NewShape.IsSame(aShape)) return Standard_True;
2169   return Standard_False;
2170 }
2171
2172 //=======================================================================
2173 //function : ModifiedSubShape
2174 //purpose  : 
2175 //=======================================================================
2176
2177 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2178
2179   return myReShape->Apply(aShape);
2180 }
2181
2182 //=======================================================================
2183 //function : Dump
2184 //purpose  : 
2185 //=======================================================================
2186
2187 void BRepBuilderAPI_Sewing::Dump() const
2188 {
2189   Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2190   TopTools_MapOfShape mapVertices, mapEdges;
2191   for (i = 1; i <= NbBounds; i++) {
2192     TopoDS_Shape bound = myBoundFaces.FindKey(i);
2193     if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2194     else NbSections++;
2195     TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2196     for (; aExp.More(); aExp.Next()) {
2197       TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2198       mapEdges.Add(E);
2199       TopoDS_Vertex V1, V2;
2200       TopExp::Vertices(E,V1,V2);
2201       mapVertices.Add(V1);
2202       mapVertices.Add(V2);
2203     }
2204   }
2205   cout << " " << endl;
2206   cout << "                        Informations                        " << endl;
2207   cout << " ===========================================================" << endl;
2208   cout << " " << endl;
2209   cout << " Number of input shapes      : " << myOldShapes.Extent() << endl;
2210   cout << " Number of actual shapes     : " << myNbShapes << endl;
2211   cout << " Number of Bounds            : " << NbBounds << endl;
2212   cout << " Number of Sections          : " << NbSections << endl;
2213   cout << " Number of Edges             : " << mapEdges.Extent() << endl;
2214   cout << " Number of Vertices          : " << myNbVertices << endl;
2215   cout << " Number of Nodes             : " << mapVertices.Extent() << endl;
2216   cout << " Number of Free Edges        : " << myFreeEdges.Extent() << endl;
2217   cout << " Number of Contigous Edges   : " << myContigousEdges.Extent() << endl;
2218   cout << " Number of Multiple Edges    : " << myMultipleEdges.Extent() << endl;
2219   cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2220   cout << " ===========================================================" << endl;
2221   cout << " " << endl;
2222 }
2223
2224 //=======================================================================
2225 //function : FaceAnalysis
2226 //purpose  : Remove
2227 //           Modifies:
2228 //                      myNbShapes
2229 //                      myOldShapes
2230 //
2231 //           Constructs:
2232 //                      myDegenerated
2233 //=======================================================================
2234
2235 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2236 {
2237   if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2238     Add(myShape);
2239     myShape.Nullify();
2240   }
2241
2242   BRep_Builder B;
2243   TopTools_MapOfShape SmallEdges;
2244   TopTools_DataMapOfShapeListOfShape GluedVertices;
2245   Standard_Integer i = 1;
2246   Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2247   for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2248     for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2249
2250       // Retrieve current face
2251       TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2252       TopoDS_Face face = TopoDS::Face(aTmpShape);
2253       Standard_Integer nbEdges = 0, nbSmall = 0;
2254
2255       // Build replacing face
2256       aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2257       TopoDS_Face nface = TopoDS::Face(aTmpShape);
2258       Standard_Boolean isFaceChanged = Standard_False;
2259
2260       TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2261       for (; witer.More(); witer.Next()) {
2262
2263         // Retrieve current wire
2264         aTmpShape = witer.Value(); //for porting
2265         if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2266         TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2267
2268         // Build replacing wire
2269         aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2270         TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2271         Standard_Boolean isWireChanged = Standard_False;
2272
2273         TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2274         for (; eiter.More(); eiter.Next()) {
2275
2276           // Retrieve current edge
2277           aTmpShape = eiter.Value(); //for porting
2278           TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2279           nbEdges++;
2280
2281           // Process degenerated edge
2282           if (BRep_Tool::Degenerated(edge)) {
2283             B.Add(nwire,edge); // Old edge kept
2284             myDegenerated.Add(edge);
2285             nbSmall++;
2286             continue;
2287           }
2288
2289           Standard_Boolean isSmall = SmallEdges.Contains(edge);
2290           if (!isSmall) {
2291
2292             // Check for small edge
2293             Standard_Real first, last;
2294             Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2295             if (c3d.IsNull()) {
2296 #ifdef OCCT_DEBUG
2297               cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2298 #endif
2299             }
2300             else {
2301               // Evaluate curve compactness
2302               const Standard_Integer npt = 5;
2303               gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2304               Standard_Real dist, maxdist = 0.0;
2305               Standard_Real delta = (last - first)/(npt - 1);
2306               for (Standard_Integer idx = 0; idx < npt; idx++) {
2307                 dist = cp.Distance(c3d->Value(first + idx*delta));
2308                 if (maxdist < dist) maxdist = dist;
2309               }
2310               isSmall = (2.*maxdist <= MinTolerance());
2311               /*try {
2312                 GeomAdaptor_Curve cAdapt(c3d);
2313                 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2314                 isSmall = (length <= MinTolerance());
2315               }
2316               catch (Standard_Failure) {
2317 #ifdef OCCT_DEBUG
2318                 cout << "Warning: Possibly small edge can be sewed: ";
2319                 Standard_Failure::Caught()->Print(cout); cout << endl;
2320 #endif
2321               }*/
2322             }
2323
2324             if (isSmall) {
2325
2326               // Store small edge in the map
2327               SmallEdges.Add(edge);
2328
2329               TopoDS_Vertex v1, v2;
2330               TopExp::Vertices(edge,v1,v2);
2331               TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2332
2333               // Store glued vertices
2334               if (!nv1.IsSame(v1)) {
2335                 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2336                 // First vertex was already glued
2337                 if (!nv2.IsSame(v2)) {
2338                   // Merge lists of glued vertices
2339                   if (!nv1.IsSame(nv2)) {
2340                     TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2341                     for (; liter.More(); liter.Next()) {
2342                       TopoDS_Shape v = liter.Value();
2343                       myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2344                       vlist1.Append(v);
2345                     }
2346                     GluedVertices.UnBind(nv2);
2347                   }
2348                 }
2349                 else {
2350                   // Add second vertex to the existing list
2351                   vlist1.Append(v2);
2352                   myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2353                 }
2354               }
2355               else if (!nv2.IsSame(v2)) {
2356                 // Add first vertex to the existing list
2357                 GluedVertices(nv2).Append(v1);
2358                 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2359               }
2360               else if (!v1.IsSame(v2)) {
2361                 // Record new glued vertices
2362                 TopoDS_Vertex nv;
2363                 B.MakeVertex(nv);
2364                 TopTools_ListOfShape vlist;
2365                 vlist.Append(v1);
2366                 vlist.Append(v2);
2367                 GluedVertices.Bind(nv,vlist);
2368                 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2369                 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2370               }
2371             }
2372           }
2373
2374           // Replace small edge
2375           if (isSmall) {
2376 #ifdef OCCT_DEBUG
2377             cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2378 #endif
2379             nbSmall++;
2380             // Create new degenerated edge
2381             aTmpShape = edge.Oriented(TopAbs_FORWARD);
2382             TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2383             Standard_Real pfirst, plast;
2384             Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2385             if (!c2d.IsNull()) {
2386               TopoDS_Edge nedge;
2387               B.MakeEdge(nedge);
2388               B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2389               B.Range(nedge,pfirst,plast);
2390               B.Degenerated(nedge,Standard_True);
2391               TopoDS_Vertex v1, v2;
2392               TopExp::Vertices(fedge,v1,v2);
2393               B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2394               B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2395               B.Add(nwire,nedge.Oriented(edge.Orientation()));
2396               myDegenerated.Add(nedge);
2397             }
2398             isWireChanged = Standard_True;
2399           }
2400           else B.Add(nwire,edge); // Old edge kept
2401         }
2402
2403         // Record wire in the new face
2404         if (isWireChanged) {
2405           B.Add(nface,nwire.Oriented(wire.Orientation()));
2406           isFaceChanged = Standard_True;
2407         }
2408         else B.Add(nface,wire);
2409       }
2410
2411       // Remove small face
2412       if (nbSmall == nbEdges) {
2413 #ifdef OCCT_DEBUG
2414         cout << "Warning: Small face removed by FaceAnalysis" << endl;
2415 #endif
2416         myLittleFace.Add(face);
2417         myReShape->Remove(face);
2418       }
2419       else if (isFaceChanged) {
2420
2421         myReShape->Replace(face,nface.Oriented(face.Orientation()));
2422       }
2423     }
2424   }
2425
2426   // Update glued vertices
2427   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2428   for (; miter.More(); miter.Next()) {
2429     TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2430     gp_XYZ coord(0.,0.,0.);
2431     Standard_Integer nbPoints = 0;
2432     const TopTools_ListOfShape& vlist = miter.Value();
2433     TopTools_ListIteratorOfListOfShape liter1(vlist);
2434     for (; liter1.More(); liter1.Next()) {
2435       coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2436       nbPoints++;
2437     }
2438     if (nbPoints) {
2439       gp_Pnt vp(coord / nbPoints);
2440       Standard_Real tol = 0.0, mtol = 0.0;
2441       TopTools_ListIteratorOfListOfShape liter2(vlist);
2442       for (; liter2.More(); liter2.Next()) {
2443         Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2444         if (mtol < vtol) mtol = vtol;
2445         vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2446         if (tol < vtol) tol = vtol;
2447       }
2448       B.UpdateVertex(vnew,vp,tol+mtol);
2449     }
2450   }
2451
2452   // Update input shapes
2453   for (i = 1; i <= myOldShapes.Extent(); i++)
2454     myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2455 }
2456
2457 //=======================================================================
2458 //function : FindFreeBoundaries
2459 //purpose  : Constructs :
2460 //                      myBoundFaces     (bound = list of faces) - REFERENCE
2461 //                      myVertexNode     (vertex = node)
2462 //                      myVertexNodeFree (floating vertex = node)
2463 //
2464 //=======================================================================
2465
2466 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2467 {
2468   // Take into account the context shape if needed
2469   TopTools_IndexedMapOfShape NewShapes;
2470   if (!myShape.IsNull()) {
2471     if (myOldShapes.IsEmpty()) {
2472       Add(myShape);
2473       myShape.Nullify();
2474     }
2475     else {
2476       TopoDS_Shape newShape = myReShape->Apply(myShape);
2477       if (!newShape.IsNull()) NewShapes.Add(newShape);
2478     }
2479   }
2480   // Create map Edge -> Faces
2481   TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2482   Standard_Integer i, nbShapes = myOldShapes.Extent();
2483   for (i = 1; i <= nbShapes; i++) {
2484     // Retrieve new shape
2485     TopoDS_Shape shape = myOldShapes(i);
2486     if (shape.IsNull()) continue;
2487     NewShapes.Add(shape);
2488     // Explore shape to find all boundaries
2489     for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2490       TopoDS_Shape edge = eExp.Current();
2491       if (!EdgeFaces.Contains(edge)) {
2492         TopTools_ListOfShape listFaces;
2493         EdgeFaces.Add(edge,listFaces);
2494       }
2495     }
2496   }
2497   // Fill map Edge -> Faces
2498   nbShapes = NewShapes.Extent();
2499    TopTools_MapOfShape mapFaces;
2500   for (i = 1; i <= nbShapes; i++) {
2501     // Explore shape to find all faces
2502     TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2503     for (; fExp.More(); fExp.Next()) {
2504       TopoDS_Shape face = fExp.Current();
2505       if(mapFaces.Contains(face)) continue;
2506       else 
2507         mapFaces.Add(face);
2508       // Explore face to find all boundaries
2509       for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2510         if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2511         for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2512           
2513           TopoDS_Shape edge = aIIe.Value();
2514           
2515           if (EdgeFaces.Contains(edge)) {
2516             EdgeFaces.ChangeFromKey(edge).Append(face);
2517             //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2518             //Standard_Boolean isContained = Standard_False;
2519             //TopTools_ListIteratorOfListOfShape itf(listFaces);
2520             //for (; itf.More() && !isContained; itf.Next())
2521             //  isContained = face.IsSame(itf.Value());
2522             //if (!isContained) listFaces.Append(face);
2523           }
2524         }
2525       }
2526     }
2527   }
2528   // Find free boundaries
2529   nbShapes = EdgeFaces.Extent();
2530   for (i = 1; i <= nbShapes; i++) {
2531     TopTools_ListOfShape& listFaces = EdgeFaces(i);
2532     Standard_Integer nbFaces = listFaces.Extent();
2533     TopoDS_Shape edge    = EdgeFaces.FindKey(i);
2534     if(edge.Orientation() == TopAbs_INTERNAL)
2535           continue;
2536     Standard_Boolean isSeam = Standard_False;
2537     if (nbFaces == 1) {
2538       TopoDS_Face face = TopoDS::Face(listFaces.First());
2539       isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2540       if (isSeam) {
2541         ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2542         //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2543         //if(!isSeam) {
2544           BRep_Builder aB;
2545           TopoDS_Shape anewEdge = edge.EmptyCopied();
2546           TopoDS_Iterator aItV(edge);
2547           for( ; aItV.More() ; aItV.Next())
2548             aB.Add(anewEdge,aItV.Value());
2549           
2550
2551
2552           Standard_Real first2d,last2d;
2553           Handle(Geom2d_Curve) c2dold = 
2554             BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2555
2556           Handle(Geom2d_Curve) c2d;
2557           BRep_Builder B;
2558           B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2559           B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2560           
2561           Standard_Real aFirst, aLast;
2562           BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2563           aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2564           aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2565           myReShape->Replace(edge,anewEdge);
2566           edge = anewEdge;
2567           
2568         //}
2569            isSeam = Standard_False;
2570       }
2571     }
2572     Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2573     Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2574     if (isBound || isBoundFloat) {
2575       // Ignore degenerated edge
2576       if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2577       // Ignore edge with internal vertices
2578      // Standard_Integer nbVtx = 0;
2579      // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2580      // if (nbVtx != 2) continue;
2581       // Add to BoundFaces
2582       TopTools_ListOfShape listFacesCopy;
2583       listFacesCopy.Append(listFaces);
2584       myBoundFaces.Add(edge,listFacesCopy);
2585       // Process edge vertices
2586       TopoDS_Vertex vFirst, vLast;
2587       TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2588       if(vFirst.IsNull() || vLast.IsNull()) continue;
2589       if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2590         continue;
2591       if (isBound) {
2592         // Add to VertexNode
2593         if (!myVertexNode.Contains(vFirst))
2594           myVertexNode.Add(vFirst,vFirst);
2595         if (!myVertexNode.Contains(vLast))
2596           myVertexNode.Add(vLast,vLast);
2597       }
2598       else {
2599         // Add to VertexNodeFree
2600         if (!myVertexNodeFree.Contains(vFirst))
2601           myVertexNodeFree.Add(vFirst,vFirst);
2602         if (!myVertexNodeFree.Contains(vLast))
2603           myVertexNodeFree.Add(vLast,vLast);
2604       }
2605     }
2606   }
2607 }
2608
2609 //=======================================================================
2610 //function : VerticesAssembling
2611 //purpose  : Modifies :
2612 //                      myVertexNode     (nodes glued)
2613 //                      myVertexNodeFree (nodes glued)
2614 //                      myNodeSections   (lists of sections merged for glued nodes)
2615 //
2616 //=======================================================================
2617
2618 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2619                                        const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2620                                        TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2621                                        TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2622 {
2623   Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2624
2625   // Create new nodes
2626   BRep_Builder B;
2627   TopTools_DataMapOfShapeShape OldNodeNewNode;
2628   TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2629   for (i = 1; i <= nbNearest; i++) {
2630     // Retrieve a pair of nodes to merge
2631     TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2632     TopoDS_Shape oldnode2 = NodeNearestNode(i);
2633     // Second node should also be in the map
2634     if (!NodeNearestNode.Contains(oldnode2)) continue;
2635     // Get new node for old node #1
2636     if (OldNodeNewNode.IsBound(oldnode1)) {
2637       TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2638       if (OldNodeNewNode.IsBound(oldnode2)) {
2639         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2640         if (!newnode1.IsSame(newnode2)) {
2641           // Change data for new node #2
2642           TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2643           TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2644           for (; itn.More(); itn.Next()) {
2645             TopoDS_Shape node2 = itn.Value();
2646             lnode1.Append(node2);
2647             OldNodeNewNode(node2) = newnode1;
2648           }
2649           NewNodeOldNodes.UnBind(newnode2);
2650         }
2651       }
2652       else {
2653         // Old node #2 is not bound - add to old node #1
2654         OldNodeNewNode.Bind(oldnode2,newnode1);
2655         NewNodeOldNodes(newnode1).Append(oldnode2);
2656       }
2657     }
2658     else {
2659       if (OldNodeNewNode.IsBound(oldnode2)) {
2660         // Old node #1 is not bound - add to old node #2
2661         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2662         OldNodeNewNode.Bind(oldnode1,newnode2);
2663         NewNodeOldNodes(newnode2).Append(oldnode1);
2664       }
2665       else {
2666         // Nodes are not bound - create new node
2667         TopoDS_Vertex newnode;
2668         B.MakeVertex(newnode);
2669         OldNodeNewNode.Bind(oldnode1,newnode);
2670         OldNodeNewNode.Bind(oldnode2,newnode);
2671         TopTools_ListOfShape lnodes;
2672         lnodes.Append(oldnode1);
2673         lnodes.Append(oldnode2);
2674         NewNodeOldNodes.Bind(newnode,lnodes);
2675       }
2676     }
2677   }
2678
2679   // Stop if no new nodes created
2680   if (!NewNodeOldNodes.Extent()) return Standard_False;
2681
2682   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2683   for (; iter1.More(); iter1.Next()) {
2684     const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2685     // Calculate new node center point
2686     gp_XYZ theCoordinates(0.,0.,0.);
2687     TopTools_ListOfShape lvert; // Accumulate node vertices
2688     TopTools_MapOfShape medge;
2689     TopTools_ListOfShape ledge; // Accumulate node edges
2690     // Iterate on old nodes
2691     TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2692     for (; itn.More(); itn.Next()) {
2693       const TopoDS_Shape& oldnode = itn.Value();
2694       // Iterate on node vertices
2695       TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2696       for (; itv.More(); itv.Next()) {
2697         TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2698         // Change node for vertex
2699         aVertexNode.ChangeFromKey(vertex) = newnode;
2700         // Accumulate coordinates
2701         theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2702         lvert.Append(vertex);
2703       }
2704       // Iterate on node edges
2705       const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2706       TopTools_ListIteratorOfListOfShape ite(edges);
2707       for (; ite.More(); ite.Next()) {
2708         TopoDS_Shape edge = ite.Value();
2709         if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2710       }
2711       // Unbind old node edges
2712       aNodeEdges.UnBind(oldnode);
2713     }
2714     // Bind new node edges
2715     aNodeEdges.Bind(newnode,ledge);
2716     gp_Pnt center(theCoordinates / lvert.Extent());
2717     // Calculate new node tolerance
2718     Standard_Real toler = 0.0;
2719     TopTools_ListIteratorOfListOfShape itv(lvert);
2720     for (; itv.More(); itv.Next()) {
2721       const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2722       Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2723       if (toler < t) toler = t;
2724     }
2725     // Update new node parameters
2726     B.UpdateVertex(newnode,center,toler);
2727   }
2728
2729   return Standard_True;
2730 }
2731
2732 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2733                                          const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2734                                          const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2735 {
2736   //Case of floating edges
2737   if (face1.IsNull())
2738     return (!IsClosedShape(e1,vtx1,vtx2));
2739
2740   // Find wires containing given edges
2741   TopoDS_Shape wire1, wire2;
2742   TopExp_Explorer itw(face1,TopAbs_WIRE);
2743   for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2744     TopoDS_Iterator ite(itw.Current(),Standard_False);
2745     for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2746       if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2747       if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2748     }
2749   }
2750   Standard_Integer Status = 0;
2751   if (!wire1.IsNull() && !wire2.IsNull()) {
2752     if (wire1.IsSame(wire2)) {
2753       for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2754         TopoDS_Vertex ve1,ve2;
2755         TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2756         if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2757             (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2758           return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2759       }
2760       if (IsClosedShape(wire1,vtx1,vtx2)) {
2761         TopoDS_Vertex V1, V2;
2762         TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2763         Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2764                                         (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2765         if (!isEndVertex) Status = 1;
2766       }
2767       else Status = 1;
2768     }
2769     else Status = -1;
2770   }
2771   return Status;
2772 }
2773
2774 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2775                                      TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2776                                      const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2777                                      const Standard_Real Tolerance,
2778                                      const Handle(Message_ProgressIndicator)& theProgress)
2779 {
2780   Standard_Integer i, nbVertices = aVertexNode.Extent();
2781   // Create map of node -> vertices
2782   TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2783   BRepBuilderAPI_CellFilter aFilter (Tolerance);
2784   BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2785   for (i = 1; i <= nbVertices; i++) {
2786     TopoDS_Shape vertex = aVertexNode.FindKey(i);
2787     TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2788     if (NodeVertices.Contains(node)) {
2789       NodeVertices.ChangeFromKey(node).Append(vertex);
2790     }
2791     else {
2792       TopTools_ListOfShape vlist;
2793       vlist.Append(vertex);
2794       NodeVertices.Add(node,vlist);
2795       gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2796       aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2797       anInspector.Add (aPnt.XYZ());
2798     }
2799   }
2800   Standard_Integer nbNodes = NodeVertices.Extent();
2801 #ifdef OCCT_DEBUG
2802   cout << "Glueing " << nbNodes << " nodes..." << endl;
2803 #endif
2804   // Merge nearest nodes
2805   TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2806   Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2807   for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2808     TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2809     // Find near nodes
2810     gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2811     anInspector.SetCurrent (pt1.XYZ());
2812     gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2813     gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2814     aFilter.Inspect (aPntMin, aPntMax, anInspector);
2815     if (anInspector.ResInd().IsEmpty()) continue;
2816     // Retrieve list of edges for the first node
2817     const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2818     // Explore list of near nodes and fill the sequence of glued nodes
2819     TopTools_SequenceOfShape SeqNodes;
2820     TopTools_ListOfShape listNodesSameEdge;
2821     //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2822     TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2823     for (; iter1.More(); iter1.Next()) {
2824       TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2825       if (node1 == node2) continue;
2826       // Retrieve list of edges for the second node
2827       const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2828       // Check merging condition for the pair of nodes
2829       Standard_Integer Status = 0, isSameEdge = Standard_False;
2830       // Explore edges of the first node
2831       TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2832       for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2833         const TopoDS_Shape& e1 = Ie1.Value();
2834         // Obtain real vertex from edge
2835         TopoDS_Shape v1 = node1;
2836         { //szv: Use brackets to destroy local variables
2837           TopoDS_Vertex ov1, ov2;
2838           TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2839           if (aVertexNode.Contains(ov1)) {
2840             if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2841           }
2842           if (aVertexNode.Contains(ov2)) {
2843             if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2844           }
2845         }
2846         // Create map of faces for e1
2847         TopTools_MapOfShape Faces1;
2848         const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2849         if (lfac1.Extent()) {
2850           TopTools_ListIteratorOfListOfShape itf(lfac1);
2851           for (; itf.More(); itf.Next())
2852             if (!itf.Value().IsNull())
2853               Faces1.Add(itf.Value());
2854         }
2855         // Explore edges of the second node
2856         TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2857         for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2858           const TopoDS_Shape& e2 = Ie2.Value();
2859           // Obtain real vertex from edge
2860           TopoDS_Shape v2 = node2;
2861           { //szv: Use brackets to destroy local variables
2862             TopoDS_Vertex ov1, ov2;
2863             TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2864             if (aVertexNode.Contains(ov1)) {
2865               if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2866             }
2867             if (aVertexNode.Contains(ov2)) {
2868               if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2869             }
2870           }
2871           // Explore faces for e2
2872           const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2873           if (lfac2.Extent()) {
2874             TopTools_ListIteratorOfListOfShape itf(lfac2);
2875             for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2876               // Check merging conditions for the same face
2877               if (Faces1.Contains(itf.Value())) {
2878                 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2879                 if (stat == 1) isSameEdge = Standard_True;
2880                 else Status = stat;
2881               }
2882             }
2883           }
2884           else if (Faces1.IsEmpty() && e1 == e2) {
2885             Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2886             if (stat == 1) isSameEdge = Standard_True;
2887             else Status = stat;
2888             break;
2889           }
2890         }
2891       }
2892       if (Status) continue;
2893       if (isSameEdge) listNodesSameEdge.Append(node2);
2894       // Append near node to the sequence
2895       gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2896       Standard_Real dist = pt1.Distance(pt2);
2897       if (dist < Tolerance) {
2898         Standard_Boolean isIns = Standard_False;
2899         for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2900           gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2901           if (dist < pt1.Distance(pt)) {
2902             SeqNodes.InsertBefore(kk,node2);
2903             isIns = Standard_True;
2904           }
2905         }
2906         if (!isIns) SeqNodes.Append(node2);
2907       }
2908     }
2909     if (SeqNodes.Length()) {
2910       // Remove nodes near to some other from the same edge
2911       if (listNodesSameEdge.Extent()) {
2912         TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2913         for (; lInt.More(); lInt.Next()) {
2914           const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2915           gp_Pnt p2 = BRep_Tool::Pnt(n2);
2916           for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2917             const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2918             if (n1 != n2) {
2919               gp_Pnt p1 = BRep_Tool::Pnt(n1);
2920               if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2921             }
2922             SeqNodes.Remove(k);
2923           }
2924         }
2925       }
2926       // Bind nearest node if at least one exists
2927       if (SeqNodes.Length())
2928         NodeNearestNode.Add(node1,SeqNodes.First());
2929     }
2930     anInspector.ClearResList();
2931   }
2932
2933   // Create new nodes for chained nearest nodes
2934   if (NodeNearestNode.IsEmpty()) return Standard_False;
2935
2936   return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2937 }
2938
2939 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2940 {
2941   Standard_Integer nbVert = myVertexNode.Extent();
2942   Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2943   Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2944   if (nbVert || nbVertFree) {
2945     // Fill map node -> sections
2946     Standard_Integer i;
2947     for (i = 1; i <= myBoundFaces.Extent(); i++) {
2948       TopoDS_Shape bound = myBoundFaces.FindKey(i);
2949       for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2950         TopoDS_Shape node = itv.Value();
2951         if (myNodeSections.IsBound(node))
2952           myNodeSections(node).Append(bound);
2953         else {
2954           TopTools_ListOfShape lbnd;
2955           lbnd.Append(bound);
2956           myNodeSections.Bind(node,lbnd);
2957         }
2958       }
2959     }
2960     // Glue vertices
2961     if (nbVert) {
2962 #ifdef OCCT_DEBUG
2963       cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2964 #endif
2965       while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2966     }
2967     if (!aPS.More())
2968       return;
2969     aPS.Next();
2970     if (nbVertFree) {
2971 #ifdef OCCT_DEBUG
2972       cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2973 #endif
2974       while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2975     }
2976   }
2977 }
2978
2979 //=======================================================================
2980 //function : replaceNMVertices
2981 //purpose  : internal use (static)
2982 //=======================================================================
2983 static void replaceNMVertices(const TopoDS_Edge& theEdge, 
2984                               const TopoDS_Vertex& theV1,
2985                               const TopoDS_Vertex& theV2,
2986                               const Handle(BRepTools_ReShape)& theReShape)
2987 {
2988   //To keep NM vertices on edge
2989   TopTools_SequenceOfShape aSeqNMVert;
2990   TColStd_SequenceOfReal aSeqNMPars;
2991   Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2992   if(!hasNMVert)
2993     return;
2994   Standard_Real first, last;
2995   BRep_Tool::Range(theEdge, first, last);
2996   TopLoc_Location aLoc;
2997   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2998   if(c3d.IsNull())
2999     return;
3000   TopTools_SequenceOfShape aEdVert;
3001   TColStd_SequenceOfReal aEdParams;
3002   Standard_Integer i =1, nb = aSeqNMPars.Length();
3003     
3004   for( ; i <= nb;i++) {
3005     Standard_Real apar = aSeqNMPars.Value(i);
3006     if(fabs(apar - first) <= Precision::PConfusion()) {
3007       theReShape->Replace(aSeqNMVert.Value(i),theV1);
3008       continue;
3009     }
3010     if(fabs(apar - last) <= Precision::PConfusion()) {
3011       theReShape->Replace(aSeqNMVert.Value(i),theV2);
3012       continue;
3013     }
3014     TopoDS_Shape aV = aSeqNMVert.Value(i);
3015     Standard_Integer j =1;
3016     for( ; j <= aEdParams.Length();j++) {
3017       Standard_Real apar2 = aEdParams.Value(j);
3018       if(fabs(apar - apar2) <= Precision::PConfusion()) {
3019         theReShape->Replace(aV,aEdVert.Value(j));
3020         break;
3021       }
3022       else if(apar < apar2) {
3023         TopoDS_Shape anewV = aV.EmptyCopied();
3024         aEdVert.InsertBefore(j,anewV);
3025         aEdParams.InsertBefore(j,apar);
3026         BRep_ListOfPointRepresentation& alistrep = 
3027           (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
3028         Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3029         alistrep.Append(aPRep);
3030         theReShape->Replace(aV,anewV);
3031         break;
3032       }
3033     }
3034     if (j > aEdParams.Length()) {
3035       TopoDS_Shape anewV = aV.EmptyCopied();
3036       aEdVert.Append(anewV);
3037       aEdParams.Append(apar);
3038       BRep_ListOfPointRepresentation& alistrep = 
3039         (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3040       Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3041       alistrep.Append(aPRep);
3042       theReShape->Replace(aV,anewV);
3043     }
3044   }
3045   
3046   Standard_Integer newnb = aEdParams.Length();
3047   if(newnb < nb) {
3048     
3049     TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3050     TopAbs_Orientation anOri = theEdge.Orientation();
3051     anewEdge.Orientation(TopAbs_FORWARD);
3052     BRep_Builder aB;
3053     aB.Add(anewEdge,theV1);
3054     aB.Add(anewEdge,theV2);
3055     
3056     for( i =1; i <= aEdVert.Length();i++) 
3057       aB.Add(anewEdge,aEdVert.Value(i));
3058     anewEdge.Orientation(anOri);
3059     theReShape->Replace(theEdge,anewEdge);
3060   }
3061  
3062 }
3063
3064 //=======================================================================
3065 //function : ReplaceEdge
3066 //purpose  : internal use (static)
3067 //=======================================================================
3068
3069 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3070                         const TopoDS_Shape& theNewShape,
3071                         const Handle(BRepTools_ReShape)& aReShape)
3072 {
3073   TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3074   TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3075   if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3076   
3077
3078   aReShape->Replace(oldShape,newShape);
3079   TopoDS_Vertex V1old,V2old,V1new,V2new;
3080   TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3081   TopAbs_Orientation Orold = oldShape.Orientation();
3082   TopAbs_Orientation Ornew = Orold;
3083   if (newShape.ShapeType() == TopAbs_EDGE) {
3084     TopoDS_Edge aEn = TopoDS::Edge(newShape);
3085     TopExp::Vertices(aEn,V1new,V2new);
3086     Ornew = aEn.Orientation();
3087     replaceNMVertices(aEn,V1new,V2new,aReShape);
3088   }
3089   else if (newShape.ShapeType() == TopAbs_WIRE) {
3090     for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3091       TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3092       Ornew = ed.Orientation();
3093       TopoDS_Vertex aV1,aV2;
3094       TopExp::Vertices(ed,aV1,aV2);
3095       replaceNMVertices(ed,aV1,aV2,aReShape);
3096       if (V1new.IsNull()) 
3097         V1new = aV1;
3098       V2new =aV2;
3099     }
3100   }
3101   
3102   V1new.Orientation(V1old.Orientation());
3103   V2new.Orientation(V2old.Orientation());
3104   if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3105     aReShape->Replace(V1old,V1new);
3106     return;
3107   }
3108   if (Orold == Ornew) {
3109     V1new.Orientation(V1old.Orientation());
3110     V2new.Orientation(V2old.Orientation());
3111     if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3112       aReShape->Replace(V1old,V1new);
3113     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3114       aReShape->Replace(V2old,V2new);
3115   }
3116   else {
3117     V1new.Orientation(V2old.Orientation());
3118     V2new.Orientation(V1old.Orientation());
3119     if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) 
3120       aReShape->Replace(V1old,V2new);
3121     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3122       aReShape->Replace(V2old,V1new);
3123   }
3124 }
3125
3126 //=======================================================================
3127 //function : Merging
3128 //purpose  : Modifies :
3129 //                   myHasFreeBound
3130 //
3131 //=======================================================================
3132
3133 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */, 
3134                                     const Handle(Message_ProgressIndicator)& thePI)
3135 {
3136   BRep_Builder B;
3137   //  TopTools_MapOfShape MergedEdges;
3138   Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3139   for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3140
3141     TopoDS_Shape bound = myBoundFaces.FindKey(i);
3142
3143     // If bound was already merged - continue
3144     if (myMergedEdges.Contains(bound)) continue;
3145
3146     if (!myBoundFaces(i).Extent()) {
3147       // Merge free edge - only vertices
3148       TopoDS_Vertex no1, no2;
3149       TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3150       TopoDS_Shape nno1 = no1, nno2 = no2;
3151       if (myVertexNodeFree.Contains(no1))
3152         nno1 = myVertexNodeFree.FindFromKey(no1);
3153       if (myVertexNodeFree.Contains(no2))
3154         nno2 = myVertexNodeFree.FindFromKey(no2);
3155       if (!no1.IsSame(nno1)) {
3156         nno1.Orientation(no1.Orientation());
3157         myReShape->Replace(no1,nno1);
3158       }
3159       if (!no2.IsSame(nno2)) {
3160         nno2.Orientation(no2.Orientation());
3161         myReShape->Replace(no2,nno2);
3162       }
3163       myMergedEdges.Add(bound);
3164       continue;
3165     }
3166
3167     // Check for previous splitting, build replacing wire
3168     TopoDS_Wire BoundWire;
3169     Standard_Boolean isPrevSplit = Standard_False;
3170     Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3171     if (hasCuttingSections) {
3172       B.MakeWire(BoundWire);
3173       BoundWire.Orientation(bound.Orientation());
3174       // Iterate on cutting sections
3175       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3176       for (; its.More(); its.Next()) {
3177         TopoDS_Shape section = its.Value();
3178         B.Add(BoundWire,section);
3179         if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3180       }
3181     }
3182
3183     // Merge with bound
3184     TopTools_DataMapOfShapeShape MergedWithBound;
3185     if (!isPrevSplit) {
3186       // Obtain sequence of edges merged with bound
3187       TopTools_SequenceOfShape seqMergedWithBound;
3188       TColStd_SequenceOfInteger seqMergedWithBoundOri;
3189       if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3190         // Store bound in the map
3191         MergedWithBound.Bind(bound,bound);
3192         // Iterate on edges merged with bound
3193         Standard_Integer ii = 1;
3194         while (ii <= seqMergedWithBound.Length()) {
3195           TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3196           // Remove edge if recorded as merged
3197           Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || 
3198             MergedWithBound.IsBound(iedge));
3199           if (!isRejected) {
3200             if (myBoundSections.IsBound(iedge)) {
3201               // Edge is splitted - check sections
3202               TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3203               for (; lit.More() && !isRejected; lit.Next()) {
3204                 const TopoDS_Shape& sec = lit.Value();
3205                 // Remove edge (bound) if at least one of its sections already merged
3206                 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3207               }
3208             }
3209             if (!isRejected) {
3210               if (mySectionBound.IsBound(iedge)) {
3211                 // Edge is a section - check bound
3212                 const TopoDS_Shape& bnd = mySectionBound(iedge);
3213                 // Remove edge (section) if its bound already merged
3214                 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3215               }
3216             }
3217           }
3218           // To the next merged edge
3219           if (isRejected) {
3220             // Remove rejected edge
3221             seqMergedWithBound.Remove(ii);
3222             seqMergedWithBoundOri.Remove(ii);
3223           }
3224           else {
3225             // Process accepted edge
3226             MergedWithBound.Bind(iedge,iedge);
3227             ii++;
3228           }
3229         }
3230         Standard_Integer nbMerged = seqMergedWithBound.Length();
3231         if (nbMerged) {
3232           // Create same parameter edge
3233           TopTools_MapOfShape ActuallyMerged;
3234           TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3235             seqMergedWithBoundOri,
3236             ActuallyMerged,myReShape);
3237           Standard_Boolean isForward = Standard_False;
3238           if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3239           // Process actually merged edges
3240           Standard_Integer nbActuallyMerged = 0;
3241           for (ii = 1; ii <= nbMerged; ii++) {
3242             TopoDS_Shape iedge = seqMergedWithBound(ii);
3243             if (ActuallyMerged.Contains(iedge)) {
3244               nbActuallyMerged++;
3245               // Record merged edge in the map
3246               TopAbs_Orientation orient = iedge.Orientation();
3247               if (!isForward) orient = TopAbs::Reverse(orient);
3248               if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3249               MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3250             }
3251             else MergedWithBound.UnBind(iedge);
3252           }
3253           if (nbActuallyMerged) {
3254             // Record merged bound in the map
3255             TopAbs_Orientation orient = bound.Orientation();
3256             if (!isForward) orient = TopAbs::Reverse(orient);
3257             MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3258           }
3259           nbMerged = nbActuallyMerged;
3260         }
3261         // Remove bound from the map if not finally merged
3262         if (!nbMerged) MergedWithBound.UnBind(bound);
3263       }
3264     }
3265     Standard_Boolean isMerged = MergedWithBound.Extent();
3266
3267     // Merge with cutting sections
3268     Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3269     TopTools_DataMapOfShapeShape MergedWithSections;
3270     if (hasCuttingSections) {
3271       // Iterate on cutting sections
3272       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3273       for (; its.More(); its.Next()) {
3274         // Retrieve cutting section
3275         TopoDS_Shape section = its.Value();
3276         // Skip section if already merged
3277         if (myMergedEdges.Contains(section)) continue;
3278         // Merge cutting section
3279         TopTools_SequenceOfShape seqMergedWithSection;
3280         TColStd_SequenceOfInteger seqMergedWithSectionOri;
3281         if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3282           // Store section in the map
3283           MergedWithSections.Bind(section,section);
3284           // Iterate on edges merged with section
3285           Standard_Integer ii = 1;
3286           while (ii <= seqMergedWithSection.Length()) {
3287             TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3288             // Remove edge if recorded as merged
3289             Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3290             if (!isRejected) {
3291               if (myBoundSections.IsBound(iedge)) {
3292                 // Edge is splitted - check sections
3293                 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3294                 for (; lit.More() && !isRejected; lit.Next()) {
3295                   const TopoDS_Shape& sec = lit.Value();
3296                   // Remove edge (bound) if at least one of its sections already merged
3297                   isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3298                 }
3299               }
3300               if (!isRejected) {
3301                 if (mySectionBound.IsBound(iedge)) {
3302                   // Edge is a section - check bound
3303                   const TopoDS_Shape& bnd = mySectionBound(iedge);
3304                   // Remove edge (section) if its bound already merged
3305                   isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3306                 }
3307               }
3308             }
3309             // To the next merged edge
3310             if (isRejected) {
3311               // Remove rejected edge
3312               seqMergedWithSection.Remove(ii);
3313               seqMergedWithSectionOri.Remove(ii);
3314             }
3315             else {
3316               // Process accepted edge
3317               MergedWithSections.Bind(iedge,iedge);
3318               ii++;
3319             }
3320           }
3321           Standard_Integer nbMerged = seqMergedWithSection.Length();
3322           if (nbMerged) {
3323             // Create same parameter edge
3324             TopTools_MapOfShape ActuallyMerged;
3325             TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3326               seqMergedWithSectionOri,
3327               ActuallyMerged,SectionsReShape);
3328             Standard_Boolean isForward = Standard_False;
3329             if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3330             // Process actually merged edges
3331             Standard_Integer nbActuallyMerged = 0;
3332             for (ii = 1; ii <= nbMerged; ii++) {
3333               TopoDS_Shape iedge = seqMergedWithSection(ii);
3334               if (ActuallyMerged.Contains(iedge)) {
3335                 nbActuallyMerged++;
3336                 // Record merged edge in the map
3337                 TopAbs_Orientation orient = iedge.Orientation();
3338                 if (!isForward) orient = TopAbs::Reverse(orient);
3339                 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3340                 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3341                 MergedWithSections.ChangeFind(iedge) = oedge;
3342                 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3343               }
3344               else MergedWithSections.UnBind(iedge);
3345             }
3346             if (nbActuallyMerged) {
3347               // Record merged section in the map
3348               TopAbs_Orientation orient = section.Orientation();
3349               if (!isForward) orient = TopAbs::Reverse(orient);
3350               TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3351               MergedWithSections.ChangeFind(section) = oedge;
3352               ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3353             }
3354             nbMerged = nbActuallyMerged;
3355           }
3356           // Remove section from the map if not finally merged
3357           if (!nbMerged) MergedWithSections.UnBind(section);
3358         }
3359         else if (isMerged) {
3360           // Reject merging of sections
3361           MergedWithSections.Clear();
3362           break;
3363         }
3364       }
3365     }
3366     Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3367
3368     if (!isMerged && !isMergedSplit) {
3369       // Nothing was merged in this iteration
3370       if (isPrevSplit) {
3371         // Replace previously splitted bound
3372         myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3373       }
3374       //      else if (hasCuttingSections) {
3375       //        myBoundSections.UnBind(bound); //szv: are you sure ???
3376       //      }
3377       continue;
3378     }
3379
3380     // Set splitting flag
3381     Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3382
3383     // Choose between bound and sections merging
3384     if (isMerged && isMergedSplit && !isPrevSplit) {
3385       // Fill map of merged cutting sections
3386       TopTools_MapOfShape MapSplitEdges;
3387       TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3388       for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3389         TopoDS_Shape edge = itm.Key();
3390         MapSplitEdges.Add(edge);
3391       }
3392       // Iterate on edges merged with bound
3393       for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3394         // Retrieve edge merged with bound
3395         TopoDS_Shape edge = itm.Key();
3396         // Remove edge from the map
3397         if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3398         if (myBoundSections.IsBound(edge)) {
3399           // Edge has cutting sections
3400           TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3401           for (; its.More(); its.Next()) {
3402             TopoDS_Shape sec = its.Value();
3403             // Remove section from the map
3404             if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3405           }
3406         }
3407       }
3408       // Calculate section merging tolerance
3409       Standard_Real MinSplitTol = RealLast();
3410       TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3411       for (; im.More(); im.Next()) {
3412         TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3413         MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3414       }
3415       // Calculate bound merging tolerance
3416       TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3417       Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3418       isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3419       isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3420     }
3421
3422     if (isSplitted) {
3423       // Merging of cutting sections
3424       //myMergedEdges.Add(bound);
3425       myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3426       TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3427       for (; itm.More(); itm.Next()) {
3428         TopoDS_Shape oldedge = itm.Key();
3429         TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3430         ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3431         myMergedEdges.Add(oldedge);
3432         if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3433
3434       }
3435     }
3436     else {
3437       // Merging of initial bound
3438       TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3439       //myMergedEdges.Add(bound);
3440       for (; itm.More(); itm.Next()) {
3441         TopoDS_Shape oldedge = itm.Key();
3442         TopoDS_Shape newedge = itm.Value();
3443         ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3444         myMergedEdges.Add(oldedge);
3445         if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3446       }
3447       if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3448       if(!myMergedEdges.Contains(bound))
3449         myMergedEdges.Add(bound);
3450     }
3451   }
3452
3453   myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3454   myNodeSections.Clear();
3455   myVertexNode.Clear();
3456   myVertexNodeFree.Clear();
3457   myCuttingNode.Clear();
3458 }
3459
3460 //=======================================================================
3461 //function : MergedNearestEdges
3462 //purpose  : 
3463 //=======================================================================
3464
3465 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3466                                                            TopTools_SequenceOfShape& SeqMergedEdge,
3467                                                            TColStd_SequenceOfInteger& SeqMergedOri)
3468 {
3469   // Retrieve edge nodes
3470   TopoDS_Vertex no1, no2;
3471   TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3472   TopoDS_Shape nno1 = no1, nno2 = no2;
3473   Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3474   Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3475   if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3476   if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3477
3478   // Fill map of nodes connected to the node #1
3479   TopTools_MapOfShape mapVert1;
3480   mapVert1.Add(nno1);
3481   if (myCuttingNode.IsBound(nno1)) {
3482     TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3483     for (; ilv.More(); ilv.Next()) {
3484       TopoDS_Shape v1 = ilv.Value();
3485       mapVert1.Add(v1);
3486       if (!isNode1 && myCuttingNode.IsBound(v1)) {
3487         TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3488         for (; ilvn.More(); ilvn.Next()) {
3489           TopoDS_Shape vn = ilvn.Value();
3490           mapVert1.Add(vn);
3491         }
3492       }
3493     }
3494   }
3495
3496   // Fill map of nodes connected to the node #2
3497   TopTools_MapOfShape mapVert2;
3498   mapVert2.Add(nno2);
3499   if (myCuttingNode.IsBound(nno2)) {
3500     TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3501     for (; ilv.More(); ilv.Next()) {
3502       TopoDS_Shape v1 = ilv.Value();
3503       mapVert2.Add(v1);
3504       if (!isNode2 && myCuttingNode.IsBound(v1)) {
3505         TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3506         for (; ilvn.More(); ilvn.Next()) {
3507           TopoDS_Shape vn = ilvn.Value();
3508           mapVert2.Add(vn);
3509         }
3510       }
3511     }
3512   }
3513
3514   // Find all possible contigous edges
3515   TopTools_SequenceOfShape seqEdges;
3516   seqEdges.Append(edge);
3517   TopTools_MapOfShape mapEdges;
3518   mapEdges.Add(edge);
3519   for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3520     TopoDS_Shape node1 = imv1.Key();
3521     if (!myNodeSections.IsBound(node1)) continue;
3522     TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3523     for (; ilsec.More(); ilsec.Next()) {
3524       TopoDS_Shape sec = ilsec.Value();
3525       if (sec.IsSame(edge)) continue;
3526       // Retrieve section nodes
3527       TopoDS_Vertex vs1, vs2;
3528       TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3529       TopoDS_Shape vs1n = vs1, vs2n = vs2;
3530       if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3531       if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3532       if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3533         (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3534         if (mapEdges.Add(sec)) {
3535           // Check for rejected cutting
3536           Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3537           if(!isRejected && myBoundSections.IsBound(sec))
3538           {
3539             TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3540             for (; its.More() && !isRejected; its.Next()) {
3541               TopoDS_Shape section = its.Value();
3542
3543               if (myMergedEdges.Contains(section)) 
3544                 isRejected = Standard_True;
3545             }
3546           }
3547           if( !isRejected && mySectionBound.IsBound(sec)) {
3548             const TopoDS_Shape& bnd = mySectionBound(sec);
3549             isRejected = (!myBoundSections.IsBound(bnd) ||
3550               myMergedEdges.Contains(bnd));
3551           }
3552
3553           if (!isRejected) seqEdges.Append(sec);
3554         }
3555     }
3556   }
3557
3558   mapEdges.Clear();
3559
3560   Standard_Boolean success = Standard_False;
3561
3562   Standard_Integer nbSection = seqEdges.Length();
3563   if (nbSection > 1) {
3564     // Find the longest edge CCI60011
3565     Standard_Integer i, indRef = 1;
3566     if (myNonmanifold) {
3567       Standard_Real lenRef = 0.;
3568       for (i = 1; i <= nbSection; i++) {
3569         Standard_Real f, l;
3570         Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3571         GeomAdaptor_Curve cAdapt(c3d);
3572         Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3573         if (len > lenRef) { indRef = i; lenRef = len; }
3574       }
3575       if (indRef != 1) {
3576         TopoDS_Shape longEdge = seqEdges(indRef);
3577         seqEdges(indRef) = seqEdges(1);
3578         seqEdges(1) = longEdge;
3579       }
3580     }
3581
3582     // Find merging candidates
3583     TColStd_SequenceOfInteger seqForward;
3584     TColStd_SequenceOfInteger seqCandidates;
3585     TColStd_IndexedMapOfInteger mapReference;
3586     mapReference.Add(indRef); // Add index of reference section
3587     if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3588       Standard_Integer nbCandidates = seqCandidates.Length();
3589       // Record candidate sections
3590       for (i = 1; i <= nbCandidates; i++) {
3591         // Retrieve merged edge
3592         TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3593         Standard_Integer ori = (seqForward(i))? 1 : 0;
3594         SeqMergedEdge.Append(iedge);
3595         SeqMergedOri.Append(ori);
3596         if (!myNonmanifold) break;
3597       }
3598       success = nbCandidates;
3599     }
3600   }
3601
3602   return success;
3603 }
3604
3605 //=======================================================================
3606 //function : Cutting
3607 //purpose  : Modifies :
3608 //                     myBoundSections
3609 //                     myNodeSections
3610 //                     myCuttingNode
3611 //=======================================================================
3612
3613 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3614 {
3615   Standard_Integer i, nbVertices = myVertexNode.Extent();
3616   if (!nbVertices) return;
3617   // Create a box tree with vertices
3618   Standard_Real eps = myTolerance*0.5;
3619   BRepBuilderAPI_BndBoxTree aTree;
3620   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
3621   BRepBuilderAPI_BndBoxTreeSelector aSelector;
3622   for (i = 1; i <= nbVertices; i++) {
3623     gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3624     Bnd_Box aBox;
3625     aBox.Set(pt);
3626     aBox.Enlarge(eps);
3627     aTreeFiller.Add (i, aBox);
3628   }
3629   aTreeFiller.Fill();
3630
3631   Handle(Geom_Curve) c3d;
3632   TopLoc_Location loc;
3633   Standard_Real first, last;
3634   // Iterate on all boundaries
3635   Standard_Integer nbBounds = myBoundFaces.Extent();
3636   Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3637   for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3638     const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3639     // Do not cut floating edges
3640     if (!myBoundFaces(i).Extent()) continue;
3641     // Obtain bound curve
3642     c3d = BRep_Tool::Curve(bound, loc, first, last);
3643     if (c3d.IsNull()) continue;
3644     if (!loc.IsIdentity()) {
3645       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3646       c3d->Transform(loc.Transformation());
3647     }
3648     // Create cutting sections
3649     TopTools_ListOfShape listSections;
3650     { //szv: Use brackets to destroy local variables
3651       // Obtain candidate vertices
3652       TopoDS_Vertex V1, V2;
3653       TopTools_IndexedMapOfShape CandidateVertices;
3654       { //szv: Use brackets to destroy local variables
3655         // Create bounding box around curve
3656         Bnd_Box aGlobalBox;
3657         GeomAdaptor_Curve adptC(c3d,first,last);
3658         BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3659         // Sort vertices to find candidates
3660         aSelector.SetCurrent (aGlobalBox);
3661         aTree.Select (aSelector); 
3662         // Skip bound if no node is in the boundind box
3663         if (!aSelector.ResInd().Extent()) continue;
3664         // Retrieve bound nodes
3665         TopExp::Vertices(bound,V1,V2);
3666         const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3667         const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3668         // Fill map of candidate vertices
3669         TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
3670         for (; itl.More(); itl.Next()) {
3671           const Standard_Integer index = itl.Value();
3672           const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3673           if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3674             TopoDS_Shape vertex = myVertexNode.FindKey(index);
3675             CandidateVertices.Add(vertex);
3676           }
3677         }
3678         aSelector.ClearResList();
3679       }
3680       Standard_Integer nbCandidates = CandidateVertices.Extent();
3681       if (!nbCandidates) continue;
3682       // Project vertices on curve
3683       TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3684       TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3685       for (Standard_Integer j = 1; j <= nbCandidates; j++)
3686         arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3687       ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3688       // Create cutting nodes
3689       TopTools_SequenceOfShape seqNode;
3690       TColStd_SequenceOfReal seqPara;
3691       CreateCuttingNodes(CandidateVertices,bound,
3692         V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3693       if (!seqPara.Length()) continue;
3694       // Create cutting sections
3695       CreateSections(bound, seqNode, seqPara, listSections);
3696     }
3697     if (listSections.Extent() > 1) {
3698       // modification of maps:
3699       //                     myBoundSections
3700       TopTools_ListIteratorOfListOfShape its(listSections);
3701       for (; its.More(); its.Next()) {
3702         TopoDS_Shape section = its.Value();
3703         // Iterate on section vertices
3704         for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3705           TopoDS_Shape vertex = itv.Value();
3706           // Convert vertex to node
3707           if (myVertexNode.Contains(vertex))
3708             vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3709           // Update node sections
3710           if (myNodeSections.IsBound(vertex))
3711             myNodeSections.ChangeFind(vertex).Append(section);
3712           else {
3713             TopTools_ListOfShape lsec;
3714             lsec.Append(section);
3715             myNodeSections.Bind(vertex,lsec);
3716           }
3717         }
3718         // Store bound for section
3719         mySectionBound.Bind(section,bound);
3720       }
3721       // Store splitted bound
3722       myBoundSections.Bind(bound,listSections);
3723     }
3724   }
3725 #ifdef OCCT_DEBUG
3726   cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3727     << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3728 #endif
3729 }
3730
3731 //=======================================================================
3732 //function : GetSeqEdges
3733 //purpose  : 
3734 //=======================================================================
3735
3736 static void GetSeqEdges(const TopoDS_Shape& edge,
3737                         TopTools_SequenceOfShape& seqEdges,
3738                         TopTools_DataMapOfShapeListOfShape& VertEdge)
3739 {
3740   Standard_Integer numV = 0;
3741   for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3742     TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3743     numV++;
3744     if (VertEdge.IsBound(V1)) {
3745       const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3746       for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3747         TopoDS_Shape edge1 = lIt.Value();
3748         if (edge1.IsSame(edge)) continue;
3749         Standard_Boolean isContained = Standard_False;
3750         Standard_Integer i, index = 1;
3751         for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3752           isContained = seqEdges.Value(i).IsSame(edge1);
3753           if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3754         }
3755         if (!isContained) {
3756           if (numV == 1) seqEdges.InsertBefore(index,edge1);
3757           else seqEdges.InsertAfter(index,edge1);
3758           GetSeqEdges(edge1,seqEdges,VertEdge);
3759         }
3760       }
3761     }
3762   }
3763 }
3764
3765 //=======================================================================
3766 //function : GetFreeWires
3767 //purpose  : 
3768 //=======================================================================
3769
3770 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3771 {
3772   TopTools_DataMapOfShapeListOfShape VertEdge;
3773   TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3774   TopTools_SequenceOfShape seqFreeEdges;
3775   for (; itMap.More(); itMap.Next()) {
3776     TopoDS_Shape edge = itMap.Key();
3777     seqFreeEdges.Append(edge);
3778     for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3779       TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3780       if (VertEdge.IsBound(V1))
3781         VertEdge.ChangeFind(V1).Append(edge);
3782       else {
3783         TopTools_ListOfShape ls;
3784         ls.Append(edge);
3785         VertEdge.Bind(V1,ls);
3786       }
3787     }
3788   }
3789   BRep_Builder B;
3790   Standard_Integer i, j;
3791   for (i = 1; i <= seqFreeEdges.Length(); i++) {
3792     TopTools_SequenceOfShape seqEdges;
3793     TopoDS_Shape edge = seqFreeEdges.Value(i);
3794     if (!MapFreeEdges.Contains(edge)) continue;
3795     seqEdges.Append(edge);
3796     GetSeqEdges(edge,seqEdges,VertEdge);
3797     TopoDS_Wire wire;
3798     B.MakeWire(wire);
3799     for (j = 1; j <= seqEdges.Length(); j++) {
3800       B.Add(wire,seqEdges.Value(j));
3801       MapFreeEdges.Remove(seqEdges.Value(j));
3802     }
3803     seqWires.Append(wire);
3804     if (MapFreeEdges.IsEmpty()) break;
3805   }
3806 }
3807
3808 //=======================================================================
3809 //function :  IsDegeneratedWire
3810 //purpose  :  internal use
3811 //=======================================================================
3812
3813 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3814 {
3815   if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3816   // Get maximal vertices tolerance
3817   TopoDS_Vertex V1,V2;
3818   //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3819   //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3820   Standard_Real wireLength = 0.0;
3821   TopLoc_Location loc;
3822   Standard_Real first, last;
3823   Standard_Integer nume = 0;
3824   Standard_Integer isSmall = 0;
3825   for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3826     nume++;
3827     TopoDS_Shape edge = aIt.Value();
3828     TopoDS_Vertex Ve1,Ve2;
3829     TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3830     if(nume == 1) {
3831       V1 = Ve1;
3832       V2 = Ve2;
3833     }
3834     else {
3835       if(Ve1.IsSame(V1))
3836         V1 = Ve2;
3837       else if(Ve1.IsSame(V2))
3838         V2 = Ve2;
3839       if(Ve2.IsSame(V1))
3840         V1 = Ve1;
3841       else if(Ve2.IsSame(V2))
3842         V2 = Ve1;
3843     }
3844     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3845     if (!c3d.IsNull()) {
3846       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3847       if (!loc.IsIdentity()) {
3848         //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3849         c3d->Transform(loc.Transformation());
3850       }
3851       gp_Pnt pfirst = c3d->Value(first);
3852       gp_Pnt plast = c3d->Value(last);
3853       gp_Pnt pmid = c3d->Value((first +last)*0.5);
3854       Standard_Real length =0;
3855       if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3856         length = pfirst.Distance(plast);
3857       }
3858       else {
3859         GeomAdaptor_Curve cAdapt(c3d);
3860         length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3861       }
3862       Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3863       if(length <= tole) isSmall++;
3864       wireLength += length;
3865     }
3866   }
3867   if(isSmall == nume) return Standard_True;
3868   Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3869   if (wireLength > tol) return Standard_False;
3870   return Standard_True;
3871 }
3872
3873 //=======================================================================
3874 //function :  DegeneratedSection
3875 //purpose  :  internal use
3876 //            create a new degenerated edge if the section is degenerated
3877 //=======================================================================
3878
3879 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3880 {
3881   // Return if section is already degenerated
3882   if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3883
3884   // Retrieve edge curve
3885   TopLoc_Location loc;
3886   Standard_Real first, last;
3887   Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3888   if (c3d.IsNull()) { //gka
3889     BRep_Builder aB;
3890     TopoDS_Edge edge1 = TopoDS::Edge(section);
3891     aB.Degenerated(edge1, Standard_True);
3892     return edge1;
3893   }
3894   if (!loc.IsIdentity()) {
3895     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3896     c3d->Transform(loc.Transformation());
3897   }
3898
3899   // Test if the new edge is degenerated
3900   TopoDS_Vertex v1,v2;
3901   TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3902   //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3903   //tol = Max(tolerance,tol);
3904
3905   gp_Pnt p1, p2, p3;
3906   p1 = BRep_Tool::Pnt(v1);
3907   p3 = BRep_Tool::Pnt(v2);
3908   c3d->D0(0.5*(first + last),p2);
3909
3910   //Standard_Boolean isDegenerated = Standard_False;
3911   //if (p1.Distance(p3) < tol) {
3912   //GeomAdaptor_Curve cAdapt(c3d);
3913   //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3914   //isDegenerated =  Standard_True; //(length < tol);
3915   //}
3916
3917   TopoDS_Edge edge;
3918   //if (!isDegenerated) return edge;
3919
3920   // processing
3921   BRep_Builder aBuilder;
3922   edge = TopoDS::Edge(section);
3923   edge.EmptyCopy();
3924   if (v1.IsSame(v2)) {