92ae0f2f |
1 | // Created by: Eugeny MALTCHIKOV |
2 | // Copyright (c) 2014 OPEN CASCADE SAS |
3 | // |
4 | // This file is part of Open CASCADE Technology software library. |
5 | // |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
11 | // |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
14 | |
92ae0f2f |
15 | #include <Bnd_Box.hxx> |
42cf5bc1 |
16 | #include <BOPAlgo_BuilderSolid.hxx> |
17 | #include <BOPAlgo_MakerVolume.hxx> |
18 | #include <BOPAlgo_PaveFiller.hxx> |
977ad983 |
19 | #include <BOPAlgo_Tools.hxx> |
33ba8565 |
20 | #include <BOPAlgo_Alerts.hxx> |
92ae0f2f |
21 | #include <BOPDS_DS.hxx> |
92ae0f2f |
22 | #include <BOPTools_AlgoTools.hxx> |
42cf5bc1 |
23 | #include <BRepPrimAPI_MakeBox.hxx> |
42cf5bc1 |
24 | #include <TopExp_Explorer.hxx> |
25 | #include <TopoDS_Solid.hxx> |
1155d05a |
26 | #include <TopTools_ListOfShape.hxx> |
92ae0f2f |
27 | |
28 | static |
29 | void AddFace(const TopoDS_Shape& theF, |
1155d05a |
30 | TopTools_ListOfShape& theLF); |
92ae0f2f |
31 | |
b1d15f53 |
32 | //======================================================================= |
33 | //function : CheckData |
34 | //purpose : |
35 | //======================================================================= |
36 | void BOPAlgo_MakerVolume::CheckData() |
37 | { |
38 | if (myArguments.IsEmpty()) { |
33ba8565 |
39 | AddError (new BOPAlgo_AlertTooFewArguments); // no arguments to process |
b1d15f53 |
40 | return; |
41 | } |
42 | // |
33ba8565 |
43 | CheckFiller(); |
b1d15f53 |
44 | } |
45 | |
92ae0f2f |
46 | //======================================================================= |
47 | //function : Perform |
48 | //purpose : |
49 | //======================================================================= |
d03c0898 |
50 | void BOPAlgo_MakerVolume::Perform(const Message_ProgressRange& theRange) |
92ae0f2f |
51 | { |
d03c0898 |
52 | Message_ProgressScope aPS(theRange, "Performing MakeVolume operation", 10); |
53 | Standard_Real anInterPart = myIntersect ? 9 : 0.5; |
54 | Standard_Real aBuildPart = 10. - anInterPart; |
55 | |
33ba8565 |
56 | GetReport()->Clear(); |
92ae0f2f |
57 | // |
58 | if (myEntryPoint == 1) { |
59 | if (myPaveFiller) { |
60 | delete myPaveFiller; |
61 | myPaveFiller = NULL; |
62 | } |
63 | } |
64 | // |
488e5b9d |
65 | Handle(NCollection_BaseAllocator) aAllocator = |
66 | NCollection_BaseAllocator::CommonBaseAllocator(); |
92ae0f2f |
67 | BOPAlgo_PaveFiller* pPF = new BOPAlgo_PaveFiller(aAllocator); |
68 | // |
69 | if (!myIntersect) { |
70 | //if there is no need to intersect the arguments, then it is necessary |
71 | //to create the compound of them and use it as one argument |
72 | TopoDS_Compound anArgs; |
73 | BRep_Builder aBB; |
1155d05a |
74 | TopTools_ListIteratorOfListOfShape aIt; |
75 | TopTools_ListOfShape aLS; |
92ae0f2f |
76 | // |
77 | aBB.MakeCompound(anArgs); |
78 | aIt.Initialize(myArguments); |
79 | for (; aIt.More(); aIt.Next()) { |
80 | const TopoDS_Shape& aS = aIt.Value(); |
81 | aBB.Add(anArgs, aS); |
82 | } |
83 | aLS.Append(anArgs); |
84 | // |
85 | pPF->SetArguments(aLS); |
86 | } |
87 | else { |
88 | pPF->SetArguments(myArguments); |
89 | } |
90 | // |
91 | pPF->SetRunParallel(myRunParallel); |
b1d15f53 |
92 | pPF->SetFuzzyValue(myFuzzyValue); |
3510db62 |
93 | pPF->SetNonDestructive(myNonDestructive); |
483ce1bd |
94 | pPF->SetGlue(myGlue); |
944768d2 |
95 | pPF->SetUseOBB(myUseOBB); |
d03c0898 |
96 | pPF->Perform(aPS.Next(anInterPart)); |
92ae0f2f |
97 | // |
98 | myEntryPoint = 1; |
d03c0898 |
99 | PerformInternal(*pPF, aPS.Next(aBuildPart)); |
92ae0f2f |
100 | } |
101 | |
102 | //======================================================================= |
103 | //function : PerformInternal1 |
104 | //purpose : |
105 | //======================================================================= |
106 | void BOPAlgo_MakerVolume::PerformInternal1 |
d03c0898 |
107 | (const BOPAlgo_PaveFiller& theFiller, const Message_ProgressRange& theRange) |
92ae0f2f |
108 | { |
d03c0898 |
109 | Message_ProgressScope aPS(theRange, "Building volumes", 100); |
92ae0f2f |
110 | myPaveFiller = (BOPAlgo_PaveFiller*)&theFiller; |
111 | myDS = myPaveFiller->PDS(); |
112 | myContext = myPaveFiller->Context(); |
113 | // |
114 | // 1. CheckData |
115 | CheckData(); |
33ba8565 |
116 | if (HasErrors()) { |
92ae0f2f |
117 | return; |
118 | } |
119 | // |
120 | // 2. Prepare |
121 | Prepare(); |
33ba8565 |
122 | if (HasErrors()) { |
92ae0f2f |
123 | return; |
124 | } |
125 | // |
d03c0898 |
126 | BOPAlgo_PISteps aSteps(PIOperation_Last); |
127 | analyzeProgress(100., aSteps); |
128 | |
92ae0f2f |
129 | // 3. Fill Images |
92ae0f2f |
130 | if (myIntersect) { |
d03c0898 |
131 | // 3.1. Vertices |
132 | FillImagesVertices(aPS.Next(aSteps.GetStep(PIOperation_TreatVertices))); |
33ba8565 |
133 | if (HasErrors()) { |
92ae0f2f |
134 | return; |
135 | } |
136 | // 3.2. Edges |
d03c0898 |
137 | FillImagesEdges(aPS.Next(aSteps.GetStep(PIOperation_TreatEdges))); |
33ba8565 |
138 | if (HasErrors()) { |
92ae0f2f |
139 | return; |
140 | } |
141 | // 3.3. Wires |
d03c0898 |
142 | FillImagesContainers(TopAbs_WIRE, aPS.Next(aSteps.GetStep(PIOperation_TreatWires))); |
33ba8565 |
143 | if (HasErrors()) { |
92ae0f2f |
144 | return; |
145 | } |
146 | // 3.4. Faces |
d03c0898 |
147 | FillImagesFaces(aPS.Next(aSteps.GetStep(PIOperation_TreatFaces))); |
33ba8565 |
148 | if (HasErrors()) { |
92ae0f2f |
149 | return; |
150 | } |
151 | } |
152 | // |
153 | // 4. Collect faces |
154 | CollectFaces(); |
33ba8565 |
155 | if (HasErrors()) { |
92ae0f2f |
156 | return; |
157 | } |
158 | // |
1155d05a |
159 | TopTools_MapOfShape aBoxFaces; |
160 | TopTools_ListOfShape aLSR; |
92ae0f2f |
161 | // |
162 | // 5. Create bounding box |
163 | MakeBox(aBoxFaces); |
164 | // |
165 | // 6. Make volumes |
d03c0898 |
166 | BuildSolids(aLSR, aPS.Next(aSteps.GetStep(PIOperation_BuildSolids))); |
33ba8565 |
167 | if (HasErrors()) { |
92ae0f2f |
168 | return; |
169 | } |
170 | // |
171 | // 7. Treat the result |
172 | RemoveBox(aLSR, aBoxFaces); |
173 | // |
174 | // 8. Fill internal shapes |
175 | FillInternalShapes(aLSR); |
176 | // |
177 | // 9. Build Result |
178 | BuildShape(aLSR); |
179 | // |
180 | // 10. History |
d03c0898 |
181 | PrepareHistory(aPS.Next(aSteps.GetStep(PIOperation_FillHistory))); |
182 | if (HasErrors()) { |
183 | return; |
184 | } |
92ae0f2f |
185 | // |
186 | // 11. Post-treatment |
d03c0898 |
187 | PostTreat(aPS.Next(aSteps.GetStep(PIOperation_PostTreat))); |
188 | } |
189 | |
190 | //======================================================================= |
191 | //function : fillPISteps |
192 | //purpose : |
193 | //======================================================================= |
194 | void BOPAlgo_MakerVolume::fillPISteps(BOPAlgo_PISteps& theSteps) const |
195 | { |
196 | NbShapes aNbShapes = getNbShapes(); |
197 | if (myIntersect) |
198 | { |
199 | theSteps.SetStep(PIOperation_TreatVertices, aNbShapes.NbVertices()); |
200 | theSteps.SetStep(PIOperation_TreatEdges, aNbShapes.NbEdges()); |
201 | theSteps.SetStep(PIOperation_TreatWires, aNbShapes.NbWires()); |
202 | theSteps.SetStep(PIOperation_TreatFaces, 50 * aNbShapes.NbFaces()); |
203 | } |
204 | theSteps.SetStep(PIOperation_BuildSolids, 50 * aNbShapes.NbFaces()); |
92ae0f2f |
205 | } |
206 | |
207 | //======================================================================= |
208 | //function : CollectFaces |
209 | //purpose : |
210 | //======================================================================= |
211 | void BOPAlgo_MakerVolume::CollectFaces() |
212 | { |
92ae0f2f |
213 | // |
214 | Standard_Integer i, aNbShapes; |
1155d05a |
215 | TopTools_ListIteratorOfListOfShape aIt; |
216 | TopTools_MapOfShape aMFence; |
92ae0f2f |
217 | // |
218 | aNbShapes = myDS->NbSourceShapes(); |
219 | for (i = 0; i < aNbShapes; ++i) { |
220 | const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); |
221 | if (aSI.ShapeType() != TopAbs_FACE) { |
222 | continue; |
223 | } |
224 | // |
225 | const Bnd_Box& aB = aSI.Box(); |
226 | myBBox.Add(aB); |
227 | // |
228 | const TopoDS_Shape& aF = aSI.Shape(); |
229 | if (myImages.IsBound(aF)) { |
1155d05a |
230 | const TopTools_ListOfShape& aLFIm = myImages.Find(aF); |
92ae0f2f |
231 | aIt.Initialize(aLFIm); |
232 | for (; aIt.More(); aIt.Next()) { |
233 | const TopoDS_Shape& aFIm = aIt.Value(); |
c45fefa7 |
234 | if (aMFence.Add(aFIm)) { |
235 | AddFace(aFIm, myFaces); |
236 | } |
92ae0f2f |
237 | } |
238 | } |
239 | else { |
240 | AddFace(aF, myFaces); |
241 | } |
242 | } |
243 | } |
244 | |
245 | //======================================================================= |
246 | //function : MakeBox |
247 | //purpose : |
248 | //======================================================================= |
1155d05a |
249 | void BOPAlgo_MakerVolume::MakeBox(TopTools_MapOfShape& theBoxFaces) |
92ae0f2f |
250 | { |
92ae0f2f |
251 | // |
252 | Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, anExt; |
253 | // |
0f04f1e1 |
254 | anExt = sqrt(myBBox.SquareExtent()) * 0.5; |
92ae0f2f |
255 | myBBox.Enlarge(anExt); |
256 | myBBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); |
257 | // |
258 | gp_Pnt aPMin(aXmin, aYmin, aZmin), |
259 | aPMax(aXmax, aYmax, aZmax); |
260 | // |
261 | mySBox = BRepPrimAPI_MakeBox(aPMin, aPMax).Solid(); |
262 | // |
263 | TopExp_Explorer aExp(mySBox, TopAbs_FACE); |
264 | for (; aExp.More(); aExp.Next()) { |
265 | const TopoDS_Shape& aF = aExp.Current(); |
266 | myFaces.Append(aF); |
267 | theBoxFaces.Add(aF); |
268 | } |
269 | } |
270 | |
271 | //======================================================================= |
272 | //function : BuildSolids |
273 | //purpose : |
274 | //======================================================================= |
d03c0898 |
275 | void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR, |
276 | const Message_ProgressRange& theRange) |
92ae0f2f |
277 | { |
92ae0f2f |
278 | BOPAlgo_BuilderSolid aBS; |
279 | // |
92ae0f2f |
280 | aBS.SetShapes(myFaces); |
281 | aBS.SetRunParallel(myRunParallel); |
291fced1 |
282 | aBS.SetAvoidInternalShapes(myAvoidInternalShapes); |
d03c0898 |
283 | aBS.Perform(theRange); |
33ba8565 |
284 | if (aBS.HasErrors()) |
285 | { |
286 | AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed |
92ae0f2f |
287 | return; |
288 | } |
289 | // |
7f3408c8 |
290 | myReport->Merge(aBS.GetReport()); |
291 | // |
92ae0f2f |
292 | theLSR = aBS.Areas(); |
293 | } |
294 | |
295 | //======================================================================= |
296 | //function : TreatResult |
297 | //purpose : |
298 | //======================================================================= |
1155d05a |
299 | void BOPAlgo_MakerVolume::RemoveBox(TopTools_ListOfShape& theLSR, |
300 | const TopTools_MapOfShape& theBoxFaces) |
92ae0f2f |
301 | { |
92ae0f2f |
302 | // |
1155d05a |
303 | TopTools_ListIteratorOfListOfShape aIt; |
92ae0f2f |
304 | TopExp_Explorer aExp; |
305 | Standard_Boolean bFound; |
306 | // |
307 | bFound = Standard_False; |
308 | aIt.Initialize(theLSR); |
309 | for (; aIt.More(); aIt.Next()) { |
310 | const TopoDS_Shape& aSR = aIt.Value(); |
311 | // |
312 | aExp.Init(aSR, TopAbs_FACE); |
313 | for (; aExp.More(); aExp.Next()) { |
314 | const TopoDS_Shape& aF = aExp.Current(); |
315 | if (theBoxFaces.Contains(aF)) { |
316 | bFound = Standard_True; |
317 | theLSR.Remove(aIt); |
318 | break; |
319 | } |
320 | } |
321 | if (bFound) { |
322 | break; |
323 | } |
324 | } |
325 | } |
326 | |
327 | //======================================================================= |
328 | //function : BuildShape |
329 | //purpose : |
330 | //======================================================================= |
1155d05a |
331 | void BOPAlgo_MakerVolume::BuildShape(const TopTools_ListOfShape& theLSR) |
92ae0f2f |
332 | { |
333 | if (theLSR.Extent() == 1) { |
334 | myShape = theLSR.First(); |
335 | } |
336 | else { |
337 | BRep_Builder aBB; |
1155d05a |
338 | TopTools_ListIteratorOfListOfShape aIt; |
92ae0f2f |
339 | // |
340 | aIt.Initialize(theLSR); |
341 | for (; aIt.More(); aIt.Next()) { |
342 | const TopoDS_Shape& aSol = aIt.Value(); |
343 | aBB.Add(myShape, aSol); |
344 | } |
345 | } |
346 | } |
347 | |
348 | //======================================================================= |
349 | //function : FillInternalShapes |
350 | //purpose : |
351 | //======================================================================= |
1155d05a |
352 | void BOPAlgo_MakerVolume::FillInternalShapes(const TopTools_ListOfShape& theLSR) |
92ae0f2f |
353 | { |
291fced1 |
354 | if (myAvoidInternalShapes) { |
355 | return; |
356 | } |
13c0e402 |
357 | |
13c0e402 |
358 | // Get all non-compound shapes |
359 | TopTools_ListOfShape aLSC; |
360 | // Fence map |
1155d05a |
361 | TopTools_MapOfShape aMFence; |
13c0e402 |
362 | |
363 | TopTools_ListOfShape::Iterator itLA(myDS->Arguments()); |
364 | for (; itLA.More(); itLA.Next()) |
739c7e59 |
365 | BOPTools_AlgoTools::TreatCompound(itLA.Value(), aLSC, &aMFence); |
13c0e402 |
366 | |
367 | // Get only edges and vertices from arguments |
368 | TopTools_ListOfShape aLVE; |
369 | |
370 | itLA.Initialize(aLSC); |
371 | for (; itLA.More(); itLA.Next()) |
372 | { |
373 | const TopoDS_Shape& aS = itLA.Value(); |
374 | TopAbs_ShapeEnum aType = aS.ShapeType(); |
375 | if (aType == TopAbs_WIRE) |
376 | { |
377 | for (TopoDS_Iterator it(aS); it.More(); it.Next()) |
378 | { |
379 | const TopoDS_Shape& aSS = it.Value(); |
380 | if (aMFence.Add(aSS)) |
381 | aLVE.Append(aSS); |
92ae0f2f |
382 | } |
383 | } |
13c0e402 |
384 | else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) |
92ae0f2f |
385 | aLVE.Append(aS); |
92ae0f2f |
386 | } |
13c0e402 |
387 | |
388 | BOPAlgo_Tools::FillInternals(theLSR, aLVE, myImages, myContext); |
92ae0f2f |
389 | } |
390 | |
391 | //======================================================================= |
392 | //function : AddFace |
393 | //purpose : |
394 | //======================================================================= |
395 | void AddFace(const TopoDS_Shape& theF, |
1155d05a |
396 | TopTools_ListOfShape& theLF) |
92ae0f2f |
397 | { |
398 | TopoDS_Shape aFF = theF; |
399 | aFF.Orientation(TopAbs_FORWARD); |
400 | theLF.Append(aFF); |
401 | aFF.Orientation(TopAbs_REVERSED); |
402 | theLF.Append(aFF); |
403 | } |