d9ca2e0c |
1 | // Created by: Eugeny MALTCHIKOV |
2 | // Copyright (c) 2018 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 | |
15 | #include <BOPAlgo_RemoveFeatures.hxx> |
16 | |
17 | #include <BOPAlgo_Alerts.hxx> |
18 | #include <BOPAlgo_BOP.hxx> |
19 | #include <BOPAlgo_Builder.hxx> |
20 | #include <BOPAlgo_BuilderSolid.hxx> |
21 | #include <BOPAlgo_MakerVolume.hxx> |
22 | #include <BOPAlgo_Tools.hxx> |
23 | |
24 | #include <BOPTools_AlgoTools.hxx> |
25 | #include <BOPTools_Parallel.hxx> |
26 | #include <BOPTools_Set.hxx> |
27 | |
28 | #include <Bnd_Box.hxx> |
29 | |
30 | #include <BRep_Builder.hxx> |
31 | |
32 | #include <BRepBndLib.hxx> |
33 | |
34 | #include <BRepLib.hxx> |
35 | |
36 | #include <NCollection_Vector.hxx> |
37 | |
38 | #include <ShapeUpgrade_UnifySameDomain.hxx> |
39 | |
40 | #include <TopAbs_ShapeEnum.hxx> |
41 | |
42 | #include <TopExp.hxx> |
43 | #include <TopExp_Explorer.hxx> |
44 | |
45 | #include <TopoDS.hxx> |
46 | #include <TopoDS_Compound.hxx> |
47 | #include <TopoDS_Edge.hxx> |
48 | #include <TopoDS_Face.hxx> |
49 | |
50 | #include <TopTools_IndexedDataMapOfShapeShape.hxx> |
51 | |
52 | |
53 | //======================================================================= |
54 | // static methods declaration |
55 | //======================================================================= |
56 | |
57 | static void MakeRemoved(const TopTools_ListOfShape& theShapes, |
58 | BRepTools_History& theHistory, |
59 | const TopTools_IndexedMapOfShape& theKeepShapes = TopTools_IndexedMapOfShape()); |
60 | |
61 | static void FindInternals(const TopoDS_Shape& theS, |
62 | TopTools_ListOfShape& theLInt); |
63 | |
64 | static void RemoveInternalWires(const TopTools_ListOfShape& theShapes, |
65 | TopTools_ListOfShape* theRemoved = NULL); |
66 | |
67 | static void GetOriginalFaces(const TopoDS_Shape& theShape, |
68 | const TopTools_IndexedMapOfShape& theSolids, |
69 | const TopTools_MapOfShape& theFeatureFacesMap, |
70 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
71 | const Handle(BRepTools_History)& theHistory, |
72 | TopTools_IndexedMapOfShape& theFacesToBeKept, |
73 | TopTools_ListOfShape& theInternalShapes, |
74 | TopTools_MapOfShape& theFacesToCheckOri, |
75 | TopTools_IndexedMapOfShape& theSolidsToRebuild, |
76 | TopTools_ListOfShape& theSharedFaces, |
77 | TopTools_ListOfShape& theUnTouchedSolids); |
78 | |
79 | static void FindShape(const TopoDS_Shape& theSWhat, |
80 | const TopoDS_Shape& theSWhere, |
81 | TopoDS_Shape& theSFound); |
82 | |
83 | static void GetValidSolids(BOPAlgo_MakerVolume& theMV, |
84 | const TopTools_MapOfShape& theFacesToCheckOri, |
85 | const TopTools_ListOfShape& aSharedFaces, |
86 | const TopoDS_Shape& theOrigFaces, |
87 | const Standard_Integer theNbSol, |
88 | TopTools_ListOfShape& theLSRes, |
89 | TopTools_ListOfShape& theRemovedShapes); |
90 | |
91 | static void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap, |
92 | const TopTools_MapOfShape& theShapesToCheckOri, |
93 | BOPAlgo_Builder& theBuilder, |
94 | TopTools_MapOfShape& theShapesToAvoid, |
95 | TopTools_MapOfShape* theValidShapes = NULL); |
96 | |
97 | static void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids, |
98 | const TopTools_ListOfShape& theLFSharedToAvoid, |
99 | BOPAlgo_Builder& theBuilder, |
100 | TopTools_ListOfShape& theExtraFaces); |
101 | |
102 | static void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn, |
103 | TopTools_ListOfShape& theSolidsRes, |
104 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
105 | BOPAlgo_Builder& theBuilder, |
106 | BRepTools_History& theSolidsHistory); |
107 | |
108 | static void TakeModified(const TopoDS_Shape& theS, |
109 | BOPAlgo_Builder& theBuilder, |
110 | TopTools_ListOfShape& theList); |
111 | |
112 | static void TakeModified(const TopoDS_Shape& theS, |
113 | BOPAlgo_Builder& theBuilder, |
114 | TopTools_MapOfShape& theMap); |
115 | |
116 | static void FindSolid(const TopoDS_Shape& theSolIn, |
117 | const TopTools_ListOfShape& theSolidsRes, |
118 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
119 | BOPAlgo_Builder& theBuilder, |
120 | TopoDS_Shape& theSolOut); |
121 | |
122 | |
123 | //======================================================================= |
124 | // function: Perform |
125 | // purpose: Performs the removal of the requested faces from the input shape |
126 | //======================================================================= |
127 | void BOPAlgo_RemoveFeatures::Perform() |
128 | { |
129 | try |
130 | { |
131 | OCC_CATCH_SIGNALS |
132 | |
948fe6ca |
133 | if (HasHistory()) |
d9ca2e0c |
134 | myHistory = new BRepTools_History(); |
135 | |
136 | // Check the input data |
137 | CheckData(); |
138 | if (HasErrors()) |
139 | return; |
140 | |
141 | // Prepare the faces to remove. |
142 | PrepareFeatures(); |
143 | if (HasErrors()) |
144 | return; |
145 | |
146 | // Remove the features and fill the created gaps |
147 | RemoveFeatures(); |
148 | |
149 | // Update history with the removed features |
150 | UpdateHistory(); |
151 | |
152 | // Simplify the result |
153 | SimplifyResult(); |
154 | |
155 | // Post treatment |
156 | PostTreat(); |
157 | } |
a738b534 |
158 | catch (Standard_Failure const&) |
d9ca2e0c |
159 | { |
160 | AddError(new BOPAlgo_AlertRemoveFeaturesFailed()); |
161 | } |
162 | } |
163 | |
164 | //======================================================================= |
165 | // function: CheckData |
166 | // purpose: Checks the input data on validity for the algorithm |
167 | //======================================================================= |
168 | void BOPAlgo_RemoveFeatures::CheckData() |
169 | { |
170 | // Prepare the shape to work with |
171 | myShape = myInputShape; |
172 | |
173 | // Check the type of input shape |
174 | const TopAbs_ShapeEnum aType = myInputShape.ShapeType(); |
175 | |
176 | if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) |
177 | return; // OK |
178 | |
179 | if (aType == TopAbs_COMPOUND) |
180 | { |
181 | TopTools_ListOfShape aShapes; |
182 | TopTools_MapOfShape aMFence; |
183 | // Extract all shapes from the compound |
184 | BOPAlgo_Tools::TreatCompound(myInputShape, aMFence, aShapes); |
185 | if (aShapes.IsEmpty()) |
186 | { |
187 | // Add error of empty input shape |
188 | AddError(new BOPAlgo_AlertEmptyShape(myInputShape)); |
189 | return; |
190 | } |
191 | |
192 | // Find all solids in the list of shapes |
193 | TopTools_ListOfShape aSolids; |
194 | TopTools_ListOfShape anOtherShapes; |
195 | TopTools_ListIteratorOfListOfShape aIt(aShapes); |
196 | for (; aIt.More(); aIt.Next()) |
197 | { |
198 | const TopoDS_Shape& aS = aIt.Value(); |
199 | if (aS.ShapeType() == TopAbs_SOLID || aS.ShapeType() == TopAbs_COMPSOLID) |
200 | aSolids.Append(aS); |
201 | else |
202 | anOtherShapes.Append(aS); |
203 | } |
204 | |
205 | if (aSolids.IsEmpty()) |
206 | { |
207 | // No solids have been found for processing. |
208 | // Add error of unsupported type of input shape |
209 | AddError(new BOPAlgo_AlertTooFewArguments()); |
210 | } |
211 | else if (anOtherShapes.Extent() > 0) |
212 | { |
213 | // Add warning of unsupported type of input shape for all |
214 | // non-solid shapes, contained in the input shape |
215 | for (aIt.Initialize(anOtherShapes); aIt.More(); aIt.Next()) |
216 | { |
217 | AddWarning(new BOPAlgo_AlertUnsupportedType(aIt.Value())); |
218 | } |
219 | |
220 | // Collect all solids into compound and overwrite the shape to rebuild |
221 | TopoDS_Compound aCS; |
222 | BRep_Builder().MakeCompound(aCS); |
223 | for (aIt.Initialize(aSolids); aIt.More(); aIt.Next()) |
224 | BRep_Builder().Add(aCS, aIt.Value()); |
225 | |
226 | myShape = aCS; |
227 | |
948fe6ca |
228 | if (HasHistory()) |
d9ca2e0c |
229 | { |
230 | // Make non solid shapes removed in the history |
231 | MakeRemoved(anOtherShapes, *myHistory.get()); |
232 | } |
233 | } |
234 | } |
235 | else |
236 | { |
237 | // Add error of unsupported type of input shape |
238 | AddError(new BOPAlgo_AlertTooFewArguments()); |
239 | } |
240 | } |
241 | |
242 | //======================================================================= |
243 | // function: PrepareFeatures |
244 | // purpose: Prepares the features to remove |
245 | //======================================================================= |
246 | void BOPAlgo_RemoveFeatures::PrepareFeatures() |
247 | { |
248 | // Map all sub-shapes of the input solids |
249 | TopExp::MapShapes(myInputShape, myInputsMap); |
250 | |
251 | // Collect all faces of the input shape requested for removal |
252 | TopTools_ListOfShape aFacesToRemove; |
253 | TopTools_ListIteratorOfListOfShape aIt(myFacesToRemove); |
254 | for (; aIt.More(); aIt.Next()) |
255 | { |
256 | const TopoDS_Shape& aS = aIt.Value(); |
257 | TopExp_Explorer anExpF(aS, TopAbs_FACE); |
258 | for (; anExpF.More(); anExpF.Next()) |
259 | { |
260 | const TopoDS_Shape& aF = anExpF.Current(); |
261 | if (myInputsMap.Contains(aF)) |
262 | aFacesToRemove.Append(aF); |
263 | } |
264 | } |
265 | |
266 | if (aFacesToRemove.IsEmpty()) |
267 | { |
268 | // Add error, that no features to remove have been found |
269 | AddError(new BOPAlgo_AlertNoFacesToRemove()); |
270 | return; |
271 | } |
272 | |
273 | // Build connexity blocks of the faces to remove |
274 | TopoDS_Compound aCFToRemove; |
275 | BRep_Builder().MakeCompound(aCFToRemove); |
276 | for (aIt.Initialize(aFacesToRemove); aIt.More(); aIt.Next()) |
277 | BRep_Builder().Add(aCFToRemove, aIt.Value()); |
278 | |
279 | // Fill the list of features with connexity blocks of faces |
280 | BOPTools_AlgoTools::MakeConnexityBlocks(aCFToRemove, TopAbs_EDGE, TopAbs_FACE, myFeatures); |
281 | } |
282 | |
283 | //======================================================================= |
284 | // Adjacent faces extension block |
285 | |
286 | //======================================================================= |
287 | // class: FillGaps |
288 | // purpose: Auxiliary class for creation of the faces for filling the gap |
289 | // created by removal of the single feature |
290 | //======================================================================= |
291 | class FillGap |
292 | { |
293 | public: //! @name Constructors |
294 | |
295 | //! Empty constructor |
296 | FillGap() : |
297 | myRunParallel(Standard_False), |
298 | myHasAdjacentFaces(Standard_False) |
299 | {} |
300 | |
301 | public: //! @name Setters/Getters |
302 | |
303 | //! Sets the feature to remove |
304 | void SetFeature(const TopoDS_Shape& theFeature) { myFeature = theFeature; } |
305 | |
306 | //! Returns the feature |
307 | const TopoDS_Shape& Feature() const { return myFeature; } |
308 | |
309 | //! Sets the EF connection map |
310 | void SetEFConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap) |
311 | { |
312 | myEFMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theEFMap; |
313 | } |
314 | |
315 | //! Sets the FS connection map |
316 | void SetFSConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theFSMap) |
317 | { |
318 | myFSMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theFSMap; |
319 | } |
320 | |
321 | //! Defines the parallel processing mode |
322 | void SetRunParallel(const Standard_Boolean bRunParallel) { myRunParallel = bRunParallel; } |
323 | |
324 | //! Gets the History object |
325 | const Handle(BRepTools_History)& History() |
326 | { |
327 | return myHistory; |
328 | } |
329 | |
330 | public: //! @name Perform the operation |
331 | |
332 | //! Performs the extension of the adjacent faces and |
333 | //! then trims the extended faces to fill the gaps |
334 | void Perform() |
335 | { |
336 | OCC_CATCH_SIGNALS |
337 | |
338 | try |
339 | { |
340 | myHistory = new BRepTools_History(); |
341 | |
342 | // Find the faces adjacent to the faces of the feature |
343 | TopTools_IndexedMapOfShape aMFAdjacent; |
344 | FindAdjacentFaces(aMFAdjacent); |
345 | |
346 | myHasAdjacentFaces = (aMFAdjacent.Extent() > 0); |
347 | if (!myHasAdjacentFaces) |
348 | return; |
349 | |
350 | // Extend the adjacent faces keeping the connection to the original faces |
351 | TopTools_IndexedDataMapOfShapeShape aFaceExtFaceMap; |
352 | ExtendAdjacentFaces(aMFAdjacent, aFaceExtFaceMap); |
353 | |
354 | // Trim the extended faces |
355 | TrimExtendedFaces(aFaceExtFaceMap); |
356 | } |
a738b534 |
357 | catch (Standard_Failure const&) |
d9ca2e0c |
358 | { |
359 | // Make sure the warning will be given on the higher level |
360 | myHasAdjacentFaces = Standard_True; |
361 | myFaces.Clear(); |
362 | } |
363 | } |
364 | |
365 | public: //! @name Obtain the result |
366 | |
367 | //! Returns the map of faces of the feature |
368 | const TopTools_MapOfShape& FeatureFacesMap() const { return myFeatureFacesMap; } |
369 | |
370 | //! Shows whether the adjacent faces have been found for the feature |
371 | Standard_Boolean HasAdjacentFaces() const { return myHasAdjacentFaces; } |
372 | |
373 | //! Returns the Images map of the adjacent faces |
374 | const TopTools_IndexedDataMapOfShapeListOfShape& Faces() const { return myFaces; } |
375 | |
376 | //! Returns the initial solids participating in the feature removal |
377 | const TopTools_IndexedMapOfShape& Solids() const { return mySolids; } |
378 | |
379 | |
380 | private: //! @name Private methods performing the operation |
381 | |
382 | //! Finds the faces adjacent to the feature and stores them into outgoing map. |
383 | void FindAdjacentFaces(TopTools_IndexedMapOfShape& theMFAdjacent) |
384 | { |
385 | // Map the faces of the feature to avoid them in the map of adjacent faces |
386 | TopoDS_Iterator aIt(myFeature); |
387 | for (; aIt.More(); aIt.Next()) |
388 | myFeatureFacesMap.Add(aIt.Value()); |
389 | |
390 | // Find faces adjacent to the feature using the connection map |
391 | aIt.Initialize(myFeature); |
392 | for (; aIt.More(); aIt.Next()) |
393 | { |
394 | const TopoDS_Shape& aF = aIt.Value(); |
395 | TopExp_Explorer anExpE(aF, TopAbs_EDGE); |
396 | for (; anExpE.More(); anExpE.Next()) |
397 | { |
398 | const TopoDS_Shape& aE = anExpE.Current(); |
399 | const TopTools_ListOfShape* pAdjacentFaces = myEFMap->Seek(aE); |
400 | if (pAdjacentFaces) |
401 | { |
402 | TopTools_ListIteratorOfListOfShape itLFA(*pAdjacentFaces); |
403 | for (; itLFA.More(); itLFA.Next()) |
404 | { |
405 | const TopoDS_Shape& anAF = itLFA.Value(); |
406 | if (!myFeatureFacesMap.Contains(anAF)) |
407 | theMFAdjacent.Add(anAF); |
408 | } |
409 | } |
410 | } |
411 | // Find solids containing the feature face |
412 | const TopTools_ListOfShape* pLS = myFSMap->Seek(aF); |
413 | if (pLS) |
414 | { |
415 | TopTools_ListIteratorOfListOfShape itLS(*pLS); |
416 | for (; itLS.More(); itLS.Next()) |
417 | mySolids.Add(itLS.Value()); |
418 | } |
419 | } |
420 | |
421 | // Find solids containing the edges of adjacent faces |
422 | const Standard_Integer aNbFA = theMFAdjacent.Extent(); |
423 | for (Standard_Integer i = 1; i <= aNbFA; ++i) |
424 | { |
425 | TopExp_Explorer anExpEA(theMFAdjacent(i), TopAbs_EDGE); |
426 | for (; anExpEA.More(); anExpEA.Next()) |
427 | { |
428 | // Faces adjacent to the face adjacent to the feature |
429 | const TopTools_ListOfShape* pLFAA = myEFMap->Seek(anExpEA.Current()); |
430 | if (pLFAA) |
431 | { |
432 | TopTools_ListIteratorOfListOfShape itLFAA(*pLFAA); |
433 | for (; itLFAA.More(); itLFAA.Next()) |
434 | { |
435 | // Solids containing the faces |
436 | const TopTools_ListOfShape* pLS = myFSMap->Seek(itLFAA.Value()); |
437 | if (pLS) |
438 | { |
439 | TopTools_ListIteratorOfListOfShape itLS(*pLS); |
440 | for (; itLS.More(); itLS.Next()) |
441 | mySolids.Add(itLS.Value()); |
442 | } |
443 | } |
444 | } |
445 | } |
446 | } |
447 | } |
448 | |
449 | //! Extends the found adjacent faces and binds them to the original faces. |
450 | void ExtendAdjacentFaces(const TopTools_IndexedMapOfShape& theMFAdjacent, |
451 | TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap) |
452 | { |
453 | // Get the extension value for the faces - half of the diagonal of bounding box of the feature |
454 | Bnd_Box aFeatureBox; |
455 | BRepBndLib::Add(myFeature, aFeatureBox); |
456 | |
457 | const Standard_Real anExtLength = sqrt(aFeatureBox.SquareExtent()); |
458 | |
459 | const Standard_Integer aNbFA = theMFAdjacent.Extent(); |
460 | for (Standard_Integer i = 1; i <= aNbFA; ++i) |
461 | { |
462 | const TopoDS_Face& aF = TopoDS::Face(theMFAdjacent(i)); |
463 | // Extend the face |
464 | TopoDS_Face aFExt; |
465 | BRepLib::ExtendFace(aF, anExtLength, |
466 | Standard_True, Standard_True, |
467 | Standard_True, Standard_True, |
468 | aFExt); |
469 | theFaceExtFaceMap.Add(aF, aFExt); |
470 | myHistory->AddModified(aF, aFExt); |
471 | } |
472 | } |
473 | |
474 | //! Trims the extended adjacent faces by intersection with each other |
475 | //! and following intersection with the bounds of original faces. |
476 | void TrimExtendedFaces(const TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap) |
477 | { |
478 | // Intersect the extended faces first |
479 | BOPAlgo_Builder aGFInter; |
480 | // Add faces for intersection |
481 | const Standard_Integer aNbF = theFaceExtFaceMap.Extent(); |
482 | for (Standard_Integer i = 1; i <= aNbF; ++i) |
483 | aGFInter.AddArgument(theFaceExtFaceMap(i)); |
484 | |
485 | aGFInter.SetRunParallel(myRunParallel); |
486 | |
487 | // Intersection result |
488 | TopoDS_Shape anIntResult; |
489 | if (aGFInter.Arguments().Extent() > 1) |
490 | { |
491 | aGFInter.Perform(); |
492 | if (aGFInter.HasErrors()) |
493 | return; |
494 | |
495 | anIntResult = aGFInter.Shape(); |
496 | |
948fe6ca |
497 | myHistory->Merge(aGFInter.History()); |
d9ca2e0c |
498 | } |
499 | else |
500 | anIntResult = aGFInter.Arguments().First(); |
501 | |
502 | // Prepare the EF map of the extended faces after intersection |
503 | // to select from them only boundary edges |
504 | TopTools_IndexedDataMapOfShapeListOfShape anEFExtMap; |
505 | TopExp::MapShapesAndAncestors(anIntResult, TopAbs_EDGE, TopAbs_FACE, anEFExtMap); |
506 | |
507 | // Get the splits of the extended faces after intersection |
508 | // and trim them by the edges of the original faces |
509 | |
510 | // Map the edges of the Feature to avoid them during the trim |
511 | TopTools_IndexedMapOfShape aFeatureEdgesMap; |
512 | TopExp::MapShapes(myFeature, TopAbs_EDGE, aFeatureEdgesMap); |
513 | |
514 | for (Standard_Integer i = 1; i <= aNbF; ++i) |
515 | { |
516 | const TopoDS_Face& aFOriginal = TopoDS::Face(theFaceExtFaceMap.FindKey(i)); |
517 | const TopoDS_Face& aFExt = TopoDS::Face(theFaceExtFaceMap(i)); |
518 | TrimFace(aFExt, aFOriginal, aFeatureEdgesMap, anEFExtMap, aGFInter); |
519 | } |
520 | } |
521 | |
522 | //! Trim the extended faces by the bounds of the original face, |
523 | //! except those contained in the feature to remove. |
524 | void TrimFace(const TopoDS_Face& theFExt, |
525 | const TopoDS_Face& theFOriginal, |
526 | const TopTools_IndexedMapOfShape& theFeatureEdgesMap, |
527 | const TopTools_IndexedDataMapOfShapeListOfShape& theEFExtMap, |
528 | BOPAlgo_Builder& theGFInter) |
529 | { |
530 | // Map all edges of the extended face, to filter the result of trim |
531 | // from the faces containing these edges |
532 | TopTools_MapOfShape aMExtEdges; |
533 | TopExp_Explorer anExpE(theFExt, TopAbs_EDGE); |
534 | for (; anExpE.More(); anExpE.Next()) |
535 | { |
536 | const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current()); |
537 | // skip degenerated and seam edges |
538 | if (BRep_Tool::Degenerated(aE) || BRep_Tool::IsClosed(aE, theFExt)) |
539 | continue; |
540 | TopTools_ListOfShape aLEIm; |
541 | TakeModified(aE, theGFInter, aLEIm); |
542 | TopTools_ListIteratorOfListOfShape itLEIm(aLEIm); |
543 | for (; itLEIm.More(); itLEIm.Next()) |
544 | { |
545 | const TopoDS_Shape& aEIm = itLEIm.Value(); |
546 | if (theEFExtMap.FindFromKey(aEIm).Extent() == 1) |
547 | aMExtEdges.Add(aEIm); |
548 | } |
549 | } |
550 | |
551 | // Trimming tool |
552 | BOPAlgo_Builder aGFTrim; |
553 | |
554 | // Get the splits of the face and add them for trimming |
555 | TopTools_ListOfShape anExtSplits; |
556 | TakeModified(theFExt, theGFInter, anExtSplits); |
557 | aGFTrim.SetArguments(anExtSplits); |
558 | |
559 | // Add edges of the original faces |
560 | TopTools_MapOfShape aMEdgesToCheckOri; |
561 | anExpE.Init(theFOriginal, TopAbs_EDGE); |
562 | for (; anExpE.More(); anExpE.Next()) |
563 | { |
564 | const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current()); |
565 | if (!theFeatureEdgesMap.Contains(aE)) |
566 | { |
567 | aGFTrim.AddArgument(aE); |
568 | if (!BRep_Tool::Degenerated(aE) && |
569 | !BRep_Tool::IsClosed(aE, theFOriginal)) |
570 | { |
571 | if (!aMEdgesToCheckOri.Add(aE)) |
572 | aMEdgesToCheckOri.Remove(aE); |
573 | } |
574 | } |
575 | } |
576 | |
577 | // Avoid faces intersection |
578 | aGFTrim.SetGlue(BOPAlgo_GlueShift); |
579 | aGFTrim.SetRunParallel(myRunParallel); |
580 | aGFTrim.SetNonDestructive(Standard_True); |
581 | |
582 | aGFTrim.Perform(); |
583 | if (aGFTrim.HasErrors()) |
584 | return; |
585 | |
586 | // Get all splits |
587 | const TopoDS_Shape& aSplits = aGFTrim.Shape(); |
588 | // Filter the trimmed faces and save the valid ones into result map |
589 | TopTools_ListOfShape aLFTrimmed; |
590 | |
591 | TopExp_Explorer anExpF(aSplits, TopAbs_FACE); |
592 | for (; anExpF.More(); anExpF.Next()) |
593 | { |
594 | const TopoDS_Shape& aSp = anExpF.Current(); |
595 | anExpE.Init(aSp, TopAbs_EDGE); |
596 | for (; anExpE.More(); anExpE.Next()) |
597 | { |
598 | if (aMExtEdges.Contains(anExpE.Current())) |
599 | break; |
600 | } |
601 | if (!anExpE.More()) |
602 | aLFTrimmed.Append(aSp); |
603 | } |
604 | |
605 | if (aLFTrimmed.Extent() > 1) |
606 | { |
607 | // Chose the correct faces - the ones that contains edges with proper |
608 | // bi-normal direction |
609 | TopTools_IndexedDataMapOfShapeListOfShape anEFMap; |
610 | TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed); |
611 | for (; itLF.More(); itLF.Next()) |
612 | TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap); |
613 | |
614 | // Check edges orientations |
615 | TopTools_MapOfShape aFacesToAvoid, aValidFaces; |
616 | FindExtraShapes(anEFMap, aMEdgesToCheckOri, aGFTrim, aFacesToAvoid, &aValidFaces); |
617 | |
618 | if (aLFTrimmed.Extent() - aFacesToAvoid.Extent() > 1) |
619 | { |
620 | // It is possible that the splits are forming the different blocks. |
621 | // Take only those containing the valid faces. |
622 | TopoDS_Compound aCF; |
623 | BRep_Builder().MakeCompound(aCF); |
624 | itLF.Initialize(aLFTrimmed); |
625 | for (; itLF.More(); itLF.Next()) |
626 | { |
627 | if (!aFacesToAvoid.Contains(itLF.Value())) |
628 | BRep_Builder().Add(aCF, itLF.Value()); |
629 | } |
630 | |
631 | TopTools_ListOfShape aLCB; |
632 | BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB); |
633 | if (aLCB.Extent() > 1) |
634 | { |
635 | TopTools_ListIteratorOfListOfShape itLCB(aLCB); |
636 | for (; itLCB.More(); itLCB.Next()) |
637 | { |
638 | // Check if the block contains any valid faces |
639 | const TopoDS_Shape& aCB = itLCB.Value(); |
640 | TopoDS_Iterator itF(aCB); |
641 | for (; itF.More(); itF.Next()) |
642 | { |
643 | if (aValidFaces.Contains(itF.Value())) |
644 | break; |
645 | } |
646 | if (!itF.More()) |
647 | { |
648 | // Invalid block |
649 | for (itF.Initialize(aCB); itF.More(); itF.Next()) |
650 | aFacesToAvoid.Add(itF.Value()); |
651 | } |
652 | } |
653 | } |
654 | } |
655 | |
656 | itLF.Initialize(aLFTrimmed); |
657 | for (; itLF.More();) |
658 | { |
659 | if (aFacesToAvoid.Contains(itLF.Value())) |
660 | aLFTrimmed.Remove(itLF); |
661 | else |
662 | itLF.Next(); |
663 | } |
664 | } |
665 | else if (aLFTrimmed.IsEmpty()) |
666 | { |
667 | // Use all splits, including those having the bounds of extended face |
668 | anExpF.ReInit(); |
669 | for (; anExpF.More(); anExpF.Next()) |
670 | aLFTrimmed.Append(anExpF.Current()); |
671 | } |
672 | |
673 | if (aLFTrimmed.Extent()) |
674 | { |
675 | // Remove the internal edges and vertices from the faces |
676 | RemoveInternalWires(aLFTrimmed); |
677 | |
678 | myFaces.Add(theFOriginal, aLFTrimmed); |
679 | } |
680 | |
681 | // Update history after intersection of the extended face with bounds |
948fe6ca |
682 | myHistory->Merge(aGFTrim.History()); |
d9ca2e0c |
683 | |
684 | // Update history with all removed shapes |
685 | BRepTools_History aHistRem; |
686 | |
687 | // Map of the result splits |
688 | TopTools_IndexedMapOfShape aResMap; |
689 | TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed); |
690 | for (; itLF.More(); itLF.Next()) |
691 | TopExp::MapShapes(itLF.Value(), aResMap); |
692 | |
693 | TopTools_ListOfShape aLSplits; |
694 | aLSplits.Append(aSplits); |
695 | |
696 | // Update the history with removed shapes |
697 | MakeRemoved(aLSplits, aHistRem, aResMap); |
698 | myHistory->Merge(aHistRem); |
699 | } |
700 | |
701 | private: //! @name Fields |
702 | |
703 | // Inputs |
704 | Standard_Boolean myRunParallel; //!< Defines the mode of processing of the single feature |
705 | TopoDS_Shape myFeature; //!< Feature to remove |
706 | TopTools_IndexedDataMapOfShapeListOfShape* myEFMap; //!< EF Connection map to find adjacent faces |
707 | TopTools_IndexedDataMapOfShapeListOfShape* myFSMap; //!< FS Connection map to find solids participating in the feature removal |
708 | |
709 | // Results |
710 | TopTools_MapOfShape myFeatureFacesMap; //!< Faces of the feature |
711 | Standard_Boolean myHasAdjacentFaces; //!< Flag to show whether the adjacent faces have been found or not |
712 | TopTools_IndexedMapOfShape mySolids; //!< Solids participating in the feature removal |
713 | TopTools_IndexedDataMapOfShapeListOfShape myFaces; //!< Reconstructed adjacent faces |
714 | Handle(BRepTools_History) myHistory; //!< History of the adjacent faces reconstruction |
715 | }; |
716 | |
717 | typedef NCollection_Vector<FillGap> VectorOfFillGap; |
718 | |
719 | typedef BOPTools_Functor <FillGap, VectorOfFillGap> FillGapFunctor; |
720 | |
721 | typedef BOPTools_Cnt <FillGapFunctor, VectorOfFillGap> FillGapCnt; |
722 | |
723 | //======================================================================= |
724 | |
725 | //======================================================================= |
726 | // function: RemoveFeatures |
727 | // purpose: Remove features by filling the gaps by extension of the |
728 | // adjacent faces |
729 | //======================================================================= |
730 | void BOPAlgo_RemoveFeatures::RemoveFeatures() |
731 | { |
732 | // For each feature: |
733 | // - Find the faces adjacent to the feature; |
734 | // - Extend the adjacent faces; |
735 | // - Trim the extended faces to fill the gap; |
736 | // - Rebuild the solids with reconstructed adjacent faces |
737 | // and avoiding the feature faces. |
738 | |
739 | // Make Edge-Face connection map of the input |
740 | // shape to find faces adjacent to the feature |
741 | TopTools_IndexedDataMapOfShapeListOfShape anEFMap; |
742 | TopExp::MapShapesAndAncestors(myInputShape, TopAbs_EDGE, TopAbs_FACE, anEFMap); |
743 | |
744 | // Make Face-Solid connection map to find the solids |
745 | // participating in the removal of each feature |
746 | TopTools_IndexedDataMapOfShapeListOfShape anFSMap; |
747 | TopExp::MapShapesAndAncestors(myInputShape, TopAbs_FACE, TopAbs_SOLID, anFSMap); |
748 | |
749 | // Tool for reconstruction of the faces adjacent to the feature |
750 | // in parallel threads if necessary. |
751 | VectorOfFillGap aVFG; |
752 | // Fill the vector |
753 | TopTools_ListIteratorOfListOfShape itF(myFeatures); |
754 | for (; itF.More(); itF.Next()) |
755 | { |
756 | const TopoDS_Shape& aFeature = itF.Value(); |
757 | FillGap& aFG = aVFG.Appended(); |
758 | aFG.SetFeature(aFeature); |
759 | aFG.SetEFConnectionMap(anEFMap); |
760 | aFG.SetFSConnectionMap(anFSMap); |
761 | aFG.SetRunParallel(myRunParallel); |
762 | } |
763 | |
764 | // Perform the reconstruction of the adjacent faces |
765 | FillGapCnt::Perform(myRunParallel, aVFG); |
766 | |
767 | // Even if the history is not requested, it is necessary to track: |
768 | // - The solids modification after each feature removal to find |
769 | // the necessary solids to rebuild on the next step. |
770 | // - The faces modification after each feature removal to find the |
771 | // splits of the adjacent and feature faces for the next steps. |
772 | if (myHistory.IsNull()) |
773 | myHistory = new BRepTools_History(); |
774 | |
775 | // Remove the features one by one. |
776 | // It will allow removing the features even if there were |
777 | // some problems with removal of the previous features. |
778 | const Standard_Integer aNbF = aVFG.Length(); |
779 | for (Standard_Integer i = 0; i < aNbF; ++i) |
780 | { |
781 | FillGap& aFG = aVFG(i); |
782 | |
783 | // No need to fill the history for solids if the history is not |
784 | // requested and the current feature is the last one. |
948fe6ca |
785 | Standard_Boolean isSolidsHistoryNeeded = HasHistory() || (i < (aNbF - 1)); |
d9ca2e0c |
786 | |
787 | // Perform removal of the single feature |
788 | RemoveFeature(aFG.Feature(), aFG.Solids(), aFG.FeatureFacesMap(), |
789 | aFG.HasAdjacentFaces(), aFG.Faces(), aFG.History(), |
790 | isSolidsHistoryNeeded); |
791 | } |
792 | } |
793 | |
794 | //======================================================================= |
795 | // function: RemoveFeature |
796 | // purpose: Remove the single feature |
797 | //======================================================================= |
798 | void BOPAlgo_RemoveFeatures::RemoveFeature |
799 | (const TopoDS_Shape& theFeature, |
800 | const TopTools_IndexedMapOfShape& theSolids, |
801 | const TopTools_MapOfShape& theFeatureFacesMap, |
802 | const Standard_Boolean theHasAdjacentFaces, |
803 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
804 | const Handle(BRepTools_History)& theAdjFacesHistory, |
805 | const Standard_Boolean theSolidsHistoryNeeded) |
806 | { |
807 | Standard_Boolean bFuseShapes = Standard_True; |
808 | const Standard_Integer aNbAF = theAdjFaces.Extent(); |
809 | if (aNbAF == 0) |
810 | { |
811 | if (theHasAdjacentFaces) |
812 | { |
813 | // The adjacent faces have been found for the feature, |
814 | // but something went wrong during their rebuilding. |
815 | // Add error |
816 | AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature)); |
817 | return; |
818 | } |
819 | |
820 | // No adjacent faces have been found for the feature. |
821 | // Most likely, the intention is to remove some internal part of the shape. |
822 | // We just have to rebuild the shape without the feature, no fuse is necessary. |
823 | bFuseShapes = Standard_False; |
824 | } |
825 | |
826 | // Rebuild the shape using MakerVolume algorithm avoiding the faces of the |
827 | // feature and replacing the adjacent faces with their images |
828 | |
829 | BRep_Builder aBB; |
830 | |
831 | // From the faces of input shape build map of faces with which the result will be validated: |
832 | // - all non-internal faces of the input shape (except for adjacent and feature faces) |
833 | // must have some trace in the result solids; |
834 | // - all adjacent faces (if any) must have some trace in the result solids. |
835 | TopTools_IndexedMapOfShape aFacesToBeKept; |
836 | // Build also the map of faces to compare orientation of the original and result faces |
837 | TopTools_MapOfShape aFacesToCheckOri; |
838 | |
839 | // Collect list of internal entities of the input shape to be avoided in result |
840 | // and to make them removed in the history. |
841 | TopTools_ListOfShape anInternalShapes; |
842 | |
843 | // In the feature removal will participate only the solids connected to the feature |
844 | // or the faces adjacent to the feature. |
845 | |
846 | // Solids to be rebuilt after the feature removal |
847 | TopTools_IndexedMapOfShape aSolidsToRebuild; |
848 | // Find faces shared between solids |
849 | TopTools_ListOfShape aSharedFaces; |
850 | // Solids to be avoided in the feature removal and added into result directly |
851 | TopTools_ListOfShape anUnTouchedSolids; |
852 | |
853 | // Prepare to the feature removal - fill all necessary containers |
854 | GetOriginalFaces(myShape, theSolids, theFeatureFacesMap, theAdjFaces, myHistory, |
855 | aFacesToBeKept, anInternalShapes, aFacesToCheckOri, |
856 | aSolidsToRebuild, aSharedFaces, anUnTouchedSolids); |
857 | |
858 | // To avoid excessive intersection of the faces collect the faces |
859 | // of the input shape into a compound |
860 | TopoDS_Compound anOrigF; |
861 | aBB.MakeCompound(anOrigF); |
862 | Standard_Integer aNbFK = aFacesToBeKept.Extent(); |
863 | for (Standard_Integer i = 1; i <= aNbFK; ++i) |
864 | aBB.Add(anOrigF, aFacesToBeKept(i)); |
865 | |
866 | // Tool for solids reconstruction |
867 | BOPAlgo_MakerVolume aMV; |
868 | aMV.SetRunParallel(myRunParallel); |
869 | aMV.SetAvoidInternalShapes(Standard_True); |
870 | aMV.SetIntersect(bFuseShapes); |
871 | aMV.SetNonDestructive(Standard_True); |
872 | // Add faces of the input shape |
873 | aMV.AddArgument(anOrigF); |
874 | |
875 | // Add reconstructed adjacent faces |
876 | for (Standard_Integer i = 1; i <= aNbAF; ++i) |
877 | { |
878 | const TopTools_ListOfShape& aLFA = theAdjFaces(i); |
879 | if (aLFA.Extent() == 1) |
880 | { |
881 | const TopoDS_Shape& aFA = aLFA.First(); |
882 | aMV.AddArgument(aFA); |
883 | aFacesToBeKept.Add(aFA); |
884 | } |
885 | else |
886 | { |
887 | // To avoid intersection among the images, collect them into compound |
888 | TopoDS_Compound anAdjF; |
889 | aBB.MakeCompound(anAdjF); |
890 | TopTools_ListIteratorOfListOfShape itLFA(aLFA); |
891 | for (; itLFA.More(); itLFA.Next()) |
892 | aBB.Add(anAdjF, itLFA.Value()); |
893 | |
894 | aMV.AddArgument(anAdjF); |
895 | aFacesToBeKept.Add(anAdjF); |
896 | } |
897 | |
948fe6ca |
898 | if (HasHistory()) |
d9ca2e0c |
899 | { |
900 | // Look for internal edges in the original adjacent faces |
901 | const TopoDS_Shape& aFOr = theAdjFaces.FindKey(i); |
902 | FindInternals(aFOr, anInternalShapes); |
903 | } |
904 | } |
905 | |
906 | // Build solids |
907 | aMV.Perform(); |
908 | if (aMV.HasErrors()) |
909 | { |
910 | // Add warning for the feature |
911 | AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature)); |
912 | return; |
913 | } |
914 | |
915 | // Result of MV operation |
916 | const TopoDS_Shape& aSolids = aMV.Shape(); |
917 | TopExp_Explorer anExpS(aSolids, TopAbs_SOLID); |
918 | if (!anExpS.More()) |
919 | { |
920 | // No solids have been built - add warning for the feature |
921 | AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature)); |
922 | return; |
923 | } |
924 | |
925 | // Now, it is necessary to: |
926 | // - Validate the result by checking faces of the map <aFacesToBeKept> |
927 | // to have some parts kept in the resulting solids; |
928 | // - Remove the solids possibly filling the holes in the original shapes; |
929 | // - Update history with the history of MakerVolume algorithm. |
930 | |
931 | // Splits of adjacent faces from previous runs |
932 | TopTools_MapOfShape anAdjFacesSplits; |
933 | for (Standard_Integer i = 1; i <= aNbAF; ++i) |
934 | { |
935 | const TopoDS_Shape& aF = theAdjFaces.FindKey(i); |
936 | const TopTools_ListOfShape& aLFIm = myHistory->Modified(aF); |
937 | if (aLFIm.IsEmpty()) |
938 | anAdjFacesSplits.Add(aF); |
939 | else |
940 | { |
941 | TopTools_ListIteratorOfListOfShape itLFIm(aLFIm); |
942 | for (; itLFIm.More(); itLFIm.Next()) |
943 | anAdjFacesSplits.Add(itLFIm.Value()); |
944 | } |
945 | } |
946 | |
947 | // Validate the result |
948 | Standard_Boolean bValid = Standard_True; |
949 | aNbFK = aFacesToBeKept.Extent(); |
950 | for (Standard_Integer i = 1; i <= aNbFK && bValid; ++i) |
951 | { |
952 | const TopoDS_Shape& aS = aFacesToBeKept(i); |
953 | if (anAdjFacesSplits.Contains(aS)) |
954 | continue; |
955 | TopExp_Explorer anExpF(aS, TopAbs_FACE); |
956 | for (; anExpF.More(); anExpF.Next()) |
957 | { |
958 | const TopoDS_Shape& aF = anExpF.Current(); |
959 | if (!aMV.IsDeleted(aF)) |
960 | break; |
961 | } |
962 | bValid = anExpF.More(); |
963 | } |
964 | |
965 | if (!bValid) |
966 | { |
967 | // Add warning for the feature |
968 | AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature)); |
969 | return; |
970 | } |
971 | |
972 | // It is possible that the result of MakerVolume operation contains |
973 | // some extra solids. Get only correct solids. |
974 | TopTools_ListOfShape aLSRes; |
975 | // Remember the removed shapes |
976 | TopTools_ListOfShape aRemovedShapes; |
977 | GetValidSolids(aMV, aFacesToCheckOri, aSharedFaces, anOrigF, theSolids.Extent(), aLSRes, aRemovedShapes); |
978 | |
979 | if (aLSRes.Extent() != theSolids.Extent()) |
980 | { |
981 | // Add warning for the feature |
982 | AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature)); |
983 | return; |
984 | } |
985 | |
986 | // Remove internal wires from the faces, possibly appeared after intersection |
987 | RemoveInternalWires(aLSRes, &anInternalShapes); |
988 | |
989 | // Update history with: |
990 | // History of adjacent faces reconstruction |
991 | myHistory->Merge(theAdjFacesHistory); |
992 | // History of intersection |
948fe6ca |
993 | myHistory->Merge(aMV.History()); |
d9ca2e0c |
994 | |
948fe6ca |
995 | if (HasHistory()) |
d9ca2e0c |
996 | { |
997 | // Map the result to check if the shape is removed |
998 | TopTools_IndexedMapOfShape aMSRes; |
999 | TopTools_ListIteratorOfListOfShape itLS(aLSRes); |
1000 | for (; itLS.More(); itLS.Next()) |
1001 | TopExp::MapShapes(itLS.Value(), aMSRes); |
1002 | |
1003 | // Remove internal shapes and extra faces |
1004 | BRepTools_History aRemHist; |
1005 | anInternalShapes.Append(aRemovedShapes); |
1006 | MakeRemoved(anInternalShapes, aRemHist, aMSRes); |
1007 | myHistory->Merge(aRemHist); |
1008 | } |
1009 | |
1010 | // Fill the history for the solids |
1011 | if (theSolidsHistoryNeeded) |
1012 | { |
1013 | BRepTools_History aSolidsHistory; |
1014 | FillSolidsHistory(aSolidsToRebuild, aLSRes, theAdjFaces, aMV, aSolidsHistory); |
1015 | myHistory->Merge(aSolidsHistory); |
1016 | } |
1017 | |
1018 | TopoDS_Compound aCRes; |
1019 | aBB.MakeCompound(aCRes); |
1020 | // Add reconstructed solids |
1021 | TopTools_ListIteratorOfListOfShape itLS(aLSRes); |
1022 | for (; itLS.More(); itLS.Next()) |
1023 | aBB.Add(aCRes, itLS.Value()); |
1024 | |
1025 | // Add unmodified solids |
1026 | itLS.Initialize(anUnTouchedSolids); |
1027 | for (; itLS.More(); itLS.Next()) |
1028 | aBB.Add(aCRes, itLS.Value()); |
1029 | |
1030 | // Save the result |
1031 | myShape = aCRes; |
1032 | } |
1033 | |
1034 | //======================================================================= |
1035 | // function: UpdateHistory |
1036 | // purpose: Update history with the removed features |
1037 | //======================================================================= |
1038 | void BOPAlgo_RemoveFeatures::UpdateHistory() |
1039 | { |
948fe6ca |
1040 | if (!HasHistory()) |
d9ca2e0c |
1041 | return; |
1042 | |
1043 | // Map the result |
948fe6ca |
1044 | myMapShape.Clear(); |
1045 | TopExp::MapShapes(myShape, myMapShape); |
d9ca2e0c |
1046 | |
1047 | // Update the history |
1048 | BRepTools_History aHistory; |
1049 | |
1050 | const Standard_Integer aNbS = myInputsMap.Extent(); |
1051 | for (Standard_Integer i = 1; i <= aNbS; ++i) |
1052 | { |
1053 | const TopoDS_Shape& aS = myInputsMap(i); |
1054 | if (!BRepTools_History::IsSupportedType(aS)) |
1055 | continue; |
1056 | |
1057 | if (myHistory->IsRemoved(aS)) |
1058 | continue; |
1059 | |
1060 | // Check if the shape has any trace in the result |
1061 | const TopTools_ListOfShape& aLSIm = myHistory->Modified(aS); |
1062 | if (aLSIm.IsEmpty()) |
1063 | { |
948fe6ca |
1064 | if (!myMapShape.Contains(aS)) |
d9ca2e0c |
1065 | aHistory.Remove(aS); |
1066 | } |
1067 | |
1068 | TopTools_ListIteratorOfListOfShape itLSIm(aLSIm); |
1069 | for (; itLSIm.More(); itLSIm.Next()) |
1070 | { |
948fe6ca |
1071 | if (!myMapShape.Contains(itLSIm.Value())) |
d9ca2e0c |
1072 | aHistory.Remove(itLSIm.Value()); |
1073 | } |
1074 | } |
1075 | |
1076 | myHistory->Merge(aHistory); |
1077 | } |
1078 | |
1079 | //======================================================================= |
1080 | // function: SimplifyResult |
1081 | // purpose: Simplifies the result by removing extra edges and vertices |
1082 | // created during operation |
1083 | //======================================================================= |
1084 | void BOPAlgo_RemoveFeatures::SimplifyResult() |
1085 | { |
1086 | if (myShape.IsSame(myInputShape)) |
1087 | return; |
1088 | ShapeUpgrade_UnifySameDomain aSDTool; |
1089 | aSDTool.Initialize(myShape, Standard_True, Standard_True); |
1090 | // Do not allow producing internal edges |
1091 | aSDTool.AllowInternalEdges(Standard_False); |
1092 | // Avoid removal of the input edges and vertices |
948fe6ca |
1093 | if (myMapShape.IsEmpty()) |
1094 | TopExp::MapShapes(myShape, myMapShape); |
d9ca2e0c |
1095 | |
1096 | const Standard_Integer aNbS = myInputsMap.Extent(); |
1097 | for (Standard_Integer i = 1; i <= aNbS; ++i) |
1098 | { |
948fe6ca |
1099 | if (myMapShape.Contains(myInputsMap(i))) |
d9ca2e0c |
1100 | aSDTool.KeepShape(myInputsMap(i)); |
1101 | } |
1102 | |
1103 | // Perform unification |
1104 | aSDTool.Build(); |
1105 | myShape = aSDTool.Shape(); |
948fe6ca |
1106 | if (HasHistory()) |
d9ca2e0c |
1107 | myHistory->Merge(aSDTool.History()); |
1108 | } |
1109 | |
1110 | //======================================================================= |
1111 | // function: PostTreat |
1112 | // purpose: Restore the type of the initial shape |
1113 | //======================================================================= |
1114 | void BOPAlgo_RemoveFeatures::PostTreat() |
1115 | { |
1116 | const TopAbs_ShapeEnum anInputType = myInputShape.ShapeType(); |
1117 | const TopAbs_ShapeEnum aResType = myShape.ShapeType(); |
1118 | if (aResType == anInputType) |
1119 | return; |
1120 | |
1121 | TopExp_Explorer anExpS(myShape, TopAbs_SOLID); |
1122 | |
1123 | if (anInputType == TopAbs_SOLID) |
1124 | { |
1125 | myShape = anExpS.Current(); |
1126 | return; |
1127 | } |
1128 | |
1129 | TopoDS_Shape aRes; |
1130 | if (anInputType == TopAbs_COMPOUND) |
1131 | BRep_Builder().MakeCompound(TopoDS::Compound(aRes)); |
1132 | else |
1133 | BRep_Builder().MakeCompSolid(TopoDS::CompSolid(aRes)); |
1134 | |
1135 | for (; anExpS.More(); anExpS.Next()) |
1136 | BRep_Builder().Add(aRes, anExpS.Current()); |
1137 | |
1138 | myShape = aRes; |
1139 | } |
1140 | |
1141 | //======================================================================= |
1142 | // static methods definition |
1143 | //======================================================================= |
1144 | |
1145 | //======================================================================= |
1146 | // function: MakeRemoved |
1147 | // purpose: Makes the shapes in the list removed in the history. |
1148 | // Keeps the shapes contained in the map. |
1149 | //======================================================================= |
1150 | void MakeRemoved(const TopTools_ListOfShape& theShapes, |
1151 | BRepTools_History& theHistory, |
1152 | const TopTools_IndexedMapOfShape& theKeepShapes) |
1153 | { |
1154 | TopTools_IndexedMapOfShape aShapesMap; |
1155 | TopTools_ListIteratorOfListOfShape it(theShapes); |
1156 | for (; it.More(); it.Next()) |
1157 | TopExp::MapShapes(it.Value(), aShapesMap); |
1158 | |
1159 | const Standard_Integer aNbS = aShapesMap.Extent(); |
1160 | for (Standard_Integer i = 1; i <= aNbS; ++i) |
1161 | { |
1162 | const TopoDS_Shape& aS = aShapesMap(i); |
1163 | if (!theKeepShapes.Contains(aS) && |
1164 | BRepTools_History::IsSupportedType(aS)) |
1165 | { |
1166 | theHistory.Remove(aS); |
1167 | } |
1168 | } |
1169 | } |
1170 | |
1171 | //======================================================================= |
1172 | // function: FindInternals |
1173 | // purpose: Looks for internal shapes inside the face or solid |
1174 | //======================================================================= |
1175 | void FindInternals(const TopoDS_Shape& theS, |
1176 | TopTools_ListOfShape& theLInt) |
1177 | { |
1178 | TopoDS_Iterator itS(theS); |
1179 | for (; itS.More(); itS.Next()) |
1180 | { |
1181 | const TopoDS_Shape& aSS = itS.Value(); |
1182 | if (aSS.Orientation() == TopAbs_INTERNAL) |
1183 | theLInt.Append(aSS); |
1184 | else |
1185 | { |
1186 | TopoDS_Iterator itSS(aSS); |
1187 | for (; itSS.More(); itSS.Next()) |
1188 | { |
1189 | if (itSS.Value().Orientation() == TopAbs_INTERNAL) |
1190 | { |
1191 | theLInt.Append(aSS); |
1192 | break; |
1193 | } |
1194 | } |
1195 | } |
1196 | } |
1197 | } |
1198 | |
1199 | //======================================================================= |
1200 | // function: RemoveInternalWires |
1201 | // purpose: Removes internal wires from the faces |
1202 | //======================================================================= |
1203 | void RemoveInternalWires(const TopTools_ListOfShape& theShapes, |
1204 | TopTools_ListOfShape *theRemoved) |
1205 | { |
1206 | TopTools_ListIteratorOfListOfShape itLS(theShapes); |
1207 | for (; itLS.More(); itLS.Next()) |
1208 | { |
1209 | const TopoDS_Shape& aShape = itLS.Value(); |
1210 | TopExp_Explorer anExpF(aShape, TopAbs_FACE); |
1211 | for (; anExpF.More(); anExpF.Next()) |
1212 | { |
1213 | TopoDS_Face& aF = *(TopoDS_Face*)&anExpF.Current(); |
1214 | TopTools_ListOfShape aLWToRemove; |
1215 | FindInternals(aF, aLWToRemove); |
1216 | if (aLWToRemove.Extent()) |
1217 | { |
1218 | aF.Free(Standard_True); |
1219 | TopTools_ListIteratorOfListOfShape itR(aLWToRemove); |
1220 | for (; itR.More(); itR.Next()) |
1221 | { |
1222 | if (theRemoved) |
1223 | theRemoved->Append(itR.Value()); |
1224 | BRep_Builder().Remove(aF, itR.Value()); |
1225 | } |
1226 | aF.Free(Standard_False); |
1227 | } |
1228 | } |
1229 | } |
1230 | } |
1231 | |
1232 | //======================================================================= |
1233 | // function: GetOriginalFaces |
1234 | // purpose: Get original faces from my face |
1235 | //======================================================================= |
1236 | void GetOriginalFaces(const TopoDS_Shape& theShape, |
1237 | const TopTools_IndexedMapOfShape& theSolids, |
1238 | const TopTools_MapOfShape& theFeatureFacesMap, |
1239 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
1240 | const Handle(BRepTools_History)& theHistory, |
1241 | TopTools_IndexedMapOfShape& theFacesToBeKept, |
1242 | TopTools_ListOfShape& theInternalShapes, |
1243 | TopTools_MapOfShape& theFacesToCheckOri, |
1244 | TopTools_IndexedMapOfShape& theSolidsToRebuild, |
1245 | TopTools_ListOfShape& theSharedFaces, |
1246 | TopTools_ListOfShape& theUnTouchedSolids) |
1247 | { |
1248 | // Use only solids which has to be reconstructed by the feature. |
1249 | // All other solids should be avoided in the feature removal and added |
1250 | // into result directly. |
1251 | |
1252 | // Update solids after removal of previous features |
1253 | const Standard_Integer aNbSols = theSolids.Extent(); |
1254 | for (Standard_Integer i = 1; i <= aNbSols; ++i) |
1255 | { |
1256 | const TopoDS_Shape& aSol = theSolids(i); |
1257 | const TopTools_ListOfShape& aLFIm = theHistory->Modified(aSol); |
1258 | if (aLFIm.IsEmpty()) |
1259 | theSolidsToRebuild.Add(aSol); |
1260 | else |
1261 | theSolidsToRebuild.Add(aLFIm.First()); |
1262 | } |
1263 | |
1264 | // Splits of the feature faces |
1265 | TopTools_MapOfShape aFeatureFacesSplits; |
1266 | TopTools_MapIteratorOfMapOfShape itM(theFeatureFacesMap); |
1267 | for (; itM.More(); itM.Next()) |
1268 | { |
1269 | const TopoDS_Shape& aF = itM.Value(); |
1270 | const TopTools_ListOfShape& aLFIm = theHistory->Modified(aF); |
1271 | if (aLFIm.IsEmpty()) |
1272 | aFeatureFacesSplits.Add(aF); |
1273 | else |
1274 | { |
1275 | TopTools_ListIteratorOfListOfShape itLFIm(aLFIm); |
1276 | for (; itLFIm.More(); itLFIm.Next()) |
1277 | aFeatureFacesSplits.Add(itLFIm.Value()); |
1278 | } |
1279 | } |
1280 | |
1281 | TopExp_Explorer anExpS(theShape, TopAbs_SOLID); |
1282 | for (; anExpS.More(); anExpS.Next()) |
1283 | { |
1284 | const TopoDS_Shape& aSol = anExpS.Current(); |
1285 | |
1286 | // Check if the solid has to be reconstructed |
1287 | if (!theSolidsToRebuild.Contains(aSol)) |
1288 | { |
1289 | // untouched solid |
1290 | theUnTouchedSolids.Append(aSol); |
1291 | continue; |
1292 | } |
1293 | |
1294 | TopoDS_Iterator itSh(aSol); |
1295 | for (; itSh.More(); itSh.Next()) |
1296 | { |
1297 | const TopoDS_Shape& aSh = itSh.Value(); |
1298 | if (aSh.ShapeType() != TopAbs_SHELL) |
1299 | { |
1300 | theInternalShapes.Append(aSh); |
1301 | continue; |
1302 | } |
1303 | |
1304 | TopoDS_Iterator itF(aSh); |
1305 | for (; itF.More(); itF.Next()) |
1306 | { |
1307 | const TopoDS_Shape& aF = itF.Value(); |
1308 | // Avoid the feature faces |
1309 | if (aFeatureFacesSplits.Contains(aF)) |
1310 | continue; |
1311 | |
1312 | // Avoid the adjacent faces |
1313 | if (theAdjFaces.Contains(aF)) |
1314 | continue; |
1315 | |
1316 | if (aF.Orientation() != TopAbs_INTERNAL) |
1317 | { |
1318 | theFacesToBeKept.Add(aF); |
1319 | |
1320 | if (!theFacesToCheckOri.Add(aF)) |
1321 | { |
1322 | theFacesToCheckOri.Remove(aF); |
1323 | theSharedFaces.Append(aF); |
1324 | } |
1325 | } |
1326 | else |
1327 | theInternalShapes.Append(aSh); |
1328 | } |
1329 | } |
1330 | } |
1331 | } |
1332 | |
1333 | //======================================================================= |
1334 | // function: FindShape |
1335 | // purpose: Find the shape in the other shape |
1336 | //======================================================================= |
1337 | void FindShape(const TopoDS_Shape& theSWhat, |
1338 | const TopoDS_Shape& theSWhere, |
1339 | TopoDS_Shape& theSFound) |
1340 | { |
1341 | TopExp_Explorer anExp(theSWhere, theSWhat.ShapeType()); |
1342 | for (; anExp.More(); anExp.Next()) |
1343 | { |
1344 | const TopoDS_Shape& aS = anExp.Current(); |
1345 | if (aS.IsSame(theSWhat)) |
1346 | { |
1347 | theSFound = aS; |
1348 | break; |
1349 | } |
1350 | } |
1351 | } |
1352 | |
1353 | //======================================================================= |
1354 | // function: GetValidSolids |
1355 | // purpose: Checks the validity of the solids and keeps only valid ones |
1356 | //======================================================================= |
1357 | void GetValidSolids(BOPAlgo_MakerVolume& theMV, |
1358 | const TopTools_MapOfShape& theFacesToCheckOri, |
1359 | const TopTools_ListOfShape& aSharedFaces, |
1360 | const TopoDS_Shape& theOrigFaces, |
1361 | const Standard_Integer theNbSol, |
1362 | TopTools_ListOfShape& theLSRes, |
1363 | TopTools_ListOfShape& theRemovedShapes) |
1364 | { |
1365 | TopExp_Explorer anExpS(theMV.Shape(), TopAbs_SOLID); |
1366 | for (; anExpS.More(); anExpS.Next()) |
1367 | theLSRes.Append(anExpS.Current()); |
1368 | |
1369 | if (theLSRes.Extent() > theNbSol) |
1370 | { |
1371 | // Find Solids filling the holes in the initial shape |
1372 | TopTools_MapOfShape aSolidsToAvoid; |
1373 | TopTools_IndexedDataMapOfShapeListOfShape aFSMap; |
1374 | TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_FACE, TopAbs_SOLID, aFSMap); |
1375 | FindExtraShapes(aFSMap, theFacesToCheckOri, theMV, aSolidsToAvoid); |
1376 | |
1377 | TopTools_ListIteratorOfListOfShape itLS(theLSRes); |
1378 | for (; itLS.More(); ) |
1379 | { |
1380 | if (aSolidsToAvoid.Contains(itLS.Value())) |
1381 | theLSRes.Remove(itLS); |
1382 | else |
1383 | itLS.Next(); |
1384 | } |
1385 | } |
1386 | |
1387 | if (theLSRes.Extent() > theNbSol) |
1388 | { |
1389 | // Check if the splits of the adjacent faces split the solids |
1390 | AvoidExtraSharedFaces(theLSRes, aSharedFaces, theMV, theRemovedShapes); |
1391 | } |
1392 | |
1393 | if (theLSRes.Extent() > theNbSol) |
1394 | { |
1395 | // Remove solids containing only the adjacent faces |
1396 | TopTools_MapOfShape anOrigFacesRes; |
1397 | TopExp_Explorer anExpF(theOrigFaces, TopAbs_FACE); |
1398 | for (; anExpF.More(); anExpF.Next()) |
1399 | TakeModified(anExpF.Current(), theMV, anOrigFacesRes); |
1400 | |
1401 | TopTools_ListIteratorOfListOfShape itLS(theLSRes); |
1402 | for (; itLS.More(); ) |
1403 | { |
1404 | anExpF.Init(itLS.Value(), TopAbs_FACE); |
1405 | for (; anExpF.More(); anExpF.Next()) |
1406 | { |
1407 | if (anOrigFacesRes.Contains(anExpF.Current())) |
1408 | break; |
1409 | } |
1410 | if (!anExpF.More()) |
1411 | { |
1412 | theRemovedShapes.Append(itLS.Value()); |
1413 | theLSRes.Remove(itLS); |
1414 | } |
1415 | else |
1416 | itLS.Next(); |
1417 | } |
1418 | } |
1419 | } |
1420 | |
1421 | //======================================================================= |
1422 | // function: FindExtraShape |
1423 | // purpose: Find shapes possibly filling the holes in the original shape |
1424 | //======================================================================= |
1425 | void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap, |
1426 | const TopTools_MapOfShape& theShapesToCheckOri, |
1427 | BOPAlgo_Builder& theBuilder, |
1428 | TopTools_MapOfShape& theShapesToAvoid, |
1429 | TopTools_MapOfShape* theValidShapes) |
1430 | { |
1431 | Handle(IntTools_Context) aCtx = theBuilder.Context(); |
1432 | TopTools_MapOfShape aValidShapes; |
1433 | TopTools_MapOfShape* pValidShapes = theValidShapes ? theValidShapes : &aValidShapes; |
1434 | TopTools_MapIteratorOfMapOfShape itM(theShapesToCheckOri); |
1435 | for (; itM.More(); itM.Next()) |
1436 | { |
1437 | const TopoDS_Shape& aSToCheckOri = itM.Value(); |
1438 | // Check modification of the shape during intersection |
1439 | TopTools_ListOfShape aLSIm; |
1440 | TakeModified(aSToCheckOri, theBuilder, aLSIm); |
1441 | |
1442 | TopTools_ListIteratorOfListOfShape itLSIm(aLSIm); |
1443 | for (; itLSIm.More(); itLSIm.Next()) |
1444 | { |
1445 | const TopoDS_Shape& aSIm = itLSIm.Value(); |
1446 | |
1447 | const TopTools_ListOfShape* pShapesToValidate = theConnectionMap.Seek(aSIm); |
1448 | if (!pShapesToValidate) |
1449 | continue; |
1450 | |
1451 | TopTools_ListIteratorOfListOfShape itSV(*pShapesToValidate); |
1452 | for (; itSV.More(); itSV.Next()) |
1453 | { |
1454 | const TopoDS_Shape& aShapeToValidate = itSV.Value(); |
1455 | if (pValidShapes->Contains(aShapeToValidate)) |
1456 | continue; |
1457 | |
1458 | TopoDS_Face aSInShape; |
1459 | FindShape(aSIm, aShapeToValidate, aSInShape); |
1460 | |
1461 | Standard_Boolean bSameOri = |
1462 | !BOPTools_AlgoTools::IsSplitToReverse(aSInShape, aSToCheckOri, aCtx); |
1463 | |
1464 | if (bSameOri) |
1465 | pValidShapes->Add(aShapeToValidate); |
1466 | else |
1467 | theShapesToAvoid.Add(aShapeToValidate); |
1468 | } |
1469 | } |
1470 | } |
1471 | |
1472 | itM.Initialize(*pValidShapes); |
1473 | for (; itM.More(); itM.Next()) |
1474 | theShapesToAvoid.Remove(itM.Value()); |
1475 | } |
1476 | |
1477 | //======================================================================= |
1478 | // function: AvoidExtraSharedFaces |
1479 | // purpose: Looks for the extra faces splitting the solids |
1480 | //======================================================================= |
1481 | void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids, |
1482 | const TopTools_ListOfShape& theLFSharedToAvoid, |
1483 | BOPAlgo_Builder& theBuilder, |
1484 | TopTools_ListOfShape& theExtraFaces) |
1485 | { |
1486 | // Get all splits of shared faces to avoid in the check |
1487 | TopTools_MapOfShape aMFSharedSp; |
1488 | { |
1489 | TopTools_ListOfShape aLFSharedSp; |
1490 | TopTools_ListIteratorOfListOfShape itLFS(theLFSharedToAvoid); |
1491 | for (; itLFS.More(); itLFS.Next()) |
1492 | TakeModified(itLFS.Value(), theBuilder, aMFSharedSp); |
1493 | } |
1494 | |
1495 | TopTools_IndexedDataMapOfShapeListOfShape aFSMap; |
1496 | TopTools_ListIteratorOfListOfShape itLS(theLSolids); |
1497 | for (; itLS.More(); itLS.Next()) |
1498 | TopExp::MapShapesAndAncestors(itLS.Value(), TopAbs_FACE, TopAbs_SOLID, aFSMap); |
1499 | |
1500 | TopTools_ListOfShape anExtraFaces; |
1501 | TopTools_ListOfShape aLFArguments; |
1502 | itLS.Initialize(theLSolids); |
1503 | for (; itLS.More(); itLS.Next()) |
1504 | { |
1505 | const TopoDS_Shape& aSol = itLS.Value(); |
1506 | TopExp_Explorer anExpF(aSol, TopAbs_FACE); |
1507 | for (; anExpF.More(); anExpF.Next()) |
1508 | { |
1509 | const TopoDS_Shape& aF = anExpF.Current(); |
1510 | const TopTools_ListOfShape& aLSol = aFSMap.FindFromKey(aF); |
1511 | if (aLSol.Extent() != 2 || aMFSharedSp.Contains(aF)) |
1512 | aLFArguments.Append(aF); |
1513 | else |
1514 | anExtraFaces.Append(aF); |
1515 | } |
1516 | } |
1517 | |
1518 | if (anExtraFaces.IsEmpty()) |
1519 | return; |
1520 | |
1521 | // Rebuild the solids avoiding the extra faces |
1522 | BOPAlgo_BuilderSolid aBS; |
1523 | aBS.SetAvoidInternalShapes(Standard_True); |
1524 | aBS.SetShapes(aLFArguments); |
1525 | aBS.Perform(); |
1526 | if (aBS.HasErrors()) |
1527 | return; |
1528 | |
1529 | theLSolids = aBS.Areas(); |
1530 | theExtraFaces.Append(anExtraFaces); |
1531 | } |
1532 | |
1533 | //======================================================================= |
1534 | // function: FillSolidsHistory |
1535 | // purpose: Fills the history of solids modifications |
1536 | //======================================================================= |
1537 | void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn, |
1538 | TopTools_ListOfShape& theSolidsOut, |
1539 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
1540 | BOPAlgo_Builder& theBuilder, |
1541 | BRepTools_History& theSolidsHistory) |
1542 | { |
1543 | const Standard_Integer aNbS = theSolIn.Extent(); |
1544 | for (Standard_Integer i = 1; i <= aNbS; ++i) |
1545 | { |
1546 | const TopoDS_Shape& aSolIn = theSolIn(i); |
1547 | |
1548 | TopoDS_Shape aSolOut; |
1549 | FindSolid(aSolIn, theSolidsOut, theAdjFaces, theBuilder, aSolOut); |
1550 | |
1551 | if (aSolOut.IsNull()) |
1552 | { |
1553 | theSolidsHistory.Remove(aSolIn); |
1554 | continue; |
1555 | } |
1556 | |
1557 | // Check if the solid has really been modified |
1558 | BOPTools_Set aSTIn, aSTOut; |
1559 | aSTIn.Add(aSolIn, TopAbs_FACE); |
1560 | aSTOut.Add(aSolOut, TopAbs_FACE); |
1561 | if (aSTIn.IsEqual(aSTOut)) |
1562 | { |
1563 | // The solids are the same. Replace the resulting solid in the result list |
1564 | // with the initial solid. |
1565 | TopTools_ListIteratorOfListOfShape itLS(theSolidsOut); |
1566 | for (; itLS.More(); itLS.Next()) |
1567 | { |
1568 | if (itLS.Value().IsSame(aSolOut)) |
1569 | { |
1570 | theSolidsOut.InsertBefore(aSolIn, itLS); |
1571 | theSolidsOut.Remove(itLS); |
1572 | break; |
1573 | } |
1574 | } |
1575 | } |
1576 | else |
1577 | { |
1578 | theSolidsHistory.AddModified(aSolIn, aSolOut); |
1579 | } |
1580 | } |
1581 | } |
1582 | |
1583 | //======================================================================= |
1584 | // function: TakeModified |
1585 | // purpose: Stores the modified object into the list |
1586 | //======================================================================= |
1587 | void TakeModified(const TopoDS_Shape& theS, |
1588 | BOPAlgo_Builder& theBuilder, |
1589 | TopTools_ListOfShape& theList) |
1590 | { |
1591 | const TopTools_ListOfShape& aModified = theBuilder.Modified(theS); |
1592 | if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS)) |
1593 | theList.Append(theS); |
1594 | else |
1595 | { |
1596 | TopTools_ListIteratorOfListOfShape itM(aModified); |
1597 | for (; itM.More(); itM.Next()) |
1598 | theList.Append(itM.Value()); |
1599 | } |
1600 | } |
1601 | //======================================================================= |
1602 | // function: TakeModified |
1603 | // purpose: Stores the modified object into the map |
1604 | //======================================================================= |
1605 | void TakeModified(const TopoDS_Shape& theS, |
1606 | BOPAlgo_Builder& theBuilder, |
1607 | TopTools_MapOfShape& theMap) |
1608 | { |
1609 | const TopTools_ListOfShape& aModified = theBuilder.Modified(theS); |
1610 | if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS)) |
1611 | theMap.Add(theS); |
1612 | else |
1613 | { |
1614 | TopTools_ListIteratorOfListOfShape itM(aModified); |
1615 | for (; itM.More(); itM.Next()) |
1616 | theMap.Add(itM.Value()); |
1617 | } |
1618 | } |
1619 | |
1620 | //======================================================================= |
1621 | // function: FindSolid |
1622 | // purpose: Looks for the image of the solid in the list of resulting solids |
1623 | //======================================================================= |
1624 | void FindSolid(const TopoDS_Shape& theSolIn, |
1625 | const TopTools_ListOfShape& theSolidsRes, |
1626 | const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces, |
1627 | BOPAlgo_Builder& theBuilder, |
1628 | TopoDS_Shape& theSolOut) |
1629 | { |
1630 | Handle(IntTools_Context) aCtx = theBuilder.Context(); |
1631 | |
1632 | // Take the face in the IN solid, and find it in the OUT list |
1633 | TopExp_Explorer anExpF(theSolIn, TopAbs_FACE); |
1634 | for (; anExpF.More(); anExpF.Next()) |
1635 | { |
1636 | const TopoDS_Shape& aFS = anExpF.Current(); |
1637 | // Images of the face |
1638 | TopTools_MapOfShape aMFSIm; |
1639 | const TopTools_ListOfShape* pLFA = theAdjFaces.Seek(aFS); |
1640 | if (pLFA) |
1641 | { |
1642 | TopTools_ListIteratorOfListOfShape itLFA(*pLFA); |
1643 | for (; itLFA.More(); itLFA.Next()) |
1644 | TakeModified(itLFA.Value(), theBuilder, aMFSIm); |
1645 | } |
1646 | else |
1647 | { |
1648 | TakeModified(aFS, theBuilder, aMFSIm); |
1649 | } |
1650 | |
1651 | // Find any of these faces in the list of solids |
1652 | TopTools_ListIteratorOfListOfShape itLS(theSolidsRes); |
1653 | for (; itLS.More(); itLS.Next()) |
1654 | { |
1655 | const TopoDS_Shape& aSol = itLS.Value(); |
1656 | TopExp_Explorer anExpFOut(aSol, TopAbs_FACE); |
1657 | for (; anExpFOut.More(); anExpFOut.Next()) |
1658 | { |
1659 | const TopoDS_Shape& aF = anExpFOut.Current(); |
1660 | if (aMFSIm.Contains(aF)) |
1661 | { |
1662 | // check orientations |
1663 | if (!BOPTools_AlgoTools::IsSplitToReverse(aF, aFS, aCtx)) |
1664 | { |
1665 | theSolOut = aSol; |
1666 | return; |
1667 | } |
1668 | } |
1669 | } |
1670 | } |
1671 | } |
1672 | } |