0026377: Passing Handle objects as arguments to functions as non-const reference...
[occt.git] / src / QANewModTopOpe / QANewModTopOpe_Glue_wire.cxx
1 // Created on: 2001-01-16
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAlgo_EdgeConnector.hxx>
20 #include <BRepBuilderAPI_MakeWire.hxx>
21 #include <BRepExtrema_DistShapeShape.hxx>
22 #include <BRepIntCurveSurface_Inter.hxx>
23 #include <BRepTopAdaptor_FClass2d.hxx>
24 #include <Geom_Curve.hxx>
25 #include <GeomAdaptor_Curve.hxx>
26 #include <GeomAPI_ProjectPointOnCurve.hxx>
27 #include <GeomAPI_ProjectPointOnSurf.hxx>
28 #include <GeomProjLib.hxx>
29 #include <gp_Pnt.hxx>
30 #include <Precision.hxx>
31 #include <QANewModTopOpe_Glue.hxx>
32 #include <TColgp_SequenceOfPnt.hxx>
33 #include <TColStd_Array2OfInteger.hxx>
34 #include <TColStd_SequenceOfInteger.hxx>
35 #include <TColStd_SequenceOfReal.hxx>
36 #include <TopExp.hxx>
37 #include <TopExp_Explorer.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Edge.hxx>
40 #include <TopoDS_Face.hxx>
41 #include <TopoDS_Iterator.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopOpeBRepTool_TOOL.hxx>
45 #include <TopTools_Array2OfShape.hxx>
46 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
48 #include <TopTools_IndexedMapOfShape.hxx>
49 #include <TopTools_ListIteratorOfListOfShape.hxx>
50
51 //#include <BRepClass_FaceClassifier.hxx>
52 //=======================================================================
53 //function : IsOnSurface
54 //purpose  : static
55 //=======================================================================
56 static Standard_Boolean
57 IsOnSurface (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace)
58 {
59   Standard_Real aParF, aParL, aTolEdge;
60   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aParF, aParL);
61   if (aCurve.IsNull()) return Standard_False;
62   aTolEdge = BRep_Tool::Tolerance(theEdge);
63   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
64
65   // define check points
66   Standard_Real aParams[4];
67   Standard_Real aDeltaRange = aParL - aParF;
68   aParams[0] = aParF;
69   aParams[1] = aParF + aDeltaRange * 0.382;
70   aParams[2] = aParF + aDeltaRange * 0.618;
71   aParams[3] = aParL;
72   gp_Pnt   aPnt;
73
74   // check distance to the surface
75   Standard_Real aTol = aTolEdge + BRep_Tool::Tolerance(theFace);
76   Standard_Integer i;
77   for (i=0; i < 4; i++) {
78     aPnt = aCurve->Value(aParams[i]);
79     GeomAPI_ProjectPointOnSurf aProjector(aPnt, aSurf);
80     if (!aProjector.IsDone() || aProjector.LowerDistance() > aTol)
81       return Standard_False;
82   }
83
84   return Standard_True;
85 }
86
87 //=======================================================================
88 //function : ProcessEdgeFaceInterference
89 //purpose  : static
90 //=======================================================================
91
92 static void
93 ProcessEdgeFaceInterference (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace,
94                              TopoDS_Shape& theNewFace,
95                              TopTools_ListOfShape& theListE,
96                              TColgp_SequenceOfPnt& thePoints1,
97                              TColgp_SequenceOfPnt& thePoints2,
98                              TColStd_SequenceOfInteger& theEdgeOnSurface,
99                              TopTools_DataMapOfShapeListOfShape& theMapSubst,
100                              TopTools_DataMapOfShapeListOfShape& theMapGener)
101 {
102   BRep_Builder aBld;
103
104
105   Standard_Boolean anIsOnSurface = IsOnSurface(theEdge, theFace);
106   TColgp_SequenceOfPnt aPntOfInter;
107   TColStd_SequenceOfReal aW;
108   TopTools_ListOfShape aListOfIntVert;
109   if(!anIsOnSurface) {
110     //check intersection points
111     BRepIntCurveSurface_Inter anInter;
112     Standard_Real f, l;
113     const TopoDS_Edge& anE = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
114     Handle(Geom_Curve) aC = 
115       BRep_Tool::Curve(anE, f, l);
116     GeomAdaptor_Curve anAdC(aC, f, l);
117     anInter.Init(theFace, anAdC, Precision::PConfusion());
118     for(; anInter.More(); anInter.Next()) {
119       if(anInter.State() == TopAbs_ON) { continue;}
120       aPntOfInter.Append(anInter.Pnt());
121       aW.Append(anInter.W());
122     }
123     // check vertices
124     
125
126     TopoDS_Vertex aV1, aV2;
127     TopExp::Vertices(anE, aV1, aV2);
128     TopoDS_Shape aCmp;
129     aBld.MakeCompound(TopoDS::Compound(aCmp));
130     aBld.Add(aCmp, aV1); 
131     if(!aV1.IsSame(aV2)) aBld.Add(aCmp, aV2);
132
133     TopoDS_Iterator anItV(theEdge);
134     for(; anItV.More(); anItV.Next()) {
135       if(anItV.Value().Orientation() == TopAbs_INTERNAL)
136         aBld.Add(aCmp, anItV.Value());
137     }
138
139     BRepExtrema_DistShapeShape aExtrema (theFace, aCmp);
140     if (aExtrema.IsDone()) {
141       Standard_Integer nbSol = aExtrema.NbSolution(), i, j;
142       Standard_Real aDist = aExtrema.Value(), aTol;
143       Standard_Integer n = aPntOfInter.Length();
144       for (i=1; i <= nbSol; i++) {
145         if(aExtrema.SupportTypeShape1(i) != BRepExtrema_IsInFace) continue; 
146         TopoDS_Shape aS2 = aExtrema.SupportOnShape2(i);
147         aTol = BRep_Tool::Tolerance(TopoDS::Vertex(aS2));
148         if(aDist > aTol) continue;
149         aListOfIntVert.Append(aS2);
150         //check intersection points on coincidence with vertex
151         gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(aS2));
152         for(j=1; j <= n;  j++) {
153           if(aP.Distance(aPntOfInter(j)) > aTol) continue;
154           aPntOfInter.Remove(j);
155           aW.Remove(j);
156           j--;
157           n--;
158         }
159       }
160     }
161   }      
162     
163
164   TopExp_Explorer aExp (theFace.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
165   Standard_Boolean IsNotInternal = Standard_True;
166   Standard_Boolean InsertVertexInBoundary = Standard_True;
167   Standard_Integer aN = thePoints1.Length();
168   for (; aExp.More(); aExp.Next()) {
169     const TopoDS_Edge& aE = TopoDS::Edge (aExp.Current());
170     IsNotInternal = Standard_True;
171     InsertVertexInBoundary = Standard_True;
172     if(aE.Orientation() == TopAbs_EXTERNAL) continue;
173     if(aE.Orientation() == TopAbs_INTERNAL) IsNotInternal = Standard_False;
174 //    if (aE.Orientation() != TopAbs_FORWARD &&
175 //      aE.Orientation() != TopAbs_REVERSED) continue;
176
177     BRepExtrema_DistShapeShape aExtrema (aE.Oriented(TopAbs_FORWARD),
178                                          theEdge.Oriented(TopAbs_FORWARD));
179     if (!aExtrema.IsDone()) continue;
180     Standard_Integer nbSol = aExtrema.NbSolution(), i;
181     Standard_Real aDist = aExtrema.Value();
182     for (i=1; i <= nbSol; i++) {
183       TopoDS_Shape aS1 = aExtrema.SupportOnShape1(i);
184       TopoDS_Shape aS2 = aExtrema.SupportOnShape2(i);
185
186       // check distance against tolerances
187       Standard_Real aTol1, aTol2;
188       if (aS1.ShapeType() == TopAbs_VERTEX)
189         aTol1 = BRep_Tool::Tolerance (TopoDS::Vertex(aS1));
190       else
191         aTol1 = BRep_Tool::Tolerance (TopoDS::Edge(aS1));
192       if (aS2.ShapeType() == TopAbs_VERTEX)
193         aTol2 = BRep_Tool::Tolerance (TopoDS::Vertex(aS2));
194       else
195         aTol2 = BRep_Tool::Tolerance (TopoDS::Edge(aS2));
196       if (aDist > aTol1 + aTol2) continue;
197
198       // avoid to process the same points twice
199       gp_Pnt aPnt1 = aExtrema.PointOnShape1(i);
200       gp_Pnt aPnt2 = aExtrema.PointOnShape2(i);
201       Standard_Integer j;
202       for (j=1; j<=thePoints1.Length(); j++) {
203         if (aPnt1.IsEqual(thePoints1(j),Precision::Confusion()) &&
204             aPnt2.IsEqual(thePoints2(j),Precision::Confusion())) {
205 //        if(anIsOnSurface && (theEdgeOnSurface(j) == 1))  break;
206 //        if(!anIsOnSurface && (theEdgeOnSurface(j) == 0))  break;
207           break;
208         }
209       }
210       if (j > aN && j <= thePoints1.Length()) continue;
211       if (j <= aN) {
212         thePoints1.Remove(j);
213         thePoints2.Remove(j);
214         theEdgeOnSurface.Remove(j);
215         InsertVertexInBoundary = Standard_False;
216         aN--;
217       }
218       thePoints1.Append (aPnt1);
219       thePoints2.Append (aPnt2);
220       theEdgeOnSurface.Append(anIsOnSurface ? 1 : 0);
221       // find or make the intersection vertex
222       TopoDS_Vertex aVerInt;
223       if (aS2.ShapeType() == TopAbs_VERTEX)
224         aVerInt = TopoDS::Vertex (aS2);
225       else if (aS1.ShapeType() == TopAbs_VERTEX)
226         aVerInt = TopoDS::Vertex (aS1);
227       else {
228         // make new vertex
229         Standard_Real aTol = Max (aTol1+aDist, aTol2);
230         aBld.MakeVertex (aVerInt, aPnt2, aTol);
231       }
232
233       if (aS1.ShapeType() == TopAbs_VERTEX) {
234         if (!aS1.IsSame(aVerInt) && !theMapSubst.IsBound(aS1)) {
235           // replace vertex from Face with vertex from Edge
236           const TopoDS_Vertex& aVer1 = TopoDS::Vertex(aS1);
237           // update intersection vertex
238           aTol2 = Max (aTol2, aTol1 + aDist);
239 //        Standard_Real aPar = BRep_Tool::Parameter (aVer1, aE);
240           gp_Pnt aP = BRep_Tool::Pnt(aVerInt);
241 //        aBld.UpdateVertex (aVerInt, aPar, aE, aTol2);
242           aBld.UpdateVertex (aVerInt, aP, aTol2);
243           // do substitution
244           TopTools_ListOfShape aList;
245           aList.Append (aVerInt);
246           theMapSubst.Bind (aVer1, aList);
247         }
248       }
249
250       else {    // aS1 is the same edge as aE
251         // insert intersection vertex in edge from Shell as internal
252         Standard_Real aPar;
253         aExtrema.ParOnEdgeS1(i, aPar);
254
255         if (!theMapSubst.IsBound(aS1)) {
256           // for Mandrake-10 - mkv,02.06.06 - theMapSubst.Bind (aE, TopTools_ListOfShape());
257           TopTools_ListOfShape aListOfShape1;
258           theMapSubst.Bind (aE, aListOfShape1);
259         }
260         TopTools_ListOfShape& aListSubst = theMapSubst(aS1);
261         TopoDS_Edge aEdge;
262         Standard_Boolean aListWasEmpty = Standard_False;
263         if (aListSubst.IsEmpty()) {
264           aListWasEmpty = Standard_True;
265           aEdge = TopoDS::Edge (aS1);
266         }
267         else {
268           // find split by parameter
269           TopTools_ListIteratorOfListOfShape aIt (aListSubst);
270           for (; aIt.More(); aIt.Next()) {
271             Standard_Real aParF, aParL;
272             const TopoDS_Edge& aE1 = TopoDS::Edge (aIt.Value());
273             BRep_Tool::Range (aE1, aParF, aParL);
274             if (aParF < aPar && aPar < aParL) {
275               aEdge = aE1;
276               break;
277             }
278           }
279           if (aIt.More()) {
280             aListSubst.Remove (aIt);
281           }
282           else
283             // unusual, needed split not found, skip to next extrema solution
284             continue;
285         }
286
287         if(InsertVertexInBoundary) {
288 //        TopoDS_Edge aNewEdge;
289 //        QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVerInt, aPar, aNewEdge);
290           TopTools_ListOfShape aListE;
291           QANewModTopOpe_Glue::SplitEdgeByVertex (aEdge, aVerInt, aPar, aListE);
292 //        aListSubst.Append (aNewEdge);
293           aListSubst.Append (aListE);
294           if (!theMapGener.IsBound(aS1)) {
295             // for Mandrake-10 - mkv,02.06.06 - theMapGener.Bind(aS1, TopTools_ListOfShape());
296             TopTools_ListOfShape aListOfShape2;
297             theMapGener.Bind(aS1, aListOfShape2);
298           }
299           theMapGener(aS1).Append (aVerInt);
300         }
301         else {
302           if(!aListWasEmpty) aListSubst.Append(aEdge);
303         }
304       }
305
306       Standard_Boolean isS2InternalVertex =
307         (aS2.ShapeType() == TopAbs_VERTEX && aS2.Orientation() == TopAbs_INTERNAL);
308
309       if (aS2.ShapeType() == TopAbs_EDGE || isS2InternalVertex) {
310         // split theEdge
311         Standard_Real aPar;
312         if (isS2InternalVertex)
313           aPar = BRep_Tool::Parameter (aVerInt, theEdge);
314         else
315           aExtrema.ParOnEdgeS2(i, aPar);
316
317         TopoDS_Edge aEdge;
318         if (theListE.IsEmpty()) {
319           aEdge = theEdge;
320         }
321         else {
322           // find split by parameter
323           TopTools_ListIteratorOfListOfShape aIt (theListE);
324           for (; aIt.More(); aIt.Next()) {
325             Standard_Real aParF, aParL;
326             const TopoDS_Edge& aE1 = TopoDS::Edge (aIt.Value());
327             BRep_Tool::Range (aE1, aParF, aParL);
328             if (aParF < aPar && aPar < aParL) {
329               aEdge = aE1;
330               break;
331             }
332           }
333           if (aIt.More())
334             theListE.Remove (aIt);
335           else
336             // unusual, needed split not found, skip to next extrema solution
337             continue;
338         }
339
340         TopTools_ListOfShape aListE;
341         if(anIsOnSurface && IsNotInternal) {
342           // split aEdge
343           QANewModTopOpe_Glue::SplitEdgeByVertex (aEdge, aVerInt, aPar, aListE);
344           theListE.Append (aListE);
345         }
346         else {
347           //insert internal vertex in aEdge
348           if(!isS2InternalVertex) {
349             TopoDS_Edge aNewEdge;
350 //          QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVerInt, aPar, aNewEdge);
351             QANewModTopOpe_Glue::SplitEdgeByVertex (aEdge, aVerInt, aPar, aListE);
352 //          theListE.Append(aNewEdge);
353             theListE.Append (aListE);
354             if (!theMapGener.IsBound(aS2)) {
355               // for Mandrake-10 - mkv,02.06.06 - theMapGener.Bind(aS2, TopTools_ListOfShape());
356               TopTools_ListOfShape aListOfShape3;
357               theMapGener.Bind(aS2, aListOfShape3);
358             }
359             theMapGener(aS2).Append (aVerInt);
360           }
361         } 
362           
363       }
364     }
365     
366   }
367
368   // treatmen intersection points
369   //   insert internal vertices in face 
370   TopTools_ListIteratorOfListOfShape aIt (aListOfIntVert);
371   gp_Pnt aP;
372   Standard_Real aTol;
373   theNewFace = theFace;
374   for(; aIt.More(); aIt.Next()) {
375     aP =  BRep_Tool::Pnt(TopoDS::Vertex(aIt.Value()));
376     aTol = BRep_Tool::Tolerance(TopoDS::Vertex(aIt.Value()));
377     Standard_Integer j;
378     for (j=1; j<=thePoints1.Length(); j++) {
379       if (aP.IsEqual(thePoints1(j),aTol))  break;
380     }
381     if (j <= thePoints1.Length()) continue;
382     thePoints1.Append (aP);
383     thePoints2.Append (aP);
384     theEdgeOnSurface.Append(anIsOnSurface ? 1 : 0);
385
386     // insert internal vertex in face;
387     QANewModTopOpe_Glue aFVGluing(theNewFace, aIt.Value());
388     theNewFace = aFVGluing.Shape();
389   }
390   // insert intersection vertices in face and in edge
391   Standard_Integer k;
392   for(k = 1; k <= aPntOfInter.Length(); k++) {
393     Standard_Integer j;
394     for (j=1; j<=thePoints1.Length(); j++) {
395       if (aPntOfInter(k).IsEqual(thePoints1(j),Precision::Confusion()))  break;
396     }
397     if (j <= thePoints1.Length()) continue;
398     
399     thePoints1.Append (aPntOfInter(k));
400     thePoints2.Append (aPntOfInter(k));
401     theEdgeOnSurface.Append(anIsOnSurface ? 1 : 0);
402
403     Standard_Real aPar = aW(k); 
404     TopoDS_Vertex aV;
405     aBld.MakeVertex (aV, aPntOfInter(k), Precision::Confusion());
406     
407     QANewModTopOpe_Glue aFVGluing(theNewFace, aV);
408     theNewFace = aFVGluing.Shape();
409     if (!theMapGener.IsBound(theFace)) {
410       // for Mandrake-10 - mkv,02.06.06 - theMapGener.Bind(theFace, TopTools_ListOfShape());
411       TopTools_ListOfShape aListOfShape4;
412       theMapGener.Bind(theFace, aListOfShape4);
413     }
414     theMapGener(theFace).Append (aV);
415     
416     TopoDS_Edge aEdge;
417     if (theListE.IsEmpty())
418       aEdge = theEdge;
419     else {
420       // find split by parameter
421       aIt.Initialize (theListE);
422       for (; aIt.More(); aIt.Next()) {
423         Standard_Real aParF, aParL;
424         const TopoDS_Edge& aE1 = TopoDS::Edge (aIt.Value());
425         BRep_Tool::Range (aE1, aParF, aParL);
426         if (aParF < aPar && aPar < aParL) {
427           aEdge = aE1;
428           break;
429         }
430       }
431       if (aIt.More())
432         theListE.Remove (aIt);
433       else
434         // unusual, needed split not found, skip to next intersection solution
435         continue;
436     }
437     
438 //    TopoDS_Edge aNewEdge;
439 //    QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aV, aPar, aNewEdge);
440 //    theListE.Append(aNewEdge);
441     TopTools_ListOfShape aListE;
442     QANewModTopOpe_Glue::SplitEdgeByVertex (aEdge, aV, aPar, aListE);
443     theListE.Append (aListE);
444     if (!theMapGener.IsBound(theEdge)) {
445       // for Mandrake-10 - mkv,02.06.06 - theMapGener.Bind(theEdge, TopTools_ListOfShape());
446       TopTools_ListOfShape aListOfShape5;
447       theMapGener.Bind(theEdge, aListOfShape5);
448     }
449     theMapGener(theEdge).Append (aV);
450     
451   }
452   
453   
454   
455   if (theListE.IsEmpty())
456     theListE.Append (theEdge);
457 }
458
459
460 //=======================================================================
461 //function : ClassifyEdgeFace
462 //purpose  : static
463 //=======================================================================
464
465 static TopAbs_State
466 ClassifyEdgeFace (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace,
467                   TopoDS_Edge& theEdgeOn,
468                   const TopTools_DataMapOfShapeListOfShape& theMapSubst)
469 {
470   Standard_Real aParF, aParL, aTolEdge;
471   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aParF, aParL);
472   if (aCurve.IsNull()) return TopAbs_OUT;
473   aTolEdge = BRep_Tool::Tolerance(theEdge);
474   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
475
476   // define check points
477   Standard_Real aParams[4];
478   Standard_Real aDeltaRange = aParL - aParF;
479   aParams[0] = aParF;
480   aParams[1] = aParF + aDeltaRange * 0.382;
481   aParams[2] = aParF + aDeltaRange * 0.618;
482   aParams[3] = aParL;
483   gp_Pnt   aPnts[4];
484   gp_Pnt2d aPnts2d[4];
485
486   // check distance to the surface
487   Standard_Real aTol = aTolEdge + BRep_Tool::Tolerance(theFace);
488   Standard_Integer i;
489   for (i=0; i < 4; i++) {
490     aPnts[i] = aCurve->Value(aParams[i]);
491     GeomAPI_ProjectPointOnSurf aProjector(aPnts[i], aSurf);
492     if (!aProjector.IsDone() || aProjector.LowerDistance() > aTol)
493       return TopAbs_OUT;
494     Standard_Real u,v;
495     aProjector.LowerDistanceParameters(u,v);
496     aPnts2d[i].SetCoord(u,v);
497   }
498
499   // check distance to edges
500   TopExp_Explorer aExp (theFace, TopAbs_EDGE);
501   for (; aExp.More(); aExp.Next()) {
502     const TopoDS_Shape& aE = aExp.Current();
503 //    if (aE.Orientation() == TopAbs_FORWARD || aE.Orientation() == TopAbs_REVERSED) {
504     if (aE.Orientation() != TopAbs_EXTERNAL) {
505       TopTools_ListOfShape aListSingle;
506       TopTools_ListIteratorOfListOfShape aIt;
507       if (theMapSubst.IsBound(aE)) {
508         aIt.Initialize (theMapSubst(aE));
509       }
510       else {
511         aListSingle.Append (aE);
512         aIt.Initialize (aListSingle);
513       }
514
515       for (; aIt.More(); aIt.Next()) {  // for each split
516         const TopoDS_Edge& aE1 = TopoDS::Edge (aIt.Value());
517         Standard_Real aPF, aPL;
518         Handle(Geom_Curve) aCrv = BRep_Tool::Curve(aE1, aPF, aPL);
519         if (aCrv.IsNull()) continue;
520         Standard_Real aTol1 = aTolEdge + BRep_Tool::Tolerance(aE1);
521
522         for (i=0; i < 4; i++) {
523           GeomAPI_ProjectPointOnCurve aProjector(aPnts[i], aCrv, aPF, aPL);
524           if (aProjector.NbPoints() == 0 || aProjector.LowerDistance() > aTol1)
525             break;
526         }
527         if (i == 4) {   // all points are on an edge
528           theEdgeOn = aE1;
529           return TopAbs_ON;
530         }
531       }
532     }
533   }
534
535   // use 2d face classifier
536 //  BRepClass_FaceClassifier aClf;
537   BRepTopAdaptor_FClass2d aClf(theFace, Precision::PConfusion());
538   for (i=0; i < 4; i++) {
539     if (aClf.Perform (aPnts2d[i]) == TopAbs_OUT)
540       return TopAbs_OUT;
541   }
542
543   return TopAbs_IN;
544 }
545
546 //=======================================================================
547 //function : UpdateEdgeOnFace
548 //purpose  : static
549 //=======================================================================
550
551 static Standard_Boolean
552 UpdateEdgeOnFace (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace)
553 {
554   BRep_Builder aBld;
555   Standard_Real aPF, aPL, aTolEdge;
556   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aPF, aPL);
557   if (aCurve.IsNull()) return Standard_False;
558   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
559   if (aSurf.IsNull()) return Standard_False;
560   aTolEdge = BRep_Tool::Tolerance(theEdge);
561
562   Standard_Real aTolApprox = Max (aTolEdge, BRep_Tool::Tolerance(theFace));
563   Handle(Geom2d_Curve) aCrv2d =  GeomProjLib::Curve2d (aCurve, aPF, aPL, aSurf,
564                                                        aTolApprox);
565   if (!aCrv2d.IsNull()) {
566     aTolEdge = Max (aTolEdge, aTolApprox);
567     aBld.UpdateEdge (theEdge, aCrv2d, theFace, aTolEdge);
568     return Standard_True;
569   }
570   return Standard_False;
571 }
572
573 //=======================================================================
574 //function : PerformShellWire
575 //purpose  : 
576 //=======================================================================
577
578 void
579 QANewModTopOpe_Glue::PerformShellWire() 
580 {
581   TopoDS_Shape& myS1=myArguments.First();
582   TopoDS_Shape& myS2=myTools.First();
583
584   Standard_Boolean anOnlyOneFace = Standard_False;
585   BRep_Builder aBld;
586   if(myS1.ShapeType() == TopAbs_FACE) {
587     TopoDS_Shape aShell;
588     aBld.MakeShell(TopoDS::Shell(aShell));
589     aBld.Add(aShell, myS1);
590     myS1 =  aShell;
591     anOnlyOneFace = Standard_True;
592   }
593
594   if(myS2.ShapeType() == TopAbs_EDGE) {
595     myS2 = BRepBuilderAPI_MakeWire(TopoDS::Edge(myS2));
596   }
597
598   TopoDS_Shape aS1F = myS1.Oriented(TopAbs_FORWARD);
599   TopoDS_Shape aS2F = myS2.Oriented(TopAbs_FORWARD);
600   BRepExtrema_DistShapeShape aExtrema (aS1F, aS2F);
601   if (!aExtrema.IsDone())
602     return;
603
604   TopTools_IndexedDataMapOfShapeListOfShape aMapAnc1;
605   TopExp::MapShapesAndAncestors (aS1F, TopAbs_VERTEX, TopAbs_EDGE, aMapAnc1);
606   TopExp::MapShapesAndAncestors (aS1F, TopAbs_VERTEX, TopAbs_FACE, aMapAnc1);
607   TopExp::MapShapesAndAncestors (aS1F, TopAbs_EDGE, TopAbs_FACE, aMapAnc1);
608   TopTools_IndexedDataMapOfShapeListOfShape aMapAnc2;
609   TopExp::MapShapesAndAncestors (aS2F, TopAbs_VERTEX, TopAbs_EDGE, aMapAnc2);
610   TopExp::MapShapesAndAncestors (aS2F, TopAbs_EDGE, TopAbs_WIRE, aMapAnc2);
611   TopTools_IndexedDataMapOfShapeListOfShape aMapFE;
612
613   // process extrema points
614   Standard_Boolean anIsCoincided = Standard_False;
615   Standard_Integer nbSol = aExtrema.NbSolution(), i;
616   Standard_Real aDist = aExtrema.Value();
617   for (i=1; i <= nbSol; i++) {
618     TopoDS_Shape aS1 = aExtrema.SupportOnShape1(i);
619     TopoDS_Shape aS2 = aExtrema.SupportOnShape2(i);
620
621     // check distance against tolerances
622     Standard_Real aTol1, aTol2;
623     if (aS1.ShapeType() == TopAbs_VERTEX)
624       aTol1 = BRep_Tool::Tolerance (TopoDS::Vertex(aS1));
625     else if (aS1.ShapeType() == TopAbs_EDGE)
626       aTol1 = BRep_Tool::Tolerance (TopoDS::Edge(aS1));
627     else
628       aTol1 = BRep_Tool::Tolerance (TopoDS::Face(aS1));
629     if (aS2.ShapeType() == TopAbs_VERTEX)
630       aTol2 = BRep_Tool::Tolerance (TopoDS::Vertex(aS2));
631     else
632       aTol2 = BRep_Tool::Tolerance (TopoDS::Edge(aS2));
633     if (aDist > aTol1 + aTol2) continue;
634
635     anIsCoincided = Standard_True;
636
637     // determine contacted faces from Shell and edges from Wire
638     // and remember them in the map
639     TopTools_ListOfShape aListF, aListE;
640     if (aS1.ShapeType() == TopAbs_FACE) {
641       aListF.Append (aS1);
642     }
643     else {
644       TopTools_ListIteratorOfListOfShape aIt (aMapAnc1.FindFromKey(aS1));
645       for (; aIt.More(); aIt.Next())
646         if (aIt.Value().ShapeType() == TopAbs_FACE)
647           aListF.Append (aIt.Value());
648     }
649     if (aS2.ShapeType() == TopAbs_EDGE) {
650       aListE.Append (aS2);
651     }
652     else {
653       TopTools_ListIteratorOfListOfShape aIt (aMapAnc2.FindFromKey(aS2));
654       for (; aIt.More(); aIt.Next())
655         aListE.Append (aIt.Value());
656     }
657     TopTools_ListIteratorOfListOfShape aItF (aListF);
658     for (; aItF.More(); aItF.Next()) {
659       if (!aMapFE.Contains (aItF.Value())) {
660         // for Mandrake-10 - mkv,02.06.06 - aMapFE.Add (aItF.Value(), TopTools_ListOfShape());
661         TopTools_ListOfShape aListOfShape1;
662         aMapFE.Add (aItF.Value(), aListOfShape1);
663       }
664       TopTools_ListOfShape& aLE = aMapFE.ChangeFromKey(aItF.Value());
665       TopTools_MapOfShape aMapE;
666       TopTools_ListIteratorOfListOfShape aItE (aLE);
667       for (; aItE.More(); aItE.Next())
668         aMapE.Add (aItE.Value());
669       for (aItE.Initialize (aListE); aItE.More(); aItE.Next())
670         if (!aMapE.Contains (aItE.Value()))
671           aLE.Append(aItE.Value());
672     }
673   }
674
675
676   if(!anIsCoincided) return;
677
678   // for each touched face make wire and add it in face as internal
679
680   TopTools_MapOfShape aMapUsedEdges;
681   TColgp_SequenceOfPnt aPoints1;
682   TColgp_SequenceOfPnt aPoints2;
683   TColStd_SequenceOfInteger aEdgeOnSurface;
684   TopTools_DataMapOfShapeListOfShape aMapSubst;
685   for (i=1; i <= aMapFE.Extent(); i++) {
686     const TopoDS_Face& aFace = TopoDS::Face (aMapFE.FindKey(i));
687     TopoDS_Shape aNewFace;
688
689     // form the new wire:
690     //   get all edges contacting the face, split them by the face boundary,
691     //   get those splits which are inside the face.
692     Standard_Boolean isWireMade = Standard_False;
693     TopoDS_Shape aWire;
694     aBld.MakeWire (TopoDS::Wire (aWire));
695     TopTools_ListIteratorOfListOfShape aIt (aMapFE(i));
696     for (; aIt.More(); aIt.Next()) {    // for each edge contacting the face
697       const TopoDS_Shape& aEdge = aIt.Value();
698       if (aMapUsedEdges.Contains(aEdge)) continue;
699
700       TopTools_ListOfShape aListSingle;
701       aListSingle.Append (aEdge);
702       TopTools_ListOfShape& aListRef = (aMapSubst.IsBound(aEdge)
703                                         ? aMapSubst(aEdge)
704                                         : aListSingle);
705       TopTools_ListIteratorOfListOfShape aIt1 (aListRef);
706       while (aIt1.More()) {     // for each old split
707         const TopoDS_Edge& aE1 = TopoDS::Edge (aIt1.Value());
708         if (!aMapUsedEdges.Contains(aE1)) {
709           TopTools_ListOfShape aListE;
710           ProcessEdgeFaceInterference (aE1, aFace, aNewFace, aListE, aPoints1, aPoints2,
711                                        aEdgeOnSurface, aMapSubst, myMapGener);
712           TopTools_ListIteratorOfListOfShape aIt2 (aListE);
713           for (aIt2.Initialize(aListE); aIt2.More(); aIt2.Next()) {
714             const TopoDS_Edge& aE2 = TopoDS::Edge (aIt2.Value());
715             TopoDS_Edge aEon;
716             TopAbs_State aState = ClassifyEdgeFace (aE2, aFace, aEon, aMapSubst);
717             if (aState == TopAbs_IN ) {
718               if (UpdateEdgeOnFace (aE2, aFace)) {
719                 isWireMade = Standard_True;
720                 aBld.Add (aWire, aE2);
721                 aMapUsedEdges.Add (aE2);
722                 if (!myMapGener.IsBound(aFace)) {
723                   // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aFace, TopTools_ListOfShape());
724                   TopTools_ListOfShape aListOfShape2;
725                   myMapGener.Bind(aFace, aListOfShape2);
726                 }
727                 myMapGener(aFace).Append (aE2);
728               }
729             }
730             else if(aState == TopAbs_ON) {
731               aMapUsedEdges.Add (aE2);
732             }
733           }
734           Standard_Boolean IsTheSame = Standard_False;
735           if(aListE.Extent() == 1) {
736             IsTheSame = aE1.IsSame(aListE.First());
737           }
738           if (aListE.Extent() > 1 || !IsTheSame) {
739             // replace old split with new splits
740             if (aMapSubst.IsBound(aEdge)) {
741               aListRef.InsertBefore (aListE, aIt1);
742               aListRef.Remove (aIt1);
743               continue;
744             }
745             else aMapSubst.Bind (aEdge, aListE);
746           }
747         }
748         aIt1.Next();
749       }
750     }
751
752     if(!aNewFace.IsSame(aFace) && !aNewFace.IsNull()) {
753       if(!aMapSubst.IsBound(aFace)) {
754         // for Mandrake-10 - mkv,02.06.06 - aMapSubst.Bind (aFace, TopTools_ListOfShape());
755         TopTools_ListOfShape aListOfShape3;
756         aMapSubst.Bind (aFace, aListOfShape3);
757       }
758       aMapSubst(aFace).Append(aNewFace);
759     }
760   
761     if (isWireMade) {
762       // add new wire to face
763       TopoDS_Shape aDummy = aNewFace.EmptyCopied().Oriented(TopAbs_FORWARD);
764       TopoDS_Face aNewFace1 = TopoDS::Face (aDummy);
765       aBld.NaturalRestriction (aNewFace1, BRep_Tool::NaturalRestriction(aFace));
766       TopoDS_Iterator aIterF (aNewFace, Standard_False);
767       for (; aIterF.More(); aIterF.Next()) {
768         aBld.Add (aNewFace1, aIterF.Value());
769       }
770       aWire = FindWireOrUpdateMap (aWire, aMapAnc2);
771       aBld.Add (aNewFace1, aWire.Oriented(TopAbs_INTERNAL));
772       // do substitution
773       TopTools_ListOfShape aList;
774       aList.Append (aNewFace1.Oriented(aFace.Orientation()));
775       if(aMapSubst.IsBound(aFace)) aMapSubst.UnBind(aFace);
776       aMapSubst.Bind (aFace, aList);
777     }
778   }
779
780   // make wires from the left edges
781
782 //  if (!aMapUsedEdges.IsEmpty()) {
783     Handle(BRepAlgo_EdgeConnector) aConnector = new BRepAlgo_EdgeConnector;
784 //    TopoDS_Iterator aIterW (myS2, Standard_False);
785     TopExp_Explorer anExpW (myS2, TopAbs_EDGE);
786     for (; anExpW.More(); anExpW.Next()) {
787       const TopoDS_Edge& aEdge = TopoDS::Edge (anExpW.Current());
788       if (aMapUsedEdges.Contains(aEdge)) continue;
789
790       if (aMapSubst.IsBound(aEdge)) {
791         TopTools_ListIteratorOfListOfShape aIt (aMapSubst(aEdge));
792         for (; aIt.More(); aIt.Next()) {        // for each old split
793           if (aMapUsedEdges.Contains(aIt.Value())) continue;
794           aConnector->Add (TopoDS::Edge(aIt.Value()));
795           aConnector->AddStart (TopoDS::Edge(aIt.Value()));
796         }
797       }
798       else {
799         aConnector->Add (aEdge);
800         aConnector->AddStart (aEdge);
801       }
802     }
803
804     // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind (myS2, TopTools_ListOfShape());
805     TopTools_ListOfShape aListOfShape4;
806     myMapModif.Bind (myS2, aListOfShape4);
807     TopTools_ListOfShape& aListW = aConnector->MakeBlock();
808     if (aConnector->IsDone()) {
809 //      TopAbs_Orientation aOri = myS2.Orientation();
810       TopTools_ListIteratorOfListOfShape aIt (aListW);
811 //      for (; aIt.More(); aIt.Next()) aIt.Value().Orientation(aOri);
812       myMapModif(myS2).Append (aListW);
813     }
814 //  }
815
816   // construct the result
817
818   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aIterM(aMapSubst);
819
820   for (; aIterM.More(); aIterM.Next()) {
821     TopAbs_Orientation aOri = TopAbs_FORWARD;
822     TopTools_ListIteratorOfListOfShape aIt (aIterM.Value());
823     for (; aIt.More(); aIt.Next()) aIt.Value().Orientation(aOri);
824     if(!aIterM.Value().IsEmpty()) mySubst.Substitute (aIterM.Key(), aIterM.Value());
825     aOri = aIterM.Key().Orientation();
826     aIt.Initialize (aIterM.Value());
827     for (; aIt.More(); aIt.Next()) aIt.Value().Orientation(aOri);
828     if(!aIterM.Value().IsEmpty()) myMapModif.Bind (aIterM.Key(), aIterM.Value());
829   }
830
831   if(anIsCoincided) {
832     TopoDS_Shape aNewS1 = myS1;
833     mySubst.Build(myS1);
834     if (mySubst.IsCopied(myS1)) {
835       aNewS1 = mySubst.Copy(myS1).First();
836       if(aNewS1.ShapeType() == TopAbs_SHELL && anOnlyOneFace) {
837         TopoDS_Iterator anIter(aNewS1);
838         aNewS1 = anIter.Value();
839       }
840       aNewS1.Orientation(myS1.Orientation());
841     }
842
843     if (myMapModif.IsBound (myS2) && myMapModif(myS2).IsEmpty()) {
844       // all wire is on shell
845       myShape = aNewS1;
846       myMapModif.UnBind (myS2);
847     }
848     else {
849       // all wire or part of wire is out of shell
850       aBld.MakeCompound (TopoDS::Compound(myShape));
851       aBld.Add(myShape, aNewS1);
852       if (myMapModif.IsBound (myS2)) {
853         TopTools_ListIteratorOfListOfShape aIt (myMapModif(myS2));
854         for (; aIt.More(); aIt.Next()) {
855           // check if wire contains only one edge
856           TopoDS_Iterator aTDIt(aIt.Value());
857           TopoDS_Shape anE = aTDIt.Value();
858           aTDIt.Next();
859           if(aTDIt.More()) aBld.Add (myShape, aIt.Value());
860           else aBld.Add (myShape, anE);
861         }
862       }
863       else aBld.Add (myShape, myS2);
864     }
865
866     Done();
867   }
868 }
869
870 //=======================================================================
871 //function : IsOverlapped
872 //purpose  : Checks if theEdge2 lies on theEdge1. It is known that the
873 //           boundary vertices of theEdge2 lie on theEdge1.
874 //=======================================================================
875
876 static Standard_Boolean IsOverlapped(const TopoDS_Edge &theEdge1,
877                                      const TopoDS_Edge &theEdge2)
878 {
879   Standard_Real      aParF1, aParL1;
880   Standard_Real      aParF2, aParL2;
881   Handle(Geom_Curve) aC1 = BRep_Tool::Curve(theEdge1, aParF1, aParL1);
882   Handle(Geom_Curve) aC2 = BRep_Tool::Curve(theEdge2, aParF2, aParL2);
883
884   if (aC1.IsNull() || aC2.IsNull())
885     return Standard_False;
886
887   GeomAdaptor_Curve aGAC1(aC1, aParF1, aParL1);
888   GeomAdaptor_Curve aGAC2(aC2, aParF2, aParL2);
889   Extrema_ExtPC     anExtPC;
890   Standard_Integer  aNbPoints = 5;
891   Standard_Real     aDelta    = (aParL2 - aParF2)/(aNbPoints + 1.);
892   Standard_Real     aCurPar   = aParF2 + aDelta;
893   Standard_Integer  i;
894   Standard_Real     aMaxDist  = Max(BRep_Tool::Tolerance(theEdge1),
895                                     BRep_Tool::Tolerance(theEdge2));
896
897   anExtPC.Initialize(aGAC1, aParF1, aParL1);
898
899   for (i = 1; i <= aNbPoints; i++) {
900     gp_Pnt aPnt = aGAC2.Value(aCurPar);
901
902     anExtPC.Perform(aPnt);
903
904     if (!anExtPC.IsDone())
905       return Standard_False;
906
907     Standard_Integer j;
908     Standard_Integer aNbExt = anExtPC.NbExt();
909     Standard_Boolean isPOnC1 = Standard_False;
910
911     for (j = 1; j <= aNbExt && !isPOnC1; j++) {
912       if (anExtPC.IsMin(j)) {
913         gp_Pnt anExtP = anExtPC.Point(j).Value();
914
915         isPOnC1 = (aPnt.Distance(anExtP) <= aMaxDist);
916       }
917     }
918     if (!isPOnC1)
919       return Standard_False;
920
921     aCurPar += aDelta;
922   }
923
924   return Standard_True;
925 }
926
927 //=======================================================================
928 //function : SplitEdge
929 //purpose  : This function splits the edge into subedges by two given vertices.
930 //=======================================================================
931
932 static void SplitEdge(const TopoDS_Edge                &theEdge,
933                       const TopTools_IndexedMapOfShape &theVertices,
934                             TopTools_ListOfShape       &theSplits)
935 {
936   //const TopoDS_Edge   aNewEdge;
937   TopoDS_Vertex aV1;
938   TopoDS_Vertex aV2;
939   BRep_Builder  aBuilder;
940
941   TopoDS_Edge aNewEdge = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD).EmptyCopied());
942   TopExp::Vertices(theEdge, aV1, aV2);
943   aBuilder.Add(aNewEdge, aV1);
944   
945 // Construction of the copied edge with
946 // the internal vertices of the map theVertices.
947
948   Standard_Integer i;
949
950   for (i = 1; i <= theVertices.Extent(); i++) 
951   {
952     const TopoDS_Shape &theVtx = theVertices.FindKey(i);
953
954     if (!aV1.IsSame(theVtx) && !aV2.IsSame(theVtx))
955       aBuilder.Add(aNewEdge, theVtx.Oriented(TopAbs_INTERNAL));
956   }
957
958   aBuilder.Add(aNewEdge, aV2);
959
960   theSplits.Clear();
961
962   // Splitting of the new edge.
963   if (!TopOpeBRepTool_TOOL::SplitE(aNewEdge, theSplits)) {
964     theSplits.Clear();
965     theSplits.Append(theEdge);
966
967     return;
968   }
969
970   // Addition of the other internal vertices into the corresponding splits.
971   TopoDS_Iterator anIter(theEdge, Standard_False);
972
973   for (; anIter.More(); anIter.Next()) 
974   {
975     TopoDS_Vertex aCurVtx = TopoDS::Vertex(anIter.Value());
976
977     // for each vertex which is not the same as aV1, aV2, theIntV1 or theIntV2.
978     if (!aCurVtx.IsSame(aV1) && !aCurVtx.IsSame(aV2) && !theVertices.Contains(aCurVtx)) 
979     {
980       TopTools_ListIteratorOfListOfShape anEdgeIter(theSplits);
981       Standard_Real aCurPar = BRep_Tool::Parameter(aCurVtx, theEdge);
982
983       // Search for the split the current vertex belongs to.
984       for (; anEdgeIter.More(); anEdgeIter.Next()) 
985       {
986         TopoDS_Edge   anEdge = TopoDS::Edge(anEdgeIter.Value());
987         Standard_Real aFPar;
988         Standard_Real aLPar;
989
990         BRep_Tool::Range(anEdge, aFPar, aLPar);
991
992         if (aCurPar > aFPar && aCurPar < aLPar) 
993         {
994           aBuilder.Add(anEdge, aCurVtx);
995           break;
996         }
997       }
998     }
999   }
1000
1001 // Setting the orientation of each split equal to the orientation of theEdge.
1002   TopTools_ListIteratorOfListOfShape anEdgeIter(theSplits);
1003   TopAbs_Orientation                 anOri = theEdge.Orientation();
1004
1005   for (; anEdgeIter.More(); anEdgeIter.Next()) 
1006   {
1007     TopoDS_Shape &anEdge = anEdgeIter.Value();
1008     anEdge.Orientation(anOri);
1009   }
1010 }
1011
1012 //=======================================================================
1013 //function : RemoveCommonPart
1014 //purpose  : 
1015 //=======================================================================
1016
1017 static void RemoveCommonPart
1018                         (const TopoDS_Edge                        &theE1,
1019                          const TopoDS_Edge                        &theE2,
1020                                TopTools_DataMapOfShapeListOfShape &theMapSubst)
1021 {
1022   if (theMapSubst.IsBound(theE1)) {
1023     const TopTools_ListOfShape         &aLOfE1 = theMapSubst.Find(theE1);
1024     TopTools_ListIteratorOfListOfShape  anIter(aLOfE1);
1025
1026 // For each split in the list aLOfE1 recursively call this function.
1027     for (; anIter.More(); anIter.Next()) {
1028       TopoDS_Edge anEdge1 = TopoDS::Edge(anIter.Value());
1029
1030       RemoveCommonPart(anEdge1, theE2, theMapSubst);
1031     }
1032
1033     return;
1034   }
1035
1036   if (theMapSubst.IsBound(theE2)) {
1037     const TopTools_ListOfShape         &aLOfE2 = theMapSubst.Find(theE2);
1038     TopTools_ListIteratorOfListOfShape  anIter(aLOfE2);
1039
1040 // For each split in the list aLOfE2 recursively call this function.
1041     for (; anIter.More(); anIter.Next()) {
1042       TopoDS_Edge anEdge2 = TopoDS::Edge(anIter.Value());
1043
1044       RemoveCommonPart(theE1, anEdge2, theMapSubst);
1045     }
1046
1047     return;
1048   }
1049
1050   TopTools_IndexedMapOfShape aMapVtx;
1051   TopTools_IndexedMapOfShape aMapCommonVtx;
1052
1053 // Searching for common vertices:
1054   TopExp::MapShapes(theE1, aMapVtx);
1055   TopoDS_Iterator anIter(theE2, Standard_False);
1056
1057   for (; anIter.More(); anIter.Next()) {
1058     TopoDS_Shape aVtx = anIter.Value();
1059
1060     if (aMapVtx.Contains(aVtx)) {
1061       aMapCommonVtx.Add(aVtx);
1062     }
1063   }
1064
1065 // If there are at least two common vertices we can check overlapping:
1066   if (aMapCommonVtx.Extent() <= 1)
1067     return;
1068
1069   TopTools_ListOfShape aSplits;
1070
1071   SplitEdge(theE2, aMapCommonVtx, aSplits);
1072
1073   TopTools_ListIteratorOfListOfShape aSplitIter(aSplits);
1074   Standard_Boolean                   isModified = Standard_False;
1075
1076   for (; aSplitIter.More();) {
1077     TopoDS_Edge aSplit = TopoDS::Edge(aSplitIter.Value());
1078
1079     if (IsOverlapped(theE1, aSplit)) {
1080 // Removal of overlapping split from the list of splits
1081       aSplits.Remove(aSplitIter);
1082       isModified = Standard_True;
1083     } else {
1084       aSplitIter.Next();
1085     }
1086   }
1087
1088 // If we deleted some splits, we should save the splits
1089 // of theE2 in order to use them in further overlapping checks.
1090   if (isModified)
1091     theMapSubst.Bind(theE2, aSplits);
1092 }
1093
1094 //=======================================================================
1095 //function : GetSplits
1096 //purpose  : This function removes returns the splits build from theEdge.
1097 //           If there are no ones the edge itself will be added to theSplits.
1098 //=======================================================================
1099
1100 static void GetSplits(const TopoDS_Shape                       &theEdge,
1101                       const TopTools_DataMapOfShapeListOfShape &theMapSubst,
1102                             TopTools_ListOfShape               &theSplits)
1103 {
1104   if (theMapSubst.IsBound(theEdge)) {
1105     const TopTools_ListOfShape         &theList =
1106                                            theMapSubst.Find(theEdge);
1107     TopTools_ListIteratorOfListOfShape  anEdgeIter(theList);
1108
1109     for (; anEdgeIter.More(); anEdgeIter.Next()) {
1110       const TopoDS_Shape &anEdge = anEdgeIter.Value();
1111
1112       GetSplits(anEdge, theMapSubst, theSplits);
1113     }
1114   } else {
1115     theSplits.Append(theEdge);
1116   }
1117 }
1118
1119 //=======================================================================
1120 //function : isWireModified
1121 //purpose  : Checks if the given wire was modified.
1122 //=======================================================================
1123
1124 static Standard_Boolean isWireModified
1125                         (const TopoDS_Shape                       &theWire,
1126                          const TopTools_DataMapOfShapeListOfShape &theMapSubst)
1127 {
1128   TopExp_Explorer anExp(theWire, TopAbs_EDGE);
1129
1130   for(; anExp.More(); anExp.Next()) {
1131     const TopoDS_Shape &anEdge = anExp.Current();
1132
1133     if (theMapSubst.IsBound(anEdge))
1134       return Standard_True;
1135   }
1136
1137   return Standard_False;
1138 }
1139
1140 //=======================================================================
1141 //function : RemoveOverlappedEdges
1142 //purpose  : This function removes doubled common parts of edges from theS2.
1143 //=======================================================================
1144
1145 static TopoDS_Shape RemoveOverlappedEdges
1146                     (const TopoDS_Shape                       &theS1, 
1147                      const TopoDS_Shape                       &theS2,
1148                            TopTools_DataMapOfShapeListOfShape &theMapModif)
1149 {
1150   TopExp_Explorer                    anExp1(theS1, TopAbs_EDGE);
1151   TopTools_DataMapOfShapeListOfShape aMapModif;
1152
1153 // For each couple of edges we remove a common part if any.
1154   for(; anExp1.More(); anExp1.Next()) {
1155     TopoDS_Edge     anEdge1 = TopoDS::Edge(anExp1.Current());
1156     TopExp_Explorer anExp2(theS2, TopAbs_EDGE);
1157
1158     for(; anExp2.More(); anExp2.Next()) {
1159       TopoDS_Edge anEdge2 = TopoDS::Edge(anExp2.Current());
1160
1161       RemoveCommonPart(anEdge1, anEdge2, aMapModif);
1162     }
1163   }
1164
1165 // Searching for built splits for every edge.
1166   TopoDS_Shape    aNewS;
1167   TopoDS_Shape    aNewS2;
1168   BRep_Builder    aBuilder;
1169
1170   aBuilder.MakeCompound(TopoDS::Compound(aNewS));
1171   aBuilder.MakeCompound(TopoDS::Compound(aNewS2));
1172   aBuilder.Add(aNewS, theS1);
1173
1174   TopExp_Explorer anExpWire(theS2, TopAbs_WIRE);
1175
1176   for(; anExpWire.More(); anExpWire.Next()) {
1177     const TopoDS_Shape &aWire = anExpWire.Current();
1178
1179     if (isWireModified(aWire, aMapModif)) {
1180       TopExp_Explorer anExpEdge(aWire, TopAbs_EDGE);
1181       TopoDS_Shape    aNewComp;
1182
1183       aBuilder.MakeCompound(TopoDS::Compound(aNewComp));
1184
1185       for(; anExpEdge.More(); anExpEdge.Next()) {
1186         const TopoDS_Shape   &anEdge = anExpEdge.Current();
1187         TopTools_ListOfShape  aSplits;
1188
1189         GetSplits(anEdge, aMapModif, aSplits);
1190
1191         if (!aSplits.IsEmpty() && !anEdge.IsSame(aSplits.First())) {
1192           if (!theMapModif.IsBound(anEdge))
1193             theMapModif.Bind(anEdge, aSplits);
1194         } else if (aSplits.IsEmpty()) {
1195             theMapModif.Bind(anEdge, aSplits);
1196         }
1197
1198         TopTools_ListIteratorOfListOfShape aSplitIter(aSplits);
1199
1200         for (; aSplitIter.More(); aSplitIter.Next()) {
1201           const TopoDS_Shape &aSplit = aSplitIter.Value();
1202
1203           aBuilder.Add(aNewComp, aSplit);
1204         }
1205       }
1206
1207 // Addition of new compound if it is not empty
1208       TopoDS_Iterator aSubShIter(aNewComp);
1209
1210       if (aSubShIter.More())
1211         aBuilder.Add(aNewS2, aNewComp);
1212     } else {
1213       aBuilder.Add(aNewS2, aWire);
1214     }
1215   }
1216
1217 // Addition of new shape if it is not empty
1218   TopoDS_Iterator aSubShIter(aNewS2);
1219
1220   if (aSubShIter.More())
1221     aBuilder.Add(aNewS, aNewS2);
1222
1223   return aNewS;
1224 }
1225
1226 //=======================================================================
1227 //function : FillMapModif
1228 //purpose  : This function fills the map of modified sub-shapes of theShape
1229 //=======================================================================
1230
1231 static void FillMapModif(const BRepTools_Substitution       &theSubst,
1232                          const TopoDS_Shape                 &theShape,
1233                          TopTools_DataMapOfShapeListOfShape &theMapModif)
1234 {
1235   TopAbs_ShapeEnum aType = theShape.ShapeType();
1236
1237   if (aType == TopAbs_EDGE || aType == TopAbs_VERTEX) {
1238     if (theSubst.IsCopied(theShape)) {
1239       const TopTools_ListOfShape &aModifShapes = theSubst.Copy(theShape);
1240
1241       if (!theMapModif.IsBound(theShape))
1242         theMapModif.Bind(theShape, aModifShapes);
1243     }
1244   }
1245
1246   TopoDS_Iterator     anIter(theShape, Standard_False);
1247   TopTools_MapOfShape aUsedShapes;
1248
1249   for (; anIter.More(); anIter.Next()) {
1250     const TopoDS_Shape &aSubShape = anIter.Value();
1251
1252     if (!aUsedShapes.Add(aSubShape))
1253       continue;
1254
1255     FillMapModif(theSubst, aSubShape, theMapModif);
1256   }
1257 }
1258
1259 //=======================================================================
1260 //function : PerformWires
1261 //purpose  : gluing two wires
1262 //=======================================================================
1263
1264 void
1265 QANewModTopOpe_Glue::PerformWires() 
1266 {
1267   TopoDS_Shape& myS1=myArguments.First();
1268   TopoDS_Shape& myS2=myTools.First();
1269
1270   Standard_Boolean S1IsEdge = Standard_False, S2IsEdge = Standard_False;
1271   if(myS1.ShapeType() == TopAbs_EDGE) {
1272     myS1 = BRepBuilderAPI_MakeWire(TopoDS::Edge(myS1));
1273     S1IsEdge = Standard_True;
1274   }
1275   if(myS2.ShapeType() == TopAbs_EDGE) {
1276     myS2 = BRepBuilderAPI_MakeWire(TopoDS::Edge(myS2));
1277     S2IsEdge = Standard_True;
1278   }
1279
1280   TopoDS_Shape aS1F = myS1.Oriented(TopAbs_FORWARD);
1281   TopoDS_Shape aS2F = myS2.Oriented(TopAbs_FORWARD);
1282   BRepExtrema_DistShapeShape aExtrema (aS1F, aS2F);
1283   if (!aExtrema.IsDone())
1284     return;
1285
1286   // process extrema points
1287
1288   TColStd_SequenceOfInteger VVInt;
1289   TColStd_SequenceOfInteger VEInt;
1290   TColStd_SequenceOfInteger EEInt;
1291   
1292
1293   Standard_Boolean anIsCoincided = Standard_False;
1294   Standard_Boolean S1IsVert = Standard_True;
1295   Standard_Boolean S2IsVert = Standard_True;
1296   Standard_Real aTol1, aTol2;
1297   Standard_Integer nbSol = aExtrema.NbSolution(), i, j, k;
1298   Standard_Real aDist = aExtrema.Value();
1299   for (i=1; i <= nbSol; i++) {
1300     TopoDS_Shape aS1 = aExtrema.SupportOnShape1(i);
1301     TopoDS_Shape aS2 = aExtrema.SupportOnShape2(i);
1302     S1IsVert = Standard_True;
1303     S2IsVert = Standard_True;
1304     // check distance against tolerances
1305      if (aS1.ShapeType() == TopAbs_VERTEX)
1306       aTol1 = BRep_Tool::Tolerance (TopoDS::Vertex(aS1));
1307     else {
1308       aTol1 = BRep_Tool::Tolerance (TopoDS::Edge(aS1));
1309       S1IsVert = Standard_False;
1310     }
1311
1312     if (aS2.ShapeType() == TopAbs_VERTEX)
1313       aTol2 = BRep_Tool::Tolerance (TopoDS::Vertex(aS2));
1314     else {
1315       aTol2 = BRep_Tool::Tolerance (TopoDS::Edge(aS2));
1316       S2IsVert = Standard_False;
1317     }
1318
1319     if (aDist > aTol1 + aTol2) continue;
1320
1321     anIsCoincided = Standard_True;
1322
1323     if(S1IsVert && S2IsVert) {
1324       if(!aS1.IsSame(aS2)) VVInt.Append(i);
1325     }
1326     else if(S1IsVert || S2IsVert)
1327       VEInt.Append(i);
1328     else 
1329       EEInt.Append(i);
1330   }
1331
1332   if(!anIsCoincided) return;
1333
1334   BRep_Builder aBld;
1335   TColgp_SequenceOfPnt aPoints1;
1336   TColgp_SequenceOfPnt aPoints2;
1337   TopTools_DataMapOfShapeListOfShape aMapSubst;
1338
1339   for(k = 1; k <= VVInt.Length(); k++) {
1340     // avoid to process the same points twice
1341     i = VVInt(k);
1342     gp_Pnt aPnt1 = aExtrema.PointOnShape1(i);
1343     gp_Pnt aPnt2 = aExtrema.PointOnShape2(i);
1344     for (j=1; j<=aPoints1.Length(); j++) {
1345       if (aPnt1.IsEqual(aPoints1(j),Precision::Confusion()) &&
1346           aPnt2.IsEqual(aPoints2(j),Precision::Confusion())) {
1347         break;
1348       }
1349     }
1350     if (j <= aPoints1.Length()) continue;
1351     aPoints1.Append (aPnt1);
1352     aPoints2.Append (aPnt2);
1353
1354     const TopoDS_Vertex& aVer1 = TopoDS::Vertex(aExtrema.SupportOnShape1(i));
1355     const TopoDS_Vertex& aVer2 = TopoDS::Vertex(aExtrema.SupportOnShape2(i));
1356     aTol1 = BRep_Tool::Tolerance(aVer1);
1357     aTol2 = BRep_Tool::Tolerance(aVer2);
1358     aTol1 = Max(aTol1, aTol2 + aDist);
1359     gp_Pnt aP = BRep_Tool::Pnt(aVer1);
1360     aBld.UpdateVertex (aVer1, aP, aTol1);
1361     TopTools_ListOfShape aList;
1362     aList.Append (aVer1);
1363     aMapSubst.Bind (aVer2, aList);
1364     
1365   }
1366
1367   for(k = 1; k <= VEInt.Length(); k++) {
1368     // avoid to process the same points twice
1369     i = VEInt(k);
1370     gp_Pnt aPnt1 = aExtrema.PointOnShape1(i);
1371     gp_Pnt aPnt2 = aExtrema.PointOnShape2(i);
1372     for (j=1; j<=aPoints1.Length(); j++) {
1373       if (aPnt1.IsEqual(aPoints1(j),Precision::Confusion()) &&
1374           aPnt2.IsEqual(aPoints2(j),Precision::Confusion())) {
1375         break;
1376       }
1377     }
1378     if (j <= aPoints1.Length()) continue;
1379     aPoints1.Append (aPnt1);
1380     aPoints2.Append (aPnt2);
1381
1382     TopoDS_Shape aS1 = aExtrema.SupportOnShape1(i);
1383     TopoDS_Shape aS2 = aExtrema.SupportOnShape2(i);
1384
1385     if(aS1.ShapeType() == TopAbs_VERTEX) {
1386       TopoDS_Vertex& aVer1 = TopoDS::Vertex(aS1);
1387       const TopoDS_Edge& aE2 = TopoDS::Edge(aS2);
1388       aTol1 = BRep_Tool::Tolerance(aVer1);
1389       aTol2 = BRep_Tool::Tolerance(aE2);
1390       aTol1 = Max(aTol1, aTol2 + aDist);
1391       gp_Pnt aP = BRep_Tool::Pnt(aVer1);
1392       aBld.UpdateVertex (aVer1, aP, aTol1);
1393       Standard_Real aPar;
1394       aExtrema.ParOnEdgeS2(i, aPar);
1395       if (!aMapSubst.IsBound(aE2)) {
1396         // for Mandrake-10 - mkv,02.06.06 - aMapSubst.Bind (aE2, TopTools_ListOfShape());
1397         TopTools_ListOfShape aListOfShape1;
1398         aMapSubst.Bind (aE2, aListOfShape1);
1399       }
1400       TopTools_ListOfShape& aListSubst = aMapSubst(aE2);
1401       TopoDS_Edge aEdge;
1402       if (aListSubst.IsEmpty()) {
1403         aEdge = aE2;
1404       }
1405       else {
1406         aEdge = TopoDS::Edge(aListSubst.First());
1407         aListSubst.Clear();
1408       }
1409
1410       TopoDS_Edge aNewEdge;
1411       QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVer1, aPar, aNewEdge);
1412       aListSubst.Append (aNewEdge);
1413     }
1414     else {
1415       TopoDS_Vertex& aVer1 = TopoDS::Vertex(aS2);
1416       const TopoDS_Edge& aE2 = TopoDS::Edge(aS1);
1417       aTol1 = BRep_Tool::Tolerance(aVer1);
1418       aTol2 = BRep_Tool::Tolerance(aE2);
1419       aTol1 = Max(aTol1, aTol2 + aDist);
1420       gp_Pnt aP = BRep_Tool::Pnt(aVer1);
1421       aBld.UpdateVertex (aVer1, aP, aTol1);
1422       Standard_Real aPar;
1423       aExtrema.ParOnEdgeS1(i, aPar);
1424       if (!aMapSubst.IsBound(aE2)) {
1425         // for Mandrake-10 - mkv,02.06.06 - aMapSubst.Bind (aE2, TopTools_ListOfShape());
1426         TopTools_ListOfShape aListOfShape2;
1427         aMapSubst.Bind (aE2, aListOfShape2);
1428       }
1429       TopTools_ListOfShape& aListSubst = aMapSubst(aE2);
1430       TopoDS_Edge aEdge;
1431       if (aListSubst.IsEmpty()) {
1432         aEdge = aE2;
1433       }
1434       else {
1435         aEdge = TopoDS::Edge(aListSubst.First());
1436         aListSubst.Clear();
1437       }
1438
1439       TopoDS_Edge aNewEdge;
1440       QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVer1, aPar, aNewEdge);
1441       aListSubst.Append (aNewEdge);
1442     }
1443   }
1444
1445   for(k = 1; k <= EEInt.Length(); k++) {
1446     // avoid to process the same points twice
1447     i = EEInt(k);
1448     gp_Pnt aPnt1 = aExtrema.PointOnShape1(i);
1449     gp_Pnt aPnt2 = aExtrema.PointOnShape2(i);
1450     for (j=1; j<=aPoints1.Length(); j++) {
1451       if (aPnt1.IsEqual(aPoints1(j),Precision::Confusion()) &&
1452           aPnt2.IsEqual(aPoints2(j),Precision::Confusion())) {
1453         break;
1454       }
1455     }
1456     if (j <= aPoints1.Length()) continue;
1457     aPoints1.Append (aPnt1);
1458     aPoints2.Append (aPnt2);
1459
1460     const TopoDS_Edge& aE1 = TopoDS::Edge(aExtrema.SupportOnShape1(i));
1461     const TopoDS_Edge& aE2 = TopoDS::Edge(aExtrema.SupportOnShape2(i));
1462     
1463     aTol1 = BRep_Tool::Tolerance(aE1);
1464     aTol2 = BRep_Tool::Tolerance(aE2);
1465     gp_Pnt aP((aPnt1.X() + aPnt2.X())*.5, (aPnt1.Y() + aPnt2.Y())*.5, (aPnt1.Z() + aPnt2.Z())*.5);
1466     aTol1 = Max(aTol1+.5*aDist, aTol2+.5*aDist);
1467     aTol1 = Max(aTol1, Precision::Confusion());
1468
1469     TopoDS_Vertex aVer;
1470     aBld.MakeVertex(aVer, aP, aTol1);
1471
1472     Standard_Real aPar;
1473     aExtrema.ParOnEdgeS1(i, aPar);
1474     if (!aMapSubst.IsBound(aE1)) {
1475       // for Mandrake-10 - mkv,02.06.06 - aMapSubst.Bind (aE1, TopTools_ListOfShape());
1476       TopTools_ListOfShape aListOfShape3;
1477       aMapSubst.Bind (aE1, aListOfShape3);
1478     }
1479     TopTools_ListOfShape& aListSubst1 = aMapSubst(aE1);
1480     TopoDS_Edge aEdge;
1481     if (aListSubst1.IsEmpty()) {
1482       aEdge = aE1;
1483     }
1484     else {
1485       aEdge = TopoDS::Edge(aListSubst1.First());
1486       aListSubst1.Clear();
1487     }
1488
1489     TopoDS_Edge aNewEdge;
1490     QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVer, aPar, aNewEdge);
1491     aListSubst1.Append (aNewEdge);
1492
1493     if(!myMapGener.IsBound(aE1)) {
1494       // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aE1, TopTools_ListOfShape());
1495       TopTools_ListOfShape aListOfShape4;
1496       myMapGener.Bind(aE1, aListOfShape4);
1497     }
1498     myMapGener(aE1).Append(aVer);
1499
1500     aExtrema.ParOnEdgeS2(i, aPar);
1501     if (!aMapSubst.IsBound(aE2)) {
1502       // for Mandrake-10 - mkv,02.06.06 - aMapSubst.Bind (aE2, TopTools_ListOfShape());
1503       TopTools_ListOfShape aListOfShape5;
1504       aMapSubst.Bind (aE2, aListOfShape5);
1505     }
1506     TopTools_ListOfShape& aListSubst2 = aMapSubst(aE2);
1507     if (aListSubst2.IsEmpty()) {
1508       aEdge = aE2;
1509     }
1510     else {
1511       aEdge = TopoDS::Edge(aListSubst2.First());
1512       aListSubst2.Clear();
1513     }
1514
1515     QANewModTopOpe_Glue::InsertVertexInEdge (aEdge, aVer, aPar, aNewEdge);
1516     aListSubst2.Append (aNewEdge);
1517
1518     if(!myMapGener.IsBound(aE2)) {
1519       // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aE2, TopTools_ListOfShape());
1520       TopTools_ListOfShape aListOfShape6;
1521       myMapGener.Bind(aE2, aListOfShape6);
1522     }
1523     myMapGener(aE2).Append(aVer);
1524
1525   }
1526
1527   aBld.MakeCompound (TopoDS::Compound(myShape));
1528   aBld.Add(myShape, myS1);
1529   aBld.Add(myShape, myS2);
1530
1531   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aIterM(aMapSubst);
1532   for (; aIterM.More(); aIterM.Next()) {
1533     TopAbs_Orientation aOri = TopAbs_FORWARD;
1534     TopTools_ListIteratorOfListOfShape aIt (aIterM.Value());
1535     for (; aIt.More(); aIt.Next()) aIt.Value().Orientation(aOri);
1536     if(aIterM.Key().ShapeType() == TopAbs_EDGE) {
1537       TopoDS_Edge aEdge = TopoDS::Edge(aIterM.Value().First());
1538       TopTools_ListOfShape& aListSubst = aMapSubst(aIterM.Key());
1539       aListSubst.Clear();
1540       if(!TopOpeBRepTool_TOOL::SplitE(aEdge, aListSubst)) {
1541         aListSubst.Append(aEdge);
1542       }
1543     }
1544     mySubst.Substitute (aIterM.Key(), aIterM.Value());
1545 //     aOri = aIterM.Key().Orientation();
1546 //     aIt.Initialize (aIterM.Value());
1547 //     for (; aIt.More(); aIt.Next()) aIt.Value().Orientation(aOri);
1548 //     myMapModif.Bind (aIterM.Key(), aIterM.Value());
1549   }
1550
1551   mySubst.Build(myShape);
1552
1553   FillMapModif(mySubst, myS1, myMapModif);
1554   FillMapModif(mySubst, myS2, myMapModif);
1555
1556   if (mySubst.IsCopied(myS1) || mySubst.IsCopied(myS2)) {
1557     TopoDS_Shape aNewS1;
1558     TopoDS_Shape aNewS2;
1559
1560     if (mySubst.IsCopied(myS1))
1561       aNewS1 = mySubst.Copy(myS1).First();
1562     else
1563       aNewS1 = myS1;
1564
1565     if(S1IsEdge) {
1566       TopoDS_Iterator aTDIt(aNewS1);
1567       TopoDS_Shape aE = aTDIt.Value();
1568       aTDIt.Next();
1569       if(!aTDIt.More()) aNewS1 = aE;
1570     }
1571
1572     if (mySubst.IsCopied(myS2))
1573       aNewS2 = mySubst.Copy(myS2).First();
1574     else
1575       aNewS2 = myS2;
1576
1577     if(S2IsEdge) {
1578       TopoDS_Iterator aTDIt(aNewS2);
1579       TopoDS_Shape aE = aTDIt.Value();
1580       aTDIt.Next();
1581       if(!aTDIt.More()) aNewS2 = aE;
1582     }
1583
1584     myShape = RemoveOverlappedEdges(aNewS1, aNewS2, myMapModif);
1585   }
1586
1587   Done();
1588 }