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