0023948: Wrong intersection between a surface of revolution and a plane.
[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 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 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 DEB
708       cout<<"can not make analitical union => make approximation"<<endl;
709 #endif
710       TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
711       /*
712       TopoDS_Wire W;
713       B.MakeWire(W);
714       for(j=1; j<=aChain.Length(); j++) {
715         TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
716         B.Add(W,edge);
717       }
718       Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W);
719       Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000);
720       Handle(Geom_BSplineCurve) bc = Conv.Curve();
721       TopoDS_Edge E;
722       B.MakeEdge (E,bc,Precision::Confusion());
723       B.Add (E,VF);
724       B.Add (E,VL);
725       */
726       aChain.SetValue(1,E);
727     }
728     else {
729 #ifdef DEB
730       cout<<"can not make approximation for such types of curves"<<endl;
731 #endif
732       return Standard_False;
733     }
734   }
735
736   anEdge = TopoDS::Edge(aChain.Value(1));
737   return Standard_True;
738 }
739
740 //=======================================================================
741 //function : ShapeUpgrade_UnifySameDomain
742 //purpose  : Constructor
743 //=======================================================================
744
745 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
746 {
747   myUnifyEdges = Standard_True;
748   myUnifyFaces = Standard_True;
749   myConcatBSplines = Standard_False;
750
751   myContext = new ShapeBuild_ReShape;
752 }
753
754 //=======================================================================
755 //function : ShapeUpgrade_UnifySameDomain
756 //purpose  : Constructor
757 //=======================================================================
758
759 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape,
760                                                            const Standard_Boolean UnifyEdges,
761                                                            const Standard_Boolean UnifyFaces,
762                                                            const Standard_Boolean ConcatBSplines)
763 {
764   myInitShape = aShape;
765   myShape = aShape;
766   myUnifyEdges = UnifyEdges;
767   myUnifyFaces = UnifyFaces;
768   myConcatBSplines = ConcatBSplines;
769
770   myContext = new ShapeBuild_ReShape;
771 }
772
773 //=======================================================================
774 //function : Initialize
775 //purpose  : 
776 //=======================================================================
777
778 void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
779                                               const Standard_Boolean UnifyEdges,
780                                               const Standard_Boolean UnifyFaces,
781                                               const Standard_Boolean ConcatBSplines)
782 {
783   myInitShape = aShape;
784   myShape = aShape;
785   myUnifyEdges = UnifyEdges;
786   myUnifyFaces = UnifyFaces;
787   myConcatBSplines = ConcatBSplines;
788
789   myContext->Clear();
790   //myOldNewMap.Clear();
791   //myGenerated.Clear();
792 }
793
794 //=======================================================================
795 //function : UnifyFaces
796 //purpose  : 
797 //=======================================================================
798
799 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
800 {
801   //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
802   TopoDS_Shape aResShape = myContext->Apply(myShape);
803
804   // processing each shell
805   TopExp_Explorer exps;
806   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
807     TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
808
809     // creating map of edge faces
810     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
811     TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
812
813     // map of processed shapes
814     TopTools_MapOfShape aProcessed;
815
816     //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
817
818     Standard_Integer NbModif = 0;
819     Standard_Boolean hasFailed = Standard_False;
820     Standard_Real tol = Precision::Confusion();
821
822     // count faces
823     Standard_Integer nbf = 0;
824     TopExp_Explorer exp;
825     TopTools_MapOfShape mapF;
826     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
827       if (mapF.Add(exp.Current()))
828         nbf++;
829     }
830
831     // processing each face
832     mapF.Clear();
833     for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
834       TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
835
836       if (aProcessed.Contains(aFace))
837         continue;
838
839       Standard_Integer dummy;
840       TopTools_SequenceOfShape edges;
841       AddOrdinaryEdges(edges,aFace,dummy);
842
843       TopTools_SequenceOfShape faces;
844       faces.Append(aFace);
845
846       //surface and location to construct result
847       TopLoc_Location aBaseLocation;
848       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
849       aBaseSurface = ClearRts(aBaseSurface);
850
851       // find adjacent faces to union
852       Standard_Integer i;
853       for (i = 1; i <= edges.Length(); i++) {
854         TopoDS_Edge edge = TopoDS::Edge(edges(i));
855         if (BRep_Tool::Degenerated(edge))
856           continue;
857
858         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
859         TopTools_ListIteratorOfListOfShape anIter(aList);
860         for (; anIter.More(); anIter.Next()) {
861           TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
862           if (anCheckedFace.IsSame(aFace))
863             continue;
864
865           if (aProcessed.Contains(anCheckedFace))
866             continue;
867
868           if (IsSameDomain(aFace,anCheckedFace)) {
869
870             if (aList.Extent() != 2) {
871               // non mainfold case is not processed
872               continue;
873             }
874
875             // replacing pcurves
876             TopoDS_Face aMockUpFace;
877             BRep_Builder B;
878             B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
879             MovePCurves(aMockUpFace,anCheckedFace);
880
881             if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
882               // sequence edges is modified
883               i = dummy;
884             }
885
886             faces.Append(anCheckedFace);
887             aProcessed.Add(anCheckedFace);
888             break;
889           }
890         }
891       }
892
893       // all faces collected in the sequence. Perform union of faces
894       if (faces.Length() > 1) {
895         NbModif++;
896         TopoDS_Face aResult;
897         BRep_Builder B;
898         B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
899         Standard_Integer nbWires = 0;
900
901         // connecting wires
902         while (edges.Length()>0) {
903
904           Standard_Boolean isEdge3d = Standard_False;
905           nbWires++;
906           TopTools_MapOfShape aVertices;
907           TopoDS_Wire aWire;
908           B.MakeWire(aWire);
909
910           TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
911           edges.Remove(1);
912
913           isEdge3d |= !BRep_Tool::Degenerated(anEdge);
914           B.Add(aWire,anEdge);
915           TopoDS_Vertex V1,V2;
916           TopExp::Vertices(anEdge,V1,V2);
917           aVertices.Add(V1);
918           aVertices.Add(V2);
919
920           Standard_Boolean isNewFound = Standard_False;
921           do {
922             isNewFound = Standard_False;
923             for(Standard_Integer j = 1; j <= edges.Length(); j++) {
924               anEdge = TopoDS::Edge(edges(j));
925               TopExp::Vertices(anEdge,V1,V2);
926               if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
927                 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
928                 aVertices.Add(V1);
929                 aVertices.Add(V2);
930                 B.Add(aWire,anEdge);
931                 edges.Remove(j);
932                 j--;
933                 isNewFound = Standard_True;
934               }
935             }
936           } while (isNewFound);
937
938           // sorting any type of edges
939           //aWire = TopoDS::Wire(aContext->Apply(aWire));
940           aWire = TopoDS::Wire(myContext->Apply(aWire));
941
942           //TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
943           TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
944           Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
945           sfw->FixReorder();
946           Standard_Boolean isDegRemoved = Standard_False;
947           if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
948             // clear degenerated edges if at least one with 3d curve exist
949             if(isEdge3d) {
950               Handle(ShapeExtend_WireData) sewd = sfw->WireData();
951               for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
952                 TopoDS_Edge E = sewd->Edge(j);
953                 if(BRep_Tool::Degenerated(E)) {
954                   sewd->Remove(j);
955                   isDegRemoved = Standard_True;
956                   j--;
957                 }
958               }
959             }
960             sfw->FixShifted();
961             if(isDegRemoved)
962               sfw->FixDegenerated();
963           }
964           TopoDS_Wire aWireFixed = sfw->Wire();
965           //aContext->Replace(aWire,aWireFixed);
966           myContext->Replace(aWire,aWireFixed);
967           //for history
968           /*
969           if (!myOldNewMap.IsBound(aWire))
970           {
971             TopTools_ListOfShape EmptyList;
972             myOldNewMap.Bind(aWire, EmptyList);
973           }
974           myOldNewMap(aWire).Clear();
975           myOldNewMap(aWire).Append(aWireFixed);
976           */
977           /////////////
978           
979           // add resulting wire
980           if(isEdge3d) {
981             B.Add(aResult,aWireFixed);
982           }
983           else  {
984             // sorting edges
985             Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
986             Standard_Integer nbEdges = sbwd->NbEdges();
987             // sort degenerated edges and create one edge instead of several ones
988             ShapeAnalysis_WireOrder sawo(Standard_False, 0);
989             ShapeAnalysis_Edge sae;
990             Standard_Integer aLastEdge = nbEdges;
991             for(Standard_Integer j = 1; j <= nbEdges; j++) {
992               Standard_Real f,l;
993               //smh protection on NULL pcurve
994               Handle(Geom2d_Curve) c2d;
995               if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
996                 aLastEdge--;
997                 continue;
998               }
999               sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
1000             }
1001             sawo.Perform();
1002
1003             // constructind one degenerative edge
1004             gp_XY aStart, anEnd, tmp;
1005             Standard_Integer nbFirst = sawo.Ordered(1);
1006             TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
1007             ShapeBuild_Edge sbe;
1008             TopoDS_Vertex aDummyV;
1009             TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
1010             sawo.XY(nbFirst,aStart,tmp);
1011             sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
1012
1013             gp_XY aVec = anEnd-aStart;
1014             Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
1015
1016             B.UpdateEdge(E,aLine,tmpF,0.);
1017             B.Range(E,tmpF,0.,aVec.Modulus());
1018             Handle(Geom_Curve) C3d;
1019             B.UpdateEdge(E,C3d,0.);
1020             B.Degenerated(E,Standard_True);
1021             TopoDS_Wire aW;
1022             B.MakeWire(aW);
1023             B.Add(aW,E);
1024             B.Add(aResult,aW);
1025           }
1026         }
1027
1028         // perform substitution of face
1029         //aContext->Replace(aContext->Apply(aFace),aResult);
1030         myContext->Replace(myContext->Apply(aFace),aResult);
1031         //for history
1032         /*
1033         if (!myOldNewMap.IsBound(aFace))
1034         {
1035           TopTools_ListOfShape EmptyList;
1036           myOldNewMap.Bind(aFace, EmptyList);
1037         }
1038         myOldNewMap(aFace).Clear();
1039         myOldNewMap(aFace).Append(aResult);
1040         */
1041         /////////////
1042
1043         ShapeFix_Face sff (aResult);
1044         //Intializing by tolerances
1045         sff.SetPrecision(Precision::Confusion());
1046         sff.SetMinTolerance(tol);
1047         sff.SetMaxTolerance(1.);
1048         //Setting modes
1049         sff.FixOrientationMode() = 0;
1050         //sff.FixWireMode() = 0;
1051         //sff.SetContext(aContext);
1052         sff.SetContext(myContext);
1053         // Applying the fixes
1054         sff.Perform();
1055         if(sff.Status(ShapeExtend_FAIL))
1056         hasFailed = Standard_True;
1057
1058         // breaking down to several faces
1059         //TopoDS_Shape theResult = aContext->Apply(aResult);
1060         TopoDS_Shape theResult = myContext->Apply(aResult);
1061         for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
1062           TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
1063           Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
1064           grid->SetValue ( 1, 1, aBaseSurface );
1065           Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
1066           ShapeFix_ComposeShell CompShell;
1067           CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
1068           //CompShell.SetContext( aContext );
1069           CompShell.SetContext( myContext );
1070
1071           TopTools_SequenceOfShape parts;
1072           ShapeFix_SequenceOfWireSegment wires;
1073           for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
1074             Handle(ShapeExtend_WireData) sbwd =
1075               new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
1076             ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
1077             wires.Append(seg);
1078           }
1079
1080           CompShell.DispatchWires ( parts,wires );
1081           for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
1082             ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
1083             //aFixOrient.SetContext(aContext);
1084             aFixOrient.SetContext(myContext);
1085             aFixOrient.FixOrientation();
1086           }
1087
1088           TopoDS_Shape CompRes;
1089           if ( faces.Length() !=1 ) {
1090             TopoDS_Shell S;
1091             B.MakeShell ( S );
1092             for ( i=1; i <= parts.Length(); i++ )
1093               B.Add ( S, parts(i) );
1094             CompRes = S;
1095           }
1096           else CompRes = parts(1);
1097
1098           //aContext->Replace(aCurrent,CompRes);
1099           myContext->Replace(aCurrent,CompRes);
1100           //for history
1101           /*
1102           if (!myOldNewMap.IsBound(aCurrent))
1103           {
1104             TopTools_ListOfShape EmptyList;
1105             myOldNewMap.Bind(aCurrent, EmptyList);
1106           }
1107           myOldNewMap(aCurrent).Clear();
1108           myOldNewMap(aCurrent).Append(CompRes);
1109           */
1110           /////////////
1111         }
1112
1113         // remove the remaining faces
1114         for(i = 2; i <= faces.Length(); i++)
1115           //aContext->Remove(faces(i));
1116           myContext->Remove(faces(i));
1117       }
1118     } // end processing each face
1119
1120     //TopoDS_Shape aResult = Shape;
1121     if (NbModif > 0 && !hasFailed) {
1122       //TopoDS_Shape aResult = aContext->Apply(aShell);
1123       TopoDS_Shape aResult = myContext->Apply(aShell);
1124
1125       ShapeFix_Edge sfe;
1126       for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
1127         TopoDS_Edge E = TopoDS::Edge(exp.Current());
1128         sfe.FixVertexTolerance (E);
1129         // ptv add fix same parameter
1130         sfe.FixSameParameter(E, Precision::Confusion());
1131       }
1132
1133       myContext->Replace(aShell, aResult);
1134       //for history
1135       /*
1136       if (!myOldNewMap.IsBound(aShell))
1137       {
1138         TopTools_ListOfShape EmptyList;
1139         myOldNewMap.Bind(aShell, EmptyList);
1140       }
1141       myOldNewMap(aShell).Clear();
1142       myOldNewMap(aShell).Append(aResult);
1143       */
1144       /////////////
1145     }
1146     //else
1147     {
1148       for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
1149         TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
1150         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
1151         sfw->SetContext(myContext);
1152         sfw->SetPrecision(Precision::Confusion());
1153         sfw->SetMinTolerance(Precision::Confusion());
1154         sfw->SetMaxTolerance(1.);
1155         sfw->SetFace(aFace);
1156         for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
1157           TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1158           sfw->Load(wire);
1159           sfw->FixReorder();
1160           sfw->FixShifted();
1161         }
1162       }
1163     }
1164   } // end processing each shell
1165
1166   myShape = myContext->Apply(myShape);
1167 }
1168
1169 //=======================================================================
1170 //function : UnifyEdges
1171 //purpose  : 
1172 //=======================================================================
1173
1174 void ShapeUpgrade_UnifySameDomain::UnifyEdges()
1175 {
1176   Standard_Real Tol = Precision::Confusion();
1177   
1178   //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
1179   Standard_Real myTolerance = Precision::Confusion();
1180   TopoDS_Shape aResult = myContext->Apply(myShape);
1181
1182   // processing each solid
1183   TopAbs_ShapeEnum aType = TopAbs_SOLID;
1184   TopExp_Explorer exps (myShape, aType);
1185   if (!exps.More()) {
1186     aType = TopAbs_SHELL;
1187     exps.Init(myShape, aType);
1188   }
1189   for (; exps.More(); exps.Next()) {
1190     //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
1191     TopoDS_Shape aSolid = exps.Current();
1192
1193     TopTools_IndexedMapOfShape ChangedFaces;
1194
1195     // creating map of edge faces
1196     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
1197     TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
1198
1199     //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
1200     TopoDS_Shape aRes = aSolid;
1201     //aRes = aContext->Apply(aSolid);
1202     aRes = myContext->Apply(aSolid);
1203
1204     // processing each face
1205     TopExp_Explorer exp;
1206     for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
1207       //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1208       TopoDS_Face aFace = TopoDS::Face(myContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
1209       TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
1210
1211       for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
1212         TopoDS_Edge edge = TopoDS::Edge(expe.Current());
1213         if (!aMapEdgeFaces.Contains(edge)) continue;
1214         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
1215         TopTools_ListIteratorOfListOfShape anIter(aList);
1216         for ( ; anIter.More(); anIter.Next()) {
1217           TopoDS_Face face = TopoDS::Face(anIter.Value());
1218           //TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
1219           TopoDS_Face face1 = TopoDS::Face(myContext->Apply(anIter.Value()));
1220           if (face1.IsSame(aFace)) continue;
1221           if (aMapFacesEdges.Contains(face)) {
1222             aMapFacesEdges.ChangeFromKey(face).Append(edge);
1223           }
1224           else {
1225             TopTools_ListOfShape ListEdges;
1226             ListEdges.Append(edge);
1227             aMapFacesEdges.Add(face,ListEdges);
1228           }
1229         }
1230       }
1231
1232       for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
1233         const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
1234         TopTools_SequenceOfShape SeqEdges;
1235         TopTools_ListIteratorOfListOfShape anIter(ListEdges);
1236         for ( ; anIter.More(); anIter.Next()) {
1237           SeqEdges.Append(anIter.Value());
1238         }
1239         if (SeqEdges.Length()==1) continue;
1240         TopoDS_Edge E;
1241         if ( MergeEdges(SeqEdges,aFace,Tol,myConcatBSplines,E) ) {
1242           // now we have only one edge - aChain.Value(1)
1243           // we have to replace old ListEdges with this new edge
1244           //aContext->Replace(SeqEdges(1),E);
1245           myContext->Replace(SeqEdges(1),E);
1246           Standard_Integer j;
1247           for (j = 2; j <= SeqEdges.Length(); j++) {
1248             //aContext->Remove(SeqEdges(j));
1249             myContext->Remove(SeqEdges(j));
1250             //myOldNewMap.Bind(SeqEdges(j), E);
1251           }
1252           //for history
1253           /*
1254           for (j = 1; j <= SeqEdges.Length(); j++)
1255           {
1256             if (!myOldNewMap.IsBound(SeqEdges(j)))
1257             {
1258               TopTools_ListOfShape EmptyList;
1259               myOldNewMap.Bind(SeqEdges(j), EmptyList);
1260             }
1261             myOldNewMap(SeqEdges(j)).Clear();
1262             myOldNewMap(SeqEdges(j)).Append(E);
1263           }
1264           */
1265           /////////////
1266           
1267           TopoDS_Face tmpF = TopoDS::Face(exp.Current());
1268           if ( !ChangedFaces.Contains(tmpF) )
1269             ChangedFaces.Add(tmpF);
1270           tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
1271           if ( !ChangedFaces.Contains(tmpF) )
1272             ChangedFaces.Add(tmpF);
1273         }
1274       }
1275
1276     } // end processing each face
1277
1278     // fix changed faces and replace them in the local context
1279     for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
1280       //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
1281       TopoDS_Face aFace = TopoDS::Face(myContext->Apply(ChangedFaces.FindKey(i)));
1282       Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
1283       sff->SetContext(myContext);
1284       sff->SetPrecision(myTolerance);
1285       sff->SetMinTolerance(myTolerance);
1286       sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
1287       sff->Perform();
1288       TopoDS_Shape aNewFace = sff->Face();
1289       //aContext->Replace(aFace,aNewFace);
1290       myContext->Replace(aFace,aNewFace);
1291       //for history
1292       /*
1293       if (!myOldNewMap.IsBound(aFace))
1294       {
1295         TopTools_ListOfShape EmptyList;
1296         myOldNewMap.Bind(aFace, EmptyList);
1297       }
1298       myOldNewMap(aFace).Clear();
1299       myOldNewMap(aFace).Append(aNewFace);
1300       */
1301       /////////////
1302     }
1303
1304     if (ChangedFaces.Extent() > 0) {
1305       // fix changed shell and replace it in the local context
1306       //TopoDS_Shape aRes1 = aContext->Apply(aRes);
1307       TopoDS_Shape aRes1 = myContext->Apply(aRes);
1308       TopExp_Explorer expsh;
1309       for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
1310         TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
1311         Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
1312         sfsh->FixFaceOrientation(aShell);
1313         TopoDS_Shape aNewShell = sfsh->Shell();
1314         //aContext->Replace(aShell,aNewShell);
1315         myContext->Replace(aShell,aNewShell);
1316         //for history
1317         /*
1318         if (!myOldNewMap.IsBound(aShell))
1319         {
1320           TopTools_ListOfShape EmptyList;
1321           myOldNewMap.Bind(aShell, EmptyList);
1322         }
1323         myOldNewMap(aShell).Clear();
1324         myOldNewMap(aShell).Append(aNewShell);
1325         */
1326         /////////////
1327       }
1328       //TopoDS_Shape aRes2 = aContext->Apply(aRes1);
1329       TopoDS_Shape aRes2 = myContext->Apply(aRes1);
1330       // put new solid into global context
1331       myContext->Replace(aSolid,aRes2);
1332       //for history
1333       /*
1334       if (!myOldNewMap.IsBound(aSolid))
1335       {
1336         TopTools_ListOfShape EmptyList;
1337         myOldNewMap.Bind(aSolid, EmptyList);
1338       }
1339       myOldNewMap(aSolid).Clear();
1340       myOldNewMap(aSolid).Append(aRes2);
1341       */
1342       /////////////
1343     }
1344
1345   } // end processing each solid
1346
1347   myShape = myContext->Apply(myShape);
1348 }
1349
1350 //=======================================================================
1351 //function : UnifyFacesAndEdges
1352 //purpose  : 
1353 //=======================================================================
1354
1355 void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
1356 {
1357   UnifyFaces();
1358   
1359   /*
1360   ShapeUpgrade_RemoveLocations RemLoc;
1361   RemLoc.Remove(myShape);
1362   myShape = RemLoc.GetResult();
1363   */
1364
1365   UnifyEdges();
1366 }
1367
1368 //=======================================================================
1369 //function : Build
1370 //purpose  : builds the resulting shape
1371 //======================================================================
1372 void ShapeUpgrade_UnifySameDomain::Build() 
1373 {
1374   if (myUnifyFaces && myUnifyEdges)
1375     UnifyFacesAndEdges();
1376
1377   else if (myUnifyEdges)
1378     UnifyEdges();
1379   else if (myUnifyFaces)
1380     UnifyFaces();
1381
1382   //Done();
1383 }
1384
1385 //=======================================================================
1386 //function : Shape
1387 //purpose  : give the resulting shape
1388 //=======================================================================
1389 const TopoDS_Shape& ShapeUpgrade_UnifySameDomain::Shape() const
1390 {
1391   return myShape;
1392 }
1393
1394 //=======================================================================
1395 //function : Generated
1396 //purpose  : returns the new shape from the old one
1397 //=======================================================================
1398 TopoDS_Shape ShapeUpgrade_UnifySameDomain::Generated(const TopoDS_Shape& aShape) const
1399 {
1400   TopoDS_Shape aNewShape = myContext->Apply(aShape);
1401   /*
1402   if (aNewShape.IsNull())
1403     aNewShape = myOldNewMap(aShape);
1404   */
1405   
1406   return aNewShape;
1407 }