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