2 // Created by: Eugeny MALTCHIKOV
3 // Copyright (c) 2016 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 // This is the implementation of the extension of the 3D offset algorithm
18 // to work in mode Complete and Join Type Intersection.
19 // Currently only the Planar cases are supported.
22 #include <BRepOffset_MakeOffset.hxx>
24 #include <Precision.hxx>
27 #include <BRepAlgo_AsDes.hxx>
28 #include <BRepAlgo_Image.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
33 #include <BRepLib.hxx>
34 #include <BRepTools.hxx>
36 #include <BRepAdaptor_Curve.hxx>
39 #include <TopExp_Explorer.hxx>
41 #include <TopTools_DataMapOfShapeInteger.hxx>
43 #include <BRepOffset_Tool.hxx>
45 #include <BRepClass3d_SolidClassifier.hxx>
47 #include <BOPDS_DS.hxx>
49 #include <BOPAlgo_PaveFiller.hxx>
50 #include <BOPAlgo_Builder.hxx>
51 #include <BOPAlgo_Section.hxx>
52 #include <BOPAlgo_MakerVolume.hxx>
53 #include <BOPAlgo_BuilderFace.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_DataMapOfShapeShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <TopTools_MapOfOrientedShape.hxx>
60 #include <BOPTools_AlgoTools3D.hxx>
61 #include <BOPTools_AlgoTools.hxx>
62 #include <BOPTools_AlgoTools2D.hxx>
63 #include <BOPTools_Set.hxx>
65 #include <IntTools_Context.hxx>
66 #include <IntTools_ShrunkRange.hxx>
69 #include <BRepAlgoAPI_Check.hxx>
72 typedef NCollection_DataMap
73 <TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeMapOfShape;
74 typedef NCollection_DataMap
75 <TopoDS_Shape, TopTools_IndexedMapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeIndexedMapOfShape;
78 void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
79 const Handle(BRepAlgo_AsDes)& theAsDes,
80 TopTools_DataMapOfShapeListOfShape& theOEImages,
81 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
82 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
83 Handle(IntTools_Context)& theCtx,
84 TopTools_MapOfShape& theNewEdges,
85 TopTools_DataMapOfShapeShape& theETrimEInf);
88 Standard_Boolean GetEdges(const TopoDS_Face& theFace,
89 const Handle(BRepAlgo_AsDes)& theAsDes,
90 const TopTools_DataMapOfShapeListOfShape& theEImages,
91 const TopTools_MapOfShape& theLastInvEdges,
92 const TopTools_IndexedMapOfShape& theInvEdges,
93 Handle(IntTools_Context)& theCtx,
94 const TopTools_MapOfShape& theModifiedEdges,
95 TopoDS_Shape& theEdges,
96 TopTools_IndexedMapOfShape& theInv);
99 void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
100 const TopoDS_Shape& theEdges,
101 TopTools_ListOfShape& theLFImages);
104 void BuildSplitsOfFace(const TopoDS_Face& theFace,
105 const TopoDS_Shape& theEdges,
106 TopTools_DataMapOfShapeShape& theOrigins,
107 TopTools_ListOfShape& theLFImages);
109 //! Auxiliary structure to contain intersection information
110 struct BRepOffset_MakeOffset_InterResults
112 TopTools_DataMapOfShapeListOfShape SSInterfs; //!< Intersection information, used to add pair for intersection
113 NCollection_DataMap <TopoDS_Shape,
114 BRepOffset_DataMapOfShapeMapOfShape,
115 TopTools_ShapeMapHasher> InterPairs; //!< All possible intersection pairs, used to avoid
116 //! some of the intersection
120 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
121 const TopTools_MapOfShape& theModifiedEdges,
122 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
123 const BRepOffset_Analyse* theAnalyse,
124 Handle(BRepAlgo_AsDes)& theAsDes,
125 TopTools_DataMapOfShapeShape& theFacesOrigins,
126 TopTools_DataMapOfShapeListOfShape& theOEImages,
127 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
128 TopTools_MapOfShape& theLastInvEdges,
129 TopTools_IndexedMapOfShape& theEdgesToAvoid,
130 TopTools_IndexedMapOfShape& theInvEdges,
131 TopTools_IndexedMapOfShape& theValidEdges,
132 TopTools_MapOfShape& theInvertedEdges,
133 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
134 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
135 TopTools_DataMapOfShapeShape& theArtInvFaces,
136 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
137 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
138 TopoDS_Shape& theSolids,
139 BRepOffset_MakeOffset_InterResults& theIntRes);
142 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
143 const TopTools_MapOfShape& theModifiedEdges,
144 const BRepOffset_Analyse* theAnalyse,
145 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
146 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
147 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
148 TopTools_DataMapOfShapeShape& theFacesOrigins,
149 TopTools_DataMapOfShapeListOfShape& theOEImages,
150 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
151 TopTools_MapOfShape& theLastInvEdges,
152 TopTools_IndexedMapOfShape& theEdgesToAvoid,
153 TopTools_MapOfShape& theVertsToAvoid,
154 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
155 TopTools_IndexedMapOfShape& theValidEdges,
156 TopTools_DataMapOfShapeShape& theETrimEInf,
157 Handle(BRepAlgo_AsDes)& theAsDes);
160 Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
161 const TopTools_ListOfShape& theLFImages,
162 const TopoDS_Shape& theCE,
163 const TopTools_IndexedMapOfShape& theMapEInv,
164 const TopTools_DataMapOfShapeListOfShape& theOEImages,
165 TopTools_MapOfShape& theMENInv,
166 Handle(BRepAlgo_AsDes)& theAsDes);
169 void FindInvalidEdges(const TopoDS_Face& theF,
170 const TopTools_ListOfShape& theLFImages,
171 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
172 const TopTools_DataMapOfShapeShape& theFacesOrigins,
173 const BRepOffset_Analyse* theAnalyse,
174 const TopTools_DataMapOfShapeListOfShape& theOEImages,
175 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
176 TopTools_IndexedMapOfShape& theInvEdges,
177 TopTools_IndexedMapOfShape& theValidEdges,
178 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
179 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
180 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
181 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
182 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
183 TopTools_MapOfShape& theMEInverted,
184 TopTools_MapOfShape& theEdgesInvalidByVertex,
185 TopTools_MapOfShape& theEdgesValidByVertex);
188 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
189 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
190 const TopTools_DataMapOfShapeShape& theFacesOrigins,
191 const BRepOffset_Analyse* theAnalyse,
192 const TopTools_IndexedMapOfShape& theInvEdges,
193 const TopTools_IndexedMapOfShape& theValidEdges,
194 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
195 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
196 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges);
199 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
200 const TopTools_IndexedMapOfShape& theInvEdges,
201 const TopTools_IndexedMapOfShape& theValidEdges,
202 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
203 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
204 const TopTools_MapOfShape& theLENeutral,
205 const TopTools_MapOfShape& theMEInverted,
206 const TopTools_MapOfShape& theEdgesInvalidByVertex,
207 const TopTools_MapOfShape& theEdgesValidByVertex,
208 const TopTools_MapOfShape& theMFHoles,
209 TopTools_IndexedMapOfShape& theMFInvInHole,
210 TopTools_ListOfShape& theInvFaces,
211 TopTools_ListOfShape& theInvertedFaces);
214 void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
215 const TopoDS_Face& theFOffset,
216 const TopTools_ListOfShape& theLFImages,
217 const TopTools_MapOfShape& theInvertedEdges,
218 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
219 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
220 TopTools_MapOfShape& theMFHoles,
221 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
222 Handle(IntTools_Context)& theContext);
225 gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
226 const Standard_Integer theNbP);
229 Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
230 const TopoDS_Face& theFOr,
231 const TopTools_DataMapOfShapeListOfShape& theOEImages,
232 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
233 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
234 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
235 const TopTools_IndexedMapOfShape& theMEdges,
236 TopTools_MapOfShape& theMEInverted);
239 Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
240 const TopTools_ListOfShape& theLCBF,
241 const TopTools_MapOfShape& theMEInverted,
242 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
243 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
244 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll);
247 void GetVerticesOnEdges(const TopoDS_Shape& theCB,
248 const TopTools_MapOfShape& theEdges,
249 TopTools_MapOfShape& theVerticesOnEdges,
250 TopTools_MapOfShape& theAllVertices);
253 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
254 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
255 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
256 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
257 TopTools_IndexedMapOfShape& theMERemoved);
260 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
261 const TopTools_DataMapOfShapeShape& theArtInvFaces,
262 const TopTools_MapOfShape& theMEInverted,
263 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
264 TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
267 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
268 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
269 const TopTools_DataMapOfShapeShape& theArtInvFaces,
270 const TopTools_IndexedMapOfShape& theInvEdges,
271 const TopTools_MapOfShape& theInvertedEdges,
272 const TopTools_ListOfShape& theInvertedFaces,
273 const TopTools_IndexedMapOfShape& theMFToCheckInt,
274 const TopTools_IndexedMapOfShape& theMFInvInHole,
275 const TopoDS_Shape& theFHoles,
276 BRepOffset_MakeOffset_InterResults& theIntRes,
277 TopTools_IndexedMapOfShape& theMERemoved,
278 TopTools_IndexedMapOfShape& theMEInside,
279 TopoDS_Shape& theSolids);
282 void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
283 const TopTools_IndexedMapOfShape& theInvEdges,
284 const TopTools_DataMapOfShapeShape& theDMFOr,
285 BOPAlgo_Builder& theBuilder,
286 TopTools_DataMapOfShapeListOfShape& theSSInterfs);
289 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
290 const TopTools_DataMapOfShapeShape& theDMFImF,
291 const TopTools_IndexedMapOfShape& theMFInv,
292 const TopTools_IndexedMapOfShape& theInvEdges,
293 const TopTools_MapOfShape& theInvertedEdges,
294 TopTools_MapOfShape& theMFToRem);
297 void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
298 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
299 BOPAlgo_Builder& theGF,
300 TopTools_IndexedMapOfShape& theMERemoved);
303 void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
304 const TopTools_DataMapOfShapeShape& theArtInvFaces,
305 const TopTools_IndexedMapOfShape& theInvEdges,
306 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
307 BOPAlgo_Builder& theGF,
308 TopTools_IndexedMapOfShape& theMERemoved);
311 void FilterEdgesImages(const TopoDS_Shape& theS,
312 TopTools_DataMapOfShapeListOfShape& theOEImages,
313 TopTools_DataMapOfShapeListOfShape& theOEOrigins);
316 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
317 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
318 const TopTools_IndexedMapOfShape& theInvEdges,
319 const TopTools_IndexedMapOfShape& theMERemoved,
320 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
321 TopTools_DataMapOfShapeShape& theArtInvFaces);
324 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
325 const TopTools_DataMapOfShapeShape& theArtInvFaces,
326 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
327 const TopTools_IndexedMapOfShape& theMERemoved,
328 TopTools_IndexedMapOfShape& theInvEdges);
331 void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
332 const TopTools_DataMapOfShapeShape& theArtInvFaces,
333 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
334 const TopTools_IndexedMapOfShape& theValidEdges,
335 TopTools_IndexedMapOfShape& theInvEdges);
338 void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
339 const TopTools_IndexedMapOfShape& theInvEdges,
340 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
341 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
342 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
343 TopTools_MapOfShape& theFSelfRebAvoid);
346 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
347 const TopTools_MapOfShape& theFSelfRebAvoid,
348 const TopoDS_Shape& theSolids,
349 const BRepOffset_MakeOffset_InterResults& theIntRes,
350 const BRepOffset_Analyse* theAnalyse,
351 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
352 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
353 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
354 TopTools_DataMapOfShapeShape& theFacesOrigins,
355 TopTools_DataMapOfShapeListOfShape& theOEImages,
356 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
357 TopTools_MapOfShape& theLastInvEdges,
358 TopTools_IndexedMapOfShape& theEdgesToAvoid,
359 TopTools_IndexedMapOfShape& theInvEdges,
360 TopTools_IndexedMapOfShape& theValidEdges,
361 const TopTools_MapOfShape& theInvertedEdges,
362 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
363 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
364 const TopTools_DataMapOfShapeShape& theArtInvFaces,
365 TopTools_MapOfShape& theVertsToAvoid,
366 TopTools_DataMapOfShapeShape& theETrimEInf,
367 Handle(BRepAlgo_AsDes)& theAsDes);
370 void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
371 const TopTools_MapOfShape& theFSelfRebAvoid,
372 const TopoDS_Shape& theSolids,
373 const BRepOffset_MakeOffset_InterResults& theIntRes,
374 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
375 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
376 TopTools_DataMapOfShapeListOfShape& theOEImages,
377 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
378 TopTools_IndexedMapOfShape& theInvEdges,
379 TopTools_IndexedMapOfShape& theValidEdges,
380 const TopTools_MapOfShape& theInvertedEdges,
381 TopTools_IndexedMapOfShape& theEdgesToAvoid,
382 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
383 const TopTools_DataMapOfShapeShape& theArtInvFaces,
384 TopTools_MapOfShape& theVertsToAvoid,
385 TopTools_DataMapOfShapeShape& theETrimEInf,
386 TopTools_MapOfShape& theModifiedEdges,
387 Handle(BRepAlgo_AsDes)& theAsDes);
390 void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
391 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
392 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
393 const TopTools_DataMapOfShapeShape& theArtInvFaces,
394 const Standard_Boolean bLookVertToAvoid,
395 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
396 TopTools_DataMapOfShapeListOfShape& theMDone,
397 TopTools_DataMapOfShapeListOfShape& theDMSF,
398 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
399 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
400 TopTools_DataMapOfShapeShape& theETrimEInf,
401 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv);
404 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
405 const TopTools_IndexedMapOfShape& theInvEdges,
406 const TopTools_IndexedMapOfShape& theValidEdges,
407 const TopTools_MapOfShape& theInvertedEdges,
408 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
409 const TopTools_DataMapOfShapeListOfShape& theOEImages,
410 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
411 TopTools_MapOfShape& theMVRInv);
414 void FindFacesForIntersection(const TopoDS_Shape& theFInv,
415 const TopTools_IndexedMapOfShape& theME,
416 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
417 const TopTools_DataMapOfShapeListOfShape& theDMSF,
418 const TopTools_MapOfShape& theMVInvAll,
419 const TopTools_DataMapOfShapeShape& theArtInvFaces,
420 const Standard_Boolean theArtCase,
421 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
422 TopTools_IndexedMapOfShape& theMFAvoid,
423 TopTools_IndexedMapOfShape& theMFInt,
424 TopTools_IndexedMapOfShape& theMFIntExt,
425 TopTools_ListOfShape& theLFImInt);
428 void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
429 const TopTools_IndexedMapOfShape& theInvEdges,
430 const TopTools_IndexedMapOfShape& theValidEdges,
431 const TopTools_IndexedMapOfShape& theME,
432 const TopTools_DataMapOfShapeShape& theETrimEInf,
433 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
434 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
435 const TopTools_MapOfShape& theAllInvs,
436 const Standard_Boolean theForceUse,
437 TopTools_IndexedMapOfShape& theMECV,
438 TopTools_MapOfShape& theMECheckExt,
439 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
440 TopTools_ListOfShape& theLFEi,
441 TopTools_ListOfShape& theLFEj,
442 TopTools_IndexedMapOfShape& theMEToInt);
445 void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
446 const TopoDS_Shape& theFi,
447 const TopoDS_Shape& theFj,
448 const TopTools_ListOfShape& theLFInv,
449 const TopTools_ListOfShape& theLFImi,
450 const TopTools_ListOfShape& theLFImj,
451 const TopTools_ListOfShape& theLFEi,
452 const TopTools_ListOfShape& theLFEj,
453 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
454 TopTools_IndexedMapOfShape& theMEToInt);
457 void IntersectFaces(const TopoDS_Shape& theFInv,
458 const TopoDS_Shape& theFi,
459 const TopoDS_Shape& theFj,
460 const TopTools_ListOfShape& theLFInv,
461 const TopTools_ListOfShape& theLFImi,
462 const TopTools_ListOfShape& theLFImj,
463 TopTools_ListOfShape& theLFEi,
464 TopTools_ListOfShape& theLFEj,
465 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
466 TopTools_IndexedMapOfShape& theMECV,
467 TopTools_IndexedMapOfShape& theMEToInt);
470 void FindOrigins(const TopTools_ListOfShape& theLFIm1,
471 const TopTools_ListOfShape& theLFIm2,
472 const TopTools_IndexedMapOfShape& theME,
473 const TopTools_DataMapOfShapeListOfShape& theOrigins,
474 TopTools_ListOfShape& theLEOr);
477 void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
478 const TopTools_IndexedMapOfShape& theMFInt,
479 const TopTools_IndexedMapOfShape& theMEInt,
480 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
481 const TopTools_IndexedMapOfShape& theMSInv,
482 const TopTools_IndexedMapOfShape& theMVE,
483 const TopTools_MapOfShape& theVertsToAvoid,
484 const TopTools_MapOfShape& theNewVertsToAvoid,
485 const TopTools_MapOfShape& theMECheckExt,
486 TopTools_MapOfShape& theMVBounds,
487 TopTools_DataMapOfShapeListOfShape& theEImages);
490 void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
491 const TopTools_MapOfShape& theMVBounds,
492 BOPAlgo_Builder& theGF,
493 TopTools_MapOfShape& theMEInv);
496 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
497 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
498 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
499 const TopTools_MapOfShape& theMVBounds,
500 const TopoDS_Shape& theSolids,
501 const TopTools_IndexedMapOfShape& theInvEdges,
502 const TopTools_MapOfShape& theInvertedEdges,
503 const TopTools_MapOfShape& theMEInvOnArt,
504 TopTools_MapOfShape& theMECheckExt,
505 TopTools_IndexedMapOfShape& theEdgesToAvoid,
506 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
507 TopTools_DataMapOfShapeListOfShape& theOEImages,
508 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
509 TopTools_MapOfShape& theVertsToAvoid,
510 TopTools_DataMapOfShapeShape& theETrimEInf,
511 TopTools_DataMapOfShapeListOfShape& theEImages,
512 TopTools_DataMapOfShapeListOfShape& theEETrim,
513 TopTools_MapOfShape& theModifiedEdges,
514 Handle(BRepAlgo_AsDes)& theAsDes);
517 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
518 const TopTools_DataMapOfShapeListOfShape& theEETrim,
519 const TopTools_MapOfShape& theMVBounds,
520 TopTools_MapOfShape& theMECheckExt,
521 TopTools_DataMapOfShapeListOfShape& theEImages,
522 TopTools_MapOfShape& theMEB,
523 TopTools_MapOfShape& theMVOld,
524 TopTools_MapOfShape& theMENew,
525 TopTools_DataMapOfShapeListOfShape& theDMEOr,
526 TopTools_DataMapOfShapeListOfShape& theMELF);
529 void IntersectEdges(const TopTools_ListOfShape& theLA,
530 const TopTools_ListOfShape& theLE,
531 const TopTools_MapOfShape& theMVBounds,
532 const TopTools_MapOfShape& theVertsToAvoid,
533 TopTools_MapOfShape& theMENew,
534 TopTools_MapOfShape& theMECheckExt,
535 TopTools_DataMapOfShapeListOfShape& theEImages,
536 TopTools_MapOfShape& theModifiedEdges,
537 TopTools_DataMapOfShapeListOfShape& theDMEOr,
538 TopTools_DataMapOfShapeListOfShape& theMELF,
539 TopoDS_Shape& theSplits);
542 void GetBounds(const TopTools_ListOfShape& theLFaces,
543 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
544 const TopTools_MapOfShape& theMEB,
545 TopoDS_Shape& theBounds);
548 void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
549 const TopTools_DataMapOfShapeListOfShape& theOEImages,
550 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
551 const TopTools_MapOfShape& theMEB,
552 TopTools_ListOfShape& theLABounds,
553 TopTools_ListOfShape& theLAValid,
554 TopoDS_Shape& theBounds,
555 Handle(BRepAlgo_AsDes)& theAsDes);
558 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
559 const TopoDS_Shape& theBounds,
560 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
561 const TopoDS_Shape& theSolids,
562 const TopTools_IndexedMapOfShape& theInvEdges,
563 const TopTools_MapOfShape& theMVOld,
564 const TopTools_MapOfShape& theMENew,
565 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
566 const TopTools_DataMapOfShapeListOfShape& theMELF,
567 const TopTools_DataMapOfShapeListOfShape& theEImages,
568 const TopTools_MapOfShape& theMECheckExt,
569 const TopTools_MapOfShape& theMEInvOnArt,
570 Handle(IntTools_Context)& theCtx,
571 TopTools_MapOfShape& theVertsToAvoid,
572 TopTools_MapOfShape& theMEInv);
575 void FilterSplits(const TopTools_ListOfShape& theLE,
576 const TopTools_MapOfShape& theMEFilter,
577 const Standard_Boolean theIsInv,
578 TopTools_DataMapOfShapeListOfShape& theEImages,
579 TopoDS_Shape& theSplits);
582 void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
583 const TopTools_DataMapOfShapeListOfShape& theMELF,
584 const TopTools_DataMapOfShapeListOfShape& theEImages,
585 const TopTools_IndexedMapOfShape& theInvEdges,
586 const TopTools_MapOfShape& theInvertedEdges,
587 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
588 TopTools_DataMapOfShapeListOfShape& theOEImages,
589 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
590 TopTools_DataMapOfShapeShape& theETrimEInf,
591 TopTools_DataMapOfShapeListOfShape& theEETrim,
592 TopTools_MapOfShape& theModifiedEdges,
593 Handle(BRepAlgo_AsDes)& theAsDes);
596 void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
599 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
600 const TopTools_DataMapOfShapeListOfShape& theEImages,
601 BRepAlgo_Image& theImage);
604 void UpdateOrigins(const TopTools_ListOfShape& theLA,
605 TopTools_DataMapOfShapeListOfShape& theOrigins,
606 BOPAlgo_Builder& theGF);
609 void UpdateImages(const TopTools_ListOfShape& theLA,
610 TopTools_DataMapOfShapeListOfShape& theImages,
611 BOPAlgo_Builder& theGF,
612 TopTools_MapOfShape& theModified);
615 void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
616 TopTools_DataMapOfShapeShape& theETrimEInf,
617 BOPAlgo_Builder& theGF);
620 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
621 const Handle(IntTools_Context)& theCtx);
624 void FindCommonParts(const TopTools_ListOfShape& theLS1,
625 const TopTools_ListOfShape& theLS2,
626 TopTools_ListOfShape& theLSC,
627 const TopAbs_ShapeEnum theType = TopAbs_EDGE);
630 Standard_Integer NbPoints(const TopoDS_Edge& theE);
633 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
634 const TopoDS_Shape& theSWhere,
635 const BRepOffset_Analyse* theAnalyse,
636 TopoDS_Shape& theRes);
639 void AppendToList(TopTools_ListOfShape& theL,
640 const TopoDS_Shape& theS);
642 template <class ContainerType, class FenceMapType>
643 static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
644 const TopTools_DataMapOfShapeListOfShape& theImages,
645 ContainerType& theMapOut,
646 FenceMapType* theMFence);
648 template <class ContainerType>
649 static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
650 const TopTools_DataMapOfShapeListOfShape& theImages,
651 ContainerType& theMapOut)
653 TopTools_MapOfShape* aDummy = NULL;
654 return TakeModified (theS, theImages, theMapOut, aDummy);
657 //=======================================================================
658 //function : BuildSplitsOfTrimmedFaces
659 //purpose : Building splits of already trimmed faces
660 //=======================================================================
661 void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF,
662 Handle(BRepAlgo_AsDes)& theAsDes,
663 BRepAlgo_Image& theImage)
665 TopTools_DataMapOfShapeListOfShape anEImages, anEOrigins;
666 TopTools_IndexedDataMapOfShapeListOfShape aDMFFIm;
667 TopTools_IndexedMapOfShape anEmptyIM;
668 TopTools_DataMapOfShapeListOfShape anEmptyDMSLS;
669 TopTools_DataMapOfShapeShape anEmptyDMSS;
670 TopTools_MapOfShape aNewEdges, anEmptyM;
672 // firstly it is necessary to fuse all the edges
673 Handle(IntTools_Context) aCtx = new IntTools_Context();
675 IntersectTrimmedEdges(theLF, theAsDes, anEImages, anEOrigins, anEmptyDMSLS, aCtx, aNewEdges, anEmptyDMSS);
677 TopTools_ListIteratorOfListOfShape aItLF(theLF);
678 for (; aItLF.More(); aItLF.Next()) {
679 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
682 TopTools_ListOfShape aLFImages;
684 Standard_Boolean bFound = GetEdges(aF, theAsDes, anEImages, anEmptyM,
685 anEmptyIM, aCtx, aNewEdges, aCE, anEmptyIM);
686 // split the face by the edges
688 if (!theImage.HasImage(aF)) {
689 aLFImages.Append(aF);
690 aDMFFIm.Add(aF, aLFImages);
695 BuildSplitsOfTrimmedFace(aF, aCE, aLFImages);
696 aDMFFIm.Add(aF, aLFImages);
698 // Fill history for faces and edges
699 FillHistory(aDMFFIm, anEImages, theImage);
702 //=======================================================================
703 //function : BuildSplitsOfExtendedFaces
704 //purpose : Building splits of not-trimmed offset faces.
705 // For the cases in which invalidity will be found,
706 // these invalidities will be rebuilt.
707 //=======================================================================
708 void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
709 const BRepOffset_Analyse& theAnalyse,
710 Handle(BRepAlgo_AsDes)& theAsDes,
711 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
712 TopTools_DataMapOfShapeShape& theFacesOrigins,
713 TopTools_DataMapOfShapeShape& theETrimEInf,
714 BRepAlgo_Image& theImage)
716 Handle(IntTools_Context) aCtx = new IntTools_Context();
717 // images and origins for offset edges
718 TopTools_DataMapOfShapeListOfShape anOEImages, anOEOrigins;
719 TopTools_MapOfShape aNewEdges;
720 // fusing all trimmed offset edges to avoid self-intersections in the splits
721 IntersectTrimmedEdges(theLF, theAsDes, anOEImages, anOEOrigins,
722 theEdgesOrigins, aCtx, aNewEdges, theETrimEInf);
724 // valid/invalid edges
725 TopTools_IndexedMapOfShape anInvEdges, aValidEdges, anEdgesToAvoid;
727 TopTools_MapOfShape anInvertedEdges;
729 TopTools_IndexedDataMapOfShapeListOfShape aFImages;
730 // found invalid faces
731 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
732 // artificially invalid faces - it will be empty here,
733 // but may be filled on the following rebuilding steps
734 TopTools_DataMapOfShapeShape anArtInvFaces;
735 // shapes connections for using in rebuilding
736 BRepOffset_MakeOffset_InterResults aIntRes;
737 // edges to avoid on second steps
738 TopTools_MapOfShape aLastInvEdges;
739 // keep information of already invalid faces to avoid
740 // infinite rebuilding of the same invalid face
741 TopTools_DataMapOfShapeInteger anAlreadyInvFaces;
742 // images of the hole faces of the original faces
743 TopTools_DataMapOfShapeListOfShape aDMFNewHoles;
744 // solid build from the new splits
745 TopoDS_Shape aSolids;
746 // now we can split the faces
747 BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, &theAnalyse, theAsDes, theFacesOrigins,
748 anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges,
749 anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages,
750 aDMFNewHoles, aSolids, aIntRes);
752 // Find faces to rebuild
753 if (anInvFaces.Extent()) {
754 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
755 TopTools_MapOfShape aFSelfRebAvoid;
756 FindFacesToRebuild(aFImages, anInvEdges, anInvFaces, aIntRes.SSInterfs, aFToRebuild, aFSelfRebAvoid);
758 if (aFToRebuild.Extent()) {
760 TopTools_MapOfShape aVAEmpty;
761 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aIntRes, &theAnalyse, aFImages, aDMFNewHoles,
762 theEdgesOrigins, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges,
763 anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces,
764 anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes);
768 // Fill possible gaps in the splits of offset faces to increase possibility of
769 // creating closed volume from these splits
772 // Fill history for faces and edges
773 FillHistory(aFImages, anOEImages, theImage);
776 //=======================================================================
777 //function : BuildSplitsOfInvFaces
778 //purpose : Rebuilding splits of faces with new intersection edges
779 //=======================================================================
780 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
781 const TopTools_MapOfShape& theModifiedEdges,
782 const BRepOffset_Analyse* theAnalyse,
783 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
784 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
785 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
786 TopTools_DataMapOfShapeShape& theFacesOrigins,
787 TopTools_DataMapOfShapeListOfShape& theOEImages,
788 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
789 TopTools_MapOfShape& theLastInvEdges,
790 TopTools_IndexedMapOfShape& theEdgesToAvoid,
791 TopTools_MapOfShape& theVertsToAvoid,
792 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
793 TopTools_IndexedMapOfShape& theValidEdges,
794 TopTools_DataMapOfShapeShape& theETrimEInf,
795 Handle(BRepAlgo_AsDes)& theAsDes)
797 Standard_Integer aNb = theFToRebuild.Extent();
802 TopTools_ListOfShape aLF;
803 aNb = theFImages.Extent();
804 for (Standard_Integer i = 1; i <= aNb; ++i) {
805 const TopoDS_Shape& aF = theFImages.FindKey(i);
810 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
811 // artificially invalid faces
812 TopTools_DataMapOfShapeShape anArtInvFaces;
814 TopTools_IndexedMapOfShape anInvEdges;
816 TopTools_MapOfShape anInvertedEdges;
817 // shapes connection for using in rebuilding process
818 BRepOffset_MakeOffset_InterResults aIntRes;
820 TopoDS_Shape aSolids;
822 BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAnalyse, theAsDes, theFacesOrigins,
823 theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges,
824 anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages,
825 theDMFNewHoles, aSolids, aIntRes);
827 if (anInvFaces.Extent()) {
828 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
829 TopTools_MapOfShape aFSelfRebAvoid;
830 FindFacesToRebuild(theFImages, anInvEdges, anInvFaces, aIntRes.SSInterfs, aFToRebuild, aFSelfRebAvoid);
832 if (aFToRebuild.Extent()) {
833 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aIntRes, theAnalyse, theFImages, theDMFNewHoles,
834 theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
835 theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces,
836 anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes);
841 //=======================================================================
842 //function : BuildSplitsOfFaces
843 //purpose : Building the splits of offset faces and
844 // looking for the invalid splits
845 //=======================================================================
846 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
847 const TopTools_MapOfShape& theModifiedEdges,
848 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
849 const BRepOffset_Analyse* theAnalyse,
850 Handle(BRepAlgo_AsDes)& theAsDes,
851 TopTools_DataMapOfShapeShape& theFacesOrigins,
852 TopTools_DataMapOfShapeListOfShape& theOEImages,
853 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
854 TopTools_MapOfShape& theLastInvEdges,
855 TopTools_IndexedMapOfShape& theEdgesToAvoid,
856 TopTools_IndexedMapOfShape& theInvEdges,
857 TopTools_IndexedMapOfShape& theValidEdges,
858 TopTools_MapOfShape& theInvertedEdges,
859 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
860 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
861 TopTools_DataMapOfShapeShape& theArtInvFaces,
862 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
863 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
864 TopoDS_Shape& theSolids,
865 BRepOffset_MakeOffset_InterResults& theIntRes)
867 if (theLF.IsEmpty()) {
872 Standard_Integer i, aNb;
875 TopTools_ListOfShape aLFDone;
876 // extended face - map of neutral edges, i.e. in one split - valid and in other - invalid
877 BRepOffset_DataMapOfShapeMapOfShape aDMFMNE;
878 // map of valid edges for each face
879 BRepOffset_DataMapOfShapeMapOfShape aDMFMVE;
880 // map of invalid edges for each face
881 BRepOffset_DataMapOfShapeIndexedMapOfShape aDMFMIE;
882 // map of valid inverted edges for the face
883 BRepOffset_DataMapOfShapeMapOfShape aDMFMVIE;
884 // map of splits to check for internals
885 TopTools_IndexedMapOfShape aMFToCheckInt;
886 // map of edges created from vertex and marked as invalid
887 TopTools_MapOfShape aMEdgeInvalidByVertex;
888 // map of edges created from vertex and marked as valid
889 TopTools_MapOfShape aMEdgeValidByVertex;
890 // connection map from old edges to new ones
891 TopTools_DataMapOfShapeListOfShape aDMEOrLEIm;
893 Handle(IntTools_Context) aCtx = new IntTools_Context;
894 // build splits of faces
895 TopTools_ListIteratorOfListOfShape aItLF(theLF);
896 for (; aItLF.More(); aItLF.Next()) {
897 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
899 TopTools_ListOfShape* pLFIm = theFImages.ChangeSeek(aF);
900 if (pLFIm && pLFIm->IsEmpty()) {
903 // get edges by which the face should be split
905 TopTools_IndexedMapOfShape aMapEInv;
906 Standard_Boolean bFound =
907 GetEdges(aF, theAsDes, theOEImages, theLastInvEdges,
908 theEdgesToAvoid, aCtx, theModifiedEdges, aCE, aMapEInv);
914 // check the found edges on self-intersection
915 BRepAlgoAPI_Check aChecker(aCE);
916 if (!aChecker.IsValid())
918 std::cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n";
922 TopTools_ListOfShape aLFImages;
923 BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages);
925 if (aMapEInv.Extent()) {
926 // check if all possible faces are built
927 TopTools_MapOfShape aMENInv;
928 Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
929 CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes);
931 // try to build splits using invalid edges
932 TopoDS_Compound aCE1;
933 aBB.MakeCompound(aCE1);
935 for (i = 1; i <= aMapEInv.Extent(); ++i) {
936 aBB.Add(aCE1, aMapEInv(i));
939 TopTools_ListOfShape aLFImages1;
940 BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1);
942 // check if the rebuilding has added some new faces to the splits
943 for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();)
945 Standard_Boolean bAllInv = Standard_True;
946 const TopoDS_Shape& aFIm = aItLFIm.Value();
947 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
948 for (; aExpE.More(); aExpE.Next()) {
949 const TopoDS_Shape& aE = aExpE.Current();
950 if (!aMapEInv.Contains(aE)) {
951 bAllInv = Standard_False;
952 if (!aMENInv.Contains(aE)) {
960 aMFToCheckInt.Add(aFIm);
962 aLFImages1.Remove(aItLFIm);
969 if (bArtificialCase) {
970 if (aLFImages.Extent() == aLFImages1.Extent()) {
971 bArtificialCase = Standard_False;
974 aLFImages = aLFImages1;
978 if (bArtificialCase) {
979 TopTools_IndexedMapOfShape aMEInv;
980 // make the face invalid
981 theArtInvFaces.Bind(aF, aCE);
984 TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages);
985 for (; aItLFIm.More(); aItLFIm.Next()) {
986 const TopoDS_Shape& aFIm = aItLFIm.Value();
987 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
988 for (; aExpE.More(); aExpE.Next()) {
989 const TopoDS_Shape& aE = aExpE.Current();
990 if (aMapEInv.Contains(aE)) {
995 theValidEdges.Add(aE);
1000 aDMFMIE.Bind(aF, aMEInv);
1007 // find invalid edges
1008 FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theAnalyse, theOEImages,
1009 theOEOrigins, theInvEdges, theValidEdges, aDMFMVE, aDMFMNE, aDMFMIE,
1010 aDMFMVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex);
1012 // save the new splits
1014 pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape()));
1019 pLFIm->Append(aLFImages);
1024 if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty() && aDMFMIE.IsEmpty()) {
1028 // Additional step to find invalid edges by checking unclassified edges
1029 // in the splits of SD faces
1030 FindInvalidEdges (aLFDone, theFImages, theFacesOrigins, theAnalyse,
1031 theInvEdges, theValidEdges, aDMFMIE, aDMFMVE, aDMFMNE);
1034 // show invalid edges
1035 TopoDS_Compound aCEInv1;
1036 BRep_Builder().MakeCompound(aCEInv1);
1037 Standard_Integer aNbEInv = theInvEdges.Extent();
1038 for (i = 1; i <= aNbEInv; ++i) {
1039 const TopoDS_Shape& aE = theInvEdges(i);
1040 BRep_Builder().Add(aCEInv1, aE);
1043 TopoDS_Compound aCEVal1;
1044 BRep_Builder().MakeCompound(aCEVal1);
1045 aNbEInv = theValidEdges.Extent();
1046 for (i = 1; i <= aNbEInv; ++i) {
1047 const TopoDS_Shape& aE = theValidEdges(i);
1048 BRep_Builder().Add(aCEVal1, aE);
1050 // show inverted edges
1051 TopoDS_Compound aCEInverted;
1052 BRep_Builder().MakeCompound(aCEInverted);
1053 TopTools_MapIteratorOfMapOfShape aItM(theInvertedEdges);
1054 for (; aItM.More(); aItM.Next()) {
1055 BRep_Builder().Add(aCEInverted, aItM.Value());
1060 // Show all obtained splits of faces
1061 TopoDS_Compound aCFIm1;
1062 BRep_Builder().MakeCompound(aCFIm1);
1065 // Build Edge-Face connectivity map to find faces which removal
1066 // may potentially lead to creation of the holes in the faces
1067 // preventing from obtaining closed volume in the result
1068 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
1069 const Standard_Integer aNbF = theFImages.Extent();
1070 for (i = 1; i <= aNbF; ++i)
1072 TopTools_ListIteratorOfListOfShape itLFIm(theFImages(i));
1073 for (; itLFIm.More(); itLFIm.Next())
1075 TopExp::MapShapesAndAncestors(itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
1077 BRep_Builder().Add(aCFIm1, itLFIm.Value());
1082 TopTools_MapOfShape anEmptyMap;
1083 // invalid faces inside the holes
1084 TopTools_IndexedMapOfShape aMFInvInHole;
1086 TopoDS_Compound aFHoles;
1087 aBB.MakeCompound(aFHoles);
1088 // Find the faces containing only the inverted edges and the invalid ones
1089 TopTools_ListOfShape anInvertedFaces;
1090 // find invalid faces
1091 // considering faces containing only invalid edges as invalid
1092 aItLF.Initialize(aLFDone);
1093 for (; aItLF.More(); aItLF.Next()) {
1094 const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1095 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
1097 TopTools_ListOfShape aLFInv;
1098 Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF);
1099 if (bArtificialCase) {
1105 const TopTools_MapOfShape* pMNE = aDMFMNE.ChangeSeek(aF);
1109 // find faces inside holes wires
1110 TopTools_MapOfShape aMFHoles;
1111 const TopoDS_Face& aFOr = TopoDS::Face(theFacesOrigins.Find(aF));
1112 FindFacesInsideHoleWires(aFOr, aF, aLFImages, theInvertedEdges,
1113 aDMEOrLEIm, anEFMap, aMFHoles, theDMFNewHoles, aCtx);
1115 TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles);
1116 for (; aItMH.More(); aItMH.Next()) {
1117 aBB.Add(aFHoles, aItMH.Value());
1120 // find invalid faces
1121 FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFMVE, aDMFMIE,
1122 *pMNE, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex,
1123 aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
1126 if (aLFInv.Extent()) {
1127 if (theAlreadyInvFaces.IsBound(aF)) {
1128 if (theAlreadyInvFaces.Find(aF) > 2) {
1129 if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) {
1136 theInvFaces.Add(aF, aLFInv);
1140 if (theInvFaces.IsEmpty()) {
1141 theInvEdges.Clear();
1146 // show invalid faces
1147 TopoDS_Compound aCFInv1;
1148 BRep_Builder().MakeCompound(aCFInv1);
1149 Standard_Integer aNbFInv = theInvFaces.Extent();
1150 for (i = 1; i <= aNbFInv; ++i) {
1151 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1152 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1153 for (; aItLFInv.More(); aItLFInv.Next()) {
1154 const TopoDS_Shape& aFIm = aItLFInv.Value();
1155 BRep_Builder().Add(aCFInv1, aFIm);
1160 TopTools_IndexedMapOfShape aMERemoved;
1161 // remove invalid splits of faces using inverted edges
1162 RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins,
1163 theInvFaces, theFImages, aMERemoved);
1164 if (theInvFaces.IsEmpty()) {
1165 theInvEdges.Clear();
1169 // remove invalid splits from valid splits
1170 RemoveInvalidSplitsFromValid (theInvFaces, theArtInvFaces, theInvertedEdges,
1171 aDMFMVIE, theFImages);
1173 // remove inside faces
1174 TopTools_IndexedMapOfShape aMEInside;
1175 RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, theInvertedEdges,
1176 anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles, theIntRes,
1177 aMERemoved, aMEInside, theSolids);
1179 // make compound of valid splits
1180 TopoDS_Compound aCFIm;
1181 aBB.MakeCompound(aCFIm);
1183 aNb = theFImages.Extent();
1184 for (i = 1; i <= aNb; ++i) {
1185 const TopTools_ListOfShape& aLFIm = theFImages(i);
1186 aItLF.Initialize(aLFIm);
1187 for (; aItLF.More(); aItLF.Next()) {
1188 const TopoDS_Shape& aFIm = aItLF.Value();
1189 aBB.Add(aCFIm, aFIm);
1193 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
1194 TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
1196 // filter maps of images and origins
1197 FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
1199 // filter invalid faces
1200 FilterInvalidFaces(theFImages, aDMEF, theInvEdges, aMEInside, theInvFaces, theArtInvFaces);
1201 aNb = theInvFaces.Extent();
1203 theInvEdges.Clear();
1208 // show invalid faces
1209 TopoDS_Compound aCFInv;
1210 BRep_Builder().MakeCompound(aCFInv);
1211 aNbFInv = theInvFaces.Extent();
1212 for (i = 1; i <= aNbFInv; ++i) {
1213 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1214 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1215 for (; aItLFInv.More(); aItLFInv.Next()) {
1216 const TopoDS_Shape& aFIm = aItLFInv.Value();
1217 BRep_Builder().Add(aCFInv, aFIm);
1222 // filter invalid edges
1223 FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFMIE, aMERemoved, theInvEdges);
1225 // Check additionally validity of edges originated from vertices.
1226 CheckEdgesCreatedByVertex (theInvFaces, theArtInvFaces, theEdgesOrigins,
1227 theValidEdges, theEdgesToAvoid);
1230 // show invalid edges
1231 TopoDS_Compound aCEInv;
1232 BRep_Builder().MakeCompound(aCEInv);
1233 aNbEInv = theInvEdges.Extent();
1234 for (i = 1; i <= aNbEInv; ++i) {
1235 const TopoDS_Shape& aE = theInvEdges(i);
1236 BRep_Builder().Add(aCEInv, aE);
1240 theLastInvEdges.Clear();
1241 aNb = theInvEdges.Extent();
1242 for (i = 1; i <= aNb; ++i) {
1243 const TopoDS_Shape& aE = theInvEdges(i);
1244 theEdgesToAvoid.Add(aE);
1245 theLastInvEdges.Add(aE);
1248 aNb = theInvFaces.Extent();
1249 for (i = 1; i <= aNb; ++i) {
1250 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
1251 if (theAlreadyInvFaces.IsBound(aF)) {
1252 theAlreadyInvFaces.ChangeFind(aF)++;
1255 theAlreadyInvFaces.Bind(aF, 1);
1260 //=======================================================================
1261 //function : IntersectTrimmedEdges
1262 //purpose : Intersection of the trimmed edges among themselves
1263 //=======================================================================
1264 void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
1265 const Handle(BRepAlgo_AsDes)& theAsDes,
1266 TopTools_DataMapOfShapeListOfShape& theOEImages,
1267 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1268 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1269 Handle(IntTools_Context)& theCtx,
1270 TopTools_MapOfShape& theNewEdges,
1271 TopTools_DataMapOfShapeShape& theETrimEInf)
1273 if (theLF.IsEmpty()) {
1277 // get edges to intersect from descendants of the offset faces
1278 TopTools_ListOfShape aLS;
1280 TopTools_ListIteratorOfListOfShape aItLF(theLF);
1281 for (; aItLF.More(); aItLF.Next()) {
1282 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1284 const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
1285 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1286 for (; aItLE.More(); aItLE.Next()) {
1287 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1289 if (ProcessMicroEdge(aE, theCtx)) {
1293 if (theNewEdges.Add(aE)) {
1299 if (aLS.Extent() < 2) {
1300 // nothing to intersect
1304 // perform intersection of the edges
1305 BOPAlgo_Builder aGFE;
1306 aGFE.SetArguments(aLS);
1308 if (aGFE.HasErrors()) {
1312 TopTools_ListOfShape aLA;
1313 // fill map with edges images
1314 TopTools_ListIteratorOfListOfShape aIt(aLS);
1315 for (; aIt.More(); aIt.Next()) {
1316 const TopoDS_Shape& aE = aIt.Value();
1317 const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
1318 if (aLEIm.IsEmpty()) {
1324 theOEImages.Bind(aE, aLEIm);
1326 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
1327 for (; aItLE.More(); aItLE.Next()) {
1328 const TopoDS_Shape& aEIm = aItLE.Value();
1329 TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm);
1331 pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape());
1333 AppendToList(*pLEOr, aE);
1337 UpdateOrigins(aLA, theEdgesOrigins, aGFE);
1338 UpdateIntersectedEdges(aLA, theETrimEInf, aGFE);
1341 //=======================================================================
1342 //function : GetEdges
1343 //purpose : Getting edges from AsDes map to build the splits of faces
1344 //=======================================================================
1345 Standard_Boolean GetEdges(const TopoDS_Face& theFace,
1346 const Handle(BRepAlgo_AsDes)& theAsDes,
1347 const TopTools_DataMapOfShapeListOfShape& theEImages,
1348 const TopTools_MapOfShape& theLastInvEdges,
1349 const TopTools_IndexedMapOfShape& theInvEdges,
1350 Handle(IntTools_Context)& theCtx,
1351 const TopTools_MapOfShape& theModifiedEdges,
1352 TopoDS_Shape& theEdges,
1353 TopTools_IndexedMapOfShape& theInv)
1355 // get boundary edges
1356 TopTools_MapOfShape aMFBounds;
1357 TopExp_Explorer aExp(theFace, TopAbs_EDGE);
1358 for (; aExp.More(); aExp.Next()) {
1359 const TopoDS_Shape& aE = aExp.Current();
1360 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1365 TopTools_ListIteratorOfListOfShape aItLE(*pLEIm);
1366 for (; aItLE.More(); aItLE.Next()) {
1367 const TopoDS_Shape& aEIm = aItLE.Value();
1368 aMFBounds.Add(aEIm);
1374 Standard_Boolean bFound(Standard_False), bUpdate(Standard_False);
1375 // the resulting edges
1376 TopoDS_Compound anEdges;
1377 aBB.MakeCompound(anEdges);
1379 TopTools_MapOfShape aMEFence;
1380 // the edges by which the offset face should be split
1381 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theFace);
1382 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1383 for (; aItLE.More(); aItLE.Next()) {
1384 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1387 bUpdate = theModifiedEdges.Contains(aE);
1390 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1392 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
1393 for (; aItLEIm.More(); aItLEIm.Next()) {
1394 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1396 if (!aMEFence.Add(aEIm))
1399 if (theInvEdges.Contains(aEIm)) {
1402 bUpdate = theLastInvEdges.Contains(aEIm);
1406 // check for micro edge
1407 if (ProcessMicroEdge(aEIm, theCtx)) {
1411 aBB.Add(anEdges, aEIm);
1413 bFound = !aMFBounds.Contains(aEIm);
1417 bUpdate = theModifiedEdges.Contains(aEIm);
1422 if (theInvEdges.Contains(aE)) {
1425 bUpdate = theLastInvEdges.Contains(aE);
1430 if (ProcessMicroEdge(aE, theCtx)) {
1433 aBB.Add(anEdges, aE);
1435 bFound = !aMFBounds.Contains(aE);
1441 return bFound && bUpdate;
1444 //=======================================================================
1445 //function : BuildSplitsOfFace
1446 //purpose : Building the splits of offset face
1447 //=======================================================================
1448 void BuildSplitsOfFace(const TopoDS_Face& theFace,
1449 const TopoDS_Shape& theEdges,
1450 TopTools_DataMapOfShapeShape& theFacesOrigins,
1451 TopTools_ListOfShape& theLFImages)
1453 theLFImages.Clear();
1455 // take edges to split the face
1456 TopTools_ListOfShape aLE;
1457 TopExp_Explorer aExp(theEdges, TopAbs_EDGE);
1458 for (; aExp.More(); aExp.Next()) {
1459 TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
1460 aE.Orientation(TopAbs_FORWARD);
1462 aE.Orientation(TopAbs_REVERSED);
1466 TopoDS_Face aFF = theFace;
1467 TopAbs_Orientation anOr = theFace.Orientation();
1468 aFF.Orientation(TopAbs_FORWARD);
1470 // build pcurves for edges on the face
1471 BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
1473 // build splits of faces
1474 BOPAlgo_BuilderFace aBF;
1479 const TopTools_ListOfShape& aLFSp = aBF.Areas();
1480 TopTools_ListIteratorOfListOfShape aItLF(aLFSp);
1481 for (; aItLF.More(); aItLF.Next()) {
1482 TopoDS_Shape& aFSp = aItLF.ChangeValue();
1483 aFSp.Orientation(anOr);
1484 theLFImages.Append(aFSp);
1486 theFacesOrigins.Bind(aFSp, theFace);
1490 //=======================================================================
1491 //function : BuildSplitsOfFace
1492 //purpose : Building the splits of offset face
1493 //=======================================================================
1494 void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
1495 const TopoDS_Shape& theEdges,
1496 TopTools_ListOfShape& theLFImages)
1498 BOPAlgo_Builder aGF;
1500 aGF.AddArgument(theFace);
1501 aGF.AddArgument(theEdges);
1503 if (aGF.HasErrors()) {
1507 // splits of the offset shape
1508 theLFImages = aGF.Modified(theFace);
1511 //=======================================================================
1512 //function : CheckIfArtificial
1513 //purpose : Checks if the face is artificially invalid
1514 //=======================================================================
1515 Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
1516 const TopTools_ListOfShape& theLFImages,
1517 const TopoDS_Shape& theCE,
1518 const TopTools_IndexedMapOfShape& theMapEInv,
1519 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1520 TopTools_MapOfShape& theMENInv,
1521 Handle(BRepAlgo_AsDes)& theAsDes)
1523 // all boundary edges should be used
1524 TopTools_IndexedMapOfShape aMEUsed;
1525 TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages);
1526 for (; aItLFIm.More(); aItLFIm.Next()) {
1527 const TopoDS_Shape& aFIm = aItLFIm.Value();
1528 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed);
1529 TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed);
1532 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
1533 TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
1535 Standard_Integer i, aNb = theMapEInv.Extent();
1536 for (i = 1; i <= aNb; ++i) {
1537 const TopoDS_Shape& aEInv = theMapEInv(i);
1538 TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX);
1539 for (; aExpV.More(); aExpV.Next()) {
1540 const TopoDS_Shape& aVEInv = aExpV.Current();
1541 const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv);
1543 TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv);
1544 for (; aItLEInv.More(); aItLEInv.Next()) {
1545 const TopoDS_Shape& aENInv = aItLEInv.Value();
1546 if (!aMEUsed.Contains(aENInv)) {
1547 theMENInv.Add(aENInv);
1554 if (theMENInv.IsEmpty()) {
1555 return Standard_False;
1558 TopTools_IndexedMapOfShape aMEFound;
1559 TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound);
1561 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF);
1562 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1563 for (; aItLE.More(); aItLE.Next()) {
1564 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1566 if (theOEImages.IsBound(aE)) {
1567 Standard_Boolean bChecked = Standard_False;
1568 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE);
1569 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
1570 for (; aItLEIm.More(); aItLEIm.Next()) {
1571 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1572 if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) {
1576 bChecked = Standard_True;
1577 if (aMEUsed.Contains(aEIm)) {
1582 if (bChecked && !aItLEIm.More()) {
1587 if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) {
1593 return aItLE.More();
1596 //=======================================================================
1597 //function : FindInvalidEdges
1598 //purpose : Looking for the invalid edges
1599 //=======================================================================
1600 void FindInvalidEdges(const TopoDS_Face& theF,
1601 const TopTools_ListOfShape& theLFImages,
1602 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1603 const TopTools_DataMapOfShapeShape& theFacesOrigins,
1604 const BRepOffset_Analyse* theAnalyse,
1605 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1606 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1607 TopTools_IndexedMapOfShape& theInvEdges,
1608 TopTools_IndexedMapOfShape& theValidEdges,
1609 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
1610 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
1611 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
1612 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
1613 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
1614 TopTools_MapOfShape& theMEInverted,
1615 TopTools_MapOfShape& theEdgesInvalidByVertex,
1616 TopTools_MapOfShape& theEdgesValidByVertex)
1618 // Edge is considered as invalid in the following cases:
1619 // 1. Its orientation on the face has changed comparing to the originals edge and face;
1620 // 2. The vertices of the edge have changed places comparing to the originals edge and face.
1622 // The edges created from vertices, i.e. as intersection between two faces connected only
1623 // by VERTEX, will also be checked on validity. For these edges the correct orientation will
1624 // be defined by the edges on the original face adjacent to the connection vertex
1627 const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
1629 TopTools_IndexedMapOfShape aMEInv;
1631 TopTools_MapOfShape aMEVal;
1633 TopTools_MapOfShape aMEInt;
1635 // maps for checking the inverted edges
1636 TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
1637 TopTools_IndexedMapOfShape aMEdges;
1638 // back map from the original shapes to their offset images
1639 TopTools_DataMapOfShapeListOfShape anImages;
1641 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
1642 for (; aItLF.More(); aItLF.Next()) {
1643 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1645 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1646 for (; aExp.More(); aExp.Next()) {
1647 const TopoDS_Shape& aE = aExp.Current();
1651 // keep connection from edges to faces
1652 TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE);
1654 pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape()));
1656 AppendToList(*pLF, aFIm);
1658 // keep connection from vertices to edges
1659 TopoDS_Iterator aItV(aE);
1660 for (; aItV.More(); aItV.Next()) {
1661 const TopoDS_Shape& aV = aItV.Value();
1663 TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV);
1665 pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape()));
1667 AppendToList(*pLE, aE);
1670 // back map from original edges to their offset images
1671 const TopTools_ListOfShape* pLOr = theEdgesOrigins.Seek (aE);
1674 for (TopTools_ListOfShape::Iterator itOr (*pLOr); itOr.More(); itOr.Next())
1676 const TopoDS_Shape& aSOr = itOr.Value();
1678 if (!FindShape (aSOr, aFOr, theAnalyse, aSInF))
1680 TopTools_ListOfShape* pImages = anImages.ChangeSeek (aSInF);
1682 pImages = anImages.Bound (aSInF, TopTools_ListOfShape());
1683 AppendToList (*pImages, aE);
1688 // the map will be used to find the edges on the original face
1689 // adjacent to the same vertex. It will be filled at first necessity;
1690 TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
1692 aItLF.Initialize(theLFImages);
1693 for (; aItLF.More(); aItLF.Next()) {
1694 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1696 // valid edges for this split
1697 TopTools_MapOfShape aMVE;
1698 // invalid edges for this split
1699 TopTools_IndexedMapOfShape aMIE;
1701 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1702 for (; aExp.More(); aExp.Next()) {
1703 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
1705 if (aEIm.Orientation() == TopAbs_INTERNAL) {
1710 if (!theEdgesOrigins.IsBound(aEIm)) {
1714 const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm);
1715 if (aLEOr.IsEmpty()) {
1719 Standard_Integer aNbVOr = 0;
1720 TopTools_ListIteratorOfListOfShape aItLEO(aLEOr);
1721 for (; aItLEO.More(); aItLEO.Next()) {
1722 if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) {
1726 if (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1)
1729 TopTools_MapOfShape aME, aMV, aMF;
1730 Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
1731 Standard_Integer aNbP = NbPoints(aEIm), aNbInv = 0;
1732 Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
1734 aDMEF.FindFromKey(aEIm).Extent() == 1 &&
1735 !theOEOrigins.IsBound(aEIm));
1737 aItLEO.Initialize(aLEOr);
1738 for (; aItLEO.More(); aItLEO.Next()) {
1739 const TopoDS_Shape& aSOr = aItLEO.Value();
1740 Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
1744 // for some cases it is impossible to check the validity of the edge
1748 // find edges on the original face adjacent to this vertex
1749 if (aDMVEFOr.IsEmpty()) {
1751 TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
1754 TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr);
1756 TopoDS_Compound aCEOr;
1757 BRep_Builder().MakeCompound(aCEOr);
1758 // Avoid classification of edges originated from vertices
1759 // located between tangent edges
1760 Standard_Boolean bAllTgt = Standard_True;
1761 TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
1762 gp_Vec aVRef = GetAverageTangent (aItLEFOr.Value(), aNbP);
1763 for (; aItLEFOr.More(); aItLEFOr.Next())
1765 const TopoDS_Shape& aEOr = aItLEFOr.Value();
1766 BRep_Builder().Add(aCEOr, aEOr);
1768 gp_Vec aVCur = GetAverageTangent (aEOr, aNbP);
1769 if (!aVRef.IsParallel (aVCur, Precision::Angular()))
1770 bAllTgt = Standard_False;
1777 FindShape(aSOr, aFOr, theAnalyse, aEOrF);
1779 TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr);
1781 pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape());
1783 AppendToList(*pLEIm, aEIm);
1786 if (aEOrF.IsNull()) {
1787 // the edge has not been found
1793 TopTools_MapOfShape aMVTotal;
1794 Standard_Integer aNbChecked = 0;
1795 // Just check if the original edges sharing the vertex do not share it any more.
1796 for (TopoDS_Iterator it (aEOrF); it.More(); it.Next())
1798 const TopoDS_Shape& aEOr = it.Value();
1799 const TopTools_ListOfShape* aLIm = anImages.Seek (aEOr);
1803 TopTools_IndexedDataMapOfShapeListOfShape aMVLoc;
1804 for (TopTools_ListOfShape::Iterator itLIM (*aLIm); itLIM.More(); itLIM.Next())
1805 TopExp::MapShapesAndAncestors (itLIM.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVLoc);
1806 for (Standard_Integer i = 1; i <= aMVLoc.Extent(); ++i)
1808 if (aMVLoc(i).Extent() > 1 && !aMVTotal.Add (aMVLoc.FindKey (i)))
1810 bInvalid = Standard_True;
1811 theEdgesInvalidByVertex.Add(aEIm);
1818 if (!bInvalid && aNbChecked < 2)
1821 theEdgesValidByVertex.Add (aEIm);
1826 // Check orientations of the image edge and original edge.
1827 // In case the 3d curves are having the same direction the orientations
1828 // must be the same. Otherwise the orientations should also be different.
1830 // get average tangent vector for each curve taking into account
1831 // the orientations of the edges, i.e. the edge is reversed
1832 // the vector is reversed as well
1833 gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP);
1834 gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP);
1839 Standard_Real aCos = aVSum1.Dot(aVSum2);
1840 if (Abs(aCos) < 0.9999) {
1845 TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX);
1846 for (; aExpE.More(); aExpE.Next()) {
1847 const TopoDS_Shape& aV = aExpE.Current();
1852 for (TopTools_ListOfShape::Iterator itFA (theAnalyse->Ancestors (aEOrF));
1853 itFA.More(); itFA.Next())
1854 aMF.Add (itFA.Value());
1857 if (aCos < Precision::Confusion()) {
1858 bInvalid = Standard_True;
1862 bChecked = Standard_True;
1869 Standard_Boolean bLocalOnly = (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1);
1870 Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
1871 if (aNbE > 1 && aNbV == 2*aNbE)
1873 Standard_Boolean bSkip = Standard_True;
1875 // Allow the edge to be analyzed if it is:
1876 // * originated from more than two faces
1877 // * unanimously considered valid or invalid
1878 // * not a boundary edge in the splits
1879 if (aMF.Extent () > 2 && (aNbInv == 0 || aNbInv == aNbE))
1881 if (theLFImages.Extent() > 2)
1883 TopoDS_Iterator itV (aEIm);
1884 for (; itV.More(); itV.Next())
1886 TopTools_ListOfShape::Iterator itE (aDMVE.FindFromKey (itV.Value()));
1887 for (; itE.More(); itE.Next())
1888 if (aDMEF.FindFromKey (itE.Value()).Extent() < 2)
1899 bLocalOnly = Standard_True;
1904 theInvEdges.Add(aEIm);
1910 // check if the edge has been inverted
1911 Standard_Boolean bInverted = !aNbE || bLocalOnly ? Standard_False :
1912 CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
1913 theEdgesOrigins, aDMVE, aMEdges, theMEInverted);
1915 if (!bInverted || !aNbVOr) {
1917 theValidEdges.Add(aEIm);
1926 theDMFMVE.Bind (aFIm, aMVE);
1932 theDMFMIE.Bind (aFIm, aMIE);
1936 // process invalid edges:
1937 // check for the inverted edges
1938 TopTools_MapOfShape aMVIE;
1939 // fill neutral edges
1940 TopTools_MapOfShape aMNE;
1942 Standard_Integer i, aNbEInv = aMEInv.Extent();
1943 for (i = 1; i <= aNbEInv; ++i) {
1944 const TopoDS_Shape& aEIm = aMEInv(i);
1946 // neutral edges - on the splits of the same offset face
1947 // it is valid for one split and invalid for other
1948 if (aMEVal.Contains(aEIm))
1954 // the inverted images of the origins of invalid edges should also be invalid
1955 if (!theMEInverted.Contains(aEIm)) {
1959 const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm);
1964 TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr);
1965 for (; aItLOEOr.More(); aItLOEOr.Next()) {
1966 const TopoDS_Shape& aOEOr = aItLOEOr.Value();
1967 const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr);
1969 TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1);
1970 for (; aItLEIm1.More(); aItLEIm1.Next()) {
1971 const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
1972 if (aMEdges.Contains(aEIm1) &&
1973 !aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) &&
1974 theMEInverted.Contains(aEIm1)) {
1975 theInvEdges.Add(aEIm1);
1984 theDMFMNE.Bind (theF, aMNE);
1989 theDMFMVIE.Bind (theF, aMVIE);
1995 static void addAsNeutral (const TopoDS_Shape& theE,
1996 const TopoDS_Shape& theFInv,
1997 const TopoDS_Shape& theFVal,
1998 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
1999 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges)
2001 TopTools_IndexedMapOfShape* pMEInv = theLocInvEdges.ChangeSeek (theFInv);
2003 pMEInv = theLocInvEdges.Bound (theFInv, TopTools_IndexedMapOfShape());
2006 TopTools_MapOfShape* pMEVal = theLocValidEdges.ChangeSeek (theFVal);
2008 pMEVal = theLocValidEdges.Bound (theFVal, TopTools_MapOfShape());
2013 //=======================================================================
2014 //function : FindInvalidEdges
2015 //purpose : Additional method to look for invalid faces
2016 //=======================================================================
2017 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
2018 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2019 const TopTools_DataMapOfShapeShape& theFacesOrigins,
2020 const BRepOffset_Analyse* theAnalyse,
2021 const TopTools_IndexedMapOfShape& theInvEdges,
2022 const TopTools_IndexedMapOfShape& theValidEdges,
2023 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2024 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
2025 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges)
2027 // 1. Find edges unclassified in faces
2028 // 2. Find SD faces in which the same edge is classified
2029 // 3. Check if the edge is neutral in face in which it wasn't classified
2031 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aMEUnclassified;
2032 TopTools_DataMapOfShapeShape aFSplitFOffset;
2034 // Avoid artificial faces
2035 TopTools_MapOfShape aNewFaces;
2038 TopTools_MapOfShape aMapNewTmp;
2039 for (TopTools_ListOfShape::Iterator it (theAnalyse->NewFaces()); it.More(); it.Next())
2040 aMapNewTmp.Add (it.Value());
2042 for (TopTools_ListOfShape::Iterator it (theLFOffset); it.More(); it.Next())
2044 const TopoDS_Shape& aFOffset = it.Value();
2045 const TopoDS_Shape& aFOrigin = theFacesOrigins.Find (aFOffset);
2046 if (aMapNewTmp.Contains (aFOrigin))
2047 aNewFaces.Add (aFOffset);
2051 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
2052 for (TopTools_ListOfShape::Iterator itLFO (theLFOffset); itLFO.More(); itLFO.Next())
2054 const TopoDS_Shape& aF = itLFO.Value();
2055 if (aNewFaces.Contains (aF))
2058 const TopTools_ListOfShape& aLFImages = theFImages.FindFromKey (aF);
2059 for (TopTools_ListOfShape::Iterator itLF (aLFImages); itLF.More(); itLF.Next())
2061 const TopoDS_Shape& aFIm = itLF.Value();
2063 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFMap);
2065 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFIm);
2066 const TopTools_MapOfShape* pMEValid = theLocValidEdges.Seek (aFIm);
2068 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
2070 const TopoDS_Shape& aE = expE.Current();
2071 if (theInvEdges.Contains (aE) != theValidEdges.Contains (aE))
2073 // edge is classified in some face
2075 if ((!pMEInvalid || !pMEInvalid->Contains (aE)) &&
2076 (!pMEValid || !pMEValid->Contains (aE)))
2078 // but not in the current one
2079 TopTools_MapOfShape *pMap = aMEUnclassified.ChangeSeek (aE);
2081 pMap = &aMEUnclassified (aMEUnclassified.Add (aE, TopTools_MapOfShape()));
2084 aFSplitFOffset.Bind (aFIm, aF);
2091 if (aMEUnclassified.IsEmpty())
2094 // Analyze unclassified edges
2095 const Standard_Integer aNbE = aMEUnclassified.Extent();
2096 for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
2098 const TopoDS_Shape& aE = aMEUnclassified.FindKey (iE);
2099 const TopTools_MapOfShape& aMFUnclassified = aMEUnclassified (iE);
2101 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
2103 for (TopTools_ListOfShape::Iterator itLF (aLF); itLF.More(); itLF.Next())
2105 const TopoDS_Shape& aFClassified = itLF.Value();
2106 if (aMFUnclassified.Contains (aFClassified))
2109 BOPTools_Set anEdgeSetClass;
2110 anEdgeSetClass.Add (aFClassified, TopAbs_EDGE);
2112 TopoDS_Shape aEClassified;
2113 FindShape (aE, aFClassified, NULL, aEClassified);
2114 TopAbs_Orientation anOriClass = aEClassified.Orientation();
2117 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aEClassified), TopoDS::Face (aFClassified), aDNClass);
2119 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFClassified);
2120 Standard_Boolean isInvalid = pMEInvalid && pMEInvalid->Contains (aE);
2122 for (TopTools_MapOfShape::Iterator itM (aMFUnclassified); itM.More(); itM.Next())
2124 const TopoDS_Shape& aFUnclassified = itM.Value();
2126 BOPTools_Set anEdgeSetUnclass;
2127 anEdgeSetUnclass.Add (aFUnclassified, TopAbs_EDGE);
2129 if (anEdgeSetClass.IsEqual (anEdgeSetUnclass))
2132 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aE), TopoDS::Face (aFUnclassified), aDNUnclass);
2134 Standard_Boolean isSameOri = aDNClass.IsEqual (aDNUnclass, Precision::Angular());
2136 // Among other splits of the same face find those where the edge is contained with different
2138 const TopoDS_Shape& aFOffset = aFSplitFOffset.Find (aFUnclassified);
2139 const TopTools_ListOfShape& aLFSplits = theFImages.FindFromKey (aFOffset);
2140 TopTools_ListOfShape::Iterator itLFSp (aLFSplits);
2141 for (; itLFSp.More(); itLFSp.Next())
2143 const TopoDS_Shape& aFSp = itLFSp.Value();
2145 if (!aFSp.IsSame (aFUnclassified) && aMFUnclassified.Contains (aFSp))
2147 TopoDS_Shape aEUnclassified;
2148 FindShape (aE, aFSp, NULL, aEUnclassified);
2150 TopAbs_Orientation anOriUnclass = aEUnclassified.Orientation();
2152 anOriUnclass = TopAbs::Reverse (anOriUnclass);
2154 if (anOriClass != anOriUnclass)
2156 // make the edge neutral for the face
2157 TopTools_MapOfShape* pMENeutral = theNeutralEdges.ChangeSeek (aFOffset);
2159 pMENeutral = theNeutralEdges.Bound (aFOffset, TopTools_MapOfShape());
2160 pMENeutral->Add (aE);
2162 if (isInvalid && isSameOri)
2164 // make edge invalid in aFUnclassified and valid in aFSp
2165 addAsNeutral (aE, aFClassified, aFSp, theLocInvEdges, theLocValidEdges);
2169 // make edge invalid in aFSp and valid in aFUnclassified
2170 addAsNeutral (aE, aFSp, aFClassified, theLocInvEdges, theLocValidEdges);
2183 //=======================================================================
2184 //function : FindInvalidFaces
2185 //purpose : Looking for the invalid faces by analyzing their invalid edges
2186 //=======================================================================
2187 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
2188 const TopTools_IndexedMapOfShape& theInvEdges,
2189 const TopTools_IndexedMapOfShape& theValidEdges,
2190 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
2191 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
2192 const TopTools_MapOfShape& theMENeutral,
2193 const TopTools_MapOfShape& theMEInverted,
2194 const TopTools_MapOfShape& theEdgesInvalidByVertex,
2195 const TopTools_MapOfShape& theEdgesValidByVertex,
2196 const TopTools_MapOfShape& theMFHoles,
2197 TopTools_IndexedMapOfShape& theMFInvInHole,
2198 TopTools_ListOfShape& theInvFaces,
2199 TopTools_ListOfShape& theInvertedFaces)
2201 // The face should be considered as invalid in the following cases:
2202 // 1. It has been reverted, i.e. at least two not connected edges
2203 // have changed orientation (i.e. invalid). In this case all edges,
2204 // should be invalid for that face, because edges have also been reverted;
2205 // 2. All checked edges of the face are invalid for this face;
2206 // The face should be removed from the splits in the following cases:
2207 // 1. All checked edges of the face are invalid for this one, but valid for
2208 // some other face in this list of splits.
2209 // The face will be kept in the following cases:
2210 // 1. Some of the edges are valid for this face.
2211 Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
2212 Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
2213 Standard_Boolean bIsInvalidByInverted;
2214 Standard_Integer aNbChecked;
2216 Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
2218 // neutral edges to remove
2219 TopTools_IndexedMapOfShape aMENRem;
2221 // faces for post treat
2222 TopTools_ListOfShape aLFPT;
2224 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
2225 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2226 for (; aItLF.More(); aItLF.Next())
2228 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2229 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
2232 aItLF.Initialize (theLFImages);
2233 for (; aItLF.More(); ) {
2234 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2236 // valid edges for this split
2237 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
2238 // invalid edges for this split
2239 const TopTools_IndexedMapOfShape* pMIE = theDMFMIE.Seek (aFIm);
2241 bHasValid = Standard_False;
2242 bAllValid = Standard_True;
2243 bAllInvalid = Standard_True;
2244 bHasReallyInvalid = Standard_False;
2245 bAllInvNeutral = Standard_True;
2246 bIsInvalidByInverted = Standard_True;
2249 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2250 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2251 for (; aExp.More(); aExp.Next()) {
2252 const TopoDS_Shape& aEIm = aExp.Current();
2254 bValid = theValidEdges.Contains(aEIm);
2255 bInvalid = theInvEdges.Contains(aEIm);
2256 bNeutral = theMENeutral.Contains(aEIm);
2258 if (!bValid && !bInvalid && !bNeutral) {
2259 // edge has not been checked for some reason
2263 // skip not-boundary edges originated from vertex
2264 if ((theEdgesInvalidByVertex.Contains (aEIm) ||
2265 theEdgesValidByVertex.Contains (aEIm)) &&
2266 aDMEF.FindFromKey (aEIm).Extent() != 1)
2271 bInvalidLoc = pMIE && pMIE->Contains (aEIm);
2272 bHasReallyInvalid = bInvalid && bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
2273 if (bHasReallyInvalid) {
2277 bValidLoc = pMVE && pMVE->Contains(aEIm);
2278 bInverted = theMEInverted.Contains(aEIm);
2279 if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid) {
2280 bInvalid = bInverted;
2283 if (bValidLoc && bNeutral) {
2284 bHasValid = Standard_True;
2287 bAllValid &= bValidLoc;
2288 bAllInvalid &= (bInvalid || bInvalidLoc);
2289 bAllInvNeutral &= (bAllInvalid && bNeutral);
2290 bIsInvalidByInverted &= (bInvalidLoc || bInverted);
2298 if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) {
2299 // remove edges from neutral
2300 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2302 theLFImages.Remove(aItLF);
2306 if (bHasReallyInvalid || (bAllInvalid &&
2307 !(bHasValid || bAllValid) &&
2308 !(bAllInvNeutral && (aNbChecked == 1)))) {
2309 theInvFaces.Append(aFIm);
2310 if (theMFHoles.Contains(aFIm)) {
2311 theMFInvInHole.Add(aFIm);
2317 if (theMFHoles.Contains(aFIm)) {
2318 // remove edges from neutral
2319 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2321 theLFImages.Remove(aItLF);
2325 if (bIsInvalidByInverted && !(bHasValid || bAllValid))
2327 // The face contains only the inverted and locally invalid edges
2328 theInvertedFaces.Append(aFIm);
2331 if (!bAllInvNeutral) {
2335 // remove edges from neutral
2336 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2341 if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) {
2345 // check the splits once more
2346 aItLF.Initialize(aLFPT);
2347 for (; aItLF.More(); aItLF.Next()) {
2348 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2350 // valid edges for this split
2351 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek(aFIm);
2353 bHasValid = Standard_False;
2354 bAllValid = Standard_True;
2355 bAllInvalid = Standard_True;
2357 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2358 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2359 for (; aExp.More(); aExp.Next()) {
2360 const TopoDS_Shape& aEIm = aExp.Current();
2362 bValid = theValidEdges.Contains(aEIm);
2363 bInvalid = theInvEdges.Contains(aEIm);
2364 bNeutral = theMENeutral.Contains(aEIm) && !aMENRem.Contains (aEIm);
2365 bValidLoc = pMVE && pMVE->Contains(aEIm);
2367 if (!bInvalid && bTreatInvertedAsInvalid) {
2368 bInvalid = theMEInverted.Contains(aEIm);
2371 if (bValidLoc && bNeutral) {
2372 bHasValid = Standard_True;
2375 bAllValid = bAllValid && bValidLoc;
2376 bAllInvalid = bAllInvalid && bInvalid;
2379 if (bAllInvalid && !bHasValid && !bAllValid) {
2380 theInvFaces.Append(aFIm);
2385 //=======================================================================
2386 //function : FindFacesInsideHoleWires
2387 //purpose : Find faces inside holes wires from the original face
2388 //=======================================================================
2389 void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
2390 const TopoDS_Face& theFOffset,
2391 const TopTools_ListOfShape& theLFImages,
2392 const TopTools_MapOfShape& theInvertedEdges,
2393 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
2394 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
2395 TopTools_MapOfShape& theMFHoles,
2396 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
2397 Handle(IntTools_Context)& theContext)
2399 if (theLFImages.IsEmpty()) {
2403 // find all hole wires in the original face
2404 TopTools_ListOfShape aLHoleWires;
2405 const TopoDS_Wire& anOuterWire = BRepTools::OuterWire(theFOrigin);
2406 TopExp_Explorer aExpW(theFOrigin, TopAbs_WIRE);
2407 for (; aExpW.More(); aExpW.Next()) {
2408 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aExpW.Current());
2409 if (!aHoleWire.IsSame(anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL) {
2410 aLHoleWires.Append(aHoleWire);
2414 if (aLHoleWires.IsEmpty()) {
2415 // no holes in the face
2419 TopTools_ListOfShape *pLFNewHoles = theDMFNewHoles.ChangeSeek(theFOrigin);
2422 pLFNewHoles = theDMFNewHoles.Bound(theFOrigin, TopTools_ListOfShape());
2424 if (pLFNewHoles->IsEmpty()) {
2426 // find the faces representing holes in the images of the faces:
2427 // 1. for each original hole wire try to build its image
2428 // 2. build the new planar face from the images
2430 // map vertices and edges of the splits
2431 TopTools_IndexedMapOfShape aMESplits;
2432 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2433 for (; aItLF.More(); aItLF.Next()) {
2434 TopExp::MapShapes(aItLF.Value(), TopAbs_EDGE, aMESplits);
2437 TopTools_ListIteratorOfListOfShape aItLW(aLHoleWires);
2438 for (; aItLW.More(); aItLW.Next()) {
2439 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aItLW.Value());
2440 // find images of all edges of the original wire
2441 TopTools_IndexedMapOfShape aMEImWire;
2442 TopoDS_Iterator aItE(aHoleWire);
2443 for (; aItE.More(); aItE.Next()) {
2444 const TopoDS_Shape& aEOr = aItE.Value();
2445 const TopTools_ListOfShape *pLEIm = theDMEOrLEIm.Seek(aEOr);
2446 if (!pLEIm || pLEIm->IsEmpty()) {
2449 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
2450 for (; aItLEIm.More(); aItLEIm.Next()) {
2451 const TopoDS_Shape& aEIm = aItLEIm.Value();
2452 if (aMESplits.Contains(aEIm)) {
2453 aMEImWire.Add(aEIm);
2458 if (aMEImWire.IsEmpty()) {
2462 // build new planar face using these edges
2463 TopTools_ListOfShape aLE;
2464 Standard_Integer i, aNbE = aMEImWire.Extent();
2465 for (i = 1; i <= aNbE; ++i) {
2466 aLE.Append(aMEImWire(i).Oriented(TopAbs_FORWARD));
2467 aLE.Append(aMEImWire(i).Oriented(TopAbs_REVERSED));
2470 BOPAlgo_BuilderFace aBF;
2471 aBF.SetFace(TopoDS::Face(theFOffset.Oriented(TopAbs_FORWARD)));
2475 const TopTools_ListOfShape& aLFNew = aBF.Areas();
2476 if (aLFNew.IsEmpty()) {
2480 // check if outer edges in the new faces are not inverted
2481 // because the inverted edges mean that the hole has been
2482 // filled during offset and there will be no faces to remove
2483 TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew;
2484 TopTools_ListIteratorOfListOfShape aItLFNew(aLFNew);
2485 for (; aItLFNew.More(); aItLFNew.Next()) {
2486 TopExp::MapShapesAndAncestors(aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew);
2489 aNbE = aDMEFNew.Extent();
2490 for (i = 1; i <= aNbE; ++i) {
2491 if (aDMEFNew(i).Extent() == 1) {
2492 const TopoDS_Shape& aE = aDMEFNew.FindKey(i);
2493 if (theInvertedEdges.Contains(aE)) {
2503 aItLFNew.Initialize(aLFNew);
2504 for (; aItLFNew.More(); aItLFNew.Next()) {
2505 pLFNewHoles->Append(aItLFNew.Value());
2510 // Build Edge-Face map for splits of current offset face
2511 TopTools_IndexedDataMapOfShapeListOfShape anEFSplitsMap;
2512 // Build Edge-Face map for holes
2513 TopTools_IndexedDataMapOfShapeListOfShape anEFHolesMap;
2515 // among the splits of the offset face find those that are
2516 // located inside the hole faces
2517 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2518 for (; aItLF.More(); aItLF.Next()) {
2519 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
2520 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFSplitsMap);
2521 // get the point inside the face and classify it relatively hole faces
2524 Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(aFIm, aP3D, aP2D, theContext);
2529 Standard_Real aTol = BRep_Tool::Tolerance(aFIm);
2531 TopTools_ListIteratorOfListOfShape aItLFNew(*pLFNewHoles);
2532 for (; aItLFNew.More(); aItLFNew.Next()) {
2533 const TopoDS_Face& aFNew = TopoDS::Face(aItLFNew.Value());
2534 if (theContext->IsValidPointForFace(aP3D, aFNew, aTol)) {
2535 // the face is classified as IN
2536 theMFHoles.Add(aFIm);
2537 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFHolesMap);
2543 // Out of all found holes find those which cannot be removed
2544 // by checking their connectivity to splits of other offset faces.
2545 // These are the faces, which will create uncovered holes if removed.
2546 const Standard_Integer aNbE = anEFHolesMap.Extent();
2547 for (Standard_Integer i = 1; i <= aNbE; ++i)
2549 const TopoDS_Shape& anEdge = anEFHolesMap.FindKey(i);
2550 const TopTools_ListOfShape& aLFHoles = anEFHolesMap(i);
2551 // Check if the edge is outer for holes
2552 if (aLFHoles.Extent() != 1)
2555 const TopoDS_Shape& aFHole = aLFHoles.First();
2556 if (!theMFHoles.Contains(aFHole))
2560 // Check if the edge is not outer for splits
2561 const TopTools_ListOfShape& aLSplits = anEFSplitsMap.FindFromKey(anEdge);
2562 if (aLSplits.Extent() == 1)
2565 // Check if edge is only connected to splits of the current offset face
2566 const TopTools_ListOfShape& aLFAll = theEFMap.FindFromKey(anEdge);
2567 if (aLFAll.Extent() == 2)
2568 // Avoid removal of the hole from the splits
2569 theMFHoles.Remove(aFHole);
2573 //=======================================================================
2574 //function : GetAverageTangent
2575 //purpose : Computes average tangent vector along the curve
2576 //=======================================================================
2577 gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
2578 const Standard_Integer theNbP)
2581 TopExp_Explorer aExp(theS, TopAbs_EDGE);
2582 for (; aExp.More(); aExp.Next()) {
2583 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
2585 Standard_Real aT1, aT2;
2586 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
2590 Standard_Real aT = aT1;
2591 Standard_Real aDt = (aT2 - aT1) / theNbP;
2594 aVSum += aV.Normalized();
2598 if (aE.Orientation() == TopAbs_REVERSED) {
2607 //=======================================================================
2608 //function : CheckInverted
2609 //purpose : Checks if the edge has been inverted
2610 //=======================================================================
2611 Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
2612 const TopoDS_Face& theFOr,
2613 const TopTools_DataMapOfShapeListOfShape& theOEImages,
2614 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2615 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
2616 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
2617 const TopTools_IndexedMapOfShape& theMEdges,
2618 TopTools_MapOfShape& theMEInverted)
2620 // It is necessary to compare the direction from first vertex
2621 // to the last vertex on the original edge with the
2622 // same direction on the new edge. If the directions
2623 // will be different - the edge has been inverted.
2625 TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
2626 TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
2629 // find vertices of the offset shape
2630 TopExp::Vertices(theEIm, aVI1, aVI2);
2633 TopTools_ListOfShape aLEImages;
2634 if (theOEOrigins.IsBound(theEIm)) {
2635 TopoDS_Wire anImages;
2636 BRep_Builder().MakeWire(anImages);
2638 TopTools_MapOfShape aMImFence;
2639 const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm);
2640 TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr);
2641 for (; aItOffset.More(); aItOffset.Next()) {
2642 const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
2643 const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr);
2645 TopTools_ListIteratorOfListOfShape aItImages(aLImages);
2646 for (; aItImages.More(); aItImages.Next()) {
2647 const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
2648 if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) {
2649 BRep_Builder().Add(anImages, anIm);
2650 aLEImages.Append(anIm);
2655 // find alone vertices
2656 TopoDS_Vertex aVW1, aVW2;
2657 TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
2658 TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
2660 TopTools_ListOfShape aLVAlone;
2661 Standard_Integer aNb = aDMImVE.Extent();
2662 for (i = 1; i <= aNb; ++i) {
2663 const TopTools_ListOfShape& aLImE = aDMImVE(i);
2664 if (aLImE.Extent() == 1) {
2665 aLVAlone.Append(aDMImVE.FindKey(i));
2669 if (aLVAlone.Extent() > 1) {
2670 aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
2671 aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
2674 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2675 const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1);
2676 const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2);
2678 Standard_Real aDist1 = aPI1.SquareDistance(aPW1);
2679 Standard_Real aDist2 = aPI1.SquareDistance(aPW2);
2681 if (aDist1 < aDist2) {
2692 aLEImages.Append(theEIm);
2695 // Find edges connected to these vertices
2696 const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1);
2697 const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2);
2699 // Find vertices on the original face corresponding to vertices on the offset edge
2701 // find original edges for both lists
2702 TopTools_ListOfShape aLOE1, aLOE2;
2703 for (i = 0; i < 2; ++i) {
2704 const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
2705 TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2707 TopTools_MapOfShape aMFence;
2709 TopTools_ListIteratorOfListOfShape aItLIE(aLIE);
2710 for (; aItLIE.More(); aItLIE.Next()) {
2711 const TopoDS_Shape& aEI = aItLIE.Value();
2712 if (theEdgesOrigins.IsBound(aEI)) {
2713 const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI);
2715 TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins);
2716 for (; aItLOE.More(); aItLOE.Next()) {
2717 const TopoDS_Shape& aEO = aItLOE.Value();
2718 if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) {
2720 if (FindShape(aEO, theFOr, NULL, aEOin)) {
2721 AppendToList(aLOE, aEO);
2729 if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) {
2730 return Standard_False;
2733 // find vertices common for all edges in the lists
2734 for (i = 0; i < 2; ++i) {
2735 const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2736 TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
2738 const TopoDS_Shape& aEO = aLOE.First();
2739 TopExp_Explorer aExpV(aEO, TopAbs_VERTEX);
2740 for (; aExpV.More(); aExpV.Next()) {
2741 const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current();
2743 Standard_Boolean bVertValid = Standard_True;
2744 TopTools_ListIteratorOfListOfShape aItLOE(aLOE);
2745 for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) {
2746 const TopoDS_Shape& aEOx = aItLOE.Value();
2747 TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX);
2748 for (; aExpVx.More(); aExpVx.Next()) {
2749 const TopoDS_Shape& aVx = aExpVx.Current();
2750 if (aVx.IsSame(aV)) {
2755 if (!aExpVx.More()) {
2756 bVertValid = Standard_False;
2768 if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) {
2769 return Standard_False;
2772 // check positions of the offset and original vertices
2773 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2774 const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2);
2775 const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1);
2776 const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2);
2778 gp_Vec aVI(aPI1, aPI2);
2779 gp_Vec aVO(aPO1, aPO2);
2781 Standard_Real anAngle = aVI.Angle(aVO);
2782 Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4;
2784 TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages);
2785 for (; aItLEIm.More(); aItLEIm.Next()) {
2786 const TopoDS_Shape& aEInvr = aItLEIm.Value();
2787 theMEInverted.Add(aEInvr);
2793 //=======================================================================
2794 //function : CheckInvertedBlock
2795 //purpose : Checks if it is possible to remove the block containing
2797 //=======================================================================
2798 Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
2799 const TopTools_ListOfShape& theLCBF,
2800 const TopTools_MapOfShape& theMEInverted,
2801 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2802 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
2803 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll)
2805 // For possible removal of the block:
2806 // 1. There should be more than just one face in the block
2807 if (theCB.NbChildren() < 2) {
2808 return Standard_False;
2811 // 2. The block should at least contain two connected inverted edges with
2812 // different origins (not just two images/splits of the same edge)
2813 TopTools_MapOfShape aMECBInv;
2814 TopoDS_Compound aCECBInv;
2815 BRep_Builder().MakeCompound(aCECBInv);
2817 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
2818 for (; aExp.More(); aExp.Next()) {
2819 const TopoDS_Shape& aE = aExp.Current();
2820 if (theMEInverted.Contains(aE)) {
2821 if (aMECBInv.Add(aE)) {
2822 BRep_Builder().Add(aCECBInv, aE);
2827 if (aMECBInv.Extent() < 2) {
2828 return Standard_False;
2831 // check that the edges are connected and different
2832 TopTools_ListOfShape aLCBE;
2833 BOPTools_AlgoTools::MakeConnexityBlocks(aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
2835 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
2836 for (; aItLCBE.More(); aItLCBE.Next()) {
2837 const TopoDS_Shape& aCBE = aItLCBE.Value();
2838 // count the unique edges in the block
2839 Standard_Integer aNbUnique = 0;
2840 TopTools_MapOfShape aMEOrigins;
2841 TopoDS_Iterator aItE(aCBE);
2842 for (; aItE.More(); aItE.Next()) {
2843 const TopoDS_Shape& aE = aItE.Value();
2844 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
2850 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
2851 for (; aItLEOr.More(); aItLEOr.Next()) {
2852 const TopoDS_Shape& aEOr = aItLEOr.Value();
2853 if (aMEOrigins.Add(aEOr)) {
2859 if (aNbUnique >= 2) {
2864 if (!aItLCBE.More()) {
2865 return Standard_False;
2868 // 3. the block should not contain inverted edges which vertices
2869 // are contained in other blocks
2871 // collect vertices from inverted edges and compare them with
2872 // vertices from other blocks
2873 TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek(theCB);
2874 TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek(theCB);
2876 pMVInverted = theDMCBVInverted.Bound(theCB, TopTools_MapOfShape());
2877 pMVAll = theDMCBVAll.Bound(theCB, TopTools_MapOfShape());
2879 GetVerticesOnEdges(theCB, theMEInverted, *pMVInverted, *pMVAll);
2882 TopTools_ListIteratorOfListOfShape aItLCB1(theLCBF);
2883 for (; aItLCB1.More(); aItLCB1.Next()) {
2884 const TopoDS_Shape& aCB1 = aItLCB1.Value();
2885 if (aCB1.IsSame(theCB)) {
2889 // collect vertices from inverted edges
2890 TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek(aCB1);
2891 TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek(aCB1);
2892 if (!pMVInverted1) {
2893 pMVInverted1 = theDMCBVInverted.Bound(aCB1, TopTools_MapOfShape());
2894 pMVAll1 = theDMCBVAll.Bound(aCB1, TopTools_MapOfShape());
2896 GetVerticesOnEdges(aCB1, theMEInverted, *pMVInverted1, *pMVAll1);
2899 if (pMVInverted->HasIntersection(*pMVAll1)) {
2900 return Standard_False;
2904 return Standard_True;
2907 //=======================================================================
2908 //function : GetVerticesOnEdges
2909 //purpose : Get vertices from the given shape belonging to the given edges
2910 //=======================================================================
2911 void GetVerticesOnEdges(const TopoDS_Shape& theCB,
2912 const TopTools_MapOfShape& theEdges,
2913 TopTools_MapOfShape& theVerticesOnEdges,
2914 TopTools_MapOfShape& theAllVertices)
2916 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
2917 for (; aExp.More(); aExp.Next()) {
2918 const TopoDS_Shape& aE = aExp.Current();
2919 Standard_Boolean bOnGivenEdge = theEdges.Contains(aE);
2920 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
2921 theAllVertices.Add(aItV.Value());
2923 theVerticesOnEdges.Add(aItV.Value());
2929 //=======================================================================
2930 //function : RemoveInvalidSplitsByInvertedEdges
2931 //purpose : Looking for the invalid faces containing inverted edges
2932 // that can be safely removed
2933 //=======================================================================
2934 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
2935 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2936 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
2937 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2938 TopTools_IndexedMapOfShape& theMERemoved)
2940 if (theMEInverted.IsEmpty()) {
2944 // check the faces on regularity, i.e. the splits of the same face
2945 // should not be connected only by vertex. Such irregular splits
2946 // will have to be rebuilt and cannot be removed.
2949 TopTools_IndexedMapOfShape aMEAvoid;
2950 TopTools_DataMapOfShapeListOfShape aDMVF;
2951 Standard_Integer aNb = theFImages.Extent(), i;
2952 for (i = 1; i <= aNb; ++i) {
2953 const TopTools_ListOfShape& aLFIm = theFImages(i);
2955 TopoDS_Compound aCFIm;
2956 aBB.MakeCompound(aCFIm);
2958 TopTools_DataMapOfShapeListOfShape aDMEF;
2959 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
2960 for (; aIt.More(); aIt.Next()) {
2961 const TopoDS_Shape& aF = aIt.Value();
2964 // make a map to use only outer edges
2965 TopExp_Explorer aExp(aF, TopAbs_EDGE);
2966 for (; aExp.More(); aExp.Next()) {
2967 const TopoDS_Shape& aE = aExp.Current();
2969 TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE);
2971 pLF = aDMEF.Bound(aE, TopTools_ListOfShape());
2974 // internal edges should not be used
2977 AppendToList(*pLF, aF);
2980 // fill connection map of the vertices of inverted edges to faces
2981 aExp.Init(aF, TopAbs_VERTEX);
2982 for (; aExp.More(); aExp.Next()) {
2983 const TopoDS_Shape& aV = aExp.Current();
2985 TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV);
2987 pLF = aDMVF.Bound(aV, TopTools_ListOfShape());
2989 AppendToList(*pLF, aF);
2993 // for the splits to be regular they should form only one block
2994 TopTools_ListOfShape aLCBF;
2995 BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
2996 if (aLCBF.Extent() == 1) {
3000 // check if the inverted edges create the irregularity
3001 BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll;
3003 TopTools_ListIteratorOfListOfShape aItLCB(aLCBF);
3004 for (; aItLCB.More(); aItLCB.Next()) {
3005 const TopoDS_Shape& aCB = aItLCB.Value();
3007 // check if it is possible to remove the block
3008 if (!CheckInvertedBlock(aCB, aLCBF, theMEInverted, theOEOrigins, aDMCBVInverted, aDMCBVAll)) {
3009 // non of the edges in this block should be removed
3010 TopExp::MapShapes(aCB, TopAbs_EDGE, aMEAvoid);
3016 // all edges not included in aMEAvoid can be removed
3017 TopTools_MapOfShape aMERem;
3018 TopTools_MapIteratorOfMapOfShape aItM(theMEInverted);
3019 for (; aItM.More(); aItM.Next()) {
3020 const TopoDS_Shape& aE = aItM.Value();
3021 if (!aMEAvoid.Contains(aE)) {
3022 TopoDS_Iterator aIt(aE);
3023 for (; aIt.More(); aIt.Next()) {
3024 const TopoDS_Shape& aV = aIt.Value();
3025 const TopTools_ListOfShape *pLF = aDMVF.Seek(aV);
3026 if (pLF && (pLF->Extent() > 3)) {
3034 if (aMERem.IsEmpty()) {
3038 // all invalid faces containing these edges can be removed
3039 TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
3040 TopTools_MapOfShape aMFRem;
3041 TopTools_IndexedMapOfShape aMFToUpdate;
3042 aNb = theInvFaces.Extent();
3043 for (i = 1; i <= aNb; ++i) {
3044 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3045 TopTools_ListOfShape& aLFIm = theInvFaces(i);
3047 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3048 for (; aIt.More(); ) {
3049 const TopoDS_Shape& aFIm = aIt.Value();
3051 // to be removed the face should have at least two not connected
3053 TopoDS_Compound aCEInv;
3054 aBB.MakeCompound(aCEInv);
3055 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
3056 for (; aExp.More(); aExp.Next()) {
3057 const TopoDS_Shape& aE = aExp.Current();
3058 if (aMERem.Contains(aE)) {
3059 aBB.Add(aCEInv, aE);
3063 // check connectivity
3064 TopTools_ListOfShape aLCBE;
3065 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
3067 if (aLCBE.Extent() >= 2) {
3068 aMFToUpdate.Add(aF);
3077 if (aLFIm.Extent()) {
3078 aInvFaces.Add(aF, aLFIm);
3082 if (aMFRem.IsEmpty()) {
3086 theInvFaces = aInvFaces;
3087 // remove from splits
3088 aNb = aMFToUpdate.Extent();
3089 for (i = 1; i <= aNb; ++i) {
3090 const TopoDS_Shape& aF = aMFToUpdate(i);
3091 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
3093 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3094 for (; aIt.More(); ) {
3095 const TopoDS_Shape& aFIm = aIt.Value();
3096 if (aMFRem.Contains(aFIm)) {
3097 TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved);
3107 //=======================================================================
3108 //function : RemoveInvalidSplitsFromValid
3109 //purpose : Removing invalid splits of faces from valid
3110 //=======================================================================
3111 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3112 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3113 const TopTools_MapOfShape& theMEInverted,
3114 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
3115 TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
3117 // Decide whether to remove the found invalid faces or not.
3118 // The procedure is the following:
3119 // 1. Make connexity blocks from invalid faces;
3120 // 2. Find free edges in this blocks;
3121 // 3. If all free edges are valid for the faces - remove block.
3123 TopTools_MapOfShape aMFence, aMFToRem;
3124 TopoDS_Compound aCFInv;
3126 aBB.MakeCompound(aCFInv);
3127 TopTools_ListIteratorOfListOfShape aItLF;
3129 // make compound of invalid faces
3130 TopTools_DataMapOfShapeShape aDMIFOF;
3131 Standard_Integer i, aNb = theInvFaces.Extent();
3132 for (i = 1; i <= aNb; ++i) {
3133 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3134 // artificially invalid faces should not be removed
3135 if (theArtInvFaces.IsBound(aF)) {
3138 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
3139 aItLF.Initialize(aLFInv);
3140 for (; aItLF.More(); aItLF.Next()) {
3141 const TopoDS_Shape& aFIm = aItLF.Value();
3142 if (aMFence.Add(aFIm)) {
3143 aBB.Add(aCFInv, aFIm);
3144 aDMIFOF.Bind(aFIm, aF);
3149 // make connexity blocks
3150 TopTools_ListOfShape aLCBInv;
3151 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
3153 // analyze each block
3154 aItLF.Initialize(aLCBInv);
3155 for (; aItLF.More(); aItLF.Next()) {
3156 const TopoDS_Shape& aCB = aItLF.Value();
3158 // if connexity block contains only one face - it should be removed;
3159 TopExp_Explorer aExp(aCB, TopAbs_FACE);
3162 // check if there are valid images left
3163 aExp.Init(aCB, TopAbs_FACE);
3164 for (; aExp.More(); aExp.Next()) {
3165 const TopoDS_Shape& aFIm = aExp.Current();
3166 const TopoDS_Shape& aF = aDMIFOF.Find(aFIm);
3168 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
3169 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
3171 if (aLFIm.Extent() == aLFInv.Extent()) {
3178 aExp.Init(aCB, TopAbs_FACE);
3179 for (; aExp.More(); aExp.Next()) {
3180 const TopoDS_Shape& aF = aExp.Current();
3186 // remove faces connected by inverted edges
3187 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3188 TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3190 TopTools_DataMapOfShapeListOfShape aDMFF;
3191 aExp.Init(aCB, TopAbs_FACE);
3192 for (; aExp.More(); aExp.Next()) {
3193 const TopoDS_Shape& aFCB = aExp.Current();
3194 const TopoDS_Shape& aF = aDMIFOF.Find (aFCB);
3195 TopTools_ListOfShape* pList = aDMFF.ChangeSeek (aF);
3197 pList = aDMFF.Bound (aF, TopTools_ListOfShape());
3198 pList->Append (aFCB);
3201 for (TopTools_DataMapOfShapeListOfShape::Iterator itM (aDMFF); itM.More(); itM.Next())
3203 const TopoDS_Shape& aF = itM.Key();
3204 const TopTools_MapOfShape* pValidInverted = theDMFMVIE.Seek (aF);
3206 // either remove all of these faces or none.
3207 const TopTools_ListOfShape& aLFCB = itM.Value();
3208 TopTools_ListOfShape::Iterator itL (aLFCB);
3209 for (; itL.More(); itL.Next())
3211 const TopoDS_Shape& aFCB = itL.Value();
3212 TopExp_Explorer aExpE(aFCB, TopAbs_EDGE);
3213 for (; aExpE.More(); aExpE.Next()) {
3214 const TopoDS_Shape& aECB = aExpE.Current();
3215 if (pValidInverted && pValidInverted->Contains (aECB))
3217 if (aDMEF.FindFromKey(aECB).Extent() > 1)
3219 if (!theMEInverted.Contains(aECB))
3224 // if one removed - remove all
3229 for (itL.Initialize (aLFCB); itL.More(); itL.Next())
3231 aMFToRem.Add (itL.Value());
3237 if (aMFToRem.Extent()) {
3238 // remove invalid faces from images
3239 aNb = theInvFaces.Extent();
3240 for (i = 1; i <= aNb; ++i) {
3241 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3242 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
3243 aItLF.Initialize(aLFImages);
3244 for (; aItLF.More();) {
3245 const TopoDS_Shape& aFIm = aItLF.Value();
3246 if (aMFToRem.Contains(aFIm)) {
3247 aLFImages.Remove(aItLF);
3259 //=======================================================================
3260 //function : buildPairs
3261 //purpose : builds pairs of shapes
3262 //=======================================================================
3263 static void buildPairs (const TopTools_IndexedMapOfShape& theSMap,
3264 BRepOffset_DataMapOfShapeMapOfShape& theIntPairs)
3266 const Standard_Integer aNbS = theSMap.Extent();
3269 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3271 const TopoDS_Shape& aS = theSMap (it1);
3272 if (!theIntPairs.IsBound (aS))
3273 theIntPairs.Bind (aS, TopTools_MapOfShape());
3276 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3278 const TopoDS_Shape& aS1 = theSMap (it1);
3279 TopTools_MapOfShape& aMap1 = theIntPairs (aS1);
3280 for (Standard_Integer it2 = it1 + 1; it2 <= aNbS; ++it2)
3282 const TopoDS_Shape& aS2 = theSMap (it2);
3284 theIntPairs (aS2).Add (aS1);
3289 //=======================================================================
3290 //function : buildIntersectionPairs
3291 //purpose : builds intersection pairs
3292 //=======================================================================
3293 static void buildIntersectionPairs (const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3294 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3295 const BOPAlgo_Builder& theBuilder,
3296 const TopTools_MapOfShape& theMFRemoved,
3297 const TopTools_DataMapOfShapeShape& theFOrigins,
3298 NCollection_DataMap<TopoDS_Shape,
3299 BRepOffset_DataMapOfShapeMapOfShape,
3300 TopTools_ShapeMapHasher>& theIntPairs)
3302 TopAbs_ShapeEnum aCType = TopAbs_VERTEX;
3303 // Build connection map from vertices to faces
3304 TopTools_IndexedDataMapOfShapeListOfShape aDMVF;
3305 TopExp::MapShapesAndAncestors (theBuilder.Shape(), aCType, TopAbs_FACE, aDMVF);
3307 const TopTools_DataMapOfShapeListOfShape& anImages = theBuilder.Images();
3308 const TopTools_DataMapOfShapeListOfShape& anOrigins = theBuilder.Origins();
3310 // Find all faces connected to the not removed faces and build intersection pairs among them.
3311 // For removed faces intersect only those connected to each other.
3313 for (Standard_Integer iF = 1; iF <= theInvFaces.Extent(); ++iF)
3315 const TopoDS_Shape& aFInv = theInvFaces.FindKey (iF);
3317 TopoDS_Compound aCF, aCFRem;
3318 BRep_Builder().MakeCompound (aCF);
3319 BRep_Builder().MakeCompound (aCFRem);
3321 for (Standard_Integer iC = 0; iC < 2; ++iC)
3323 const TopTools_ListOfShape& aLF = !iC ? theInvFaces (iF) : theFImages.FindFromKey (aFInv);
3325 for (TopTools_ListOfShape::Iterator it (aLF); it.More(); it.Next())
3327 TopTools_ListOfShape aLFIm;
3328 TakeModified (it.Value(), anImages, aLFIm);
3330 for (TopTools_ListOfShape::Iterator itIm (aLFIm); itIm.More(); itIm.Next())
3332 const TopoDS_Shape& aFIm = itIm.Value();
3334 if (theMFRemoved.Contains (aFIm))
3335 BRep_Builder().Add (aCFRem, aFIm);
3337 BRep_Builder().Add (aCF, aFIm);
3342 TopTools_ListOfShape aLCB;
3343 BOPTools_AlgoTools::MakeConnexityBlocks (aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
3348 BRepOffset_DataMapOfShapeMapOfShape* pFInterMap =
3349 theIntPairs.Bound (aFInv, BRepOffset_DataMapOfShapeMapOfShape());
3351 // build pairs for not removed faces
3352 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3354 const TopoDS_Shape& aCB = itCB.Value();
3356 TopTools_IndexedMapOfShape aMFInter;
3357 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3359 const TopoDS_Shape& aCS = exp.Current();
3360 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3364 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3366 const TopoDS_Shape& aFConnected = itFV.Value();
3368 TopTools_ListOfShape aLFOr;
3369 TakeModified (aFConnected, anOrigins, aLFOr);
3370 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3372 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3374 aMFInter.Add (*pFOr);
3379 // build intersection pairs
3380 buildPairs (aMFInter, *pFInterMap);
3384 BOPTools_AlgoTools::MakeConnexityBlocks (aCFRem, TopAbs_EDGE, TopAbs_FACE, aLCB);
3389 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3391 const TopoDS_Shape& aCB = itCB.Value();
3393 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3394 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3396 const TopoDS_Shape& aCS = exp.Current();
3397 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3401 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3403 const TopoDS_Shape& aFConnected = itFV.Value();
3404 TopExp::MapShapesAndAncestors (aFConnected, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3408 for (Standard_Integer iE = 1; iE <= aDMEF.Extent(); ++iE)
3410 const TopTools_ListOfShape& aLFConnected = aDMEF (iE);
3411 if (aLFConnected.Extent() < 2)
3414 TopTools_IndexedMapOfShape aMFInter;
3415 for (TopTools_ListOfShape::Iterator itLF (aLFConnected); itLF.More(); itLF.Next())
3417 const TopoDS_Shape& aFConnected = itLF.Value();
3419 TopTools_ListOfShape aLFOr;
3420 TakeModified (aFConnected, anOrigins, aLFOr);
3421 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3423 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3425 aMFInter.Add (*pFOr);
3429 buildPairs (aMFInter, *pFInterMap);
3437 //=======================================================================
3438 //function : RemoveInsideFaces
3439 //purpose : Looking for the inside faces that can be safely removed
3440 //=======================================================================
3441 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3442 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3443 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3444 const TopTools_IndexedMapOfShape& theInvEdges,
3445 const TopTools_MapOfShape& theInvertedEdges,
3446 const TopTools_ListOfShape& theInvertedFaces,
3447 const TopTools_IndexedMapOfShape& theMFToCheckInt,
3448 const TopTools_IndexedMapOfShape& theMFInvInHole,
3449 const TopoDS_Shape& theFHoles,
3450 BRepOffset_MakeOffset_InterResults& theIntRes,
3451 TopTools_IndexedMapOfShape& theMERemoved,
3452 TopTools_IndexedMapOfShape& theMEInside,
3453 TopoDS_Shape& theSolids)
3455 TopTools_ListOfShape aLS;
3456 TopTools_MapOfShape aMFence;
3457 TopTools_IndexedMapOfShape aMFInv;
3458 TopTools_ListIteratorOfListOfShape aItLF;
3459 TopTools_DataMapOfShapeShape aDMFImF;
3461 Standard_Integer i, aNb = theFImages.Extent();
3462 for (i = 1; i <= aNb; ++i) {
3463 const TopoDS_Shape& aF = theFImages.FindKey(i);
3464 // to avoid intersection of the splits of the same
3465 // offset faces among themselves make compound of the
3466 // splits and use it as one argument
3467 TopoDS_Compound aCFImi;
3468 BRep_Builder().MakeCompound(aCFImi);
3470 for (Standard_Integer j = 0; j < 2; ++j) {
3471 const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i);
3476 aItLF.Initialize(*pLFSp);
3477 for (; aItLF.More(); aItLF.Next()) {
3478 const TopoDS_Shape& aFIm = aItLF.Value();
3479 if (aMFence.Add(aFIm)) {
3480 BRep_Builder().Add(aCFImi, aFIm);
3481 aDMFImF.Bind(aFIm, aF);
3492 // to make the solids more complete add for intersection also the faces
3493 // consisting only of invalid edges and not included into splits
3494 aNb = theMFToCheckInt.Extent();
3495 for (i = 1; i <= aNb; ++i) {
3496 const TopoDS_Shape& aFSp = theMFToCheckInt(i);
3497 if (aMFence.Add(aFSp)) {
3502 BOPAlgo_MakerVolume aMV;
3503 aMV.SetArguments(aLS);
3504 aMV.SetIntersect(Standard_True);
3506 if (aMV.HasErrors())
3510 // get shapes connection for using in the rebuilding process
3511 // for the cases in which some of the intersection left undetected
3512 ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theIntRes.SSInterfs);
3514 // find faces to remove
3515 const TopoDS_Shape& aSols = aMV.Shape();
3517 TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
3518 TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
3520 aNb = aDMFS.Extent();
3525 // To use the created solids for classifications, firstly, it is necessary
3526 // to check them on validity - the created solids should be complete,
3527 // i.e. all faces should be included.
3529 TopTools_MapOfShape aMFToRem;
3530 // Check completeness
3531 if (aMV.HasDeleted()) {
3532 TopTools_IndexedMapOfShape aMEHoles;
3533 TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles);
3535 // Map edges of the solids to check the connectivity
3536 // of the removed invalid splits
3537 TopTools_IndexedMapOfShape aMESols;
3538 TopExp::MapShapes(aSols, TopAbs_EDGE, aMESols);
3540 // perform additional check on faces
3541 aNb = theFImages.Extent();
3542 for (i = 1; i <= aNb; ++i) {
3543 const TopTools_ListOfShape& aLFIm = theFImages(i);
3544 if (aLFIm.IsEmpty()) {
3548 const TopoDS_Shape& aF = theFImages.FindKey(i);
3549 Standard_Boolean bInvalid = theInvFaces.Contains(aF);
3550 // For invalid faces it is allowed to be at least connected
3551 // to the solids, otherwise the solids are considered as broken
3552 Standard_Boolean bConnected = Standard_False;
3554 Standard_Boolean bFaceKept = Standard_False;
3555 aItLF.Initialize(aLFIm);
3556 for (; aItLF.More(); aItLF.Next()) {
3557 const TopoDS_Shape& aFIm = aItLF.Value();
3558 if (!aMV.IsDeleted(aFIm)) {
3559 bFaceKept = Standard_True;
3563 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
3564 for (; aExpE.More(); aExpE.Next()) {
3565 if (aMEHoles.Contains(aExpE.Current())) {
3566 bFaceKept = Standard_True;
3570 if (!bFaceKept && bInvalid && !bConnected)
3571 bConnected = aMESols.Contains(aExpE.Current());
3575 if (!bFaceKept && !bConnected) {
3581 TopTools_IndexedMapOfShape aMEBoundary;
3582 aNb = aDMFS.Extent();
3583 for (i = 1; i <= aNb; ++i) {
3584 const TopoDS_Shape& aFIm = aDMFS.FindKey(i);
3585 const TopTools_ListOfShape& aLSol = aDMFS(i);
3586 if (aLSol.Extent() > 1) {
3589 else if (aFIm.Orientation() != TopAbs_INTERNAL) {
3590 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary);
3594 // Tool for getting the splits of faces
3595 const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
3597 // update invalid faces with images
3598 aNb = aMFInv.Extent();
3599 for (i = 1; i <= aNb; ++i) {
3600 const TopoDS_Shape& aFInv = aMFInv(i);
3601 TakeModified(aFInv, aMVIms, aMFInv);
3604 // Take into account the faces invalid by inverted edges
3605 for (TopTools_ListOfShape::Iterator itLF(theInvertedFaces); itLF.More(); itLF.Next())
3606 TakeModified(itLF.Value(), aMVIms, aMFInv);
3608 // check if the invalid faces inside the holes are really invalid:
3609 // check its normal direction - if it has changed relatively the
3610 // original face the offset face is invalid and should be kept for rebuilding
3611 Standard_Integer aNbFH = theMFInvInHole.Extent();
3612 for (i = 1; i <= aNbFH; ++i) {
3613 const TopoDS_Shape& aFInv = theMFInvInHole(i);
3614 TopTools_ListOfShape aLFInvIm = aMV.Modified(aFInv);
3615 if (aLFInvIm.IsEmpty()) {
3616 aLFInvIm.Append(aFInv);
3619 const TopoDS_Shape *pFOffset = aDMFImF.Seek(aFInv);
3623 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInvIm);
3624 for (; aItLFInv.More(); aItLFInv.Next()) {
3625 const TopoDS_Shape& aFInvIm = aItLFInv.Value();
3626 const TopTools_ListOfShape* pLSols = aDMFS.Seek(aFInvIm);
3627 if (!pLSols || pLSols->Extent() != 1) {
3631 const TopoDS_Shape& aFSol = pLSols->First();
3634 if (!FindShape(aFInvIm, aFSol, NULL, aFx)) {
3638 if (BRepOffset_Tool::CheckPlanesNormals(TopoDS::Face(aFx), TopoDS::Face(*pFOffset))) {
3639 // the normal direction has not changed, thus the face can be removed
3640 aMFToRem.Add(aFInvIm);
3645 TopoDS_Compound aSolids;
3646 BRep_Builder().MakeCompound(aSolids);
3647 TopTools_MapOfShape aMFKeep;
3649 TopExp_Explorer aExpS(aSols, TopAbs_SOLID);
3650 for (; aExpS.More(); aExpS.Next()) {
3651 const TopoDS_Shape& aSol = aExpS.Current();
3653 Standard_Boolean bAllInv(Standard_True), bAllRemoved(Standard_True);
3655 for (TopExp_Explorer aExpF(aSol, TopAbs_FACE); aExpF.More(); aExpF.Next())
3657 const TopoDS_Shape& aFS = aExpF.Current();
3659 if (aFS.Orientation() == TopAbs_INTERNAL) {
3664 if (aMFToRem.Contains(aFS))
3667 bAllRemoved = false;
3668 bAllInv &= aMFInv.Contains(aFS);
3671 if (bAllInv && !bAllRemoved) {
3672 // remove invalid faces but keep those that have already been marked for removal
3673 TopExp_Explorer aExpF(aSol, TopAbs_FACE);
3674 for (; aExpF.More(); aExpF.Next()) {
3675 const TopoDS_Shape& aFS = aExpF.Current();
3677 if (aMFToRem.Contains(aFS)) {
3678 if (!aMFKeep.Add(aFS)) {
3679 aMFKeep.Remove(aFS);
3688 BRep_Builder().Add(aSolids, aSol);
3689 theSolids = aSolids;
3693 TopTools_MapIteratorOfMapOfShape aItM(aMFKeep);
3694 for (; aItM.More(); aItM.Next()) {
3695 aMFToRem.Remove(aItM.Value());
3698 // Remove the invalid hanging parts external to the solids
3699 RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, theInvertedEdges, aMFToRem);
3701 // Remove newly found internal and hanging faces
3702 RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
3703 RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
3705 // Get inside faces from the removed ones comparing them with boundary edges
3706 aNb = theMERemoved.Extent();
3707 for (i = 1; i <= aNb; ++i) {
3708 const TopoDS_Shape& aE = theMERemoved(i);
3709 if (!aMEBoundary.Contains(aE)) {
3710 theMEInside.Add(aE);
3714 // build all possible intersection pairs basing on the intersection results
3715 // taking into account removed faces.
3716 if (aMFToRem.Extent())
3717 buildIntersectionPairs (theFImages, theInvFaces, aMV, aMFToRem, aDMFImF, theIntRes.InterPairs);
3720 //=======================================================================
3721 //function : ShapesConnections
3722 //purpose : Looking for the connections between faces not to miss
3723 // some necessary intersection
3724 //=======================================================================
3725 void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3726 const TopTools_IndexedMapOfShape& theInvEdges,
3727 const TopTools_DataMapOfShapeShape& theDMFOr,
3728 BOPAlgo_Builder& theBuilder,
3729 TopTools_DataMapOfShapeListOfShape& theSSInterfs)
3731 // update invalid edges with images and keep connection to original edge
3732 TopTools_DataMapOfShapeListOfShape aDMEOr;
3733 Standard_Integer aNb = theInvEdges.Extent();
3734 for (Standard_Integer i = 1; i <= aNb; ++i) {
3735 const TopoDS_Shape& aEInv = theInvEdges(i);
3736 const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv);
3737 if (aLEIm.IsEmpty()) {
3738 aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv);
3742 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
3743 for (; aItLEIm.More(); aItLEIm.Next()) {
3744 const TopoDS_Shape& aEIm = aItLEIm.Value();
3746 TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm);
3748 pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape());
3750 AppendToList(*pLEOr, aEInv);
3754 // get shapes connections for using in the rebuilding process
3755 const BOPDS_PDS& pDS = theBuilder.PDS();
3756 // analyze all Face/Face intersections
3757 const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
3758 Standard_Integer iInt, aNbFF = aFFs.Length();
3759 for (iInt = 0; iInt < aNbFF; ++iInt) {
3760 const BOPDS_InterfFF& aFF = aFFs(iInt);
3761 const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
3762 Standard_Integer aNbC = aVNC.Length();
3767 const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1());
3768 const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2());
3770 const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1);
3771 const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2);
3777 if (pF1->IsSame(*pF2)) {
3781 Standard_Boolean bInv1 = theInvFaces.Contains(*pF1);
3782 Standard_Boolean bInv2 = theInvFaces.Contains(*pF2);
3784 if (!bInv1 && !bInv2) {
3788 // check if it is real Face/Face intersection
3789 TopTools_MapOfShape aMEInt;
3790 for (Standard_Integer iC = 0; iC < aNbC; ++iC) {
3791 const BOPDS_Curve& aNC = aVNC(iC);
3792 const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
3793 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
3794 for (; aItLPB.More(); aItLPB.Next()) {
3795 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
3796 Standard_Integer nEInt;
3797 if (aPB->HasEdge(nEInt)) {
3798 const TopoDS_Shape& aEInt = pDS->Shape(nEInt);
3804 if (aMEInt.IsEmpty()) {
3808 // check if invalid edges of the face are in the same splits with intersection edges
3809 for (Standard_Integer i = 0; i < 2; ++i) {
3810 if ((!i && !bInv1) || (i && !bInv2)) {
3814 const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
3815 const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
3816 const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
3818 Standard_Boolean bFound = Standard_False;
3820 TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm);
3821 if (aLFIm.IsEmpty()) {
3825 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
3826 for (; aItLFIm.More(); aItLFIm.Next()) {
3827 const TopoDS_Shape& aFImIm = aItLFIm.Value();
3829 Standard_Boolean bInv(Standard_False), bInt(Standard_False);
3830 TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE);
3831 for (; aExpE.More(); aExpE.Next()) {
3832 const TopoDS_Shape& aE = aExpE.Current();
3834 bInv = aDMEOr.IsBound(aE);
3837 bInt = aMEInt.Contains(aE);
3844 if (!bInt || !bInv) {
3848 bFound = Standard_True;
3850 // append opposite face to all invalid edges in the split
3851 aExpE.Init(aFImIm, TopAbs_EDGE);
3852 for (; aExpE.More(); aExpE.Next()) {
3853 const TopoDS_Shape& aE = aExpE.Current();
3854 const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE);
3859 TopTools_ListIteratorOfListOfShape aItLE(*pLEOr);
3860 for (; aItLE.More(); aItLE.Next()) {
3861 const TopoDS_Shape& aEOr = aItLE.Value();
3862 TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr);
3864 pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape());
3866 AppendToList(*pLFE, aFOp);
3871 // save connection between offset faces
3872 TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF);
3874 pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape());
3876 AppendToList(*pLF, aFOp);
3882 //=======================================================================
3883 //function : RemoveHangingParts
3884 //purpose : Remove isolated invalid hanging parts
3885 //=======================================================================
3886 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
3887 const TopTools_DataMapOfShapeShape& theDMFImF,
3888 const TopTools_IndexedMapOfShape& theMFInv,
3889 const TopTools_IndexedMapOfShape& theInvEdges,
3890 const TopTools_MapOfShape& theInvertedEdges,
3891 TopTools_MapOfShape& theMFToRem)
3893 // Map the faces of the result solids to filter them from avoided faces
3894 TopTools_IndexedMapOfShape aMFS;
3895 TopExp::MapShapes(theMV.Shape(), TopAbs_FACE, aMFS);
3898 // Build compound of all faces not included into solids
3899 TopoDS_Compound aCFHangs;
3900 aBB.MakeCompound(aCFHangs);
3902 // Tool for getting the splits of faces
3903 const TopTools_DataMapOfShapeListOfShape& aMVIms = theMV.Images();
3905 TopTools_ListIteratorOfListOfShape aItLArgs(theMV.Arguments());
3906 for (; aItLArgs.More(); aItLArgs.Next())
3908 TopExp_Explorer anExpF(aItLArgs.Value(), TopAbs_FACE);
3909 for (; anExpF.More(); anExpF.Next())
3911 const TopoDS_Shape& aF = anExpF.Current();
3912 TakeModified(aF, aMVIms, aCFHangs, &aMFS);
3916 // Make connexity blocks of all hanging parts and check that they are isolated
3917 TopTools_ListOfShape aLCBHangs;
3918 BOPTools_AlgoTools::MakeConnexityBlocks(aCFHangs, TopAbs_EDGE, TopAbs_FACE, aLCBHangs);
3919 if (aLCBHangs.IsEmpty())
3922 // To be removed, the block should contain invalid splits of offset faces and should
3923 // meet one of the following conditions:
3924 // 1. The block should not be connected to any invalid parts (Faces or Edges)
3925 // contained in solids;
3926 // 2. The block should be isolated from other faces, i.e. it should consist of
3927 // the splits of the single offset face.
3929 // Map the edges and vertices of the result solids to check connectivity
3930 // of the hanging blocks to invalid parts contained in solids
3931 TopTools_IndexedDataMapOfShapeListOfShape aDMEF, aDMVE;
3932 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_EDGE , TopAbs_FACE, aDMEF);
3933 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
3935 // Update invalid edges with intersection results
3936 TopTools_MapOfShape aMEInv;
3937 Standard_Integer i, aNbE = theInvEdges.Extent();
3938 for (i = 1; i <= aNbE; ++i)
3939 TakeModified(theInvEdges(i), aMVIms, aMEInv);
3941 // Update inverted edges with intersection results
3942 TopTools_MapOfShape aMEInverted;
3943 for (TopTools_MapIteratorOfMapOfShape itM(theInvertedEdges); itM.More(); itM.Next())
3944 TakeModified(itM.Value(), aMVIms, aMEInverted);
3946 // Tool for getting the origins of the splits
3947 const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
3949 // Find hanging blocks to remove
3950 TopTools_ListOfShape aBlocksToRemove;
3952 TopTools_ListIteratorOfListOfShape aItLCBH(aLCBHangs);
3953 for (; aItLCBH.More(); aItLCBH.Next())
3955 const TopoDS_Shape& aCBH = aItLCBH.Value();
3957 // Remove the block containing the inverted edges
3958 Standard_Boolean bHasInverted = Standard_False;
3959 TopExp_Explorer anExpE(aCBH, TopAbs_EDGE);
3960 for (; anExpE.More() && !bHasInverted; anExpE.Next())
3962 const TopoDS_Shape& aE = anExpE.Current();
3963 bHasInverted = !aDMEF .Contains(aE) &&
3964 aMEInverted.Contains(aE);
3969 aBlocksToRemove.Append(aCBH);
3973 // Check the block to contain invalid split
3974 Standard_Boolean bHasInvalidFace = Standard_False;
3975 // Check connectivity to invalid parts
3976 Standard_Boolean bIsConnected = Standard_False;
3977 TopTools_IndexedMapOfShape aBlockME;
3978 TopExp::MapShapes(aCBH, TopAbs_EDGE, aBlockME);
3979 // Map to collect all original faces
3980 TopTools_MapOfShape aMOffsetF;
3982 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
3983 for (; anExpF.More(); anExpF.Next())
3985 const TopoDS_Shape& aF = anExpF.Current();
3986 // Check block to contain invalid face
3987 if (!bHasInvalidFace)
3988 bHasInvalidFace = theMFInv.Contains(aF);
3990 // Check block for connectivity to invalid parts
3994 anExpE.Init(aF, TopAbs_EDGE);
3995 for (; anExpE.More() && !bIsConnected; anExpE.Next())
3997 const TopoDS_Shape& aE = anExpE.Current();
3998 const TopTools_ListOfShape *pLF = aDMEF.Seek(aE);
4001 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
4002 for (; aItLF.More() && !bIsConnected; aItLF.Next())
4003 bIsConnected = theMFInv.Contains(aItLF.Value());
4009 TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
4010 for (; anExpV.More() && !bIsConnected; anExpV.Next())
4012 const TopoDS_Shape& aV = anExpV.Current();
4013 const TopTools_ListOfShape *pLE = aDMVE.Seek(aV);
4016 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
4017 for (; aItLE.More() && !bIsConnected; aItLE.Next())
4018 bIsConnected = !aBlockME.Contains(aItLE.Value()) &&
4019 aMEInv .Contains(aItLE.Value());
4025 // Check block to be isolated
4026 const TopTools_ListOfShape* pLFOr = aMVOrs.Seek(aF);
4029 TopTools_ListIteratorOfListOfShape aItLFOr(*pLFOr);
4030 for (; aItLFOr.More(); aItLFOr.Next())
4032 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aItLFOr.Value());
4034 aMOffsetF.Add(*pFOffset);
4039 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aF);
4041 aMOffsetF.Add(*pFOffset);
4045 Standard_Boolean bRemove = bHasInvalidFace &&
4046 (!bIsConnected || aMOffsetF.Extent() == 1);
4049 aBlocksToRemove.Append(aCBH);
4052 // remove the invalidated blocks
4053 aItLCBH.Initialize(aBlocksToRemove);
4054 for (; aItLCBH.More(); aItLCBH.Next())
4056 const TopoDS_Shape& aCBH = aItLCBH.Value();
4057 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
4058 for (; anExpF.More(); anExpF.Next())
4059 theMFToRem.Add(anExpF.Current());
4063 //=======================================================================
4064 //function : RemoveValidSplits
4065 //purpose : Removing valid splits according to results of intersection
4066 //=======================================================================
4067 void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
4068 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
4069 BOPAlgo_Builder& theGF,
4070 TopTools_IndexedMapOfShape& theMERemoved)
4072 Standard_Integer i, aNb = theImages.Extent();
4077 for (i = 1; i <= aNb; ++i) {
4078 TopTools_ListOfShape& aLSIm = theImages(i);
4079 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
4080 for (; aIt.More(); ) {
4081 const TopoDS_Shape& aSIm = aIt.Value();
4082 if (theSpRem.Contains(aSIm)) {
4083 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4088 // check if all its images are have to be removed
4089 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
4090 if (aLSImIm.Extent()) {
4091 Standard_Boolean bAllRem = Standard_True;
4092 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
4093 for (; aIt1.More(); aIt1.Next()) {
4094 const TopoDS_Shape& aSImIm = aIt1.Value();
4095 if (theSpRem.Contains(aSImIm)) {
4096 TopExp::MapShapes(aSImIm, TopAbs_EDGE, theMERemoved);
4099 bAllRem = Standard_False;
4104 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4114 //=======================================================================
4115 //function : RemoveInvalidSplits
4116 //purpose : Removing invalid splits according to the results of intersection
4117 //=======================================================================
4118 void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
4119 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4120 const TopTools_IndexedMapOfShape& theInvEdges,
4121 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
4122 BOPAlgo_Builder& theGF,
4123 TopTools_IndexedMapOfShape& theMERemoved)
4125 Standard_Integer i, aNb = theImages.Extent();
4130 for (i = 1; i <= aNb; ++i) {
4131 const TopoDS_Shape& aS = theImages.FindKey(i);
4132 Standard_Boolean bArt = theArtInvFaces.IsBound(aS);
4134 TopTools_ListOfShape& aLSIm = theImages(i);
4135 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
4136 for (; aIt.More();) {
4137 const TopoDS_Shape& aSIm = aIt.Value();
4138 if (theSpRem.Contains(aSIm)) {
4139 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4144 // check if all its images are have to be removed
4145 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
4146 if (aLSImIm.IsEmpty()) {
4151 Standard_Boolean bAllRem = Standard_True;
4152 TopTools_IndexedMapOfShape aMERemoved;
4153 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
4154 for (; aIt1.More(); aIt1.Next()) {
4155 const TopoDS_Shape& aSImIm = aIt1.Value();
4156 if (theSpRem.Contains(aSImIm)) {
4157 TopExp::MapShapes(aSImIm, TopAbs_EDGE, aMERemoved);
4160 bAllRem = Standard_False;
4174 // remove the face from invalid if all invalid edges of this face
4175 // have been marked for removal
4176 TopExp_Explorer aExpE(aSIm, TopAbs_EDGE);
4177 for (; aExpE.More(); aExpE.Next()) {
4178 const TopoDS_Shape& aEInv = aExpE.Current();
4179 if (theInvEdges.Contains(aEInv) && !aMERemoved.Contains(aEInv)) {
4183 if (!aExpE.More()) {
4184 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4194 //=======================================================================
4195 //function : FilterEdgesImages
4196 //purpose : Updating the maps of images and origins of the offset edges
4197 //=======================================================================
4198 void FilterEdgesImages(const TopoDS_Shape& theS,
4199 TopTools_DataMapOfShapeListOfShape& theOEImages,
4200 TopTools_DataMapOfShapeListOfShape& theOEOrigins)
4203 TopTools_IndexedMapOfShape aME;
4204 TopExp::MapShapes(theS, TopAbs_EDGE, aME);
4206 theOEOrigins.Clear();
4207 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(theOEImages);
4208 for (; aItDM.More(); aItDM.Next()) {
4209 const TopoDS_Shape& aE = aItDM.Key();
4210 TopTools_ListOfShape& aLEIm = aItDM.ChangeValue();
4212 TopTools_ListIteratorOfListOfShape aIt(aLEIm);
4213 for (; aIt.More(); ) {
4214 const TopoDS_Shape& aEIm = aIt.Value();
4216 if (!aME.Contains(aEIm)) {
4218 // edges with no images left should be kept in the map
4219 // to avoid their usage when building the splits of faces
4225 if (theOEOrigins.IsBound(aEIm)) {
4226 AppendToList(theOEOrigins.ChangeFind(aEIm), aE);
4229 TopTools_ListOfShape aLOr;
4231 theOEOrigins.Bind(aEIm, aLOr);
4239 //=======================================================================
4240 //function : FilterInvalidFaces
4241 //purpose : Filtering of the invalid faces
4242 //=======================================================================
4243 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4244 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
4245 const TopTools_IndexedMapOfShape& theInvEdges,
4246 const TopTools_IndexedMapOfShape& theMERemoved,
4247 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4248 TopTools_DataMapOfShapeShape& theArtInvFaces)
4251 // filter invalid faces, considering faces having only valid
4252 // images left with non-free edges as valid
4253 // do not remove invalid faces if it creates free edges
4255 TopTools_IndexedDataMapOfShapeListOfShape aReallyInvFaces;
4256 // Edge-Face connexity map of all splits, both invalid and valid
4257 TopTools_IndexedDataMapOfShapeListOfShape aDMEFAll;
4258 TopTools_ListIteratorOfListOfShape aItLF;
4260 const Standard_Integer aNb = theInvFaces.Extent();
4261 for (Standard_Integer i = 1; i <= aNb; ++i) {
4262 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4263 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4265 if (theArtInvFaces.IsBound(aF)) {
4266 if (aLFInv.IsEmpty()) {
4267 theArtInvFaces.UnBind(aF);
4270 aReallyInvFaces.Add(aF, aLFInv);
4275 if (aLFInv.IsEmpty()) {
4279 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
4280 Standard_Boolean bInvalid = aLFIm.IsEmpty();
4283 // check two lists on common splits
4284 aItLF.Initialize(aLFInv);
4285 for (; aItLF.More(); aItLF.Next()) {
4286 const TopoDS_Shape& aFInv = aItLF.Value();
4288 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4289 for (; aItLFIm.More(); aItLFIm.Next()) {
4290 const TopoDS_Shape& aFIm = aItLFIm.Value();
4292 if (aFInv.IsSame(aFIm)) {
4297 if (aItLFIm.More()) {
4302 bInvalid = aItLF.More();
4306 // check for free edges
4307 for (Standard_Integer j = 0; !bInvalid && j < 2; ++j) {
4308 const TopTools_ListOfShape& aLI = !j ? aLFIm : aLFInv;
4309 aItLF.Initialize(aLI);
4310 for (; aItLF.More(); aItLF.Next()) {
4311 const TopoDS_Shape& aFIm = aItLF.Value();
4313 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4314 for (; aExp.More(); aExp.Next()) {
4315 const TopoDS_Shape& aE = aExp.Current();
4316 if (!theMERemoved.Contains(aE)) {
4317 const TopTools_ListOfShape* pLEF = theDMEF.Seek(aE);
4318 if (pLEF && pLEF->Extent() == 1) {
4328 bInvalid = aItLF.More();
4333 if (aDMEFAll.IsEmpty())
4336 for (Standard_Integer iF = 1; iF <= aNb; ++iF)
4337 for (TopTools_ListOfShape::Iterator itLFInv (theInvFaces(iF)); itLFInv.More(); itLFInv.Next())
4338 TopExp::MapShapesAndAncestors (itLFInv.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFAll);
4341 TopTools_MapOfShape aLocalSplits;
4342 for (Standard_Integer j = 0; j < 2; ++j)
4343 for (aItLF.Initialize((!j ? aLFIm : aLFInv)); aItLF.More(); aItLF.Next())
4344 aLocalSplits.Add (aItLF.Value());
4346 // Check if all invalid edges are located inside the split and do not touch
4347 // any other faces both invalid and valid
4348 aItLF.Initialize(aLFInv);
4349 for (; aItLF.More(); aItLF.Next())
4351 const TopoDS_Shape& aFIm = aItLF.Value();
4352 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4353 for (; aExp.More(); aExp.Next())
4355 const TopoDS_Shape& aE = aExp.Current();
4356 if (theInvEdges.Contains (aE) && !theMERemoved.Contains (aE))
4358 const TopTools_ListOfShape& aLF = aDMEFAll.FindFromKey (aE);
4359 TopTools_ListOfShape::Iterator itLF (aLF);
4360 for (; itLF.More(); itLF.Next())
4362 if (!aLocalSplits.Contains (itLF.Value()))
4372 bInvalid = aItLF.More();
4375 aItLF.Initialize(aLFInv);
4376 for (; aItLF.More(); aItLF.Next())
4377 AppendToList (aLFIm, aItLF.Value());
4382 aReallyInvFaces.Add(aF, aLFInv);
4386 theInvFaces = aReallyInvFaces;
4389 //=======================================================================
4390 //function : CheckEdgesCreatedByVertex
4391 //purpose : Checks additionally the unchecked edges originated from vertices
4392 //=======================================================================
4393 void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4394 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4395 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4396 const TopTools_IndexedMapOfShape& theValidEdges,
4397 TopTools_IndexedMapOfShape& theInvEdges)
4399 // Mark the unchecked edges contained in invalid faces as invalid
4400 const Standard_Integer aNbF = theInvFaces.Extent();
4401 for (Standard_Integer i = 1; i <= aNbF; ++i)
4403 const TopoDS_Shape& aF = theInvFaces.FindKey (i);
4404 if (theArtInvFaces.IsBound (aF))
4407 const TopTools_ListOfShape& aLFIm = theInvFaces (i);
4408 for (TopTools_ListOfShape::Iterator it (aLFIm); it.More(); it.Next())
4410 const TopoDS_Shape& aFIm = it.Value();
4411 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
4413 const TopoDS_Shape& aE = expE.Current();
4414 if (theInvEdges.Contains (aE)
4415 || theValidEdges.Contains (aE))
4420 // check if this edges is created by vertex
4421 const TopTools_ListOfShape* pLEOr = theEdgesOrigins.Seek (aE);
4424 TopTools_ListOfShape::Iterator itLEO (*pLEOr);
4425 for (; itLEO.More(); itLEO.Next())
4427 if (itLEO.Value().ShapeType() != TopAbs_VERTEX)
4432 theInvEdges.Add (aE);
4439 //=======================================================================
4440 //function : FilterInvalidEdges
4441 //purpose : Filtering the invalid edges according to currently invalid faces
4442 //=======================================================================
4443 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4444 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4445 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
4446 const TopTools_IndexedMapOfShape& theMERemoved,
4447 TopTools_IndexedMapOfShape& theInvEdges)
4449 TopoDS_Compound aCEInv;
4450 TopTools_IndexedMapOfShape aMEInv;
4452 aBB.MakeCompound(aCEInv);
4453 TopTools_ListIteratorOfListOfShape aItLF;
4455 Standard_Integer i, aNb = theInvFaces.Extent();
4456 for (i = 1; i <= aNb; ++i) {
4457 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4458 aItLF.Initialize(aLFInv);
4459 for (; aItLF.More(); aItLF.Next()) {
4460 const TopoDS_Shape& aFIm = aItLF.Value();
4461 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEInv);
4463 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4464 for (; aExpE.More(); aExpE.Next()) {
4465 const TopoDS_Shape& aE = aExpE.Current();
4466 if (theInvEdges.Contains(aE)) {
4467 aBB.Add(aCEInv, aE);
4473 // remove edges which have been marked for removal
4474 TopTools_IndexedMapOfShape aMEInvToAvoid;
4475 TopTools_ListOfShape aLCBE;
4476 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4478 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
4479 for (; aItLCBE.More(); aItLCBE.Next()) {
4480 const TopoDS_Shape& aCBE = aItLCBE.Value();
4481 TopExp_Explorer aExpCB(aCBE, TopAbs_EDGE);
4482 for (; aExpCB.More(); aExpCB.Next()) {
4483 const TopoDS_Shape& aE = aExpCB.Current();
4484 if (!theMERemoved.Contains(aE)) {
4489 if (!aExpCB.More()) {
4490 TopExp::MapShapes(aCBE, TopAbs_EDGE, aMEInvToAvoid);
4494 TopTools_IndexedMapOfShape aReallyInvEdges;
4496 aNb = theInvFaces.Extent();
4497 for (i = 1; i <= aNb; ++i) {
4498 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4499 if (theArtInvFaces.IsBound(aF)) {
4500 const TopTools_IndexedMapOfShape& aMIE = theDMFMIE.Find(aF);
4501 const Standard_Integer aNbIE = aMIE.Extent();
4502 for (Standard_Integer iE = 1; iE <= aNbIE; ++iE)
4504 const TopoDS_Shape& aE = aMIE (iE);
4505 if (aMEInv.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4506 aReallyInvEdges.Add(aE);
4511 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4512 aItLF.Initialize(aLFInv);
4513 for (; aItLF.More(); aItLF.Next()) {
4514 const TopoDS_Shape& aFIm = aItLF.Value();
4515 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4516 for (; aExpE.More(); aExpE.Next()) {
4517 const TopoDS_Shape& aE = aExpE.Current();
4518 if (theInvEdges.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4519 aReallyInvEdges.Add(aE);
4526 theInvEdges = aReallyInvEdges;
4529 //=======================================================================
4530 //function : FindFacesToRebuild
4531 //purpose : Looking for the faces that have to be rebuilt:
4532 // 1. Faces close to invalidity
4533 // 2. Faces containing some invalid parts
4534 //=======================================================================
4535 void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
4536 const TopTools_IndexedMapOfShape& theInvEdges,
4537 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4538 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4539 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4540 TopTools_MapOfShape& theFSelfRebAvoid)
4542 Standard_Integer i, aNb = theLFImages.Extent();
4547 Standard_Boolean bRebuild;
4548 TopTools_ListIteratorOfListOfShape aItLF;
4549 TopTools_ListOfShape aLEValid;
4550 TopTools_MapOfShape aMFence, aMEReb, aMFReb;
4551 TopExp_Explorer aExp;
4553 TopTools_DataMapOfShapeListOfShape aDMFLV;
4554 // get edges from invalid faces
4555 aNb = theInvFaces.Extent();
4556 for (i = 1; i <= aNb; i++) {
4557 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4559 TopTools_ListOfShape aLVAvoid;
4560 const TopTools_ListOfShape& aLFIm = theInvFaces(i);
4561 aItLF.Initialize(aLFIm);
4562 for (; aItLF.More(); aItLF.Next()) {
4563 const TopoDS_Shape& aFIm = aItLF.Value();
4564 aExp.Init(aFIm, TopAbs_EDGE);
4565 for (; aExp.More(); aExp.Next()) {
4566 const TopoDS_Shape& aE = aExp.Current();
4568 if (theInvEdges.Contains(aE)) {
4569 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
4570 for (; aExpV.More(); aExpV.Next()) {
4571 const TopoDS_Shape& aV = aExpV.Current();
4572 if (aMFence.Add(aV)) {
4573 aLVAvoid.Append(aV);
4581 if (aLVAvoid.Extent()) {
4582 aDMFLV.Bind(aF, aLVAvoid);
4585 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aF);
4587 TopTools_ListIteratorOfListOfShape aItLFE(*pLF);
4588 for (; aItLFE.More(); aItLFE.Next()) {
4589 const TopoDS_Shape& aFE = aItLFE.Value();
4595 // get face to rebuild
4596 aNb = theLFImages.Extent();
4597 for (i = 1; i <= aNb; i++) {
4598 const TopoDS_Shape& aF = theLFImages.FindKey(i);
4599 const TopTools_ListOfShape& aLFIm = theLFImages(i);
4600 TopTools_MapOfShape aMVAvoid;
4601 if (aDMFLV.IsBound(aF)) {
4602 const TopTools_ListOfShape& aLVAvoid = aDMFLV.Find(aF);
4603 TopTools_ListIteratorOfListOfShape aItLV(aLVAvoid);
4604 for (; aItLV.More(); aItLV.Next()) {
4605 const TopoDS_Shape& aV = aItLV.Value();
4610 bRebuild = aMFReb.Contains(aF);
4614 aItLF.Initialize(aLFIm);
4615 for (; aItLF.More(); aItLF.Next()) {
4616 const TopoDS_Shape& aFIm = aItLF.Value();
4617 aExp.Init(aFIm, TopAbs_EDGE);
4618 for (; aExp.More(); aExp.Next()) {
4619 const TopoDS_Edge& anEIm = TopoDS::Edge(aExp.Current());
4620 if (!theInvEdges.Contains(anEIm)) {
4621 if (aMFence.Add(anEIm)) {
4622 aLEValid.Append(anEIm);
4627 bRebuild = aMEReb.Contains(anEIm);
4632 TopExp_Explorer aExpV(anEIm, TopAbs_VERTEX);
4633 for (; aExpV.More() && !bRebuild; aExpV.Next()) {
4634 const TopoDS_Shape& aV = aExpV.Current();
4635 if (!aMVAvoid.Contains(aV)) {
4636 bRebuild = aMEReb.Contains(aV);
4644 bRebuild = aLFIm.Extent() && theInvFaces.Contains(aF);
4646 theFSelfRebAvoid.Add(aF);
4651 theFToRebuild.Add(aF, aLEValid);
4656 //=======================================================================
4657 //function : RebuildFaces
4658 //purpose : Rebuilding of the faces
4659 //=======================================================================
4660 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4661 const TopTools_MapOfShape& theFSelfRebAvoid,
4662 const TopoDS_Shape& theSolids,
4663 const BRepOffset_MakeOffset_InterResults& theIntRes,
4664 const BRepOffset_Analyse* theAnalyse,
4665 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4666 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
4667 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4668 TopTools_DataMapOfShapeShape& theFacesOrigins,
4669 TopTools_DataMapOfShapeListOfShape& theOEImages,
4670 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4671 TopTools_MapOfShape& theLastInvEdges,
4672 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4673 TopTools_IndexedMapOfShape& theInvEdges,
4674 TopTools_IndexedMapOfShape& theValidEdges,
4675 const TopTools_MapOfShape& theInvertedEdges,
4676 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
4677 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4678 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4679 TopTools_MapOfShape& theVertsToAvoid,
4680 TopTools_DataMapOfShapeShape& theETrimEInf,
4681 Handle(BRepAlgo_AsDes)& theAsDes)
4683 TopTools_MapOfShape aModifiedEdges;
4685 // 1. Intersect faces
4686 IntersectFaces(theFToRebuild, theFSelfRebAvoid, theSolids, theIntRes, theFImages, theEdgesOrigins, theOEImages,
4687 theOEOrigins, theInvEdges, theValidEdges, theInvertedEdges, theEdgesToAvoid,
4688 theInvFaces, theArtInvFaces, theVertsToAvoid, theETrimEInf, aModifiedEdges, theAsDes);
4690 // 2. Repeat steps to build the correct faces
4691 BuildSplitsOfInvFaces(theFToRebuild, aModifiedEdges, theAnalyse, theFImages, theDMFNewHoles, theEdgesOrigins,
4692 theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
4693 theEdgesToAvoid, theVertsToAvoid, theAlreadyInvFaces, theValidEdges,
4694 theETrimEInf, theAsDes);
4697 //=======================================================================
4698 //function : IntersectFaces
4699 //purpose : Intersection of the faces that should be rebuild
4700 // to resolve all invalidities
4701 //=======================================================================
4702 void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4703 const TopTools_MapOfShape& theFSelfRebAvoid,
4704 const TopoDS_Shape& theSolids,
4705 const BRepOffset_MakeOffset_InterResults& theIntRes,
4706 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4707 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4708 TopTools_DataMapOfShapeListOfShape& theOEImages,
4709 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4710 TopTools_IndexedMapOfShape& theInvEdges,
4711 TopTools_IndexedMapOfShape& theValidEdges,
4712 const TopTools_MapOfShape& theInvertedEdges,
4713 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4714 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4715 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4716 TopTools_MapOfShape& theVertsToAvoid,
4717 TopTools_DataMapOfShapeShape& theETrimEInf,
4718 TopTools_MapOfShape& theModifiedEdges,
4719 Handle(BRepAlgo_AsDes)& theAsDes)
4721 Standard_Integer aNbFR = theFToRebuild.Extent();
4726 Standard_Integer i, j, k, aNbInv;
4727 TopTools_ListIteratorOfListOfShape aItLF, aItLE;
4729 // get vertices from invalid edges
4730 TopTools_MapOfShape aMVInv, aMVInvAll;
4731 aNbInv = theInvEdges.Extent();
4732 for (i = 1; i <= aNbInv; ++i) {
4733 const TopoDS_Shape& aEInv = theInvEdges(i);
4734 Standard_Boolean bValid = theValidEdges.Contains(aEInv);
4735 for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next()) {
4736 const TopoDS_Shape& aV = aExp.Current();
4744 Standard_Boolean bLookVertToAvoid = (aMVInv.Extent() > 0);
4746 TopTools_DataMapOfShapeListOfShape aDMSF, aMDone, aMEInfETrim, aDMVEFull;
4747 TopTools_IndexedDataMapOfShapeListOfShape aFLE, aDMEFInv;
4749 // Add all faces to rebuild to outgoing map <aFLE>,
4750 // plus link edges and vertices to the faces to
4751 // define intersection faces
4752 PrepareFacesForIntersection(theFToRebuild, theFImages, theInvFaces, theArtInvFaces,
4753 bLookVertToAvoid, aFLE, aMDone, aDMSF, aMEInfETrim,
4754 aDMVEFull, theETrimEInf, aDMEFInv);
4756 // Find vertices to avoid while trimming the edges.
4757 // These vertices are taken from the invalid edges common between
4758 // splits of different invalid, but not artificially, faces.
4759 // Additional condition for these vertices is that all
4760 // edges adjacent to this vertex must be either invalid
4761 // or contained in invalid faces
4762 TopTools_MapOfShape aMVRInv = theVertsToAvoid;
4763 FindVerticesToAvoid(aDMEFInv, theInvEdges, theValidEdges, theInvertedEdges,
4764 aDMVEFull, theOEImages, theOEOrigins, aMVRInv);
4766 // The faces should be intersected selectively -
4767 // intersect only faces neighboring to the same invalid face
4768 // and connected to its invalid edges;
4769 // when dealing with artificially invalid faces for intersection to be
4770 // complete we need to use not only invalid edges, but also the
4771 // edges connected to invalid ones
4773 // find blocks of artificially invalid faces
4774 TopTools_DataMapOfShapeShape aDMFImF;
4775 TopoDS_Compound aCFArt;
4776 BRep_Builder().MakeCompound(aCFArt);
4777 TopTools_DataMapIteratorOfDataMapOfShapeShape aItM(theArtInvFaces);
4778 for (; aItM.More(); aItM.Next()) {
4779 const TopoDS_Shape& aF = aItM.Key();
4780 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
4781 aItLF.Initialize(aLFInv);
4782 for (; aItLF.More(); aItLF.Next()) {
4783 BRep_Builder().Add(aCFArt, aItLF.Value());
4784 aDMFImF.Bind(aItLF.Value(), aF);
4788 // make connexity blocks
4789 TopTools_ListOfShape aLCBArt;
4790 BOPTools_AlgoTools::MakeConnexityBlocks(aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt);
4793 TopTools_MapOfShape aMEAlone, aMEInvOnArt;
4795 TopTools_ListIteratorOfListOfShape aItLCBArt(aLCBArt);
4796 for (; aItLCBArt.More(); aItLCBArt.Next()) {
4797 const TopoDS_Shape& aCB = aItLCBArt.Value();
4799 // check if aCB contains splits of only one offset face
4800 TopTools_MapOfShape aMFArt;
4801 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
4802 for (; aExpF.More(); aExpF.Next()) {
4803 aMFArt.Add(aDMFImF.Find(aExpF.Current()));
4806 Standard_Boolean bAlone = (aMFArt.Extent() == 1);
4808 // vertices on invalid edges
4809 TopTools_MapOfShape aMVEInv;
4810 TopTools_MapOfShape aMFence;
4811 // edges that should not be marked as alone - edges having same origins as invalid ones
4812 TopTools_MapOfShape aMEAvoid;
4813 // map to find alone edges by looking for free vertices
4814 TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal;
4816 TopExp_Explorer aExpE(aCB, TopAbs_EDGE);
4817 for (; aExpE.More(); aExpE.Next()) {
4818 const TopoDS_Shape& aE = aExpE.Current();
4819 if (theInvEdges.Contains(aE)) {
4820 aMEInvOnArt.Add(aE);
4821 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
4822 aMVEInv.Add(aItV.Value());
4826 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4828 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4829 for (; aItLEOr.More(); aItLEOr.Next()) {
4830 TopTools_ListIteratorOfListOfShape aItLEIm(theOEImages.Find(aItLEOr.Value()));
4831 for (; aItLEIm.More(); aItLEIm.Next()) {
4832 aMEAvoid.Add(aItLEIm.Value());
4840 if (aMFence.Add(aE)) {
4841 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal);
4845 // find edges with free vertices
4846 Standard_Integer aNbV = aDMVEVal.Extent();
4847 for (i = 1; i <= aNbV; ++i) {
4848 const TopoDS_Shape& aV = aDMVEVal.FindKey(i);
4849 if (!aMVEInv.Contains(aV)) {
4853 const TopTools_ListOfShape& aLEV = aDMVEVal(i);
4854 if (aLEV.Extent() > 1) {
4858 const TopoDS_Shape& aE = aLEV.First();
4859 if (aMEAvoid.Contains(aE)) {
4865 // if this alone edge adds nothing to the intersection list
4866 // it means that the origin of this edge has been split and we need to
4867 // add the neighboring images of the same origins
4868 if (aDMSF.Find(aE).Extent() > 1) {
4872 // check also its vertices
4873 TopoDS_Iterator aItE(aE);
4874 for (; aItE.More(); aItE.Next()) {
4875 const TopoDS_Shape& aVE = aItE.Value();
4876 if (aDMSF.Find(aVE).Extent() > 2) {
4885 // the edge is useless - look for other images
4886 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4891 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4892 for (; aItLEOr.More(); aItLEOr.Next()) {
4893 const TopoDS_Shape& aEOr = aItLEOr.Value();
4895 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr);
4896 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
4897 for (; aItLEIm.More(); aItLEIm.Next()) {
4898 const TopoDS_Shape& aEIm = aItLEIm.Value();
4900 if (aMFence.Contains(aEIm)) {
4908 // Get all invalidities from all faces to be used for avoiding
4909 // repeated usage of the common edges
4910 TopTools_MapOfShape aMAllInvs;
4911 aNbInv = theInvFaces.Extent();
4912 for (k = 1; k <= aNbInv; ++k) {
4913 TopTools_ListIteratorOfListOfShape aIt(theInvFaces(k));
4914 for (; aIt.More(); aIt.Next()) {
4915 TopExp_Explorer aExp(aIt.Value(), TopAbs_EDGE);
4916 for (; aExp.More(); aExp.Next()) {
4917 const TopoDS_Shape& aE = aExp.Current();
4918 if (theInvEdges.Contains(aE) || aMEAlone.Contains(aE)) {
4920 TopoDS_Iterator aItV(aE);
4921 for (; aItV.More(); aItV.Next()) {
4922 aMAllInvs.Add(aItV.Value());
4929 // Bounding vertices of not trimmed edges
4930 TopTools_MapOfShape aMVBounds;
4932 TopTools_MapOfShape aMECheckExt;
4933 // Save connections between not trimmed edge and its trimmed parts
4934 TopTools_DataMapOfShapeListOfShape aDMEETrim;
4935 // Splits of the new edges
4936 TopTools_DataMapOfShapeListOfShape aEImages;
4939 // Keep connection between blocks of invalid edges to the lists of
4940 // found edges to be intersected for its treatment
4941 TopTools_IndexedDataMapOfShapeListOfShape aDMOENEdges;
4943 aNbInv = theInvFaces.Extent();
4944 for (k = 1; k <= aNbInv; ++k) {
4945 const TopoDS_Shape& aFInv = theInvFaces.FindKey(k);
4946 Standard_Boolean bSelfRebAvoid = theFSelfRebAvoid.Contains(aFInv);
4947 const TopTools_ListOfShape& aLFInv = theInvFaces(k);
4949 TopTools_ListOfShape aLCB;
4950 if (aLFInv.Extent() > 1) {
4951 // make compound of invalid faces
4952 TopoDS_Compound aCFInv;
4953 aBB.MakeCompound(aCFInv);
4955 TopTools_ListIteratorOfListOfShape aIt(aLFInv);
4956 for (; aIt.More(); aIt.Next()) {
4957 const TopoDS_Shape& aFIm = aIt.Value();
4958 aBB.Add(aCFInv, aFIm);
4961 // make connexity blocks
4962 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCB);
4968 Standard_Boolean bArtificial = theArtInvFaces.IsBound(aFInv);
4969 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
4970 for (; aItLCB.More(); aItLCB.Next()) {
4971 const TopoDS_Shape& aCBInv = aItLCB.Value();
4973 TopTools_MapOfShape aMEFence;
4975 TopoDS_Compound aCBE;
4976 aBB.MakeCompound(aCBE);
4978 TopExp_Explorer aExp(aCBInv, TopAbs_EDGE);
4979 for (; aExp.More(); aExp.Next()) {
4980 const TopoDS_Shape& aE = aExp.Current();
4981 if (theInvEdges.Contains(aE) || (bArtificial && aMEAlone.Contains(aE))) {
4982 if (aMEFence.Add(aE)) {
4988 // make connexity blocks of edges
4989 TopTools_ListOfShape aLCBE;
4990 BOPTools_AlgoTools::MakeConnexityBlocks(aCBE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4992 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
4993 for (; aItLCBE.More(); aItLCBE.Next()) {
4994 const TopoDS_Shape& aCBELoc = aItLCBE.Value();
4996 // map of edges and vertices of processing invalidity
4997 TopTools_IndexedMapOfShape aME;
4998 // map of vertices to trim the new edges
4999 TopTools_IndexedMapOfShape aMECV;
5000 TopExp::MapShapes(aCBELoc, TopAbs_EDGE, aME);
5002 TopExp::MapShapes(aCBELoc, TopAbs_VERTEX, aME);
5004 // Using the map <aME> find chain of faces to be intersected;
5006 // faces for intersection
5007 TopTools_IndexedMapOfShape aMFInt;
5008 // additional faces for intersection
5009 TopTools_IndexedMapOfShape aMFIntExt;
5010 // splits of faces for intersection
5011 TopTools_ListOfShape aLFInt;
5012 // faces to avoid intersection
5013 TopTools_IndexedMapOfShape aMFAvoid;
5015 FindFacesForIntersection(aFInv, aME, theFImages, aDMSF, aMVInvAll,
5016 theArtInvFaces, bArtificial, theIntRes.SSInterfs, aMFAvoid, aMFInt, aMFIntExt, aLFInt);
5017 if (aMFInt.Extent() < 3) {
5018 // nothing to intersect
5022 const BRepOffset_DataMapOfShapeMapOfShape* pMFInter = theIntRes.InterPairs.Seek (aFInv);
5023 // intersect the faces, but do not intersect the invalid ones
5024 // among each other (except for the artificially invalid faces)
5025 TopTools_IndexedMapOfShape aMEToInt;
5026 Standard_Integer aNb = aMFInt.Extent();
5027 for (i = 1; i <= aNb; ++i) {
5028 const TopoDS_Face& aFi = TopoDS::Face(aMFInt(i));
5029 if (bSelfRebAvoid && aFi.IsSame(aFInv)) {
5033 const TopTools_ListOfShape& aLFImi = theFImages.FindFromKey(aFi);
5035 TopTools_ListOfShape& aLFEi = aFLE.ChangeFromKey(aFi);
5037 TopTools_ListOfShape& aLFDone = aMDone.ChangeFind(aFi);
5039 const TopTools_MapOfShape* pInterFi = !pMFInter ? 0 : pMFInter->Seek (aFi);
5040 if (pMFInter && !pInterFi)
5043 for (j = i + 1; j <= aNb; ++j) {
5044 const TopoDS_Face& aFj = TopoDS::Face(aMFInt(j));
5045 if (bSelfRebAvoid && aFj.IsSame(aFInv)) {
5049 if (pInterFi && !pInterFi->Contains (aFj))
5052 const TopTools_ListOfShape& aLFImj = theFImages.FindFromKey(aFj);
5054 TopTools_ListOfShape& aLFEj = aFLE.ChangeFromKey(aFj);
5056 // if there are some common edges between faces
5057 // we should use these edges and do not intersect again.
5058 TopTools_ListOfShape aLEC;
5059 FindCommonParts(aLFImi, aLFImj, aLEC);
5061 if (aLEC.Extent()) {
5062 // no need to intersect if we have common edges between faces
5063 Standard_Boolean bForceUse = aMFIntExt.Contains(aFi) || aMFIntExt.Contains(aFj);
5064 ProcessCommonEdges(aLEC, theInvEdges, theValidEdges, aME, theETrimEInf, aMEInfETrim,
5065 theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt);
5069 // check if both these faces are invalid and sharing edges
5070 if (theInvFaces.Contains(aFi) && theInvFaces.Contains(aFj) &&
5071 !theArtInvFaces.IsBound(aFi) && !theArtInvFaces.IsBound(aFj)) {
5075 // check if these two faces have already been treated
5076 aItLE.Initialize(aLFDone);
5077 for (; aItLE.More(); aItLE.Next()) {
5078 const TopoDS_Shape& aF = aItLE.Value();
5079 if (aF.IsSame(aFj)) {
5085 // use intersection line obtained on the previous steps
5086 // plus, find new origins for these lines
5087 UpdateIntersectedFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
5088 aLFEi, aLFEj, theEdgesOrigins, aMEToInt);
5092 if (aMFAvoid.Contains(aFi) || aMFAvoid.Contains(aFj)) {
5096 aLFDone.Append(aFj);
5097 aMDone.ChangeFind(aFj).Append(aFi);
5099 IntersectFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
5100 aLFEi, aLFEj, theEdgesOrigins, aMECV, aMEToInt);
5104 // intersect and trim edges for this chain
5105 IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV,
5106 aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages);
5108 Standard_Integer iE, aNbEToInt = aMEToInt.Extent();
5109 for (iE = 1; iE <= aNbEToInt; ++iE)
5111 const TopoDS_Shape& aEInt = aMEToInt(iE);
5112 TopExp_Explorer anExpE(aCBELoc, TopAbs_EDGE);
5113 for (; anExpE.More(); anExpE.Next())
5115 const TopoDS_Shape& aE = anExpE.Current();
5116 TopTools_ListOfShape* pLEToInt = aDMOENEdges.ChangeSeek(aE);
5118 pLEToInt = &aDMOENEdges(aDMOENEdges.Add(aE, TopTools_ListOfShape()));
5119 AppendToList(*pLEToInt, aEInt);
5126 // filter the obtained edges
5127 UpdateValidEdges(theFImages, aFLE, aDMOENEdges, aMVBounds, theSolids, theInvEdges, theInvertedEdges, aMEInvOnArt,
5128 aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins,
5129 theVertsToAvoid, theETrimEInf, aEImages, aDMEETrim, theModifiedEdges, theAsDes);
5132 //=======================================================================
5133 //function : PrepareFacesForIntersection
5134 //purpose : Preparation of the maps for analyzing intersections of the faces
5135 //=======================================================================
5136 void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
5137 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5138 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
5139 const TopTools_DataMapOfShapeShape& theArtInvFaces,
5140 const Standard_Boolean bLookVertToAvoid,
5141 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
5142 TopTools_DataMapOfShapeListOfShape& theMDone,
5143 TopTools_DataMapOfShapeListOfShape& theDMSF,
5144 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5145 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5146 TopTools_DataMapOfShapeShape& theETrimEInf,
5147 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv)
5149 Standard_Integer i, aNb = theFToRebuild.Extent();
5150 for (i = 1; i <= aNb; ++i) {
5151 const TopoDS_Shape& aF = theFToRebuild.FindKey(i);
5153 TopTools_ListOfShape aLE;
5154 theFLE.Add(aF, aLE);
5155 theMDone.Bind(aF, aLE);
5157 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5158 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
5159 for (; aItLF.More(); aItLF.Next()) {
5160 const TopoDS_Shape& aFIm = aItLF.Value();
5161 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
5162 for (; aExp.More(); aExp.Next()) {
5163 const TopoDS_Shape& aE = aExp.Current();
5164 // save connection to untrimmed face
5165 TopTools_ListOfShape *pLF = theDMSF.ChangeSeek(aE);
5167 pLF = theDMSF.Bound(aE, TopTools_ListOfShape());
5169 AppendToList(*pLF, aF);
5171 // save connection to untrimmed edge
5172 const TopoDS_Shape& aEInf = theETrimEInf.Find(aE);
5173 TopTools_ListOfShape *pLETrim = theMEInfETrim.ChangeSeek(aEInf);
5175 pLETrim = theMEInfETrim.Bound(aEInf, TopTools_ListOfShape());
5177 AppendToList(*pLETrim, aE);
5179 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
5180 for (; aExpV.More(); aExpV.Next()) {
5181 const TopoDS_Shape& aV = aExpV.Current();
5182 // save connection to face
5183 TopTools_ListOfShape *pLFV = theDMSF.ChangeSeek(aV);
5185 pLFV = theDMSF.Bound(aV, TopTools_ListOfShape());
5187 AppendToList(*pLFV, aF);
5189 if (bLookVertToAvoid) {
5190 // save connection to edges
5191 TopTools_ListOfShape *pLEV = theDMVEFull.ChangeSeek(aV);
5193 pLEV = theDMVEFull.Bound(aV, TopTools_ListOfShape());
5195 AppendToList(*pLEV, aE);
5201 if (bLookVertToAvoid) {
5202 // get edges of invalid faces (from invalid splits only)
5203 const TopTools_ListOfShape *pLFInv = theInvFaces.Seek(aF);
5204 if (!pLFInv || theArtInvFaces.IsBound(aF)) {
5208 aItLF.Initialize(*pLFInv);
5209 for (; aItLF.More(); aItLF.Next()) {
5210 const TopoDS_Shape& aFInv = aItLF.Value();
5211 TopExp_Explorer aExp(aFInv, TopAbs_EDGE);
5212 for (; aExp.More(); aExp.Next()) {
5213 const TopoDS_Shape& aE = aExp.Current();
5214 TopTools_ListOfShape *pLF = theDMEFInv.ChangeSeek(aE);
5216 pLF = &theDMEFInv(theDMEFInv.Add(aE, TopTools_ListOfShape()));
5218 AppendToList(*pLF, aF);
5225 //=======================================================================
5226 //function : FindVerticesToAvoid
5227 //purpose : Looking for the invalid vertices
5228 //=======================================================================
5229 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
5230 const TopTools_IndexedMapOfShape& theInvEdges,
5231 const TopTools_IndexedMapOfShape& theValidEdges,
5232 const TopTools_MapOfShape& theInvertedEdges,
5233 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5234 const TopTools_DataMapOfShapeListOfShape& theOEImages,
5235 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
5236 TopTools_MapOfShape& theMVRInv)
5238 TopTools_MapOfShape aMFence;
5239 Standard_Integer i, aNb = theDMEFInv.Extent();
5240 for (i = 1; i <= aNb; ++i) {
5241 const TopTools_ListOfShape& aLFInv = theDMEFInv(i);
5242 if (aLFInv.Extent() == 1) {
5246 const TopoDS_Shape& aE = theDMEFInv.FindKey(i);
5247 if (!theInvEdges.Contains(aE) || theValidEdges.Contains(aE)) {
5251 if (!aMFence.Add(aE))
5254 TopTools_IndexedDataMapOfShapeListOfShape aMVEEdges;
5255 // Do not check the splitting vertices, but check only the ending ones
5256 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
5259 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
5260 for (; aItLEOr.More(); aItLEOr.Next())
5262 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aItLEOr.Value());
5263 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
5264 for (; aItLEIm.More(); aItLEIm.Next())
5266 aMFence.Add(aItLEIm.Value());
5267 TopExp::MapShapesAndAncestors(aItLEIm.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5273 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5276 Standard_Integer j, aNbV = aMVEEdges.Extent();
5277 for (j = 1; j <= aNbV; ++j)
5279 if (aMVEEdges(j).Extent() != 1)
5282 const TopoDS_Shape& aV = aMVEEdges.FindKey(j);
5283 if (!aMFence.Add(aV))
5285 const TopTools_ListOfShape *pLE = theDMVEFull.Seek(aV);
5292 // If all edges sharing the vertex are either invalid or
5293 // the vertex is connected to at least two inverted edges
5294 // mark the vertex to be avoided in the new splits
5295 Standard_Integer iNbEInverted = 0;
5296 Standard_Boolean bAllEdgesInv = Standard_True;
5297 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
5298 for (; aItLE.More(); aItLE.Next()) {
5299 const TopoDS_Shape& aEV = aItLE.Value();
5301 if (theInvertedEdges.Contains(aEV))
5305 bAllEdgesInv = theInvEdges.Contains(aEV);
5308 if (iNbEInverted > 1 || bAllEdgesInv)
5316 //=======================================================================
5317 //function : FindFacesForIntersection
5318 //purpose : Looking for the faces around each invalidity for intersection
5319 //=======================================================================
5320 void FindFacesForIntersection(const TopoDS_Shape& theFInv,
5321 const TopTools_IndexedMapOfShape& theME,
5322 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5323 const TopTools_DataMapOfShapeListOfShape& theDMSF,
5324 const TopTools_MapOfShape& theMVInvAll,
5325 const TopTools_DataMapOfShapeShape& theArtInvFaces,
5326 const Standard_Boolean theArtCase,
5327 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
5328 TopTools_IndexedMapOfShape& theMFAvoid,
5329 TopTools_IndexedMapOfShape& theMFInt,
5330 TopTools_IndexedMapOfShape& theMFIntExt,
5331 TopTools_ListOfShape& theLFImInt)
5333 Standard_Integer i, aNbE = theME.Extent();
5335 TopTools_IndexedMapOfShape aMShapes;
5337 for (i = 1; i <= aNbE; ++i) {
5338 const TopoDS_Shape& aS = theME(i);
5339 if (!theDMSF.IsBound(aS)) {
5343 // in artificial case we intersect the faces which are close to invalidity
5344 Standard_Boolean bAvoid = theArtCase ?
5345 ((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains(aS)) : Standard_False;
5347 const TopTools_ListOfShape& aLF = theDMSF.Find(aS);
5348 TopTools_ListIteratorOfListOfShape aItLF(aLF);
5349 for (; aItLF.More(); aItLF.Next()) {
5350 const TopoDS_Shape& aF = aItLF.Value();
5351 if (theMFInt.Contains(aF)) {
5355 if (bAvoid && theArtInvFaces.IsBound(aF)) {
5361 Standard_Boolean bUse = !aF.IsSame(theFInv);
5363 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5364 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5365 for (; aItLFIm.More(); aItLFIm.Next()) {
5366 const TopoDS_Shape& aFIm = aItLFIm.Value();
5367 theLFImInt.Append(aFIm);
5369 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMShapes);
5379 const TopTools_ListOfShape* pLFInv = theSSInterfs.Seek(theFInv);
5384 TopTools_MapOfShape aMF;
5385 TopTools_ListIteratorOfListOfShape aItLF(*pLFInv);
5386 for (; aItLF.More(); aItLF.Next()) {
5387 const TopoDS_Shape& aF = aItLF.Value();
5391 // the faces should be unique in each place
5392 TopoDS_Compound aCF;
5393 BRep_Builder().MakeCompound(aCF);
5395 TopTools_IndexedMapOfShape aMFToAdd;
5396 TopTools_DataMapOfShapeShape aDMFOr;
5398 for (i = 1; i <= aNbE; ++i) {
5399 const TopoDS_Shape& aS = theME(i);
5400 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aS);
5405 aItLF.Initialize(*pLF);
5406 for (; aItLF.More(); aItLF.Next()) {
5407 const TopoDS_Shape& aF = aItLF.Value();
5408 if (theMFInt.Contains(aF) || aMFToAdd.Contains(aF) || !aMF.Contains(aF)) {
5412 // check if the face has some connection to already added for intersection faces
5413 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5414 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5415 for (; aItLFIm.More(); aItLFIm.Next()) {
5416 const TopoDS_Shape& aFIm = aItLFIm.Value();
5417 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
5418 for (; aExp.More(); aExp.Next()) {
5419 if (aMShapes.Contains(aExp.Current())) {
5427 if (!aItLFIm.More()) {
5432 aItLFIm.Initialize(aLFIm);
5433 for (; aItLFIm.More(); aItLFIm.Next()) {
5434 const TopoDS_Shape& aFIm = aItLFIm.Value();
5435 aDMFOr.Bind(aFIm, aF);
5436 BRep_Builder().Add(aCF, aFIm);
5441 if (aMFToAdd.IsEmpty()) {
5445 TopTools_ListOfShape aLCB;
5446 BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
5448 if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1)) {
5452 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
5453 for (; aItLCB.More(); aItLCB.Next()) {
5454 const TopoDS_Shape& aCB = aItLCB.Value();
5456 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
5457 for (; aExpF.More(); aExpF.Next()) {
5458 const TopoDS_Shape& aFIm = aExpF.Current();
5459 aMFToAdd.Add(aDMFOr.Find(aFIm));
5462 if (aMFToAdd.Extent() == 1) {
5463 const TopoDS_Shape& aF = aMFToAdd(1);
5466 theMFIntExt.Add(aF);
5468 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5469 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5470 for (; aItLFIm.More(); aItLFIm.Next()) {
5471 const TopoDS_Shape& aFIm = aItLFIm.Value();
5472 theLFImInt.Append(aFIm);
5478 //=======================================================================
5479 //function : ProcessCommonEdges
5480 //purpose : Analyzing the common edges between splits of offset faces
5481 //=======================================================================
5482 void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
5483 const TopTools_IndexedMapOfShape& theInvEdges,
5484 const TopTools_IndexedMapOfShape& theValidEdges,
5485 const TopTools_IndexedMapOfShape& theME,
5486 const TopTools_DataMapOfShapeShape& theETrimEInf,
5487 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5488 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
5489 const TopTools_MapOfShape& theAllInvs,
5490 const Standard_Boolean theForceUse,
5491 TopTools_IndexedMapOfShape& theMECV,
5492 TopTools_MapOfShape& theMECheckExt,
5493 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5494 TopTools_ListOfShape& theLFEi,
5495 TopTools_ListOfShape& theLFEj,
5496 TopTools_IndexedMapOfShape& theMEToInt)
5498 TopTools_ListOfShape aLEC;
5499 // process common edges
5500 TopTools_ListIteratorOfListOfShape aItLE(theLEC);
5501 for (; aItLE.More(); aItLE.Next()) {
5502 const TopoDS_Shape& aEC = aItLE.Value();
5504 // check first if common edges are valid
5505 if (theInvEdges.Contains(aEC) && !theValidEdges.Contains(aEC)) {
5509 // common edge should have connection to current invalidity
5510 if (theME.Contains(aEC)) {
5515 TopoDS_Iterator aItV(aEC);
5516 for (; aItV.More(); aItV.Next()) {
5517 const TopoDS_Shape& aVE = aItV.Value();
5518 if (theME.Contains(aVE)) {
5525 Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
5531 aItLE.Initialize(theLEC);
5532 for (; aItLE.More(); aItLE.Next()) {
5533 const TopoDS_Shape& aEC = aItLE.Value();
5534 // check if all images of the origin of this edge
5535 // are not connected to any invalidity
5536 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5537 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5538 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5539 for (; aItLVE.More(); aItLVE.Next()) {
5540 const TopoDS_Shape& aECx = aItLVE.Value();
5541 if (theAllInvs.Contains(aECx) || theInvEdges.Contains(aECx)) {
5545 TopoDS_Iterator aItV(aECx);
5546 for (; aItV.More(); aItV.Next()) {
5547 if (theAllInvs.Contains(aItV.Value())) {
5552 // use only one element
5553 if (aLEC.IsEmpty()) {
5560 aItLE.Initialize(aLEC);
5561 for (; aItLE.More(); aItLE.Next()) {
5562 const TopoDS_Shape& aEC = aItLE.Value();
5564 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5566 // find the edges of the same original edge
5567 // and take their vertices as well
5568 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5569 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5570 for (; aItLVE.More(); aItLVE.Next()) {
5571 const TopoDS_Shape& aECx = aItLVE.Value();
5573 const TopTools_ListOfShape* pLEOr = theOEOrigins.Seek(aECx);
5574 if (!pLEOr || (pLEOr->Extent() == 1)) {
5575 TopExp::MapShapes(aECx, TopAbs_VERTEX, theMECV);
5579 // bind unlimited edge to its trimmed part in face to update maps of
5580 // images and origins in the future
5581 TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek(aEInt);
5583 pLTAdded = theDMEETrim.Bound(aEInt, TopTools_ListOfShape());
5585 AppendToList(*pLTAdded, aEC);
5587 else if (!theForceUse) {
5588 theMECheckExt.Add(aEInt);
5591 AppendToList(theLFEi, aEInt);
5592 AppendToList(theLFEj, aEInt);
5593 theMEToInt.Add(aEInt);
5597 //=======================================================================
5598 //function : UpdateIntersectedFaces
5599 //purpose : Updating the already interfered faces
5600 //=======================================================================
5601 void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
5602 const TopoDS_Shape& theFi,
5603 const TopoDS_Shape& theFj,
5604 const TopTools_ListOfShape& theLFInv,
5605 const TopTools_ListOfShape& theLFImi,
5606 const TopTools_ListOfShape& theLFImj,
5607 const TopTools_ListOfShape& theLFEi,
5608 const TopTools_ListOfShape& theLFEj,
5609 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5610 TopTools_IndexedMapOfShape& theMEToInt)
5612 // Find common edges in these two lists
5613 TopTools_MapOfShape aMEi;
5614 TopTools_ListIteratorOfListOfShape aItLE(theLFEi);
5615 for (; aItLE.More(); aItLE.Next()) {
5616 const TopoDS_Shape& aE = aItLE.Value();
5621 TopTools_IndexedMapOfShape aMEToFindOrigins;
5622 TopTools_ListOfShape aLEToFindOrigins;
5623 if (!theFi.IsSame(theFInv)) {
5624 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5626 if (!theFj.IsSame(theFInv)) {
5627 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5630 TopTools_ListOfShape aLEOrInit;
5631 aItLE.Initialize(aLEToFindOrigins);
5632 for (; aItLE.More(); aItLE.Next()) {
5633 const TopoDS_Shape& aEC = aItLE.Value();
5634 aMEToFindOrigins.Add(aEC);
5637 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5639 aItLE.Initialize(theLFEj);
5640 for (; aItLE.More(); aItLE.Next()) {
5641 const TopoDS_Shape& aE = aItLE.Value();
5642 if (aMEi.Contains(aE)) {
5644 if (aLEOrInit.Extent()) {
5645 if (theEdgesOrigins.IsBound(aE)) {
5646 TopTools_ListOfShape& aLEOr = theEdgesOrigins.ChangeFind(aE);
5647 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOrInit);
5648 for (; aItLEOr.More(); aItLEOr.Next()) {
5649 const TopoDS_Shape& aEOr = aItLEOr.Value();
5650 AppendToList(aLEOr, aEOr);
5654 theEdgesOrigins.Bind(aE, aLEOrInit);
5661 //=======================================================================
5662 //function : IntersectFaces
5663 //purpose : Intersection of the pair of faces
5664 //=======================================================================
5665 void IntersectFaces(const TopoDS_Shape& theFInv,
5666 const TopoDS_Shape& theFi,
5667 const TopoDS_Shape& theFj,
5668 const TopTools_ListOfShape& theLFInv,
5669 const TopTools_ListOfShape& theLFImi,
5670 const TopTools_ListOfShape& theLFImj,
5671 TopTools_ListOfShape& theLFEi,
5672 TopTools_ListOfShape& theLFEj,
5673 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5674 TopTools_IndexedMapOfShape& theMECV,
5675 TopTools_IndexedMapOfShape& theMEToInt)
5678 TopAbs_State aSide = TopAbs_OUT;
5679 TopTools_ListOfShape aLInt1, aLInt2;
5680 TopoDS_Edge aNullEdge;
5681 TopoDS_Face aNullFace;
5682 BRepOffset_Tool::Inter3D(TopoDS::Face(theFi), TopoDS::Face(theFj), aLInt1, aLInt2, aSide,
5683 aNullEdge, aNullFace, aNullFace);
5685 if (aLInt1.IsEmpty()) {
5689 // find common vertices for trimming edges
5690 TopTools_ListOfShape aLCV;
5691 TopTools_ListIteratorOfListOfShape aItLE;
5692 FindCommonParts(theLFImi, theLFImj, aLCV, TopAbs_VERTEX);
5693 if (aLCV.Extent() > 1) {
5694 aItLE.Initialize(aLCV);
5695 for (; aItLE.More(); aItLE.Next()) {
5696 const TopoDS_Shape& aCV = aItLE.Value();
5702 TopTools_IndexedMapOfShape aMEToFindOrigins;
5703 TopTools_ListOfShape aLEToFindOrigins;
5704 if (!theFi.IsSame(theFInv)) {
5705 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5707 if (!theFj.IsSame(theFInv)) {
5708 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5710 TopTools_ListOfShape aLEOrInit;
5711 aItLE.Initialize(aLEToFindOrigins);
5712 for (; aItLE.More(); aItLE.Next()) {
5713 const TopoDS_Shape& aEC = aItLE.Value();
5714 aMEToFindOrigins.Add(aEC);
5717 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5719 aItLE.Initialize(aLInt1);
5720 for (; aItLE.More(); aItLE.Next()) {
5721 const TopoDS_Shape& aEInt = aItLE.Value();
5722 theLFEi.Append(aEInt);
5723 theLFEj.Append(aEInt);
5725 if (aLEOrInit.Extent()) {
5726 theEdgesOrigins.Bind(aEInt, aLEOrInit);
5729 theMEToInt.Add(aEInt);
5733 //=======================================================================
5734 //function : FindOrigins
5735 //purpose : Looking for the origin edges
5736 //=======================================================================
5737 void FindOrigins(const TopTools_ListOfShape& theLFIm1,
5738 const TopTools_ListOfShape& theLFIm2,
5739 const TopTools_IndexedMapOfShape& theME,
5740 const TopTools_DataMapOfShapeListOfShape& theOrigins,
5741 TopTools_ListOfShape& theLEOr)
5744 TopTools_MapOfShape aMFence;
5745 TopExp_Explorer aExp;
5746 TopTools_ListIteratorOfListOfShape aIt, aItLE;
5748 for (i = 0; i < 2; ++i) {
5749 const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2;
5750 aIt.Initialize(aLF);
5751 for (; aIt.More(); aIt.Next()) {
5752 const TopoDS_Shape& aF = aIt.Value();
5754 aExp.Init(aF, TopAbs_EDGE);
5755 for (; aExp.More(); aExp.Next()) {
5756 const TopoDS_Shape& aE = aExp.Current();
5758 if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5759 const TopTools_ListOfShape& aLEOr = theOrigins.Find(aE);
5760 aItLE.Initialize(aLEOr);
5761 for (; aItLE.More(); aItLE.Next()) {
5762 const TopoDS_Shape& aEOr = aItLE.Value();
5764 if (aMFence.Add(aEOr) && (aEOr.ShapeType() == TopAbs_EDGE)) {
5765 theLEOr.Append(aEOr);
5767 } // for (; aItLE.More(); aItLE.Next()) {
5768 } // if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5769 } // aExp.Init(aF, TopAbs_EDGE);
5770 } // for (; aIt.More(); aIt.Next()) {
5771 } // for (i = 0; i < 2; ++i) {
5774 //=======================================================================
5775 //function : IntersectAndTrimEdges
5776 //purpose : Intersection of the new intersection edges among themselves
5777 //=======================================================================
5778 void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
5779 const TopTools_IndexedMapOfShape& theMFInt,
5780 const TopTools_IndexedMapOfShape& theMEInt,
5781 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5782 const TopTools_IndexedMapOfShape& theMSInv,
5783 const TopTools_IndexedMapOfShape& theMVE,
5784 const TopTools_MapOfShape& theVertsToAvoid,
5785 const TopTools_MapOfShape& theNewVertsToAvoid,
5786 const TopTools_MapOfShape& theMECheckExt,
5787 TopTools_MapOfShape& theMVBounds,
5788 TopTools_DataMapOfShapeListOfShape& theEImages)
5790 Standard_Integer i, aNb = theMEInt.Extent();
5795 TopTools_ListOfShape aLArgs;
5796 TopTools_MapOfShape aMFence;
5797 TopTools_ListIteratorOfListOfShape aIt, aIt1;
5798 TopExp_Explorer aExp;
5800 // get vertices from the splits of intersected faces.
5801 // vertices are taken from the edges close to invalidity
5803 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
5804 aNb = theMFInt.Extent();
5805 for (i = 1; i <= aNb; ++i) {
5806 const TopoDS_Shape& aF = theMFInt(i);
5807 const TopTools_ListOfShape& aLE = theFToRebuild.FindFromKey(aF);
5809 aIt.Initialize(aLE);
5810 for (; aIt.More(); aIt.Next()) {
5811 const TopoDS_Shape& aE = aIt.Value();
5812 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
5814 aExp.Init(aE, TopAbs_VERTEX);
5815 for (; aExp.More(); aExp.Next()) {
5816 const TopoDS_Shape& aV1 = aExp.Current();
5817 if (!theVertsToAvoid.Contains(aV1) && theMVE.Contains(aV1) && aMFence.Add(aV1)) {
5824 aNb = theMSInv.Extent();
5825 for (i = 1; i <= aNb; ++i) {
5826 const TopoDS_Shape& aV = theMSInv(i);
5827 if (aV.ShapeType() != TopAbs_VERTEX) {
5831 TopTools_ListOfShape *pLVE = aDMVE.ChangeSeek(aV);
5836 aIt.Initialize(*pLVE);
5837 for (; aIt.More(); aIt.Next()) {
5838 const TopoDS_Shape& aE = aIt.Value();
5840 aExp.Init(aE, TopAbs_VERTEX);
5841 for (; aExp.More(); aExp.Next()) {
5842 const TopoDS_Shape& aV1 = aExp.Current();
5843 if (!theVertsToAvoid.Contains(aV1) && aMFence.Add(aV1)) {
5850 // bounding vertices of untrimmed edges
5851 TopTools_ListOfShape aLVBounds;
5852 // new intersection edges
5853 TopTools_ListOfShape aLENew;
5854 // get edges to intersect
5855 TopTools_ListOfShape aLEInt;
5856 // Common intersection edges. Should be intersected separately
5857 TopTools_ListOfShape aLCE;
5859 aNb = theMEInt.Extent();
5860 for (i = 1; i <= aNb; ++i) {
5861 const TopoDS_Shape& aE = theMEInt(i);
5862 if (theMECheckExt.Contains(aE)) {
5863 // avoid trimming of the intersection edges by additional common edges
5868 if (!theDMEETrim.IsBound(aE)) {
5875 aExp.Init(aE, TopAbs_VERTEX);
5876 for (; aExp.More(); aExp.Next()) {
5877 const TopoDS_Shape& aV = aExp.Current();
5878 aLVBounds.Append(aV);
5883 BOPAlgo_Builder aGF;
5884 aGF.SetArguments(aLArgs);
5886 if (aGF.HasErrors()) {
5890 // update vertices to avoid with SD vertices
5891 aIt.Initialize(aLVBounds);
5892 for (; aIt.More(); aIt.Next()) {
5893 const TopoDS_Shape& aV = aIt.Value();
5894 const TopTools_ListOfShape& aLVIm = aGF.Modified(aV);
5895 if (aLVIm.IsEmpty()) {
5896 theMVBounds.Add(aV);
5899 const TopoDS_Shape& aVIm = aLVIm.First();
5900 theMVBounds.Add(aVIm);
5904 // find invalid splits of edges
5905 TopTools_MapOfShape aMEInv;
5906 GetInvalidEdges(theNewVertsToAvoid, theMVBounds, aGF, aMEInv);
5909 // get valid splits to intersect with the commons
5910 TopoDS_Compound aCEIm;
5911 aBB.MakeCompound(aCEIm);
5913 // remove the splits containing vertices from invalid edges
5914 aIt.Initialize(aLEInt);
5915 for (; aIt.More(); aIt.Next()) {
5916 const TopoDS_Shape& aE = aIt.Value();
5918 TopTools_ListOfShape aLEIm = aGF.Modified(aE);
5919 if (aLEIm.IsEmpty()) {
5923 aIt1.Initialize(aLEIm);
5924 for (; aIt1.More(); ) {
5925 const TopoDS_Shape& aEIm = aIt1.Value();
5927 if (aMEInv.Contains(aEIm)) {
5931 aBB.Add(aCEIm, aEIm);
5936 if (aLEIm.Extent()) {
5937 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
5939 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
5941 pLEIm->Append(aLEIm);
5945 if (!aLCE.Extent()) {
5949 // trim common edges by other intersection edges
5950 BOPAlgo_Builder aGFCE;
5951 aGFCE.SetArguments(aLCE);
5952 aGFCE.AddArgument(aCEIm);
5955 if (aGFCE.HasErrors()) {
5959 const BOPDS_PDS& pDS = aGFCE.PDS();
5960 TopTools_ListIteratorOfListOfShape aItLCE(aLCE);
5961 for (; aItLCE.More(); aItLCE.Next()) {
5962 const TopoDS_Shape& aE = aItLCE.Value();
5963 TopTools_ListOfShape aLEIm = aGFCE.Modified(aE);
5964 if (aLEIm.IsEmpty()) {
5968 // check if it's not coincide with some intersection edge
5969 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(pDS->PaveBlocks(pDS->Index(aE)));
5970 for (; aItLPB.More(); aItLPB.Next()) {
5971 if (pDS->IsCommonBlock(aItLPB.Value())) {
5972 // find with what it is a common
5973 const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock(aItLPB.Value())->PaveBlocks();
5974 BOPDS_ListIteratorOfListOfPaveBlock aItLPBC(aLPBC);
5975 for (; aItLPBC.More(); aItLPBC.Next()) {
5976 const TopoDS_Shape& aEC = pDS->Shape(aItLPBC.Value()->OriginalEdge());
5977 if (!theMECheckExt.Contains(aEC)) {
5981 if (aItLPBC.More()) {
5986 if (aItLPB.More()) {
5987 // avoid creation of unnecessary splits from commons which
5988 // coincide with intersection edges
5993 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
5995 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
5997 pLEIm->Append(aLEIm);
5999 // save bounding vertices
6000 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
6001 const TopoDS_Shape& aV = aItV.Value();
6002 const TopTools_ListOfShape& aLVIm = aGFCE.Modified(aV);
6003 theMVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
6008 //=======================================================================
6009 //function : GetInvalidEdges
6010 //purpose : Looking for the invalid edges by intersecting with invalid vertices
6011 //=======================================================================
6012 void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
6013 const TopTools_MapOfShape& theMVBounds,
6014 BOPAlgo_Builder& theGF,
6015 TopTools_MapOfShape& theMEInv)
6017 if (theVertsToAvoid.IsEmpty()) {
6021 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6022 // get vertices created with intersection edges
6023 const TopoDS_Shape& aRes = theGF.Shape();
6024 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6025 TopExp::MapShapesAndAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6027 const BOPDS_PDS& pDS = theGF.PDS();
6029 // find invalid splits of edges
6030 // check if the vertex is invalid:
6031 // a. it may be the vertex SD with the vertices to avoid
6032 // b. or it may be the vertex which is created by the intersection
6033 // of only existing edges, i.e. no new intersection edges goes
6034 // through this vertex
6036 TopTools_MapOfShape aMVInv;
6037 Standard_Integer i, aNb = aDMVE.Extent();
6038 for (i = 1; i <= aNb; ++i) {
6039 const TopoDS_Vertex& aV = TopoDS::Vertex(aDMVE.FindKey(i));
6040 if (theMVBounds.Contains(aV)) {
6044 Standard_Integer nV = pDS->Index(aV);
6045 if ((nV >= 0) && !pDS->IsNewShape(nV)) {
6049 TopTools_MapIteratorOfMapOfShape aItM(theVertsToAvoid);
6050 for (; aItM.More(); aItM.Next()) {
6051 const TopoDS_Vertex& aVInv = *(TopoDS_Vertex*)&aItM.Value();
6052 Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV(aV, aVInv);
6060 const TopTools_ListOfShape& aLVE = aDMVE.FindFromKey(aV);
6061 aIt.Initialize(aLVE);
6062 for (; aIt.More(); aIt.Next()) {
6063 const TopoDS_Shape& aE = aIt.Value();
6070 //=======================================================================
6071 //function : UpdateValidEdges
6072 //purpose : Making the new splits and updating the maps
6073 //=======================================================================
6074 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6075 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
6076 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
6077 const TopTools_MapOfShape& theMVBounds,
6078 const TopoDS_Shape& theSolids,
6079 const TopTools_IndexedMapOfShape& theInvEdges,
6080 const TopTools_MapOfShape& theInvertedEdges,
6081 const TopTools_MapOfShape& theMEInvOnArt,
6082 TopTools_MapOfShape& theMECheckExt,
6083 TopTools_IndexedMapOfShape& theEdgesToAvoid,
6084 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
6085 TopTools_DataMapOfShapeListOfShape& theOEImages,
6086 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6087 TopTools_MapOfShape& theVertsToAvoid,
6088 TopTools_DataMapOfShapeShape& theETrimEInf,
6089 TopTools_DataMapOfShapeListOfShape& theEImages,
6090 TopTools_DataMapOfShapeListOfShape& theEETrim,
6091 TopTools_MapOfShape& theModifiedEdges,
6092 Handle(BRepAlgo_AsDes)& theAsDes)
6094 // update images and origins of edges, plus update AsDes
6097 TopTools_ListOfShape aLE;
6098 // back connection from edges to faces
6099 TopTools_DataMapOfShapeListOfShape aMELF;
6101 TopTools_MapOfShape aMETmp;
6102 Standard_Integer i, aNb = theFLE.Extent();
6103 for (i = 1; i <= aNb; ++i) {
6104 const TopoDS_Face& aF = TopoDS::Face(theFLE.FindKey(i));
6106 const TopTools_ListOfShape& aLEInt = theFLE(i);
6107 TopTools_ListIteratorOfListOfShape aItLE(aLEInt);
6108 for (; aItLE.More(); aItLE.Next()) {
6109 const TopoDS_Shape& aE = aItLE.Value();
6110 if ((theMECheckExt.Contains(aE) || aMETmp.Contains(aE)) && !theEImages.IsBound(aE)) {
6111 theMECheckExt.Remove(aE);
6115 TopTools_ListOfShape* pLF = aMELF.ChangeSeek(aE);
6117 pLF = aMELF.Bound(aE, TopTools_ListOfShape());
6124 if (aLE.IsEmpty()) {
6128 // bounding edges, that are going to be replaced
6129 TopTools_MapOfShape aMEB;
6131 // new intersection edges
6132 TopTools_MapOfShape aMENew;
6133 // map of old vertices
6134 TopTools_MapOfShape aMVOld;
6135 // back connection to untrimmed edges
6136 TopTools_DataMapOfShapeListOfShape aDMEOr;
6138 // trim the new intersection edges
6139 TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt,
6140 theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF);
6142 if (theEImages.IsEmpty())
6144 // No new splits is preserved
6145 // update intersection edges and exit
6146 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6147 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6153 // Make connexity blocks of the invalid edges
6154 // and treat each block separately
6156 // Compound of all invalid edges to make the blocks
6157 TopoDS_Compound aCEAll;
6158 aBB.MakeCompound(aCEAll);
6160 Standard_Integer aNbE = theOENEdges.Extent();
6161 for (i = 1; i <= aNbE; ++i)
6162 aBB.Add(aCEAll, theOENEdges.FindKey(i));
6164 // Separate the edges into blocks
6165 TopTools_ListOfShape aLBlocks;
6166 BOPTools_AlgoTools::MakeConnexityBlocks(aCEAll, TopAbs_VERTEX, TopAbs_EDGE, aLBlocks);
6168 // Perform intersection of the new splits for each block
6170 // Intersected splits
6171 TopTools_IndexedDataMapOfShapeListOfShape aMBlocksSp;
6173 TopTools_ListIteratorOfListOfShape aItLB(aLBlocks);
6174 for (; aItLB.More(); aItLB.Next())
6176 const TopoDS_Shape& aBlock = aItLB.Value();
6178 // Get the list of new edges for the block
6179 TopTools_ListOfShape aBlockLENew;
6182 TopTools_MapOfShape aMEFence;
6183 TopExp_Explorer anExpE(aBlock, TopAbs_EDGE);
6184 for (; anExpE.More(); anExpE.Next())
6186 const TopoDS_Shape& aE = anExpE.Current();
6187 const TopTools_ListOfShape& aLEInt = theOENEdges.FindFromKey(aE);
6188 TopTools_ListIteratorOfListOfShape aItLEInt(aLEInt);
6189 for (; aItLEInt.More(); aItLEInt.Next())
6191 if (aMEFence.Add(aItLEInt.Value()))
6192 aBlockLENew.Append(aItLEInt.Value());
6197 if (aBlockLENew.IsEmpty())
6200 // Get the splits of new edges to intersect
6201 TopTools_ListOfShape aLSplits;
6203 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
6204 for (; aItLE.More(); aItLE.Next())
6206 const TopoDS_Shape& aE = aItLE.Value();
6207 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
6208 if (!pLEIm || pLEIm->IsEmpty())
6211 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6212 for (; aItLEIm.More(); aItLEIm.Next())
6213 aLSplits.Append(aItLEIm.Value());
6216 if (aLSplits.IsEmpty())
6220 if (aLSplits.Extent() > 1)
6221 // Intersect the new splits among themselves to avoid self-intersections
6222 IntersectEdges(aLSplits, aBlockLENew, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6223 theEImages, theModifiedEdges, aDMEOr, aMELF, aCE);
6225 aCE = aLSplits.First();
6227 aMBlocksSp.Add(aCE, aBlockLENew);
6230 // Perform filtering of the edges in two steps:
6231 // - Check each block separately using localized bounds
6232 // taken only from the splits of faces of the current block;
6233 // - Intersect all splits together and filter the splits by all bounds.
6235 // FIRST STAGE - separate treatment of the blocks
6237 // Valid splits to be preserved on the first stage
6238 TopTools_MapOfShape aMEVal;
6240 // Blocks of valid edges on the first stage
6241 TopTools_ListOfShape aLValBlocks;
6243 // Context for caching the classification tools
6244 Handle(IntTools_Context) aCtx = new IntTools_Context;
6246 Standard_Integer aNbB = aMBlocksSp.Extent();
6247 for (i = 1; i <= aNbB; ++i)
6249 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6250 const TopTools_ListOfShape& aBlockLENew = aMBlocksSp(i);
6252 // Get all participating faces to get the bounds
6253 TopTools_ListOfShape aLFaces;
6254 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
6255 for (; aItLE.More(); aItLE.Next())
6257 const TopTools_ListOfShape *pLF = aMELF.Seek(aItLE.Value());
6260 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
6261 for (; aItLF.More(); aItLF.Next())
6262 AppendToList(aLFaces, aItLF.Value());
6265 // Localized bounds of the splits of the offset faces
6266 // to filter the new splits of the current block
6267 TopoDS_Shape aFilterBounds;
6268 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6270 // Filter the splits by bounds
6271 TopTools_MapOfShape aMEInvLoc;
6272 GetInvalidEdgesByBounds(aCE, aFilterBounds, theFImages, theSolids,
6273 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6274 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInvLoc);
6276 // Keep only valid edges of the block
6277 TopoDS_Compound aCEVal;
6278 aBB.MakeCompound(aCEVal);
6280 Standard_Boolean bKept = Standard_False;
6282 TopExp_Explorer anExpE(aCE, TopAbs_EDGE);
6283 for (; anExpE.More(); anExpE.Next())
6285 const TopoDS_Shape& aESp = anExpE.Current();
6286 if (!aMEInvLoc.Contains(aESp) && aMEVal.Add(aESp))
6288 aBB.Add(aCEVal, aESp);
6289 bKept = Standard_True;
6294 aLValBlocks.Append(aCEVal);
6297 // Filter the images of edges after the first filtering stage
6298 TopoDS_Shape aSplits1;
6299 FilterSplits(aLE, aMEVal, Standard_False, theEImages, aSplits1);
6301 if (aLValBlocks.IsEmpty())
6303 // update intersection edges
6304 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6305 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6309 // SECOND STAGE - Filter the remaining splits together
6311 // Add for intersection already removed new edges using them
6312 // as markers for other invalid edges
6313 aNbB = aMBlocksSp.Extent();
6314 for (i = 1; i <= aNbB; ++i)
6316 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6317 for (TopExp_Explorer anExp(aCE, TopAbs_EDGE); anExp.More(); anExp.Next())
6319 const TopoDS_Shape& aEIm = anExp.Current();
6320 if (aMENew.Contains(aEIm) && !aMEVal.Contains(aEIm))
6321 aLValBlocks.Append(aEIm);
6325 if (aLValBlocks.Extent() > 1)
6326 // intersect the new splits among themselves to avoid self-intersections
6327 IntersectEdges(aLValBlocks, aLE, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6328 theEImages, theModifiedEdges, aDMEOr, aMELF, aSplits1);
6330 aSplits1 = aLValBlocks.First();
6332 // Get all faces to get the bounds from their splits
6333 TopTools_ListOfShape aLFaces;
6334 for (i = 1; i <= theFImages.Extent(); ++i)
6335 aLFaces.Append(theFImages.FindKey(i));
6337 // Bounds of the splits of the offset faces to filter the new splits
6338 TopoDS_Shape aFilterBounds;
6339 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6341 // Filter the splits by intersection with bounds
6342 TopTools_MapOfShape aMEInv;
6343 GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids,
6344 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6345 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInv);
6347 // Filter the images of edges after the second filtering stage
6348 // and combine all valid edges into a single compound
6349 TopoDS_Shape aSplits;
6350 FilterSplits(aLE, aMEInv, Standard_True, theEImages, aSplits);
6352 // get bounds to update
6353 // we need to update the edges of all the affected faces
6354 TopTools_ListOfShape aLF;
6355 // prepare the vertices from new splits of edges
6356 TopTools_IndexedMapOfShape aMVSp;
6357 TopExp::MapShapes(aSplits, TopAbs_VERTEX, aMVSp);
6359 Standard_Integer aNbF = theFImages.Extent();
6360 for (i = 1; i <= aNbF; ++i) {
6361 const TopoDS_Shape& aF = theFImages.FindKey(i);
6362 if (theFLE.Contains(aF)) {
6367 // check the splits of faces to have vertices from splits
6368 const TopTools_ListOfShape& aLFIm = theFImages(i);
6369 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
6370 for (; aItLFIm.More(); aItLFIm.Next()) {
6371 const TopoDS_Shape& aFIm = aItLFIm.Value();
6373 TopExp_Explorer aExpV(aFIm, TopAbs_VERTEX);
6374 for (; aExpV.More(); aExpV.Next()) {
6375 const TopoDS_Shape& aV = aExpV.Current();
6376 if (aMVSp.Contains(aV)) {
6386 if (aItLFIm.More()) {
6391 // get bounds from splits of faces of aLF
6392 TopoDS_Shape aBounds;
6393 TopTools_ListOfShape aLAValid, aLABounds;
6394 GetBoundsToUpdate(aLF, theOEImages, theOEOrigins, aMEB,
6395 aLABounds, aLAValid, aBounds, theAsDes);
6397 // Intersect valid splits with bounds and update both
6398 BOPAlgo_Builder aGF;
6399 aGF.AddArgument(aBounds);
6400 aGF.AddArgument(aSplits);
6404 UpdateImages(aLE, theEImages, aGF, theModifiedEdges);
6406 // update new intersection edges
6407 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6408 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6411 UpdateImages(aLAValid, theOEImages, aGF, theModifiedEdges);
6412 UpdateOrigins(aLABounds, theOEOrigins, aGF);
6413 UpdateOrigins(aLABounds, theEdgesOrigins, aGF);
6414 UpdateIntersectedEdges(aLABounds, theETrimEInf, aGF);
6416 // update the EdgesToAvoid with the splits
6417 TopTools_IndexedMapOfShape aNewEdges;
6418 const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek(aSplits);
6420 TopTools_ListIteratorOfListOfShape aItSpIm(*pSplitsIm);
6421 for (; aItSpIm.More(); aItSpIm.Next()) {
6422 TopExp::MapShapes(aItSpIm.Value(), TopAbs_EDGE, aNewEdges);
6426 // Rebuild the map of edges to avoid, using the intersection results
6427 TopTools_IndexedMapOfShape aMEAvoid;
6428 // GF's data structure
6429 const BOPDS_PDS& pDS = aGF.PDS();
6431 aNbE = theEdgesToAvoid.Extent();
6432 for (i = 1; i <= aNbE; ++i)
6434 const TopoDS_Shape& aE = theEdgesToAvoid(i);
6435 const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
6437 // Only untouched and fully coinciding edges should be kept in the avoid map
6438 Standard_Boolean bKeep = aLEIm.IsEmpty();
6439 if (aLEIm.Extent() == 1 && aE.IsSame(aLEIm.First()))
6441 const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(pDS->Index(aE));
6442 if (aLPB.Extent() == 1)
6444 const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
6445 const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock(aPB);
6448 const BOPDS_ListOfPaveBlock& aLPBCB = aCB->PaveBlocks();
6449 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
6450 for (; aItLPB.More(); aItLPB.Next())
6452 if (pDS->PaveBlocks(aItLPB.Value()->OriginalEdge()).Extent() > 1)
6455 bKeep = !aItLPB.More();
6462 // keep the original edge
6467 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6468 for (; aItLEIm.More(); aItLEIm.Next())
6470 const TopoDS_Shape& aEIm = aItLEIm.Value();
6471 if (!aNewEdges.Contains(aEIm))
6475 theEdgesToAvoid = aMEAvoid;
6478 //=======================================================================
6479 //function : TrimNewIntersectionEdges
6481 //=======================================================================
6482 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
6483 const TopTools_DataMapOfShapeListOfShape& theEETrim,
6484 const TopTools_MapOfShape& theMVBounds,
6485 TopTools_MapOfShape& theMECheckExt,
6486 TopTools_DataMapOfShapeListOfShape& theEImages,
6487 TopTools_MapOfShape& theMEB,
6488 TopTools_MapOfShape& theMVOld,
6489 TopTools_MapOfShape& theMENew,
6490 TopTools_DataMapOfShapeListOfShape& theDMEOr,
6491 TopTools_DataMapOfShapeListOfShape& theMELF)
6493 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6494 aIt.Initialize(theLE);
6495 for (; aIt.More(); aIt.Next()) {
6496 const TopoDS_Shape& aE = aIt.Value();
6498 Standard_Boolean bCheckExt = theMECheckExt.Remove(aE);
6500 Standard_Boolean bOld = theEETrim.IsBound(aE);
6502 const TopTools_ListOfShape& aLET = theEETrim.Find(aE);
6503 aIt1.Initialize(aLET);
6504 for (; aIt1.More(); aIt1.Next()) {
6505 const TopoDS_Shape& aET = aIt1.Value();
6507 TopExp_Explorer aExpV(aET, TopAbs_VERTEX);
6508 for (; aExpV.More(); aExpV.Next()) {
6509 const TopoDS_Shape& aV = aExpV.Current();
6515 if (!theEImages.IsBound(aE)) {
6519 TopTools_ListOfShape& aLEIm = theEImages.ChangeFind(aE);
6520 if (aLEIm.IsEmpty()) {
6521 theEImages.UnBind(aE);
6526 TopTools_MapOfShape aMEVBounds;
6528 if (aLEIm.Extent() > 1) {
6529 TopTools_IndexedMapOfShape aMV;
6531 BOPAlgo_Builder aGFE;
6532 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6533 for (; aItLEIm.More(); aItLEIm.Next()) {
6534 const TopoDS_Shape& aEIm = aItLEIm.Value();
6535 aGFE.AddArgument(aEIm);
6536 TopExp::MapShapes(aEIm, TopAbs_VERTEX, aMV);
6539 // add two bounding vertices of this edge to the operation
6540 TopoDS_Vertex aV1, aV2;
6541 TopExp::Vertices(TopoDS::Edge(aE), aV1, aV2);
6543 aGFE.AddArgument(aV1);
6544 aGFE.AddArgument(aV2);
6549 if (!aGFE.HasErrors()) {
6550 // get images of bounding vertices to remove splits containing them
6551 // in case some of the bounding edges has been interfered
6552 // during operation it is necessary to update their images as well
6553 Standard_Integer iV, aNbV = aMV.Extent();
6554 for (iV = 1; iV <= aNbV; ++iV) {
6555 const TopoDS_Shape& aV = aMV(iV);
6556 if (theMVBounds.Contains(aV) || aV.IsSame(aV1) || aV.IsSame(aV2)) {
6557 const TopTools_ListOfShape& aLVIm = aGFE.Modified(aV);
6558 aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
6562 aCEIm = aGFE.Shape();
6566 aCEIm = aLEIm.First();
6571 TopExp_Explorer aExp(aCEIm, TopAbs_EDGE);
6572 for (; aExp.More(); aExp.Next()) {
6573 const TopoDS_Shape& aEIm = aExp.Current();
6575 // check the split not to contain bounding vertices
6576 TopoDS_Iterator aItV(aEIm);
6577 for (; aItV.More(); aItV.Next()) {
6578 const TopoDS_Shape& aV = aItV.Value();
6579 if (aMEVBounds.Contains(aV) || theMVBounds.Contains(aV)) {
6587 theDMEOr.Bound(aEIm, TopTools_ListOfShape())->Append(aE);
6591 if (aLEIm.IsEmpty()) {
6592 theEImages.UnBind(aE);
6595 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6596 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6597 for (; aItLEIm.More(); aItLEIm.Next()) {
6598 const TopoDS_Shape& aEIm = aItLEIm.Value();
6599 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6601 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6603 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6604 for (; aItLF.More(); aItLF.Next()) {
6605 AppendToList(*pLFEIm, aItLF.Value());
6609 theMECheckExt.Add(aEIm);
6619 //=======================================================================
6620 //function : IntersectEdges
6621 //purpose : Intersecting the trimmed edges to avoid self-intersections
6622 //=======================================================================
6623 void IntersectEdges(const TopTools_ListOfShape& theLA,
6624 const TopTools_ListOfShape& theLE,
6625 const TopTools_MapOfShape& theMVBounds,
6626 const TopTools_MapOfShape& theVertsToAvoid,
6627 TopTools_MapOfShape& theMENew,
6628 TopTools_MapOfShape& theMECheckExt,
6629 TopTools_DataMapOfShapeListOfShape& theEImages,
6630 TopTools_MapOfShape& theModifiedEdges,
6631 TopTools_DataMapOfShapeListOfShape& theDMEOr,
6632 TopTools_DataMapOfShapeListOfShape& theMELF,
6633 TopoDS_Shape& theSplits)
6635 BOPAlgo_Builder aGFA;
6636 aGFA.SetArguments(theLA);
6638 if (aGFA.HasErrors()) {
6639 // just copy input to the result
6640 TopoDS_Compound aSp;
6642 aBB.MakeCompound(aSp);
6643 TopTools_ListIteratorOfListOfShape anIt(theLA);
6644 for (; anIt.More(); anIt.Next()) {
6645 const TopoDS_Shape& aE = anIt.Value();
6652 UpdateImages(theLE, theEImages, aGFA, theModifiedEdges);
6654 // compound of valid splits
6655 theSplits = aGFA.Shape();
6657 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6659 // prepare list of edges to update
6660 TopTools_ListOfShape aLEInput;
6661 for (aIt.Initialize(theLA); aIt.More(); aIt.Next())
6663 TopExp_Explorer anExpE(aIt.Value(), TopAbs_EDGE);
6664 for (; anExpE.More(); anExpE.Next())
6665 aLEInput.Append(anExpE.Current());
6669 aIt.Initialize(aLEInput);
6670 for (; aIt.More(); aIt.Next()) {
6671 const TopoDS_Shape& aE = aIt.Value();
6672 if (!theMENew.Contains(aE))
6675 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
6676 if (aLEIm.IsEmpty())
6679 theMENew.Remove(aE);
6680 aIt1.Initialize(aLEIm);
6681 for (; aIt1.More(); aIt1.Next())
6682 theMENew.Add(aIt1.Value());
6685 // update edges after intersection for extended checking
6686 aIt.Initialize(aLEInput);
6687 for (; aIt.More(); aIt.Next()) {
6688 const TopoDS_Shape& aE = aIt.Value();
6689 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
6690 if (aLEIm.IsEmpty()) {
6694 if (theMECheckExt.Contains(aE)) {
6695 aIt1.Initialize(aLEIm);
6696 for (; aIt1.More(); aIt1.Next()) {
6697 theMECheckExt.Add(aIt1.Value());
6699 theMECheckExt.Remove(aE);
6702 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6703 aIt1.Initialize(aLEIm);
6704 for (; aIt1.More(); aIt1.Next()) {
6705 const TopoDS_Shape& aEIm = aIt1.Value();
6706 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6708 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6710 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6711 for (; aItLF.More(); aItLF.Next()) {
6712 AppendToList(*pLFEIm, aItLF.Value());
6717 TopTools_MapOfShape aMEInv;
6718 GetInvalidEdges(theVertsToAvoid, theMVBounds, aGFA, aMEInv);
6719 if (aMEInv.Extent()) {
6721 TopoDS_Compound aSp;
6723 aBB.MakeCompound(aSp);
6724 TopExp_Explorer aExp(theSplits, TopAbs_EDGE);
6725 for (; aExp.More(); aExp.Next()) {
6726 const TopoDS_Shape& aE = aExp.Current();
6727 if (!aMEInv.Contains(aE)) {
6735 UpdateOrigins(aLEInput, theDMEOr, aGFA);
6738 //=======================================================================
6739 //function : GetBounds
6740 //purpose : Getting edges from the splits of offset faces
6741 //=======================================================================
6742 void GetBounds(const TopTools_ListOfShape& theLFaces,
6743 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6744 const TopTools_MapOfShape& theMEB,
6745 TopoDS_Shape& theBounds)
6748 // Make compound of edges contained in the splits of faces
6749 TopoDS_Compound aBounds;
6750 aBB.MakeCompound(aBounds);
6752 TopTools_MapOfShape aMFence;
6754 TopTools_ListIteratorOfListOfShape aItLF(theLFaces);
6755 for (; aItLF.More(); aItLF.Next())
6757 const TopTools_ListOfShape* pLFIm = theFImages.Seek(aItLF.Value());
6760 TopTools_ListIteratorOfListOfShape aIt(*pLFIm);
6761 for (; aIt.More(); aIt.Next())
6763 const TopoDS_Shape& aFIm = aIt.Value();
6765 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
6766 for (; aExpE.More(); aExpE.Next())
6768 const TopoDS_Shape& aEIm = aExpE.Current();
6769 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6770 aBB.Add(aBounds, aEIm);
6775 theBounds = aBounds;
6778 //=======================================================================
6779 //function : GetBoundsToUpdate
6780 //purpose : Get bounding edges that should be updated
6781 //=======================================================================
6782 void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
6783 const TopTools_DataMapOfShapeListOfShape& theOEImages,
6784 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6785 const TopTools_MapOfShape& theMEB,
6786 TopTools_ListOfShape& theLABounds,
6787 TopTools_ListOfShape& theLAValid,
6788 TopoDS_Shape& theBounds,
6789 Handle(BRepAlgo_AsDes)& theAsDes)
6792 TopoDS_Compound aBounds;
6794 aBB.MakeCompound(aBounds);
6796 TopTools_MapOfShape aMAValid, aMFence;
6798 TopTools_ListIteratorOfListOfShape aItLF(theLF);
6799 for (; aItLF.More(); aItLF.Next()) {
6800 const TopoDS_Shape& aF = aItLF.Value();
6802 TopTools_IndexedMapOfShape aMDE;
6803 const TopTools_ListOfShape& aLFDes = theAsDes->Descendant(aF);
6804 TopTools_ListIteratorOfListOfShape aItLFDes(aLFDes);
6805 for (; aItLFDes.More(); aItLFDes.Next()) {
6806 const TopoDS_Shape& aED = aItLFDes.Value();
6807 const TopTools_ListOfShape *pLEDIm = theOEImages.Seek(aED);
6813 TopTools_ListIteratorOfListOfShape aItLEDIm(*pLEDIm);
6814 for (; aItLEDIm.More(); aItLEDIm.Next()) {
6815 const TopoDS_Shape& aEDIm = aItLEDIm.Value();
6820 Standard_Integer j, aNbE = aMDE.Extent();
6821 for (j = 1; j <= aNbE; ++j) {
6822 const TopoDS_Edge& aEIm = TopoDS::Edge(aMDE(j));
6824 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6825 aBB.Add(aBounds, aEIm);
6826 theLABounds.Append(aEIm);
6829 const TopTools_ListOfShape *pLO = theOEOrigins.Seek(aEIm);
6831 TopTools_ListIteratorOfListOfShape aItLO(*pLO);
6832 for (; aItLO.More(); aItLO.Next()) {
6833 const TopoDS_Shape& aEO = aItLO.Value();
6835 if (aMAValid.Add(aEO)) {
6836 theLAValid.Append(aEO);
6841 if (aMAValid.Add(aEIm)) {
6842 theLAValid.Append(aEIm);
6847 theBounds = aBounds;
6850 //=======================================================================
6851 //function : GetInvalidEdgesByBounds
6852 //purpose : Filter new splits by intersection with bounds
6853 //=======================================================================
6854 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
6855 const TopoDS_Shape& theBounds,
6856 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6857 const TopoDS_Shape& theSolids,
6858 const TopTools_IndexedMapOfShape& theInvEdges,
6859 const TopTools_MapOfShape& theMVOld,
6860 const TopTools_MapOfShape& theMENew,
6861 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
6862 const TopTools_DataMapOfShapeListOfShape& theMELF,
6863 const TopTools_DataMapOfShapeListOfShape& theEImages,
6864 const TopTools_MapOfShape& theMECheckExt,
6865 const TopTools_MapOfShape& theMEInvOnArt,
6866 Handle(IntTools_Context)& theCtx,
6867 TopTools_MapOfShape& theVertsToAvoid,
6868 TopTools_MapOfShape& theMEInv)
6870 // map splits to check the vertices of edges
6871 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6872 TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6874 BOPAlgo_Section aSec;
6875 aSec.AddArgument(theSplits);
6876 aSec.AddArgument(theBounds);
6881 TopTools_IndexedMapOfShape aMVInv;
6882 // vertices to check additionally by classification relatively to solid
6883 TopTools_MapOfShape aMVCheckAdd;
6884 // collect parts for removal
6885 const BOPDS_PDS& pDS = aSec.PDS();
6887 // check edge/edge intersections
6888 const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
6889 Standard_Integer i, aNb = aEEs.Length();
6890 for (i = 0; i < aNb; ++i) {
6891 const BOPDS_InterfEE& aEE = aEEs(i);
6893 const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1());
6894 const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2());
6896 if (!aEE.HasIndexNew()) {
6897 if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) {
6903 if (theInvEdges.Contains(aE2)) {
6907 if (theMEInvOnArt.Contains(aE2)) {
6908 // avoid checking of the vertices of the split edge intersected by
6909 // the invalid edge from artificial face
6910 TopoDS_Vertex aV1, aV2;
6911 TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2);
6912 if (aDMVE.Contains(aV1) && aDMVE.Contains(aV2)) {
6917 // add vertices of all images of the edge from splits for checking
6918 const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1);
6919 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr);
6920 for (; aItLEOr.More(); aItLEOr.Next()) {
6921 const TopoDS_Shape& aEOr = aItLEOr.Value();
6923 const TopTools_ListOfShape *pLEIm = theEImages.Seek(aEOr);
6926 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6927 for (; aItLEIm.More(); aItLEIm.Next()) {
6928 const TopoDS_Shape& aEIm = aItLEIm.Value();
6930 TopoDS_Iterator aItV(aEIm);
6931 for (; aItV.More(); aItV.Next()) {
6932 const TopoDS_Shape& aV = aItV.Value();
6933 if (!theMVOld.Contains(aV)) {
6935 aMVCheckAdd.Add(aV);
6942 // to avoid unnecessary filling of parts due to extra trim of the edges
6943 // process Edge/Edge interferences of type EDGE, i.e. common blocks and check
6944 // not the bounding vertices of the edges, but check the edge itself
6945 // to be lying on some face
6947 // all common blocks are contained in the result of SECTION operation
6948 // between sets of edges
6949 const TopoDS_Shape& aSecR = aSec.Shape();
6951 TopTools_IndexedMapOfShape aMSSec;
6952 TopExp::MapShapes(aSecR, aMSSec);
6954 const TopTools_DataMapOfShapeListOfShape& anIm = aSec.Images();
6955 for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
6957 const TopoDS_Shape& aE = aExp.Current();
6958 if (aSec.IsDeleted(aE)) {
6959 // no common blocks for this edge
6963 const TopTools_ListOfShape* pLEIm = anIm.Seek(aE);
6965 // no splits, i.e. completely coincides with some edge from boundary
6969 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6970 for (; aItLEIm.More(); aItLEIm.Next()) {
6971 const TopoDS_Shape& aEIm = aItLEIm.Value();
6972 if (!aMSSec.Contains(aEIm)) {
6973 // the edge included in section only partially.
6974 // the part not included in section may be excessive
6976 // check vertices of this edge - if one of them is new
6977 // the edge might be removed
6978 TopoDS_Vertex aV1, aV2;
6979 TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2);
6980 if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) {
6981 // add this edge for checking by making new vertex in the middle of the edge
6984 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l);
6985 BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion());
6986 // and adding this vertex for checking
6987 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
6995 // Add for check also the edges created from common between splits
6996 // of offset faces edges not connected to any invalidity.
6997 // These edges may also accidentally fill some part.
6998 TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt);
6999 for (; aItM.More(); aItM.Next()) {
7000 const TopoDS_Shape& aE = aItM.Value();
7002 // make new vertex in the middle of the edge
7005 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l);
7006 BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion());
7007 // add this vertex for checking
7008 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
7012 // add for check also the vertices connected only to new or old edges
7013 aNb = aDMVE.Extent();
7014 for (i = 1; i <= aNb; ++i) {
7015 const TopoDS_Shape& aV = aDMVE.FindKey(i);
7016 if (theMVOld.Contains(aV)) {
7020 Standard_Boolean bNew = Standard_False, bOld = Standard_False;
7021 const TopTools_ListOfShape& aLEx = aDMVE(i);
7022 TopTools_ListIteratorOfListOfShape aIt(aLEx);
7023 for (; aIt.More(); aIt.Next()) {
7024 const TopoDS_Shape& aE = aIt.Value();
7025 if (theMECheckExt.Contains(aE)) {
7029 if (theMENew.Contains(aE)) {
7030 bNew = Standard_True;
7033 bOld = Standard_True;
7041 if (!bNew || !bOld) {
7043 aMVCheckAdd.Remove(aV);
7047 // perform the checking of the vertices
7048 Standard_Integer iv, aNbIV = aMVInv.Extent();
7049 for (iv = 1; iv <= aNbIV; ++iv) {
7050 const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv));
7051 if (theMVOld.Contains(aV)) {
7055 const TopTools_ListOfShape* pLEInv = aDMVE.Seek(aV);
7059 // find faces by the edges to check the vertex
7060 TopTools_IndexedMapOfShape aMF;
7061 TopTools_ListIteratorOfListOfShape aItLE(*pLEInv);
7062 for (; aItLE.More(); aItLE.Next()) {
7063 const TopoDS_Shape& aE = aItLE.Value();
7064 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
7065 TopTools_ListIteratorOfListOfShape aItLF(aLF);
7066 for (; aItLF.More(); aItLF.Next()) {
7067 aMF.Add(aItLF.Value());
7071 // check the vertex to belong to some split of the faces
7072 Standard_Boolean bInvalid = Standard_True;
7074 Standard_Integer aNbF = aMF.Extent();
7075 for (i = 1; i <= aNbF && bInvalid; ++i) {
7076 const TopoDS_Face& aF = TopoDS::Face(aMF(i));
7077 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
7079 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
7080 for (; aItLF.More() && bInvalid; aItLF.Next()) {
7081 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
7082 TopExp_Explorer aExp(aFIm, TopAbs_VERTEX);
7083 for (; aExp.More() && bInvalid; aExp.Next()) {
7084 const TopoDS_Shape& aVF = aExp.Current();
7085 bInvalid = !aVF.IsSame(aV);
7090 Standard_Real U, V, aTol;
7091 Standard_Integer iStatus = theCtx->ComputeVF(aV, aF, U, V, aTol);
7093 // classify the point relatively faces
7094 gp_Pnt2d aP2d(U, V);
7095 aItLF.Initialize(aLFIm);
7096 for (; aItLF.More() && bInvalid; aItLF.Next()) {
7097 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
7098 bInvalid = !theCtx->IsPointInOnFace(aFIm, aP2d);
7104 if (bInvalid && aMVCheckAdd.Contains(aV)) {
7105 // the vertex is invalid for all faces
7106 // check the same vertex for the solids
7107 const gp_Pnt& aP = BRep_Tool::Pnt(aV);
7108 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
7110 TopExp_Explorer aExpS(theSolids, TopAbs_SOLID);
7111 for (; aExpS.More() && bInvalid; aExpS.Next()) {
7112 const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current());
7113 BRepClass3d_SolidClassifier& aSC = theCtx->SolidClassifier(aSol);
7114 aSC.Perform(aP, aTolV);
7115 bInvalid = (aSC.State() == TopAbs_OUT);
7120 theVertsToAvoid.Add(aV);
7121 aItLE.Initialize(*pLEInv);
7122 for (; aItLE.More(); aItLE.Next()) {
7123 theMEInv.Add(aItLE.Value());
7129 //=======================================================================
7130 //function : FilterSplits
7131 //purpose : Filter the images of edges from the invalid edges
7132 //=======================================================================
7133 void FilterSplits(const TopTools_ListOfShape& theLE,
7134 const TopTools_MapOfShape& theMEFilter,
7135 const Standard_Boolean theIsInv,
7136 TopTools_DataMapOfShapeListOfShape& theEImages,
7137 TopoDS_Shape& theSplits)
7139 TopoDS_Compound aSplits;
7140 BRep_Builder().MakeCompound(aSplits);
7141 TopTools_MapOfShape aMFence;
7143 TopTools_ListIteratorOfListOfShape aItLE(theLE);
7144 for (; aItLE.More(); aItLE.Next())
7146 const TopoDS_Shape& aE = aItLE.Value();
7147 TopTools_ListOfShape *pLEIm = theEImages.ChangeSeek(aE);
7151 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
7152 for (; aItLEIm.More();)
7154 const TopoDS_Shape& aEIm = aItLEIm.Value();
7155 if (theMEFilter.Contains(aEIm) == theIsInv)
7157 pLEIm->Remove(aItLEIm);
7161 if (aMFence.Add(aEIm))
7162 BRep_Builder().Add(aSplits, aEIm);
7166 if (pLEIm->IsEmpty())
7167 theEImages.UnBind(aE);
7169 theSplits = aSplits;
7172 //=======================================================================
7173 //function : UpdateNewIntersectionEdges
7174 //purpose : Updating the maps of images and origins of the offset edges
7175 //=======================================================================
7176 void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
7177 const TopTools_DataMapOfShapeListOfShape& theMELF,
7178 const TopTools_DataMapOfShapeListOfShape& theEImages,
7179 const TopTools_IndexedMapOfShape& theInvEdges,
7180 const TopTools_MapOfShape& theInvertedEdges,
7181 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
7182 TopTools_DataMapOfShapeListOfShape& theOEImages,
7183 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
7184 TopTools_DataMapOfShapeShape& theETrimEInf,
7185 TopTools_DataMapOfShapeListOfShape& theEETrim,
7186 TopTools_MapOfShape& theModifiedEdges,
7187 Handle(BRepAlgo_AsDes)& theAsDes)
7189 TopTools_ListOfShape aLEImEmpty;
7190 TopTools_ListIteratorOfListOfShape aIt, aIt1;
7191 // update global maps of images and origins with new splits
7192 aIt.Initialize(theLE);
7193 for (; aIt.More(); aIt.Next()) {
7194 const TopoDS_Shape& aE = aIt.Value();
7196 if (!theEImages.IsBound(aE)) {
7197 TopTools_ListOfShape* pLET = theEETrim.ChangeSeek(aE);
7202 TopTools_ListIteratorOfListOfShape aItLET(*pLET);
7203 for (; aItLET.More();) {
7204 const TopoDS_Shape& aET = aItLET.Value();
7205 if (!theInvEdges.Contains(aET) && !theInvertedEdges.Contains(aET)) {
7206 pLET->Remove(aItLET);
7213 if (pLET->IsEmpty()) {
7218 const TopTools_ListOfShape& aLENew =
7219 theEImages.IsBound(aE) ? theEImages.Find(aE) : aLEImEmpty;
7221 // save connection to untrimmed edge for the next steps
7222 aIt1.Initialize(aLENew);
7223 for (; aIt1.More(); aIt1.Next()) {
7224 const TopoDS_Shape& aET = aIt1.Value();
7225 theETrimEInf.Bind(aET, aE);
7226 theModifiedEdges.Add(aET);
7229 // check if it is existing edge
7230 if (!theEETrim.IsBound(aE)) {
7231 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
7233 // add this edge to AsDes
7234 aIt1.Initialize(aLF);
7235 for (; aIt1.More(); aIt1.Next()) {
7236 const TopoDS_Shape& aF = aIt1.Value();
7237 theAsDes->Add(aF, aE);
7240 // add aE to the images
7241 theOEImages.Bind(aE, aLENew);
7242 theModifiedEdges.Add(aE);
7245 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7246 for (; aItNew.More(); aItNew.Next()) {
7247 const TopoDS_Shape& aENew = aItNew.Value();
7248 if (theOEOrigins.IsBound(aENew)) {
7249 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7250 AppendToList(aEOrigins, aE);
7253 TopTools_ListOfShape aEOrigins;
7254 aEOrigins.Append(aE);
7255 theOEOrigins.Bind(aENew, aEOrigins);
7259 // update connection to initial origins
7260 if (theEdgesOrigins.IsBound(aE)) {
7261 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aE);
7262 aIt1.Initialize(aLENew);
7263 for (; aIt1.More(); aIt1.Next()) {
7264 const TopoDS_Shape& aENew = aIt1.Value();
7265 if (theEdgesOrigins.IsBound(aENew)) {
7266 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7267 TopTools_ListIteratorOfListOfShape aItOrInit(aLEOrInit);
7268 for (; aItOrInit.More(); aItOrInit.Next()) {
7269 const TopoDS_Shape& aEOr = aItOrInit.Value();
7270 AppendToList(aLENewOr, aEOr);
7274 theEdgesOrigins.Bind(aENew, aLEOrInit);
7283 const TopTools_ListOfShape& aLEOld = theEETrim.Find(aE);
7285 // list of initial origins
7286 TopTools_ListOfShape anInitOrigins;
7288 // it is necessary to replace the old edges with new ones
7289 aIt1.Initialize(aLEOld);
7290 for (; aIt1.More(); aIt1.Next()) {
7291 const TopoDS_Shape& aEOld = aIt1.Value();
7293 if (theOEOrigins.IsBound(aEOld)) {
7295 const TopTools_ListOfShape& aEOrigins = theOEOrigins.Find(aEOld);
7297 TopTools_ListIteratorOfListOfShape aItOr(aEOrigins);
7298 for (; aItOr.More(); aItOr.Next()) {
7299 const TopoDS_Shape& aEOr = aItOr.Value();
7301 theModifiedEdges.Add(aEOr);
7303 TopTools_ListOfShape& aEImages = theOEImages.ChangeFind(aEOr);
7305 // remove old edge from images
7306 TopTools_ListIteratorOfListOfShape aItIm(aEImages);
7307 for (; aItIm.More(); ) {
7308 const TopoDS_Shape& aEIm = aItIm.Value();
7309 if (aEIm.IsSame(aEOld)) {
7310 aEImages.Remove(aItIm);
7318 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7319 for (; aItNew.More(); aItNew.Next()) {
7320 const TopoDS_Shape& aENew = aItNew.Value();
7321 AppendToList(aEImages, aENew);
7322 if (theOEOrigins.IsBound(aENew)) {
7323 TopTools_ListOfShape& aENewOrigins = theOEOrigins.ChangeFind(aENew);
7324 AppendToList(aENewOrigins, aEOr);
7327 TopTools_ListOfShape aENewOrigins;
7328 aENewOrigins.Append(aEOr);
7329 theOEOrigins.Bind(aENew, aENewOrigins);
7336 theOEImages.Bind(aEOld, aLENew);
7338 theModifiedEdges.Add(aEOld);
7341 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7342 for (; aItNew.More(); aItNew.Next()) {
7343 const TopoDS_Shape& aENew = aItNew.Value();
7344 if (theOEOrigins.IsBound(aENew)) {
7345 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7346 AppendToList(aEOrigins, aEOld);
7349 TopTools_ListOfShape aEOrigins;
7350 aEOrigins.Append(aEOld);
7351 theOEOrigins.Bind(aENew, aEOrigins);
7356 // update connection to initial shape
7357 if (theEdgesOrigins.IsBound(aEOld)) {
7358 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aEOld);
7359 TopTools_ListIteratorOfListOfShape aItEOrInit(aLEOrInit);
7360 for (; aItEOrInit.More(); aItEOrInit.Next()) {
7361 const TopoDS_Shape& aEOrInit = aItEOrInit.Value();
7362 AppendToList(anInitOrigins, aEOrInit);
7367 if (anInitOrigins.Extent()) {
7368 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7369 for (; aItNew.More(); aItNew.Next()) {
7370 const TopoDS_Shape& aENew = aItNew.Value();
7371 if (theEdgesOrigins.IsBound(aENew)) {
7372 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7373 TopTools_ListIteratorOfListOfShape aItOrInit(anInitOrigins);
7374 for (; aItOrInit.More(); aItOrInit.Next()) {
7375 const TopoDS_Shape& aEOr = aItOrInit.Value();
7376 AppendToList(aLENewOr, aEOr);
7380 theEdgesOrigins.Bind(aENew, anInitOrigins);
7387 //=======================================================================
7388 //function : FillGaps
7389 //purpose : Fill possible gaps (holes) in the splits of the offset faces
7390 //=======================================================================
7391 void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
7393 Standard_Integer aNbF = theFImages.Extent();
7397 // Check the splits of offset faces on the free edges and fill the gaps (holes)
7398 // in created splits, otherwise the closed volume will not be possible to create.
7400 // Map the splits of faces to find free edges
7401 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
7402 for (Standard_Integer i = 1; i <= aNbF; ++i)
7404 TopTools_ListIteratorOfListOfShape itLF(theFImages(i));
7405 for (; itLF.More(); itLF.Next())
7406 TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
7409 // Analyze images of each offset face on the presence of free edges
7410 // and try to fill the holes
7411 for (Standard_Integer i = 1; i <= aNbF; ++i)
7413 TopTools_ListOfShape& aLFImages = theFImages(i);
7414 if (aLFImages.IsEmpty())
7417 // Collect all edges from the splits
7418 TopoDS_Compound anEdges;
7419 BRep_Builder().MakeCompound(anEdges);
7421 // Collect all free edges into a map with reverted orientation
7422 TopTools_MapOfOrientedShape aFreeEdgesMap;
7423 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7424 for (; itLF.More(); itLF.Next())
7426 const TopoDS_Shape& aFIm = itLF.Value();
7427 TopExp_Explorer anExpE(aFIm, TopAbs_EDGE);
7428 for (; anExpE.More(); anExpE.Next())
7430 const TopoDS_Shape& aE = anExpE.Current();
7431 if (aE.Orientation() != TopAbs_FORWARD &&
7432 aE.Orientation() != TopAbs_REVERSED)
7436 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey(aE);
7437 if (aLF.Extent() == 1)
7438 aFreeEdgesMap.Add(aE.Reversed());
7440 BRep_Builder().Add(anEdges, aE);
7444 if (aFreeEdgesMap.IsEmpty())
7448 // Free edges are found - fill the gaps by creating new splits
7449 // of the face using these free edges
7450 const TopoDS_Shape& aF = theFImages.FindKey(i);
7452 // Build new splits using all kept edges and among new splits
7453 // find those containing free edges
7454 TopTools_ListOfShape aLFNew;
7455 TopTools_DataMapOfShapeShape aDummy;
7457 BuildSplitsOfFace(TopoDS::Face(aF), anEdges, aDummy, aLFNew);
7459 // Find faces filling holes
7460 itLF.Initialize(aLFNew);
7461 for (; itLF.More(); itLF.Next())
7463 const TopoDS_Shape& aFNew = itLF.Value();
7464 TopExp_Explorer anExpE(aFNew, TopAbs_EDGE);
7465 for (; anExpE.More(); anExpE.Next())
7467 const TopoDS_Shape& aE = anExpE.Current();
7468 if (aFreeEdgesMap.Contains(aE))
7470 // Add face to splits
7471 aLFImages.Append(aFNew);
7479 //=======================================================================
7480 //function : FillHistory
7481 //purpose : Saving obtained results in history tools
7482 //=======================================================================
7483 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
7484 const TopTools_DataMapOfShapeListOfShape& theEImages,
7485 BRepAlgo_Image& theImage)
7487 Standard_Integer aNbF = theFImages.Extent();
7492 // Build compound of faces to see preliminary result
7493 TopoDS_Compound aDFaces;
7494 BRep_Builder().MakeCompound(aDFaces);
7497 // Map of kept edges
7498 TopTools_IndexedMapOfShape anEdgesMap;
7500 // Fill history for faces
7501 for (Standard_Integer i = 1; i <= aNbF; ++i)
7503 const TopTools_ListOfShape& aLFImages = theFImages(i);
7504 if (aLFImages.IsEmpty())
7507 // Add the splits to history map
7508 const TopoDS_Shape& aF = theFImages.FindKey(i);
7509 if (theImage.HasImage(aF))
7510 theImage.Add(aF, aLFImages);
7512 theImage.Bind(aF, aLFImages);
7514 // Collect edges from splits
7515 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7516 for (; itLF.More(); itLF.Next())
7518 const TopoDS_Shape& aFIm = itLF.Value();
7519 TopExp::MapShapes(aFIm, TopAbs_EDGE, anEdgesMap);
7522 BRep_Builder().Add(aDFaces, aFIm);
7527 // Fill history for edges (iteration by the map is safe because the
7528 // order is not important here)
7529 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(theEImages);
7530 for (; aItEIm.More(); aItEIm.Next())
7532 const TopoDS_Shape& aE = aItEIm.Key();
7533 const TopTools_ListOfShape& aLEIm = aItEIm.Value();
7535 Standard_Boolean bHasImage = theImage.HasImage(aE);
7536 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
7537 for (; aItLE.More(); aItLE.Next())
7539 const TopoDS_Shape& aEIm = aItLE.Value();
7540 if (anEdgesMap.Contains(aEIm))
7544 theImage.Add(aE, aEIm);
7548 theImage.Bind(aE, aEIm);
7549 bHasImage = Standard_True;
7556 //=======================================================================
7557 //function : ProcessMicroEdge
7558 //purpose : Checking if the edge is micro edge
7559 //=======================================================================
7560 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
7561 const Handle(IntTools_Context)& theCtx)
7563 TopoDS_Vertex aV1, aV2;
7564 TopExp::Vertices(theEdge, aV1, aV2);
7565 if (aV1.IsNull() || aV2.IsNull()) {
7566 return Standard_False;
7569 Standard_Boolean bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx);
7570 if (bMicro && BRepAdaptor_Curve(theEdge).GetType() == GeomAbs_Line) {
7571 Standard_Real aLen = BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
7572 BRep_Builder().UpdateVertex(aV1, aLen / 2.);
7573 BRep_Builder().UpdateVertex(aV2, aLen / 2.);
7579 //=======================================================================
7580 //function : UpdateOrigins
7581 //purpose : Updating origins
7582 //=======================================================================
7583 void UpdateOrigins(const TopTools_ListOfShape& theLA,
7584 TopTools_DataMapOfShapeListOfShape& theOrigins,
7585 BOPAlgo_Builder& theGF)
7587 TopTools_ListIteratorOfListOfShape aItA(theLA);
7588 for (; aItA.More(); aItA.Next()) {
7589 const TopoDS_Shape& aS = aItA.Value();
7591 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7592 if (aLSIm.IsEmpty()) {
7596 TopTools_ListOfShape aLSEmpt;
7597 TopTools_ListOfShape *pLS = theOrigins.ChangeSeek(aS);
7603 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7604 for (; aIt.More(); aIt.Next()) {
7605 const TopoDS_Shape& aSIm = aIt.Value();
7607 TopTools_ListOfShape *pLSOr = theOrigins.ChangeSeek(aSIm);
7609 // just bind the origins
7610 theOrigins.Bind(aSIm, *pLS);
7614 TopTools_ListIteratorOfListOfShape aIt1(*pLS);
7615 for (; aIt1.More(); aIt1.Next()) {
7616 const TopoDS_Shape& aS1 = aIt1.Value();
7617 AppendToList(*pLSOr, aS1);
7624 //=======================================================================
7625 //function : UpdateImages
7626 //purpose : Updating images of the shapes
7627 //=======================================================================
7628 void UpdateImages(const TopTools_ListOfShape& theLA,
7629 TopTools_DataMapOfShapeListOfShape& theImages,
7630 BOPAlgo_Builder& theGF,
7631 TopTools_MapOfShape& theModified)
7633 TopTools_ListIteratorOfListOfShape aIt(theLA);
7634 for (; aIt.More(); aIt.Next())
7636 const TopoDS_Shape& aS = aIt.Value();
7638 TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS);
7641 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7644 theImages.Bind(aS, aLSIm);
7645 theModified.Add(aS);
7650 TopTools_MapOfShape aMFence;
7651 TopTools_ListOfShape aLSImNew;
7653 Standard_Boolean bModified = Standard_False;
7655 // check modifications of the images
7656 TopTools_ListIteratorOfListOfShape aIt1(*pLSIm);
7657 for (; aIt1.More(); aIt1.Next())
7659 const TopoDS_Shape& aSIm = aIt1.Value();
7660 bModified |= TakeModified(aSIm, theGF.Images(), aLSImNew, &aMFence);
7666 theModified.Add(aS);
7671 //=======================================================================
7672 //function : UpdateIntersectedEdges
7673 //purpose : Saving connection from trimmed edges to not trimmed ones
7674 //=======================================================================
7675 void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
7676 TopTools_DataMapOfShapeShape& theETrimEInf,
7677 BOPAlgo_Builder& theGF)
7679 TopTools_ListIteratorOfListOfShape aItA(theLA);
7680 for (; aItA.More(); aItA.Next()) {
7681 const TopoDS_Shape& aS = aItA.Value();
7683 const TopoDS_Shape* pEInf = theETrimEInf.Seek(aS);
7688 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7689 if (aLSIm.IsEmpty()) {
7693 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7694 for (; aIt.More(); aIt.Next()) {
7695 const TopoDS_Shape& aEIm = aIt.Value();
7696 if (!theETrimEInf.IsBound(aEIm)) {
7697 theETrimEInf.Bind(aEIm, *pEInf);
7703 //=======================================================================
7704 //function : FindCommonParts
7705 //purpose : Looking for the parts of type <theType> contained in both lists
7706 //=======================================================================
7707 void FindCommonParts(const TopTools_ListOfShape& theLS1,
7708 const TopTools_ListOfShape& theLS2,
7709 TopTools_ListOfShape& theLSC,
7710 const TopAbs_ShapeEnum theType)
7712 // map shapes in the first list
7713 TopTools_IndexedMapOfShape aMS1;
7714 TopTools_ListIteratorOfListOfShape aIt(theLS1);
7715 for (; aIt.More(); aIt.Next()) {
7716 const TopoDS_Shape& aS = aIt.Value();
7717 TopExp::MapShapes(aS, theType, aMS1);
7720 if (aMS1.IsEmpty()) {
7724 TopTools_MapOfShape aMFence;
7725 // check for such shapes in the other list
7726 aIt.Initialize(theLS2);
7727 for (; aIt.More(); aIt.Next()) {
7728 const TopoDS_Shape& aS = aIt.Value();
7730 TopExp_Explorer aExp(aS, theType);
7731 for(; aExp.More(); aExp.Next()) {
7732 const TopoDS_Shape& aST = aExp.Current();
7734 if (aMS1.Contains(aST) && aMFence.Add(aST)) {
7741 //=======================================================================
7742 //function : NbPoints
7743 //purpose : Defines number of sample points to get average direction of the edge
7744 //=======================================================================
7745 Standard_Integer NbPoints(const TopoDS_Edge& theEdge)
7747 Standard_Integer aNbP;
7748 BRepAdaptor_Curve aBAC(theEdge);
7749 switch (aBAC.GetType()) {
7760 //=======================================================================
7761 //function : FindShape
7762 //purpose : Looking for the same sub-shape in the shape
7763 //=======================================================================
7764 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
7765 const TopoDS_Shape& theSWhere,
7766 const BRepOffset_Analyse* theAnalyse,
7767 TopoDS_Shape& theRes)
7769 Standard_Boolean bFound = Standard_False;
7770 TopAbs_ShapeEnum aType = theSWhat.ShapeType();
7771 TopExp_Explorer aExp(theSWhere, aType);
7772 for (; aExp.More(); aExp.Next()) {
7773 const TopoDS_Shape& aS = aExp.Current();
7774 if (aS.IsSame(theSWhat)) {
7776 bFound = Standard_True;
7781 if (!bFound && theAnalyse)
7783 const TopTools_ListOfShape *pLD = theAnalyse->Descendants (theSWhere);
7786 for (TopTools_ListOfShape::Iterator it (*pLD); it.More(); it.Next())
7788 const TopoDS_Shape& aS = it.Value();
7789 if (aS.IsSame (theSWhat))
7792 bFound = Standard_True;
7803 //=======================================================================
7804 //function : AppendToList
7805 //purpose : Add to a list only unique elements
7806 //=======================================================================
7807 void AppendToList(TopTools_ListOfShape& theList,
7808 const TopoDS_Shape& theShape)
7810 TopTools_ListIteratorOfListOfShape aIt(theList);
7811 for (; aIt.More(); aIt.Next()) {
7812 const TopoDS_Shape& aS = aIt.Value();
7813 if (aS.IsSame(theShape)) {
7817 theList.Append(theShape);
7820 //=======================================================================
7821 //function : AddToContainer
7822 //purpose : Set of methods to add a shape into container
7823 //=======================================================================
7824 static void AddToContainer(const TopoDS_Shape& theS,
7825 TopTools_ListOfShape& theList)
7827 theList.Append(theS);
7829 static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7830 TopTools_MapOfShape& theMap)
7832 return theMap.Add(theS);
7834 static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7835 TopTools_IndexedMapOfShape& theMap)
7837 const Standard_Integer aNb = theMap.Extent();
7838 const Standard_Integer anInd = theMap.Add(theS);
7841 static void AddToContainer(const TopoDS_Shape& theS,
7842 TopoDS_Shape& theSOut)
7844 BRep_Builder().Add(theSOut, theS);
7847 //=======================================================================
7848 //function : TakeModified
7849 //purpose : Check if the shape has images in the given images map.
7850 // Puts in the output map either the images or the shape itself.
7851 //=======================================================================
7852 template <class ContainerType, class FenceMapType>
7853 Standard_Boolean TakeModified(const TopoDS_Shape& theS,
7854 const TopTools_DataMapOfShapeListOfShape& theImages,
7855 ContainerType& theContainer,
7856 FenceMapType* theMFence)
7858 const TopTools_ListOfShape *pLSIm = theImages.Seek(theS);
7861 TopTools_ListIteratorOfListOfShape itLSIm(*pLSIm);
7862 for (; itLSIm.More(); itLSIm.Next())
7864 const TopoDS_Shape& aSIm = itLSIm.Value();
7865 if (!theMFence || AddToContainer(aSIm, *theMFence))
7866 AddToContainer(aSIm, theContainer);
7868 return Standard_True;
7872 if (!theMFence || AddToContainer(theS, *theMFence))
7873 AddToContainer(theS, theContainer);
7874 return Standard_False;