0022967: Boolean operations between two cylinders with orthogonal axis generate a...
[occt.git] / src / BOP / BOP_SDFWESFiller.cxx
1 // File:        BOP_SDFWESFiller.cxx
2 // Created:     Wed Jun  6 12:48:58 2001
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6 #include <BOP_SDFWESFiller.ixx>
7
8 #include <gp_Pnt.hxx>
9
10 #include <TopoDS.hxx>
11 #include <TopoDS_Face.hxx>
12 #include <TopoDS_Shape.hxx>
13 #include <TopoDS_Edge.hxx>
14
15 #include <TopExp_Explorer.hxx>
16 #include <TopTools_IndexedMapOfOrientedShape.hxx>
17 #include <TopTools_IndexedMapOfShape.hxx>
18 #include <TopAbs_Orientation.hxx>
19
20 #include <BRep_Tool.hxx>
21
22 #include <TColStd_ListOfInteger.hxx>
23 #include <TColStd_IndexedMapOfInteger.hxx>
24 #include <TColStd_ListIteratorOfListOfInteger.hxx>
25
26 #include <BooleanOperations_ShapesDataStructure.hxx>
27 #include <BooleanOperations_StateOfShape.hxx>
28
29 #include <IntTools_Tools.hxx>
30 #include <IntTools_Context.hxx>
31
32 #include <BOPTools_Tools2D.hxx>
33 #include <BOPTools_Tools3D.hxx>
34 #include <BOPTools_ListOfPaveBlock.hxx>
35 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
36 #include <BOPTools_PaveBlock.hxx>
37 #include <BOPTools_PaveFiller.hxx>
38 #include <BOPTools_SplitShapesPool.hxx>
39 #include <BOPTools_CommonBlockPool.hxx>
40 #include <BOPTools_ListOfCommonBlock.hxx>
41 #include <BOPTools_ListIteratorOfListOfCommonBlock.hxx>
42 #include <BOPTools_CommonBlock.hxx>
43 #include <BOPTools_Tools.hxx>
44 #include <BOPTools_PointBetween.hxx>
45 #include <BOPTools_SolidStateFiller.hxx>
46
47 #include <BOPTColStd_Dump.hxx>
48 #include <TopTools_MapOfShape.hxx>
49 //
50 static Standard_Boolean IsValidSeam(const TopoDS_Edge& aE,
51                                     const TopoDS_Face& aF,
52                                     const Standard_Real aT,
53                                     const Handle(IntTools_Context)& aContext);
54
55 static void CorrespondantSeam(const TopoDS_Edge& aSpE1Seam11,
56                               const Standard_Real aT1,
57                               const TopoDS_Edge& aSpE1Seam21,
58                               const TopoDS_Edge& aSpE1Seam22,
59                               const Standard_Real aT2,
60                               const TopoDS_Face& aF1FWD,
61                               TopoDS_Edge& aSS);
62
63 static void TreatSDSeams (const TopoDS_Edge& aSpE1Seam11,
64                           const Standard_Real aT1,
65                           const TopoDS_Face& aF1FWD,
66                           const TopoDS_Edge& aSpE1Seam21,
67                           const Standard_Real aT2,
68                           const TopoDS_Face& aF2FWD,
69                           const Standard_Boolean bIsTakenSp1,
70                           BOP_WireEdgeSet& aWES,
71                           const Handle(IntTools_Context)& aContext);
72
73
74 //=======================================================================
75 // function: BOP_SDFWESFiller::BOP_SDFWESFiller
76 // purpose: 
77 //=======================================================================
78   BOP_SDFWESFiller::BOP_SDFWESFiller()
79 :
80   myDSFiller(NULL),
81   myOperation(BOP_UNKNOWN),
82   myNF1(0),
83   myNF2(0),
84   mySenseFlag(0)
85 {}
86
87 //=======================================================================
88 // function: BOP_SDFWESFiller::BOP_SDFWESFiller
89 // purpose: 
90 //=======================================================================
91   BOP_SDFWESFiller::BOP_SDFWESFiller(const Standard_Integer nF1,
92                                      const Standard_Integer nF2,
93                                      const BOPTools_DSFiller& aDSFiller)
94 :
95   myNF1(nF1),
96   myNF2(nF2),
97   mySenseFlag(0)
98 {
99   myDSFiller=(BOPTools_DSFiller*) &aDSFiller;
100   Prepare();
101 }
102 //=======================================================================
103 // function: SetStatesMap
104 // purpose: 
105 //=======================================================================
106   void BOP_SDFWESFiller::SetStatesMap (const BOPTools_IndexedDataMapOfIntegerState& aMap)
107 {
108   myStatesMap.Clear();
109   myStatesMap=aMap;
110 }
111 //=======================================================================
112 // function: StatesMap
113 // purpose: 
114 //=======================================================================
115   const BOPTools_IndexedDataMapOfIntegerState& BOP_SDFWESFiller::StatesMap ()const
116 {
117   return myStatesMap;
118 }
119
120 //=======================================================================
121 // function: SetFaces
122 // purpose: 
123 //=======================================================================
124   void BOP_SDFWESFiller::SetFaces (const Standard_Integer nF1,
125                                    const Standard_Integer nF2)
126 {
127    myNF1=nF1;
128    myNF2=nF2;
129 }
130 //=======================================================================
131 // function: SetSenseFlag
132 // purpose: 
133 //=======================================================================
134   void BOP_SDFWESFiller::SetSenseFlag (const Standard_Integer iFlag)
135                                  
136 {
137    mySenseFlag=iFlag;
138 }
139
140 //=======================================================================
141 // function: SenseFlag
142 // purpose: 
143 //=======================================================================
144   Standard_Integer BOP_SDFWESFiller::SenseFlag () const
145                                  
146 {
147    return mySenseFlag;
148 }
149
150 //=======================================================================
151 // function: Faces
152 // purpose: 
153 //=======================================================================
154   void BOP_SDFWESFiller::Faces (Standard_Integer& nF1,
155                                 Standard_Integer& nF2) const
156 {
157    nF1=myNF1;
158    nF2=myNF2;
159 }
160 //=======================================================================
161 // function: SetDSFiller
162 // purpose: 
163 //=======================================================================
164   void BOP_SDFWESFiller::SetDSFiller(const BOPTools_DSFiller& aDSFiller)
165 {
166    myDSFiller=(BOPTools_DSFiller*) &aDSFiller;
167 }
168
169 //=======================================================================
170 // function: DSFiller
171 // purpose: 
172 //=======================================================================
173   const BOPTools_DSFiller& BOP_SDFWESFiller::DSFiller()const
174 {
175   return *myDSFiller;
176 }
177
178 //=======================================================================
179 // function: SetOperation
180 // purpose: 
181 //=======================================================================
182   void BOP_SDFWESFiller::SetOperation(const BOP_Operation anOp)
183 {
184   myOperation=anOp;
185 }
186 //=======================================================================
187 // function: Operation
188 // purpose: 
189 //=======================================================================
190   BOP_Operation BOP_SDFWESFiller::Operation()const
191 {
192   return myOperation;
193 }
194 //xf
195 //=======================================================================
196 //function : RejectedOnParts
197 //purpose  : 
198 //=======================================================================
199   const TopTools_ListOfShape& BOP_SDFWESFiller::RejectedOnParts()const
200 {
201   return myRejectedOnParts;
202 }
203 //xt
204 //=======================================================================
205 // function: Prepare
206 // purpose: 
207 //======================================================================= 
208   void BOP_SDFWESFiller::Prepare()
209 {
210   if (!myNF1 || !myNF2) {
211     return;
212   }
213   //
214   // 1. Prepare States 2D for the Faces' entities  (myStatesMap)
215   AssignStates(myNF1, myNF2);
216   AssignStates(myNF2, myNF1);
217   //
218   AssignDEStates(myNF1, myNF2);
219   AssignDEStates(myNF2, myNF1);
220   //
221   //  
222   // 2.
223   PrepareOnParts();
224   //
225 }
226
227 //=======================================================================
228 // function: Do
229 // purpose: 
230 //======================================================================= 
231   void BOP_SDFWESFiller::Do(const BOP_WireEdgeSet& pWES)
232 {
233   
234   myWES=(BOP_WireEdgeSet*) &pWES;
235
236   if (!myNF1 || !myNF2) {
237     return;
238   }
239   
240   //
241   // WES
242   switch (myOperation) {
243     case BOP_COMMON: {
244       PrepareWESForZone (myNF1, myNF2);
245       break;
246     }
247     case BOP_CUT: {
248       PrepareWESForCut (myNF1, myNF2);
249       break;
250     }
251     case BOP_CUT21: {
252       PrepareWESForCut (myNF2, myNF1);
253       break;
254     }
255     default: {
256       return;
257     }
258   }
259 }
260
261 //=======================================================================
262 // function: AssignStates
263 // purpose: 
264 //======================================================================= 
265   void BOP_SDFWESFiller::AssignStates(const Standard_Integer nF1,
266                                       const Standard_Integer nF2) 
267 {
268   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
269   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
270   BOPTools_PaveFiller* pPaveFiller=(BOPTools_PaveFiller*) &aPaveFiller;
271   const BOPTools_SplitShapesPool& aSplitShapesPool=aPaveFiller.SplitShapesPool();
272   //
273   Standard_Integer aBid=0, nSplit, nE, nW, nSp, anEdgeFlag, aWireFlag, aNbPB, iRankF1;
274   TColStd_ListOfInteger aList1IN2, aList1ON2;
275   TColStd_IndexedMapOfInteger aSpMapIN, aSpMapON;
276   TColStd_ListIteratorOfListOfInteger anIt;
277   //
278   iRankF1=aDS.Rank(nF1);
279   //
280   const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1));
281   // 
282   //  Splits that are from nF2 and are IN2D for nF2
283   pPaveFiller->SplitsInFace (aBid, nF1, nF2, aList1IN2);
284   
285   anIt.Initialize(aList1IN2);
286   for (; anIt.More();  anIt.Next()) {
287     nSplit=anIt.Value();
288     aSpMapIN.Add(nSplit);
289   }
290   //
291   // that are from nF2 and are ON2D for nF2
292   pPaveFiller->SplitsOnFace (aBid, nF1, nF2, aList1ON2);
293   
294   anIt.Initialize(aList1ON2);
295   for (; anIt.More();  anIt.Next()) {
296     nSplit=anIt.Value();
297     aSpMapON.Add(nSplit);
298   }
299   //
300   // Treatment of the Face's entities
301   aWireFlag=1;
302   TopExp_Explorer anExpWire(aF1, TopAbs_WIRE);
303   for (; anExpWire.More(); anExpWire.Next()) {
304     const TopoDS_Shape& aWire=anExpWire.Current();
305     nW=aDS.ShapeIndex(aWire, iRankF1);
306     anEdgeFlag=1;
307
308     TopExp_Explorer anExpEdge (aWire, TopAbs_EDGE);
309     for (; anExpEdge.More(); anExpEdge.Next()) {
310       const TopoDS_Shape& anEdge=anExpEdge.Current();
311       nE=aDS.ShapeIndex(anEdge, iRankF1);
312       
313       const BOPTools_ListOfPaveBlock& aLPB=aSplitShapesPool(aDS.RefEdge(nE));
314
315       aNbPB=aLPB.Extent();
316       if (!aNbPB) {
317         // the whole edge is OUT
318         myStatesMap.Add(nE, BooleanOperations_OUT);
319         continue;
320       }
321
322       BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aLPB);
323
324       for (;  aPBIt.More();  aPBIt.Next()) {
325         const BOPTools_PaveBlock& aPB=aPBIt.Value();
326         nSp=aPB.Edge();
327         
328         if (aSpMapIN.Contains(nSp)) {// IN
329           myStatesMap.Add(nSp, BooleanOperations_IN);
330           anEdgeFlag=0;
331         }
332         else if (aSpMapON.Contains(nSp)) {// ON
333           myStatesMap.Add(nSp, BooleanOperations_ON);
334           anEdgeFlag=0;
335         }
336         else {// if (nSp!=nE) {// OUT
337           myStatesMap.Add(nSp, BooleanOperations_OUT);
338         }
339       } 
340     } //  enf of for (; anExpEdge.More(); anExpEdge.Next()) 
341      
342     if (anEdgeFlag) {// all Wire is out
343       myStatesMap.Add(nW, BooleanOperations_OUT);
344     }
345     else {
346       aWireFlag=0;
347     }
348   } // enf of for (; anExpEdge.More(); anExpEdge.Next())
349   
350   if (aWireFlag) { // all Face is out of nF2
351     myStatesMap.Add(nF1, BooleanOperations_OUT);
352   }
353 }
354
355 //=======================================================================
356 // function: PrepareOnParts
357 // purpose: 
358 //=======================================================================
359   void BOP_SDFWESFiller::PrepareOnParts ()
360 {
361   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
362   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
363   BOPTools_PaveFiller* pPaveFiller=(BOPTools_PaveFiller*) &aPaveFiller;
364   BOPTools_CommonBlockPool& aCBPool=pPaveFiller->ChangeCommonBlockPool();
365   //
366   Standard_Integer aBid=0, nE1, nE2, aNbSpON, nSp1, nSp2, iRankF1;
367   Standard_Real aT1, aT2, aT, aTs; /*, U, V;*/ 
368   Standard_Boolean aFlag;
369   TColStd_ListOfInteger aLs;
370   TColStd_IndexedMapOfInteger aMap;
371   TopExp_Explorer anExpF1, anExpF2;
372   //
373   iRankF1=aDS.Rank(myNF1);
374
375   gp_Pnt aPx1;
376   //
377   TopoDS_Face aF1FWD, aF2FWD;
378   PrepareFaces(myNF1, myNF2, aF1FWD, aF2FWD);
379   //
380   // Process 
381   anExpF1.Init(aF1FWD, TopAbs_EDGE);
382   for (; anExpF1.More(); anExpF1.Next()) {
383     const TopoDS_Edge& anE1=TopoDS::Edge(anExpF1.Current());
384     //
385     if (BRep_Tool::Degenerated(anE1)){
386       continue;
387     }
388     //
389     nE1=aDS.ShapeIndex(anE1, iRankF1);
390
391     aLs.Clear();
392     pPaveFiller->SplitsOnFace(nE1, myNF2, aLs);
393     
394     aNbSpON=aLs.Extent();
395     if (!aNbSpON) {
396       continue;
397     }
398
399     aMap.Clear();
400     TColStd_ListIteratorOfListOfInteger anItLs(aLs);
401     for (; anItLs.More(); anItLs.Next()) {
402       aBid=anItLs.Value();
403       aMap.Add(aBid);
404     }
405
406     BOPTools_ListOfCommonBlock& aLCB=aCBPool(aDS.RefEdge(nE1));
407     BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
408     for (; anItCB.More(); anItCB.Next()) {
409       BOPTools_CommonBlock& aCB=anItCB.Value();
410       BOPTools_PaveBlock& aPB1=aCB.PaveBlock1(nE1);
411       nSp1=aPB1.Edge();
412       if (aMap.Contains(nSp1)) {
413         //
414         // aPB1
415         aPB1.Parameters(aT1, aT2);
416         aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
417         BOPTools_Tools::PointOnEdge(anE1, aT, aPx1);
418
419         BOPTools_PointBetween aPointBetween;
420         aPointBetween.SetParameter(aT);
421         aPointBetween.SetPnt(aPx1);
422         
423         aPB1.SetPointBetween(aPointBetween);
424         //
425         // aPB2
426         BOPTools_PaveBlock& aPB2=aCB.PaveBlock2(nE1);
427         nE2=aPB2.OriginalEdge();
428         nSp2=aPB2.Edge();
429         const TopoDS_Edge& anE2=TopoDS::Edge(aDS.GetShape(nE2));
430         //
431         const Handle(IntTools_Context)& aContext=pPaveFiller->Context();
432         aFlag=aContext->ProjectPointOnEdge(aPx1, anE2, aTs);
433         //
434         if (!aFlag) {
435           BOPTColStd_Dump::PrintMessage(" BOP_SDFWESFiller::PrepareOnParts() failed\n");
436           return;
437         }
438
439         aPointBetween.SetParameter(aTs);
440         aPointBetween.SetPnt(aPx1);
441         
442         aPB2.SetPointBetween(aPointBetween);
443         //
444         BOPTools_ListOfCommonBlock& aLCB2=aCBPool(aDS.RefEdge(nE2));
445         BOPTools_ListIteratorOfListOfCommonBlock anItCB2(aLCB2);
446         for (; anItCB2.More(); anItCB2.Next()){
447           BOPTools_CommonBlock& aCB2=anItCB2.Value();
448           BOPTools_PaveBlock& aPB21=aCB2.PaveBlock1(nE2);
449           BOPTools_PaveBlock& aPB22=aCB2.PaveBlock2(nE2);
450           
451           if ((aPB21.IsEqual(aPB1) && aPB22.IsEqual(aPB2)) 
452               ||
453               (aPB21.IsEqual(aPB2) && aPB22.IsEqual(aPB1))) {
454             
455             aPointBetween.SetPnt(aPx1);
456             
457             aPointBetween.SetParameter(aTs);
458             aPB21.SetPointBetween(aPointBetween);
459             
460             aPointBetween.SetParameter(aT);
461             aPB22.SetPointBetween(aPointBetween);
462             
463             break;
464           }
465         }
466         //
467       }
468     }
469   }
470 }
471
472 //=======================================================================
473 // function: PrepareWESForZone
474 // purpose: 
475 //=======================================================================
476   void BOP_SDFWESFiller::PrepareWESForZone (const Standard_Integer nF1, 
477                                             const Standard_Integer nF2)
478 {
479   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
480   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
481   const BOPTools_SplitShapesPool& aSplitShapesPool=aPaveFiller.SplitShapesPool();
482   BOP_WireEdgeSet& aWES=*myWES;
483   //
484   Standard_Integer nE, nSp, iRankF1, iRankF2; 
485   
486   TopAbs_Orientation anOr;
487   BooleanOperations_StateOfShape aState;
488   TopTools_IndexedMapOfOrientedShape aMap;
489   //
490   iRankF1=aDS.Rank(nF1);
491   iRankF2=aDS.Rank(nF2);
492   // W E S 
493   TopoDS_Face aF1FWD, aF2FWD; 
494   PrepareFaces(nF1, nF2, aF1FWD, aF2FWD);
495
496   TopExp_Explorer anExp;
497   //
498   // aF1FWD
499   anExp.Init(aF1FWD, TopAbs_EDGE);
500   for (; anExp.More(); anExp.Next()) {
501     const TopoDS_Shape& anE=anExp.Current();
502     anOr=anE.Orientation();
503
504     nE=aDS.ShapeIndex(anE, iRankF1);
505
506     const BOPTools_ListOfPaveBlock& aLPB=aSplitShapesPool(aDS.RefEdge(nE));
507     BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aLPB);
508     for (; aPBIt.More(); aPBIt.Next()) {
509       const BOPTools_PaveBlock& aPB=aPBIt.Value();
510       nSp=aPB.Edge();
511       //>>>
512       if (!myStatesMap.Contains(nSp)) {
513         continue;
514       }
515       //>>>
516       aState=myStatesMap.FindFromKey(nSp);
517       
518       if (aState==BooleanOperations_IN) {
519         
520         const TopoDS_Shape& aSplit=aDS.Shape(nSp);
521         TopoDS_Edge aSS=TopoDS::Edge(aSplit);
522         aSS.Orientation(anOr);
523         //
524         if (aMap.Contains(aSS)) {
525           continue;
526         }
527         //
528         aWES.AddStartElement (aSS);
529         aMap.Add(aSS);  
530
531         if (BRep_Tool::IsClosed(aSS, aF1FWD)){
532           TopoDS_Shape EE=aSS.Reversed();
533           aWES.AddStartElement (EE);
534           aMap.Add(EE);
535         }
536       }
537     }
538   }
539   //
540   // aF2FWD
541   aMap.Clear();
542   anExp.Init(aF2FWD, TopAbs_EDGE);
543   for (; anExp.More(); anExp.Next()) {
544     const TopoDS_Shape& anE=anExp.Current();
545
546     anOr=anE.Orientation();
547
548     nE=aDS.ShapeIndex(anE, iRankF2);
549
550     const BOPTools_ListOfPaveBlock& aLPB=aSplitShapesPool(aDS.RefEdge(nE));
551     
552     BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aLPB);
553     for (; aPBIt.More(); aPBIt.Next()) {
554       const BOPTools_PaveBlock& aPB=aPBIt.Value();
555       nSp=aPB.Edge();
556       //>>>
557       if (!myStatesMap.Contains(nSp)) {
558         continue;
559       }
560       //>>>
561       aState=myStatesMap.FindFromKey(nSp);
562       
563       if (aState==BooleanOperations_IN) {
564         const TopoDS_Shape& aSplit=aDS.Shape(nSp);
565         TopoDS_Edge aSS=TopoDS::Edge(aSplit);
566         //
567         if (!BOPTools_Tools2D::HasCurveOnSurface(aSS, aF1FWD)) {
568           continue;
569         }
570         //
571         aSS.Orientation(anOr);
572         //
573         if (aMap.Contains(aSS)) {
574           continue;
575         }
576         //      
577         aWES.AddStartElement (aSS);
578         aMap.Add(aSS);
579
580         if (BRep_Tool::IsClosed(aSS, aF2FWD)){
581           TopoDS_Shape EE=aSS.Reversed();
582           aWES.AddStartElement (EE);
583           aMap.Add(EE);
584         }
585       }
586     }
587   }
588
589   PrepareOnParts(nF1, nF2, BOP_COMMON);
590 }
591
592 //=======================================================================
593 // function: PrepareWESForCut
594 // purpose: 
595 //=======================================================================
596   void BOP_SDFWESFiller::PrepareWESForCut (const Standard_Integer nF1, 
597                                            const Standard_Integer nF2)
598 {
599   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
600   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
601   const BOPTools_SplitShapesPool& aSplitShapesPool=aPaveFiller.SplitShapesPool();
602   BOP_WireEdgeSet& aWES=*myWES;
603   //
604   Standard_Integer  nE, nSp, nPB, iRankF2;
605   TopAbs_Orientation anOr;
606   BooleanOperations_StateOfShape aState;
607
608   iRankF2=aDS.Rank(nF2);
609   //
610   // W E S 
611   TopoDS_Face aF1FWD, aF2FWD; 
612   PrepareFaces(nF1, nF2, aF1FWD, aF2FWD);
613
614   aF2FWD.Reverse();
615   
616   TopExp_Explorer anExp;
617   //
618   //  aF2FWD
619   anExp.Init(aF2FWD, TopAbs_EDGE);
620   for (; anExp.More(); anExp.Next()) {
621     const TopoDS_Shape& anE=anExp.Current();
622     anOr=anE.Orientation();
623
624     nE=aDS.ShapeIndex(anE, iRankF2);
625
626     const BOPTools_ListOfPaveBlock& aLPB=aSplitShapesPool(aDS.RefEdge(nE));
627
628     nPB=aLPB.Extent();
629     if (nPB) {
630       BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aLPB);
631       for (; aPBIt.More(); aPBIt.Next()) {
632         const BOPTools_PaveBlock& aPB=aPBIt.Value();
633         nSp=aPB.Edge();
634         //>>>
635         if (!myStatesMap.Contains(nSp)) {
636           continue;
637         }
638         //>>>
639         aState=myStatesMap.FindFromKey(nSp);
640         
641         if (aState==BooleanOperations_IN) {
642           const TopoDS_Shape& aSplit=aDS.Shape(nSp);
643           TopoDS_Edge aSS=TopoDS::Edge(aSplit);
644           //
645           if (!BOPTools_Tools2D::HasCurveOnSurface(aSS, aF1FWD)) {
646             continue;
647           }
648           //
649           aSS.Orientation(anOr);
650           //
651           aWES.AddStartElement (aSS);
652           //
653           if (BRep_Tool::IsClosed(aSS, aF2FWD)){
654             TopoDS_Shape EE=aSS.Reversed();
655             aWES.AddStartElement (EE);
656           }
657         }
658       }
659     }
660     else {
661       //>>>
662       if (!myStatesMap.Contains(nE)) {
663         continue;
664       }
665       //>>>
666       aState=myStatesMap.FindFromKey(nE);
667       if (aState==BooleanOperations_IN) {
668         TopoDS_Edge aSS=TopoDS::Edge(anE);
669         //
670         aWES.AddStartElement (aSS);
671       }
672     }
673   } // end of for (; anExp.More(); anExp.Next()) {
674   
675   PrepareOnParts(nF1, nF2, BOP_CUT);
676 }
677 //=======================================================================
678 // function: PrepareOnParts
679 // purpose: 
680 //=======================================================================
681   void BOP_SDFWESFiller::PrepareOnParts (const Standard_Integer nF1, 
682                                          const Standard_Integer nF2,
683                                          const BOP_Operation anOperation)
684 {
685   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
686   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
687   BOPTools_PaveFiller* pPaveFiller=(BOPTools_PaveFiller*) &aPaveFiller;
688   BOPTools_CommonBlockPool& aCBPool=pPaveFiller->ChangeCommonBlockPool();
689   BOP_WireEdgeSet& aWES=*myWES;
690   //
691   const Handle(IntTools_Context)& aContext=pPaveFiller->Context();
692   //
693   Standard_Integer nE1, nE2, aNbSpON, nSp1, aBid, nSpTaken, nSp2, iRankF1, iRankF2;
694   Standard_Real aT1, aT2, aU, aV, aScPr;
695   Standard_Boolean bToReverse, bInternal1, bInternal2, bAdded;
696   
697   TopoDS_Edge aSS, aSSx;
698   TopoDS_Face aF1FWD, aF2FWD;
699   TopAbs_Orientation anOr, anOr2;
700
701   TColStd_ListOfInteger aLs;
702   TColStd_IndexedMapOfInteger aMap;
703   TopTools_IndexedMapOfShape aM;
704   TopTools_MapOfShape aMFence;//xft
705   //
706   gp_Vec aN1, aN2, aTau1, aTau2, aBiN1, aBiN2;
707   TopExp_Explorer anExpF1, anExpF2;
708   //
709   // Source faces
710   iRankF1=aDS.Rank(nF1);
711   iRankF2=aDS.Rank(nF2);
712   //
713   PrepareFaces(nF1, nF2, aF1FWD, aF2FWD);
714   //
715   myRejectedOnParts.Clear();//xft
716   //
717   anExpF1.Init(aF1FWD, TopAbs_EDGE);
718   for (; anExpF1.More(); anExpF1.Next()) {
719     const TopoDS_Edge& anE1=TopoDS::Edge(anExpF1.Current());
720     anOr=anE1.Orientation();
721     //
722     if (BRep_Tool::Degenerated(anE1)){
723       continue;
724     }
725     //
726     nE1=aDS.ShapeIndex(anE1, iRankF1); 
727
728     anExpF2.Init(aF2FWD, TopAbs_EDGE);
729     for (; anExpF2.More(); anExpF2.Next()) {
730       const TopoDS_Edge& anE2=TopoDS::Edge(anExpF2.Current());
731       anOr2=anE2.Orientation();
732       //
733       if (BRep_Tool::Degenerated(anE2)){
734         continue;
735       }
736       //
737       nE2=aDS.ShapeIndex(anE2, iRankF2);
738       aLs.Clear();
739       pPaveFiller->SplitsOnEdge(nE1, nE2, aLs);
740       
741       aNbSpON=aLs.Extent();
742       if (!aNbSpON) {
743         continue;
744       }
745
746       aMap.Clear();
747       TColStd_ListIteratorOfListOfInteger anItLs(aLs);
748       for (; anItLs.More(); anItLs.Next()) {
749         aBid=anItLs.Value();
750         aMap.Add(aBid);
751       }
752
753       BOPTools_ListOfCommonBlock& aLCB=aCBPool(aDS.RefEdge(nE1));
754       BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
755       for (; anItCB.More(); anItCB.Next()) {
756         bAdded=Standard_False;//xft
757         BOPTools_CommonBlock& aCB=anItCB.Value();
758         // Pave Block from which new edge will be taken
759         const BOPTools_PaveBlock& aPB=aCB.PaveBlock1();
760         nSpTaken=aPB.Edge();
761         const TopoDS_Shape& aSpTaken=aDS.Shape(nSpTaken);
762         //
763         BOPTools_PaveBlock& aPB1=aCB.PaveBlock1(nE1);
764         nSp1=aPB1.Edge();
765         
766         if (aMap.Contains(nSp1)) {
767           BOPTools_PaveBlock& aPB2=aCB.PaveBlock2(nE1);
768           nSp2=aPB2.Edge();
769           //
770           //
771           //iiiiiiiiiiiiiiiii Tue Dec 25 15:10:09 2001 iiiiii
772           //
773           // Internal eges' processing
774           bInternal1=(anOr ==TopAbs_INTERNAL);
775           bInternal2=(anOr2==TopAbs_INTERNAL);
776           //
777           if (bInternal1 || bInternal2) {
778             aSS=TopoDS::Edge(aDS.Shape(nSpTaken));
779             // a.
780             if (bInternal1 && bInternal2) {
781               if (anOperation==BOP_COMMON) {
782                 aWES.AddStartElement (aSS);
783                 bAdded=Standard_True;//xft
784               }
785             }
786             // b.
787             else { // else x 
788               if (bInternal1 && !bInternal2) {
789                 if (nSpTaken==nSp1) {
790                   aSS.Orientation(TopAbs_FORWARD);
791                   aSSx=TopoDS::Edge(aDS.Shape(nSp2));
792                   aSSx.Orientation(anOr2);
793                   //
794                   bToReverse=BOPTools_Tools3D::IsSplitToReverse1 (aSSx, aSS, aContext);
795                   //
796                   if (bToReverse) {
797                     aSS.Reverse();
798                   }
799                 }
800                 else {//nSpTaken!=nSp1
801                   aSS.Orientation(anOr2);
802                 }
803               }
804               // c.
805               else if (!bInternal1 && bInternal2) {
806                 if (nSpTaken==nSp2) {
807                   aSS.Orientation(TopAbs_FORWARD);
808                   aSSx=TopoDS::Edge(aDS.Shape(nSp1));
809                   aSSx.Orientation(anOr);
810                   //
811                   bToReverse=BOPTools_Tools3D::IsSplitToReverse1 (aSSx, aSS, aContext);
812                   //
813                   if (bToReverse) {
814                     aSS.Reverse();
815                   }
816                 }
817                 else {//nSpTaken!=nSp2
818                   aSS.Orientation(anOr);
819                 }
820               }
821               // writting
822               if (anOperation==BOP_COMMON) {
823                 aWES.AddStartElement (aSS);
824                 bAdded=Standard_True;//xft
825               }
826               if (anOperation==BOP_CUT) { 
827                 aSS.Reverse();
828                 aWES.AddStartElement (aSS);
829                 bAdded=Standard_True;//xft
830               }
831             } // else x 
832             continue;
833           }  
834           //
835           //iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
836           //
837           //
838           const BOPTools_PointBetween &aPbn1=aPB1.PointBetween();
839           aT1=aPbn1.Parameter();
840           BOPTools_Tools2D::EdgeTangent(anE1, aT1, aTau1);
841           
842           BOPTools_Tools2D::PointOnSurface(anE1, aF1FWD, aT1, aU, aV);
843           BOPTools_Tools2D::FaceNormal(aF1FWD, aU, aV, aN1);
844           aBiN1=aN1^aTau1;
845           
846           const BOPTools_PointBetween &aPbn2=aPB2.PointBetween();
847           aT2=aPbn2.Parameter();
848           BOPTools_Tools2D::EdgeTangent(anE2, aT2, aTau2);
849           
850           BOPTools_Tools2D::PointOnSurface(anE2, aF2FWD, aT2, aU, aV);
851           BOPTools_Tools2D::FaceNormal(aF2FWD, aU, aV, aN2);
852           aBiN2=aN2^aTau2;
853
854           aScPr=aBiN1*aBiN2;
855           //
856           if (aScPr < 0.) {
857             if (anOperation==BOP_CUT) { 
858               
859               if (nSpTaken==nSp1) {
860                 aSS=TopoDS::Edge(aDS.GetShape(nSp1));
861                 aSS.Orientation(anOr);
862               }
863               
864               else {
865                 const TopoDS_Shape& aSp1=aDS.Shape(nSp1);
866                 TopoDS_Edge aSpE1=TopoDS::Edge(aSp1);
867                 aSpE1.Orientation(anOr);
868
869                 const TopoDS_Shape& aSp2=aDS.Shape(nSp2);
870                 TopoDS_Edge aSpE2=TopoDS::Edge(aSp2);
871                 //
872                 bToReverse=BOPTools_Tools3D::IsSplitToReverse1 (aSpE1, aSpE2, aContext);
873                 //
874                 if (bToReverse) {
875                   aSpE2.Reverse();
876                 }
877                 aSS=aSpE2;
878               }
879               // modified by NIZHNY-MKK  Thu May 29 12:39:32 2003.BEGIN
880               if (BRep_Tool::IsClosed(anE1, aF1FWD) && (!aSS.IsSame(anE1))) {
881                 Standard_Boolean areverse = Standard_False;
882                 BOPTools_Tools3D::DoSplitSEAMOnFace(aSS, anE1, aF1FWD, areverse);
883               }
884
885               if(BRep_Tool::IsClosed(anE2, aF2FWD) && (!aSS.IsSame(anE2))) {
886                 Standard_Boolean areverse = Standard_False;
887                 BOPTools_Tools3D::DoSplitSEAMOnFace(aSS, anE2, aF2FWD, areverse);
888               }
889               // modified by NIZHNY-MKK  Thu May 29 12:39:35 2003.END
890               //
891               if (BRep_Tool::IsClosed(anE1, aF1FWD) &&
892                   BRep_Tool::IsClosed(anE2, aF2FWD)){
893                 //
894                 Standard_Boolean bIsTakenSp1;
895                 TopoDS_Edge aSpE1Seam11, aSpE1Seam21;
896
897                 bIsTakenSp1=(nSpTaken==nSp1);
898                 aSpE1Seam11=TopoDS::Edge(aDS.Shape(nSp1));
899                 aSpE1Seam21=TopoDS::Edge(aDS.Shape(nSp2));
900                 //
901                 if (aM.Contains(aSpE1Seam11)){
902                   continue;
903                 }
904                 aM.Add(aSpE1Seam11);
905                 //
906                 if (aM.Contains(aSpE1Seam21)){
907                   continue;
908                 }
909                 aM.Add(aSpE1Seam21);
910                 //
911                 TreatSDSeams (aSpE1Seam11, aT1, aF1FWD, 
912                               aSpE1Seam21, aT2, aF2FWD,
913                               bIsTakenSp1, aWES,
914                               aContext);
915                 //
916                 continue;
917               }
918               //
919               aWES.AddStartElement (aSS);
920               bAdded=Standard_True;//xft
921             } 
922             
923           }
924           
925           else {
926             if (anOperation==BOP_COMMON) {
927               
928               if (nSpTaken==nSp1) {
929                 aSS=TopoDS::Edge(aDS.GetShape(nSp1));
930                 aSS.Orientation(anOr);
931               }
932               
933               else {
934                 const TopoDS_Shape& aSp1=aDS.Shape(nSp1);
935                 TopoDS_Edge aSpE1=TopoDS::Edge(aSp1);
936                 aSpE1.Orientation(anOr);
937
938                 const TopoDS_Shape& aSp2=aDS.Shape(nSp2);
939                 TopoDS_Edge aSpE2=TopoDS::Edge(aSp2);
940                 //
941                 bToReverse=BOPTools_Tools3D::IsSplitToReverse1 (aSpE1, aSpE2, aContext);
942                 //
943                 if (bToReverse) {
944                   aSpE2.Reverse();
945                 }
946                 aSS=aSpE2;
947                 //
948                 if (BRep_Tool::IsClosed(aSpE1, aF1FWD)) {
949                   //
950                   if (aM.Contains(aSpE2)){
951                     continue;
952                   }
953                   aM.Add(aSpE2);
954                   //
955                   if (!BRep_Tool::IsClosed(aSpE2, aF1FWD)) {
956                     BOPTools_Tools3D::DoSplitSEAMOnFace (aSpE2, aF1FWD);
957                   }
958                   aWES.AddStartElement (aSpE2);
959                   aSpE2.Reverse();
960                   aWES.AddStartElement (aSpE2);
961                   bAdded=Standard_True; //xft
962                   continue;  
963                 }
964                 //
965               }
966               //
967               aWES.AddStartElement (aSS);
968               bAdded=Standard_True; //xft
969             }// if (anOperation==BOP_COMMON) {
970           }// else {
971           if (!bAdded) {
972             if(aMFence.Add(aSpTaken)) { 
973               myRejectedOnParts.Append(aSpTaken);
974             }
975           }
976         }// if (aMap.Contains(nSp1)) { 
977       }// for (; anItCB.More(); anItCB.Next()) {
978     }// for (; anExpF2.More(); anExpF2.Next()) {
979   }//for (; anExpF1.More(); anExpF1.Next()) {
980 }
981
982 //=======================================================================
983 // function: PrepareFaces
984 // purpose: 
985 //=======================================================================
986   void BOP_SDFWESFiller::PrepareFaces   (const Standard_Integer nF1, 
987                                          const Standard_Integer nF2, 
988                                          TopoDS_Face& aF1FWD,
989                                          TopoDS_Face& aF2FWD) const
990 {
991   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
992   TopAbs_Orientation anOr1, anOr2;
993
994   const TopoDS_Shape& aF1=aDS.GetShape(nF1); 
995   aF1FWD=TopoDS::Face(aF1);
996   anOr1=aF1.Orientation();
997
998   const TopoDS_Shape& aF2=aDS.GetShape(nF2);
999   aF2FWD=TopoDS::Face(aF2);
1000   anOr2=aF2.Orientation();
1001
1002   aF1FWD.Orientation(TopAbs_FORWARD);
1003
1004   if (mySenseFlag==1) {
1005     if      (anOr1==TopAbs_FORWARD   && anOr2==TopAbs_FORWARD) {
1006       aF2FWD.Orientation(TopAbs_FORWARD);
1007     }
1008     else if (anOr1==TopAbs_REVERSED  && anOr2==TopAbs_REVERSED) {
1009       aF2FWD.Orientation(TopAbs_FORWARD);
1010     }
1011     else if (anOr1==TopAbs_FORWARD  && anOr2==TopAbs_REVERSED) {
1012       aF2FWD.Orientation(TopAbs_REVERSED);
1013     }
1014     else if (anOr1==TopAbs_REVERSED  && anOr2==TopAbs_FORWARD) {
1015       aF2FWD.Orientation(TopAbs_REVERSED);
1016     }
1017   }
1018
1019   else{
1020     if      (anOr1==TopAbs_FORWARD   && anOr2==TopAbs_FORWARD) {
1021       aF2FWD.Orientation(TopAbs_REVERSED);
1022     }
1023     else if (anOr1==TopAbs_REVERSED  && anOr2==TopAbs_REVERSED) {
1024       aF2FWD.Orientation(TopAbs_REVERSED);
1025     }
1026     else if (anOr1==TopAbs_FORWARD  && anOr2==TopAbs_REVERSED) {
1027       aF2FWD.Orientation(TopAbs_FORWARD);
1028     }
1029     else if (anOr1==TopAbs_REVERSED  && anOr2==TopAbs_FORWARD) {
1030       aF2FWD.Orientation(TopAbs_FORWARD);
1031     }
1032   }
1033 }
1034 //
1035 //=======================================================================
1036 // function: AssignDEStates
1037 // purpose: 
1038 //======================================================================= 
1039   void BOP_SDFWESFiller::AssignDEStates(const Standard_Integer nF1,
1040                                         const Standard_Integer nF2) 
1041 {
1042   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
1043   
1044   Standard_Integer nE1, iRankF1;
1045   TopExp_Explorer anExpF1;
1046
1047   iRankF1=aDS.Rank(nF1);
1048
1049   const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1));
1050
1051   anExpF1.Init(aF1, TopAbs_EDGE);
1052   for (; anExpF1.More(); anExpF1.Next()) {
1053     const TopoDS_Edge& anE1=TopoDS::Edge(anExpF1.Current());
1054     //
1055     if (!BRep_Tool::Degenerated(anE1)){
1056       continue;
1057     }
1058     //
1059     nE1=aDS.ShapeIndex(anE1, iRankF1);
1060     AssignDEStates (nF1, nE1, nF2); 
1061   }
1062 }
1063
1064 //=======================================================================
1065 // function: AssignDEStates
1066 // purpose: 
1067 //======================================================================= 
1068   void BOP_SDFWESFiller::AssignDEStates(const Standard_Integer nFD,
1069                                         const Standard_Integer nED, 
1070                                         const Standard_Integer nF2) 
1071 {
1072   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
1073   const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
1074   BOPTools_PaveFiller* pPaveFiller=(BOPTools_PaveFiller*) &aPaveFiller;
1075   const BOPTools_SplitShapesPool& aSplitShapesPool=aPaveFiller.SplitShapesPool();
1076   //
1077   const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(aDS.RefEdge(nED));
1078   //
1079   const Handle(IntTools_Context)& aContext=pPaveFiller->Context();
1080   const TopoDS_Edge& aDE=TopoDS::Edge(aDS.Shape(nED));
1081   const TopoDS_Face& aDF=TopoDS::Face(aDS.Shape(nFD));
1082   const TopoDS_Face& aFaceReference=TopoDS::Face(aDS.Shape(nF2));
1083   //
1084   Standard_Boolean bIsValidPoint;
1085   Standard_Integer nSp;
1086   Standard_Real aT, aT1, aT2;
1087   TopAbs_State aState;
1088   TopoDS_Face aF;
1089   gp_Pnt2d aPx2DNear;
1090   gp_Pnt aPxNear;
1091   //
1092   aF=aDF;
1093   aF.Orientation(TopAbs_FORWARD);
1094   
1095   BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
1096   for (; aPBIt.More(); aPBIt.Next()) {
1097     BOPTools_PaveBlock& aPB=aPBIt.Value();
1098     
1099     nSp=aPB.Edge();
1100     const TopoDS_Edge& aSp=TopoDS::Edge(aDS.Shape(nSp));
1101     
1102     aPB.Parameters(aT1, aT2);
1103     aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
1104
1105     TopoDS_Edge aDERight, aSpRight;
1106     aDERight=aDE;
1107     aSpRight=aSp;
1108
1109     BOPTools_Tools3D::OrientEdgeOnFace (aDE, aF, aDERight);
1110     aSpRight.Orientation(aDERight.Orientation());
1111     //
1112     BOPTools_Tools3D::PointNearEdge(aSpRight, aDF, aT, aPx2DNear, aPxNear);
1113     //
1114     aState=TopAbs_OUT;
1115     //
1116     bIsValidPoint=aContext->IsValidPointForFace(aPxNear, aFaceReference, 1.e-3);
1117     //
1118     if (bIsValidPoint) {
1119       aState=TopAbs_IN;
1120     }
1121     //
1122     BooleanOperations_StateOfShape aSt;
1123     
1124     aSt=BOPTools_SolidStateFiller::ConvertState(aState);
1125     if (myStatesMap.Contains(nSp)) {
1126       BooleanOperations_StateOfShape& aBooState=myStatesMap.ChangeFromKey(nSp);
1127       aBooState=aSt;
1128     }
1129     else {
1130       myStatesMap.Add(nSp, aSt);
1131     }
1132   }
1133 }
1134
1135 //=======================================================================
1136 // function: UpdateDEStates3D
1137 // purpose: 
1138 //======================================================================= 
1139   void BOP_SDFWESFiller::UpdateDEStates3D()
1140 {
1141   BooleanOperations_ShapesDataStructure* pDS=
1142     (BooleanOperations_ShapesDataStructure*)&myDSFiller->DS();
1143   
1144   Standard_Integer i, aNb, nSp;
1145   BooleanOperations_StateOfShape aSt;
1146
1147   aNb=myStatesMap.Extent();
1148   for (i=1; i<=aNb; i++) {
1149     nSp=myStatesMap.FindKey(i);
1150     aSt=pDS->GetState(nSp);
1151     aSt=BooleanOperations_UNKNOWN;
1152     pDS->SetState(nSp, aSt);
1153   }
1154 }
1155 //
1156 #include <Geom2d_Curve.hxx>
1157 #include <gp_Pnt2d.hxx>
1158
1159 //=======================================================================
1160 // function: TreatSDSeams
1161 // purpose: 
1162 //=======================================================================
1163 void TreatSDSeams (const TopoDS_Edge& aSpE1Seam11,
1164                    const Standard_Real aT1,
1165                    const TopoDS_Face& aF1FWD,
1166         
1167                    const TopoDS_Edge& aSpE1Seam21,
1168                    const Standard_Real aT2,
1169                    const TopoDS_Face& aF2FWD,
1170                    
1171                    const Standard_Boolean bIsTakenSp1,
1172                    BOP_WireEdgeSet& aWES,
1173                    const Handle(IntTools_Context)& aContext)
1174 {
1175   Standard_Boolean bIsValidSeam11, bIsValidSeam12, 
1176                    bIsValidSeam21, bIsValidSeam22;
1177   Standard_Real aScPr;
1178   TopoDS_Edge aSS, aSpE1Seam12,aSpE1Seam22;
1179   gp_Dir aDB11, aDB12, aDB21, aDB22;
1180             
1181   aSpE1Seam12=TopoDS::Edge(aSpE1Seam11.Reversed());
1182   aSpE1Seam22=TopoDS::Edge(aSpE1Seam21.Reversed());
1183             //
1184   if (!bIsTakenSp1) {
1185     BOPTools_Tools3D::DoSplitSEAMOnFace (aSpE1Seam21, aF1FWD);
1186     aSpE1Seam22=TopoDS::Edge(aSpE1Seam21.Reversed());
1187   }
1188   //
1189   bIsValidSeam11=IsValidSeam(aSpE1Seam11, aF1FWD, aT1, aContext);
1190   bIsValidSeam12=IsValidSeam(aSpE1Seam12, aF1FWD, aT1, aContext);
1191   bIsValidSeam21=IsValidSeam(aSpE1Seam21, aF2FWD, aT2, aContext);
1192   bIsValidSeam22=IsValidSeam(aSpE1Seam22, aF2FWD, aT2, aContext);
1193   // 1
1194   if (bIsValidSeam11 && bIsValidSeam12) {
1195     BOPTools_Tools3D::GetBiNormal(aSpE1Seam11, aF1FWD, aT1, aDB11);
1196     BOPTools_Tools3D::GetBiNormal(aSpE1Seam12, aF1FWD, aT1, aDB12);
1197     // 1.1
1198     if (bIsValidSeam21 && !bIsValidSeam22) {
1199       BOPTools_Tools3D::GetBiNormal(aSpE1Seam21, aF2FWD, aT2, aDB21);
1200       aScPr=aDB11*aDB21;
1201       if (aScPr<0.) {
1202         if (bIsTakenSp1) {
1203           aSS=aSpE1Seam11;
1204         }
1205         else {
1206           //aSS=aSpE1Seam21;
1207           CorrespondantSeam(aSpE1Seam11, aT1, 
1208                             aSpE1Seam21, aSpE1Seam22, aT2, 
1209                             aF1FWD, aSS);
1210         }
1211       }
1212       else { //if (aScPr>0.)
1213         if (bIsTakenSp1) {
1214           aSS=aSpE1Seam12;
1215         }
1216         else {
1217           //aSS=aSpE1Seam22;
1218           CorrespondantSeam(aSpE1Seam12, aT1, 
1219                             aSpE1Seam21, aSpE1Seam22, aT2, 
1220                             aF1FWD, aSS);
1221         }
1222       }
1223       aWES.AddStartElement (aSS);
1224     } //if (bIsValidSeam21 && !bIsValidSeam22)
1225     //  
1226     // 1.2      
1227     if (!bIsValidSeam21 && bIsValidSeam22) {
1228       BOPTools_Tools3D::GetBiNormal(aSpE1Seam22, aF2FWD, aT2, aDB22);
1229       aScPr=aDB11*aDB22;
1230       if (aScPr<0.) {
1231         if (bIsTakenSp1) {
1232           aSS=aSpE1Seam11;
1233         }
1234         else {
1235           //aSS=aSpE1Seam22;
1236           CorrespondantSeam(aSpE1Seam11, aT1, 
1237                             aSpE1Seam21, aSpE1Seam22, aT2, 
1238                             aF1FWD, aSS);
1239         }
1240       }
1241       else {//if (aScPr>0.)
1242         if (bIsTakenSp1) {
1243           aSS=aSpE1Seam12;
1244         }
1245         else {
1246           //aSS=aSpE1Seam21;
1247           CorrespondantSeam(aSpE1Seam12, aT1, 
1248                             aSpE1Seam21, aSpE1Seam22, aT2, 
1249                             aF1FWD, aSS);
1250         }
1251       }
1252       aWES.AddStartElement (aSS);
1253     }// if (!bIsValidSeam21 && bIsValidSeam22)
1254   } //if (bIsValidSeam11 && bIsValidSeam12)
1255 }
1256
1257 //=======================================================================
1258 // function: IsValidSeam
1259 // purpose: 
1260 //======================================================================= 
1261   Standard_Boolean IsValidSeam(const TopoDS_Edge& aE,
1262                                const TopoDS_Face& aF,
1263                                const Standard_Real aT,
1264                                const Handle(IntTools_Context)& aContext)
1265 {
1266   Standard_Boolean bIsPointInOnFace;
1267   gp_Pnt2d aPx2DNear;
1268   gp_Pnt aPxNear;
1269
1270   BOPTools_Tools3D::PointNearEdge(aE, aF, aT, aPx2DNear, aPxNear);
1271   //
1272   bIsPointInOnFace=aContext->IsPointInOnFace(aF, aPx2DNear);
1273   return bIsPointInOnFace;
1274 }
1275 //=======================================================================
1276 // function: CorrespondantSeam
1277 // purpose: 
1278 //======================================================================= 
1279   void CorrespondantSeam(const TopoDS_Edge& aSpE1Seam11,
1280                          const Standard_Real aT1,
1281                          const TopoDS_Edge& aSpE1Seam21,
1282                          const TopoDS_Edge& aSpE1Seam22,
1283                          const Standard_Real aT2,
1284                          const TopoDS_Face& aF1FWD,
1285                          TopoDS_Edge& aSS)
1286                                       
1287 {
1288   Standard_Real a, b, aD1121, aD1122, aTol=1.e-7;
1289   Handle(Geom2d_Curve) aC2DSeam11, aC2DSeam21, aC2DSeam22;
1290   gp_Pnt2d aP2D11, aP2D21, aP2D22;
1291
1292   aC2DSeam11=BRep_Tool::CurveOnSurface(aSpE1Seam11, aF1FWD, a, b);
1293   aC2DSeam11->D0(aT1, aP2D11);
1294
1295   aC2DSeam21=BRep_Tool::CurveOnSurface(aSpE1Seam21, aF1FWD, a, b);
1296   aC2DSeam21->D0(aT2, aP2D21);
1297
1298   aC2DSeam22=BRep_Tool::CurveOnSurface(aSpE1Seam22, aF1FWD, a, b);
1299   aC2DSeam22->D0(aT2, aP2D22);
1300
1301   aD1121=aP2D11.Distance(aP2D21);
1302   aD1122=aP2D11.Distance(aP2D22);
1303   
1304   aSS=aSpE1Seam22;
1305   if (aD1121<aTol) {
1306     aSS=aSpE1Seam21;
1307   }
1308 }