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