0025266: Debug statements in the source are getting flushed on to the console
[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 #include <ShapeUpgrade_UnifySameDomain.ixx>
17 #include <ShapeUpgrade_UnifySameDomain.hxx>
18 #include <TopTools_SequenceOfShape.hxx>
19 #include <TopTools_IndexedMapOfShape.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <Geom_Surface.hxx>
22 #include <Geom_Line.hxx>
23 #include <gp_Dir.hxx>
24 #include <Geom_CylindricalSurface.hxx>
25 #include <gp_Cylinder.hxx>
26 #include <Geom_SurfaceOfRevolution.hxx>
27 #include <Geom_SurfaceOfLinearExtrusion.hxx>
28 #include <gp_Lin.hxx>
29 #include <Geom_Circle.hxx>
30 #include <Geom_RectangularTrimmedSurface.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <BRep_Tool.hxx>
33 #include <GeomAdaptor_HSurface.hxx>
34 #include <BRepTopAdaptor_TopolTool.hxx>
35 #include <IntPatch_ImpImpIntersection.hxx>
36 #include <GeomLib_IsPlanarSurface.hxx>
37 #include <BRep_Builder.hxx>
38 #include <ShapeFix_Wire.hxx>
39 #include <TopoDS.hxx>
40 #include <ShapeAnalysis_Edge.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TColGeom_SequenceOfSurface.hxx>
43 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
44 #include <BRep_TEdge.hxx>
45 #include <BRep_CurveRepresentation.hxx>
46 #include <TColGeom_Array1OfBSplineCurve.hxx>
47 #include <TColGeom_HArray1OfBSplineCurve.hxx>
48 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
49 #include <TColGeom2d_HArray1OfBSplineCurve.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TopExp.hxx>
52 #include <Geom_TrimmedCurve.hxx>
53 #include <Geom2d_TrimmedCurve.hxx>
54 #include <GeomConvert.hxx>
55 #include <Geom2dConvert.hxx>
56 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
57 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
58 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
59 #include <BRepLib_MakeEdge.hxx>
60 #include <TColStd_MapOfInteger.hxx>
61 #include <BRepLib.hxx>
62 #include <GC_MakeCircle.hxx>
63 #include <Geom_BezierCurve.hxx>
64 #include <ShapeBuild_ReShape.hxx>
65 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
66 #include <TopTools_MapOfShape.hxx>
67 #include <TopTools_ListIteratorOfListOfShape.hxx>
68 #include <ShapeAnalysis_WireOrder.hxx>
69 #include <ShapeBuild_Edge.hxx>
70 #include <Geom2d_Line.hxx>
71 #include <ShapeFix_Face.hxx>
72 #include <TColGeom_HArray2OfSurface.hxx>
73 #include <ShapeExtend_CompositeSurface.hxx>
74 #include <ShapeFix_ComposeShell.hxx>
75 #include <ShapeFix_SequenceOfWireSegment.hxx>
76 #include <ShapeFix_WireSegment.hxx>
77 #include <ShapeFix_Edge.hxx>
78 #include <ShapeFix_Shell.hxx>
79 #include <ShapeUpgrade_RemoveLocations.hxx>
80
81
82 //=======================================================================
83 //function : AddOrdinaryEdges
84 //purpose  : auxilary
85 //=======================================================================
86 // adds edges from the shape to the sequence
87 // seams and equal edges are dropped
88 // Returns true if one of original edges dropped
89 static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
90                                          const TopoDS_Shape aShape,
91                                          Standard_Integer& anIndex)
92 {
93   //map of edges
94   TopTools_IndexedMapOfShape aNewEdges;
95   //add edges without seams
96   for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
97     TopoDS_Shape edge = exp.Current();
98     if(aNewEdges.Contains(edge))
99     {
100       //aNewEdges.Remove(edge);
101       TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
102       aNewEdges.RemoveLast();
103       if (aNewEdges.FindIndex(edge) != 0)
104         aNewEdges.Substitute(aNewEdges.FindIndex(edge), LastEdge);
105       /////////////////////////
106     }
107     else
108       aNewEdges.Add(edge);
109   }
110
111   Standard_Boolean isDropped = Standard_False;
112   //merge edges and drop seams
113   Standard_Integer i;
114   for (i = 1; i <= edges.Length(); i++) {
115     TopoDS_Shape current = edges(i);
116     if(aNewEdges.Contains(current)) {
117
118       //aNewEdges.Remove(current);
119       TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
120       aNewEdges.RemoveLast();
121       if (aNewEdges.FindIndex(current) != 0)
122         aNewEdges.Substitute(aNewEdges.FindIndex(current), LastEdge);
123       /////////////////////////
124       edges.Remove(i);
125       i--;
126
127       if(!isDropped) {
128         isDropped = Standard_True;
129         anIndex = i;
130       }
131     }
132   }
133
134   //add edges to the sequemce
135   for (i = 1; i <= aNewEdges.Extent(); i++)
136     edges.Append(aNewEdges(i));
137
138   return isDropped;
139 }
140
141 //=======================================================================
142 //function : getCylinder
143 //purpose  : auxilary
144 //=======================================================================
145 static Standard_Boolean getCylinder(Handle(Geom_Surface)& theInSurface,
146                                     gp_Cylinder& theOutCylinder)
147 {
148   Standard_Boolean isCylinder = Standard_False;
149
150   if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
151     Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface);
152
153     theOutCylinder = aGC->Cylinder();
154     isCylinder = Standard_True;
155   }
156   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
157     Handle(Geom_SurfaceOfRevolution) aRS =
158       Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface);
159     Handle(Geom_Curve) aBasis = aRS->BasisCurve();
160     if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) {
161       Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis);
162       gp_Dir aDir = aRS->Direction();
163       gp_Dir aBasisDir = aBasisLine->Position().Direction();
164       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
165         // basis line is parallel to the revolution axis: it is a cylinder
166         gp_Pnt aLoc = aRS->Location();
167         Standard_Real aR = aBasisLine->Lin().Distance(aLoc);
168         gp_Ax3 aCylAx (aLoc, aDir);
169
170         theOutCylinder = gp_Cylinder(aCylAx, aR);
171         isCylinder = Standard_True;
172       }
173     }
174   }
175   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
176     Handle(Geom_SurfaceOfLinearExtrusion) aLES =
177       Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface);
178     Handle(Geom_Curve) aBasis = aLES->BasisCurve();
179     if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) {
180       Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis);
181       gp_Dir aDir = aLES->Direction();
182       gp_Dir aBasisDir = aBasisCircle->Position().Direction();
183       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
184         // basis circle is normal to the extrusion axis: it is a cylinder
185         gp_Pnt aLoc = aBasisCircle->Location();
186         Standard_Real aR = aBasisCircle->Radius();
187         gp_Ax3 aCylAx (aLoc, aDir);
188
189         theOutCylinder = gp_Cylinder(aCylAx, aR);
190         isCylinder = Standard_True;
191       }
192     }
193   }
194   else {
195   }
196
197   return isCylinder;
198 }
199
200 //=======================================================================
201 //function : ClearRts
202 //purpose  : auxilary
203 //=======================================================================
204 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
205 {
206   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
207     Handle(Geom_RectangularTrimmedSurface) rts =
208       Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
209     return rts->BasisSurface();
210   }
211   return aSurface;
212 }
213
214 //=======================================================================
215 //function : IsSameDomain
216 //purpose  : 
217 //=======================================================================
218 static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
219                                      const TopoDS_Face& aCheckedFace)
220 {
221   //checking the same handles
222   TopLoc_Location L1, L2;
223   Handle(Geom_Surface) S1, S2;
224
225   S1 = BRep_Tool::Surface(aFace,L1);
226   S2 = BRep_Tool::Surface(aCheckedFace,L2);
227
228   if (S1 == S2 && L1 == L2)
229     return Standard_True;
230
231   // planar and cylindrical cases (IMP 20052)
232   Standard_Real aPrec = Precision::Confusion();
233
234   S1 = BRep_Tool::Surface(aFace);
235   S2 = BRep_Tool::Surface(aCheckedFace);
236
237   S1 = ClearRts(S1);
238   S2 = ClearRts(S2);
239
240   //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
241   //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
242   //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
243   //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
244   //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
245
246   // case of two elementary surfaces: use OCCT tool
247   // elementary surfaces: ConicalSurface, CylindricalSurface,
248   //                      Plane, SphericalSurface and ToroidalSurface
249   if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
250       S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
251   {
252     Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1);
253     Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2);
254
255     Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
256     Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
257
258     try {
259       IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
260       if (!anIIInt.IsDone() || anIIInt.IsEmpty())
261         return Standard_False;
262
263       return anIIInt.TangentFaces();
264     }
265     catch (Standard_Failure) {
266       return Standard_False;
267     }
268   }
269
270   // case of two planar surfaces:
271   // all kinds of surfaces checked, including b-spline and bezier
272   GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
273   if (aPlanarityChecker1.IsPlanar()) {
274     GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
275     if (aPlanarityChecker2.IsPlanar()) {
276       gp_Pln aPln1 = aPlanarityChecker1.Plan();
277       gp_Pln aPln2 = aPlanarityChecker2.Plan();
278
279       if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(),Precision::Angular()) &&
280           aPln1.Distance(aPln2) < aPrec) {
281         return Standard_True;
282       }
283     }
284   }
285
286   // case of two cylindrical surfaces, at least one of which is a swept surface
287   // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
288   if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
289        S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
290       (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
291        S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
292   {
293     gp_Cylinder aCyl1, aCyl2;
294     if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
295       if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
296         gp_Dir aDir1 = aCyl1.Position().Direction();
297         gp_Dir aDir2 = aCyl2.Position().Direction();
298         if (aDir1.IsParallel(aDir2, Precision::Angular())) {
299           gp_Pnt aLoc1 = aCyl1.Location();
300           gp_Pnt aLoc2 = aCyl2.Location();
301           gp_Vec aVec12 (aLoc1, aLoc2);
302           if (aVec12.SquareMagnitude() < aPrec*aPrec ||
303               aVec12.IsParallel(aDir1, Precision::Angular())) {
304             return Standard_True;
305           }
306         }
307       }
308     }
309   }
310
311   return Standard_False;
312 }
313
314 //=======================================================================
315 //function : MovePCurves
316 //purpose  :
317 //=======================================================================
318 static void MovePCurves(TopoDS_Face& aTarget,
319                         const TopoDS_Face& aSource)
320 {
321   BRep_Builder B;
322   for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
323     Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
324                                                   aTarget, Precision::Confusion());
325     sfw->FixReorder();
326     Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
327     sfw->FixEdgeCurves();
328     if(isReoredFailed)
329       continue;
330
331     sfw->FixShifted();
332     sfw->FixDegenerated();
333
334     // remove degenerated edges from not degenerated points
335     ShapeAnalysis_Edge sae;
336     Handle(ShapeExtend_WireData) sewd = sfw->WireData();
337     for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
338       TopoDS_Edge E = sewd->Edge(i);
339       if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
340         sewd->Remove(i);
341         i--;
342       }
343     }
344
345     TopoDS_Wire ResWire = sfw->Wire();
346     B.Add(aTarget,ResWire);
347   }
348 }
349
350 //=======================================================================
351 //function : GlueEdgesWithPCurves
352 //purpose  : Glues the pcurves of the sequence of edges
353 //           and glues their 3d curves
354 //=======================================================================
355 static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
356                                         const TopoDS_Vertex& FirstVertex,
357                                         const TopoDS_Vertex& LastVertex)
358 {
359   Standard_Integer i, j;
360
361   TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
362   //TColGeom2d_SequenceOfCurve PCurveSeq;
363   TColGeom_SequenceOfSurface SurfSeq;
364   //TopTools_SequenceOfShape LocSeq;
365   
366   BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() );
367   for (; itr.More(); itr.Next())
368   {
369     Handle(BRep_CurveRepresentation) CurveRep = itr.Value();
370     if (CurveRep->IsCurveOnSurface())
371     {
372       //PCurveSeq.Append(CurveRep->PCurve());
373       SurfSeq.Append(CurveRep->Surface());
374       /*
375       TopoDS_Shape aLocShape;
376       aLocShape.Location(CurveRep->Location());
377       LocSeq.Append(aLocShape);
378       */
379     }
380   }
381
382   Standard_Real fpar, lpar;
383   BRep_Tool::Range(FirstEdge, fpar, lpar);
384   TopoDS_Edge PrevEdge = FirstEdge;
385   TopoDS_Vertex CV;
386   Standard_Real MaxTol = 0.;
387   
388   TopoDS_Edge ResEdge;
389   BRep_Builder BB;
390
391   Standard_Integer nb_curve = aChain.Length();   //number of curves
392   TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1);                    //array of the curves
393   TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
394     
395   TopoDS_Vertex PrevVertex = FirstVertex;
396   for (i = 1; i <= nb_curve; i++)
397   {
398     TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
399     TopoDS_Vertex VF, VL;
400     TopExp::Vertices(anEdge, VF, VL);
401     Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
402     
403     Standard_Real Tol1 = BRep_Tool::Tolerance(VF);
404     Standard_Real Tol2 = BRep_Tool::Tolerance(VL);
405     if (Tol1 > MaxTol)
406       MaxTol = Tol1;
407     if (Tol2 > MaxTol)
408       MaxTol = Tol2;
409     
410     if (i > 1)
411     {
412       TopExp::CommonVertex(PrevEdge, anEdge, CV);
413       Standard_Real Tol = BRep_Tool::Tolerance(CV);
414       tabtolvertex(i-2) = Tol;
415     }
416     
417     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
418     Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar);
419     tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
420     GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion());
421     if (ToReverse)
422       tab_c3d(i-1)->Reverse();
423     PrevVertex = (ToReverse)? VF : VL;
424     PrevEdge = anEdge;
425   }
426   Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
427   Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
428   GeomConvert::ConcatC1(tab_c3d,
429                         tabtolvertex,
430                         ArrayOfIndices,
431                         concatcurve,
432                         Standard_False,
433                         Precision::Confusion());   //C1 concatenation
434   
435   if (concatcurve->Length() > 1)
436   {
437     GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
438     
439     for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
440       Concat.Add( concatcurve->Value(i), MaxTol, Standard_True );
441     
442     concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
443   }
444   Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower());
445   
446   TColGeom2d_SequenceOfBoundedCurve ResPCurves;
447   TopLoc_Location aLoc;
448   for (j = 1; j <= SurfSeq.Length(); j++)
449   {
450     TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves
451     
452     PrevVertex = FirstVertex;
453     PrevEdge = FirstEdge;
454     //TopLoc_Location theLoc = LocSeq(j).Location();
455     for (i = 1; i <= nb_curve; i++)
456     {
457       TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
458       TopoDS_Vertex VF, VL;
459       TopExp::Vertices(anEdge, VF, VL);
460       Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
461
462       /*
463       Handle(Geom2d_Curve) aPCurve =
464         BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar);
465       */
466       Handle(Geom2d_Curve) aPCurve =
467         BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar);
468       Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
469       tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve);
470       Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion());
471       if (ToReverse)
472         tab_c2d(i-1)->Reverse();
473       PrevVertex = (ToReverse)? VF : VL;
474       PrevEdge = anEdge;
475     }
476     Handle(TColGeom2d_HArray1OfBSplineCurve)  concatc2d;     //array of the concatenated curves
477     Handle(TColStd_HArray1OfInteger)        ArrayOfInd2d;  //array of the remining Vertex
478     Geom2dConvert::ConcatC1(tab_c2d,
479                             tabtolvertex,
480                             ArrayOfInd2d,
481                             concatc2d,
482                             Standard_False,
483                             Precision::Confusion());   //C1 concatenation
484     
485     if (concatc2d->Length() > 1)
486     {
487       Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower()));
488       
489       for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++)
490         Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True );
491       
492       concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve());
493     }
494     Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower());
495     ResPCurves.Append(aResPCurve);
496   }
497   
498   ResEdge = BRepLib_MakeEdge(ResCurve,
499                              FirstVertex, LastVertex,
500                              ResCurve->FirstParameter(), ResCurve->LastParameter());
501   BB.SameRange(ResEdge, Standard_False);
502   BB.SameParameter(ResEdge, Standard_False);
503   for (j = 1; j <= ResPCurves.Length(); j++)
504   {
505     BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol);
506     BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
507   }
508
509   BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
510   
511   return ResEdge;
512 }
513
514 //=======================================================================
515 //function : MergeEdges
516 //purpose  : auxilary
517 //=======================================================================
518 static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
519                                    const TopoDS_Face& /*aFace*/,
520                                    const Standard_Real Tol,
521                                    const Standard_Boolean ConcatBSplines,
522                                    TopoDS_Edge& anEdge)
523 {
524   // make chain for union
525   BRep_Builder B;
526   ShapeAnalysis_Edge sae;
527   TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1));
528   TopoDS_Edge LastE = FirstE;
529   TopoDS_Vertex VF = sae.FirstVertex(FirstE);
530   TopoDS_Vertex VL = sae.LastVertex(LastE);
531   TopTools_SequenceOfShape aChain;
532   aChain.Append(FirstE);
533   TColStd_MapOfInteger IndUsedEdges;
534   IndUsedEdges.Add(1);
535   Standard_Integer j;
536   for (j = 1; j <= SeqEdges.Length(); j++)
537   {
538     TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j));
539     if (BRep_Tool::Degenerated(anEdge))
540       return Standard_False;
541   }
542   
543   for(j=2; j<=SeqEdges.Length(); j++) {
544     for(Standard_Integer k=2; k<=SeqEdges.Length(); k++) {
545       if(IndUsedEdges.Contains(k)) continue;
546       TopoDS_Edge edge = TopoDS::Edge(SeqEdges.Value(k));
547       TopoDS_Vertex VF2 = sae.FirstVertex(edge);
548       TopoDS_Vertex VL2 = sae.LastVertex(edge);
549       if(sae.FirstVertex(edge).IsSame(VL)) {
550         aChain.Append(edge);
551         LastE = edge;
552         VL = sae.LastVertex(LastE);
553         IndUsedEdges.Add(k);
554       }
555       else if(sae.LastVertex(edge).IsSame(VF)) {
556         aChain.Prepend(edge);
557         FirstE = edge;
558         VF = sae.FirstVertex(FirstE);
559         IndUsedEdges.Add(k);
560       }
561     }
562   }
563   if(aChain.Length()<SeqEdges.Length()) {
564 #ifdef SHAPEUPGRADE_DEB
565     cout<<"can not create correct chain..."<<endl;
566 #endif
567     return Standard_False;
568   }
569   // union edges in chain
570   // first step: union lines and circles
571   TopLoc_Location Loc;
572   Standard_Real fp1,lp1,fp2,lp2;
573   for(j=1; j<aChain.Length(); j++) {
574     TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
575     Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1);
576     if(c3d1.IsNull()) break;
577     while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
578       Handle(Geom_TrimmedCurve) tc =
579         Handle(Geom_TrimmedCurve)::DownCast(c3d1);
580       c3d1 = tc->BasisCurve();
581     }
582     TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
583     Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,Loc,fp2,lp2);
584     if(c3d2.IsNull()) break;
585     while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
586       Handle(Geom_TrimmedCurve) tc =
587         Handle(Geom_TrimmedCurve)::DownCast(c3d2);
588       c3d2 = tc->BasisCurve();
589     }
590     if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
591       // union lines
592       Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
593       Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
594       gp_Dir Dir1 = L1->Position().Direction();
595       gp_Dir Dir2 = L2->Position().Direction();
596       //if(!Dir1.IsEqual(Dir2,Precision::Angular())) { 
597       //if(!Dir1.IsParallel(Dir2,Precision::Angular())) { 
598       if(!Dir1.IsParallel(Dir2,Tol)) { 
599         continue;
600       }
601       // can union lines => create new edge
602       TopoDS_Vertex V1 = sae.FirstVertex(edge1);
603       gp_Pnt PV1 = BRep_Tool::Pnt(V1);
604       TopoDS_Vertex V2 = sae.LastVertex(edge2);
605       gp_Pnt PV2 = BRep_Tool::Pnt(V2);
606       gp_Vec Vec(PV1,PV2);
607       Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
608       Standard_Real dist = PV1.Distance(PV2);
609       Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
610       TopoDS_Edge E;
611       B.MakeEdge (E,tc,Precision::Confusion());
612       B.Add (E,V1);  B.Add (E,V2);
613       B.UpdateVertex(V1, 0., E, 0.);
614       B.UpdateVertex(V2, dist, E, 0.);
615       //ShapeFix_Edge sfe;
616       //sfe.FixAddPCurve(E,aFace,Standard_False);
617       //sfe.FixSameParameter(E);
618       aChain.Remove(j);
619       aChain.SetValue(j,E);
620       j--;
621     }
622     if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
623       // union circles
624       Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
625       Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
626       gp_Pnt P01 = C1->Location();
627       gp_Pnt P02 = C2->Location();
628       if (P01.Distance(P02) > Precision::Confusion()) continue;
629       // can union circles => create new edge
630       TopoDS_Vertex V1 = sae.FirstVertex(edge1);
631       gp_Pnt PV1 = BRep_Tool::Pnt(V1);
632       TopoDS_Vertex V2 = sae.LastVertex(edge2);
633       gp_Pnt PV2 = BRep_Tool::Pnt(V2);
634       TopoDS_Vertex VM = sae.LastVertex(edge1);
635       gp_Pnt PVM = BRep_Tool::Pnt(VM);
636       GC_MakeCircle MC (PV1,PVM,PV2);
637       Handle(Geom_Circle) C = MC.Value();
638       TopoDS_Edge E;
639       if (!MC.IsDone() || C.IsNull()) {
640         // jfa for Mantis issue 0020228
641         if (PV1.Distance(PV2) > Precision::Confusion()) continue;
642         // closed chain
643         C = C1;
644         B.MakeEdge (E,C,Precision::Confusion());
645         B.Add(E,V1);
646         B.Add(E,V2);
647       }
648       else {
649         gp_Pnt P0 = C->Location();
650         gp_Dir D1(gp_Vec(P0,PV1));
651         gp_Dir D2(gp_Vec(P0,PV2));
652         Standard_Real fpar = C->XAxis().Direction().Angle(D1);
653         if(fabs(fpar)>Precision::Confusion()) {
654           // check orientation
655           gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
656           if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
657             fpar = -fpar;
658           }
659         }
660         Standard_Real lpar = C->XAxis().Direction().Angle(D2);
661         if(fabs(lpar)>Precision::Confusion()) {
662           // check orientation
663           gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
664           if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
665             lpar = -lpar;
666           }
667         }
668         if (lpar < fpar) lpar += 2*M_PI;
669         Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
670         B.MakeEdge (E,tc,Precision::Confusion());
671         B.Add(E,V1);
672         B.Add(E,V2);
673         B.UpdateVertex(V1, fpar, E, 0.);
674         B.UpdateVertex(V2, lpar, E, 0.);
675       }
676       aChain.Remove(j);
677       aChain.SetValue(j,E);
678       j--;
679     }
680   }
681   if (j < aChain.Length()) {
682 #ifdef SHAPEUPGRADE_DEB
683     cout<<"null curve3d in edge..."<<endl;
684 #endif
685     return Standard_False;
686   }
687   if (aChain.Length() > 1 && ConcatBSplines) {
688     // second step: union edges with various curves
689     // skl for bug 0020052 from Mantis: perform such unions
690     // only if curves are bspline or bezier
691     bool NeedUnion = true;
692     for(j=1; j<=aChain.Length(); j++) {
693       TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
694       Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
695       if(c3d.IsNull()) continue;
696       while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
697         Handle(Geom_TrimmedCurve) tc =
698           Handle(Geom_TrimmedCurve)::DownCast(c3d);
699         c3d = tc->BasisCurve();
700       }
701       if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
702             c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
703       NeedUnion = false;
704       break;
705     }
706     if(NeedUnion) {
707 #ifdef SHAPEUPGRADE_DEB
708       cout<<"can not make analitical union => make approximation"<<endl;
709 #endif
710       TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
711       aChain.SetValue(1,E);
712     }
713     else {
714 #ifdef SHAPEUPGRADE_DEB
715       cout<<"can not make approximation for such types of curves"<<endl;
716 #endif
717       return Standard_False;
718     }
719   }
720
721   anEdge = TopoDS::Edge(aChain.Value(1));
722   return Standard_True;
723 }
724
725 //=======================================================================
726 //function : ShapeUpgrade_UnifySameDomain
727 //purpose  : Constructor
728 //=======================================================================
729
730 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
731 {
732   myUnifyEdges = Standard_True;
733   myUnifyFaces = Standard_True;
734   myConcatBSplines = Standard_False;
735
736   myContext = new ShapeBuild_ReShape;
737 }
738
739 //=======================================================================
740 //function : ShapeUpgrade_UnifySameDomain
741 //purpose  : Constructor
742 //=======================================================================
743
744 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape,
745                                                            const Standard_Boolean UnifyEdges,
746                                                            const Standard_Boolean UnifyFaces,
747                                                            const Standard_Boolean ConcatBSplines)
748 {
749   myInitShape = aShape;
750   myShape = aShape;
751   myUnifyEdges = UnifyEdges;
752   myUnifyFaces = UnifyFaces;
753   myConcatBSplines = ConcatBSplines;
754
755   myContext = new ShapeBuild_ReShape;
756 }
757
758 //=======================================================================
759 //function : Initialize
760 //purpose  : 
761 //=======================================================================
762
763 void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
764                                               const Standard_Boolean UnifyEdges,
765                                               const Standard_Boolean UnifyFaces,
766                                               const Standard_Boolean ConcatBSplines)
767 {
768   myInitShape = aShape;
769   myShape = aShape;
770   myUnifyEdges = UnifyEdges;
771   myUnifyFaces = UnifyFaces;
772   myConcatBSplines = ConcatBSplines;
773
774   myContext->Clear();
775   //myOldNewMap.Clear();
776   //myGenerated.Clear();
777 }
778
779 //=======================================================================
780 //function : UnifyFaces
781 //purpose  : 
782 //=======================================================================
783
784 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
785 {
786   //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
787   TopoDS_Shape aResShape = myContext->Apply(myShape);
788
789   // processing each shell
790   TopExp_Explorer exps;
791   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
792     TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
793
794     // creating map of edge faces
795     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
796     TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
797
798     // map of processed shapes
799     TopTools_MapOfShape aProcessed;
800
801     //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
802
803     Standard_Integer NbModif = 0;
804     Standard_Boolean hasFailed = Standard_False;
805     Standard_Real tol = Precision::Confusion();
806
807     // count faces
808     Standard_Integer nbf = 0;
809     TopExp_Explorer exp;
810     TopTools_MapOfShape mapF;
811     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
812       if (mapF.Add(exp.Current()))
813         nbf++;
814     }
815
816     // processing each face
817     mapF.Clear();
818     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
819       TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
820
821       if (aProcessed.Contains(aFace))
822         continue;
823
824       Standard_Integer dummy;
825       TopTools_SequenceOfShape edges;
826       AddOrdinaryEdges(edges,aFace,dummy);
827
828       TopTools_SequenceOfShape faces;
829       faces.Append(aFace);
830
831       //surface and location to construct result
832       TopLoc_Location aBaseLocation;
833       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
834       aBaseSurface = ClearRts(aBaseSurface);
835
836       // find adjacent faces to union
837       Standard_Integer i;
838       for (i = 1; i <= edges.Length(); i++) {
839         TopoDS_Edge edge = TopoDS::Edge(edges(i));
840         if (BRep_Tool::Degenerated(edge))
841           continue;
842
843         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
844         TopTools_ListIteratorOfListOfShape anIter(aList);
845         for (; anIter.More(); anIter.Next()) {
846           TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
847           if (anCheckedFace.IsSame(aFace))
848             continue;
849
850           if (aProcessed.Contains(anCheckedFace))
851             continue;
852
853           if (IsSameDomain(aFace,anCheckedFace)) {
854
855             if (aList.Extent() != 2) {
856               // non mainfold case is not processed
857               continue;
858             }
859
860             // replacing pcurves
861             TopoDS_Face aMockUpFace;
862             BRep_Builder B;
863             B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
864             MovePCurves(aMockUpFace,anCheckedFace);
865
866             if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
867               // sequence edges is modified
868               i = dummy;
869             }
870
871             faces.Append(anCheckedFace);
872             aProcessed.Add(anCheckedFace);
873             break;
874           }
875         }
876       }
877
878       // all faces collected in the sequence. Perform union of faces
879       if (faces.Length() > 1) {
880         NbModif++;
881         TopoDS_Face aResult;
882         BRep_Builder B;
883         B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
884         Standard_Integer nbWires = 0;
885
886         // connecting wires
887         while (edges.Length()>0) {
888
889           Standard_Boolean isEdge3d = Standard_False;
890           nbWires++;
891           TopTools_MapOfShape aVertices;
892           TopoDS_Wire aWire;
893           B.MakeWire(aWire);
894
895           TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
896           edges.Remove(1);
897
898           isEdge3d |= !BRep_Tool::Degenerated(anEdge);
899           B.Add(aWire,anEdge);
900           TopoDS_Vertex V1,V2;
901           TopExp::Vertices(anEdge,V1,V2);
902           aVertices.Add(V1);
903           aVertices.Add(V2);
904
905           Standard_Boolean isNewFound = Standard_False;
906           do {
907             isNewFound = Standard_False;
908             for(Standard_Integer j = 1; j <= edges.Length(); j++) {
909               anEdge = TopoDS::Edge(edges(j));
910               TopExp::Vertices(anEdge,V1,V2);
911               if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
912                 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
913                 aVertices.Add(V1);
914                 aVertices.Add(V2);
915                 B.Add(aWire,anEdge);
916                 edges.Remove(j);
917                 j--;
918                 isNewFound = Standard_True;
919               }
920             }
921           } while (isNewFound);
922
923           // sorting any type of edges
924           aWire.Closed (BRep_Tool::IsClosed (aWire));
925           aWire = TopoDS::Wire(myContext->Apply(aWire));
926
927           TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
928           Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
929           sfw->FixReorder();
930           Standard_Boolean isDegRemoved = Standard_False;
931           if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
932             // clear degenerated edges if at least one with 3d curve exist
933             if(isEdge3d) {
934               Handle(ShapeExtend_WireData) sewd = sfw->WireData();
935               for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
936                 TopoDS_Edge E = sewd->Edge(j);
937                 if(BRep_Tool::Degenerated(E)) {
938                   sewd->Remove(j);
939                   isDegRemoved = Standard_True;
940                   j--;
941                 }
942               }
943             }
944             sfw->FixShifted();
945             if(isDegRemoved)
946               sfw->FixDegenerated();
947           }
948           TopoDS_Wire aWireFixed = sfw->Wire();
949           //aContext->Replace(aWire,aWireFixed);
950           myContext->Replace(aWire,aWireFixed);
951           //for history
952           /*
953           if (!myOldNewMap.IsBound(aWire))
954           {
955             TopTools_ListOfShape EmptyList;
956             myOldNewMap.Bind(aWire, EmptyList);
957           }
958           myOldNewMap(aWire).Clear();
959           myOldNewMap(aWire).Append(aWireFixed);
960           */
961           /////////////
962           
963           // add resulting wire
964           if(isEdge3d) {
965             B.Add(aResult,aWireFixed);
966           }
967           else  {
968             // sorting edges
969             Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
970             Standard_Integer nbEdges = sbwd->NbEdges();
971             // sort degenerated edges and create one edge instead of several ones
972             ShapeAnalysis_WireOrder sawo(Standard_False, 0);
973             ShapeAnalysis_Edge sae;
974             Standard_Integer aLastEdge = nbEdges;
975             for(Standard_Integer j = 1; j <= nbEdges; j++) {
976               Standard_Real f,l;
977               //smh protection on NULL pcurve
978               Handle(Geom2d_Curve) c2d;
979               if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
980                 aLastEdge--;
981                 continue;
982               }
983               sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
984             }
985             sawo.Perform();
986
987             // constructind one degenerative edge
988             gp_XY aStart, anEnd, tmp;
989             Standard_Integer nbFirst = sawo.Ordered(1);
990             TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
991             ShapeBuild_Edge sbe;
992             TopoDS_Vertex aDummyV;
993             TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
994             sawo.XY(nbFirst,aStart,tmp);
995             sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
996
997             gp_XY aVec = anEnd-aStart;
998             Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
999
1000             B.UpdateEdge(E,aLine,tmpF,0.);
1001             B.Range(E,tmpF,0.,aVec.Modulus());
1002             Handle(Geom_Curve) C3d;
1003             B.UpdateEdge(E,C3d,0.);
1004             B.Degenerated(E,Standard_True);
1005             TopoDS_Wire aW;
1006             B.MakeWire(aW);
1007             B.Add(aW,E);
1008             aW.Closed (Standard_True);
1009             B.Add(aResult,aW);
1010           }
1011         }
1012
1013         // perform substitution of face
1014         //aContext->Replace(aContext->Apply(aFace),aResult);
1015         myContext->Replace(myContext->Apply(aFace),aResult);
1016         //for history
1017         /*
1018         if (!myOldNewMap.IsBound(aFace))
1019         {
1020           TopTools_ListOfShape EmptyList;
1021           myOldNewMap.Bind(aFace, EmptyList);
1022         }
1023         myOldNewMap(aFace).Clear();
1024         myOldNewMap(aFace).Append(aResult);
1025         */
1026         /////////////
1027
1028         ShapeFix_Face sff (aResult);
1029         //Intializing by tolerances
1030         sff.SetPrecision(Precision::Confusion());
1031         sff.SetMinTolerance(tol);
1032         sff.SetMaxTolerance(1.);
1033         //Setting modes
1034         sff.FixOrientationMode() = 0;
1035         //sff.FixWireMode() = 0;
1036         //sff.SetContext(aContext);
1037         sff.SetContext(myContext);
1038         // Applying the fixes
1039         sff.Perform();
1040         if(sff.Status(ShapeExtend_FAIL))
1041         hasFailed = Standard_True;
1042
1043         // breaking down to several faces
1044         //TopoDS_Shape theResult = aContext->Apply(aResult);
1045         TopoDS_Shape theResult = myContext->Apply(aResult);
1046         for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
1047           TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
1048           Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
1049           grid->SetValue ( 1, 1, aBaseSurface );
1050           Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
1051           ShapeFix_ComposeShell CompShell;
1052           CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
1053           //CompShell.SetContext( aContext );
1054           CompShell.SetContext( myContext );
1055
1056           TopTools_SequenceOfShape parts;
1057           ShapeFix_SequenceOfWireSegment wires;
1058           for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
1059             Handle(ShapeExtend_WireData) sbwd =
1060               new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
1061             ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
1062             wires.Append(seg);
1063           }
1064
1065           CompShell.DispatchWires ( parts,wires );
1066           for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
1067             ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
1068             //aFixOrient.SetContext(aContext);
1069             aFixOrient.SetContext(myContext);
1070             aFixOrient.FixOrientation();
1071           }
1072
1073           TopoDS_Shape CompRes;
1074           if ( faces.Length() !=1 ) {
1075             TopoDS_Shell S;
1076             B.MakeShell ( S );
1077             for ( i=1; i <= parts.Length(); i++ )
1078               B.Add ( S, parts(i) );
1079             S.Closed (BRep_Tool::IsClosed (S));
1080             CompRes = S;
1081           }
1082           else CompRes = parts(1);
1083
1084           //aContext->Replace(aCurrent,CompRes);
1085           myContext->Replace(aCurrent,CompRes);
1086           //for history
1087           /*
1088           if (!myOldNewMap.IsBound(aCurrent))
1089           {
1090             TopTools_ListOfShape EmptyList;
1091             myOldNewMap.Bind(aCurrent, EmptyList);
1092           }
1093           myOldNewMap(aCurrent).Clear();
1094           myOldNewMap(aCurrent).Append(CompRes);
1095           */
1096           /////////////
1097         }
1098
1099         // remove the remaining faces
1100         for(i = 2; i <= faces.Length(); i++)
1101           //aContext->Remove(faces(i));
1102           myContext->Remove(faces(i));
1103       }
1104     } // end processing each face
1105
1106     //TopoDS_Shape aResult = Shape;
1107     if (NbModif > 0 && !hasFailed) {
1108       //TopoDS_Shape aResult = aContext->Apply(aShell);
1109       TopoDS_Shape aResult = myContext->Apply(aShell);
1110
1111       ShapeFix_Edge sfe;
1112       for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
1113         TopoDS_Edge E = TopoDS::Edge(exp.Current());
1114         sfe.FixVertexTolerance (E);
1115         // ptv add fix same parameter
1116         sfe.FixSameParameter(E, Precision::Confusion());
1117       }
1118
1119       myContext->Replace(aShell, aResult);
1120       //for history
1121       /*
1122       if (!myOldNewMap.IsBound(aShell))
1123       {
1124         TopTools_ListOfShape EmptyList;
1125         myOldNewMap.Bind(aShell, EmptyList);
1126       }
1127       myOldNewMap(aShell).Clear();
1128       myOldNewMap(aShell).Append(aResult);
1129       */
1130       /////////////
1131     }
1132     //else
1133     {
1134       for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
1135         TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
1136         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
1137         sfw->SetContext(myContext);
1138         sfw->SetPrecision(Precision::Confusion());
1139         sfw->SetMinTolerance(Precision::Confusion());
1140         sfw->SetMaxTolerance(1.);
1141         sfw->SetFace(aFace);
1142         for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
1143           TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1144           sfw->Load(wire);
1145           sfw->FixReorder();
1146           sfw->FixShifted();
1147         }
1148       }
1149     }
1150   } // end processing each shell
1151
1152   myShape = myContext->Apply(myShape);
1153 }
1154
1155 //=======================================================================
1156 //function : UnifyEdges
1157 //purpose  : 
1158 //=======================================================================
1159
1160 void ShapeUpgrade_UnifySameDomain::UnifyEdges()
1161 {
1162   Standard_Real Tol = Precision::Confusion();
1163   
1164   //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
1165   Standard_Real myTolerance = Precision::Confusion();
1166   TopoDS_Shape aResult = myContext->Apply(myShape);
1167
1168   // processing each solid
1169   TopAbs_ShapeEnum aType = TopAbs_SOLID;
1170   TopExp_Explorer exps (myShape, aType);
1171   if (!exps.More()) {
1172     aType = TopAbs_SHELL;
1173     exps.Init(myShape, aType);
1174   }
1175   for (; exps.More(); exps.Next()) {
1176     //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
1177     TopoDS_Shape aSolid = exps.Current();
1178
1179     TopTools_IndexedMapOfShape ChangedFaces;
1180
1181     // creating map of edge faces
1182     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
1183     TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
1184
1185     //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
1186     TopoDS_Shape aRes = aSolid;
1187     //aRes = aContext->Apply(aSolid);
1188     aRes = myContext->Apply(aSolid);
1189
1190     // processing each face
1191     TopExp_Explorer exp;
1192     for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
1193       //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1194       TopoDS_Face aFace = TopoDS::Face(myContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1195       TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
1196
1197       for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
1198         TopoDS_Edge edge = TopoDS::Edge(expe.Current());
1199         if (!aMapEdgeFaces.Contains(edge)) continue;
1200         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
1201         TopTools_ListIteratorOfListOfShape anIter(aList);
1202         for ( ; anIter.More(); anIter.Next()) {
1203           TopoDS_Face face = TopoDS::Face(anIter.Value());
1204           //TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
1205           TopoDS_Face face1 = TopoDS::Face(myContext->Apply(anIter.Value()));
1206           if (face1.IsSame(aFace)) continue;
1207           if (aMapFacesEdges.Contains(face)) {
1208             aMapFacesEdges.ChangeFromKey(face).Append(edge);
1209           }
1210           else {
1211             TopTools_ListOfShape ListEdges;
1212             ListEdges.Append(edge);
1213             aMapFacesEdges.Add(face,ListEdges);
1214           }
1215         }
1216       }
1217
1218       for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
1219         const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
1220         TopTools_SequenceOfShape SeqEdges;
1221         TopTools_ListIteratorOfListOfShape anIter(ListEdges);
1222         for ( ; anIter.More(); anIter.Next()) {
1223           SeqEdges.Append(anIter.Value());
1224         }
1225         if (SeqEdges.Length()==1) continue;
1226         TopoDS_Edge E;
1227         if ( MergeEdges(SeqEdges,aFace,Tol,myConcatBSplines,E) ) {
1228           // now we have only one edge - aChain.Value(1)
1229           // we have to replace old ListEdges with this new edge
1230           //aContext->Replace(SeqEdges(1),E);
1231           myContext->Replace(SeqEdges(1),E);
1232           Standard_Integer j;
1233           for (j = 2; j <= SeqEdges.Length(); j++) {
1234             //aContext->Remove(SeqEdges(j));
1235             myContext->Remove(SeqEdges(j));
1236             //myOldNewMap.Bind(SeqEdges(j), E);
1237           }
1238           //for history
1239           /*
1240           for (j = 1; j <= SeqEdges.Length(); j++)
1241           {
1242             if (!myOldNewMap.IsBound(SeqEdges(j)))
1243             {
1244               TopTools_ListOfShape EmptyList;
1245               myOldNewMap.Bind(SeqEdges(j), EmptyList);
1246             }
1247             myOldNewMap(SeqEdges(j)).Clear();
1248             myOldNewMap(SeqEdges(j)).Append(E);
1249           }
1250           */
1251           /////////////
1252           
1253           TopoDS_Face tmpF = TopoDS::Face(exp.Current());
1254           if ( !ChangedFaces.Contains(tmpF) )
1255             ChangedFaces.Add(tmpF);
1256           tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
1257           if ( !ChangedFaces.Contains(tmpF) )
1258             ChangedFaces.Add(tmpF);
1259         }
1260       }
1261
1262     } // end processing each face
1263
1264     // fix changed faces and replace them in the local context
1265     for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
1266       //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
1267       TopoDS_Face aFace = TopoDS::Face(myContext->Apply(ChangedFaces.FindKey(i)));
1268       Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
1269       sff->SetContext(myContext);
1270       sff->SetPrecision(myTolerance);
1271       sff->SetMinTolerance(myTolerance);
1272       sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
1273       sff->Perform();
1274       TopoDS_Shape aNewFace = sff->Face();
1275       //aContext->Replace(aFace,aNewFace);
1276       myContext->Replace(aFace,aNewFace);
1277       //for history
1278       /*
1279       if (!myOldNewMap.IsBound(aFace))
1280       {
1281         TopTools_ListOfShape EmptyList;
1282         myOldNewMap.Bind(aFace, EmptyList);
1283       }
1284       myOldNewMap(aFace).Clear();
1285       myOldNewMap(aFace).Append(aNewFace);
1286       */
1287       /////////////
1288     }
1289
1290     if (ChangedFaces.Extent() > 0) {
1291       // fix changed shell and replace it in the local context
1292       //TopoDS_Shape aRes1 = aContext->Apply(aRes);
1293       TopoDS_Shape aRes1 = myContext->Apply(aRes);
1294       TopExp_Explorer expsh;
1295       for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
1296         TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
1297         Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
1298         sfsh->FixFaceOrientation(aShell);
1299         TopoDS_Shape aNewShell = sfsh->Shell();
1300         //aContext->Replace(aShell,aNewShell);
1301         myContext->Replace(aShell,aNewShell);
1302         //for history
1303         /*
1304         if (!myOldNewMap.IsBound(aShell))
1305         {
1306           TopTools_ListOfShape EmptyList;
1307           myOldNewMap.Bind(aShell, EmptyList);
1308         }
1309         myOldNewMap(aShell).Clear();
1310         myOldNewMap(aShell).Append(aNewShell);
1311         */
1312         /////////////
1313       }
1314       //TopoDS_Shape aRes2 = aContext->Apply(aRes1);
1315       TopoDS_Shape aRes2 = myContext->Apply(aRes1);
1316       // put new solid into global context
1317       myContext->Replace(aSolid,aRes2);
1318       //for history
1319       /*
1320       if (!myOldNewMap.IsBound(aSolid))
1321       {
1322         TopTools_ListOfShape EmptyList;
1323         myOldNewMap.Bind(aSolid, EmptyList);
1324       }
1325       myOldNewMap(aSolid).Clear();
1326       myOldNewMap(aSolid).Append(aRes2);
1327       */
1328       /////////////
1329     }
1330
1331   } // end processing each solid
1332
1333   myShape = myContext->Apply(myShape);
1334 }
1335
1336 //=======================================================================
1337 //function : UnifyFacesAndEdges
1338 //purpose  : 
1339 //=======================================================================
1340
1341 void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
1342 {
1343   UnifyFaces();
1344   
1345   /*
1346   ShapeUpgrade_RemoveLocations RemLoc;
1347   RemLoc.Remove(myShape);
1348   myShape = RemLoc.GetResult();
1349   */
1350
1351   UnifyEdges();
1352 }
1353
1354 //=======================================================================
1355 //function : Build
1356 //purpose  : builds the resulting shape
1357 //======================================================================
1358 void ShapeUpgrade_UnifySameDomain::Build() 
1359 {
1360   if (myUnifyFaces && myUnifyEdges)
1361     UnifyFacesAndEdges();
1362
1363   else if (myUnifyEdges)
1364     UnifyEdges();
1365   else if (myUnifyFaces)
1366     UnifyFaces();
1367
1368   //Done();
1369 }
1370
1371 //=======================================================================
1372 //function : Shape
1373 //purpose  : give the resulting shape
1374 //=======================================================================
1375 const TopoDS_Shape& ShapeUpgrade_UnifySameDomain::Shape() const
1376 {
1377   return myShape;
1378 }
1379
1380 //=======================================================================
1381 //function : Generated
1382 //purpose  : returns the new shape from the old one
1383 //=======================================================================
1384 TopoDS_Shape ShapeUpgrade_UnifySameDomain::Generated(const TopoDS_Shape& aShape) const
1385 {
1386   TopoDS_Shape aNewShape = myContext->Apply(aShape);
1387   /*
1388   if (aNewShape.IsNull())
1389     aNewShape = myOldNewMap(aShape);
1390   */
1391   
1392   return aNewShape;
1393 }