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