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