0026431: Can't cut a sphere from a cylinder
[occt.git] / src / BRepAlgo / BRepAlgo_BooleanOperations.cxx
1 // Created on: 1997-11-20
2 // Created by: Prestataire Mary FABIEN
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Bnd_Box.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAlgo_BooleanOperations.hxx>
22 #include <BRepAlgo_DSAccess.hxx>
23 #include <BRepBndLib.hxx>
24 #include <BRepTools_Substitution.hxx>
25 #include <Geom_Surface.hxx>
26 #include <TopLoc_Location.hxx>
27 #include <TopoDS.hxx>
28 #include <TopoDS_Compound.hxx>
29 #include <TopoDS_Shape.hxx>
30 #include <TopOpeBRep_DSFiller.hxx>
31 #include <TopOpeBRepBuild_HBuilder.hxx>
32 #include <TopOpeBRepDS_BuildTool.hxx>
33 #include <TopOpeBRepDS_HDataStructure.hxx>
34 #include <TopOpeBRepTool_GeomTool.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <TopTools_ListOfShape.hxx>
37
38 //=======================================================================
39 //function : Create
40 //purpose  : 
41 //=======================================================================
42 BRepAlgo_BooleanOperations::BRepAlgo_BooleanOperations() :
43 myApproxNbPntMax (30) ,
44 myApproxTol3D (1.e-7) ,
45 myApproxTol2D (1.e-7)
46 {
47 }
48
49 //=======================================================================
50 //function : Shapes2d
51 //purpose  : 
52 //=======================================================================
53   void BRepAlgo_BooleanOperations::Shapes2d (const TopoDS_Shape& S1,
54                                             const TopoDS_Shape& S2) 
55 {
56   // S1 doit etre une face ou un ensemble de faces
57   // S2 doit etre une edge.
58
59   if (S2.ShapeType() != TopAbs_EDGE) return;
60
61   BRep_Builder Builder ;
62   TopoDS_Wire Wire ;
63   Builder.MakeWire (Wire);
64   Builder.Add (Wire, S2);
65   
66   TopExp_Explorer Exp (S1, TopAbs_FACE) ;
67   if (!Exp.More()) return ;
68   const TopoDS_Face& FirstFace = TopoDS::Face (Exp.Current()) ;
69
70   TopLoc_Location Loc;
71   const Handle(Geom_Surface)& Surf = BRep_Tool::Surface (FirstFace, Loc) ; 
72
73   TopoDS_Face Face ;
74   Builder.MakeFace (Face, Surf, Loc, BRep_Tool::Tolerance (FirstFace)) ;
75   Builder.Add (Face, Wire) ;
76   Face.Orientation (FirstFace.Orientation()) ;
77   
78   myS1 = S1 ;
79   myS2 = Face ;
80
81   myDSA.Init() ;
82   myDSA.Load (myS1, myS2) ;
83   Handle (TopOpeBRepDS_HDataStructure)& HDS = myDSA.ChangeDS() ;
84   myDSA.myDSFiller.Insert2d (myS1, myS2, HDS) ;
85 }
86
87 //=======================================================================
88 //function : Shapes
89 //purpose  : Defines the arguments.
90 //=======================================================================
91   void BRepAlgo_BooleanOperations::Shapes (const TopoDS_Shape& S1,
92                                            const TopoDS_Shape& S2)
93 {
94   myS1 = S1;
95   myS2 = S2;
96   myDSA.Init();
97   myDSA.Load(myS1, myS2);
98   Handle(TopOpeBRepDS_HDataStructure)& HDS = myDSA.ChangeDS();
99   myDSA.myDSFiller.Insert(myS1,myS2,HDS);
100   //  const Standard_Boolean CheckShapes = Standard_True;
101   //  Standard_Boolean esp = HDS->EdgesSameParameter();
102   //  Standard_Boolean localcheck = CheckShapes;
103 }
104
105 //=======================================================================
106 //function : SetApproxParameters
107 //purpose  : Sets the parameters for the approximations.
108 //=======================================================================
109   void BRepAlgo_BooleanOperations::SetApproxParameters (const Standard_Integer NbPntMax,
110                                                         const Standard_Real Tol3D,
111                                                         const Standard_Real Tol2D)
112 {
113   myApproxNbPntMax = NbPntMax ;
114   myApproxTol3D = Tol3D ;
115   myApproxTol2D = Tol2D ;
116 }
117
118 //=======================================================================
119 //function : Define
120 //purpose  : 
121 //=======================================================================
122   void BRepAlgo_BooleanOperations::Define (const TopoDS_Shape& S1,
123                                            const TopoDS_Shape& S2,
124                                            Handle(TopOpeBRepDS_HDataStructure)& HDS)
125 {
126   ChangeDataStructure() = HDS;
127   myS1 = S1;
128   myS2 = S2;
129 }
130
131 //=======================================================================
132 //function : Perform
133 //purpose  : Performs the global boolean operation.
134 //=======================================================================
135   void BRepAlgo_BooleanOperations::Perform ()
136 {
137   TopOpeBRepDS_BuildTool& BTofBuilder = myDSA.myHB->ChangeBuildTool();
138   TopOpeBRepTool_GeomTool& GTofBTofBuilder = BTofBuilder.ChangeGeomTool();
139   GTofBTofBuilder.SetNbPntMax(myApproxNbPntMax);
140   GTofBTofBuilder.SetTolerances (myApproxTol3D, myApproxTol2D) ;
141   Handle(TopOpeBRepBuild_HBuilder)& HB = myDSA.myHB;
142   Handle(TopOpeBRepDS_HDataStructure)& HDS = myDSA.ChangeDS();
143   HB->Perform(HDS,myS1,myS2);
144 }
145
146 //=======================================================================
147 //function : Perform
148 //purpose  : Performs the global boolean operation in regards of the
149 //           given states.
150 //=======================================================================
151   void BRepAlgo_BooleanOperations::Perform (const TopAbs_State State1,
152                                            const TopAbs_State State2)
153 {
154   Perform() ;
155
156   myShape.Nullify() ;
157   myResult.Nullify() ;
158   myMapShape.Clear() ;
159
160   Handle(TopOpeBRepBuild_HBuilder)& HBuilder = ChangeBuilder() ;
161   HBuilder->MergeShapes (myS1, State1, myS2, State2) ;
162
163   const TopTools_ListOfShape& ListResults = HBuilder->Merged (myS1, State1) ;
164   Standard_Integer NbResults = ListResults.Extent() ;
165   if (NbResults > 0) {
166     if (NbResults == 1) {
167       myShape = ListResults.First() ;
168     } else {
169       BRep_Builder Builder ;
170       Builder.MakeCompound (TopoDS::Compound (myShape)) ;
171       TopTools_ListIteratorOfListOfShape Iter ;
172       for (Iter.Initialize (ListResults) ; Iter.More() ; Iter.Next())
173         Builder.Add (myShape, Iter.Value()) ;
174     }
175     TopExp_Explorer Explorer ;
176     for (Explorer.Init (myShape, TopAbs_FACE) ; Explorer.More() ; Explorer.Next()) {
177       myMapShape.Add (Explorer.Current()) ;
178     }
179     for (Explorer.Init (myShape, TopAbs_EDGE) ; Explorer.More() ; Explorer.Next()) {
180       myMapShape.Add (Explorer.Current()) ;
181     }
182   }
183 }
184
185 //=======================================================================
186 //function : Common
187 //purpose  : 
188 //=======================================================================
189   const TopoDS_Shape& BRepAlgo_BooleanOperations::Common() 
190 {
191   Perform (TopAbs_IN, TopAbs_IN) ;
192   return myShape ;
193 }
194
195 //=======================================================================
196 //function : fus
197 //purpose  : 
198 //=======================================================================
199   const TopoDS_Shape& BRepAlgo_BooleanOperations::Fus() 
200 {
201   Perform (TopAbs_OUT, TopAbs_OUT) ;
202   return myShape ;
203 }
204
205 //=======================================================================
206 //function : cut
207 //purpose  : 
208 //=======================================================================
209   const TopoDS_Shape& BRepAlgo_BooleanOperations::Cut() 
210 {
211   Perform (TopAbs_OUT, TopAbs_IN) ;
212   return myShape ;
213 }
214
215 //=======================================================================
216 //function : Section
217 //purpose  : 
218 //=======================================================================
219   const TopoDS_Shape& BRepAlgo_BooleanOperations::Section() 
220 {
221 //  Standard_Boolean bcw = BuilderCanWork();
222 //  if ( ! bcw || myshapeisnull) return;
223
224   Perform () ;
225
226   myShape.Nullify() ;
227   myResult.Nullify() ;
228   myMapShape.Clear() ;
229   
230   Handle(TopOpeBRepBuild_HBuilder)& HBuilder = myDSA.myHB ;
231
232   const TopTools_ListOfShape& ListResults = HBuilder->Section() ;
233   Standard_Integer NbResults = ListResults.Extent() ;
234   if (NbResults > 0) {
235     if (NbResults == 1) {
236       myShape = ListResults.First() ;
237     } else {
238       BRep_Builder Builder ;
239       Builder.MakeCompound (TopoDS::Compound (myShape)) ;
240       TopTools_ListIteratorOfListOfShape Iter ;
241       for (Iter.Initialize (ListResults) ; Iter.More() ; Iter.Next())
242         Builder.Add (myShape, Iter.Value()) ;
243     }
244     TopExp_Explorer Explorer ;
245     for (Explorer.Init (myShape, TopAbs_EDGE) ; Explorer.More() ; Explorer.Next()) {
246       myMapShape.Add (Explorer.Current()) ;
247     }
248   }
249
250   return myShape ;
251 }
252
253 //=======================================================================
254 //function : Shape
255 //purpose  : 
256 //=======================================================================
257   const TopoDS_Shape& BRepAlgo_BooleanOperations::Shape() 
258 {
259   return myShape;
260 }
261
262 //=======================================================================
263 //function : Shape
264 //purpose  : 
265 //=======================================================================
266   const TopoDS_Shape& BRepAlgo_BooleanOperations::ShapeFrom (const TopoDS_Shape& Shape) 
267 {
268   myResult.Nullify() ;
269
270   if (!myShape.IsNull()) {
271     
272     TopoDS_Shape ShapeToDel ;
273     if (Shape.IsSame (myS1)) {
274       ShapeToDel = myS2 ;
275     } else {
276       ShapeToDel = myS1 ;
277     }
278
279     BRepTools_Substitution Substitute ;
280
281     TopTools_ListOfShape NullFaces ;
282     NullFaces.Clear() ;
283
284     TopExp_Explorer ExpFac ;
285     for (ExpFac.Init (ShapeToDel, TopAbs_FACE) ; ExpFac.More() ; ExpFac.Next()) {
286       const TopoDS_Face& Face = TopoDS::Face (ExpFac.Current()) ;
287       const TopTools_ListOfShape& ListResults = Modified (Face) ;
288       if (ListResults.Extent() == 0) {
289         if (myMapShape.Contains (Face)) Substitute.Substitute (Face, NullFaces) ;
290       } else {
291         TopTools_ListIteratorOfListOfShape ItrFace ;
292         for (ItrFace.Initialize (ListResults) ; ItrFace.More() ; ItrFace.Next()) {
293           Substitute.Substitute (TopoDS::Face (ItrFace.Value()), NullFaces) ;
294         }
295       }
296     }
297
298     Substitute.Build (myShape) ;
299     if (Substitute.IsCopied (myShape)) {
300       const TopTools_ListOfShape& ListResults = Substitute.Copy (myShape) ;
301       Standard_Integer NbResults = ListResults.Extent() ;
302       if (NbResults == 1) {
303         myResult = ListResults.First() ;
304       } else if (NbResults > 1) {
305         BRep_Builder Builder ;
306         Builder.MakeCompound (TopoDS::Compound (myResult)) ;
307         TopTools_ListIteratorOfListOfShape ItrResult ;
308         for (ItrResult.Initialize (ListResults) ; ItrResult.More() ; ItrResult.Next()) {
309           Builder.Add (myResult, ItrResult.Value()) ;
310         }
311       }
312     } else {
313       myResult = myShape ;
314     }
315
316   }  
317   return myResult ;
318 }
319
320 //=======================================================================
321 //function : Modified
322 //purpose  : 
323 //=======================================================================
324   const TopTools_ListOfShape& BRepAlgo_BooleanOperations::Modified (const TopoDS_Shape& Shape) 
325 {
326   return myDSA.Modified(Shape);
327 }
328
329 //=======================================================================
330 //function : IsDeleted
331 //purpose  : 
332 //=======================================================================
333   Standard_Boolean BRepAlgo_BooleanOperations::IsDeleted (const TopoDS_Shape& Shape)
334 {
335   Standard_Boolean Deleted = Standard_True ; 
336
337   Handle(TopOpeBRepBuild_HBuilder)& HBuilder = myDSA.myHB ;
338
339   if (   myMapShape.Contains (Shape)
340       || HBuilder->IsMerged (Shape, TopAbs_OUT)
341       || HBuilder->IsMerged (Shape, TopAbs_IN)
342       || HBuilder->IsMerged (Shape, TopAbs_ON)
343       || HBuilder->IsSplit (Shape, TopAbs_OUT)
344       || HBuilder->IsSplit (Shape, TopAbs_IN)
345       || HBuilder->IsSplit (Shape, TopAbs_ON))
346     Deleted = Standard_False ;
347
348   return Deleted ;    
349 }
350
351 //=======================================================================
352 //function : DataStructure
353 //purpose  : 
354 //=======================================================================
355   const Handle(TopOpeBRepDS_HDataStructure)& BRepAlgo_BooleanOperations::DataStructure() const
356 {
357   return myDSA.DS();
358 }
359
360 //=======================================================================
361 //function : DataStructure
362 //purpose  : 
363 //=======================================================================
364   Handle(TopOpeBRepDS_HDataStructure)& BRepAlgo_BooleanOperations::ChangeDataStructure()
365 {
366   return myDSA.ChangeDS();
367 }
368
369 //=======================================================================
370 //function : Builder
371 //purpose  : 
372 //=======================================================================
373   const Handle(TopOpeBRepBuild_HBuilder)& BRepAlgo_BooleanOperations::Builder() const 
374 {
375   return myDSA.Builder();
376 }
377
378 //=======================================================================
379 //function : Builder
380 //purpose  : 
381 //=======================================================================
382   Handle(TopOpeBRepBuild_HBuilder)& BRepAlgo_BooleanOperations::ChangeBuilder() 
383 {
384   return myDSA.ChangeBuilder();
385 }
386
387 //=======================================================================
388 //function : DataStructureAccess
389 //purpose  : returns the member myDSA.
390 //=======================================================================
391   BRepAlgo_DSAccess& BRepAlgo_BooleanOperations::DataStructureAccess()
392 {
393   return myDSA;
394 }
395