0027271: Unifysamedomain invalid result
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_UnifySameDomain.cxx
1 // Created on: 2012-06-09
2 // Created by: jgv@ROLEX
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <BRep_Builder.hxx>
18 #include <BRep_CurveRepresentation.hxx>
19 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
20 #include <BRep_TEdge.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepLib.hxx>
23 #include <BRepLib_MakeEdge.hxx>
24 #include <BRepTopAdaptor_TopolTool.hxx>
25 #include <GC_MakeCircle.hxx>
26 #include <Geom2d_Line.hxx>
27 #include <Geom2d_TrimmedCurve.hxx>
28 #include <Geom2dConvert.hxx>
29 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
30 #include <Geom_BezierCurve.hxx>
31 #include <Geom_BSplineCurve.hxx>
32 #include <Geom_Circle.hxx>
33 #include <Geom_CylindricalSurface.hxx>
34 #include <Geom_ElementarySurface.hxx>
35 #include <Geom_Line.hxx>
36 #include <Geom_OffsetSurface.hxx>
37 #include <Geom_RectangularTrimmedSurface.hxx>
38 #include <Geom_Surface.hxx>
39 #include <Geom_SurfaceOfLinearExtrusion.hxx>
40 #include <Geom_SurfaceOfRevolution.hxx>
41 #include <Geom_SweptSurface.hxx>
42 #include <Geom_TrimmedCurve.hxx>
43 #include <GeomAdaptor_HSurface.hxx>
44 #include <GeomConvert.hxx>
45 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
46 #include <GeomLib_IsPlanarSurface.hxx>
47 #include <gp_Cylinder.hxx>
48 #include <gp_Dir.hxx>
49 #include <gp_Lin.hxx>
50 #include <IntPatch_ImpImpIntersection.hxx>
51 #include <ShapeAnalysis_Edge.hxx>
52 #include <ShapeAnalysis_WireOrder.hxx>
53 #include <ShapeBuild_Edge.hxx>
54 #include <ShapeBuild_ReShape.hxx>
55 #include <ShapeExtend_CompositeSurface.hxx>
56 #include <ShapeFix_ComposeShell.hxx>
57 #include <ShapeFix_Edge.hxx>
58 #include <ShapeFix_Face.hxx>
59 #include <ShapeFix_SequenceOfWireSegment.hxx>
60 #include <ShapeFix_Shell.hxx>
61 #include <ShapeFix_Wire.hxx>
62 #include <ShapeFix_WireSegment.hxx>
63 #include <ShapeUpgrade_RemoveLocations.hxx>
64 #include <ShapeUpgrade_UnifySameDomain.hxx>
65 #include <Standard_Type.hxx>
66 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
67 #include <TColGeom2d_HArray1OfBSplineCurve.hxx>
68 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
69 #include <TColGeom_Array1OfBSplineCurve.hxx>
70 #include <TColGeom_HArray1OfBSplineCurve.hxx>
71 #include <TColGeom_HArray2OfSurface.hxx>
72 #include <TColGeom_SequenceOfSurface.hxx>
73 #include <TColStd_Array1OfReal.hxx>
74 #include <TColStd_MapOfInteger.hxx>
75 #include <TopExp.hxx>
76 #include <TopExp_Explorer.hxx>
77 #include <TopoDS.hxx>
78 #include <TopoDS_Edge.hxx>
79 #include <TopoDS_Face.hxx>
80 #include <TopoDS_Shape.hxx>
81 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
82 #include <TopTools_IndexedMapOfShape.hxx>
83 #include <TopTools_ListIteratorOfListOfShape.hxx>
84 #include <TopTools_MapOfShape.hxx>
85 #include <TopTools_SequenceOfShape.hxx>
86 #include <gp_Circ.hxx>
87 #include <BRepAdaptor_Curve.hxx>
88 #include <BRepClass_FaceClassifier.hxx>
89 #include <BRepAdaptor_Curve2d.hxx>
90 #include <gp_Vec2d.hxx>
91
92 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_UnifySameDomain,MMgt_TShared)
93
94 struct SubSequenceOfEdges
95 {
96   TopTools_SequenceOfShape SeqsEdges;
97   TopoDS_Edge UnionEdges;
98 };
99
100 static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge,
101                                    const TopoDS_Face& aFace,
102                                    const Handle(Geom_Surface)& aBaseSurface)
103 {
104   if (!aBaseSurface->IsUPeriodic() && !aBaseSurface->IsVPeriodic())
105     return Standard_False;
106
107   BRepAdaptor_Curve2d BAcurve2d(anEdge, aFace);
108   gp_Pnt2d FirstPoint, LastPoint;
109   gp_Vec2d FirstDir, LastDir;
110   BAcurve2d.D1(BAcurve2d.FirstParameter(), FirstPoint, FirstDir);
111   BAcurve2d.D1(BAcurve2d.LastParameter(),  LastPoint,  LastDir);
112   Standard_Real Length = FirstDir.Magnitude();
113   if (Length <= gp::Resolution())
114     return Standard_False;
115   else
116     FirstDir /= Length;
117   Length = LastDir.Magnitude();
118   if (Length <= gp::Resolution())
119     return Standard_False;
120   else
121     LastDir /= Length;
122   
123   Standard_Real Tol = 1.e-7;
124   if (aBaseSurface->IsUPeriodic() &&
125     (Abs(FirstDir.X()) < Tol) &&
126     (Abs(LastDir.X()) < Tol))
127     return Standard_True;
128
129   if (aBaseSurface->IsVPeriodic() &&
130     (Abs(FirstDir.Y()) < Tol) &&
131     (Abs(LastDir.Y()) < Tol))
132     return Standard_True;
133
134   return Standard_False;
135 }
136
137 //=======================================================================
138 //function : AddOrdinaryEdges
139 //purpose  : auxilary
140 //=======================================================================
141 // adds edges from the shape to the sequence
142 // seams and equal edges are dropped
143 // Returns true if one of original edges dropped
144 static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
145                                          const TopoDS_Shape aShape,
146                                          Standard_Integer& anIndex)
147 {
148   //map of edges
149   TopTools_IndexedMapOfShape aNewEdges;
150   //add edges without seams
151   for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
152     TopoDS_Shape edge = exp.Current();
153     if(aNewEdges.Contains(edge))
154     {
155       //aNewEdges.Remove(edge);
156       TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
157       aNewEdges.RemoveLast();
158       if (aNewEdges.FindIndex(edge) != 0)
159         aNewEdges.Substitute(aNewEdges.FindIndex(edge), LastEdge);
160       /////////////////////////
161     }
162     else
163       aNewEdges.Add(edge);
164   }
165
166   Standard_Boolean isDropped = Standard_False;
167   //merge edges and drop seams
168   Standard_Integer i;
169   for (i = 1; i <= edges.Length(); i++) {
170     TopoDS_Shape current = edges(i);
171     if(aNewEdges.Contains(current)) {
172
173       //aNewEdges.Remove(current);
174       TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
175       aNewEdges.RemoveLast();
176       if (aNewEdges.FindIndex(current) != 0)
177         aNewEdges.Substitute(aNewEdges.FindIndex(current), LastEdge);
178       /////////////////////////
179       edges.Remove(i);
180       i--;
181
182       if(!isDropped) {
183         isDropped = Standard_True;
184         anIndex = i;
185       }
186     }
187   }
188
189   //add edges to the sequemce
190   for (i = 1; i <= aNewEdges.Extent(); i++)
191     edges.Append(aNewEdges(i));
192
193   return isDropped;
194 }
195
196 //=======================================================================
197 //function : getCylinder
198 //purpose  : auxilary
199 //=======================================================================
200 static Standard_Boolean getCylinder(Handle(Geom_Surface)& theInSurface,
201                                     gp_Cylinder& theOutCylinder)
202 {
203   Standard_Boolean isCylinder = Standard_False;
204
205   if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
206     Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface);
207
208     theOutCylinder = aGC->Cylinder();
209     isCylinder = Standard_True;
210   }
211   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
212     Handle(Geom_SurfaceOfRevolution) aRS =
213       Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface);
214     Handle(Geom_Curve) aBasis = aRS->BasisCurve();
215     if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) {
216       Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis);
217       gp_Dir aDir = aRS->Direction();
218       gp_Dir aBasisDir = aBasisLine->Position().Direction();
219       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
220         // basis line is parallel to the revolution axis: it is a cylinder
221         gp_Pnt aLoc = aRS->Location();
222         Standard_Real aR = aBasisLine->Lin().Distance(aLoc);
223         gp_Ax3 aCylAx (aLoc, aDir);
224
225         theOutCylinder = gp_Cylinder(aCylAx, aR);
226         isCylinder = Standard_True;
227       }
228     }
229   }
230   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
231     Handle(Geom_SurfaceOfLinearExtrusion) aLES =
232       Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface);
233     Handle(Geom_Curve) aBasis = aLES->BasisCurve();
234     if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) {
235       Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis);
236       gp_Dir aDir = aLES->Direction();
237       gp_Dir aBasisDir = aBasisCircle->Position().Direction();
238       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
239         // basis circle is normal to the extrusion axis: it is a cylinder
240         gp_Pnt aLoc = aBasisCircle->Location();
241         Standard_Real aR = aBasisCircle->Radius();
242         gp_Ax3 aCylAx (aLoc, aDir);
243
244         theOutCylinder = gp_Cylinder(aCylAx, aR);
245         isCylinder = Standard_True;
246       }
247     }
248   }
249   else {
250   }
251
252   return isCylinder;
253 }
254
255 //=======================================================================
256 //function : ClearRts
257 //purpose  : auxilary
258 //=======================================================================
259 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
260 {
261   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
262     Handle(Geom_RectangularTrimmedSurface) rts =
263       Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
264     return rts->BasisSurface();
265   }
266   return aSurface;
267 }
268
269 //=======================================================================
270 //function : IsSameDomain
271 //purpose  : 
272 //=======================================================================
273 static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
274                                      const TopoDS_Face& aCheckedFace)
275 {
276   //checking the same handles
277   TopLoc_Location L1, L2;
278   Handle(Geom_Surface) S1, S2;
279
280   S1 = BRep_Tool::Surface(aFace,L1);
281   S2 = BRep_Tool::Surface(aCheckedFace,L2);
282
283   if (S1 == S2 && L1 == L2)
284     return Standard_True;
285
286   // planar and cylindrical cases (IMP 20052)
287   Standard_Real aPrec = Precision::Confusion();
288
289   S1 = BRep_Tool::Surface(aFace);
290   S2 = BRep_Tool::Surface(aCheckedFace);
291
292   S1 = ClearRts(S1);
293   S2 = ClearRts(S2);
294
295   //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
296   //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
297   //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
298   //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
299   //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
300
301   // case of two elementary surfaces: use OCCT tool
302   // elementary surfaces: ConicalSurface, CylindricalSurface,
303   //                      Plane, SphericalSurface and ToroidalSurface
304   if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
305       S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
306   {
307     Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1);
308     Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2);
309
310     Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
311     Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
312
313     try {
314       IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
315       if (!anIIInt.IsDone() || anIIInt.IsEmpty())
316         return Standard_False;
317
318       return anIIInt.TangentFaces();
319     }
320     catch (Standard_Failure) {
321       return Standard_False;
322     }
323   }
324
325   // case of two planar surfaces:
326   // all kinds of surfaces checked, including b-spline and bezier
327   GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
328   if (aPlanarityChecker1.IsPlanar()) {
329     GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
330     if (aPlanarityChecker2.IsPlanar()) {
331       gp_Pln aPln1 = aPlanarityChecker1.Plan();
332       gp_Pln aPln2 = aPlanarityChecker2.Plan();
333
334       if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(),Precision::Angular()) &&
335           aPln1.Distance(aPln2) < aPrec) {
336         return Standard_True;
337       }
338     }
339   }
340
341   // case of two cylindrical surfaces, at least one of which is a swept surface
342   // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
343   if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
344        S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
345       (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
346        S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
347   {
348     gp_Cylinder aCyl1, aCyl2;
349     if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
350       if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
351         gp_Dir aDir1 = aCyl1.Position().Direction();
352         gp_Dir aDir2 = aCyl2.Position().Direction();
353         if (aDir1.IsParallel(aDir2, Precision::Angular())) {
354           gp_Pnt aLoc1 = aCyl1.Location();
355           gp_Pnt aLoc2 = aCyl2.Location();
356           gp_Vec aVec12 (aLoc1, aLoc2);
357           if (aVec12.SquareMagnitude() < aPrec*aPrec ||
358               aVec12.IsParallel(aDir1, Precision::Angular())) {
359             return Standard_True;
360           }
361         }
362       }
363     }
364   }
365
366   return Standard_False;
367 }
368
369 //=======================================================================
370 //function : MovePCurves
371 //purpose  :
372 //=======================================================================
373 static void MovePCurves(TopoDS_Face& aTarget,
374                         const TopoDS_Face& aSource)
375 {
376   BRep_Builder B;
377   for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
378     Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
379                                                   aTarget, Precision::Confusion());
380     sfw->FixReorder();
381     Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
382     sfw->FixEdgeCurves();
383     if(isReoredFailed)
384       continue;
385
386     sfw->FixShifted();
387     sfw->FixDegenerated();
388
389     // remove degenerated edges from not degenerated points
390     ShapeAnalysis_Edge sae;
391     Handle(ShapeExtend_WireData) sewd = sfw->WireData();
392     for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
393       TopoDS_Edge E = sewd->Edge(i);
394       if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
395         sewd->Remove(i);
396         i--;
397       }
398     }
399
400     TopoDS_Wire ResWire = sfw->Wire();
401     B.Add(aTarget,ResWire);
402   }
403 }
404
405 //=======================================================================
406 //function : GlueEdgesWithPCurves
407 //purpose  : Glues the pcurves of the sequence of edges
408 //           and glues their 3d curves
409 //=======================================================================
410 static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
411                                         const TopoDS_Vertex& FirstVertex,
412                                         const TopoDS_Vertex& LastVertex)
413 {
414   Standard_Integer i, j;
415
416   TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
417   //TColGeom2d_SequenceOfCurve PCurveSeq;
418   TColGeom_SequenceOfSurface SurfSeq;
419   //TopTools_SequenceOfShape LocSeq;
420   
421   BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() );
422   for (; itr.More(); itr.Next())
423   {
424     Handle(BRep_CurveRepresentation) CurveRep = itr.Value();
425     if (CurveRep->IsCurveOnSurface())
426     {
427       //PCurveSeq.Append(CurveRep->PCurve());
428       SurfSeq.Append(CurveRep->Surface());
429       /*
430       TopoDS_Shape aLocShape;
431       aLocShape.Location(CurveRep->Location());
432       LocSeq.Append(aLocShape);
433       */
434     }
435   }
436
437   Standard_Real fpar, lpar;
438   BRep_Tool::Range(FirstEdge, fpar, lpar);
439   TopoDS_Edge PrevEdge = FirstEdge;
440   TopoDS_Vertex CV;
441   Standard_Real MaxTol = 0.;
442   
443   TopoDS_Edge ResEdge;
444   BRep_Builder BB;
445
446   Standard_Integer nb_curve = aChain.Length();   //number of curves
447   TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1);                    //array of the curves
448   TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
449     
450   TopoDS_Vertex PrevVertex = FirstVertex;
451   for (i = 1; i <= nb_curve; i++)
452   {
453     TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
454     TopoDS_Vertex VF, VL;
455     TopExp::Vertices(anEdge, VF, VL);
456     Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
457     
458     Standard_Real Tol1 = BRep_Tool::Tolerance(VF);
459     Standard_Real Tol2 = BRep_Tool::Tolerance(VL);
460     if (Tol1 > MaxTol)
461       MaxTol = Tol1;
462     if (Tol2 > MaxTol)
463       MaxTol = Tol2;
464     
465     if (i > 1)
466     {
467       TopExp::CommonVertex(PrevEdge, anEdge, CV);
468       Standard_Real Tol = BRep_Tool::Tolerance(CV);
469       tabtolvertex(i-2) = Tol;
470     }
471     
472     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
473     Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar);
474     tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
475     GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion());
476     if (ToReverse)
477       tab_c3d(i-1)->Reverse();
478     PrevVertex = (ToReverse)? VF : VL;
479     PrevEdge = anEdge;
480   }
481   Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
482   Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
483   GeomConvert::ConcatC1(tab_c3d,
484                         tabtolvertex,
485                         ArrayOfIndices,
486                         concatcurve,
487                         Standard_False,
488                         Precision::Confusion());   //C1 concatenation
489   
490   if (concatcurve->Length() > 1)
491   {
492     GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
493     
494     for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
495       Concat.Add( concatcurve->Value(i), MaxTol, Standard_True );
496     
497     concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
498   }
499   Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower());
500   
501   TColGeom2d_SequenceOfBoundedCurve ResPCurves;
502   TopLoc_Location aLoc;
503   for (j = 1; j <= SurfSeq.Length(); j++)
504   {
505     TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves
506     
507     PrevVertex = FirstVertex;
508     PrevEdge = FirstEdge;
509     //TopLoc_Location theLoc = LocSeq(j).Location();
510     for (i = 1; i <= nb_curve; i++)
511     {
512       TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
513       TopoDS_Vertex VF, VL;
514       TopExp::Vertices(anEdge, VF, VL);
515       Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
516
517       /*
518       Handle(Geom2d_Curve) aPCurve =
519         BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar);
520       */
521       Handle(Geom2d_Curve) aPCurve =
522         BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar);
523       Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
524       tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve);
525       Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion());
526       if (ToReverse)
527         tab_c2d(i-1)->Reverse();
528       PrevVertex = (ToReverse)? VF : VL;
529       PrevEdge = anEdge;
530     }
531     Handle(TColGeom2d_HArray1OfBSplineCurve)  concatc2d;     //array of the concatenated curves
532     Handle(TColStd_HArray1OfInteger)        ArrayOfInd2d;  //array of the remining Vertex
533     Geom2dConvert::ConcatC1(tab_c2d,
534                             tabtolvertex,
535                             ArrayOfInd2d,
536                             concatc2d,
537                             Standard_False,
538                             Precision::Confusion());   //C1 concatenation
539     
540     if (concatc2d->Length() > 1)
541     {
542       Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower()));
543       
544       for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++)
545         Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True );
546       
547       concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve());
548     }
549     Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower());
550     ResPCurves.Append(aResPCurve);
551   }
552   
553   ResEdge = BRepLib_MakeEdge(ResCurve,
554                              FirstVertex, LastVertex,
555                              ResCurve->FirstParameter(), ResCurve->LastParameter());
556   BB.SameRange(ResEdge, Standard_False);
557   BB.SameParameter(ResEdge, Standard_False);
558   for (j = 1; j <= ResPCurves.Length(); j++)
559   {
560     BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol);
561     BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
562   }
563
564   BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
565   
566   return ResEdge;
567 }
568
569 //=======================================================================
570 //function : MergeSubSeq
571 //purpose  : Merges a sequence of edges into one edge if possible
572 //=======================================================================
573
574 static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& aChain, TopoDS_Edge& OutEdge, double Tol, Standard_Boolean ConcatBSplines) 
575 {
576   ShapeAnalysis_Edge sae;
577   BRep_Builder B;
578   // union edges in chain
579   int j;
580   Standard_Real fp1,lp1,fp2,lp2;
581   Standard_Boolean IsUnionOfLinesPossible = Standard_True;
582   Standard_Boolean IsUnionOfCirclesPossible = Standard_True;
583   Handle(Geom_Curve) c3d1, c3d2;
584   for(j=1; j<aChain.Length(); j++) 
585   {
586     TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
587     c3d1 = BRep_Tool::Curve(edge1,fp1,lp1);
588
589     TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
590     c3d2 = BRep_Tool::Curve(edge2,fp2,lp2);
591
592     if(c3d1.IsNull() || c3d2.IsNull()) 
593       return Standard_False;
594
595     while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
596       Handle(Geom_TrimmedCurve) tc =
597         Handle(Geom_TrimmedCurve)::DownCast(c3d1);
598       c3d1 = tc->BasisCurve();
599     }
600     while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
601       Handle(Geom_TrimmedCurve) tc =
602         Handle(Geom_TrimmedCurve)::DownCast(c3d2);
603       c3d2 = tc->BasisCurve();
604     }
605     if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
606       Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
607       Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
608       gp_Dir Dir1 = L1->Position().Direction();
609       gp_Dir Dir2 = L2->Position().Direction();
610       if(!Dir1.IsParallel(Dir2,Tol))  
611         IsUnionOfLinesPossible = Standard_False;
612     }
613     else
614       IsUnionOfLinesPossible = Standard_False;
615     if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
616       Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
617       Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
618       gp_Pnt P01 = C1->Location();
619       gp_Pnt P02 = C2->Location();
620       if (P01.Distance(P02) > Precision::Confusion())
621         IsUnionOfCirclesPossible = Standard_False;
622     }
623     else
624       IsUnionOfCirclesPossible = Standard_False;
625   }
626   if (IsUnionOfLinesPossible && IsUnionOfCirclesPossible)
627     return Standard_False;
628
629   //union of lines is possible
630   if (IsUnionOfLinesPossible)
631   {
632     TopoDS_Vertex V1 = sae.FirstVertex(TopoDS::Edge(aChain.First()));
633     gp_Pnt PV1 = BRep_Tool::Pnt(V1);
634     TopoDS_Vertex V2 = sae.LastVertex(TopoDS::Edge(aChain.Last()));
635     gp_Pnt PV2 = BRep_Tool::Pnt(V2);
636     gp_Vec Vec(PV1, PV2);
637     Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
638     Standard_Real dist = PV1.Distance(PV2);
639     Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
640     TopoDS_Edge E;
641     B.MakeEdge (E, tc ,Precision::Confusion());
642     B.Add (E,V1);  B.Add (E,V2);
643     B.UpdateVertex(V1, 0., E, 0.);
644     B.UpdateVertex(V2, dist, E, 0.);
645     OutEdge = E;
646     return Standard_True;
647   }
648
649   if (IsUnionOfCirclesPossible)
650   {
651     double f,l;
652     TopoDS_Edge FE = TopoDS::Edge(aChain.First());
653     Handle(Geom_Curve) c3d = BRep_Tool::Curve(FE,f,l);
654
655     while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
656       Handle(Geom_TrimmedCurve) tc =
657         Handle(Geom_TrimmedCurve)::DownCast(c3d);
658       c3d = tc->BasisCurve();
659     }
660     Handle(Geom_Circle) Cir = Handle(Geom_Circle)::DownCast(c3d);
661
662     TopoDS_Vertex V1 = sae.FirstVertex(FE);
663     TopoDS_Vertex V2 = sae.LastVertex(TopoDS::Edge(aChain.Last()));
664     TopoDS_Edge E;
665     if (V1.IsSame(V2)) {
666       // closed chain
667       BRepAdaptor_Curve adef(FE);
668       Handle(Geom_Circle) Cir1;
669       double FP, LP;
670       if ( FE.Orientation() == TopAbs_FORWARD)
671       {
672         FP = adef.FirstParameter();
673         LP = adef.LastParameter();
674       }
675       else
676       {
677         FP = adef.LastParameter();
678         LP = adef.FirstParameter();
679       }
680       if (Abs(FP) < Precision::PConfusion())
681       {
682         B.MakeEdge (E,Cir, Precision::Confusion());
683         B.Add(E,V1);
684         B.Add(E,V2);
685         E.Orientation(FE.Orientation());
686       }
687       else
688       {
689         GC_MakeCircle MC1 (adef.Value(FP), adef.Value((FP + LP) * 0.5), adef.Value(LP));
690         if (MC1.IsDone())
691           Cir1 = MC1.Value();
692         else
693           return Standard_False;
694         B.MakeEdge (E, Cir1, Precision::Confusion());
695         B.Add(E,V1);
696         B.Add(E,V2);
697       }
698     }
699     else {
700       gp_Pnt PV1 = BRep_Tool::Pnt(V1);
701       gp_Pnt PV2 = BRep_Tool::Pnt(V2);
702       TopoDS_Vertex VM = sae.LastVertex(FE);
703       gp_Pnt PVM = BRep_Tool::Pnt(VM);
704       GC_MakeCircle MC (PV1,PVM,PV2);
705       Handle(Geom_Circle) C = MC.Value();
706       gp_Pnt P0 = C->Location();
707       gp_Dir D1(gp_Vec(P0,PV1));
708       gp_Dir D2(gp_Vec(P0,PV2));
709       Standard_Real fpar = C->XAxis().Direction().Angle(D1);
710       if(fabs(fpar)>Precision::Confusion()) {
711         // check orientation
712         gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
713         if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
714           fpar = -fpar;
715         }
716       }
717       Standard_Real lpar = C->XAxis().Direction().Angle(D2);
718       if(fabs(lpar)>Precision::Confusion()) {
719         // check orientation
720         gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
721         if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
722           lpar = -lpar;
723         }
724       }
725       if (lpar < fpar) lpar += 2*M_PI;
726       Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
727       B.MakeEdge (E,tc,Precision::Confusion());
728       B.Add(E,V1);
729       B.Add(E,V2);
730       B.UpdateVertex(V1, fpar, E, 0.);
731       B.UpdateVertex(V2, lpar, E, 0.);
732     }
733     OutEdge = E;
734     return Standard_True;
735   }
736   if (aChain.Length() > 1 && ConcatBSplines) {
737     // second step: union edges with various curves
738     // skl for bug 0020052 from Mantis: perform such unions
739     // only if curves are bspline or bezier
740
741     TopoDS_Vertex VF = sae.FirstVertex(TopoDS::Edge(aChain.First()));
742     TopoDS_Vertex VL = sae.LastVertex(TopoDS::Edge(aChain.Last()));
743     Standard_Boolean NeedUnion = Standard_True;
744     for(j=1; j<=aChain.Length(); j++) {
745       TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
746       TopLoc_Location Loc;
747       Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
748       if(c3d.IsNull()) continue;
749       while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
750         Handle(Geom_TrimmedCurve) tc =
751           Handle(Geom_TrimmedCurve)::DownCast(c3d);
752         c3d = tc->BasisCurve();
753       }
754       if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
755             c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
756       NeedUnion = Standard_False;
757       break;
758     }
759     if(NeedUnion) {
760 #ifdef OCCT_DEBUG
761       cout<<"can not make analitical union => make approximation"<<endl;
762 #endif
763       TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
764       OutEdge = E;
765       return Standard_True;
766     }
767     else {
768 #ifdef OCCT_DEBUG
769       cout<<"can not make approximation for such types of curves"<<endl;
770 #endif
771       return Standard_False;
772     }
773   }
774   return Standard_False;
775 }
776
777 //=======================================================================
778 //function : IsMergingPossible
779 //purpose  : Checks if merging of two edges is possible
780 //=======================================================================
781
782 static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, 
783                                           double Tol, const TopTools_MapOfShape& DegEdgeVrt)
784 {
785   TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True);
786   if (CV.IsNull() || DegEdgeVrt.Contains(CV))
787     return Standard_False;
788
789   BRepAdaptor_Curve ade1(edge1);
790   BRepAdaptor_Curve ade2(edge2);
791
792   GeomAbs_CurveType t1 = ade1.GetType();
793   GeomAbs_CurveType t2 = ade2.GetType();
794
795   if( t1 == GeomAbs_Circle && t2 == GeomAbs_Circle)
796   {
797     if (ade1.Circle().Location().Distance(ade2.Circle().Location()) > Precision::Confusion())
798       return Standard_False;
799   }
800
801   if( ( (t1 != GeomAbs_BezierCurve && t1 != GeomAbs_BSplineCurve) ||
802       (t2 != GeomAbs_BezierCurve && t2 != GeomAbs_BSplineCurve)) && t1 != t2)
803     return Standard_False;
804
805   gp_Vec Diff1, Diff2;
806   gp_Pnt P1, P2;
807   if (edge1.Orientation() == TopAbs_FORWARD)
808     ade1.D1(ade1.LastParameter(), P1, Diff1);
809   else
810   {
811     ade1.D1(ade1.FirstParameter(), P1, Diff1);
812     Diff1 = -Diff1;
813   }
814
815   if (edge2.Orientation() == TopAbs_FORWARD)
816     ade2.D1(ade2.FirstParameter(), P2, Diff2);
817   else
818   {
819     ade2.D1(ade2.LastParameter(), P2, Diff2);
820     Diff2 = -Diff2;
821   }
822
823   if (Diff1.Angle(Diff2) > Tol)
824     return Standard_False;
825
826   return Standard_True;
827 }
828
829 //=======================================================================
830 //function : GenerateSubSeq
831 //purpose  : Generates sub-sequences of edges from sequence of edges
832 //Edges from each subsequences can be merged into the one edge  
833 //=======================================================================
834
835 static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
836                             NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
837                             Standard_Boolean IsClosed, double Tol, const TopTools_MapOfShape& DegEdgeVrt )
838 {
839   Standard_Boolean isOk = Standard_False;
840   TopoDS_Edge edge1, edge2;
841
842   SubSequenceOfEdges SubSeq;
843   SubSeq.SeqsEdges.Append(TopoDS::Edge(anInpEdgeSeq(1)));
844   SeqOfSubSeqOfEdges.Append(SubSeq);
845
846   for (int i = 1; i < anInpEdgeSeq.Length(); i++)
847   {
848     edge1 = TopoDS::Edge(anInpEdgeSeq(i));
849     edge2 = TopoDS::Edge(anInpEdgeSeq(i+1));
850     isOk = IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt);
851     if (!isOk)
852     {
853       SubSequenceOfEdges aSubSeq;
854       aSubSeq.SeqsEdges.Append(edge2);
855       SeqOfSubSeqOfEdges.Append(aSubSeq);
856     }
857     else
858       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(edge2);
859   }
860   /// check first and last chain segments
861   if (IsClosed && SeqOfSubSeqOfEdges.Length() > 1)
862   {
863     edge1 = TopoDS::Edge(anInpEdgeSeq.Last());
864     edge2 = TopoDS::Edge(anInpEdgeSeq.First());
865     if (IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt))
866     {
867       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges);
868       SeqOfSubSeqOfEdges.Remove(1);
869     }
870   }
871 }
872
873
874 //=======================================================================
875 //function : MergeEdges
876 //purpose  : auxilary
877 //=======================================================================
878 static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges,
879                                    const Standard_Real Tol,
880                                    const Standard_Boolean ConcatBSplines,
881                                    NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
882                                    const TopTools_MapOfShape& NonMergVrt )
883 {
884   // skip degenerated edges, and forbid merging through them
885   TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
886   Standard_Integer j;
887   TopTools_MapOfShape VerticesToAvoid;
888   for (j = 1; j <= SeqEdges.Length(); j++)
889   {
890     TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j));
891     if (BRep_Tool::Degenerated(anEdge))
892     {
893       TopoDS_Vertex V1, V2;
894       TopExp::Vertices(anEdge, V1, V2);
895       VerticesToAvoid.Add(V1);
896       VerticesToAvoid.Add(V2);
897       SeqEdges.Remove(j--);
898     }
899     else
900     {
901       // fill in the map V-E
902       for (TopoDS_Iterator it(anEdge.Oriented(TopAbs_FORWARD)); it.More(); it.Next())
903       {
904         TopoDS_Shape aV = it.Value();
905         if (aV.Orientation() == TopAbs_FORWARD || aV.Orientation() == TopAbs_REVERSED)
906         {
907           if (!aMapVE.Contains(aV))
908             aMapVE.Add(aV, TopTools_ListOfShape());
909           aMapVE.ChangeFromKey(aV).Append(anEdge);
910   }
911       }
912     }
913   }
914   VerticesToAvoid.Unite(NonMergVrt);
915
916   // do loop while there are unused edges
917   TopTools_MapOfShape aUsedEdges;
918   for (;;)
919   {
920     TopoDS_Edge edge;
921     for(j=1; j <= SeqEdges.Length(); j++)
922     {
923       edge = TopoDS::Edge(SeqEdges.Value(j));
924       if (!aUsedEdges.Contains(edge))
925         break;
926     }
927     if (j > SeqEdges.Length())
928       break; // all edges have been used
929
930     // make chain for unite
931     TopTools_SequenceOfShape aChain;
932         aChain.Append(edge);
933     aUsedEdges.Add(edge);
934     TopoDS_Vertex V[2];
935     TopExp::Vertices(edge, V[0], V[1], Standard_True);
936
937     // connect more edges to the chain in both directions
938     for (j = 0; j < 2; j++)
939     {
940       Standard_Boolean isAdded = Standard_True;
941       while (isAdded)
942       {
943         isAdded = Standard_False;
944         if (V[j].IsNull())
945           break;
946         const TopTools_ListOfShape& aLE = aMapVE.FindFromKey(V[j]);
947         for (TopTools_ListIteratorOfListOfShape itL(aLE); itL.More(); itL.Next())
948         {
949           edge = TopoDS::Edge(itL.Value());
950           if (!aUsedEdges.Contains(edge))
951           {
952             if (j == 0)
953         aChain.Prepend(edge);
954             else
955               aChain.Append(edge);
956             aUsedEdges.Add(edge);
957             TopoDS_Vertex VF2, VL2;
958             TopExp::Vertices(edge, VF2, VL2, Standard_True);
959             V[j] = (VF2.IsSame(V[j]) ? VL2 : VF2);
960             isAdded = Standard_True;
961             break;
962       }
963     }
964   }
965     }
966
967     if (aChain.Length() < 2)
968       continue;
969
970   Standard_Boolean IsClosed = Standard_False;
971     if (V[0].IsSame ( V[1] ))
972     IsClosed = Standard_True;
973
974     // split chain by vertices at which merging is not possible
975     NCollection_Sequence<SubSequenceOfEdges> aOneSeq;
976     GenerateSubSeq(aChain, aOneSeq, IsClosed, Tol, VerticesToAvoid);
977
978     // put sub-chains in the result
979     SeqOfSubSeqOfEdges.Append(aOneSeq);
980   }
981
982   for (int i = 1; i <= SeqOfSubSeqOfEdges.Length(); i++)
983   {
984     TopoDS_Edge UE;
985     if (SeqOfSubSeqOfEdges(i).SeqsEdges.Length() < 2)
986       continue;
987     if (MergeSubSeq(SeqOfSubSeqOfEdges(i).SeqsEdges, UE, Tol, ConcatBSplines))
988       SeqOfSubSeqOfEdges(i).UnionEdges = UE;
989   }
990   return Standard_True;
991 }
992
993 //=======================================================================
994 //function : MergeSeq
995 //purpose  : Tries to unify the sequence of edges with the set of another edges 
996 //which lies on the same geometry
997 //=======================================================================
998
999 static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges,
1000                                   const Standard_Real Tol,
1001                                   const Standard_Boolean ConcatBSplines,
1002                                   Handle(ShapeBuild_ReShape)& theContext,
1003                                   TopTools_DataMapOfShapeShape& theOldShapes,
1004                                   const TopTools_MapOfShape& nonMergVert,
1005                                   const TopTools_DataMapOfShapeShape& NewEdges2OldEdges)
1006
1007   NCollection_Sequence<SubSequenceOfEdges> SeqOfSubsSeqOfEdges;
1008   int k = 1;
1009   if ( MergeEdges(SeqEdges, Tol, ConcatBSplines, SeqOfSubsSeqOfEdges, nonMergVert) )
1010   {
1011     for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ )
1012     {
1013       if (SeqOfSubsSeqOfEdges(i).UnionEdges.IsNull())
1014         continue;
1015       theContext->Replace(SeqOfSubsSeqOfEdges(i).SeqsEdges(1), SeqOfSubsSeqOfEdges(i).UnionEdges);
1016       k++;
1017       for (Standard_Integer j = 2; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++)
1018       {
1019         TopoDS_Shape OldEdge = NewEdges2OldEdges(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
1020         theOldShapes.Bind(OldEdge, SeqOfSubsSeqOfEdges(i).UnionEdges);
1021         theContext->Remove(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
1022       }
1023     }
1024     return Standard_True;
1025   }
1026   else
1027     return Standard_False;
1028 }
1029
1030 //=======================================================================
1031 //function : CheckSharedVertices
1032 //purpose  : Checks the sequence of edges on the presence of shared vertex 
1033 //=======================================================================
1034
1035 static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, 
1036                                 const TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgesVertex,
1037                                 TopTools_MapOfShape& theShareVertMap)
1038 {
1039   ShapeAnalysis_Edge sae;
1040   TopTools_SequenceOfShape SeqVertexes;
1041   TopTools_MapOfShape MapVertexes;
1042   for (Standard_Integer k = 1; k <= theSeqEdges.Length(); k++ )
1043   {
1044     TopoDS_Vertex aV1 = sae.FirstVertex(TopoDS::Edge(theSeqEdges(k)));
1045     TopoDS_Vertex aV2 = sae.LastVertex(TopoDS::Edge(theSeqEdges(k)));
1046     if (!MapVertexes.Add(aV1))
1047       SeqVertexes.Append(aV1);
1048     if (!MapVertexes.Add(aV2))
1049       SeqVertexes.Append(aV2);
1050   }
1051
1052   for (Standard_Integer k = 1; k <= SeqVertexes.Length()/* && !IsSharedVertexPresent*/; k++ )
1053   {
1054     const TopTools_ListOfShape& ListEdgesV1 = theMapEdgesVertex.FindFromKey(SeqVertexes(k));
1055     TopTools_MapOfShape aMapOfEdges;
1056     TopTools_ListIteratorOfListOfShape iter(ListEdgesV1);
1057     for (; iter.More(); iter.Next())
1058       aMapOfEdges.Add(iter.Value());
1059     if (aMapOfEdges.Extent() > 2)
1060       theShareVertMap.Add(SeqVertexes(k));
1061   }
1062   //return theShareVertMap.IsEmpty() ? false : true;
1063 }
1064
1065 //=======================================================================
1066 //function : ShapeUpgrade_UnifySameDomain
1067 //purpose  : Constructor
1068 //=======================================================================
1069
1070 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
1071   : myUnifyFaces (Standard_True),
1072     myUnifyEdges (Standard_True),
1073     myConcatBSplines (Standard_False),
1074     myAllowInternal (Standard_False)
1075 {
1076   myContext = new ShapeBuild_ReShape;
1077 }
1078
1079 //=======================================================================
1080 //function : ShapeUpgrade_UnifySameDomain
1081 //purpose  : Constructor
1082 //=======================================================================
1083
1084 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape,
1085                                                            const Standard_Boolean UnifyEdges,
1086                                                            const Standard_Boolean UnifyFaces,
1087                                                            const Standard_Boolean ConcatBSplines)
1088   : myInitShape (aShape),
1089     myUnifyFaces (UnifyFaces),
1090     myUnifyEdges (UnifyEdges),
1091     myConcatBSplines (ConcatBSplines),
1092     myAllowInternal (Standard_False),
1093     myShape (aShape)
1094 {
1095   myContext = new ShapeBuild_ReShape;
1096 }
1097
1098 //=======================================================================
1099 //function : Initialize
1100 //purpose  : 
1101 //=======================================================================
1102
1103 void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
1104                                               const Standard_Boolean UnifyEdges,
1105                                               const Standard_Boolean UnifyFaces,
1106                                               const Standard_Boolean ConcatBSplines)
1107 {
1108   myInitShape = aShape;
1109   myShape = aShape;
1110   myUnifyEdges = UnifyEdges;
1111   myUnifyFaces = UnifyFaces;
1112   myConcatBSplines = ConcatBSplines;
1113
1114   myContext->Clear();
1115   myOldShapes.Clear();
1116 }
1117
1118 //=======================================================================
1119 //function : AllowInternalEdges
1120 //purpose  : 
1121 //=======================================================================
1122
1123 void ShapeUpgrade_UnifySameDomain::AllowInternalEdges (const Standard_Boolean theValue)
1124 {
1125   myAllowInternal = theValue;
1126 }
1127
1128 //=======================================================================
1129 //function : putIntWires
1130 //purpose  : Add internal wires that are classified inside the face as a subshape,
1131 //           and remove them from the sequence
1132 //=======================================================================
1133 static void putIntWires(TopoDS_Shape& theFace, TopTools_SequenceOfShape& theWires)
1134 {
1135   TopoDS_Face& aFace = TopoDS::Face(theFace);
1136   for (Standard_Integer i=1; i <= theWires.Length(); i++)
1137   {
1138     TopoDS_Shape aWire = theWires(i);
1139     gp_Pnt2d aP2d;
1140     Standard_Boolean isP2d = Standard_False;
1141     for (TopoDS_Iterator it(aWire); it.More() && !isP2d; it.Next())
1142     {
1143       const TopoDS_Edge& anEdge = TopoDS::Edge(it.Value());
1144       Standard_Real aFirst, aLast;
1145       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aFace, aFirst, aLast);
1146       aC2d->D0((aFirst + aLast) * 0.5, aP2d);
1147       isP2d = Standard_True;
1148     }
1149     BRepClass_FaceClassifier aClass(aFace, aP2d, Precision::PConfusion());
1150     if (aClass.State() == TopAbs_IN)
1151     {
1152       BRep_Builder().Add(aFace, aWire);
1153       theWires.Remove(i);
1154       i--;
1155     }
1156   }
1157 }
1158
1159 //=======================================================================
1160 //function : UnifyFaces
1161 //purpose  : 
1162 //=======================================================================
1163
1164 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
1165 {
1166   // creating map of edge faces for the whole shape
1167   TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces;
1168   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces);
1169
1170   // processing each shell
1171   TopExp_Explorer exps;
1172   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
1173     TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
1174
1175     // creating map of edge faces for the shell
1176     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
1177     TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
1178
1179     // map of processed shapes
1180     TopTools_MapOfShape aProcessed;
1181
1182     Standard_Integer NbModif = 0;
1183     Standard_Boolean hasFailed = Standard_False;
1184     Standard_Real tol = Precision::Confusion();
1185
1186     // count faces
1187     Standard_Integer nbf = 0;
1188     TopExp_Explorer exp;
1189     TopTools_MapOfShape mapF;
1190     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
1191       if (mapF.Add(exp.Current()))
1192         nbf++;
1193     }
1194
1195     // processing each face
1196     mapF.Clear();
1197     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
1198       TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
1199
1200       if (aProcessed.Contains(aFace))
1201         continue;
1202
1203       Standard_Integer dummy;
1204       TopTools_SequenceOfShape edges;
1205       AddOrdinaryEdges(edges,aFace,dummy);
1206
1207       TopTools_SequenceOfShape faces;
1208       faces.Append(aFace);
1209
1210       //surface and location to construct result
1211       TopLoc_Location aBaseLocation;
1212       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
1213       aBaseSurface = ClearRts(aBaseSurface);
1214
1215       // find adjacent faces to union
1216       Standard_Integer i;
1217       for (i = 1; i <= edges.Length(); i++) {
1218         TopoDS_Edge edge = TopoDS::Edge(edges(i));
1219         if (BRep_Tool::Degenerated(edge))
1220           continue;
1221
1222         // get connectivity of the edge in the global shape
1223         const TopTools_ListOfShape& aGList = aGMapEdgeFaces.FindFromKey(edge);
1224         if (!myAllowInternal && aGList.Extent() != 2) {
1225           // non mainfold case is not processed unless myAllowInternal
1226           continue;
1227         }
1228         // process faces connected through the edge in the current shell
1229         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
1230         TopTools_ListIteratorOfListOfShape anIter(aList);
1231         for (; anIter.More(); anIter.Next()) {
1232           TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
1233           if (anCheckedFace.IsSame(aFace))
1234             continue;
1235
1236           if (aProcessed.Contains(anCheckedFace))
1237             continue;
1238
1239           if (IsSameDomain(aFace,anCheckedFace)) {
1240
1241             // hotfix for 27271: prevent merging along periodic direction.
1242             if (IsLikeSeam(edge, aFace, aBaseSurface))
1243               continue;
1244
1245             // replacing pcurves
1246             TopoDS_Face aMockUpFace;
1247             BRep_Builder B;
1248             B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
1249             MovePCurves(aMockUpFace,anCheckedFace);
1250
1251             if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
1252               // sequence edges is modified
1253               i = dummy;
1254             }
1255
1256             faces.Append(anCheckedFace);
1257             aProcessed.Add(anCheckedFace);
1258             break;
1259           }
1260         }
1261       }
1262
1263       if (faces.Length() > 1) {
1264         // fill in the connectivity map for selected faces
1265         TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1266         for (i = 1; i <= faces.Length(); i++) {
1267           TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
1268         }
1269
1270         // Collect multiconnected edges, i.e. edges that are internal to
1271         // the set of selected faces and have connections to other faces.
1272         TopTools_ListOfShape aMultEdges;
1273         for (i = 1; i <= aMapEF.Extent(); i++) {
1274           const TopTools_ListOfShape& aLF = aMapEF(i);
1275           if (aLF.Extent() == 2) {
1276             const TopoDS_Shape& aE = aMapEF.FindKey(i);
1277             const TopTools_ListOfShape& aGLF = aGMapEdgeFaces.FindFromKey(aE);
1278             if (aGLF.Extent() > 2) {
1279               aMultEdges.Append(aE);
1280             }
1281           }
1282         }
1283         if (!aMultEdges.IsEmpty()) {
1284           if (!myAllowInternal) {
1285             // Remove from the selection the faces containing multiconnected edges
1286             TopTools_MapOfShape anAvoidFaces;
1287             TopTools_ListIteratorOfListOfShape it(aMultEdges);
1288             for (; it.More(); it.Next()) {
1289               const TopoDS_Shape& aE = it.Value();
1290               const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
1291               anAvoidFaces.Add(aLF.First());
1292               anAvoidFaces.Add(aLF.Last());
1293             }
1294             for (i = 1; i <= faces.Length(); ) {
1295               if (anAvoidFaces.Contains(faces(i))) {
1296                 // update the boundaries of merged area, for that
1297                 // remove from 'edges' the edges of this face and add to 'edges' 
1298                 // the edges of this face that were not present in 'edges' before
1299                 TopExp_Explorer ex(faces(i), TopAbs_EDGE);
1300                 for (; ex.More(); ex.Next()) {
1301                   TopoDS_Shape aE = ex.Current();
1302                   Standard_Integer j;
1303                   for (j = 1; j <= edges.Length(); j++) {
1304                     if (edges(j).IsSame(aE))
1305                       break;
1306                   }
1307                   if (j <= edges.Length())
1308                     edges.Remove(j);
1309                   else
1310                     edges.Append(aE);
1311                 }
1312                 faces.Remove(i);
1313               }
1314               else
1315                 i++;
1316             }
1317           }
1318           else {
1319             // add multiconnected edges as internal in new face
1320             TopTools_ListIteratorOfListOfShape it(aMultEdges);
1321             for (; it.More(); it.Next()) {
1322               const TopoDS_Shape& aE = it.Value();
1323               edges.Append(aE.Oriented(TopAbs_INTERNAL));
1324             }
1325           }
1326         }
1327       }
1328
1329       // all faces collected in the sequence. Perform union of faces
1330       if (faces.Length() > 1) {
1331         NbModif++;
1332         TopoDS_Face aResult;
1333         BRep_Builder B;
1334         B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
1335         Standard_Integer nbWires = 0;
1336
1337         TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
1338         // connecting wires
1339         while (edges.Length()>0) {
1340
1341           Standard_Boolean isEdge3d = Standard_False;
1342           nbWires++;
1343           TopTools_MapOfShape aVertices;
1344           TopoDS_Wire aWire;
1345           B.MakeWire(aWire);
1346
1347           TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
1348           edges.Remove(1);
1349           // collect internal edges in separate wires
1350           Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
1351
1352           isEdge3d |= !BRep_Tool::Degenerated(anEdge);
1353           B.Add(aWire,anEdge);
1354           TopoDS_Vertex V1,V2;
1355           TopExp::Vertices(anEdge,V1,V2);
1356           aVertices.Add(V1);
1357           aVertices.Add(V2);
1358
1359           Standard_Boolean isNewFound = Standard_False;
1360           do {
1361             isNewFound = Standard_False;
1362             for(Standard_Integer j = 1; j <= edges.Length(); j++) {
1363               anEdge = TopoDS::Edge(edges(j));
1364               // check if the current edge orientation corresponds to the first one
1365               Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
1366               if (isCurrInternal != isInternal)
1367                 continue;
1368               TopExp::Vertices(anEdge,V1,V2);
1369               if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
1370                 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
1371                 aVertices.Add(V1);
1372                 aVertices.Add(V2);
1373                 B.Add(aWire,anEdge);
1374                 edges.Remove(j);
1375                 j--;
1376                 isNewFound = Standard_True;
1377               }
1378             }
1379           } while (isNewFound);
1380
1381           // sorting any type of edges
1382           aWire.Closed (BRep_Tool::IsClosed (aWire));
1383           aWire = TopoDS::Wire(myContext->Apply(aWire));
1384
1385           Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
1386           sfw->FixReorder();
1387           Standard_Boolean isDegRemoved = Standard_False;
1388           if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
1389             // clear degenerated edges if at least one with 3d curve exist
1390             if(isEdge3d) {
1391               Handle(ShapeExtend_WireData) sewd = sfw->WireData();
1392               for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
1393                 TopoDS_Edge E = sewd->Edge(j);
1394                 if(BRep_Tool::Degenerated(E)) {
1395                   sewd->Remove(j);
1396                   isDegRemoved = Standard_True;
1397                   j--;
1398                 }
1399               }
1400             }
1401             sfw->FixShifted();
1402             if(isDegRemoved)
1403               sfw->FixDegenerated();
1404           }
1405           TopoDS_Wire aWireFixed = sfw->Wire();
1406           //aContext->Replace(aWire,aWireFixed);
1407           myContext->Replace(aWire,aWireFixed);
1408           //for history
1409           /*
1410           if (!myOldNewMap.IsBound(aWire))
1411           {
1412             TopTools_ListOfShape EmptyList;
1413             myOldNewMap.Bind(aWire, EmptyList);
1414           }
1415           myOldNewMap(aWire).Clear();
1416           myOldNewMap(aWire).Append(aWireFixed);
1417           */
1418           /////////////
1419           
1420           // add resulting wire
1421           if(isEdge3d) {
1422             B.Add(aResult,aWireFixed);
1423           }
1424           else  {
1425             // sorting edges
1426             Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
1427             Standard_Integer nbEdges = sbwd->NbEdges();
1428             // sort degenerated edges and create one edge instead of several ones
1429             ShapeAnalysis_WireOrder sawo(Standard_False, 0);
1430             ShapeAnalysis_Edge sae;
1431             Standard_Integer aLastEdge = nbEdges;
1432             for(Standard_Integer j = 1; j <= nbEdges; j++) {
1433               Standard_Real f,l;
1434               //smh protection on NULL pcurve
1435               Handle(Geom2d_Curve) c2d;
1436               if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
1437                 aLastEdge--;
1438                 continue;
1439               }
1440               sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
1441             }
1442             sawo.Perform();
1443
1444             // constructind one degenerative edge
1445             gp_XY aStart, anEnd, tmp;
1446             Standard_Integer nbFirst = sawo.Ordered(1);
1447             TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
1448             ShapeBuild_Edge sbe;
1449             TopoDS_Vertex aDummyV;
1450             TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
1451             sawo.XY(nbFirst,aStart,tmp);
1452             sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
1453
1454             gp_XY aVec = anEnd-aStart;
1455             Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
1456
1457             B.UpdateEdge(E,aLine,tmpF,0.);
1458             B.Range(E,tmpF,0.,aVec.Modulus());
1459             Handle(Geom_Curve) C3d;
1460             B.UpdateEdge(E,C3d,0.);
1461             B.Degenerated(E,Standard_True);
1462             TopoDS_Wire aW;
1463             B.MakeWire(aW);
1464             B.Add(aW,E);
1465             aW.Closed (Standard_True);
1466             B.Add(aResult,aW);
1467           }
1468         }
1469
1470         // perform substitution of face
1471         //aContext->Replace(aContext->Apply(aFace),aResult);
1472         myContext->Replace(myContext->Apply(aFace),aResult);
1473         //for history
1474         /*
1475         if (!myOldNewMap.IsBound(aFace))
1476         {
1477           TopTools_ListOfShape EmptyList;
1478           myOldNewMap.Bind(aFace, EmptyList);
1479         }
1480         myOldNewMap(aFace).Clear();
1481         myOldNewMap(aFace).Append(aResult);
1482         */
1483         /////////////
1484
1485         ShapeFix_Face sff (aResult);
1486         //Intializing by tolerances
1487         sff.SetPrecision(Precision::Confusion());
1488         sff.SetMinTolerance(tol);
1489         sff.SetMaxTolerance(1.);
1490         //Setting modes
1491         sff.FixOrientationMode() = 0;
1492         //sff.FixWireMode() = 0;
1493         //sff.SetContext(aContext);
1494         sff.SetContext(myContext);
1495         // Applying the fixes
1496         sff.Perform();
1497         if(sff.Status(ShapeExtend_FAIL))
1498         hasFailed = Standard_True;
1499
1500         // breaking down to several faces
1501         //TopoDS_Shape theResult = aContext->Apply(aResult);
1502         TopoDS_Shape theResult = myContext->Apply(aResult);
1503         for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
1504           TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
1505           Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
1506           grid->SetValue ( 1, 1, aBaseSurface );
1507           Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
1508           ShapeFix_ComposeShell CompShell;
1509           CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
1510           //CompShell.SetContext( aContext );
1511           CompShell.SetContext( myContext );
1512
1513           TopTools_SequenceOfShape parts, anIntWires;
1514           ShapeFix_SequenceOfWireSegment wires;
1515           for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
1516             const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current());
1517             // check if the wire is ordinary (contains non-internal edges)
1518             Standard_Boolean isInternal = Standard_True;
1519             for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next())
1520               isInternal = (it.Value().Orientation() == TopAbs_INTERNAL);
1521             if (isInternal)
1522             {
1523               // place internal wire separately
1524               anIntWires.Append(aWire);
1525             }
1526             else
1527             {
1528             Handle(ShapeExtend_WireData) sbwd =
1529                 new ShapeExtend_WireData (aWire);
1530             ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
1531             wires.Append(seg);
1532           }
1533           }
1534
1535           CompShell.DispatchWires ( parts,wires );
1536           for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
1537             ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
1538             //aFixOrient.SetContext(aContext);
1539             aFixOrient.SetContext(myContext);
1540             aFixOrient.FixOrientation();
1541             // put internal wires to faces
1542             putIntWires(parts(j), anIntWires);
1543           }
1544
1545           TopoDS_Shape CompRes;
1546           if ( parts.Length() !=1 ) {
1547             TopoDS_Shell S;
1548             B.MakeShell ( S );
1549             for ( i=1; i <= parts.Length(); i++ )
1550               B.Add ( S, parts(i) );
1551             S.Closed (BRep_Tool::IsClosed (S));
1552             CompRes = S;
1553           }
1554           else CompRes = parts(1);
1555
1556           //aContext->Replace(aCurrent,CompRes);
1557           myContext->Replace(aCurrent,CompRes);
1558           //for history
1559           /*
1560           if (!myOldNewMap.IsBound(aCurrent))
1561           {
1562             TopTools_ListOfShape EmptyList;
1563             myOldNewMap.Bind(aCurrent, EmptyList);
1564           }
1565           myOldNewMap(aCurrent).Clear();
1566           myOldNewMap(aCurrent).Append(CompRes);
1567           */
1568           /////////////
1569         }
1570
1571         // remove the remaining faces
1572         for(i = 2; i <= faces.Length(); i++)
1573         { 
1574           myOldShapes.Bind(faces(i), theResult);
1575           myContext->Remove(faces(i));
1576         }
1577       }
1578     } // end processing each face
1579
1580     //TopoDS_Shape aResult = Shape;
1581     if (NbModif > 0 && !hasFailed) {
1582       //TopoDS_Shape aResult = aContext->Apply(aShell);
1583       TopoDS_Shape aResult = myContext->Apply(aShell);
1584
1585       ShapeFix_Edge sfe;
1586       if (!myContext.IsNull()) sfe.SetContext(myContext);
1587       for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
1588         TopoDS_Edge E = TopoDS::Edge(exp.Current());
1589         sfe.FixVertexTolerance (E);
1590         // ptv add fix same parameter
1591         sfe.FixSameParameter(E, Precision::Confusion());
1592       }
1593
1594       myContext->Replace(aShell, aResult);
1595       //for history
1596       /*
1597       if (!myOldNewMap.IsBound(aShell))
1598       {
1599         TopTools_ListOfShape EmptyList;
1600         myOldNewMap.Bind(aShell, EmptyList);
1601       }
1602       myOldNewMap(aShell).Clear();
1603       myOldNewMap(aShell).Append(aResult);
1604       */
1605       /////////////
1606     }
1607     //else
1608     {
1609       for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
1610         TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
1611         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
1612         sfw->SetContext(myContext);
1613         sfw->SetPrecision(Precision::Confusion());
1614         sfw->SetMinTolerance(Precision::Confusion());
1615         sfw->SetMaxTolerance(1.);
1616         sfw->SetFace(aFace);
1617         for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
1618           TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1619           sfw->Load(wire);
1620           sfw->FixReorder();
1621           sfw->FixShifted();
1622         }
1623       }
1624     }
1625   } // end processing each shell
1626
1627   myShape = myContext->Apply(myShape);
1628 }
1629
1630 //=======================================================================
1631 //function : UnifyEdges
1632 //purpose  : 
1633 //=======================================================================
1634 void ShapeUpgrade_UnifySameDomain::UnifyEdges()
1635 {
1636   Standard_Real Tol = Precision::Confusion();
1637   
1638   //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
1639   Standard_Real myTolerance = Precision::Confusion();
1640   TopoDS_Shape aResult = myContext->Apply(myShape);
1641
1642   TopTools_IndexedMapOfShape ChangedFaces;
1643
1644   // creating map of edge faces
1645   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
1646   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
1647   
1648   // creating map of vertex edges
1649   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgesVertex;
1650   TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMapEdgesVertex);
1651
1652   //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
1653   TopoDS_Shape aRes = myShape;
1654   //aRes = aContext->Apply(aSolid);
1655   aRes = myContext->Apply(myShape);
1656   
1657   TopTools_MapOfShape SharedVert;
1658
1659   
1660   TopTools_IndexedMapOfShape anOldEdges;
1661   TopExp::MapShapes(myInitShape, TopAbs_EDGE, anOldEdges);
1662
1663   TopTools_DataMapOfShapeShape NewEdges2OldEdges;
1664   for (int i = 1; i <= anOldEdges.Extent(); i++)
1665   {
1666     TopoDS_Shape NewEdge = myContext->Apply(anOldEdges(i));
1667     if (!NewEdge.IsNull())
1668       NewEdges2OldEdges.Bind(NewEdge, anOldEdges(i));
1669   }
1670
1671   TopExp_Explorer exp;
1672   // processing separate wires
1673   for (exp.Init(aRes, TopAbs_WIRE, TopAbs_FACE); exp.More(); exp.Next()) 
1674   {
1675     TopTools_SequenceOfShape SeqEdges;
1676     TopExp_Explorer expE(exp.Current(), TopAbs_EDGE);
1677     for (; expE.More(); expE.Next())
1678       SeqEdges.Append(expE.Current());
1679     SharedVert.Clear();
1680     CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert); 
1681     MergeSeq(SeqEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges);
1682   }
1683
1684   TopTools_DataMapOfShapeShape oldFaces2NewFaces;
1685   for (exp.Init(myShape, TopAbs_FACE); exp.More(); exp.Next()) 
1686   {
1687     const TopoDS_Face& f = TopoDS::Face(exp.Current());
1688     TopoDS_Face NewF = TopoDS::Face(myContext->Apply(f));
1689     if (!NewF.IsNull())
1690       oldFaces2NewFaces.Bind(f, NewF);
1691   }
1692
1693   // processing each face
1694   for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
1695     //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1696     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1697     TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
1698     TopTools_SequenceOfShape aNonSharedEdges;
1699     for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
1700       TopoDS_Edge edge = TopoDS::Edge(expe.Current());
1701       if (!aMapEdgeFaces.Contains(edge)) continue;
1702       const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
1703       TopTools_ListIteratorOfListOfShape anIter(aList);
1704       Standard_Integer NbFacesPerEdge = aList.Extent();
1705       for ( ; anIter.More(); anIter.Next()) {
1706         TopoDS_Face face = TopoDS::Face(anIter.Value());
1707         TopoDS_Face face1 = TopoDS::Face(oldFaces2NewFaces(anIter.Value()));
1708         if (face1.IsSame(aFace) && NbFacesPerEdge != 1)
1709           continue;
1710         if (NbFacesPerEdge == 1)
1711           //store non-shared edges separately 
1712           aNonSharedEdges.Append(edge);
1713         else 
1714         {
1715           if (aMapFacesEdges.Contains(face))
1716             aMapFacesEdges.ChangeFromKey(face).Append(edge);
1717           else 
1718           {
1719             TopTools_ListOfShape ListEdges;
1720             ListEdges.Append(edge);
1721             aMapFacesEdges.Add(face,ListEdges);
1722           }
1723         }
1724       }
1725     }
1726       
1727     for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++)
1728     {
1729       const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
1730       TopTools_SequenceOfShape SeqEdges;
1731       TopTools_ListIteratorOfListOfShape anIter(ListEdges);
1732       for ( ; anIter.More(); anIter.Next())
1733         SeqEdges.Append(anIter.Value());
1734       if (SeqEdges.Length()==1) 
1735         continue;  
1736
1737       SharedVert.Clear();
1738       CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert);
1739       //if (!SharedVert.IsEmpty()) 
1740       //  continue;
1741       if ( MergeSeq(SeqEdges,Tol,myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) )
1742       {
1743         //for history
1744         /*
1745         for (j = 1; j <= SeqEdges.Length(); j++)
1746         {
1747           if (!myOldNewMap.IsBound(SeqEdges(j)))
1748           {
1749             TopTools_ListOfShape EmptyList;
1750             myOldNewMap.Bind(SeqEdges(j), EmptyList);
1751           }
1752           myOldNewMap(SeqEdges(j)).Clear();
1753           myOldNewMap(SeqEdges(j)).Append(E);
1754         }
1755         */
1756         /////////////
1757         
1758         TopoDS_Face tmpF = TopoDS::Face(exp.Current());
1759         if ( !ChangedFaces.Contains(tmpF) )
1760           ChangedFaces.Add(tmpF);
1761         tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
1762         if ( !ChangedFaces.Contains(tmpF) )
1763           ChangedFaces.Add(tmpF);
1764       }
1765     }
1766     
1767     if ( aNonSharedEdges.Length() > 1 )
1768     {
1769       SharedVert.Clear();
1770       CheckSharedVertices(aNonSharedEdges, aMapEdgesVertex, SharedVert); 
1771       if ( MergeSeq(aNonSharedEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) )
1772       {
1773         TopoDS_Face tmpF = TopoDS::Face(exp.Current());
1774         if ( !ChangedFaces.Contains(tmpF) )
1775           ChangedFaces.Add(tmpF);
1776       }
1777     }
1778
1779   } // end processing each face
1780
1781   // fix changed faces and replace them in the local context
1782   for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
1783     //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
1784     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(ChangedFaces.FindKey(i)));
1785     if (aFace.IsNull())
1786       continue;
1787     Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
1788     sff->SetContext(myContext);
1789     sff->SetPrecision(myTolerance);
1790     sff->SetMinTolerance(myTolerance);
1791     sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
1792     sff->Perform();
1793     TopoDS_Shape aNewFace = sff->Face();
1794     //aContext->Replace(aFace,aNewFace);
1795     myContext->Replace(aFace,aNewFace);
1796     //for history
1797     /*
1798     if (!myOldNewMap.IsBound(aFace))
1799     {
1800       TopTools_ListOfShape EmptyList;
1801       myOldNewMap.Bind(aFace, EmptyList);
1802     }
1803     myOldNewMap(aFace).Clear();
1804     myOldNewMap(aFace).Append(aNewFace);
1805     */
1806     /////////////
1807   }
1808
1809   if (ChangedFaces.Extent() > 0) {
1810     // fix changed shell and replace it in the local context
1811     //TopoDS_Shape aRes1 = aContext->Apply(aRes);
1812     TopoDS_Shape aRes1 = myContext->Apply(aRes);
1813     TopExp_Explorer expsh;
1814     for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
1815       TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
1816       Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
1817       sfsh->FixFaceOrientation(aShell);
1818       TopoDS_Shape aNewShell = sfsh->Shell();
1819       //aContext->Replace(aShell,aNewShell);
1820       myContext->Replace(aShell,aNewShell);
1821       //for history
1822       /*
1823       if (!myOldNewMap.IsBound(aShell))
1824       {
1825         TopTools_ListOfShape EmptyList;
1826         myOldNewMap.Bind(aShell, EmptyList);
1827       }
1828       myOldNewMap(aShell).Clear();
1829       myOldNewMap(aShell).Append(aNewShell);
1830       */
1831       /////////////
1832     }
1833     //TopoDS_Shape aRes2 = aContext->Apply(aRes1);
1834     TopoDS_Shape aRes2 = myContext->Apply(aRes1);
1835     myContext->Replace(myShape,aRes2);
1836     //for history
1837     /*
1838     if (!myOldNewMap.IsBound(aSolid))
1839     {
1840       TopTools_ListOfShape EmptyList;
1841       myOldNewMap.Bind(aSolid, EmptyList);
1842     }
1843     myOldNewMap(aSolid).Clear();
1844     myOldNewMap(aSolid).Append(aRes2);
1845     */
1846     /////////////
1847   }
1848
1849   myShape = myContext->Apply(myShape);
1850 }
1851
1852 //=======================================================================
1853 //function : UnifyFacesAndEdges
1854 //purpose  : 
1855 //=======================================================================
1856
1857 void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
1858 {
1859   UnifyFaces();
1860   
1861   /*
1862   ShapeUpgrade_RemoveLocations RemLoc;
1863   RemLoc.Remove(myShape);
1864   myShape = RemLoc.GetResult();
1865   */
1866
1867   UnifyEdges();
1868 }
1869
1870 //=======================================================================
1871 //function : Build
1872 //purpose  : builds the resulting shape
1873 //======================================================================
1874 void ShapeUpgrade_UnifySameDomain::Build() 
1875 {
1876   if (myUnifyFaces && myUnifyEdges)
1877     UnifyFacesAndEdges();
1878
1879   else if (myUnifyEdges)
1880     UnifyEdges();
1881   else if (myUnifyFaces)
1882     UnifyFaces();
1883
1884   //Done();
1885 }
1886
1887 //=======================================================================
1888 //function : Shape
1889 //purpose  : give the resulting shape
1890 //=======================================================================
1891 const TopoDS_Shape& ShapeUpgrade_UnifySameDomain::Shape() const
1892 {
1893   return myShape;
1894 }
1895
1896 //=======================================================================
1897 //function : Generated
1898 //purpose  : returns the new shape from the old one
1899 //=======================================================================
1900 TopoDS_Shape ShapeUpgrade_UnifySameDomain::Generated(const TopoDS_Shape& aShape) const
1901 {
1902   TopoDS_Shape aNewShape = myContext->Apply(aShape);
1903
1904   if (aNewShape.IsNull())
1905     aNewShape = myContext->Apply(myOldShapes(aShape));
1906   
1907   return aNewShape;
1908 }