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