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