0023024: Update headers of OCCT files
[occt.git] / src / BOP / BOP_ShellSolid_3.cxx
1 // Created on: 2004-06-09
2 // Created by: Mikhail KLOKOV
3 // Copyright (c) 2004-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
22 #include <BOP_ShellSolid.ixx>
23
24 #include <TopAbs_Orientation.hxx>
25
26 #include <TopExp_Explorer.hxx>
27 #include <TopoDS_Shape.hxx>
28 #include <TopoDS_Vertex.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <TopoDS.hxx>
33
34 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
35 #include <TopTools_MapOfShape.hxx>
36 #include <TopTools_ListOfShape.hxx>
37 #include <TopTools_ListIteratorOfListOfShape.hxx>
38
39 #include <TopExp.hxx>
40
41 #include <Geom_Surface.hxx>
42 #include <GeomAPI_ProjectPointOnSurf.hxx>
43
44 #include <BRepClass3d_SolidClassifier.hxx>
45
46 #include <BRep_Builder.hxx>
47 #include <BRepTools.hxx>
48 #include <BRep_Tool.hxx>
49
50 #include <BooleanOperations_ShapesDataStructure.hxx>
51
52 #include <BOPTools_InterferencePool.hxx>
53 #include <BOPTools_CArray1OfSSInterference.hxx>
54 #include <BOPTools_SSInterference.hxx>
55 #include <BOPTools_SequenceOfCurves.hxx>
56 #include <BOPTools_Curve.hxx>
57 #include <BOPTools_ListOfPaveBlock.hxx>
58 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
59 #include <BOPTools_PaveBlock.hxx>
60
61 #include <BOPTools_Tools3D.hxx>
62
63 #include <BOPTools_PaveFiller.hxx>
64 #include <BOPTools_CommonBlockPool.hxx>
65
66 #include <BOPTools_ListOfCommonBlock.hxx>
67 #include <BOPTools_ListIteratorOfListOfCommonBlock.hxx>
68 #include <BOPTools_CommonBlock.hxx>
69
70 #include <BOP_BuilderTools.hxx>
71
72 #include <BOP_FaceBuilder.hxx>
73 #include <BOPTColStd_IndexedDataMapOfIntegerIndexedMapOfInteger.hxx>
74
75 // =====================================================================================================================
76 //  function: SplitFace
77 //  purpose:
78 // =====================================================================================================================
79 Standard_Boolean BOP_ShellSolid::SplitFace(const Standard_Integer theFaceIndex,
80                                            TopTools_DataMapOfShapeInteger& theMapOfEdgeIndex,
81                                            TopTools_ListOfShape& theListOfFace) const
82 {
83   theListOfFace.Clear();
84
85   const BooleanOperations_ShapesDataStructure& aDS              = myDSFiller->DS();
86   const BOPTools_PaveFiller&                   aPaveFiller      = myDSFiller->PaveFiller();
87   BOPTools_PaveFiller*                         pPaveFiller      = (BOPTools_PaveFiller*)&aPaveFiller;
88   BOPTools_CommonBlockPool&                    aCBPool          = pPaveFiller->ChangeCommonBlockPool();
89   const BOPTools_SplitShapesPool&              aSplitShapesPool = aPaveFiller.SplitShapesPool();
90
91   BOPTools_InterferencePool* pIntrPool=
92     (BOPTools_InterferencePool*)&myDSFiller->InterfPool();
93   
94   BOPTools_CArray1OfSSInterference& aFFs = pIntrPool->SSInterferences();
95
96   TopoDS_Face aFace = TopoDS::Face(aDS.Shape(theFaceIndex));
97   aFace.Orientation(TopAbs_FORWARD);
98
99   BOP_WireEdgeSet aWES (aFace);
100
101
102   Standard_Integer i = 0;
103
104   for(i = 1; i <= aFFs.Length(); i++) {
105     BOPTools_SSInterference& aFF = aFFs(i);
106
107     if((aFF.Index1() != theFaceIndex) && (aFF.Index2() != theFaceIndex))
108       continue;
109
110     BOPTools_SequenceOfCurves& aSC = aFF.Curves();
111     Standard_Integer aNbCurves = aSC.Length();
112     Standard_Integer j = 0;
113
114     for(j = 1; j <= aNbCurves; j++) {
115       const BOPTools_Curve& aBC = aSC(j);
116       const BOPTools_ListOfPaveBlock& aLPB = aBC.NewPaveBlocks();
117       BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB);
118
119       for (; anIt.More(); anIt.Next()) {
120         const BOPTools_PaveBlock& aPB = anIt.Value();
121         Standard_Integer nE = aPB.Edge();
122         const TopoDS_Shape& aE = aDS.Shape(nE);
123         TopoDS_Edge aES = TopoDS::Edge(aE);
124         aWES.AddStartElement(aES);
125         aES.Reverse();
126         aWES.AddStartElement(aES);
127
128         if(!theMapOfEdgeIndex.IsBound(aES)) {
129           theMapOfEdgeIndex.Bind(aES, nE);
130         }
131       }
132     }
133   }
134
135   Standard_Integer aFaceRank = aDS.Rank(theFaceIndex);
136   TopExp_Explorer anExpE(aFace, TopAbs_EDGE);
137
138   for(; anExpE.More(); anExpE.Next()) {
139     const TopoDS_Shape& anOldEdge = anExpE.Current();
140     TopAbs_Orientation anOr = anOldEdge.Orientation();
141     Standard_Integer anEdgeIndex = aDS.ShapeIndex(anOldEdge, aFaceRank);
142
143     if(anEdgeIndex <= 0)
144       continue;
145     
146     const BOPTools_ListOfPaveBlock& aLPB = aSplitShapesPool(aDS.RefEdge(anEdgeIndex));
147
148     if(aLPB.IsEmpty()) {
149       TopoDS_Edge aSS = TopoDS::Edge(anOldEdge);
150       //
151       aWES.AddStartElement (aSS);
152
153       if(!theMapOfEdgeIndex.IsBound(aSS)) {
154         theMapOfEdgeIndex.Bind(aSS, anEdgeIndex);
155       }
156     }
157     else {
158       BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aLPB);
159
160       for (; aPBIt.More(); aPBIt.Next()) {
161         const BOPTools_PaveBlock& aPB = aPBIt.Value();
162         Standard_Integer nSp = aPB.Edge();
163         Standard_Integer nSpToAdd = nSp;
164
165         BooleanOperations_StateOfShape aState = aDS.GetState(nSp);
166         Standard_Boolean bAddToWes = ((aState == BooleanOperations_IN) ||
167                                       (aState == BooleanOperations_OUT));
168
169         if(aState == BooleanOperations_ON) {
170           bAddToWes = Standard_True;
171
172           BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(anEdgeIndex));
173
174           BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
175     
176           for (; anItCB.More(); anItCB.Next()) {
177             BOPTools_CommonBlock& aCB = anItCB.Value();
178             Standard_Integer iCBFace = aCB.Face();
179
180             if(iCBFace == 0) {
181               BOPTools_PaveBlock& aPBEF1 = aCB.PaveBlock1(anEdgeIndex);
182               BOPTools_PaveBlock& aPBEF2 = aCB.PaveBlock2(anEdgeIndex);
183
184               const BOPTools_PaveBlock& aPB1 = aCB.PaveBlock1();
185               Standard_Integer nSpTaken = aPB1.Edge();
186
187               if((nSp == aPBEF1.Edge()) || (nSp == aPBEF2.Edge())) {
188                 nSpToAdd = nSpTaken;
189                 break;
190               }
191             }
192           }
193         }
194         
195         if(bAddToWes) {
196           const TopoDS_Shape& aSplit = aDS.Shape(nSpToAdd);
197           TopoDS_Edge aSS=TopoDS::Edge(aSplit);
198           aSS.Orientation(anOr);
199
200           if(nSpToAdd != nSp) {
201             const TopoDS_Shape& aSp1=aDS.Shape(nSp);
202             TopoDS_Edge aSpF1=TopoDS::Edge(aSp1);
203             aSpF1.Orientation(anOr);
204           
205             const TopoDS_Shape& aSp2 = aDS.Shape(nSpToAdd);
206             TopoDS_Edge aSpF2 = TopoDS::Edge(aSp2);
207           
208             Standard_Boolean bToReverse=
209               BOPTools_Tools3D::IsSplitToReverse1 (aSpF1, aSpF2, pPaveFiller->Context());
210
211             if (bToReverse) {
212               aSpF2.Reverse();
213             }
214             
215             if (BRep_Tool::IsClosed(TopoDS::Edge(anOldEdge), aFace) && 
216                 !BRep_Tool::IsClosed(aSpF2, aFace)) {
217               Standard_Boolean bIsReversed = Standard_False;
218
219               if(!BOPTools_Tools3D::DoSplitSEAMOnFace(aSpF2, aSpF1, aFace, bIsReversed))
220                 BOPTools_Tools3D::DoSplitSEAMOnFace (aSpF2, aFace);
221             }
222
223
224             aSS = aSpF2;
225           }
226           //
227           aWES.AddStartElement (aSS);
228
229           if(!theMapOfEdgeIndex.IsBound(aSS)) {
230             theMapOfEdgeIndex.Bind(aSS, nSpToAdd);
231           }
232         }
233       }
234     }
235   }
236
237   BOPTColStd_IndexedDataMapOfIntegerIndexedMapOfInteger aFFMap;
238   BOP_BuilderTools::DoMap(aFFs, aFFMap);
239
240   Standard_Integer aNb = aFFMap.Extent();
241
242   for (i = 1; i <= aNb; i++) {
243     Standard_Integer nF1 = aFFMap.FindKey(i);
244
245     if(nF1 != theFaceIndex)
246       continue;
247
248     const TColStd_IndexedMapOfInteger& aFFIndicesMap=aFFMap.FindFromIndex(i);
249     Standard_Integer aNbj = aFFIndicesMap.Extent();
250     Standard_Integer j = 0;
251
252     for (j = 1; j <= aNbj; j++) {
253       Standard_Integer iFF = aFFIndicesMap(j);
254       BOPTools_SSInterference& aFF = aFFs(iFF);
255       //
256       Standard_Integer nF2 = aFF.OppositeIndex(nF1);
257
258       if(nF2 <= 0)
259         continue;
260       //
261       Standard_Integer iRankF2 = aDS.Rank(nF2);
262       TopoDS_Shape aFace2 = aDS.Shape(nF2);
263
264       anExpE.Init(aFace2, TopAbs_EDGE);
265
266       for(; anExpE.More(); anExpE.Next()) {
267         Standard_Integer anEdgeIndex2 = aDS.ShapeIndex(anExpE.Current(), iRankF2);
268
269         if(anEdgeIndex2 <= 0)
270           continue;
271
272         BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(anEdgeIndex2));
273     
274         BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
275     
276         for (; anItCB.More(); anItCB.Next()) {
277           BOPTools_CommonBlock& aCB = anItCB.Value();
278           Standard_Integer iCBFace = aCB.Face();
279
280           if(iCBFace == theFaceIndex) {
281             BOPTools_PaveBlock& aPB = aCB.PaveBlock1(anEdgeIndex2);
282             Standard_Integer nSpEF2 = aPB.Edge();
283             const TopoDS_Shape& aSpEF2 = aDS.Shape(nSpEF2);
284
285             TopoDS_Edge aEF = TopoDS::Edge(aSpEF2);
286
287             if(!theMapOfEdgeIndex.IsBound(aEF)) {
288               theMapOfEdgeIndex.Bind(aEF, nSpEF2);
289             }
290
291             if(aEF.Orientation() == TopAbs_INTERNAL) {
292               aWES.AddStartElement(aEF);
293             }
294             else {
295               aEF.Orientation(TopAbs_FORWARD);
296               aWES.AddStartElement(aEF);
297               aEF.Reverse();
298               aWES.AddStartElement(aEF);
299             }
300           }
301         }
302       }
303     }
304   }
305
306   // process internal edges
307   BOP_WireEdgeSet aFilteredWES (aFace);
308   TopoDS_Compound aComp;
309   BRep_Builder aBB;
310   aBB.MakeCompound(aComp);
311
312   for(aWES.InitStartElements(); aWES.MoreStartElements(); aWES.NextStartElement()) {
313     aBB.Add(aComp, aWES.StartElement());
314   }
315   TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
316   TopExp::MapShapesAndAncestors(aComp, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
317
318   for(aWES.InitStartElements(); aWES.MoreStartElements(); aWES.NextStartElement()) {
319     const TopoDS_Shape& anEdge = aWES.StartElement();
320
321     if(anEdge.Orientation() != TopAbs_INTERNAL) {
322       aFilteredWES.AddStartElement(anEdge);
323     }
324     else {
325       TopoDS_Vertex aV1, aV2, aV;
326
327       Standard_Boolean bFound1 = Standard_False;
328       Standard_Boolean bFound2 = Standard_False;
329       Standard_Boolean bIsClosed = Standard_False;
330       Standard_Integer vcounter = 0;
331       TopTools_IndexedMapOfShape aMapOfEInternal;
332       aMapOfEInternal.Add(anEdge);
333
334       TopExp::Vertices(TopoDS::Edge(anEdge), aV1, aV2);
335
336       if(!aV1.IsNull() && aV1.IsSame(aV2)) {
337         bIsClosed = Standard_True;
338       }
339       else {
340         TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
341
342         for(; anExpV.More(); anExpV.Next(), vcounter++) {
343           aV = TopoDS::Vertex(anExpV.Current());
344           TopTools_MapOfShape aMapOfV;
345
346           while(!aV.IsNull()) {
347             if(!aMapVE.Contains(aV))
348               aV.Nullify();
349
350             if(aMapOfV.Contains(aV))
351               break;
352             aMapOfV.Add(aV);
353             const TopTools_ListOfShape& aListOfE = aMapVE.FindFromKey(aV);
354             TopTools_ListIteratorOfListOfShape anIt(aListOfE);
355             Standard_Boolean bFound = Standard_False;
356             aV.Nullify();
357
358             for(; anIt.More(); anIt.Next()) {
359               const TopoDS_Shape& anAdjE = anIt.Value();
360
361               if(anEdge.IsSame(anAdjE))
362                 continue;
363           
364               if(anAdjE.Orientation() != TopAbs_INTERNAL) {
365                 if(vcounter == 0)
366                   bFound1 = Standard_True;
367                 else
368                 bFound2 = Standard_True;
369                 bFound = Standard_True;
370               }
371               else {
372                 aMapOfEInternal.Add(anAdjE);
373               }
374             } // end for
375
376             if(!bFound) {
377               anIt.Initialize(aListOfE);
378
379               for(; anIt.More(); anIt.Next()) {
380                 const TopoDS_Shape& anAdjE = anIt.Value();
381
382                 if(anEdge.IsSame(anAdjE))
383                   continue;
384           
385                 if(anAdjE.Orientation() == TopAbs_INTERNAL) {
386                   //
387                   aMapOfEInternal.Add(anAdjE);
388                   //
389
390                   TopExp_Explorer anExpV2(anAdjE, TopAbs_VERTEX);
391
392                   for(; anExpV2.More(); anExpV2.Next()) {
393                     if(aMapOfV.Contains(anExpV2.Current()))
394                       continue;
395                     aV = TopoDS::Vertex(anExpV2.Current());
396                   }
397                 }
398               }
399             }
400             // end if
401           }
402           // end while
403         }
404       }
405
406       if(bIsClosed ||
407          ((vcounter > 1) && bFound1 && bFound2) ||
408          ((vcounter == 1) && bFound1)) {
409         TopoDS_Shape anOrientedEdge = anEdge;
410         anOrientedEdge.Orientation(TopAbs_FORWARD);
411
412         aFilteredWES.AddStartElement(anOrientedEdge);
413         anOrientedEdge.Reverse();
414         aFilteredWES.AddStartElement(anOrientedEdge);
415       }
416       else {
417         Standard_Integer aMapIt = 1, nbv = 0, nbe = 0;
418         TopTools_IndexedMapOfShape aMapOfFoundV;
419
420         for(aMapIt = 1; aMapIt <= aMapOfEInternal.Extent(); aMapIt++) {
421           const TopoDS_Shape& aShape = aMapOfEInternal(aMapIt);
422           TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapOfFoundV);
423         }
424         nbe = aMapOfEInternal.Extent();
425         nbv = aMapOfFoundV.Extent();
426
427         if((nbe != 0) && (nbe == nbv)) {
428           TopoDS_Shape anOrientedEdge = anEdge;
429           anOrientedEdge.Orientation(TopAbs_FORWARD);
430
431           aFilteredWES.AddStartElement(anOrientedEdge);
432           anOrientedEdge.Reverse();
433           aFilteredWES.AddStartElement(anOrientedEdge);
434         }
435         else {
436           aFilteredWES.AddStartElement(anEdge);
437         }
438       }
439     }
440   }
441
442   BOP_FaceBuilder aFB;
443   aFB.Do(aFilteredWES);
444   const TopTools_ListOfShape& aLF = aFB.NewFaces();
445
446   theListOfFace = aLF;
447
448   Standard_Integer nbstartedges = aFilteredWES.StartElements().Extent();
449   Standard_Integer nbedgeused = 0;
450   TopTools_ListIteratorOfListOfShape anItNewF(aLF);
451
452   // was:
453   // -----------------------------------------------------------
454 //  for(; anItNewF.More(); anItNewF.Next()) {
455 //    TopExp_Explorer anExp(anItNewF.Value(), TopAbs_EDGE);
456 //    for(; anExp.More(); anExp.Next(), nbedgeused++);
457 //  }
458 //  if(nbedgeused != nbstartedges) {
459 //    return Standard_False;
460 //  }
461   // -----------------------------------------------------------
462   //
463   // modified 6841:
464   //
465   if(aLF.Extent() != 2) {
466     for(; anItNewF.More(); anItNewF.Next()) {
467       TopExp_Explorer anExp(anItNewF.Value(), TopAbs_EDGE);
468       for(; anExp.More(); anExp.Next(), nbedgeused++);
469     }
470     if(nbedgeused != nbstartedges) {
471       return Standard_False;
472     }
473   }
474   else { // two faces analysis
475     TopTools_IndexedDataMapOfShapeListOfShape amFLIE;
476     TopTools_ListOfShape aLIntAll;
477     for(; anItNewF.More(); anItNewF.Next()) {
478       const TopoDS_Face & anF = TopoDS::Face(anItNewF.Value());
479       TopExp_Explorer anExp(anItNewF.Value(), TopAbs_EDGE);
480       TopTools_ListOfShape aLInt;
481       for(; anExp.More(); anExp.Next(), nbedgeused++) {
482         const TopoDS_Edge & anE = TopoDS::Edge(anExp.Current());
483         if(anE.Orientation() == TopAbs_INTERNAL) {
484           aLIntAll.Append(anE);
485           aLInt.Append(anE);
486         }
487       }
488       amFLIE.Add(anF,aLInt);
489     }
490     if(nbedgeused != nbstartedges) {
491       if(!aLIntAll.IsEmpty()) {
492         Standard_Integer nbUsed = nbedgeused;
493         TopTools_ListIteratorOfListOfShape anItInt(aLIntAll);
494         for(; anItInt.More(); anItInt.Next()) {
495           const TopoDS_Edge & aEInt = TopoDS::Edge(anItInt.Value());
496           Standard_Integer nbFRE = 0;
497           TopTools_ListIteratorOfListOfShape anItWes(aFilteredWES.StartElements());
498           for(; anItWes.More(); anItWes.Next()) {
499             const TopoDS_Edge & aEWes = TopoDS::Edge(anItWes.Value());
500             if(aEWes.Orientation() != TopAbs_INTERNAL) {
501               if(aEInt.IsSame(aEWes))
502                 nbFRE++;
503             }
504           }
505           if(nbFRE > 1)
506             nbUsed += (nbFRE - 1);
507         }
508         if(nbUsed == nbstartedges && Abs(nbstartedges-nbedgeused) == 1) {
509           Standard_Integer iF = 0, nbFI = 0;
510           for(iF = 1; iF <= amFLIE.Extent(); iF++) {
511             const TopTools_ListOfShape& aLOfIE = amFLIE.FindFromIndex(iF);
512             if(!aLOfIE.IsEmpty()) nbFI++;
513           }
514           if(nbFI == 1) {
515             anItNewF.Initialize(aLF);
516             Standard_Boolean checkOk = Standard_False;
517             for(; anItNewF.More(); anItNewF.Next()) {
518               const TopoDS_Face & anF = TopoDS::Face(anItNewF.Value());
519               const TopTools_ListOfShape& aLOfIE = amFLIE.FindFromKey(anF);
520               if(!aLOfIE.IsEmpty() && aLOfIE.Extent() == 1) {
521                 const TopoDS_Edge & anIntE = TopoDS::Edge(aLOfIE.First());
522                 TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
523                 TopExp::MapShapesAndAncestors(anF,TopAbs_VERTEX,TopAbs_EDGE,aMapVE);
524                 TopoDS_Vertex v1,v2; 
525                 TopExp::Vertices(anIntE,v1,v2);
526                 Standard_Boolean hasSingle = Standard_False;
527                 if(!v1.IsNull() && !v2.IsNull()) {
528                   const TopTools_ListOfShape& aL1E = aMapVE.FindFromKey(v1);
529                   const TopTools_ListOfShape& aL2E = aMapVE.FindFromKey(v2);
530                   if((aL1E.Extent() == 1 && aL2E.Extent() != 1) ||
531                      (aL2E.Extent() == 1 && aL1E.Extent() != 1))
532                     hasSingle = Standard_True;
533                 }
534                 if(hasSingle) {
535                   checkOk = Standard_True;
536                   break;
537                 }
538               }
539             }
540             if(checkOk) {
541               return Standard_True;
542             }
543           }
544         } // all edges are really used
545       } // has internals
546       return Standard_False;
547     }
548   } // two faces analysis
549
550   return Standard_True;
551 }