0022904: Clean up sccsid variables
[occt.git] / src / QANewModTopOpe / QANewModTopOpe_Glue_shell.cxx
1 // File:        QANewModTopOpe_Glue_shell.cxx
2 // Created:     Tue Jan 16 09:58:04 2001
3 // Author:      Michael SAZONOV <msv@nnov.matra-dtv.fr>
4 // Copyright:    SAMTECH S.A. 2001
5
6 // Lastly modified by :
7 // +---------------------------------------------------------------------------+
8 // !       msv ! Creation                                !16-01-2001! 3.0-00-5!
9 // !       skv ! Adaptation to OCC version 5.0           ! 6-05-2003! 3.0-00-2!
10 // +---------------------------------------------------------------------------+
11
12
13 #include <QANewModTopOpe_Glue.ixx>
14 #include <Precision.hxx>
15 #include <Geom2d_Curve.hxx>
16 #include <Geom_Surface.hxx>
17 #include <GeomAPI_ProjectPointOnSurf.hxx>
18 #include <TopoDS.hxx>
19 #include <TopoDS_Iterator.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepTools.hxx>
22 #include <BRepClass_FaceClassifier.hxx>
23 #include <BRepFeat_SplitShape.hxx>
24 #include <BRepLib.hxx>
25 #include <TopExp.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <TopTools_DataMapOfShapeInteger.hxx>
28 #include <TopTools_ListIteratorOfListOfShape.hxx>
29 #include <TopTools_MapIteratorOfMapOfShape.hxx>
30 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
31 #include <BRepAlgo_EdgeConnector.hxx>
32 #include <TopTools_MapOfShape.hxx>
33 #include <BRep_Builder.hxx>
34 #include <QANewModTopOpe_Tools.hxx>
35 #include <TopTools_IndexedMapOfShape.hxx>
36
37 //=======================================================================
38 //function : SplitEdgeComplete
39 //purpose  : static
40 //=======================================================================
41
42 static void
43 SplitEdgeComplete (const TopoDS_Edge& theEdge,
44                    TopTools_ListOfShape& theListSplits)
45 {
46   struct ParVer {
47     Standard_Real myParF, myParL;
48     TopoDS_Vertex myVerF, myVerL;
49   };
50   ParVer *aParVer = new ParVer[theListSplits.Extent()+1];
51   TopTools_DataMapOfShapeInteger aMapEdgeIPV;
52   TopTools_ListOfShape aListTodo;
53   aListTodo = theListSplits;
54
55   // prepare structures aMapEdgeIPV and aParVer
56
57   aListTodo.Prepend(theEdge);
58   TopTools_ListIteratorOfListOfShape aIter(aListTodo);
59   Standard_Integer iPV;
60   for (iPV=0; aIter.More(); aIter.Next(), iPV++) {
61     const TopoDS_Edge& aEdge = TopoDS::Edge(aIter.Value());
62     TopoDS_Vertex aVer1, aVer2;
63     Standard_Real aPar1, aPar2;
64
65     // compute parameters of first and last vertices of aEdge on theEdge
66
67     TopExp::Vertices(aEdge, aVer1, aVer2);
68
69     if(aVer1.IsNull() || aVer2.IsNull()) {
70       aListTodo.Remove(aIter);
71       TopTools_ListIteratorOfListOfShape aIter1(theListSplits);
72       for (; aIter1.More(); aIter1.Next()) {
73         if(aEdge.IsSame(aIter1.Value())) {
74           theListSplits.Remove(aIter1);
75           break;
76         }
77       }
78       if(aIter.More()) continue;
79       break;
80     }
81
82     if (iPV == 0) {
83       // the vertices of theEdge
84       aPar1 = BRep_Tool::Parameter(aVer1, theEdge);
85       aPar2 = BRep_Tool::Parameter(aVer2, theEdge);
86     }
87     else {
88       Standard_Real aDist;
89       // the vertices of an edge from the source list
90       if (!QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aVer1),
91                                             theEdge, aPar1, aDist)) {
92         // the vertex is out of theEdge => take one from theEdge
93         Standard_Real aPar;
94         if (QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aParVer[0].myVerF),
95                                              aEdge, aPar, aDist)) {
96           aVer1 = aParVer[0].myVerF;
97           aPar1 = aParVer[0].myParF;
98         }
99         else {
100           aVer1 = aParVer[0].myVerL;
101           aPar1 = aParVer[0].myParL;
102         }
103       }
104       if (!QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aVer2),
105                                             theEdge, aPar2, aDist)) {
106         // the vertex is out of theEdge => take one from theEdge
107         Standard_Real aPar;
108         if (QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aParVer[0].myVerL),
109                                              aEdge, aPar, aDist)) {
110           aVer2 = aParVer[0].myVerL;
111           aPar2 = aParVer[0].myParL;
112         }
113         else {
114           aVer2 = aParVer[0].myVerF;
115           aPar2 = aParVer[0].myParF;
116         }
117       }
118     }
119     if (aPar1 < aPar2) {
120       aParVer[iPV].myParF = aPar1; aParVer[iPV].myVerF = aVer1;
121       aParVer[iPV].myParL = aPar2; aParVer[iPV].myVerL = aVer2;
122     }
123     else {
124       aParVer[iPV].myParF = aPar2; aParVer[iPV].myVerF = aVer2;
125       aParVer[iPV].myParL = aPar1; aParVer[iPV].myVerL = aVer1;
126       if(iPV != 0) {
127         TopTools_ListIteratorOfListOfShape aIterSplits(theListSplits);
128         for(; aIterSplits.More(); aIterSplits.Next()) {
129           if(aEdge.IsSame(aIterSplits.Value())) {
130             aIterSplits.Value().Reverse();
131           }
132         }
133       }
134     }
135     aMapEdgeIPV.Bind(aEdge,iPV);
136   }
137   aListTodo.RemoveFirst();
138
139   // find holes and make new edges
140
141   BRep_Builder aBld;
142   Standard_Integer iPVLast = 0;
143   iPV = -1;
144   while (iPV != 0) {
145
146     // find the most left edge
147     iPV = 0;
148     TopTools_ListIteratorOfListOfShape aIterFound;
149     Standard_Real aParF = aParVer[0].myParL;
150     TopoDS_Vertex aVerF = aParVer[0].myVerL;
151     for (aIter.Initialize(aListTodo); aIter.More(); aIter.Next()) {
152       const TopoDS_Edge& aEdge = TopoDS::Edge(aIter.Value());
153       Standard_Integer i = aMapEdgeIPV(aEdge);
154       if (aParVer[i].myParF < aParF) {
155         aParF = aParVer[i].myParF;
156         aVerF = aParVer[i].myVerF;
157         iPV = i;
158         aIterFound = aIter;
159       }
160     }
161
162     // get previous last parameter
163     Standard_Real aParPrevL;
164     TopoDS_Vertex aVerPrevL;
165     if (iPVLast == 0) {
166       aParPrevL = aParVer[0].myParF;
167       aVerPrevL = aParVer[0].myVerF;
168     }
169     else {
170       aParPrevL = aParVer[iPVLast].myParL;
171       aVerPrevL = aParVer[iPVLast].myVerL;
172     }
173
174     if (aParF > aParPrevL && !BRepTools::Compare(aVerF, aVerPrevL)) {
175       // make new edge to close the hole
176       TopoDS_Edge aNewEdge = theEdge;
177       aNewEdge.EmptyCopy();
178       aNewEdge.Orientation(TopAbs_FORWARD);
179       TopoDS_Vertex aV1 = aVerPrevL;
180       TopoDS_Vertex aV2 = aVerF;
181       aV1.Orientation(TopAbs_FORWARD);
182       aV2.Orientation(TopAbs_REVERSED);
183       aBld.Add(aNewEdge, aV1);
184       aBld.Add(aNewEdge, aV2);
185       aBld.UpdateVertex(aV1, aParPrevL, aNewEdge, BRep_Tool::Tolerance(aV1));
186       aBld.UpdateVertex(aV2, aParF, aNewEdge, BRep_Tool::Tolerance(aV2));
187       theListSplits.Append(aNewEdge);
188     }
189
190     iPVLast = iPV;
191     if (aIterFound.More()) aListTodo.Remove(aIterFound);
192   }
193
194   delete [] aParVer;
195 }
196
197 //=======================================================================
198 //function : SplitEdge
199 //purpose  : static
200 //=======================================================================
201
202 static void
203 SplitEdge (const TopoDS_Edge          &theEdge,
204            const BOPTools_PDSFiller   &thePDSFiller,
205            const TopTools_MapOfShape  &theEdgesValid,
206            const Standard_Boolean      useMap,
207                  TopTools_ListOfShape &theListSplits)
208 {
209   const TopAbs_State aStates[3] = {TopAbs_ON, TopAbs_IN, TopAbs_OUT};
210
211   for (Standard_Integer i=0; i < 3; i++) {      // for each state {ON, IN, OUT}
212     if (QANewModTopOpe_Tools::IsSplit(thePDSFiller, theEdge, aStates[i])) {
213       // get splits according to this state
214       // and append them to the substitution list
215       TopTools_ListOfShape aListSplits;
216
217       QANewModTopOpe_Tools::Splits(thePDSFiller, theEdge, aStates[i], aListSplits);
218       TopTools_ListIteratorOfListOfShape aIterSplits(aListSplits);
219       for(; aIterSplits.More(); aIterSplits.Next()) {
220         const TopoDS_Shape& aEdge = aIterSplits.Value();
221         if (!useMap || theEdgesValid.Contains (aEdge))
222           theListSplits.Append(aEdge.Oriented(TopAbs_FORWARD));
223       }
224     }
225   }
226
227   if (!theListSplits.IsEmpty()) {
228     SplitEdgeComplete (theEdge, theListSplits);
229   }
230 }
231
232 //=======================================================================
233 //function : IsEdgeOut
234 //purpose  : static
235 //remark   : the edge is expected to have a pcurve on this face
236 //=======================================================================
237
238 static Standard_Boolean
239 IsEdgeOut (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace)
240 {
241   Standard_Real aParF, aParL, aParM;
242   Handle(Geom2d_Curve) aCrv = BRep_Tool::CurveOnSurface(theEdge, theFace, aParF, aParL);
243   if (aCrv.IsNull()) return Standard_True;
244
245   Standard_Real aPrec = Precision::PConfusion();
246   BRepClass_FaceClassifier aClf;
247   gp_Pnt2d aPnt;
248
249   if (!Precision::IsNegativeInfinite(aParF)) {
250     //check first point
251     aPnt = aCrv->Value(aParF);
252     aClf.Perform(theFace, aPnt, aPrec);
253     if(aClf.State() == TopAbs_OUT) return Standard_True;
254   }
255
256   if (!Precision::IsPositiveInfinite(aParL)) {
257     //check last point
258     aPnt = aCrv->Value(aParL);
259     aClf.Perform(theFace, aPnt, aPrec);
260     if(aClf.State() == TopAbs_OUT) return Standard_True;
261   }
262
263   //check middle point
264   if (!Precision::IsNegativeInfinite(aParF) &&
265       !Precision::IsPositiveInfinite(aParL)) {
266     aParM = aParF + 0.618 * (aParL - aParF);
267   }
268   else {
269     if (Precision::IsNegativeInfinite(aParF) &&
270         Precision::IsPositiveInfinite(aParL))
271       aParM = 0.;
272     else if (Precision::IsNegativeInfinite(aParF))
273       aParM = aParL - 1.;
274     else
275       aParM = aParF + 1.;
276   }
277   aPnt = aCrv->Value(aParM);
278   aClf.Perform(theFace, aPnt, aPrec);
279   if(aClf.State() == TopAbs_OUT) return Standard_True;
280
281   return Standard_False;
282 }
283
284 //=======================================================================
285 //function : CorrectAncestorsList
286 //purpose  : static
287 //=======================================================================
288
289 static void
290 CorrectAncestorsList (const TopoDS_Edge& theEdge, TopTools_ListOfShape& aListF)
291 {
292   // remove duplicates from list,
293   // remove faces for which theEdge has the state "OUT"
294
295   // get a middle point on edge
296   TopTools_MapOfShape aMapF;
297   TopTools_ListIteratorOfListOfShape aIter(aListF);
298   while (aIter.More()) {
299     const TopoDS_Face& aFace = TopoDS::Face(aIter.Value());
300     if (!aMapF.Add(aFace)) {
301       // duplicate -> remove
302       aListF.Remove(aIter);
303       continue;
304     }
305     if (IsEdgeOut(theEdge, aFace)) {
306       // this face is not an ancestor -> remove
307       aListF.Remove(aIter);
308       continue;
309     }
310     aIter.Next();
311   }
312 }
313
314 //=======================================================================
315 //function : PerformShell
316 //purpose  : 
317 //=======================================================================
318
319 void
320 QANewModTopOpe_Glue::PerformShell() 
321 {
322 //  Standard_Boolean isSolidShell = (myS1.ShapeType() == TopAbs_SOLID);
323   Standard_Boolean isSolidShell = Standard_False;
324   Standard_Integer i;
325
326   TopTools_MapOfShape anEdges, aCommonEdges, anOldVertices, aGenEdges;
327   TopExp_Explorer anExp;
328
329   anExp.Init(myS1, TopAbs_EDGE);
330   for(; anExp.More(); anExp.Next()) anEdges.Add(anExp.Current());
331
332   anExp.Init(myS2, TopAbs_EDGE);
333   for(; anExp.More(); anExp.Next()) {
334     if(anEdges.Contains(anExp.Current())) aCommonEdges.Add(anExp.Current());
335   }
336
337   anExp.ReInit();
338   for(; anExp.More(); anExp.Next()) anEdges.Add(anExp.Current());
339
340   anExp.Init(myS1, TopAbs_VERTEX);
341   for(; anExp.More(); anExp.Next()) anOldVertices.Add(anExp.Current());
342
343   anExp.Init(myS2, TopAbs_VERTEX);
344   for(; anExp.More(); anExp.Next()) anOldVertices.Add(anExp.Current());
345
346
347   // initialization
348   TopoDS_Shape aS1, aS2;
349   Standard_Boolean aWire1 = Standard_False, aWire2 = Standard_False; 
350   anExp.Init(myS1, TopAbs_WIRE, TopAbs_FACE);
351   if(anExp.More()) {
352     aS1 = myS1;
353     aWire1 = Standard_True;
354   }
355   else {
356     anExp.Init(myS1, TopAbs_EDGE, TopAbs_WIRE);
357     if(anExp.More()) {
358       aS1 = myS1;
359       aWire1 = Standard_True;
360     }
361   }
362    
363   anExp.Init(myS2, TopAbs_WIRE, TopAbs_FACE);
364   if(anExp.More()) {
365     aS2 = myS2;
366     aWire2 = Standard_True;
367   }
368   else {
369     anExp.Init(myS2, TopAbs_EDGE, TopAbs_WIRE);
370     if(anExp.More()) {
371       aS2 = myS2;
372       aWire2 = Standard_True;
373     }
374   }
375  
376   if(aWire1) {
377     BRep_Builder aBld;
378     myS1.Nullify();
379     aBld.MakeCompound(TopoDS::Compound(myS1));
380     anExp.Init(aS1, TopAbs_COMPSOLID);
381     for(; anExp.More(); anExp.Next()) {
382       aBld.Add(myS1, anExp.Current());
383     }
384     
385     anExp.Init(aS1, TopAbs_SOLID, TopAbs_COMPSOLID);
386     for(; anExp.More(); anExp.Next()) {
387       aBld.Add(myS1, anExp.Current());
388     }
389     
390     anExp.Init(aS1, TopAbs_SHELL, TopAbs_SOLID);
391     for(; anExp.More(); anExp.Next()) {
392       aBld.Add(myS1, anExp.Current());
393     }
394     
395     anExp.Init(aS1, TopAbs_FACE, TopAbs_SHELL);
396     for(; anExp.More(); anExp.Next()) {
397       aBld.Add(myS1, anExp.Current());
398     }
399     
400   }
401
402   if(aWire2) {
403     BRep_Builder aBld;
404     myS2.Nullify();
405     aBld.MakeCompound(TopoDS::Compound(myS2));
406     anExp.Init(aS2, TopAbs_COMPSOLID);
407     for(; anExp.More(); anExp.Next()) {
408       aBld.Add(myS2, anExp.Current());
409     }
410     
411     anExp.Init(aS2, TopAbs_SOLID, TopAbs_COMPSOLID);
412     for(; anExp.More(); anExp.Next()) {
413       aBld.Add(myS2, anExp.Current());
414     }
415     
416     anExp.Init(aS2, TopAbs_SHELL, TopAbs_SOLID);
417     for(; anExp.More(); anExp.Next()) {
418       aBld.Add(myS2, anExp.Current());
419     }
420     
421     anExp.Init(aS2, TopAbs_FACE, TopAbs_SHELL);
422     for(; anExp.More(); anExp.Next()) {
423       aBld.Add(myS2, anExp.Current());
424     }
425     
426   }
427
428   Standard_Boolean hasSolid1 = Standard_False;
429   Standard_Boolean hasSolid2 = Standard_False;
430
431   anExp.Init(myS1, TopAbs_SOLID);
432
433   if (anExp.More())
434     hasSolid1 = Standard_True;
435
436   anExp.Init(myS2, TopAbs_SOLID);
437
438   if (anExp.More())
439     hasSolid2 = Standard_True;
440
441   if (hasSolid1 && hasSolid2)
442     myOperation = BOP_FUSE;
443   else if (hasSolid1)
444     myOperation = BOP_CUT21;
445   else if (hasSolid2)
446     myOperation = BOP_CUT;
447   else
448     myOperation = BOP_SECTION;
449
450   BRepAlgoAPI_BooleanOperation::Build();
451   if (!BuilderCanWork())
452     return;
453
454   if(aWire1) myS1 = aS1;
455   if(aWire2) myS2 = aS2;
456
457   TopTools_DataMapOfShapeListOfShape* aMapSEdgeFaces[2] =
458     {&myMapSEdgeFaces1, &myMapSEdgeFaces2};
459   TopTools_DataMapOfShapeShape* aMapSEdgeCrossFace[2] =
460     {&myMapSEdgeCrossFace1, &myMapSEdgeCrossFace2};
461   TopTools_MapOfShape aSetFaces[2];
462   TopTools_MapOfShape aSetEdges[2];
463
464   // fill myMapGener for new vertices
465   TopTools_MapIteratorOfMapOfShape aMapIter(anEdges);
466   const TopAbs_State aStates[3] = {TopAbs_ON, TopAbs_IN, TopAbs_OUT};
467   for(; aMapIter.More(); aMapIter.Next()) {
468     const TopoDS_Shape& aEdge = aMapIter.Key();
469
470     if(aCommonEdges.Contains(aEdge)) continue;
471
472     for (i=0; i < 3; i++) {     // for each state {ON, IN, OUT}
473       if (QANewModTopOpe_Tools::IsSplit(myDSFiller, aEdge, aStates[i])) {
474         TopTools_ListOfShape aListSplits;
475
476         QANewModTopOpe_Tools::Splits(myDSFiller, aEdge, aStates[i], aListSplits);
477
478         TopTools_ListIteratorOfListOfShape aIterSplits(aListSplits);
479         for(; aIterSplits.More(); aIterSplits.Next()) {
480           const TopoDS_Shape& aE = aIterSplits.Value();
481           TopoDS_Iterator aTDSIter(aE);
482           for(; aTDSIter.More(); aTDSIter.Next()) {
483             const TopoDS_Shape& aV = aTDSIter.Value();
484
485             if(!anOldVertices.Add(aV)) continue;
486
487             if(!myMapGener.IsBound(aEdge)) {
488               // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aEdge, TopTools_ListOfShape());
489               TopTools_ListOfShape aListOfShape1;
490               myMapGener.Bind(aEdge, aListOfShape1);
491             }
492
493             myMapGener(aEdge).Append(aV);
494           }
495         }
496       }
497     }
498   }       
499
500
501   // get list of section edges
502   const TopTools_ListOfShape& aListSE = SectionEdges();
503
504   // for each section edge remember the face crossed by the edge
505   // and the faces for which the edge coincides with a face's bound
506   TopTools_ListIteratorOfListOfShape aIterSE(aListSE);
507   Standard_Integer aNbUsedSecEdges = 0;
508   for(; aIterSE.More(); aIterSE.Next()) {
509     const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
510
511     if(!aCommonEdges.Contains(aSecEdge)) {
512
513       aNbUsedSecEdges++;
514
515       TopoDS_Face aFaces[2];
516       QANewModTopOpe_Tools::EdgeCurveAncestors(myDSFiller, aSecEdge, aFaces[0],
517                                           aFaces[1]);
518
519       TopTools_ListOfShape aListF[2], aListE[2];
520       QANewModTopOpe_Tools::EdgeSectionAncestors(myDSFiller, aSecEdge, aListF[0],
521                                             aListF[1], aListE[0], aListE[1]);
522       CorrectAncestorsList (aSecEdge, aListF[0]);
523       CorrectAncestorsList (aSecEdge, aListF[1]);
524
525       Standard_Integer nbCurveAncestors = 0;
526       for (i = 0; i < 2; i++) {
527         if (!aListF[i].IsEmpty()) {
528           aMapSEdgeFaces[i]->Bind(aSecEdge, aListF[i]);
529           if (aListE[i].IsEmpty())
530             aMapSEdgeCrossFace[i]->Bind(aSecEdge, aListF[i].First());
531           TopTools_ListIteratorOfListOfShape aIter (aListF[i]);
532           for (; aIter.More(); aIter.Next())
533             aSetFaces[i].Add(aIter.Value());
534         }
535         else if (!aFaces[i].IsNull()) {
536           TopTools_ListOfShape aList;
537           aList.Append(aFaces[i]);
538           aMapSEdgeFaces[i]->Bind(aSecEdge, aList);
539           aMapSEdgeCrossFace[i]->Bind(aSecEdge, aFaces[i]);
540           aSetFaces[i].Add(aFaces[i]);
541           nbCurveAncestors++;
542         }
543         else if (!aListE[i].IsEmpty()) {
544           myEdgesToLeave.Add (aSecEdge);
545           TopTools_ListIteratorOfListOfShape aIter (aListE[i]);
546           for (; aIter.More(); aIter.Next())
547             aSetEdges[i].Add(aIter.Value());
548         }
549       }
550       if (nbCurveAncestors == 2) {
551         // the edge was computed by intersection of 2 surfaces
552         aGenEdges.Add(aSecEdge);
553         if (isSolidShell && !myAllowCutting) {
554           // Shell goes inside Solid while it is forbidden
555           return;
556         }
557         else {
558           // force same parameter
559           const Standard_Real aTol = 1.e-5;
560           BRep_Builder aBld;
561           aBld.SameRange (aSecEdge, Standard_False);
562           aBld.SameParameter (aSecEdge, Standard_False);
563           BRepLib::SameParameter (aSecEdge, aTol);
564         }
565       }
566     }
567   }
568
569   //--------------------------------------------------
570   if(aNbUsedSecEdges == 0 && aListSE.Extent() != 0) {
571     // all section edges are common edges - make compound
572     BRep_Builder aBld;
573     aBld.MakeCompound (TopoDS::Compound(myShape));
574     aBld.Add(myShape, myS1);
575     aBld.Add(myShape, myS2);
576     Done();
577     return;
578   }
579   //--------------------------------------------------
580
581   // cut faces of shell if another shape is solid
582   if (isSolidShell) {
583     // split edges of shape by section edges which are got
584     // due to coinciding of edges rather than intersecting of faces
585     TopTools_MapIteratorOfMapOfShape aIter(aSetEdges[1]);
586     for(; aIter.More(); aIter.Next()) {
587       const TopoDS_Edge aEdge = TopoDS::Edge (aIter.Key());
588       TopTools_ListOfShape aListSplitE;
589       SplitEdge (aEdge, myDSFiller, myEdgesToLeave, Standard_False, aListSplitE);
590       if (!aListSplitE.IsEmpty()) {
591         mySubst.Substitute (aEdge, aListSplitE);
592         if (mySubst.IsCopied (aEdge)) {
593           // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aEdge, TopTools_ListOfShape());
594           TopTools_ListOfShape aListOfShape2;
595           myMapModif.Bind(aEdge, aListOfShape2);
596           myMapModif(aEdge).Append (aListSplitE);
597         }
598       }
599     }
600
601     for(aIter.Initialize (aSetFaces[1]); aIter.More(); aIter.Next()) {
602       const TopoDS_Face aFace = TopoDS::Face (aIter.Key());
603       TopTools_ListOfShape aListSEOnFace;
604
605       // select section edges on this face
606       for (aIterSE.Initialize(aListSE); aIterSE.More(); aIterSE.Next()) {
607         const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
608         // check if aFace is an ancestor of aSecEdge
609         if (aMapSEdgeFaces[1]->IsBound(aSecEdge)) {
610           TopTools_ListIteratorOfListOfShape
611             aIterF (aMapSEdgeFaces[1]->Find(aSecEdge));
612           for (; aIterF.More(); aIterF.Next())
613             if (aIterF.Value().IsSame(aFace)) {
614               aListSEOnFace.Append(aSecEdge);
615               break;
616             }
617         }
618       }
619       if (!aListSEOnFace.IsEmpty()) {
620         Standard_Boolean isCut = CutFace (aFace, aListSEOnFace);
621         if (isCut && !myAllowCutting) {
622           // Shell goes inside Solid while it is forbidden
623           return;
624         }
625       }
626     }
627
628     // remove from maps all the section edges which are not marked to leave
629     for (aIterSE.Initialize (aListSE); aIterSE.More(); aIterSE.Next()) {
630       const TopoDS_Shape& aSecEdge = aIterSE.Value();
631       if (!myEdgesToLeave.Contains (aSecEdge)) {
632         myMapSEdgeFaces1.UnBind (aSecEdge);
633         myMapSEdgeFaces2.UnBind (aSecEdge);
634         myMapSEdgeCrossFace1.UnBind (aSecEdge);
635         myMapSEdgeCrossFace2.UnBind (aSecEdge);
636       }
637     }
638   }
639   else {        // not the case Solid-Shell
640     for (aIterSE.Initialize (aListSE); aIterSE.More(); aIterSE.Next())
641       myEdgesToLeave.Add (aIterSE.Value());
642   }
643
644   // process intersected faces
645   for (i = 0; i < 2; i++) {
646     if (i == 1 && isSolidShell) continue;
647
648     // split edges of shape by section edges which are got
649     // due to coinciding of edges rather than intersecting of faces
650     TopTools_MapIteratorOfMapOfShape aIter(aSetEdges[i]);
651     for(; aIter.More(); aIter.Next()) {
652       const TopoDS_Edge aEdge = TopoDS::Edge (aIter.Key());
653       TopTools_ListOfShape aListSplitE;
654       SplitEdge (aEdge, myDSFiller, myEdgesToLeave, Standard_True, aListSplitE);
655       if (!aListSplitE.IsEmpty()) {
656         mySubst.Substitute (aEdge, aListSplitE);
657         //Substitution of vertices at the ends of aEdge.
658         TopoDS_Vertex aV1, aV2;
659         TopExp::Vertices(aEdge, aV1, aV2);
660         TopTools_ListIteratorOfListOfShape anIter(aListSplitE);
661         for(; anIter.More(); anIter.Next()) {
662           const TopoDS_Edge& aSpE = TopoDS::Edge(anIter.Value());
663           TopoDS_Vertex aSpV1, aSpV2;
664           TopExp::Vertices(aSpE, aSpV1, aSpV2);
665           aSpV1.Orientation(TopAbs_FORWARD);
666           aSpV2.Orientation(TopAbs_FORWARD);
667           TopTools_ListOfShape aL;
668           if(BRepTools::Compare(aV1, aSpV1) && (!aV1.IsSame(aSpV1))) {
669             aL.Clear();
670             aL.Append(aSpV1);
671             if(!mySubst.IsCopied (aV1)) {
672               mySubst.Substitute(aV1, aL);
673 //            if (mySubst.IsCopied (aV1)) {
674                 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV1, TopTools_ListOfShape());
675                 TopTools_ListOfShape aListOfShape3;
676                 myMapModif.Bind(aV1, aListOfShape3);
677                 myMapModif(aV1).Append (aL);
678 //            }
679             }
680           }
681           if(BRepTools::Compare(aV1, aSpV2) && (!aV1.IsSame(aSpV2))) {
682             aL.Clear();
683             aL.Append(aSpV2);
684             if(!mySubst.IsCopied (aV1)) {
685               mySubst.Substitute(aV1, aL);
686 //            if (mySubst.IsCopied (aV1)) {
687                 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV1, TopTools_ListOfShape());
688                 TopTools_ListOfShape aListOfShape4;
689                 myMapModif.Bind(aV1, aListOfShape4);
690                 myMapModif(aV1).Append (aL);
691 //            }
692             }
693           }
694           if(BRepTools::Compare(aV2, aSpV1) && (!aV2.IsSame(aSpV1))) {
695             aL.Clear();
696             aL.Append(aSpV1);
697             if (!mySubst.IsCopied (aV2)) {
698               mySubst.Substitute(aV2, aL);
699 //            if (mySubst.IsCopied (aV2)) {
700                 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV2, TopTools_ListOfShape());
701                 TopTools_ListOfShape aListOfShape5;
702                 myMapModif.Bind(aV2, aListOfShape5);
703                 myMapModif(aV2).Append (aL);
704 //            }
705             }
706           }
707           if(BRepTools::Compare(aV2, aSpV2) && (!aV2.IsSame(aSpV2))) {
708             aL.Clear();
709             aL.Append(aSpV2);
710             if (!mySubst.IsCopied (aV2)) {
711               mySubst.Substitute(aV2, aL);
712 //            if (mySubst.IsCopied (aV2)) {
713                 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV2, TopTools_ListOfShape());
714                 TopTools_ListOfShape aListOfShape6;
715                 myMapModif.Bind(aV2, aListOfShape6);
716                 myMapModif(aV2).Append (aL);
717 //            }
718             }
719           }
720         }
721
722         if (mySubst.IsCopied (aEdge)) {
723           // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aEdge, TopTools_ListOfShape());
724           TopTools_ListOfShape aListOfShape7;
725           myMapModif.Bind(aEdge, aListOfShape7);
726           myMapModif(aEdge).Append (aListSplitE);
727         }
728       }
729     }
730
731     for(aIter.Initialize (aSetFaces[i]); aIter.More(); aIter.Next()) {
732       const TopoDS_Face aFace = TopoDS::Face (aIter.Key());
733       TopTools_ListOfShape aListSEOnFace;
734
735       // select section edges on this face
736       for (aIterSE.Initialize(aListSE); aIterSE.More(); aIterSE.Next()) {
737         const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
738         // check if aFace is an ancestor of aSecEdge
739         if (aMapSEdgeFaces[i]->IsBound(aSecEdge)) {
740           TopTools_ListIteratorOfListOfShape
741             aIterF (aMapSEdgeFaces[i]->Find(aSecEdge));
742           for (; aIterF.More(); aIterF.Next())
743             if (aIterF.Value().IsSame(aFace)) {
744               aListSEOnFace.Append(aSecEdge);
745               break;
746             }
747         }
748       }
749       if (!aListSEOnFace.IsEmpty())
750         SectionInsideFace (aFace, aListSEOnFace, i, aGenEdges);
751     }
752   }
753
754   // construct new shapes from myS1 and myS2
755   // and result compound
756   TopoDS_Shape aNewS[2];
757   Standard_Integer nbModified = 0;
758   Standard_Integer nbDeleted = 0;
759   Standard_Integer iShape;
760
761   for (i = 0; i < 2; i++) {
762     const TopoDS_Shape& aOldS = (i==0 ? myS1 : myS2);
763     mySubst.Build(aOldS);
764     if (mySubst.IsCopied(aOldS)) {
765       if (!mySubst.Copy(aOldS).IsEmpty()) {
766         aNewS[i] = mySubst.Copy(aOldS).First();
767         aNewS[i].Orientation(aOldS.Orientation());
768         nbModified++;
769         iShape = i;
770       }
771       else if (!myAllowCutting) {
772         // all Shell is inside Solid while it is forbidden
773         return;
774       }
775       else
776         nbDeleted++;
777     }
778     else {
779       aNewS[i] = aOldS;
780       iShape = i;
781     }
782     
783     TopExp_Explorer aExp (aOldS, TopAbs_FACE);
784     for (; aExp.More(); aExp.Next()) {
785       const TopoDS_Shape& aFace = aExp.Current();
786       if(myMapModif.IsBound(aFace)) continue;
787       if (mySubst.IsCopied(aFace)) {
788         if (!mySubst.Copy(aFace).IsEmpty()) {   
789           myMapModif.Bind(aFace,mySubst.Copy(aFace));
790         }
791       }
792     }
793       
794   }
795
796   if (nbModified > 0 && nbDeleted == 0) {
797     // the usual case
798     isSolidShell = Standard_True; 
799     BRep_Builder aBld;
800     if(isSolidShell) {
801       aBld.MakeCompound (TopoDS::Compound(myShape));
802       aBld.Add(myShape, aNewS[0]);
803       aBld.Add(myShape, aNewS[1]);
804     }
805     else {
806       aBld.MakeShell (TopoDS::Shell(myShape));
807       for(anExp.Init(aNewS[0], TopAbs_FACE); anExp.More(); anExp.Next()) {
808         aBld.Add(myShape, anExp.Current());
809       }
810       for(anExp.Init(aNewS[1], TopAbs_FACE); anExp.More(); anExp.Next()) {
811         aBld.Add(myShape, anExp.Current());
812       }
813     }
814     Done();
815   }
816   else if (nbDeleted == 1) {
817     // all Shell is inside Solid while it is permitted
818     myShape = aNewS[iShape];
819     Done();
820   } else if (nbModified == 0) {
821     // The case if nothing is changed.
822     BRep_Builder aBld;
823
824     aBld.MakeCompound (TopoDS::Compound(myShape));
825     aBld.Add(myShape, aNewS[0]);
826     aBld.Add(myShape, aNewS[1]);
827     Done();
828   }
829
830   mySubst.Clear();
831   TopExp_Explorer aExp (myShape, TopAbs_EDGE);
832   Standard_Boolean IsSplit = Standard_False;
833   for (; aExp.More(); aExp.Next()) {
834     TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
835     if(mySubst.IsCopied(aE)) continue;
836     aE.Orientation(TopAbs_FORWARD);
837     TopTools_ListOfShape aListSplits;
838     if(QANewModTopOpe_Tools::SplitE(aE, aListSplits)) {
839       if(!IsSplit) IsSplit = Standard_True;
840
841       BRep_Builder aBld;
842       Standard_Real aTol = Precision::Confusion();
843       TopTools_ListIteratorOfListOfShape anISpl(aListSplits);
844       for(; anISpl.More(); anISpl.Next()) {
845         const TopoDS_Shape& aSpE = anISpl.Value();
846         Standard_Real tol = BRep_Tool::Tolerance(TopoDS::Edge(aSpE));
847         if(tol > aTol) {
848           aBld.UpdateEdge(TopoDS::Edge(aSpE), 1.05*tol);
849         }
850       }
851           
852       mySubst.Substitute(aE, aListSplits);
853       myMapModif.Bind(aE, aListSplits);
854     }
855   }
856
857   if(IsSplit) {
858     mySubst.Build(myShape);
859     if(mySubst.IsCopied(myShape)) {
860       aExp.Init(myShape, TopAbs_FACE);
861       for(; aExp.More(); aExp.Next()) {
862         const TopoDS_Shape& aF = aExp.Current();
863         if(mySubst.IsCopied(aF)) {
864           myMapModif.Bind(aF, mySubst.Copy(aF));
865         }
866       }
867       myShape = mySubst.Copy(myShape).First();
868     }
869   }
870
871 }
872
873 //=======================================================================
874 //function : SplitFaceBoundary
875 //purpose  : static
876 //=======================================================================
877
878 static TopoDS_Face
879 SplitFaceBoundary (const TopoDS_Face& theFace,
880                    BRepTools_Substitution& theSubst,
881                    const BOPTools_PDSFiller   &thePDSFiller,
882                    const TopTools_MapOfShape& theEdgesValid,
883                    const Standard_Boolean useMap,
884                    TopTools_DataMapOfShapeListOfShape& theMapModif)
885 {
886   // split the face's edges by section edges lying on boundary
887   BRepTools_Substitution aLocalSubst;
888   TopExp_Explorer aExp (theFace, TopAbs_EDGE);
889   for (; aExp.More(); aExp.Next()) {
890     const TopoDS_Edge& aEdge = TopoDS::Edge (aExp.Current());
891     if (theSubst.IsCopied (aEdge)) continue;
892
893     TopTools_ListOfShape aListSplitE;
894     SplitEdge (aEdge, thePDSFiller, theEdgesValid, useMap, aListSplitE);
895     if (aListSplitE.IsEmpty()) continue;
896
897     theSubst.Substitute (aEdge, aListSplitE);
898     aLocalSubst.Substitute (aEdge, aListSplitE);
899 //-------------------------------------------------------------
900         //Substitution of vertices at the ends of aEdge.
901         TopoDS_Vertex aV1, aV2;
902         TopExp::Vertices(aEdge, aV1, aV2);
903         TopTools_ListIteratorOfListOfShape anIter(aListSplitE);
904         for(; anIter.More(); anIter.Next()) {
905           const TopoDS_Edge& aSpE = TopoDS::Edge(anIter.Value());
906           TopoDS_Vertex aSpV1, aSpV2;
907           TopExp::Vertices(aSpE, aSpV1, aSpV2);
908           aSpV1.Orientation(TopAbs_FORWARD);
909           aSpV2.Orientation(TopAbs_FORWARD);
910           TopTools_ListOfShape aL;
911           if(BRepTools::Compare(aV1, aSpV1) && (!aV1.IsSame(aSpV1))) {
912             aL.Clear();
913             aL.Append(aSpV1);
914             aLocalSubst.Substitute(aV1, aL);
915             theSubst.Substitute(aV1, aL);
916             if (aLocalSubst.IsCopied (aV1)) {
917               // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV1, TopTools_ListOfShape());
918               TopTools_ListOfShape aListOfShape1;
919               theMapModif.Bind(aV1, aListOfShape1);
920               theMapModif(aV1).Append (aL);
921             }
922           }
923           if(BRepTools::Compare(aV1, aSpV2) && (!aV1.IsSame(aSpV2))) {
924             aL.Clear();
925             aL.Append(aSpV2);
926             aLocalSubst.Substitute(aV1, aL);
927             theSubst.Substitute(aV1, aL);
928             if (aLocalSubst.IsCopied (aV1)) {
929               // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV1, TopTools_ListOfShape());
930               TopTools_ListOfShape aListOfShape2;
931               theMapModif.Bind(aV1, aListOfShape2);
932               theMapModif(aV1).Append (aL);
933             }
934           }
935           if(BRepTools::Compare(aV2, aSpV1) && (!aV2.IsSame(aSpV1))) {
936             aL.Clear();
937             aL.Append(aSpV1);
938             aLocalSubst.Substitute(aV2, aL);
939             theSubst.Substitute(aV2, aL);
940             if (aLocalSubst.IsCopied (aV2)) {
941               // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV2, TopTools_ListOfShape());
942               TopTools_ListOfShape aListOfShape3;
943               theMapModif.Bind(aV2, aListOfShape3);
944               theMapModif(aV2).Append (aL);
945             }
946           }
947           if(BRepTools::Compare(aV2, aSpV2) && (!aV2.IsSame(aSpV2))) {
948             aL.Clear();
949             aL.Append(aSpV2);
950             aLocalSubst.Substitute(aV2, aL);
951             theSubst.Substitute(aV2, aL);
952             if (aLocalSubst.IsCopied (aV2)) {
953               // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV2, TopTools_ListOfShape());
954               TopTools_ListOfShape aListOfShape4;
955               theMapModif.Bind(aV2, aListOfShape4);
956               theMapModif(aV2).Append (aL);
957             }
958           }
959         }
960 //-------------------------------------------------------------
961     if (aLocalSubst.IsCopied (aEdge)) {
962       // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aEdge, TopTools_ListOfShape());
963       TopTools_ListOfShape aListOfShape5;
964       theMapModif.Bind(aEdge, aListOfShape5);
965       theMapModif(aEdge).Append (aListSplitE);
966     }
967   }
968
969   aLocalSubst.Build (theFace);
970   if (aLocalSubst.IsCopied (theFace)) {
971 //    TopoDS_Iterator aIterF (theFace);
972 //    for (; aIterF.More(); aIterF.Next()) {
973 //      const TopoDS_Shape& aWire = aIterF.Value();
974 //      if (aLocalSubst.IsCopied (aWire))
975 //      theSubst.Substitute (aWire, aLocalSubst.Copy(aWire));
976 //    }
977     aExp.Init(theFace, TopAbs_EDGE);
978     for(; aExp.More(); aExp.Next()) {
979       const TopoDS_Shape& anE = aExp.Current();
980
981       if (aLocalSubst.IsCopied (anE)) {
982         if(!theSubst.IsCopied (anE)) {
983           theSubst.Substitute (anE, aLocalSubst.Copy(anE));
984           theMapModif.Bind(anE, aLocalSubst.Copy(anE));
985         }
986       }
987     }
988     return TopoDS::Face (aLocalSubst.Copy(theFace).First());
989   }
990   return theFace;
991 }
992
993 //=======================================================================
994 //function : CutFace
995 //purpose  : 
996 //=======================================================================
997
998 Standard_Boolean
999 QANewModTopOpe_Glue::CutFace(const TopoDS_Face& theFace,
1000                         const TopTools_ListOfShape& theListSE)
1001 {
1002   Standard_Boolean aRetValue = Standard_False;
1003   if (mySubst.IsCopied(theFace)) return aRetValue;
1004
1005   // theFace may contain edges which need to be substituted
1006   mySubst.Build(theFace);
1007   TopoDS_Face aFace;
1008   if (mySubst.IsCopied(theFace)) {
1009     if (mySubst.Copy(theFace).IsEmpty()) return Standard_True;
1010     aFace = TopoDS::Face(mySubst.Copy(theFace).First());
1011   }
1012   else
1013     aFace = theFace;
1014
1015   // split the face's edges by section edges lying on boundary
1016   TopoDS_Face aFace1 = SplitFaceBoundary (aFace, mySubst, myDSFiller,
1017                                           myEdgesToLeave, Standard_False, myMapModif);
1018
1019   // split face on subfaces by section edges lying inside the face
1020   BRepFeat_SplitShape aSpliter (aFace1);
1021   TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1022   for (; aIterSE.More(); aIterSE.Next()) {
1023     const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1024     if (myMapSEdgeCrossFace2.IsBound(aSEdge))
1025       aSpliter.Add (aSEdge, aFace1);
1026   }
1027   aSpliter.Build();
1028   const TopTools_ListOfShape& aListSplit = aSpliter.Modified(aFace1);
1029
1030   // get OUT splits and append them to the substitution list
1031   TopTools_ListOfShape aListToSubst;
1032   TopTools_ListIteratorOfListOfShape aIter(aListSplit);
1033   for(; aIter.More(); aIter.Next()) {
1034     const TopoDS_Face& aFaceNew = TopoDS::Face (aIter.Value());
1035     TopAbs_State aState = ClassifyFace (aFaceNew, theListSE);
1036     if (aState == TopAbs_OUT) {
1037       aListToSubst.Append(aFaceNew.Oriented(TopAbs_FORWARD));
1038       // remember in the map the section edges to leave
1039       TopExp_Explorer aExp (aFaceNew, TopAbs_EDGE);
1040       for (; aExp.More(); aExp.Next()) {
1041         const TopoDS_Shape& aEdge = aExp.Current();
1042         if (myMapSEdgeFaces2.IsBound (aEdge))
1043           myEdgesToLeave.Add (aEdge);
1044       }
1045     }
1046     else {
1047       aRetValue = Standard_True;
1048     }
1049   }
1050   mySubst.Substitute(aFace, aListToSubst);
1051
1052   // update history
1053   if (mySubst.IsCopied(aFace)) {
1054     // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(theFace, TopTools_ListOfShape());
1055     TopTools_ListOfShape aListOfShape;
1056     myMapModif.Bind(theFace, aListOfShape);
1057     myMapModif(theFace).Append (aListToSubst);
1058   }
1059
1060   return aRetValue;
1061 }
1062
1063 //=======================================================================
1064 //function : GetVecIntoFace
1065 //purpose  : static
1066 //=======================================================================
1067
1068 static Standard_Boolean
1069 GetVecIntoFace (const TopoDS_Face& theFace,
1070                 const TopoDS_Edge& theEdge,
1071                 gp_Pnt& thePntOnEdge,
1072                 gp_Vec& theVecIntoFace)
1073 {
1074   TopoDS_Shape aDummy = theFace.Oriented(TopAbs_FORWARD);
1075   TopoDS_Face aFace = TopoDS::Face(aDummy);
1076   TopoDS_Edge aEdge;  // theEdge extracted from theFace (with orientation)
1077
1078   TopExp_Explorer aExp (aFace, TopAbs_EDGE);
1079   for (; aExp.More(); aExp.Next()) {
1080     aEdge = TopoDS::Edge (aExp.Current());
1081     if (aEdge.IsSame(theEdge)) break;
1082   }
1083   if (!aExp.More()) return Standard_False;
1084
1085   TopAbs_Orientation aOrient = aEdge.Orientation();
1086   if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
1087     return Standard_False;
1088
1089   Standard_Real aParF, aParL;
1090   Handle(Geom2d_Curve) aCrv = BRep_Tool::CurveOnSurface(aEdge, aFace, aParF, aParL);
1091   if (aCrv.IsNull()) return Standard_False;
1092   if (aCrv->Continuity() < GeomAbs_C1) return Standard_False;
1093
1094   // get middle point on edge and normal
1095   Standard_Real aParM = aParF + (aParL - aParF) * 0.618;
1096   gp_Pnt2d aPntOnCrv;
1097   gp_Vec2d aDeriv;
1098   aCrv->D1(aParM, aPntOnCrv, aDeriv);
1099   gp_Vec2d aNormal(-aDeriv.Y(), aDeriv.X());
1100   aNormal.Normalize();
1101   if (aOrient == TopAbs_REVERSED) aNormal.Reverse();
1102
1103   // translate middle point along the normal
1104   Standard_Real uMin, uMax, vMin, vMax;
1105   BRepTools::UVBounds(aFace, uMin, uMax, vMin, vMax);
1106   Standard_Real duv = Min(uMax - uMin, vMax - vMin) * 0.1;
1107   Standard_Real dtol = BRep_Tool::Tolerance(aEdge) * 100.;
1108   Standard_Real d = Min(duv, dtol);
1109   gp_Pnt2d aPntOnSurf = aPntOnCrv.Translated(aNormal * d);
1110
1111   // get 3d points
1112   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
1113   gp_Pnt aPntOnFace;
1114   aSurf->D0(aPntOnSurf.X(), aPntOnSurf.Y(), aPntOnFace);
1115   aSurf->D0(aPntOnCrv.X(), aPntOnCrv.Y(), thePntOnEdge);
1116
1117   // compute theVecIntoFace
1118   theVecIntoFace = gp_Vec(thePntOnEdge, aPntOnFace);
1119   Standard_Real aNorm = theVecIntoFace.Magnitude();
1120   if (aNorm < Precision::Confusion())
1121     return Standard_False;
1122   theVecIntoFace.Divide(aNorm);
1123
1124   return Standard_True;
1125 }
1126
1127 //=======================================================================
1128 //function : ClassifyFace
1129 //purpose  : 
1130 //=======================================================================
1131
1132 TopAbs_State
1133 QANewModTopOpe_Glue::ClassifyFace(const TopoDS_Face& theFace,
1134                              const TopTools_ListOfShape& theListSE) const
1135 {
1136   TopAbs_State aState = TopAbs_UNKNOWN;
1137
1138   TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1139   for (; aIterSE.More(); aIterSE.Next()) {
1140     const TopoDS_Edge& aEdge = TopoDS::Edge (aIterSE.Value());
1141
1142     // get a point on edge and a vector directed to inside face
1143     // relatively that point
1144     gp_Pnt aPntOnEdge;
1145     gp_Vec aVecIntoFace;
1146     if (BRep_Tool::Degenerated(aEdge) ||
1147         !GetVecIntoFace (theFace, aEdge, aPntOnEdge, aVecIntoFace))
1148       continue;
1149
1150     // get faces from solid
1151     if (!myMapSEdgeFaces1.IsBound(aEdge)) continue;
1152     TopTools_ListIteratorOfListOfShape aIterF (myMapSEdgeFaces1(aEdge));
1153     for (; aIterF.More(); aIterF.Next()) {
1154       const TopoDS_Face& aFaceSol = TopoDS::Face(aIterF.Value());
1155       TopAbs_Orientation aOrient = aFaceSol.Orientation();
1156       if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
1157         continue;
1158
1159       // classify theFace relatively aFaceSol
1160
1161       // get normal to the surface at the point aPntOnEdge
1162       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFaceSol);
1163       GeomAPI_ProjectPointOnSurf aProjector(aPntOnEdge, aSurf);
1164       if (!aProjector.IsDone()) continue;
1165       Standard_Real u,v;
1166       aProjector.LowerDistanceParameters(u,v);
1167       gp_Vec d1u,d1v;
1168       gp_Pnt aPntProj;
1169       aSurf->D1(u, v, aPntProj, d1u, d1v);
1170       gp_Vec aNormal = d1u.Crossed(d1v);
1171       if (aOrient == TopAbs_REVERSED) aNormal.Reverse();
1172
1173       // compare normal and the vector "into face"
1174       Standard_Real aScalar = aVecIntoFace * aNormal;
1175       if (aScalar > Precision::Confusion()) {
1176         aState = TopAbs_OUT;
1177         break;
1178       }
1179       else if (aScalar < -Precision::Confusion())
1180         aState = TopAbs_IN;
1181       else
1182         aState = TopAbs_ON;
1183     }
1184     if (aState == TopAbs_IN || aState == TopAbs_ON)
1185       break;
1186   }
1187
1188   return aState;
1189 }
1190
1191 //=======================================================================
1192 //function : IsVertexOnFaceBound
1193 //purpose  : static
1194 //=======================================================================
1195
1196 static Standard_Boolean
1197 IsVertexOnFaceBound (const TopoDS_Vertex& theVer,
1198                      const TopoDS_Face& theFace,
1199                      TopoDS_Edge& theEdgeContacted,
1200                      TopoDS_Vertex& theVerContacted,
1201                      Standard_Real& thePar,
1202                      Standard_Real& theDist)
1203 {
1204   Standard_Real aDist, aPar, aTol2;
1205   theDist = RealLast();
1206   gp_Pnt aPnt(BRep_Tool::Pnt(theVer));
1207   Standard_Boolean isContactByVer = Standard_False;
1208
1209   TopExp_Explorer aExp (theFace.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1210   for (; aExp.More() && theDist > Precision::Confusion(); aExp.Next()) {
1211     const TopoDS_Edge& aEdge = TopoDS::Edge (aExp.Current());
1212
1213     // first compare by vertices
1214     TopoDS_Iterator aIter (aEdge, Standard_False);
1215     for (; aIter.More(); aIter.Next()) {
1216       const TopoDS_Vertex& aVer = TopoDS::Vertex (aIter.Value());
1217       if (aVer.IsSame(theVer)) {
1218         theEdgeContacted = aEdge;
1219         theVerContacted = aVer;
1220         return Standard_True;
1221       }
1222       if (QANewModTopOpe_Glue::CompareVertices (aVer, theVer, aDist)) {
1223         if (aDist < theDist) {
1224           theEdgeContacted = aEdge;
1225           theVerContacted = aVer;
1226           theDist = aDist;
1227           thePar = BRep_Tool::Parameter (aVer, aEdge);
1228           aTol2 = BRep_Tool::Tolerance (aVer);
1229           isContactByVer = Standard_True;
1230         }
1231       }
1232     }
1233
1234     if (!isContactByVer) {
1235       // project on edge
1236       if (!BRep_Tool::Degenerated(aEdge)) {
1237         if (QANewModTopOpe_Glue::ProjPointOnEdge (aPnt, aEdge, aPar, aDist)) {
1238           if (aDist < theDist) {
1239             theEdgeContacted = aEdge;
1240             theVerContacted.Nullify();
1241             theDist = aDist;
1242             thePar = aPar;
1243             aTol2 = BRep_Tool::Tolerance(aEdge);
1244           }
1245         }
1246       }
1247     }
1248   }
1249
1250   if (theDist <= BRep_Tool::Tolerance(theVer) || theDist <= aTol2)
1251     return Standard_True;
1252
1253   return Standard_False;
1254 }
1255
1256 //=======================================================================
1257 //function : UpdateMapNewOld
1258 //purpose  : static
1259 //=======================================================================
1260
1261 static void
1262 UpdateMapNewOld (const TopoDS_Shape& theSh, const BRepTools_Substitution& theSubst,
1263                  TopTools_DataMapOfShapeShape& theMapNewOld)
1264 {
1265   TopTools_IndexedMapOfShape aMapSh;
1266   TopExp::MapShapes (theSh, aMapSh);
1267
1268   for (Standard_Integer i=1; i<=aMapSh.Extent(); i++) {
1269     const TopoDS_Shape& aSubSh = aMapSh(i);
1270     if (!aSubSh.IsSame(theSh) && theSubst.IsCopied (aSubSh)) {
1271       TopTools_ListIteratorOfListOfShape aIt (theSubst.Copy(aSubSh));
1272       for (; aIt.More(); aIt.Next()) {
1273         const TopoDS_Shape& aNewSubSh = aIt.Value();
1274         if (theMapNewOld.IsBound(aSubSh)) {
1275           TopoDS_Shape aOldSubSh = theMapNewOld(aSubSh);
1276           theMapNewOld.UnBind (aSubSh);
1277           theMapNewOld.Bind (aNewSubSh, aOldSubSh);
1278         }
1279         else {
1280           theMapNewOld.Bind (aNewSubSh, aSubSh);
1281         }
1282       }
1283     }
1284   }
1285 }
1286
1287 //=======================================================================
1288 //function : DoLocalSubstitution
1289 //purpose  : static
1290 //=======================================================================
1291
1292 static void
1293 DoLocalSubstitution (TopoDS_Shape& theSh, const TopoDS_Shape& theSubSh,
1294                      const TopoDS_Shape& theNewSubSh,
1295                      TopTools_DataMapOfShapeShape& theMapNewOld)
1296 {
1297   BRepTools_Substitution aLocalSubst;
1298   TopTools_ListOfShape aList;
1299   aList.Append (theNewSubSh.Oriented(TopAbs_FORWARD));
1300   aLocalSubst.Substitute (theSubSh, aList);
1301   aLocalSubst.Build(theSh);
1302
1303   if (aLocalSubst.IsCopied(theSh)) {
1304     UpdateMapNewOld (theSh, aLocalSubst, theMapNewOld);
1305     theSh = aLocalSubst.Copy(theSh).First();
1306   }
1307 }
1308
1309 //=======================================================================
1310 //function : SectionInsideFace
1311 //purpose  : 
1312 //=======================================================================
1313
1314 void
1315 QANewModTopOpe_Glue::SectionInsideFace(const TopoDS_Face& theFace,
1316                                   const TopTools_ListOfShape& theListSE,
1317                                   const Standard_Integer theShapeNum, 
1318                                   const TopTools_MapOfShape& theGenEdges) 
1319 {
1320   if (mySubst.IsCopied(theFace)) return;
1321
1322   // theFace may contain edges which need to be substituted
1323   mySubst.Build(theFace);
1324   TopoDS_Face aFace;
1325   if (mySubst.IsCopied(theFace)) {
1326     if (mySubst.Copy(theFace).IsEmpty()) return;
1327     aFace = TopoDS::Face(mySubst.Copy(theFace).First());
1328   }
1329   else
1330     aFace = theFace;
1331
1332   // split the face's edges by section edges lying on boundary
1333   TopoDS_Face aFace1 = SplitFaceBoundary (aFace, mySubst, myDSFiller,
1334                                           myEdgesToLeave, Standard_True, myMapModif);
1335   TopTools_DataMapOfShapeShape aMapNewOrig;
1336   UpdateMapNewOld (theFace, mySubst, aMapNewOrig);
1337
1338   // process section edges contacting the face boundary:
1339   // insert internal vertices in the boundary
1340   const TopTools_DataMapOfShapeShape& aMapEF =
1341     (theShapeNum==0 ? myMapSEdgeCrossFace1 : myMapSEdgeCrossFace2);
1342   BRep_Builder aBld;
1343   TopTools_DataMapOfShapeShape aMapNewOld;
1344   TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1345
1346   TopTools_MapOfShape aVerGener;
1347
1348   for (; aIterSE.More(); aIterSE.Next()) {
1349     const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1350     // skip edges lying on the boundary
1351     if (!aMapEF.IsBound (aSEdge)) continue;
1352
1353     // check if vertices of aSEdge contacts edges of aFace
1354     TopoDS_Iterator aIter (aSEdge, Standard_False);
1355     for (; aIter.More(); aIter.Next()) {
1356       const TopoDS_Vertex& aSVer = TopoDS::Vertex (aIter.Value());
1357       if (aSVer.Orientation() != TopAbs_FORWARD &&
1358           aSVer.Orientation() != TopAbs_REVERSED) continue;
1359
1360       TopoDS_Edge aEdge;
1361       TopoDS_Vertex aVer;
1362       Standard_Real aPar, aDist;
1363       if (IsVertexOnFaceBound (aSVer, aFace1, aEdge, aVer, aPar, aDist)) {
1364         // aSVer contacts aFace's boundary
1365
1366         if (!aVer.IsNull()) { // vertex contacted
1367           if (!aVer.IsSame(aSVer)) {
1368             // the vertices are coincided but not the same
1369             // => substitute aVer with aSVer
1370             Standard_Real aTol = Max (BRep_Tool::Tolerance(aSVer),
1371                                       BRep_Tool::Tolerance(aVer) + aDist);
1372             TopAbs_Orientation aOri = aVer.Orientation();
1373             if (aOri != TopAbs_FORWARD && aOri != TopAbs_REVERSED) {
1374               TopoDS_Shape aDummy = aSVer.Oriented(aOri);
1375               aBld.UpdateVertex (TopoDS::Vertex (aDummy),
1376                                  aPar, aEdge, aTol);
1377             }
1378             DoLocalSubstitution (aFace1, aVer, aSVer, aMapNewOld);
1379             // update history
1380             TopoDS_Shape aOrig = aMapNewOld(aSVer);
1381             if (aMapNewOrig.IsBound(aOrig)) aOrig = aMapNewOrig(aOrig);
1382             // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aOrig, TopTools_ListOfShape());
1383             TopTools_ListOfShape aListOfShape1;
1384             myMapModif.Bind(aOrig, aListOfShape1);
1385             myMapModif(aOrig).Append (aSVer);
1386             aVerGener.Add(aSVer);
1387             continue;
1388           }
1389         }
1390
1391         else { // contact inside edge
1392           // add the vertex as internal to the edge of the face
1393           TopoDS_Edge aNewEdge;
1394           InsertVertexInEdge (aEdge, aSVer, aPar, aNewEdge);
1395           // substitute edge
1396           DoLocalSubstitution (aFace1, aEdge, aNewEdge, aMapNewOld);
1397           // update history
1398           const TopoDS_Shape& aOld = aMapNewOld(aNewEdge);
1399           TopoDS_Shape aOrig;
1400           if (aMapNewOrig.IsBound(aOld)) {
1401             aOrig = aMapNewOrig(aOld);
1402             TopTools_ListOfShape& aListModif = myMapModif(aOrig);
1403             TopTools_ListIteratorOfListOfShape aIt (aListModif);
1404             for (; aIt.More(); aIt.Next())
1405               if (aIt.Value().IsSame(aOld)) {
1406                 aListModif.Remove (aIt);
1407                 break;
1408               }
1409             aListModif.Append (aNewEdge);
1410           }
1411           else {
1412             aOrig = aOld;
1413             // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aOrig, TopTools_ListOfShape());
1414             TopTools_ListOfShape aListOfShape2;
1415             myMapModif.Bind(aOrig, aListOfShape2);
1416             myMapModif(aOrig).Append (aNewEdge);
1417           }
1418           if (!myMapGener.IsBound (aOrig)) {
1419             // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aOrig, TopTools_ListOfShape());
1420             TopTools_ListOfShape aListOfShape3;
1421             myMapGener.Bind(aOrig, aListOfShape3);
1422           }
1423           myMapGener(aOrig).Append (aSVer);
1424           aVerGener.Add(aSVer);
1425         }
1426       }
1427     }
1428   }
1429
1430   // add the made replacements in the global substitution list
1431   TopTools_DataMapIteratorOfDataMapOfShapeShape aDIter (aMapNewOld);
1432   for (; aDIter.More(); aDIter.Next()) {
1433     TopTools_ListOfShape aList;
1434     const TopoDS_Shape& aOld = aDIter.Value();
1435     const TopoDS_Shape& aNew = aDIter.Key();
1436     aList.Append (aNew);
1437     mySubst.Substitute (aOld, aList);
1438   }
1439
1440   // make wires from section edges
1441   Handle(BRepAlgo_EdgeConnector) aConnector = new BRepAlgo_EdgeConnector;
1442   TopTools_ListOfShape aListGener;
1443   TopoDS_Vertex aV1, aV2;
1444   for (aIterSE.Initialize (theListSE); aIterSE.More(); aIterSE.Next()) {
1445     const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1446     if (aMapEF.IsBound (aSEdge)) {
1447       aConnector->Add (aSEdge);
1448       aConnector->AddStart (aSEdge);
1449       if(theGenEdges.Contains(aSEdge)) {
1450         aListGener.Append (aSEdge);
1451         TopExp::Vertices(aSEdge, aV1, aV2);
1452         if(aVerGener.Add(aV1)) aListGener.Append (aV1);
1453         if(aVerGener.Add(aV2)) aListGener.Append (aV2);
1454       }
1455     }
1456   }
1457   const TopTools_ListOfShape& aListW = aConnector->MakeBlock();
1458   if (aConnector->IsDone()) {
1459     // add new wires to face
1460     TopoDS_Face aNewFace = aFace1;
1461     aNewFace.EmptyCopy();
1462     aNewFace.Orientation(TopAbs_FORWARD);
1463     aBld.NaturalRestriction (aNewFace, BRep_Tool::NaturalRestriction(aFace1));
1464     // add old subshapes
1465     TopoDS_Iterator aIterF (aFace1, Standard_False);
1466     for (; aIterF.More(); aIterF.Next()) {
1467       aBld.Add (aNewFace, aIterF.Value());
1468     }
1469     // add new wires as internal
1470     TopTools_ListIteratorOfListOfShape aIterL (aListW);
1471     for (; aIterL.More(); aIterL.Next()) {
1472       TopoDS_Shape aWire = aIterL.Value();
1473       // check if there is a wire containing the same set of edges;
1474       // in this case use the old wire
1475       aWire = FindWireOrUpdateMap (aWire, myMapEdgeWires);
1476       aBld.Add (aNewFace, aWire.Oriented(TopAbs_INTERNAL));
1477     }
1478     // substitute face
1479     TopTools_ListOfShape aList;
1480     aList.Append(aNewFace);
1481     mySubst.Substitute(aFace, aList);
1482     // update history
1483     // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(theFace, TopTools_ListOfShape());
1484     TopTools_ListOfShape aListOfShape4;
1485     myMapModif.Bind(theFace, aListOfShape4);
1486     myMapModif(theFace).Append (aList);
1487     if(!aListGener.IsEmpty()) {
1488       // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(theFace, TopTools_ListOfShape());
1489       TopTools_ListOfShape aListOfShape5;
1490       myMapGener.Bind(theFace, aListOfShape5);
1491       myMapGener(theFace).Append (aListGener);
1492     }
1493   }
1494 #ifdef DEB
1495   else if (!aListW.IsEmpty()) {
1496     cout<<"QANewModTopOpe_Glue::SectionInsideFace : can't connect edges"<<endl;
1497   }
1498 #endif
1499 }
1500
1501 // @@SDM: begin
1502
1503 // Copyright SAMTECH ..........................................Version    3.0-00
1504 // Lastly modified by : skv                                    Date : 6-05-2003
1505
1506 // File history synopsis (creation,modification,correction)
1507 // +---------------------------------------------------------------------------+
1508 // ! Developer !              Comments                   !   Date   ! Version  !
1509 // +-----------!-----------------------------------------!----------!----------+
1510 // !       msv ! Creation                                !16-01-2001! 3.0-00-5!
1511 // !       skv ! Adaptation to OCC version 5.0           ! 6-05-2003! 3.0-00-2!
1512 // !  vladimir ! adaptation to CAS 5.0                   !  07/01/03!    4.0-1!
1513 // +---------------------------------------------------------------------------+
1514 //
1515 // @@SDM: end