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);
110 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
111 const TopTools_MapOfShape& theModifiedEdges,
112 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
113 const BRepOffset_Analyse* theAnalyse,
114 Handle(BRepAlgo_AsDes)& theAsDes,
115 TopTools_DataMapOfShapeShape& theFacesOrigins,
116 TopTools_DataMapOfShapeListOfShape& theOEImages,
117 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
118 TopTools_MapOfShape& theLastInvEdges,
119 TopTools_IndexedMapOfShape& theEdgesToAvoid,
120 TopTools_IndexedMapOfShape& theInvEdges,
121 TopTools_IndexedMapOfShape& theValidEdges,
122 TopTools_MapOfShape& theInvertedEdges,
123 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
124 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
125 TopTools_DataMapOfShapeShape& theArtInvFaces,
126 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
127 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
128 TopoDS_Shape& theSolids,
129 TopTools_DataMapOfShapeListOfShape& theSSInterfs);
132 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
133 const TopTools_MapOfShape& theModifiedEdges,
134 const BRepOffset_Analyse* theAnalyse,
135 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
136 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
137 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
138 TopTools_DataMapOfShapeShape& theFacesOrigins,
139 TopTools_DataMapOfShapeListOfShape& theOEImages,
140 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
141 TopTools_MapOfShape& theLastInvEdges,
142 TopTools_IndexedMapOfShape& theEdgesToAvoid,
143 TopTools_MapOfShape& theVertsToAvoid,
144 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
145 TopTools_IndexedMapOfShape& theValidEdges,
146 TopTools_DataMapOfShapeShape& theETrimEInf,
147 Handle(BRepAlgo_AsDes)& theAsDes);
150 Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
151 const TopTools_ListOfShape& theLFImages,
152 const TopoDS_Shape& theCE,
153 const TopTools_IndexedMapOfShape& theMapEInv,
154 const TopTools_DataMapOfShapeListOfShape& theOEImages,
155 TopTools_MapOfShape& theMENInv,
156 Handle(BRepAlgo_AsDes)& theAsDes);
159 void FindInvalidEdges(const TopoDS_Face& theF,
160 const TopTools_ListOfShape& theLFImages,
161 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
162 const TopTools_DataMapOfShapeShape& theFacesOrigins,
163 const BRepOffset_Analyse* theAnalyse,
164 const TopTools_DataMapOfShapeListOfShape& theOEImages,
165 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
166 TopTools_IndexedMapOfShape& theInvEdges,
167 TopTools_IndexedMapOfShape& theValidEdges,
168 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
169 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
170 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
171 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
172 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
173 TopTools_MapOfShape& theMEInverted,
174 TopTools_MapOfShape& theEdgesInvalidByVertex,
175 TopTools_MapOfShape& theEdgesValidByVertex);
178 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
179 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
180 const TopTools_DataMapOfShapeShape& theFacesOrigins,
181 const BRepOffset_Analyse* theAnalyse,
182 const TopTools_IndexedMapOfShape& theInvEdges,
183 const TopTools_IndexedMapOfShape& theValidEdges,
184 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
185 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
186 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges);
189 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
190 const TopTools_IndexedMapOfShape& theInvEdges,
191 const TopTools_IndexedMapOfShape& theValidEdges,
192 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
193 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
194 const TopTools_MapOfShape& theLENeutral,
195 const TopTools_MapOfShape& theMEInverted,
196 const TopTools_MapOfShape& theEdgesInvalidByVertex,
197 const TopTools_MapOfShape& theEdgesValidByVertex,
198 const TopTools_MapOfShape& theMFHoles,
199 TopTools_IndexedMapOfShape& theMFInvInHole,
200 TopTools_ListOfShape& theInvFaces,
201 TopTools_ListOfShape& theInvertedFaces);
204 void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
205 const TopoDS_Face& theFOffset,
206 const TopTools_ListOfShape& theLFImages,
207 const TopTools_MapOfShape& theInvertedEdges,
208 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
209 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
210 TopTools_MapOfShape& theMFHoles,
211 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
212 Handle(IntTools_Context)& theContext);
215 gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
216 const Standard_Integer theNbP);
219 Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
220 const TopoDS_Face& theFOr,
221 const TopTools_DataMapOfShapeListOfShape& theOEImages,
222 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
223 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
224 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
225 const TopTools_IndexedMapOfShape& theMEdges,
226 TopTools_MapOfShape& theMEInverted);
229 Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
230 const TopTools_ListOfShape& theLCBF,
231 const TopTools_MapOfShape& theMEInverted,
232 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
233 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
234 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll);
237 void GetVerticesOnEdges(const TopoDS_Shape& theCB,
238 const TopTools_MapOfShape& theEdges,
239 TopTools_MapOfShape& theVerticesOnEdges,
240 TopTools_MapOfShape& theAllVertices);
243 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
244 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
245 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
246 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
247 TopTools_IndexedMapOfShape& theMERemoved);
250 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
251 const TopTools_DataMapOfShapeShape& theArtInvFaces,
252 const TopTools_MapOfShape& theMEInverted,
253 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
254 TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
257 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
258 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
259 const TopTools_DataMapOfShapeShape& theArtInvFaces,
260 const TopTools_IndexedMapOfShape& theInvEdges,
261 const TopTools_MapOfShape& theInvertedEdges,
262 const TopTools_ListOfShape& theInvertedFaces,
263 const TopTools_IndexedMapOfShape& theMFToCheckInt,
264 const TopTools_IndexedMapOfShape& theMFInvInHole,
265 const TopoDS_Shape& theFHoles,
266 TopTools_DataMapOfShapeListOfShape& theSSInterfs,
267 TopTools_IndexedMapOfShape& theMERemoved,
268 TopTools_IndexedMapOfShape& theMEInside,
269 TopoDS_Shape& theSolids);
272 void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
273 const TopTools_IndexedMapOfShape& theInvEdges,
274 const TopTools_DataMapOfShapeShape& theDMFOr,
275 BOPAlgo_Builder& theBuilder,
276 TopTools_DataMapOfShapeListOfShape& theSSInterfs);
279 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
280 const TopTools_DataMapOfShapeShape& theDMFImF,
281 const TopTools_IndexedMapOfShape& theMFInv,
282 const TopTools_IndexedMapOfShape& theInvEdges,
283 const TopTools_MapOfShape& theInvertedEdges,
284 TopTools_MapOfShape& theMFToRem);
287 void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
288 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
289 BOPAlgo_Builder& theGF,
290 TopTools_IndexedMapOfShape& theMERemoved);
293 void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
294 const TopTools_DataMapOfShapeShape& theArtInvFaces,
295 const TopTools_IndexedMapOfShape& theInvEdges,
296 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
297 BOPAlgo_Builder& theGF,
298 TopTools_IndexedMapOfShape& theMERemoved);
301 void FilterEdgesImages(const TopoDS_Shape& theS,
302 TopTools_DataMapOfShapeListOfShape& theOEImages,
303 TopTools_DataMapOfShapeListOfShape& theOEOrigins);
306 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
307 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
308 const TopTools_IndexedMapOfShape& theInvEdges,
309 const TopTools_IndexedMapOfShape& theMERemoved,
310 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
311 TopTools_DataMapOfShapeShape& theArtInvFaces);
314 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
315 const TopTools_DataMapOfShapeShape& theArtInvFaces,
316 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
317 const TopTools_IndexedMapOfShape& theMERemoved,
318 TopTools_IndexedMapOfShape& theInvEdges);
321 void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
322 const TopTools_DataMapOfShapeShape& theArtInvFaces,
323 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
324 const TopTools_IndexedMapOfShape& theValidEdges,
325 TopTools_IndexedMapOfShape& theInvEdges);
328 void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
329 const TopTools_IndexedMapOfShape& theInvEdges,
330 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
331 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
332 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
333 TopTools_MapOfShape& theFSelfRebAvoid);
336 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
337 const TopTools_MapOfShape& theFSelfRebAvoid,
338 const TopoDS_Shape& theSolids,
339 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
340 const BRepOffset_Analyse* theAnalyse,
341 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
342 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
343 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
344 TopTools_DataMapOfShapeShape& theFacesOrigins,
345 TopTools_DataMapOfShapeListOfShape& theOEImages,
346 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
347 TopTools_MapOfShape& theLastInvEdges,
348 TopTools_IndexedMapOfShape& theEdgesToAvoid,
349 TopTools_IndexedMapOfShape& theInvEdges,
350 TopTools_IndexedMapOfShape& theValidEdges,
351 const TopTools_MapOfShape& theInvertedEdges,
352 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
353 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
354 const TopTools_DataMapOfShapeShape& theArtInvFaces,
355 TopTools_MapOfShape& theVertsToAvoid,
356 TopTools_DataMapOfShapeShape& theETrimEInf,
357 Handle(BRepAlgo_AsDes)& theAsDes);
360 void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
361 const TopTools_MapOfShape& theFSelfRebAvoid,
362 const TopoDS_Shape& theSolids,
363 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
364 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
365 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
366 TopTools_DataMapOfShapeListOfShape& theOEImages,
367 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
368 TopTools_IndexedMapOfShape& theInvEdges,
369 TopTools_IndexedMapOfShape& theValidEdges,
370 const TopTools_MapOfShape& theInvertedEdges,
371 TopTools_IndexedMapOfShape& theEdgesToAvoid,
372 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
373 const TopTools_DataMapOfShapeShape& theArtInvFaces,
374 TopTools_MapOfShape& theVertsToAvoid,
375 TopTools_DataMapOfShapeShape& theETrimEInf,
376 TopTools_MapOfShape& theModifiedEdges,
377 Handle(BRepAlgo_AsDes)& theAsDes);
380 void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
381 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
382 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
383 const TopTools_DataMapOfShapeShape& theArtInvFaces,
384 const Standard_Boolean bLookVertToAvoid,
385 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
386 TopTools_DataMapOfShapeListOfShape& theMDone,
387 TopTools_DataMapOfShapeListOfShape& theDMSF,
388 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
389 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
390 TopTools_DataMapOfShapeShape& theETrimEInf,
391 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv);
394 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
395 const TopTools_IndexedMapOfShape& theInvEdges,
396 const TopTools_IndexedMapOfShape& theValidEdges,
397 const TopTools_MapOfShape& theInvertedEdges,
398 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
399 const TopTools_DataMapOfShapeListOfShape& theOEImages,
400 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
401 TopTools_MapOfShape& theMVRInv);
404 void FindFacesForIntersection(const TopoDS_Shape& theFInv,
405 const TopTools_IndexedMapOfShape& theME,
406 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
407 const TopTools_DataMapOfShapeListOfShape& theDMSF,
408 const TopTools_MapOfShape& theMVInvAll,
409 const TopTools_DataMapOfShapeShape& theArtInvFaces,
410 const Standard_Boolean theArtCase,
411 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
412 TopTools_IndexedMapOfShape& theMFAvoid,
413 TopTools_IndexedMapOfShape& theMFInt,
414 TopTools_IndexedMapOfShape& theMFIntExt,
415 TopTools_ListOfShape& theLFImInt);
418 void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
419 const TopTools_IndexedMapOfShape& theInvEdges,
420 const TopTools_IndexedMapOfShape& theValidEdges,
421 const TopTools_IndexedMapOfShape& theME,
422 const TopTools_DataMapOfShapeShape& theETrimEInf,
423 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
424 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
425 const TopTools_MapOfShape& theAllInvs,
426 const Standard_Boolean theForceUse,
427 TopTools_IndexedMapOfShape& theMECV,
428 TopTools_MapOfShape& theMECheckExt,
429 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
430 TopTools_ListOfShape& theLFEi,
431 TopTools_ListOfShape& theLFEj,
432 TopTools_IndexedMapOfShape& theMEToInt);
435 void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
436 const TopoDS_Shape& theFi,
437 const TopoDS_Shape& theFj,
438 const TopTools_ListOfShape& theLFInv,
439 const TopTools_ListOfShape& theLFImi,
440 const TopTools_ListOfShape& theLFImj,
441 const TopTools_ListOfShape& theLFEi,
442 const TopTools_ListOfShape& theLFEj,
443 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
444 TopTools_IndexedMapOfShape& theMEToInt);
447 void IntersectFaces(const TopoDS_Shape& theFInv,
448 const TopoDS_Shape& theFi,
449 const TopoDS_Shape& theFj,
450 const TopTools_ListOfShape& theLFInv,
451 const TopTools_ListOfShape& theLFImi,
452 const TopTools_ListOfShape& theLFImj,
453 TopTools_ListOfShape& theLFEi,
454 TopTools_ListOfShape& theLFEj,
455 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
456 TopTools_IndexedMapOfShape& theMECV,
457 TopTools_IndexedMapOfShape& theMEToInt);
460 void FindOrigins(const TopTools_ListOfShape& theLFIm1,
461 const TopTools_ListOfShape& theLFIm2,
462 const TopTools_IndexedMapOfShape& theME,
463 const TopTools_DataMapOfShapeListOfShape& theOrigins,
464 TopTools_ListOfShape& theLEOr);
467 void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
468 const TopTools_IndexedMapOfShape& theMFInt,
469 const TopTools_IndexedMapOfShape& theMEInt,
470 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
471 const TopTools_IndexedMapOfShape& theMSInv,
472 const TopTools_IndexedMapOfShape& theMVE,
473 const TopTools_MapOfShape& theVertsToAvoid,
474 const TopTools_MapOfShape& theNewVertsToAvoid,
475 const TopTools_MapOfShape& theMECheckExt,
476 TopTools_MapOfShape& theMVBounds,
477 TopTools_DataMapOfShapeListOfShape& theEImages);
480 void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
481 const TopTools_MapOfShape& theMVBounds,
482 BOPAlgo_Builder& theGF,
483 TopTools_MapOfShape& theMEInv);
486 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
487 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
488 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
489 const TopTools_MapOfShape& theMVBounds,
490 const TopoDS_Shape& theSolids,
491 const TopTools_IndexedMapOfShape& theInvEdges,
492 const TopTools_MapOfShape& theInvertedEdges,
493 const TopTools_MapOfShape& theMEInvOnArt,
494 TopTools_MapOfShape& theMECheckExt,
495 TopTools_IndexedMapOfShape& theEdgesToAvoid,
496 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
497 TopTools_DataMapOfShapeListOfShape& theOEImages,
498 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
499 TopTools_MapOfShape& theVertsToAvoid,
500 TopTools_DataMapOfShapeShape& theETrimEInf,
501 TopTools_DataMapOfShapeListOfShape& theEImages,
502 TopTools_DataMapOfShapeListOfShape& theEETrim,
503 TopTools_MapOfShape& theModifiedEdges,
504 Handle(BRepAlgo_AsDes)& theAsDes);
507 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
508 const TopTools_DataMapOfShapeListOfShape& theEETrim,
509 const TopTools_MapOfShape& theMVBounds,
510 TopTools_MapOfShape& theMECheckExt,
511 TopTools_DataMapOfShapeListOfShape& theEImages,
512 TopTools_MapOfShape& theMEB,
513 TopTools_MapOfShape& theMVOld,
514 TopTools_MapOfShape& theMENew,
515 TopTools_DataMapOfShapeListOfShape& theDMEOr,
516 TopTools_DataMapOfShapeListOfShape& theMELF);
519 void IntersectEdges(const TopTools_ListOfShape& theLA,
520 const TopTools_ListOfShape& theLE,
521 const TopTools_MapOfShape& theMVBounds,
522 const TopTools_MapOfShape& theVertsToAvoid,
523 TopTools_MapOfShape& theMENew,
524 TopTools_MapOfShape& theMECheckExt,
525 TopTools_DataMapOfShapeListOfShape& theEImages,
526 TopTools_MapOfShape& theModifiedEdges,
527 TopTools_DataMapOfShapeListOfShape& theDMEOr,
528 TopTools_DataMapOfShapeListOfShape& theMELF,
529 TopoDS_Shape& theSplits);
532 void GetBounds(const TopTools_ListOfShape& theLFaces,
533 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
534 const TopTools_MapOfShape& theMEB,
535 TopoDS_Shape& theBounds);
538 void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
539 const TopTools_DataMapOfShapeListOfShape& theOEImages,
540 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
541 const TopTools_MapOfShape& theMEB,
542 TopTools_ListOfShape& theLABounds,
543 TopTools_ListOfShape& theLAValid,
544 TopoDS_Shape& theBounds,
545 Handle(BRepAlgo_AsDes)& theAsDes);
548 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
549 const TopoDS_Shape& theBounds,
550 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
551 const TopoDS_Shape& theSolids,
552 const TopTools_IndexedMapOfShape& theInvEdges,
553 const TopTools_MapOfShape& theMVOld,
554 const TopTools_MapOfShape& theMENew,
555 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
556 const TopTools_DataMapOfShapeListOfShape& theMELF,
557 const TopTools_DataMapOfShapeListOfShape& theEImages,
558 const TopTools_MapOfShape& theMECheckExt,
559 const TopTools_MapOfShape& theMEInvOnArt,
560 Handle(IntTools_Context)& theCtx,
561 TopTools_MapOfShape& theVertsToAvoid,
562 TopTools_MapOfShape& theMEInv);
565 void FilterSplits(const TopTools_ListOfShape& theLE,
566 const TopTools_MapOfShape& theMEFilter,
567 const Standard_Boolean theIsInv,
568 TopTools_DataMapOfShapeListOfShape& theEImages,
569 TopoDS_Shape& theSplits);
572 void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
573 const TopTools_DataMapOfShapeListOfShape& theMELF,
574 const TopTools_DataMapOfShapeListOfShape& theEImages,
575 const TopTools_IndexedMapOfShape& theInvEdges,
576 const TopTools_MapOfShape& theInvertedEdges,
577 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
578 TopTools_DataMapOfShapeListOfShape& theOEImages,
579 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
580 TopTools_DataMapOfShapeShape& theETrimEInf,
581 TopTools_DataMapOfShapeListOfShape& theEETrim,
582 TopTools_MapOfShape& theModifiedEdges,
583 Handle(BRepAlgo_AsDes)& theAsDes);
586 void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
589 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
590 const TopTools_DataMapOfShapeListOfShape& theEImages,
591 BRepAlgo_Image& theImage);
594 void UpdateOrigins(const TopTools_ListOfShape& theLA,
595 TopTools_DataMapOfShapeListOfShape& theOrigins,
596 BOPAlgo_Builder& theGF);
599 void UpdateImages(const TopTools_ListOfShape& theLA,
600 TopTools_DataMapOfShapeListOfShape& theImages,
601 BOPAlgo_Builder& theGF,
602 TopTools_MapOfShape& theModified);
605 void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
606 TopTools_DataMapOfShapeShape& theETrimEInf,
607 BOPAlgo_Builder& theGF);
610 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
611 const Handle(IntTools_Context)& theCtx);
614 void FindCommonParts(const TopTools_ListOfShape& theLS1,
615 const TopTools_ListOfShape& theLS2,
616 TopTools_ListOfShape& theLSC,
617 const TopAbs_ShapeEnum theType = TopAbs_EDGE);
620 Standard_Integer NbPoints(const TopoDS_Edge& theE);
623 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
624 const TopoDS_Shape& theSWhere,
625 const BRepOffset_Analyse* theAnalyse,
626 TopoDS_Shape& theRes);
629 void AppendToList(TopTools_ListOfShape& theL,
630 const TopoDS_Shape& theS);
632 template <class ContainerType, class FenceMapType>
633 static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
634 const TopTools_DataMapOfShapeListOfShape& theImages,
635 ContainerType& theMapOut,
636 FenceMapType* theMFence);
638 template <class ContainerType>
639 static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
640 const TopTools_DataMapOfShapeListOfShape& theImages,
641 ContainerType& theMapOut)
643 TopTools_MapOfShape* aDummy = NULL;
644 return TakeModified (theS, theImages, theMapOut, aDummy);
647 //=======================================================================
648 //function : BuildSplitsOfTrimmedFaces
649 //purpose : Building splits of already trimmed faces
650 //=======================================================================
651 void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF,
652 Handle(BRepAlgo_AsDes)& theAsDes,
653 BRepAlgo_Image& theImage)
655 TopTools_DataMapOfShapeListOfShape anEImages, anEOrigins;
656 TopTools_IndexedDataMapOfShapeListOfShape aDMFFIm;
657 TopTools_IndexedMapOfShape anEmptyIM;
658 TopTools_DataMapOfShapeListOfShape anEmptyDMSLS;
659 TopTools_DataMapOfShapeShape anEmptyDMSS;
660 TopTools_MapOfShape aNewEdges, anEmptyM;
662 // firstly it is necessary to fuse all the edges
663 Handle(IntTools_Context) aCtx = new IntTools_Context();
665 IntersectTrimmedEdges(theLF, theAsDes, anEImages, anEOrigins, anEmptyDMSLS, aCtx, aNewEdges, anEmptyDMSS);
667 TopTools_ListIteratorOfListOfShape aItLF(theLF);
668 for (; aItLF.More(); aItLF.Next()) {
669 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
672 TopTools_ListOfShape aLFImages;
674 Standard_Boolean bFound = GetEdges(aF, theAsDes, anEImages, anEmptyM,
675 anEmptyIM, aCtx, aNewEdges, aCE, anEmptyIM);
676 // split the face by the edges
678 if (!theImage.HasImage(aF)) {
679 aLFImages.Append(aF);
680 aDMFFIm.Add(aF, aLFImages);
685 BuildSplitsOfTrimmedFace(aF, aCE, aLFImages);
686 aDMFFIm.Add(aF, aLFImages);
688 // Fill history for faces and edges
689 FillHistory(aDMFFIm, anEImages, theImage);
692 //=======================================================================
693 //function : BuildSplitsOfExtendedFaces
694 //purpose : Building splits of not-trimmed offset faces.
695 // For the cases in which invalidity will be found,
696 // these invalidities will be rebuilt.
697 //=======================================================================
698 void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
699 const BRepOffset_Analyse& theAnalyse,
700 Handle(BRepAlgo_AsDes)& theAsDes,
701 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
702 TopTools_DataMapOfShapeShape& theFacesOrigins,
703 TopTools_DataMapOfShapeShape& theETrimEInf,
704 BRepAlgo_Image& theImage)
706 Handle(IntTools_Context) aCtx = new IntTools_Context();
707 // images and origins for offset edges
708 TopTools_DataMapOfShapeListOfShape anOEImages, anOEOrigins;
709 TopTools_MapOfShape aNewEdges;
710 // fusing all trimmed offset edges to avoid self-intersections in the splits
711 IntersectTrimmedEdges(theLF, theAsDes, anOEImages, anOEOrigins,
712 theEdgesOrigins, aCtx, aNewEdges, theETrimEInf);
714 // valid/invalid edges
715 TopTools_IndexedMapOfShape anInvEdges, aValidEdges, anEdgesToAvoid;
717 TopTools_MapOfShape anInvertedEdges;
719 TopTools_IndexedDataMapOfShapeListOfShape aFImages;
720 // found invalid faces
721 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
722 // artificially invalid faces - it will be empty here,
723 // but may be filled on the following rebuilding steps
724 TopTools_DataMapOfShapeShape anArtInvFaces;
725 // shapes connections for using in rebuilding
726 TopTools_DataMapOfShapeListOfShape aSSInterfs;
727 // edges to avoid on second steps
728 TopTools_MapOfShape aLastInvEdges;
729 // keep information of already invalid faces to avoid
730 // infinite rebuilding of the same invalid face
731 TopTools_DataMapOfShapeInteger anAlreadyInvFaces;
732 // images of the hole faces of the original faces
733 TopTools_DataMapOfShapeListOfShape aDMFNewHoles;
734 // solid build from the new splits
735 TopoDS_Shape aSolids;
736 // now we can split the faces
737 BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, &theAnalyse, theAsDes, theFacesOrigins,
738 anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges,
739 anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages,
740 aDMFNewHoles, aSolids, aSSInterfs);
742 // Find faces to rebuild
743 if (anInvFaces.Extent()) {
744 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
745 TopTools_MapOfShape aFSelfRebAvoid;
746 FindFacesToRebuild(aFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid);
748 if (aFToRebuild.Extent()) {
750 TopTools_MapOfShape aVAEmpty;
751 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, &theAnalyse, aFImages, aDMFNewHoles,
752 theEdgesOrigins, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges,
753 anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces,
754 anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes);
758 // Fill possible gaps in the splits of offset faces to increase possibility of
759 // creating closed volume from these splits
762 // Fill history for faces and edges
763 FillHistory(aFImages, anOEImages, theImage);
766 //=======================================================================
767 //function : BuildSplitsOfInvFaces
768 //purpose : Rebuilding splits of faces with new intersection edges
769 //=======================================================================
770 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
771 const TopTools_MapOfShape& theModifiedEdges,
772 const BRepOffset_Analyse* theAnalyse,
773 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
774 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
775 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
776 TopTools_DataMapOfShapeShape& theFacesOrigins,
777 TopTools_DataMapOfShapeListOfShape& theOEImages,
778 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
779 TopTools_MapOfShape& theLastInvEdges,
780 TopTools_IndexedMapOfShape& theEdgesToAvoid,
781 TopTools_MapOfShape& theVertsToAvoid,
782 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
783 TopTools_IndexedMapOfShape& theValidEdges,
784 TopTools_DataMapOfShapeShape& theETrimEInf,
785 Handle(BRepAlgo_AsDes)& theAsDes)
787 Standard_Integer aNb = theFToRebuild.Extent();
792 TopTools_ListOfShape aLF;
793 aNb = theFImages.Extent();
794 for (Standard_Integer i = 1; i <= aNb; ++i) {
795 const TopoDS_Shape& aF = theFImages.FindKey(i);
800 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
801 // artificially invalid faces
802 TopTools_DataMapOfShapeShape anArtInvFaces;
804 TopTools_IndexedMapOfShape anInvEdges;
806 TopTools_MapOfShape anInvertedEdges;
807 // shapes connection for using in rebuilding process
808 TopTools_DataMapOfShapeListOfShape aSSInterfs;
810 TopoDS_Shape aSolids;
812 BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAnalyse, theAsDes, theFacesOrigins,
813 theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges,
814 anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages,
815 theDMFNewHoles, aSolids, aSSInterfs);
817 if (anInvFaces.Extent()) {
818 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
819 TopTools_MapOfShape aFSelfRebAvoid;
820 FindFacesToRebuild(theFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid);
822 if (aFToRebuild.Extent()) {
823 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, theAnalyse, theFImages, theDMFNewHoles,
824 theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
825 theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces,
826 anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes);
831 //=======================================================================
832 //function : BuildSplitsOfFaces
833 //purpose : Building the splits of offset faces and
834 // looking for the invalid splits
835 //=======================================================================
836 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
837 const TopTools_MapOfShape& theModifiedEdges,
838 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
839 const BRepOffset_Analyse* theAnalyse,
840 Handle(BRepAlgo_AsDes)& theAsDes,
841 TopTools_DataMapOfShapeShape& theFacesOrigins,
842 TopTools_DataMapOfShapeListOfShape& theOEImages,
843 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
844 TopTools_MapOfShape& theLastInvEdges,
845 TopTools_IndexedMapOfShape& theEdgesToAvoid,
846 TopTools_IndexedMapOfShape& theInvEdges,
847 TopTools_IndexedMapOfShape& theValidEdges,
848 TopTools_MapOfShape& theInvertedEdges,
849 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
850 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
851 TopTools_DataMapOfShapeShape& theArtInvFaces,
852 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
853 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
854 TopoDS_Shape& theSolids,
855 TopTools_DataMapOfShapeListOfShape& theSSInterfs)
857 if (theLF.IsEmpty()) {
862 Standard_Integer i, aNb;
865 TopTools_ListOfShape aLFDone;
866 // extended face - map of neutral edges, i.e. in one split - valid and in other - invalid
867 BRepOffset_DataMapOfShapeMapOfShape aDMFMNE;
868 // map of valid edges for each face
869 BRepOffset_DataMapOfShapeMapOfShape aDMFMVE;
870 // map of invalid edges for each face
871 BRepOffset_DataMapOfShapeIndexedMapOfShape aDMFMIE;
872 // map of valid inverted edges for the face
873 BRepOffset_DataMapOfShapeMapOfShape aDMFMVIE;
874 // map of splits to check for internals
875 TopTools_IndexedMapOfShape aMFToCheckInt;
876 // map of edges created from vertex and marked as invalid
877 TopTools_MapOfShape aMEdgeInvalidByVertex;
878 // map of edges created from vertex and marked as valid
879 TopTools_MapOfShape aMEdgeValidByVertex;
880 // connection map from old edges to new ones
881 TopTools_DataMapOfShapeListOfShape aDMEOrLEIm;
883 Handle(IntTools_Context) aCtx = new IntTools_Context;
884 // build splits of faces
885 TopTools_ListIteratorOfListOfShape aItLF(theLF);
886 for (; aItLF.More(); aItLF.Next()) {
887 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
889 TopTools_ListOfShape* pLFIm = theFImages.ChangeSeek(aF);
890 if (pLFIm && pLFIm->IsEmpty()) {
893 // get edges by which the face should be split
895 TopTools_IndexedMapOfShape aMapEInv;
896 Standard_Boolean bFound =
897 GetEdges(aF, theAsDes, theOEImages, theLastInvEdges,
898 theEdgesToAvoid, aCtx, theModifiedEdges, aCE, aMapEInv);
904 // check the found edges on self-intersection
905 BRepAlgoAPI_Check aChecker(aCE);
906 if (!aChecker.IsValid())
908 std::cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n";
912 TopTools_ListOfShape aLFImages;
913 BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages);
915 if (aMapEInv.Extent()) {
916 // check if all possible faces are built
917 TopTools_MapOfShape aMENInv;
918 Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
919 CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes);
921 // try to build splits using invalid edges
922 TopoDS_Compound aCE1;
923 aBB.MakeCompound(aCE1);
925 for (i = 1; i <= aMapEInv.Extent(); ++i) {
926 aBB.Add(aCE1, aMapEInv(i));
929 TopTools_ListOfShape aLFImages1;
930 BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1);
932 // check if the rebuilding has added some new faces to the splits
933 for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();)
935 Standard_Boolean bAllInv = Standard_True;
936 const TopoDS_Shape& aFIm = aItLFIm.Value();
937 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
938 for (; aExpE.More(); aExpE.Next()) {
939 const TopoDS_Shape& aE = aExpE.Current();
940 if (!aMapEInv.Contains(aE)) {
941 bAllInv = Standard_False;
942 if (!aMENInv.Contains(aE)) {
950 aMFToCheckInt.Add(aFIm);
952 aLFImages1.Remove(aItLFIm);
959 if (bArtificialCase) {
960 if (aLFImages.Extent() == aLFImages1.Extent()) {
961 bArtificialCase = Standard_False;
964 aLFImages = aLFImages1;
968 if (bArtificialCase) {
969 TopTools_IndexedMapOfShape aMEInv;
970 // make the face invalid
971 theArtInvFaces.Bind(aF, aCE);
974 TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages);
975 for (; aItLFIm.More(); aItLFIm.Next()) {
976 const TopoDS_Shape& aFIm = aItLFIm.Value();
977 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
978 for (; aExpE.More(); aExpE.Next()) {
979 const TopoDS_Shape& aE = aExpE.Current();
980 if (aMapEInv.Contains(aE)) {
985 theValidEdges.Add(aE);
990 aDMFMIE.Bind(aF, aMEInv);
997 // find invalid edges
998 FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theAnalyse, theOEImages,
999 theOEOrigins, theInvEdges, theValidEdges, aDMFMVE, aDMFMNE, aDMFMIE,
1000 aDMFMVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex);
1002 // save the new splits
1004 pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape()));
1009 pLFIm->Append(aLFImages);
1014 if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty() && aDMFMIE.IsEmpty()) {
1018 // Additional step to find invalid edges by checking unclassified edges
1019 // in the splits of SD faces
1020 FindInvalidEdges (aLFDone, theFImages, theFacesOrigins, theAnalyse,
1021 theInvEdges, theValidEdges, aDMFMIE, aDMFMVE, aDMFMNE);
1024 // show invalid edges
1025 TopoDS_Compound aCEInv1;
1026 BRep_Builder().MakeCompound(aCEInv1);
1027 Standard_Integer aNbEInv = theInvEdges.Extent();
1028 for (i = 1; i <= aNbEInv; ++i) {
1029 const TopoDS_Shape& aE = theInvEdges(i);
1030 BRep_Builder().Add(aCEInv1, aE);
1033 TopoDS_Compound aCEVal1;
1034 BRep_Builder().MakeCompound(aCEVal1);
1035 aNbEInv = theValidEdges.Extent();
1036 for (i = 1; i <= aNbEInv; ++i) {
1037 const TopoDS_Shape& aE = theValidEdges(i);
1038 BRep_Builder().Add(aCEVal1, aE);
1040 // show inverted edges
1041 TopoDS_Compound aCEInverted;
1042 BRep_Builder().MakeCompound(aCEInverted);
1043 TopTools_MapIteratorOfMapOfShape aItM(theInvertedEdges);
1044 for (; aItM.More(); aItM.Next()) {
1045 BRep_Builder().Add(aCEInverted, aItM.Value());
1050 // Show all obtained splits of faces
1051 TopoDS_Compound aCFIm1;
1052 BRep_Builder().MakeCompound(aCFIm1);
1055 // Build Edge-Face connectivity map to find faces which removal
1056 // may potentially lead to creation of the holes in the faces
1057 // preventing from obtaining closed volume in the result
1058 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
1059 const Standard_Integer aNbF = theFImages.Extent();
1060 for (i = 1; i <= aNbF; ++i)
1062 TopTools_ListIteratorOfListOfShape itLFIm(theFImages(i));
1063 for (; itLFIm.More(); itLFIm.Next())
1065 TopExp::MapShapesAndAncestors(itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
1067 BRep_Builder().Add(aCFIm1, itLFIm.Value());
1072 TopTools_MapOfShape anEmptyMap;
1073 // invalid faces inside the holes
1074 TopTools_IndexedMapOfShape aMFInvInHole;
1076 TopoDS_Compound aFHoles;
1077 aBB.MakeCompound(aFHoles);
1078 // Find the faces containing only the inverted edges and the invalid ones
1079 TopTools_ListOfShape anInvertedFaces;
1080 // find invalid faces
1081 // considering faces containing only invalid edges as invalid
1082 aItLF.Initialize(aLFDone);
1083 for (; aItLF.More(); aItLF.Next()) {
1084 const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1085 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
1087 TopTools_ListOfShape aLFInv;
1088 Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF);
1089 if (bArtificialCase) {
1095 const TopTools_MapOfShape* pMNE = aDMFMNE.ChangeSeek(aF);
1099 // find faces inside holes wires
1100 TopTools_MapOfShape aMFHoles;
1101 const TopoDS_Face& aFOr = TopoDS::Face(theFacesOrigins.Find(aF));
1102 FindFacesInsideHoleWires(aFOr, aF, aLFImages, theInvertedEdges,
1103 aDMEOrLEIm, anEFMap, aMFHoles, theDMFNewHoles, aCtx);
1105 TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles);
1106 for (; aItMH.More(); aItMH.Next()) {
1107 aBB.Add(aFHoles, aItMH.Value());
1110 // find invalid faces
1111 FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFMVE, aDMFMIE,
1112 *pMNE, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex,
1113 aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
1116 if (aLFInv.Extent()) {
1117 if (theAlreadyInvFaces.IsBound(aF)) {
1118 if (theAlreadyInvFaces.Find(aF) > 2) {
1119 if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) {
1126 theInvFaces.Add(aF, aLFInv);
1130 if (theInvFaces.IsEmpty()) {
1131 theInvEdges.Clear();
1136 // show invalid faces
1137 TopoDS_Compound aCFInv1;
1138 BRep_Builder().MakeCompound(aCFInv1);
1139 Standard_Integer aNbFInv = theInvFaces.Extent();
1140 for (i = 1; i <= aNbFInv; ++i) {
1141 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1142 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1143 for (; aItLFInv.More(); aItLFInv.Next()) {
1144 const TopoDS_Shape& aFIm = aItLFInv.Value();
1145 BRep_Builder().Add(aCFInv1, aFIm);
1150 TopTools_IndexedMapOfShape aMERemoved;
1151 // remove invalid splits of faces using inverted edges
1152 RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins,
1153 theInvFaces, theFImages, aMERemoved);
1154 if (theInvFaces.IsEmpty()) {
1155 theInvEdges.Clear();
1159 // remove invalid splits from valid splits
1160 RemoveInvalidSplitsFromValid (theInvFaces, theArtInvFaces, theInvertedEdges,
1161 aDMFMVIE, theFImages);
1163 // remove inside faces
1164 TopTools_IndexedMapOfShape aMEInside;
1165 RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, theInvertedEdges,
1166 anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs,
1167 aMERemoved, aMEInside, theSolids);
1169 // make compound of valid splits
1170 TopoDS_Compound aCFIm;
1171 aBB.MakeCompound(aCFIm);
1173 aNb = theFImages.Extent();
1174 for (i = 1; i <= aNb; ++i) {
1175 const TopTools_ListOfShape& aLFIm = theFImages(i);
1176 aItLF.Initialize(aLFIm);
1177 for (; aItLF.More(); aItLF.Next()) {
1178 const TopoDS_Shape& aFIm = aItLF.Value();
1179 aBB.Add(aCFIm, aFIm);
1183 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
1184 TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
1186 // filter maps of images and origins
1187 FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
1189 // filter invalid faces
1190 FilterInvalidFaces(theFImages, aDMEF, theInvEdges, aMEInside, theInvFaces, theArtInvFaces);
1191 aNb = theInvFaces.Extent();
1193 theInvEdges.Clear();
1198 // show invalid faces
1199 TopoDS_Compound aCFInv;
1200 BRep_Builder().MakeCompound(aCFInv);
1201 aNbFInv = theInvFaces.Extent();
1202 for (i = 1; i <= aNbFInv; ++i) {
1203 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1204 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1205 for (; aItLFInv.More(); aItLFInv.Next()) {
1206 const TopoDS_Shape& aFIm = aItLFInv.Value();
1207 BRep_Builder().Add(aCFInv, aFIm);
1212 // filter invalid edges
1213 FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFMIE, aMERemoved, theInvEdges);
1215 // Check additionally validity of edges originated from vertices.
1216 CheckEdgesCreatedByVertex (theInvFaces, theArtInvFaces, theEdgesOrigins,
1217 theValidEdges, theEdgesToAvoid);
1220 // show invalid edges
1221 TopoDS_Compound aCEInv;
1222 BRep_Builder().MakeCompound(aCEInv);
1223 aNbEInv = theInvEdges.Extent();
1224 for (i = 1; i <= aNbEInv; ++i) {
1225 const TopoDS_Shape& aE = theInvEdges(i);
1226 BRep_Builder().Add(aCEInv, aE);
1230 theLastInvEdges.Clear();
1231 aNb = theInvEdges.Extent();
1232 for (i = 1; i <= aNb; ++i) {
1233 const TopoDS_Shape& aE = theInvEdges(i);
1234 theEdgesToAvoid.Add(aE);
1235 theLastInvEdges.Add(aE);
1238 aNb = theInvFaces.Extent();
1239 for (i = 1; i <= aNb; ++i) {
1240 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
1241 if (theAlreadyInvFaces.IsBound(aF)) {
1242 theAlreadyInvFaces.ChangeFind(aF)++;
1245 theAlreadyInvFaces.Bind(aF, 1);
1250 //=======================================================================
1251 //function : IntersectTrimmedEdges
1252 //purpose : Intersection of the trimmed edges among themselves
1253 //=======================================================================
1254 void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
1255 const Handle(BRepAlgo_AsDes)& theAsDes,
1256 TopTools_DataMapOfShapeListOfShape& theOEImages,
1257 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1258 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1259 Handle(IntTools_Context)& theCtx,
1260 TopTools_MapOfShape& theNewEdges,
1261 TopTools_DataMapOfShapeShape& theETrimEInf)
1263 if (theLF.IsEmpty()) {
1267 // get edges to intersect from descendants of the offset faces
1268 TopTools_ListOfShape aLS;
1270 TopTools_ListIteratorOfListOfShape aItLF(theLF);
1271 for (; aItLF.More(); aItLF.Next()) {
1272 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1274 const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
1275 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1276 for (; aItLE.More(); aItLE.Next()) {
1277 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1279 if (ProcessMicroEdge(aE, theCtx)) {
1283 if (theNewEdges.Add(aE)) {
1289 if (aLS.Extent() < 2) {
1290 // nothing to intersect
1294 // perform intersection of the edges
1295 BOPAlgo_Builder aGFE;
1296 aGFE.SetArguments(aLS);
1298 if (aGFE.HasErrors()) {
1302 TopTools_ListOfShape aLA;
1303 // fill map with edges images
1304 TopTools_ListIteratorOfListOfShape aIt(aLS);
1305 for (; aIt.More(); aIt.Next()) {
1306 const TopoDS_Shape& aE = aIt.Value();
1307 const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
1308 if (aLEIm.IsEmpty()) {
1314 theOEImages.Bind(aE, aLEIm);
1316 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
1317 for (; aItLE.More(); aItLE.Next()) {
1318 const TopoDS_Shape& aEIm = aItLE.Value();
1319 TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm);
1321 pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape());
1323 AppendToList(*pLEOr, aE);
1327 UpdateOrigins(aLA, theEdgesOrigins, aGFE);
1328 UpdateIntersectedEdges(aLA, theETrimEInf, aGFE);
1331 //=======================================================================
1332 //function : GetEdges
1333 //purpose : Getting edges from AsDes map to build the splits of faces
1334 //=======================================================================
1335 Standard_Boolean GetEdges(const TopoDS_Face& theFace,
1336 const Handle(BRepAlgo_AsDes)& theAsDes,
1337 const TopTools_DataMapOfShapeListOfShape& theEImages,
1338 const TopTools_MapOfShape& theLastInvEdges,
1339 const TopTools_IndexedMapOfShape& theInvEdges,
1340 Handle(IntTools_Context)& theCtx,
1341 const TopTools_MapOfShape& theModifiedEdges,
1342 TopoDS_Shape& theEdges,
1343 TopTools_IndexedMapOfShape& theInv)
1345 // get boundary edges
1346 TopTools_MapOfShape aMFBounds;
1347 TopExp_Explorer aExp(theFace, TopAbs_EDGE);
1348 for (; aExp.More(); aExp.Next()) {
1349 const TopoDS_Shape& aE = aExp.Current();
1350 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1355 TopTools_ListIteratorOfListOfShape aItLE(*pLEIm);
1356 for (; aItLE.More(); aItLE.Next()) {
1357 const TopoDS_Shape& aEIm = aItLE.Value();
1358 aMFBounds.Add(aEIm);
1364 Standard_Boolean bFound(Standard_False), bUpdate(Standard_False);
1365 // the resulting edges
1366 TopoDS_Compound anEdges;
1367 aBB.MakeCompound(anEdges);
1369 TopTools_MapOfShape aMEFence;
1370 // the edges by which the offset face should be split
1371 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theFace);
1372 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1373 for (; aItLE.More(); aItLE.Next()) {
1374 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1377 bUpdate = theModifiedEdges.Contains(aE);
1380 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1382 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
1383 for (; aItLEIm.More(); aItLEIm.Next()) {
1384 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1386 if (!aMEFence.Add(aEIm))
1389 if (theInvEdges.Contains(aEIm)) {
1392 bUpdate = theLastInvEdges.Contains(aEIm);
1396 // check for micro edge
1397 if (ProcessMicroEdge(aEIm, theCtx)) {
1401 aBB.Add(anEdges, aEIm);
1403 bFound = !aMFBounds.Contains(aEIm);
1407 bUpdate = theModifiedEdges.Contains(aEIm);
1412 if (theInvEdges.Contains(aE)) {
1415 bUpdate = theLastInvEdges.Contains(aE);
1420 if (ProcessMicroEdge(aE, theCtx)) {
1423 aBB.Add(anEdges, aE);
1425 bFound = !aMFBounds.Contains(aE);
1431 return bFound && bUpdate;
1434 //=======================================================================
1435 //function : BuildSplitsOfFace
1436 //purpose : Building the splits of offset face
1437 //=======================================================================
1438 void BuildSplitsOfFace(const TopoDS_Face& theFace,
1439 const TopoDS_Shape& theEdges,
1440 TopTools_DataMapOfShapeShape& theFacesOrigins,
1441 TopTools_ListOfShape& theLFImages)
1443 theLFImages.Clear();
1445 // take edges to split the face
1446 TopTools_ListOfShape aLE;
1447 TopExp_Explorer aExp(theEdges, TopAbs_EDGE);
1448 for (; aExp.More(); aExp.Next()) {
1449 TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
1450 aE.Orientation(TopAbs_FORWARD);
1452 aE.Orientation(TopAbs_REVERSED);
1456 TopoDS_Face aFF = theFace;
1457 TopAbs_Orientation anOr = theFace.Orientation();
1458 aFF.Orientation(TopAbs_FORWARD);
1460 // build pcurves for edges on the face
1461 BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
1463 // build splits of faces
1464 BOPAlgo_BuilderFace aBF;
1469 const TopTools_ListOfShape& aLFSp = aBF.Areas();
1470 TopTools_ListIteratorOfListOfShape aItLF(aLFSp);
1471 for (; aItLF.More(); aItLF.Next()) {
1472 TopoDS_Shape& aFSp = aItLF.ChangeValue();
1473 aFSp.Orientation(anOr);
1474 theLFImages.Append(aFSp);
1476 theFacesOrigins.Bind(aFSp, theFace);
1480 //=======================================================================
1481 //function : BuildSplitsOfFace
1482 //purpose : Building the splits of offset face
1483 //=======================================================================
1484 void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
1485 const TopoDS_Shape& theEdges,
1486 TopTools_ListOfShape& theLFImages)
1488 BOPAlgo_Builder aGF;
1490 aGF.AddArgument(theFace);
1491 aGF.AddArgument(theEdges);
1493 if (aGF.HasErrors()) {
1497 // splits of the offset shape
1498 theLFImages = aGF.Modified(theFace);
1501 //=======================================================================
1502 //function : CheckIfArtificial
1503 //purpose : Checks if the face is artificially invalid
1504 //=======================================================================
1505 Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
1506 const TopTools_ListOfShape& theLFImages,
1507 const TopoDS_Shape& theCE,
1508 const TopTools_IndexedMapOfShape& theMapEInv,
1509 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1510 TopTools_MapOfShape& theMENInv,
1511 Handle(BRepAlgo_AsDes)& theAsDes)
1513 // all boundary edges should be used
1514 TopTools_IndexedMapOfShape aMEUsed;
1515 TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages);
1516 for (; aItLFIm.More(); aItLFIm.Next()) {
1517 const TopoDS_Shape& aFIm = aItLFIm.Value();
1518 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed);
1519 TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed);
1522 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
1523 TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
1525 Standard_Integer i, aNb = theMapEInv.Extent();
1526 for (i = 1; i <= aNb; ++i) {
1527 const TopoDS_Shape& aEInv = theMapEInv(i);
1528 TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX);
1529 for (; aExpV.More(); aExpV.Next()) {
1530 const TopoDS_Shape& aVEInv = aExpV.Current();
1531 const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv);
1533 TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv);
1534 for (; aItLEInv.More(); aItLEInv.Next()) {
1535 const TopoDS_Shape& aENInv = aItLEInv.Value();
1536 if (!aMEUsed.Contains(aENInv)) {
1537 theMENInv.Add(aENInv);
1544 if (theMENInv.IsEmpty()) {
1545 return Standard_False;
1548 TopTools_IndexedMapOfShape aMEFound;
1549 TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound);
1551 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF);
1552 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1553 for (; aItLE.More(); aItLE.Next()) {
1554 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1556 if (theOEImages.IsBound(aE)) {
1557 Standard_Boolean bChecked = Standard_False;
1558 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE);
1559 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
1560 for (; aItLEIm.More(); aItLEIm.Next()) {
1561 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1562 if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) {
1566 bChecked = Standard_True;
1567 if (aMEUsed.Contains(aEIm)) {
1572 if (bChecked && !aItLEIm.More()) {
1577 if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) {
1583 return aItLE.More();
1586 //=======================================================================
1587 //function : FindInvalidEdges
1588 //purpose : Looking for the invalid edges
1589 //=======================================================================
1590 void FindInvalidEdges(const TopoDS_Face& theF,
1591 const TopTools_ListOfShape& theLFImages,
1592 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1593 const TopTools_DataMapOfShapeShape& theFacesOrigins,
1594 const BRepOffset_Analyse* theAnalyse,
1595 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1596 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1597 TopTools_IndexedMapOfShape& theInvEdges,
1598 TopTools_IndexedMapOfShape& theValidEdges,
1599 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
1600 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
1601 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
1602 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
1603 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
1604 TopTools_MapOfShape& theMEInverted,
1605 TopTools_MapOfShape& theEdgesInvalidByVertex,
1606 TopTools_MapOfShape& theEdgesValidByVertex)
1608 // Edge is considered as invalid in the following cases:
1609 // 1. Its orientation on the face has changed comparing to the originals edge and face;
1610 // 2. The vertices of the edge have changed places comparing to the originals edge and face.
1612 // The edges created from vertices, i.e. as intersection between two faces connected only
1613 // by VERTEX, will also be checked on validity. For these edges the correct orientation will
1614 // be defined by the edges on the original face adjacent to the connection vertex
1617 const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
1619 TopTools_IndexedMapOfShape aMEInv;
1621 TopTools_MapOfShape aMEVal;
1623 TopTools_MapOfShape aMEInt;
1625 // maps for checking the inverted edges
1626 TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
1627 TopTools_IndexedMapOfShape aMEdges;
1628 // back map from the original shapes to their offset images
1629 TopTools_DataMapOfShapeListOfShape anImages;
1631 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
1632 for (; aItLF.More(); aItLF.Next()) {
1633 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1635 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1636 for (; aExp.More(); aExp.Next()) {
1637 const TopoDS_Shape& aE = aExp.Current();
1641 // keep connection from edges to faces
1642 TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE);
1644 pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape()));
1646 AppendToList(*pLF, aFIm);
1648 // keep connection from vertices to edges
1649 TopoDS_Iterator aItV(aE);
1650 for (; aItV.More(); aItV.Next()) {
1651 const TopoDS_Shape& aV = aItV.Value();
1653 TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV);
1655 pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape()));
1657 AppendToList(*pLE, aE);
1660 // back map from original edges to their offset images
1661 const TopTools_ListOfShape* pLOr = theEdgesOrigins.Seek (aE);
1664 for (TopTools_ListOfShape::Iterator itOr (*pLOr); itOr.More(); itOr.Next())
1666 const TopoDS_Shape& aSOr = itOr.Value();
1668 if (!FindShape (aSOr, aFOr, theAnalyse, aSInF))
1670 TopTools_ListOfShape* pImages = anImages.ChangeSeek (aSInF);
1672 pImages = anImages.Bound (aSInF, TopTools_ListOfShape());
1673 AppendToList (*pImages, aE);
1678 // the map will be used to find the edges on the original face
1679 // adjacent to the same vertex. It will be filled at first necessity;
1680 TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
1682 aItLF.Initialize(theLFImages);
1683 for (; aItLF.More(); aItLF.Next()) {
1684 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1686 // valid edges for this split
1687 TopTools_MapOfShape aMVE;
1688 // invalid edges for this split
1689 TopTools_IndexedMapOfShape aMIE;
1691 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1692 for (; aExp.More(); aExp.Next()) {
1693 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
1695 if (aEIm.Orientation() == TopAbs_INTERNAL) {
1700 if (!theEdgesOrigins.IsBound(aEIm)) {
1704 const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm);
1705 if (aLEOr.IsEmpty()) {
1709 Standard_Integer aNbVOr = 0;
1710 TopTools_ListIteratorOfListOfShape aItLEO(aLEOr);
1711 for (; aItLEO.More(); aItLEO.Next()) {
1712 if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) {
1716 if (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1)
1719 TopTools_MapOfShape aME, aMV, aMF;
1720 Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
1721 Standard_Integer aNbP = NbPoints(aEIm), aNbInv = 0;
1722 Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
1724 aDMEF.FindFromKey(aEIm).Extent() == 1 &&
1725 !theOEOrigins.IsBound(aEIm));
1727 aItLEO.Initialize(aLEOr);
1728 for (; aItLEO.More(); aItLEO.Next()) {
1729 const TopoDS_Shape& aSOr = aItLEO.Value();
1730 Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
1734 // for some cases it is impossible to check the validity of the edge
1738 // find edges on the original face adjacent to this vertex
1739 if (aDMVEFOr.IsEmpty()) {
1741 TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
1744 TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr);
1746 TopoDS_Compound aCEOr;
1747 BRep_Builder().MakeCompound(aCEOr);
1748 // Avoid classification of edges originated from vertices
1749 // located between tangent edges
1750 Standard_Boolean bAllTgt = Standard_True;
1751 TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
1752 gp_Vec aVRef = GetAverageTangent (aItLEFOr.Value(), aNbP);
1753 for (; aItLEFOr.More(); aItLEFOr.Next())
1755 const TopoDS_Shape& aEOr = aItLEFOr.Value();
1756 BRep_Builder().Add(aCEOr, aEOr);
1758 gp_Vec aVCur = GetAverageTangent (aEOr, aNbP);
1759 if (!aVRef.IsParallel (aVCur, Precision::Angular()))
1760 bAllTgt = Standard_False;
1767 FindShape(aSOr, aFOr, theAnalyse, aEOrF);
1769 TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr);
1771 pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape());
1773 AppendToList(*pLEIm, aEIm);
1776 if (aEOrF.IsNull()) {
1777 // the edge has not been found
1783 TopTools_MapOfShape aMVTotal;
1784 Standard_Integer aNbChecked = 0;
1785 // Just check if the original edges sharing the vertex do not share it any more.
1786 for (TopoDS_Iterator it (aEOrF); it.More(); it.Next())
1788 const TopoDS_Shape& aEOr = it.Value();
1789 const TopTools_ListOfShape* aLIm = anImages.Seek (aEOr);
1793 TopTools_IndexedDataMapOfShapeListOfShape aMVLoc;
1794 for (TopTools_ListOfShape::Iterator itLIM (*aLIm); itLIM.More(); itLIM.Next())
1795 TopExp::MapShapesAndAncestors (itLIM.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVLoc);
1796 for (Standard_Integer i = 1; i <= aMVLoc.Extent(); ++i)
1798 if (aMVLoc(i).Extent() > 1 && !aMVTotal.Add (aMVLoc.FindKey (i)))
1800 bInvalid = Standard_True;
1801 theEdgesInvalidByVertex.Add(aEIm);
1808 if (!bInvalid && aNbChecked < 2)
1811 theEdgesValidByVertex.Add (aEIm);
1816 // Check orientations of the image edge and original edge.
1817 // In case the 3d curves are having the same direction the orientations
1818 // must be the same. Otherwise the orientations should also be different.
1820 // get average tangent vector for each curve taking into account
1821 // the orientations of the edges, i.e. the edge is reversed
1822 // the vector is reversed as well
1823 gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP);
1824 gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP);
1829 Standard_Real aCos = aVSum1.Dot(aVSum2);
1830 if (Abs(aCos) < 0.9999) {
1835 TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX);
1836 for (; aExpE.More(); aExpE.Next()) {
1837 const TopoDS_Shape& aV = aExpE.Current();
1842 for (TopTools_ListOfShape::Iterator itFA (theAnalyse->Ancestors (aEOrF));
1843 itFA.More(); itFA.Next())
1844 aMF.Add (itFA.Value());
1847 if (aCos < Precision::Confusion()) {
1848 bInvalid = Standard_True;
1852 bChecked = Standard_True;
1859 Standard_Boolean bLocalOnly = (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1);
1860 Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
1861 if (aNbE > 1 && aNbV == 2*aNbE)
1863 Standard_Boolean bSkip = Standard_True;
1865 // Allow the edge to be analyzed if it is:
1866 // * originated from more than two faces
1867 // * unanimously considered valid or invalid
1868 // * not a boundary edge in the splits
1869 if (aMF.Extent () > 2 && (aNbInv == 0 || aNbInv == aNbE))
1871 if (theLFImages.Extent() > 2)
1873 TopoDS_Iterator itV (aEIm);
1874 for (; itV.More(); itV.Next())
1876 TopTools_ListOfShape::Iterator itE (aDMVE.FindFromKey (itV.Value()));
1877 for (; itE.More(); itE.Next())
1878 if (aDMEF.FindFromKey (itE.Value()).Extent() < 2)
1889 bLocalOnly = Standard_True;
1894 theInvEdges.Add(aEIm);
1900 // check if the edge has been inverted
1901 Standard_Boolean bInverted = !aNbE || bLocalOnly ? Standard_False :
1902 CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
1903 theEdgesOrigins, aDMVE, aMEdges, theMEInverted);
1905 if (!bInverted || !aNbVOr) {
1907 theValidEdges.Add(aEIm);
1916 theDMFMVE.Bind (aFIm, aMVE);
1922 theDMFMIE.Bind (aFIm, aMIE);
1926 // process invalid edges:
1927 // check for the inverted edges
1928 TopTools_MapOfShape aMVIE;
1929 // fill neutral edges
1930 TopTools_MapOfShape aMNE;
1932 Standard_Integer i, aNbEInv = aMEInv.Extent();
1933 for (i = 1; i <= aNbEInv; ++i) {
1934 const TopoDS_Shape& aEIm = aMEInv(i);
1936 // neutral edges - on the splits of the same offset face
1937 // it is valid for one split and invalid for other
1938 if (aMEVal.Contains(aEIm))
1944 // the inverted images of the origins of invalid edges should also be invalid
1945 if (!theMEInverted.Contains(aEIm)) {
1949 const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm);
1954 TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr);
1955 for (; aItLOEOr.More(); aItLOEOr.Next()) {
1956 const TopoDS_Shape& aOEOr = aItLOEOr.Value();
1957 const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr);
1959 TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1);
1960 for (; aItLEIm1.More(); aItLEIm1.Next()) {
1961 const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
1962 if (aMEdges.Contains(aEIm1) &&
1963 !aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) &&
1964 theMEInverted.Contains(aEIm1)) {
1965 theInvEdges.Add(aEIm1);
1974 theDMFMNE.Bind (theF, aMNE);
1979 theDMFMVIE.Bind (theF, aMVIE);
1985 static void addAsNeutral (const TopoDS_Shape& theE,
1986 const TopoDS_Shape& theFInv,
1987 const TopoDS_Shape& theFVal,
1988 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
1989 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges)
1991 TopTools_IndexedMapOfShape* pMEInv = theLocInvEdges.ChangeSeek (theFInv);
1993 pMEInv = theLocInvEdges.Bound (theFInv, TopTools_IndexedMapOfShape());
1996 TopTools_MapOfShape* pMEVal = theLocValidEdges.ChangeSeek (theFVal);
1998 pMEVal = theLocValidEdges.Bound (theFVal, TopTools_MapOfShape());
2003 //=======================================================================
2004 //function : FindInvalidEdges
2005 //purpose : Additional method to look for invalid faces
2006 //=======================================================================
2007 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
2008 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2009 const TopTools_DataMapOfShapeShape& theFacesOrigins,
2010 const BRepOffset_Analyse* theAnalyse,
2011 const TopTools_IndexedMapOfShape& theInvEdges,
2012 const TopTools_IndexedMapOfShape& theValidEdges,
2013 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2014 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
2015 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges)
2017 // 1. Find edges unclassified in faces
2018 // 2. Find SD faces in which the same edge is classified
2019 // 3. Check if the edge is neutral in face in which it wasn't classified
2021 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aMEUnclassified;
2022 TopTools_DataMapOfShapeShape aFSplitFOffset;
2024 // Avoid artificial faces
2025 TopTools_MapOfShape aNewFaces;
2028 TopTools_MapOfShape aMapNewTmp;
2029 for (TopTools_ListOfShape::Iterator it (theAnalyse->NewFaces()); it.More(); it.Next())
2030 aMapNewTmp.Add (it.Value());
2032 for (TopTools_ListOfShape::Iterator it (theLFOffset); it.More(); it.Next())
2034 const TopoDS_Shape& aFOffset = it.Value();
2035 const TopoDS_Shape& aFOrigin = theFacesOrigins.Find (aFOffset);
2036 if (aMapNewTmp.Contains (aFOrigin))
2037 aNewFaces.Add (aFOffset);
2041 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
2042 for (TopTools_ListOfShape::Iterator itLFO (theLFOffset); itLFO.More(); itLFO.Next())
2044 const TopoDS_Shape& aF = itLFO.Value();
2045 if (aNewFaces.Contains (aF))
2048 const TopTools_ListOfShape& aLFImages = theFImages.FindFromKey (aF);
2049 for (TopTools_ListOfShape::Iterator itLF (aLFImages); itLF.More(); itLF.Next())
2051 const TopoDS_Shape& aFIm = itLF.Value();
2053 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFMap);
2055 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFIm);
2056 const TopTools_MapOfShape* pMEValid = theLocValidEdges.Seek (aFIm);
2058 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
2060 const TopoDS_Shape& aE = expE.Current();
2061 if (theInvEdges.Contains (aE) != theValidEdges.Contains (aE))
2063 // edge is classified in some face
2065 if ((!pMEInvalid || !pMEInvalid->Contains (aE)) &&
2066 (!pMEValid || !pMEValid->Contains (aE)))
2068 // but not in the current one
2069 TopTools_MapOfShape *pMap = aMEUnclassified.ChangeSeek (aE);
2071 pMap = &aMEUnclassified (aMEUnclassified.Add (aE, TopTools_MapOfShape()));
2074 aFSplitFOffset.Bind (aFIm, aF);
2081 if (aMEUnclassified.IsEmpty())
2084 // Analyze unclassified edges
2085 const Standard_Integer aNbE = aMEUnclassified.Extent();
2086 for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
2088 const TopoDS_Shape& aE = aMEUnclassified.FindKey (iE);
2089 const TopTools_MapOfShape& aMFUnclassified = aMEUnclassified (iE);
2091 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
2093 for (TopTools_ListOfShape::Iterator itLF (aLF); itLF.More(); itLF.Next())
2095 const TopoDS_Shape& aFClassified = itLF.Value();
2096 if (aMFUnclassified.Contains (aFClassified))
2099 BOPTools_Set anEdgeSetClass;
2100 anEdgeSetClass.Add (aFClassified, TopAbs_EDGE);
2102 TopoDS_Shape aEClassified;
2103 FindShape (aE, aFClassified, NULL, aEClassified);
2104 TopAbs_Orientation anOriClass = aEClassified.Orientation();
2107 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aEClassified), TopoDS::Face (aFClassified), aDNClass);
2109 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFClassified);
2110 Standard_Boolean isInvalid = pMEInvalid && pMEInvalid->Contains (aE);
2112 for (TopTools_MapOfShape::Iterator itM (aMFUnclassified); itM.More(); itM.Next())
2114 const TopoDS_Shape& aFUnclassified = itM.Value();
2116 BOPTools_Set anEdgeSetUnclass;
2117 anEdgeSetUnclass.Add (aFUnclassified, TopAbs_EDGE);
2119 if (anEdgeSetClass.IsEqual (anEdgeSetUnclass))
2122 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aE), TopoDS::Face (aFUnclassified), aDNUnclass);
2124 Standard_Boolean isSameOri = aDNClass.IsEqual (aDNUnclass, Precision::Angular());
2126 // Among other splits of the same face find those where the edge is contained with different
2128 const TopoDS_Shape& aFOffset = aFSplitFOffset.Find (aFUnclassified);
2129 const TopTools_ListOfShape& aLFSplits = theFImages.FindFromKey (aFOffset);
2130 TopTools_ListOfShape::Iterator itLFSp (aLFSplits);
2131 for (; itLFSp.More(); itLFSp.Next())
2133 const TopoDS_Shape& aFSp = itLFSp.Value();
2135 if (!aFSp.IsSame (aFUnclassified) && aMFUnclassified.Contains (aFSp))
2137 TopoDS_Shape aEUnclassified;
2138 FindShape (aE, aFSp, NULL, aEUnclassified);
2140 TopAbs_Orientation anOriUnclass = aEUnclassified.Orientation();
2142 anOriUnclass = TopAbs::Reverse (anOriUnclass);
2144 if (anOriClass != anOriUnclass)
2146 // make the edge neutral for the face
2147 TopTools_MapOfShape* pMENeutral = theNeutralEdges.ChangeSeek (aFOffset);
2149 pMENeutral = theNeutralEdges.Bound (aFOffset, TopTools_MapOfShape());
2150 pMENeutral->Add (aE);
2152 if (isInvalid && isSameOri)
2154 // make edge invalid in aFUnclassified and valid in aFSp
2155 addAsNeutral (aE, aFClassified, aFSp, theLocInvEdges, theLocValidEdges);
2159 // make edge invalid in aFSp and valid in aFUnclassified
2160 addAsNeutral (aE, aFSp, aFClassified, theLocInvEdges, theLocValidEdges);
2173 //=======================================================================
2174 //function : FindInvalidFaces
2175 //purpose : Looking for the invalid faces by analyzing their invalid edges
2176 //=======================================================================
2177 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
2178 const TopTools_IndexedMapOfShape& theInvEdges,
2179 const TopTools_IndexedMapOfShape& theValidEdges,
2180 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
2181 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
2182 const TopTools_MapOfShape& theMENeutral,
2183 const TopTools_MapOfShape& theMEInverted,
2184 const TopTools_MapOfShape& theEdgesInvalidByVertex,
2185 const TopTools_MapOfShape& theEdgesValidByVertex,
2186 const TopTools_MapOfShape& theMFHoles,
2187 TopTools_IndexedMapOfShape& theMFInvInHole,
2188 TopTools_ListOfShape& theInvFaces,
2189 TopTools_ListOfShape& theInvertedFaces)
2191 // The face should be considered as invalid in the following cases:
2192 // 1. It has been reverted, i.e. at least two not connected edges
2193 // have changed orientation (i.e. invalid). In this case all edges,
2194 // should be invalid for that face, because edges have also been reverted;
2195 // 2. All checked edges of the face are invalid for this face;
2196 // The face should be removed from the splits in the following cases:
2197 // 1. All checked edges of the face are invalid for this one, but valid for
2198 // some other face in this list of splits.
2199 // The face will be kept in the following cases:
2200 // 1. Some of the edges are valid for this face.
2201 Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
2202 Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
2203 Standard_Boolean bIsInvalidByInverted;
2204 Standard_Integer aNbChecked;
2206 Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
2208 // neutral edges to remove
2209 TopTools_IndexedMapOfShape aMENRem;
2211 // faces for post treat
2212 TopTools_ListOfShape aLFPT;
2214 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
2215 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2216 for (; aItLF.More(); aItLF.Next())
2218 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2219 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
2222 aItLF.Initialize (theLFImages);
2223 for (; aItLF.More(); ) {
2224 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2226 // valid edges for this split
2227 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
2228 // invalid edges for this split
2229 const TopTools_IndexedMapOfShape* pMIE = theDMFMIE.Seek (aFIm);
2231 bHasValid = Standard_False;
2232 bAllValid = Standard_True;
2233 bAllInvalid = Standard_True;
2234 bHasReallyInvalid = Standard_False;
2235 bAllInvNeutral = Standard_True;
2236 bIsInvalidByInverted = Standard_True;
2239 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2240 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2241 for (; aExp.More(); aExp.Next()) {
2242 const TopoDS_Shape& aEIm = aExp.Current();
2244 bValid = theValidEdges.Contains(aEIm);
2245 bInvalid = theInvEdges.Contains(aEIm);
2246 bNeutral = theMENeutral.Contains(aEIm);
2248 if (!bValid && !bInvalid && !bNeutral) {
2249 // edge has not been checked for some reason
2253 // skip not-boundary edges originated from vertex
2254 if ((theEdgesInvalidByVertex.Contains (aEIm) ||
2255 theEdgesValidByVertex.Contains (aEIm)) &&
2256 aDMEF.FindFromKey (aEIm).Extent() != 1)
2261 bInvalidLoc = pMIE && pMIE->Contains (aEIm);
2262 bHasReallyInvalid = bInvalid && bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
2263 if (bHasReallyInvalid) {
2267 bValidLoc = pMVE && pMVE->Contains(aEIm);
2268 bInverted = theMEInverted.Contains(aEIm);
2269 if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid) {
2270 bInvalid = bInverted;
2273 if (bValidLoc && bNeutral) {
2274 bHasValid = Standard_True;
2277 bAllValid &= bValidLoc;
2278 bAllInvalid &= (bInvalid || bInvalidLoc);
2279 bAllInvNeutral &= (bAllInvalid && bNeutral);
2280 bIsInvalidByInverted &= (bInvalidLoc || bInverted);
2288 if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) {
2289 // remove edges from neutral
2290 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2292 theLFImages.Remove(aItLF);
2296 if (bHasReallyInvalid || (bAllInvalid &&
2297 !(bHasValid || bAllValid) &&
2298 !(bAllInvNeutral && (aNbChecked == 1)))) {
2299 theInvFaces.Append(aFIm);
2300 if (theMFHoles.Contains(aFIm)) {
2301 theMFInvInHole.Add(aFIm);
2307 if (theMFHoles.Contains(aFIm)) {
2308 // remove edges from neutral
2309 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2311 theLFImages.Remove(aItLF);
2315 if (bIsInvalidByInverted && !(bHasValid || bAllValid))
2317 // The face contains only the inverted and locally invalid edges
2318 theInvertedFaces.Append(aFIm);
2321 if (!bAllInvNeutral) {
2325 // remove edges from neutral
2326 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2331 if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) {
2335 // check the splits once more
2336 aItLF.Initialize(aLFPT);
2337 for (; aItLF.More(); aItLF.Next()) {
2338 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2340 // valid edges for this split
2341 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek(aFIm);
2343 bHasValid = Standard_False;
2344 bAllValid = Standard_True;
2345 bAllInvalid = Standard_True;
2347 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2348 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2349 for (; aExp.More(); aExp.Next()) {
2350 const TopoDS_Shape& aEIm = aExp.Current();
2352 bValid = theValidEdges.Contains(aEIm);
2353 bInvalid = theInvEdges.Contains(aEIm);
2354 bNeutral = theMENeutral.Contains(aEIm) && !aMENRem.Contains (aEIm);
2355 bValidLoc = pMVE && pMVE->Contains(aEIm);
2357 if (!bInvalid && bTreatInvertedAsInvalid) {
2358 bInvalid = theMEInverted.Contains(aEIm);
2361 if (bValidLoc && bNeutral) {
2362 bHasValid = Standard_True;
2365 bAllValid = bAllValid && bValidLoc;
2366 bAllInvalid = bAllInvalid && bInvalid;
2369 if (bAllInvalid && !bHasValid && !bAllValid) {
2370 theInvFaces.Append(aFIm);
2375 //=======================================================================
2376 //function : FindFacesInsideHoleWires
2377 //purpose : Find faces inside holes wires from the original face
2378 //=======================================================================
2379 void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
2380 const TopoDS_Face& theFOffset,
2381 const TopTools_ListOfShape& theLFImages,
2382 const TopTools_MapOfShape& theInvertedEdges,
2383 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
2384 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
2385 TopTools_MapOfShape& theMFHoles,
2386 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
2387 Handle(IntTools_Context)& theContext)
2389 if (theLFImages.IsEmpty()) {
2393 // find all hole wires in the original face
2394 TopTools_ListOfShape aLHoleWires;
2395 const TopoDS_Wire& anOuterWire = BRepTools::OuterWire(theFOrigin);
2396 TopExp_Explorer aExpW(theFOrigin, TopAbs_WIRE);
2397 for (; aExpW.More(); aExpW.Next()) {
2398 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aExpW.Current());
2399 if (!aHoleWire.IsSame(anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL) {
2400 aLHoleWires.Append(aHoleWire);
2404 if (aLHoleWires.IsEmpty()) {
2405 // no holes in the face
2409 TopTools_ListOfShape *pLFNewHoles = theDMFNewHoles.ChangeSeek(theFOrigin);
2412 pLFNewHoles = theDMFNewHoles.Bound(theFOrigin, TopTools_ListOfShape());
2414 if (pLFNewHoles->IsEmpty()) {
2416 // find the faces representing holes in the images of the faces:
2417 // 1. for each original hole wire try to build its image
2418 // 2. build the new planar face from the images
2420 // map vertices and edges of the splits
2421 TopTools_IndexedMapOfShape aMESplits;
2422 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2423 for (; aItLF.More(); aItLF.Next()) {
2424 TopExp::MapShapes(aItLF.Value(), TopAbs_EDGE, aMESplits);
2427 TopTools_ListIteratorOfListOfShape aItLW(aLHoleWires);
2428 for (; aItLW.More(); aItLW.Next()) {
2429 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aItLW.Value());
2430 // find images of all edges of the original wire
2431 TopTools_IndexedMapOfShape aMEImWire;
2432 TopoDS_Iterator aItE(aHoleWire);
2433 for (; aItE.More(); aItE.Next()) {
2434 const TopoDS_Shape& aEOr = aItE.Value();
2435 const TopTools_ListOfShape *pLEIm = theDMEOrLEIm.Seek(aEOr);
2436 if (!pLEIm || pLEIm->IsEmpty()) {
2439 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
2440 for (; aItLEIm.More(); aItLEIm.Next()) {
2441 const TopoDS_Shape& aEIm = aItLEIm.Value();
2442 if (aMESplits.Contains(aEIm)) {
2443 aMEImWire.Add(aEIm);
2448 if (aMEImWire.IsEmpty()) {
2452 // build new planar face using these edges
2453 TopTools_ListOfShape aLE;
2454 Standard_Integer i, aNbE = aMEImWire.Extent();
2455 for (i = 1; i <= aNbE; ++i) {
2456 aLE.Append(aMEImWire(i).Oriented(TopAbs_FORWARD));
2457 aLE.Append(aMEImWire(i).Oriented(TopAbs_REVERSED));
2460 BOPAlgo_BuilderFace aBF;
2461 aBF.SetFace(TopoDS::Face(theFOffset.Oriented(TopAbs_FORWARD)));
2465 const TopTools_ListOfShape& aLFNew = aBF.Areas();
2466 if (aLFNew.IsEmpty()) {
2470 // check if outer edges in the new faces are not inverted
2471 // because the inverted edges mean that the hole has been
2472 // filled during offset and there will be no faces to remove
2473 TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew;
2474 TopTools_ListIteratorOfListOfShape aItLFNew(aLFNew);
2475 for (; aItLFNew.More(); aItLFNew.Next()) {
2476 TopExp::MapShapesAndAncestors(aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew);
2479 aNbE = aDMEFNew.Extent();
2480 for (i = 1; i <= aNbE; ++i) {
2481 if (aDMEFNew(i).Extent() == 1) {
2482 const TopoDS_Shape& aE = aDMEFNew.FindKey(i);
2483 if (theInvertedEdges.Contains(aE)) {
2493 aItLFNew.Initialize(aLFNew);
2494 for (; aItLFNew.More(); aItLFNew.Next()) {
2495 pLFNewHoles->Append(aItLFNew.Value());
2500 // Build Edge-Face map for splits of current offset face
2501 TopTools_IndexedDataMapOfShapeListOfShape anEFSplitsMap;
2502 // Build Edge-Face map for holes
2503 TopTools_IndexedDataMapOfShapeListOfShape anEFHolesMap;
2505 // among the splits of the offset face find those that are
2506 // located inside the hole faces
2507 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2508 for (; aItLF.More(); aItLF.Next()) {
2509 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
2510 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFSplitsMap);
2511 // get the point inside the face and classify it relatively hole faces
2514 Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(aFIm, aP3D, aP2D, theContext);
2519 Standard_Real aTol = BRep_Tool::Tolerance(aFIm);
2521 TopTools_ListIteratorOfListOfShape aItLFNew(*pLFNewHoles);
2522 for (; aItLFNew.More(); aItLFNew.Next()) {
2523 const TopoDS_Face& aFNew = TopoDS::Face(aItLFNew.Value());
2524 if (theContext->IsValidPointForFace(aP3D, aFNew, aTol)) {
2525 // the face is classified as IN
2526 theMFHoles.Add(aFIm);
2527 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFHolesMap);
2533 // Out of all found holes find those which cannot be removed
2534 // by checking their connectivity to splits of other offset faces.
2535 // These are the faces, which will create uncovered holes if removed.
2536 const Standard_Integer aNbE = anEFHolesMap.Extent();
2537 for (Standard_Integer i = 1; i <= aNbE; ++i)
2539 const TopoDS_Shape& anEdge = anEFHolesMap.FindKey(i);
2540 const TopTools_ListOfShape& aLFHoles = anEFHolesMap(i);
2541 // Check if the edge is outer for holes
2542 if (aLFHoles.Extent() != 1)
2545 const TopoDS_Shape& aFHole = aLFHoles.First();
2546 if (!theMFHoles.Contains(aFHole))
2550 // Check if the edge is not outer for splits
2551 const TopTools_ListOfShape& aLSplits = anEFSplitsMap.FindFromKey(anEdge);
2552 if (aLSplits.Extent() == 1)
2555 // Check if edge is only connected to splits of the current offset face
2556 const TopTools_ListOfShape& aLFAll = theEFMap.FindFromKey(anEdge);
2557 if (aLFAll.Extent() == 2)
2558 // Avoid removal of the hole from the splits
2559 theMFHoles.Remove(aFHole);
2563 //=======================================================================
2564 //function : GetAverageTangent
2565 //purpose : Computes average tangent vector along the curve
2566 //=======================================================================
2567 gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
2568 const Standard_Integer theNbP)
2571 TopExp_Explorer aExp(theS, TopAbs_EDGE);
2572 for (; aExp.More(); aExp.Next()) {
2573 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
2575 Standard_Real aT1, aT2;
2576 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
2580 Standard_Real aT = aT1;
2581 Standard_Real aDt = (aT2 - aT1) / theNbP;
2584 aVSum += aV.Normalized();
2588 if (aE.Orientation() == TopAbs_REVERSED) {
2597 //=======================================================================
2598 //function : CheckInverted
2599 //purpose : Checks if the edge has been inverted
2600 //=======================================================================
2601 Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
2602 const TopoDS_Face& theFOr,
2603 const TopTools_DataMapOfShapeListOfShape& theOEImages,
2604 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2605 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
2606 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
2607 const TopTools_IndexedMapOfShape& theMEdges,
2608 TopTools_MapOfShape& theMEInverted)
2610 // It is necessary to compare the direction from first vertex
2611 // to the last vertex on the original edge with the
2612 // same direction on the new edge. If the directions
2613 // will be different - the edge has been inverted.
2615 TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
2616 TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
2619 // find vertices of the offset shape
2620 TopExp::Vertices(theEIm, aVI1, aVI2);
2623 TopTools_ListOfShape aLEImages;
2624 if (theOEOrigins.IsBound(theEIm)) {
2625 TopoDS_Wire anImages;
2626 BRep_Builder().MakeWire(anImages);
2628 TopTools_MapOfShape aMImFence;
2629 const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm);
2630 TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr);
2631 for (; aItOffset.More(); aItOffset.Next()) {
2632 const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
2633 const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr);
2635 TopTools_ListIteratorOfListOfShape aItImages(aLImages);
2636 for (; aItImages.More(); aItImages.Next()) {
2637 const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
2638 if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) {
2639 BRep_Builder().Add(anImages, anIm);
2640 aLEImages.Append(anIm);
2645 // find alone vertices
2646 TopoDS_Vertex aVW1, aVW2;
2647 TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
2648 TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
2650 TopTools_ListOfShape aLVAlone;
2651 Standard_Integer aNb = aDMImVE.Extent();
2652 for (i = 1; i <= aNb; ++i) {
2653 const TopTools_ListOfShape& aLImE = aDMImVE(i);
2654 if (aLImE.Extent() == 1) {
2655 aLVAlone.Append(aDMImVE.FindKey(i));
2659 if (aLVAlone.Extent() > 1) {
2660 aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
2661 aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
2664 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2665 const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1);
2666 const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2);
2668 Standard_Real aDist1 = aPI1.SquareDistance(aPW1);
2669 Standard_Real aDist2 = aPI1.SquareDistance(aPW2);
2671 if (aDist1 < aDist2) {
2682 aLEImages.Append(theEIm);
2685 // Find edges connected to these vertices
2686 const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1);
2687 const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2);
2689 // Find vertices on the original face corresponding to vertices on the offset edge
2691 // find original edges for both lists
2692 TopTools_ListOfShape aLOE1, aLOE2;
2693 for (i = 0; i < 2; ++i) {
2694 const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
2695 TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2697 TopTools_MapOfShape aMFence;
2699 TopTools_ListIteratorOfListOfShape aItLIE(aLIE);
2700 for (; aItLIE.More(); aItLIE.Next()) {
2701 const TopoDS_Shape& aEI = aItLIE.Value();
2702 if (theEdgesOrigins.IsBound(aEI)) {
2703 const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI);
2705 TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins);
2706 for (; aItLOE.More(); aItLOE.Next()) {
2707 const TopoDS_Shape& aEO = aItLOE.Value();
2708 if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) {
2710 if (FindShape(aEO, theFOr, NULL, aEOin)) {
2711 AppendToList(aLOE, aEO);
2719 if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) {
2720 return Standard_False;
2723 // find vertices common for all edges in the lists
2724 for (i = 0; i < 2; ++i) {
2725 const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2726 TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
2728 const TopoDS_Shape& aEO = aLOE.First();
2729 TopExp_Explorer aExpV(aEO, TopAbs_VERTEX);
2730 for (; aExpV.More(); aExpV.Next()) {
2731 const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current();
2733 Standard_Boolean bVertValid = Standard_True;
2734 TopTools_ListIteratorOfListOfShape aItLOE(aLOE);
2735 for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) {
2736 const TopoDS_Shape& aEOx = aItLOE.Value();
2737 TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX);
2738 for (; aExpVx.More(); aExpVx.Next()) {
2739 const TopoDS_Shape& aVx = aExpVx.Current();
2740 if (aVx.IsSame(aV)) {
2745 if (!aExpVx.More()) {
2746 bVertValid = Standard_False;
2758 if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) {
2759 return Standard_False;
2762 // check positions of the offset and original vertices
2763 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2764 const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2);
2765 const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1);
2766 const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2);
2768 gp_Vec aVI(aPI1, aPI2);
2769 gp_Vec aVO(aPO1, aPO2);
2771 Standard_Real anAngle = aVI.Angle(aVO);
2772 Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4;
2774 TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages);
2775 for (; aItLEIm.More(); aItLEIm.Next()) {
2776 const TopoDS_Shape& aEInvr = aItLEIm.Value();
2777 theMEInverted.Add(aEInvr);
2783 //=======================================================================
2784 //function : CheckInvertedBlock
2785 //purpose : Checks if it is possible to remove the block containing
2787 //=======================================================================
2788 Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
2789 const TopTools_ListOfShape& theLCBF,
2790 const TopTools_MapOfShape& theMEInverted,
2791 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2792 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
2793 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll)
2795 // For possible removal of the block:
2796 // 1. There should be more than just one face in the block
2797 if (theCB.NbChildren() < 2) {
2798 return Standard_False;
2801 // 2. The block should at least contain two connected inverted edges with
2802 // different origins (not just two images/splits of the same edge)
2803 TopTools_MapOfShape aMECBInv;
2804 TopoDS_Compound aCECBInv;
2805 BRep_Builder().MakeCompound(aCECBInv);
2807 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
2808 for (; aExp.More(); aExp.Next()) {
2809 const TopoDS_Shape& aE = aExp.Current();
2810 if (theMEInverted.Contains(aE)) {
2811 if (aMECBInv.Add(aE)) {
2812 BRep_Builder().Add(aCECBInv, aE);
2817 if (aMECBInv.Extent() < 2) {
2818 return Standard_False;
2821 // check that the edges are connected and different
2822 TopTools_ListOfShape aLCBE;
2823 BOPTools_AlgoTools::MakeConnexityBlocks(aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
2825 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
2826 for (; aItLCBE.More(); aItLCBE.Next()) {
2827 const TopoDS_Shape& aCBE = aItLCBE.Value();
2828 // count the unique edges in the block
2829 Standard_Integer aNbUnique = 0;
2830 TopTools_MapOfShape aMEOrigins;
2831 TopoDS_Iterator aItE(aCBE);
2832 for (; aItE.More(); aItE.Next()) {
2833 const TopoDS_Shape& aE = aItE.Value();
2834 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
2840 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
2841 for (; aItLEOr.More(); aItLEOr.Next()) {
2842 const TopoDS_Shape& aEOr = aItLEOr.Value();
2843 if (aMEOrigins.Add(aEOr)) {
2849 if (aNbUnique >= 2) {
2854 if (!aItLCBE.More()) {
2855 return Standard_False;
2858 // 3. the block should not contain inverted edges which vertices
2859 // are contained in other blocks
2861 // collect vertices from inverted edges and compare them with
2862 // vertices from other blocks
2863 TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek(theCB);
2864 TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek(theCB);
2866 pMVInverted = theDMCBVInverted.Bound(theCB, TopTools_MapOfShape());
2867 pMVAll = theDMCBVAll.Bound(theCB, TopTools_MapOfShape());
2869 GetVerticesOnEdges(theCB, theMEInverted, *pMVInverted, *pMVAll);
2872 TopTools_ListIteratorOfListOfShape aItLCB1(theLCBF);
2873 for (; aItLCB1.More(); aItLCB1.Next()) {
2874 const TopoDS_Shape& aCB1 = aItLCB1.Value();
2875 if (aCB1.IsSame(theCB)) {
2879 // collect vertices from inverted edges
2880 TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek(aCB1);
2881 TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek(aCB1);
2882 if (!pMVInverted1) {
2883 pMVInverted1 = theDMCBVInverted.Bound(aCB1, TopTools_MapOfShape());
2884 pMVAll1 = theDMCBVAll.Bound(aCB1, TopTools_MapOfShape());
2886 GetVerticesOnEdges(aCB1, theMEInverted, *pMVInverted1, *pMVAll1);
2889 if (pMVInverted->HasIntersection(*pMVAll1)) {
2890 return Standard_False;
2894 return Standard_True;
2897 //=======================================================================
2898 //function : GetVerticesOnEdges
2899 //purpose : Get vertices from the given shape belonging to the given edges
2900 //=======================================================================
2901 void GetVerticesOnEdges(const TopoDS_Shape& theCB,
2902 const TopTools_MapOfShape& theEdges,
2903 TopTools_MapOfShape& theVerticesOnEdges,
2904 TopTools_MapOfShape& theAllVertices)
2906 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
2907 for (; aExp.More(); aExp.Next()) {
2908 const TopoDS_Shape& aE = aExp.Current();
2909 Standard_Boolean bOnGivenEdge = theEdges.Contains(aE);
2910 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
2911 theAllVertices.Add(aItV.Value());
2913 theVerticesOnEdges.Add(aItV.Value());
2919 //=======================================================================
2920 //function : RemoveInvalidSplitsByInvertedEdges
2921 //purpose : Looking for the invalid faces containing inverted edges
2922 // that can be safely removed
2923 //=======================================================================
2924 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
2925 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2926 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
2927 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2928 TopTools_IndexedMapOfShape& theMERemoved)
2930 if (theMEInverted.IsEmpty()) {
2934 // check the faces on regularity, i.e. the splits of the same face
2935 // should not be connected only by vertex. Such irregular splits
2936 // will have to be rebuilt and cannot be removed.
2939 TopTools_IndexedMapOfShape aMEAvoid;
2940 TopTools_DataMapOfShapeListOfShape aDMVF;
2941 Standard_Integer aNb = theFImages.Extent(), i;
2942 for (i = 1; i <= aNb; ++i) {
2943 const TopTools_ListOfShape& aLFIm = theFImages(i);
2945 TopoDS_Compound aCFIm;
2946 aBB.MakeCompound(aCFIm);
2948 TopTools_DataMapOfShapeListOfShape aDMEF;
2949 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
2950 for (; aIt.More(); aIt.Next()) {
2951 const TopoDS_Shape& aF = aIt.Value();
2954 // make a map to use only outer edges
2955 TopExp_Explorer aExp(aF, TopAbs_EDGE);
2956 for (; aExp.More(); aExp.Next()) {
2957 const TopoDS_Shape& aE = aExp.Current();
2959 TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE);
2961 pLF = aDMEF.Bound(aE, TopTools_ListOfShape());
2964 // internal edges should not be used
2967 AppendToList(*pLF, aF);
2970 // fill connection map of the vertices of inverted edges to faces
2971 aExp.Init(aF, TopAbs_VERTEX);
2972 for (; aExp.More(); aExp.Next()) {
2973 const TopoDS_Shape& aV = aExp.Current();
2975 TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV);
2977 pLF = aDMVF.Bound(aV, TopTools_ListOfShape());
2979 AppendToList(*pLF, aF);
2983 // for the splits to be regular they should form only one block
2984 TopTools_ListOfShape aLCBF;
2985 BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
2986 if (aLCBF.Extent() == 1) {
2990 // check if the inverted edges create the irregularity
2991 BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll;
2993 TopTools_ListIteratorOfListOfShape aItLCB(aLCBF);
2994 for (; aItLCB.More(); aItLCB.Next()) {
2995 const TopoDS_Shape& aCB = aItLCB.Value();
2997 // check if it is possible to remove the block
2998 if (!CheckInvertedBlock(aCB, aLCBF, theMEInverted, theOEOrigins, aDMCBVInverted, aDMCBVAll)) {
2999 // non of the edges in this block should be removed
3000 TopExp::MapShapes(aCB, TopAbs_EDGE, aMEAvoid);
3006 // all edges not included in aMEAvoid can be removed
3007 TopTools_MapOfShape aMERem;
3008 TopTools_MapIteratorOfMapOfShape aItM(theMEInverted);
3009 for (; aItM.More(); aItM.Next()) {
3010 const TopoDS_Shape& aE = aItM.Value();
3011 if (!aMEAvoid.Contains(aE)) {
3012 TopoDS_Iterator aIt(aE);
3013 for (; aIt.More(); aIt.Next()) {
3014 const TopoDS_Shape& aV = aIt.Value();
3015 const TopTools_ListOfShape *pLF = aDMVF.Seek(aV);
3016 if (pLF && (pLF->Extent() > 3)) {
3024 if (aMERem.IsEmpty()) {
3028 // all invalid faces containing these edges can be removed
3029 TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
3030 TopTools_MapOfShape aMFRem;
3031 TopTools_IndexedMapOfShape aMFToUpdate;
3032 aNb = theInvFaces.Extent();
3033 for (i = 1; i <= aNb; ++i) {
3034 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3035 TopTools_ListOfShape& aLFIm = theInvFaces(i);
3037 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3038 for (; aIt.More(); ) {
3039 const TopoDS_Shape& aFIm = aIt.Value();
3041 // to be removed the face should have at least two not connected
3043 TopoDS_Compound aCEInv;
3044 aBB.MakeCompound(aCEInv);
3045 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
3046 for (; aExp.More(); aExp.Next()) {
3047 const TopoDS_Shape& aE = aExp.Current();
3048 if (aMERem.Contains(aE)) {
3049 aBB.Add(aCEInv, aE);
3053 // check connectivity
3054 TopTools_ListOfShape aLCBE;
3055 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
3057 if (aLCBE.Extent() >= 2) {
3058 aMFToUpdate.Add(aF);
3067 if (aLFIm.Extent()) {
3068 aInvFaces.Add(aF, aLFIm);
3072 if (aMFRem.IsEmpty()) {
3076 theInvFaces = aInvFaces;
3077 // remove from splits
3078 aNb = aMFToUpdate.Extent();
3079 for (i = 1; i <= aNb; ++i) {
3080 const TopoDS_Shape& aF = aMFToUpdate(i);
3081 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
3083 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3084 for (; aIt.More(); ) {
3085 const TopoDS_Shape& aFIm = aIt.Value();
3086 if (aMFRem.Contains(aFIm)) {
3087 TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved);
3097 //=======================================================================
3098 //function : RemoveInvalidSplitsFromValid
3099 //purpose : Removing invalid splits of faces from valid
3100 //=======================================================================
3101 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3102 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3103 const TopTools_MapOfShape& theMEInverted,
3104 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
3105 TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
3107 // Decide whether to remove the found invalid faces or not.
3108 // The procedure is the following:
3109 // 1. Make connexity blocks from invalid faces;
3110 // 2. Find free edges in this blocks;
3111 // 3. If all free edges are valid for the faces - remove block.
3113 TopTools_MapOfShape aMFence, aMFToRem;
3114 TopoDS_Compound aCFInv;
3116 aBB.MakeCompound(aCFInv);
3117 TopTools_ListIteratorOfListOfShape aItLF;
3119 // make compound of invalid faces
3120 TopTools_DataMapOfShapeShape aDMIFOF;
3121 Standard_Integer i, aNb = theInvFaces.Extent();
3122 for (i = 1; i <= aNb; ++i) {
3123 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3124 // artificially invalid faces should not be removed
3125 if (theArtInvFaces.IsBound(aF)) {
3128 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
3129 aItLF.Initialize(aLFInv);
3130 for (; aItLF.More(); aItLF.Next()) {
3131 const TopoDS_Shape& aFIm = aItLF.Value();
3132 if (aMFence.Add(aFIm)) {
3133 aBB.Add(aCFInv, aFIm);
3134 aDMIFOF.Bind(aFIm, aF);
3139 // make connexity blocks
3140 TopTools_ListOfShape aLCBInv;
3141 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
3143 // analyze each block
3144 aItLF.Initialize(aLCBInv);
3145 for (; aItLF.More(); aItLF.Next()) {
3146 const TopoDS_Shape& aCB = aItLF.Value();
3148 // if connexity block contains only one face - it should be removed;
3149 TopExp_Explorer aExp(aCB, TopAbs_FACE);
3152 // check if there are valid images left
3153 aExp.Init(aCB, TopAbs_FACE);
3154 for (; aExp.More(); aExp.Next()) {
3155 const TopoDS_Shape& aFIm = aExp.Current();
3156 const TopoDS_Shape& aF = aDMIFOF.Find(aFIm);
3158 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
3159 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
3161 if (aLFIm.Extent() == aLFInv.Extent()) {
3168 aExp.Init(aCB, TopAbs_FACE);
3169 for (; aExp.More(); aExp.Next()) {
3170 const TopoDS_Shape& aF = aExp.Current();
3176 // remove faces connected by inverted edges
3177 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3178 TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3180 TopTools_DataMapOfShapeListOfShape aDMFF;
3181 aExp.Init(aCB, TopAbs_FACE);
3182 for (; aExp.More(); aExp.Next()) {
3183 const TopoDS_Shape& aFCB = aExp.Current();
3184 const TopoDS_Shape& aF = aDMIFOF.Find (aFCB);
3185 TopTools_ListOfShape* pList = aDMFF.ChangeSeek (aF);
3187 pList = aDMFF.Bound (aF, TopTools_ListOfShape());
3188 pList->Append (aFCB);
3191 for (TopTools_DataMapOfShapeListOfShape::Iterator itM (aDMFF); itM.More(); itM.Next())
3193 const TopoDS_Shape& aF = itM.Key();
3194 const TopTools_MapOfShape* pValidInverted = theDMFMVIE.Seek (aF);
3196 // either remove all of these faces or none.
3197 const TopTools_ListOfShape& aLFCB = itM.Value();
3198 TopTools_ListOfShape::Iterator itL (aLFCB);
3199 for (; itL.More(); itL.Next())
3201 const TopoDS_Shape& aFCB = itL.Value();
3202 TopExp_Explorer aExpE(aFCB, TopAbs_EDGE);
3203 for (; aExpE.More(); aExpE.Next()) {
3204 const TopoDS_Shape& aECB = aExpE.Current();
3205 if (pValidInverted && pValidInverted->Contains (aECB))
3207 if (aDMEF.FindFromKey(aECB).Extent() > 1)
3209 if (!theMEInverted.Contains(aECB))
3214 // if one removed - remove all
3219 for (itL.Initialize (aLFCB); itL.More(); itL.Next())
3221 aMFToRem.Add (itL.Value());
3227 if (aMFToRem.Extent()) {
3228 // remove invalid faces from images
3229 aNb = theInvFaces.Extent();
3230 for (i = 1; i <= aNb; ++i) {
3231 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3232 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
3233 aItLF.Initialize(aLFImages);
3234 for (; aItLF.More();) {
3235 const TopoDS_Shape& aFIm = aItLF.Value();
3236 if (aMFToRem.Contains(aFIm)) {
3237 aLFImages.Remove(aItLF);
3247 //=======================================================================
3248 //function : RemoveInsideFaces
3249 //purpose : Looking for the inside faces that can be safely removed
3250 //=======================================================================
3251 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3252 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3253 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3254 const TopTools_IndexedMapOfShape& theInvEdges,
3255 const TopTools_MapOfShape& theInvertedEdges,
3256 const TopTools_ListOfShape& theInvertedFaces,
3257 const TopTools_IndexedMapOfShape& theMFToCheckInt,
3258 const TopTools_IndexedMapOfShape& theMFInvInHole,
3259 const TopoDS_Shape& theFHoles,
3260 TopTools_DataMapOfShapeListOfShape& theSSInterfs,
3261 TopTools_IndexedMapOfShape& theMERemoved,
3262 TopTools_IndexedMapOfShape& theMEInside,
3263 TopoDS_Shape& theSolids)
3265 TopTools_ListOfShape aLS;
3266 TopTools_MapOfShape aMFence;
3267 TopTools_IndexedMapOfShape aMFInv;
3268 TopTools_ListIteratorOfListOfShape aItLF;
3269 TopTools_DataMapOfShapeShape aDMFImF;
3271 Standard_Integer i, aNb = theFImages.Extent();
3272 for (i = 1; i <= aNb; ++i) {
3273 const TopoDS_Shape& aF = theFImages.FindKey(i);
3274 // to avoid intersection of the splits of the same
3275 // offset faces among themselves make compound of the
3276 // splits and use it as one argument
3277 TopoDS_Compound aCFImi;
3278 BRep_Builder().MakeCompound(aCFImi);
3280 for (Standard_Integer j = 0; j < 2; ++j) {
3281 const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i);
3286 aItLF.Initialize(*pLFSp);
3287 for (; aItLF.More(); aItLF.Next()) {
3288 const TopoDS_Shape& aFIm = aItLF.Value();
3289 if (aMFence.Add(aFIm)) {
3290 BRep_Builder().Add(aCFImi, aFIm);
3291 aDMFImF.Bind(aFIm, aF);
3302 // to make the solids more complete add for intersection also the faces
3303 // consisting only of invalid edges and not included into splits
3304 aNb = theMFToCheckInt.Extent();
3305 for (i = 1; i <= aNb; ++i) {
3306 const TopoDS_Shape& aFSp = theMFToCheckInt(i);
3307 if (aMFence.Add(aFSp)) {
3312 BOPAlgo_MakerVolume aMV;
3313 aMV.SetArguments(aLS);
3314 aMV.SetIntersect(Standard_True);
3316 if (aMV.HasErrors())
3320 // get shapes connection for using in the rebuilding process
3321 // for the cases in which some of the intersection left undetected
3322 ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theSSInterfs);
3324 // find faces to remove
3325 const TopoDS_Shape& aSols = aMV.Shape();
3327 TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
3328 TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
3330 aNb = aDMFS.Extent();
3335 // To use the created solids for classifications, firstly, it is necessary
3336 // to check them on validity - the created solids should be complete,
3337 // i.e. all faces should be included.
3339 TopTools_MapOfShape aMFToRem;
3340 // Check completeness
3341 if (aMV.HasDeleted()) {
3342 TopTools_IndexedMapOfShape aMEHoles;
3343 TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles);
3345 // Map edges of the solids to check the connectivity
3346 // of the removed invalid splits
3347 TopTools_IndexedMapOfShape aMESols;
3348 TopExp::MapShapes(aSols, TopAbs_EDGE, aMESols);
3350 // perform additional check on faces
3351 aNb = theFImages.Extent();
3352 for (i = 1; i <= aNb; ++i) {
3353 const TopTools_ListOfShape& aLFIm = theFImages(i);
3354 if (aLFIm.IsEmpty()) {
3358 const TopoDS_Shape& aF = theFImages.FindKey(i);
3359 Standard_Boolean bInvalid = theInvFaces.Contains(aF);
3360 // For invalid faces it is allowed to be at least connected
3361 // to the solids, otherwise the solids are considered as broken
3362 Standard_Boolean bConnected = Standard_False;
3364 Standard_Boolean bFaceKept = Standard_False;
3365 aItLF.Initialize(aLFIm);
3366 for (; aItLF.More(); aItLF.Next()) {
3367 const TopoDS_Shape& aFIm = aItLF.Value();
3368 if (!aMV.IsDeleted(aFIm)) {
3369 bFaceKept = Standard_True;
3373 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
3374 for (; aExpE.More(); aExpE.Next()) {
3375 if (aMEHoles.Contains(aExpE.Current())) {
3376 bFaceKept = Standard_True;
3380 if (!bFaceKept && bInvalid && !bConnected)
3381 bConnected = aMESols.Contains(aExpE.Current());
3385 if (!bFaceKept && !bConnected) {
3391 TopTools_IndexedMapOfShape aMEBoundary;
3392 aNb = aDMFS.Extent();
3393 for (i = 1; i <= aNb; ++i) {
3394 const TopoDS_Shape& aFIm = aDMFS.FindKey(i);
3395 const TopTools_ListOfShape& aLSol = aDMFS(i);
3396 if (aLSol.Extent() > 1) {
3399 else if (aFIm.Orientation() != TopAbs_INTERNAL) {
3400 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary);
3404 // Tool for getting the splits of faces
3405 const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
3407 // update invalid faces with images
3408 aNb = aMFInv.Extent();
3409 for (i = 1; i <= aNb; ++i) {
3410 const TopoDS_Shape& aFInv = aMFInv(i);
3411 TakeModified(aFInv, aMVIms, aMFInv);
3414 // Take into account the faces invalid by inverted edges
3415 for (TopTools_ListOfShape::Iterator itLF(theInvertedFaces); itLF.More(); itLF.Next())
3416 TakeModified(itLF.Value(), aMVIms, aMFInv);
3418 // check if the invalid faces inside the holes are really invalid:
3419 // check its normal direction - if it has changed relatively the
3420 // original face the offset face is invalid and should be kept for rebuilding
3421 Standard_Integer aNbFH = theMFInvInHole.Extent();
3422 for (i = 1; i <= aNbFH; ++i) {
3423 const TopoDS_Shape& aFInv = theMFInvInHole(i);
3424 TopTools_ListOfShape aLFInvIm = aMV.Modified(aFInv);
3425 if (aLFInvIm.IsEmpty()) {
3426 aLFInvIm.Append(aFInv);
3429 const TopoDS_Shape *pFOffset = aDMFImF.Seek(aFInv);
3433 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInvIm);
3434 for (; aItLFInv.More(); aItLFInv.Next()) {
3435 const TopoDS_Shape& aFInvIm = aItLFInv.Value();
3436 const TopTools_ListOfShape* pLSols = aDMFS.Seek(aFInvIm);
3437 if (!pLSols || pLSols->Extent() != 1) {
3441 const TopoDS_Shape& aFSol = pLSols->First();
3444 if (!FindShape(aFInvIm, aFSol, NULL, aFx)) {
3448 if (BRepOffset_Tool::CheckPlanesNormals(TopoDS::Face(aFx), TopoDS::Face(*pFOffset))) {
3449 // the normal direction has not changed, thus the face can be removed
3450 aMFToRem.Add(aFInvIm);
3455 TopoDS_Compound aSolids;
3456 BRep_Builder().MakeCompound(aSolids);
3457 TopTools_MapOfShape aMFKeep;
3459 TopExp_Explorer aExpS(aSols, TopAbs_SOLID);
3460 for (; aExpS.More(); aExpS.Next()) {
3461 const TopoDS_Shape& aSol = aExpS.Current();
3463 Standard_Boolean bAllInv(Standard_True), bAllRemoved(Standard_True);
3465 for (TopExp_Explorer aExpF(aSol, TopAbs_FACE); aExpF.More(); aExpF.Next())
3467 const TopoDS_Shape& aFS = aExpF.Current();
3469 if (aFS.Orientation() == TopAbs_INTERNAL) {
3474 if (aMFToRem.Contains(aFS))
3477 bAllRemoved = false;
3478 bAllInv &= aMFInv.Contains(aFS);
3481 if (bAllInv && !bAllRemoved) {
3482 // remove invalid faces but keep those that have already been marked for removal
3483 TopExp_Explorer aExpF(aSol, TopAbs_FACE);
3484 for (; aExpF.More(); aExpF.Next()) {
3485 const TopoDS_Shape& aFS = aExpF.Current();
3487 if (aMFToRem.Contains(aFS)) {
3488 if (!aMFKeep.Add(aFS)) {
3489 aMFKeep.Remove(aFS);
3498 BRep_Builder().Add(aSolids, aSol);
3499 theSolids = aSolids;
3503 TopTools_MapIteratorOfMapOfShape aItM(aMFKeep);
3504 for (; aItM.More(); aItM.Next()) {
3505 aMFToRem.Remove(aItM.Value());
3508 // Remove the invalid hanging parts external to the solids
3509 RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, theInvertedEdges, aMFToRem);
3511 // Remove newly found internal and hanging faces
3512 RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
3513 RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
3515 // Get inside faces from the removed ones comparing them with boundary edges
3516 aNb = theMERemoved.Extent();
3517 for (i = 1; i <= aNb; ++i) {
3518 const TopoDS_Shape& aE = theMERemoved(i);
3519 if (!aMEBoundary.Contains(aE)) {
3520 theMEInside.Add(aE);
3525 //=======================================================================
3526 //function : ShapesConnections
3527 //purpose : Looking for the connections between faces not to miss
3528 // some necessary intersection
3529 //=======================================================================
3530 void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3531 const TopTools_IndexedMapOfShape& theInvEdges,
3532 const TopTools_DataMapOfShapeShape& theDMFOr,
3533 BOPAlgo_Builder& theBuilder,
3534 TopTools_DataMapOfShapeListOfShape& theSSInterfs)
3536 // update invalid edges with images and keep connection to original edge
3537 TopTools_DataMapOfShapeListOfShape aDMEOr;
3538 Standard_Integer aNb = theInvEdges.Extent();
3539 for (Standard_Integer i = 1; i <= aNb; ++i) {
3540 const TopoDS_Shape& aEInv = theInvEdges(i);
3541 const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv);
3542 if (aLEIm.IsEmpty()) {
3543 aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv);
3547 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
3548 for (; aItLEIm.More(); aItLEIm.Next()) {
3549 const TopoDS_Shape& aEIm = aItLEIm.Value();
3551 TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm);
3553 pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape());
3555 AppendToList(*pLEOr, aEInv);
3559 // get shapes connections for using in the rebuilding process
3560 const BOPDS_PDS& pDS = theBuilder.PDS();
3561 // analyze all Face/Face intersections
3562 const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
3563 Standard_Integer iInt, aNbFF = aFFs.Length();
3564 for (iInt = 0; iInt < aNbFF; ++iInt) {
3565 const BOPDS_InterfFF& aFF = aFFs(iInt);
3566 const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
3567 Standard_Integer aNbC = aVNC.Length();
3572 const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1());
3573 const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2());
3575 const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1);
3576 const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2);
3582 if (pF1->IsSame(*pF2)) {
3586 Standard_Boolean bInv1 = theInvFaces.Contains(*pF1);
3587 Standard_Boolean bInv2 = theInvFaces.Contains(*pF2);
3589 if (!bInv1 && !bInv2) {
3593 // check if it is real Face/Face intersection
3594 TopTools_MapOfShape aMEInt;
3595 for (Standard_Integer iC = 0; iC < aNbC; ++iC) {
3596 const BOPDS_Curve& aNC = aVNC(iC);
3597 const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
3598 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
3599 for (; aItLPB.More(); aItLPB.Next()) {
3600 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
3601 Standard_Integer nEInt;
3602 if (aPB->HasEdge(nEInt)) {
3603 const TopoDS_Shape& aEInt = pDS->Shape(nEInt);
3609 if (aMEInt.IsEmpty()) {
3613 // check if invalid edges of the face are in the same splits with intersection edges
3614 for (Standard_Integer i = 0; i < 2; ++i) {
3615 if ((!i && !bInv1) || (i && !bInv2)) {
3619 const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
3620 const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
3621 const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
3623 Standard_Boolean bFound = Standard_False;
3625 TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm);
3626 if (aLFIm.IsEmpty()) {
3630 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
3631 for (; aItLFIm.More(); aItLFIm.Next()) {
3632 const TopoDS_Shape& aFImIm = aItLFIm.Value();
3634 Standard_Boolean bInv(Standard_False), bInt(Standard_False);
3635 TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE);
3636 for (; aExpE.More(); aExpE.Next()) {
3637 const TopoDS_Shape& aE = aExpE.Current();
3639 bInv = aDMEOr.IsBound(aE);
3642 bInt = aMEInt.Contains(aE);
3649 if (!bInt || !bInv) {
3653 bFound = Standard_True;
3655 // append opposite face to all invalid edges in the split
3656 aExpE.Init(aFImIm, TopAbs_EDGE);
3657 for (; aExpE.More(); aExpE.Next()) {
3658 const TopoDS_Shape& aE = aExpE.Current();
3659 const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE);
3664 TopTools_ListIteratorOfListOfShape aItLE(*pLEOr);
3665 for (; aItLE.More(); aItLE.Next()) {
3666 const TopoDS_Shape& aEOr = aItLE.Value();
3667 TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr);
3669 pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape());
3671 AppendToList(*pLFE, aFOp);
3676 // save connection between offset faces
3677 TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF);
3679 pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape());
3681 AppendToList(*pLF, aFOp);
3687 //=======================================================================
3688 //function : RemoveHangingParts
3689 //purpose : Remove isolated invalid hanging parts
3690 //=======================================================================
3691 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
3692 const TopTools_DataMapOfShapeShape& theDMFImF,
3693 const TopTools_IndexedMapOfShape& theMFInv,
3694 const TopTools_IndexedMapOfShape& theInvEdges,
3695 const TopTools_MapOfShape& theInvertedEdges,
3696 TopTools_MapOfShape& theMFToRem)
3698 // Map the faces of the result solids to filter them from avoided faces
3699 TopTools_IndexedMapOfShape aMFS;
3700 TopExp::MapShapes(theMV.Shape(), TopAbs_FACE, aMFS);
3703 // Build compound of all faces not included into solids
3704 TopoDS_Compound aCFHangs;
3705 aBB.MakeCompound(aCFHangs);
3707 // Tool for getting the splits of faces
3708 const TopTools_DataMapOfShapeListOfShape& aMVIms = theMV.Images();
3710 TopTools_ListIteratorOfListOfShape aItLArgs(theMV.Arguments());
3711 for (; aItLArgs.More(); aItLArgs.Next())
3713 TopExp_Explorer anExpF(aItLArgs.Value(), TopAbs_FACE);
3714 for (; anExpF.More(); anExpF.Next())
3716 const TopoDS_Shape& aF = anExpF.Current();
3717 TakeModified(aF, aMVIms, aCFHangs, &aMFS);
3721 // Make connexity blocks of all hanging parts and check that they are isolated
3722 TopTools_ListOfShape aLCBHangs;
3723 BOPTools_AlgoTools::MakeConnexityBlocks(aCFHangs, TopAbs_EDGE, TopAbs_FACE, aLCBHangs);
3724 if (aLCBHangs.IsEmpty())
3727 // To be removed, the block should contain invalid splits of offset faces and should
3728 // meet one of the following conditions:
3729 // 1. The block should not be connected to any invalid parts (Faces or Edges)
3730 // contained in solids;
3731 // 2. The block should be isolated from other faces, i.e. it should consist of
3732 // the splits of the single offset face.
3734 // Map the edges and vertices of the result solids to check connectivity
3735 // of the hanging blocks to invalid parts contained in solids
3736 TopTools_IndexedDataMapOfShapeListOfShape aDMEF, aDMVE;
3737 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_EDGE , TopAbs_FACE, aDMEF);
3738 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
3740 // Update invalid edges with intersection results
3741 TopTools_MapOfShape aMEInv;
3742 Standard_Integer i, aNbE = theInvEdges.Extent();
3743 for (i = 1; i <= aNbE; ++i)
3744 TakeModified(theInvEdges(i), aMVIms, aMEInv);
3746 // Update inverted edges with intersection results
3747 TopTools_MapOfShape aMEInverted;
3748 for (TopTools_MapIteratorOfMapOfShape itM(theInvertedEdges); itM.More(); itM.Next())
3749 TakeModified(itM.Value(), aMVIms, aMEInverted);
3751 // Tool for getting the origins of the splits
3752 const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
3754 // Find hanging blocks to remove
3755 TopTools_ListOfShape aBlocksToRemove;
3757 TopTools_ListIteratorOfListOfShape aItLCBH(aLCBHangs);
3758 for (; aItLCBH.More(); aItLCBH.Next())
3760 const TopoDS_Shape& aCBH = aItLCBH.Value();
3762 // Remove the block containing the inverted edges
3763 Standard_Boolean bHasInverted = Standard_False;
3764 TopExp_Explorer anExpE(aCBH, TopAbs_EDGE);
3765 for (; anExpE.More() && !bHasInverted; anExpE.Next())
3767 const TopoDS_Shape& aE = anExpE.Current();
3768 bHasInverted = !aDMEF .Contains(aE) &&
3769 aMEInverted.Contains(aE);
3774 aBlocksToRemove.Append(aCBH);
3778 // Check the block to contain invalid split
3779 Standard_Boolean bHasInvalidFace = Standard_False;
3780 // Check connectivity to invalid parts
3781 Standard_Boolean bIsConnected = Standard_False;
3782 TopTools_IndexedMapOfShape aBlockME;
3783 TopExp::MapShapes(aCBH, TopAbs_EDGE, aBlockME);
3784 // Map to collect all original faces
3785 TopTools_MapOfShape aMOffsetF;
3787 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
3788 for (; anExpF.More(); anExpF.Next())
3790 const TopoDS_Shape& aF = anExpF.Current();
3791 // Check block to contain invalid face
3792 if (!bHasInvalidFace)
3793 bHasInvalidFace = theMFInv.Contains(aF);
3795 // Check block for connectivity to invalid parts
3799 anExpE.Init(aF, TopAbs_EDGE);
3800 for (; anExpE.More() && !bIsConnected; anExpE.Next())
3802 const TopoDS_Shape& aE = anExpE.Current();
3803 const TopTools_ListOfShape *pLF = aDMEF.Seek(aE);
3806 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
3807 for (; aItLF.More() && !bIsConnected; aItLF.Next())
3808 bIsConnected = theMFInv.Contains(aItLF.Value());
3814 TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
3815 for (; anExpV.More() && !bIsConnected; anExpV.Next())
3817 const TopoDS_Shape& aV = anExpV.Current();
3818 const TopTools_ListOfShape *pLE = aDMVE.Seek(aV);
3821 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
3822 for (; aItLE.More() && !bIsConnected; aItLE.Next())
3823 bIsConnected = !aBlockME.Contains(aItLE.Value()) &&
3824 aMEInv .Contains(aItLE.Value());
3830 // Check block to be isolated
3831 const TopTools_ListOfShape* pLFOr = aMVOrs.Seek(aF);
3834 TopTools_ListIteratorOfListOfShape aItLFOr(*pLFOr);
3835 for (; aItLFOr.More(); aItLFOr.Next())
3837 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aItLFOr.Value());
3839 aMOffsetF.Add(*pFOffset);
3844 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aF);
3846 aMOffsetF.Add(*pFOffset);
3850 Standard_Boolean bRemove = bHasInvalidFace &&
3851 (!bIsConnected || aMOffsetF.Extent() == 1);
3854 aBlocksToRemove.Append(aCBH);
3857 // remove the invalidated blocks
3858 aItLCBH.Initialize(aBlocksToRemove);
3859 for (; aItLCBH.More(); aItLCBH.Next())
3861 const TopoDS_Shape& aCBH = aItLCBH.Value();
3862 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
3863 for (; anExpF.More(); anExpF.Next())
3864 theMFToRem.Add(anExpF.Current());
3868 //=======================================================================
3869 //function : RemoveValidSplits
3870 //purpose : Removing valid splits according to results of intersection
3871 //=======================================================================
3872 void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
3873 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
3874 BOPAlgo_Builder& theGF,
3875 TopTools_IndexedMapOfShape& theMERemoved)
3877 Standard_Integer i, aNb = theImages.Extent();
3882 for (i = 1; i <= aNb; ++i) {
3883 TopTools_ListOfShape& aLSIm = theImages(i);
3884 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
3885 for (; aIt.More(); ) {
3886 const TopoDS_Shape& aSIm = aIt.Value();
3887 if (theSpRem.Contains(aSIm)) {
3888 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
3893 // check if all its images are have to be removed
3894 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
3895 if (aLSImIm.Extent()) {
3896 Standard_Boolean bAllRem = Standard_True;
3897 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
3898 for (; aIt1.More(); aIt1.Next()) {
3899 const TopoDS_Shape& aSImIm = aIt1.Value();
3900 if (theSpRem.Contains(aSImIm)) {
3901 TopExp::MapShapes(aSImIm, TopAbs_EDGE, theMERemoved);
3904 bAllRem = Standard_False;
3909 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
3919 //=======================================================================
3920 //function : RemoveInvalidSplits
3921 //purpose : Removing invalid splits according to the results of intersection
3922 //=======================================================================
3923 void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
3924 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3925 const TopTools_IndexedMapOfShape& theInvEdges,
3926 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
3927 BOPAlgo_Builder& theGF,
3928 TopTools_IndexedMapOfShape& theMERemoved)
3930 Standard_Integer i, aNb = theImages.Extent();
3935 for (i = 1; i <= aNb; ++i) {
3936 const TopoDS_Shape& aS = theImages.FindKey(i);
3937 Standard_Boolean bArt = theArtInvFaces.IsBound(aS);
3939 TopTools_ListOfShape& aLSIm = theImages(i);
3940 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
3941 for (; aIt.More();) {
3942 const TopoDS_Shape& aSIm = aIt.Value();
3943 if (theSpRem.Contains(aSIm)) {
3944 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
3949 // check if all its images are have to be removed
3950 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
3951 if (aLSImIm.IsEmpty()) {
3956 Standard_Boolean bAllRem = Standard_True;
3957 TopTools_IndexedMapOfShape aMERemoved;
3958 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
3959 for (; aIt1.More(); aIt1.Next()) {
3960 const TopoDS_Shape& aSImIm = aIt1.Value();
3961 if (theSpRem.Contains(aSImIm)) {
3962 TopExp::MapShapes(aSImIm, TopAbs_EDGE, aMERemoved);
3965 bAllRem = Standard_False;
3979 // remove the face from invalid if all invalid edges of this face
3980 // have been marked for removal
3981 TopExp_Explorer aExpE(aSIm, TopAbs_EDGE);
3982 for (; aExpE.More(); aExpE.Next()) {
3983 const TopoDS_Shape& aEInv = aExpE.Current();
3984 if (theInvEdges.Contains(aEInv) && !aMERemoved.Contains(aEInv)) {
3988 if (!aExpE.More()) {
3989 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
3999 //=======================================================================
4000 //function : FilterEdgesImages
4001 //purpose : Updating the maps of images and origins of the offset edges
4002 //=======================================================================
4003 void FilterEdgesImages(const TopoDS_Shape& theS,
4004 TopTools_DataMapOfShapeListOfShape& theOEImages,
4005 TopTools_DataMapOfShapeListOfShape& theOEOrigins)
4008 TopTools_IndexedMapOfShape aME;
4009 TopExp::MapShapes(theS, TopAbs_EDGE, aME);
4011 theOEOrigins.Clear();
4012 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(theOEImages);
4013 for (; aItDM.More(); aItDM.Next()) {
4014 const TopoDS_Shape& aE = aItDM.Key();
4015 TopTools_ListOfShape& aLEIm = aItDM.ChangeValue();
4017 TopTools_ListIteratorOfListOfShape aIt(aLEIm);
4018 for (; aIt.More(); ) {
4019 const TopoDS_Shape& aEIm = aIt.Value();
4021 if (!aME.Contains(aEIm)) {
4023 // edges with no images left should be kept in the map
4024 // to avoid their usage when building the splits of faces
4030 if (theOEOrigins.IsBound(aEIm)) {
4031 AppendToList(theOEOrigins.ChangeFind(aEIm), aE);
4034 TopTools_ListOfShape aLOr;
4036 theOEOrigins.Bind(aEIm, aLOr);
4044 //=======================================================================
4045 //function : FilterInvalidFaces
4046 //purpose : Filtering of the invalid faces
4047 //=======================================================================
4048 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4049 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
4050 const TopTools_IndexedMapOfShape& theInvEdges,
4051 const TopTools_IndexedMapOfShape& theMERemoved,
4052 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4053 TopTools_DataMapOfShapeShape& theArtInvFaces)
4056 // filter invalid faces, considering faces having only valid
4057 // images left with non-free edges as valid
4058 // do not remove invalid faces if it creates free edges
4060 TopTools_IndexedDataMapOfShapeListOfShape aReallyInvFaces;
4061 // Edge-Face connexity map of all splits, both invalid and valid
4062 TopTools_IndexedDataMapOfShapeListOfShape aDMEFAll;
4063 TopTools_ListIteratorOfListOfShape aItLF;
4065 const Standard_Integer aNb = theInvFaces.Extent();
4066 for (Standard_Integer i = 1; i <= aNb; ++i) {
4067 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4068 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4070 if (theArtInvFaces.IsBound(aF)) {
4071 if (aLFInv.IsEmpty()) {
4072 theArtInvFaces.UnBind(aF);
4075 aReallyInvFaces.Add(aF, aLFInv);
4080 if (aLFInv.IsEmpty()) {
4084 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
4085 Standard_Boolean bInvalid = aLFIm.IsEmpty();
4088 // check two lists on common splits
4089 aItLF.Initialize(aLFInv);
4090 for (; aItLF.More(); aItLF.Next()) {
4091 const TopoDS_Shape& aFInv = aItLF.Value();
4093 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4094 for (; aItLFIm.More(); aItLFIm.Next()) {
4095 const TopoDS_Shape& aFIm = aItLFIm.Value();
4097 if (aFInv.IsSame(aFIm)) {
4102 if (aItLFIm.More()) {
4107 bInvalid = aItLF.More();
4111 // check for free edges
4112 for (Standard_Integer j = 0; !bInvalid && j < 2; ++j) {
4113 const TopTools_ListOfShape& aLI = !j ? aLFIm : aLFInv;
4114 aItLF.Initialize(aLI);
4115 for (; aItLF.More(); aItLF.Next()) {
4116 const TopoDS_Shape& aFIm = aItLF.Value();
4118 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4119 for (; aExp.More(); aExp.Next()) {
4120 const TopoDS_Shape& aE = aExp.Current();
4121 if (!theMERemoved.Contains(aE)) {
4122 const TopTools_ListOfShape* pLEF = theDMEF.Seek(aE);
4123 if (pLEF && pLEF->Extent() == 1) {
4133 bInvalid = aItLF.More();
4138 if (aDMEFAll.IsEmpty())
4141 for (Standard_Integer iF = 1; iF <= aNb; ++iF)
4142 for (TopTools_ListOfShape::Iterator itLFInv (theInvFaces(iF)); itLFInv.More(); itLFInv.Next())
4143 TopExp::MapShapesAndAncestors (itLFInv.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFAll);
4146 TopTools_MapOfShape aLocalSplits;
4147 for (Standard_Integer j = 0; j < 2; ++j)
4148 for (aItLF.Initialize((!j ? aLFIm : aLFInv)); aItLF.More(); aItLF.Next())
4149 aLocalSplits.Add (aItLF.Value());
4151 // Check if all invalid edges are located inside the split and do not touch
4152 // any other faces both invalid and valid
4153 aItLF.Initialize(aLFInv);
4154 for (; aItLF.More(); aItLF.Next())
4156 const TopoDS_Shape& aFIm = aItLF.Value();
4157 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4158 for (; aExp.More(); aExp.Next())
4160 const TopoDS_Shape& aE = aExp.Current();
4161 if (theInvEdges.Contains (aE) && !theMERemoved.Contains (aE))
4163 const TopTools_ListOfShape& aLF = aDMEFAll.FindFromKey (aE);
4164 TopTools_ListOfShape::Iterator itLF (aLF);
4165 for (; itLF.More(); itLF.Next())
4167 if (!aLocalSplits.Contains (itLF.Value()))
4177 bInvalid = aItLF.More();
4180 aItLF.Initialize(aLFInv);
4181 for (; aItLF.More(); aItLF.Next())
4182 AppendToList (aLFIm, aItLF.Value());
4187 aReallyInvFaces.Add(aF, aLFInv);
4191 theInvFaces = aReallyInvFaces;
4194 //=======================================================================
4195 //function : CheckEdgesCreatedByVertex
4196 //purpose : Checks additionally the unchecked edges originated from vertices
4197 //=======================================================================
4198 void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4199 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4200 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4201 const TopTools_IndexedMapOfShape& theValidEdges,
4202 TopTools_IndexedMapOfShape& theInvEdges)
4204 // Mark the unchecked edges contained in invalid faces as invalid
4205 const Standard_Integer aNbF = theInvFaces.Extent();
4206 for (Standard_Integer i = 1; i <= aNbF; ++i)
4208 const TopoDS_Shape& aF = theInvFaces.FindKey (i);
4209 if (theArtInvFaces.IsBound (aF))
4212 const TopTools_ListOfShape& aLFIm = theInvFaces (i);
4213 for (TopTools_ListOfShape::Iterator it (aLFIm); it.More(); it.Next())
4215 const TopoDS_Shape& aFIm = it.Value();
4216 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
4218 const TopoDS_Shape& aE = expE.Current();
4219 if (theInvEdges.Contains (aE)
4220 || theValidEdges.Contains (aE))
4225 // check if this edges is created by vertex
4226 const TopTools_ListOfShape* pLEOr = theEdgesOrigins.Seek (aE);
4229 TopTools_ListOfShape::Iterator itLEO (*pLEOr);
4230 for (; itLEO.More(); itLEO.Next())
4232 if (itLEO.Value().ShapeType() != TopAbs_VERTEX)
4237 theInvEdges.Add (aE);
4244 //=======================================================================
4245 //function : FilterInvalidEdges
4246 //purpose : Filtering the invalid edges according to currently invalid faces
4247 //=======================================================================
4248 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4249 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4250 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
4251 const TopTools_IndexedMapOfShape& theMERemoved,
4252 TopTools_IndexedMapOfShape& theInvEdges)
4254 TopoDS_Compound aCEInv;
4255 TopTools_IndexedMapOfShape aMEInv;
4257 aBB.MakeCompound(aCEInv);
4258 TopTools_ListIteratorOfListOfShape aItLF;
4260 Standard_Integer i, aNb = theInvFaces.Extent();
4261 for (i = 1; i <= aNb; ++i) {
4262 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4263 aItLF.Initialize(aLFInv);
4264 for (; aItLF.More(); aItLF.Next()) {
4265 const TopoDS_Shape& aFIm = aItLF.Value();
4266 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEInv);
4268 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4269 for (; aExpE.More(); aExpE.Next()) {
4270 const TopoDS_Shape& aE = aExpE.Current();
4271 if (theInvEdges.Contains(aE)) {
4272 aBB.Add(aCEInv, aE);
4278 // remove edges which have been marked for removal
4279 TopTools_IndexedMapOfShape aMEInvToAvoid;
4280 TopTools_ListOfShape aLCBE;
4281 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4283 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
4284 for (; aItLCBE.More(); aItLCBE.Next()) {
4285 const TopoDS_Shape& aCBE = aItLCBE.Value();
4286 TopExp_Explorer aExpCB(aCBE, TopAbs_EDGE);
4287 for (; aExpCB.More(); aExpCB.Next()) {
4288 const TopoDS_Shape& aE = aExpCB.Current();
4289 if (!theMERemoved.Contains(aE)) {
4294 if (!aExpCB.More()) {
4295 TopExp::MapShapes(aCBE, TopAbs_EDGE, aMEInvToAvoid);
4299 TopTools_IndexedMapOfShape aReallyInvEdges;
4301 aNb = theInvFaces.Extent();
4302 for (i = 1; i <= aNb; ++i) {
4303 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4304 if (theArtInvFaces.IsBound(aF)) {
4305 const TopTools_IndexedMapOfShape& aMIE = theDMFMIE.Find(aF);
4306 const Standard_Integer aNbIE = aMIE.Extent();
4307 for (Standard_Integer iE = 1; iE <= aNbIE; ++iE)
4309 const TopoDS_Shape& aE = aMIE (iE);
4310 if (aMEInv.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4311 aReallyInvEdges.Add(aE);
4316 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4317 aItLF.Initialize(aLFInv);
4318 for (; aItLF.More(); aItLF.Next()) {
4319 const TopoDS_Shape& aFIm = aItLF.Value();
4320 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4321 for (; aExpE.More(); aExpE.Next()) {
4322 const TopoDS_Shape& aE = aExpE.Current();
4323 if (theInvEdges.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4324 aReallyInvEdges.Add(aE);
4331 theInvEdges = aReallyInvEdges;
4334 //=======================================================================
4335 //function : FindFacesToRebuild
4336 //purpose : Looking for the faces that have to be rebuilt:
4337 // 1. Faces close to invalidity
4338 // 2. Faces containing some invalid parts
4339 //=======================================================================
4340 void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
4341 const TopTools_IndexedMapOfShape& theInvEdges,
4342 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4343 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4344 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4345 TopTools_MapOfShape& theFSelfRebAvoid)
4347 Standard_Integer i, aNb = theLFImages.Extent();
4352 Standard_Boolean bRebuild;
4353 TopTools_ListIteratorOfListOfShape aItLF;
4354 TopTools_ListOfShape aLEValid;
4355 TopTools_MapOfShape aMFence, aMEReb, aMFReb;
4356 TopExp_Explorer aExp;
4358 TopTools_DataMapOfShapeListOfShape aDMFLV;
4359 // get edges from invalid faces
4360 aNb = theInvFaces.Extent();
4361 for (i = 1; i <= aNb; i++) {
4362 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4364 TopTools_ListOfShape aLVAvoid;
4365 const TopTools_ListOfShape& aLFIm = theInvFaces(i);
4366 aItLF.Initialize(aLFIm);
4367 for (; aItLF.More(); aItLF.Next()) {
4368 const TopoDS_Shape& aFIm = aItLF.Value();
4369 aExp.Init(aFIm, TopAbs_EDGE);
4370 for (; aExp.More(); aExp.Next()) {
4371 const TopoDS_Shape& aE = aExp.Current();
4373 if (theInvEdges.Contains(aE)) {
4374 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
4375 for (; aExpV.More(); aExpV.Next()) {
4376 const TopoDS_Shape& aV = aExpV.Current();
4377 if (aMFence.Add(aV)) {
4378 aLVAvoid.Append(aV);
4386 if (aLVAvoid.Extent()) {
4387 aDMFLV.Bind(aF, aLVAvoid);
4390 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aF);
4392 TopTools_ListIteratorOfListOfShape aItLFE(*pLF);
4393 for (; aItLFE.More(); aItLFE.Next()) {
4394 const TopoDS_Shape& aFE = aItLFE.Value();
4400 // get face to rebuild
4401 aNb = theLFImages.Extent();
4402 for (i = 1; i <= aNb; i++) {
4403 const TopoDS_Shape& aF = theLFImages.FindKey(i);
4404 const TopTools_ListOfShape& aLFIm = theLFImages(i);
4405 TopTools_MapOfShape aMVAvoid;
4406 if (aDMFLV.IsBound(aF)) {
4407 const TopTools_ListOfShape& aLVAvoid = aDMFLV.Find(aF);
4408 TopTools_ListIteratorOfListOfShape aItLV(aLVAvoid);
4409 for (; aItLV.More(); aItLV.Next()) {
4410 const TopoDS_Shape& aV = aItLV.Value();
4415 bRebuild = aMFReb.Contains(aF);
4419 aItLF.Initialize(aLFIm);
4420 for (; aItLF.More(); aItLF.Next()) {
4421 const TopoDS_Shape& aFIm = aItLF.Value();
4422 aExp.Init(aFIm, TopAbs_EDGE);
4423 for (; aExp.More(); aExp.Next()) {
4424 const TopoDS_Edge& anEIm = TopoDS::Edge(aExp.Current());
4425 if (!theInvEdges.Contains(anEIm)) {
4426 if (aMFence.Add(anEIm)) {
4427 aLEValid.Append(anEIm);
4432 bRebuild = aMEReb.Contains(anEIm);
4437 TopExp_Explorer aExpV(anEIm, TopAbs_VERTEX);
4438 for (; aExpV.More() && !bRebuild; aExpV.Next()) {
4439 const TopoDS_Shape& aV = aExpV.Current();
4440 if (!aMVAvoid.Contains(aV)) {
4441 bRebuild = aMEReb.Contains(aV);
4449 bRebuild = aLFIm.Extent() && theInvFaces.Contains(aF);
4451 theFSelfRebAvoid.Add(aF);
4456 theFToRebuild.Add(aF, aLEValid);
4461 //=======================================================================
4462 //function : RebuildFaces
4463 //purpose : Rebuilding of the faces
4464 //=======================================================================
4465 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4466 const TopTools_MapOfShape& theFSelfRebAvoid,
4467 const TopoDS_Shape& theSolids,
4468 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4469 const BRepOffset_Analyse* theAnalyse,
4470 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4471 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
4472 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4473 TopTools_DataMapOfShapeShape& theFacesOrigins,
4474 TopTools_DataMapOfShapeListOfShape& theOEImages,
4475 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4476 TopTools_MapOfShape& theLastInvEdges,
4477 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4478 TopTools_IndexedMapOfShape& theInvEdges,
4479 TopTools_IndexedMapOfShape& theValidEdges,
4480 const TopTools_MapOfShape& theInvertedEdges,
4481 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
4482 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4483 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4484 TopTools_MapOfShape& theVertsToAvoid,
4485 TopTools_DataMapOfShapeShape& theETrimEInf,
4486 Handle(BRepAlgo_AsDes)& theAsDes)
4488 TopTools_MapOfShape aModifiedEdges;
4490 // 1. Intersect faces
4491 IntersectFaces(theFToRebuild, theFSelfRebAvoid, theSolids, theSSInterfs, theFImages, theEdgesOrigins, theOEImages,
4492 theOEOrigins, theInvEdges, theValidEdges, theInvertedEdges, theEdgesToAvoid,
4493 theInvFaces, theArtInvFaces, theVertsToAvoid, theETrimEInf, aModifiedEdges, theAsDes);
4495 // 2. Repeat steps to build the correct faces
4496 BuildSplitsOfInvFaces(theFToRebuild, aModifiedEdges, theAnalyse, theFImages, theDMFNewHoles, theEdgesOrigins,
4497 theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
4498 theEdgesToAvoid, theVertsToAvoid, theAlreadyInvFaces, theValidEdges,
4499 theETrimEInf, theAsDes);
4502 //=======================================================================
4503 //function : IntersectFaces
4504 //purpose : Intersection of the faces that should be rebuild
4505 // to resolve all invalidities
4506 //=======================================================================
4507 void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4508 const TopTools_MapOfShape& theFSelfRebAvoid,
4509 const TopoDS_Shape& theSolids,
4510 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4511 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4512 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4513 TopTools_DataMapOfShapeListOfShape& theOEImages,
4514 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4515 TopTools_IndexedMapOfShape& theInvEdges,
4516 TopTools_IndexedMapOfShape& theValidEdges,
4517 const TopTools_MapOfShape& theInvertedEdges,
4518 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4519 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4520 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4521 TopTools_MapOfShape& theVertsToAvoid,
4522 TopTools_DataMapOfShapeShape& theETrimEInf,
4523 TopTools_MapOfShape& theModifiedEdges,
4524 Handle(BRepAlgo_AsDes)& theAsDes)
4526 Standard_Integer aNbFR = theFToRebuild.Extent();
4531 Standard_Integer i, j, k, aNbInv;
4532 TopTools_ListIteratorOfListOfShape aItLF, aItLE;
4534 // get vertices from invalid edges
4535 TopTools_MapOfShape aMVInv, aMVInvAll;
4536 aNbInv = theInvEdges.Extent();
4537 for (i = 1; i <= aNbInv; ++i) {
4538 const TopoDS_Shape& aEInv = theInvEdges(i);
4539 Standard_Boolean bValid = theValidEdges.Contains(aEInv);
4540 for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next()) {
4541 const TopoDS_Shape& aV = aExp.Current();
4549 Standard_Boolean bLookVertToAvoid = (aMVInv.Extent() > 0);
4551 TopTools_DataMapOfShapeListOfShape aDMSF, aMDone, aMEInfETrim, aDMVEFull;
4552 TopTools_IndexedDataMapOfShapeListOfShape aFLE, aDMEFInv;
4554 // Add all faces to rebuild to outgoing map <aFLE>,
4555 // plus link edges and vertices to the faces to
4556 // define intersection faces
4557 PrepareFacesForIntersection(theFToRebuild, theFImages, theInvFaces, theArtInvFaces,
4558 bLookVertToAvoid, aFLE, aMDone, aDMSF, aMEInfETrim,
4559 aDMVEFull, theETrimEInf, aDMEFInv);
4561 // Find vertices to avoid while trimming the edges.
4562 // These vertices are taken from the invalid edges common between
4563 // splits of different invalid, but not artificially, faces.
4564 // Additional condition for these vertices is that all
4565 // edges adjacent to this vertex must be either invalid
4566 // or contained in invalid faces
4567 TopTools_MapOfShape aMVRInv = theVertsToAvoid;
4568 FindVerticesToAvoid(aDMEFInv, theInvEdges, theValidEdges, theInvertedEdges,
4569 aDMVEFull, theOEImages, theOEOrigins, aMVRInv);
4571 // The faces should be intersected selectively -
4572 // intersect only faces neighboring to the same invalid face
4573 // and connected to its invalid edges;
4574 // when dealing with artificially invalid faces for intersection to be
4575 // complete we need to use not only invalid edges, but also the
4576 // edges connected to invalid ones
4578 // find blocks of artificially invalid faces
4579 TopTools_DataMapOfShapeShape aDMFImF;
4580 TopoDS_Compound aCFArt;
4581 BRep_Builder().MakeCompound(aCFArt);
4582 TopTools_DataMapIteratorOfDataMapOfShapeShape aItM(theArtInvFaces);
4583 for (; aItM.More(); aItM.Next()) {
4584 const TopoDS_Shape& aF = aItM.Key();
4585 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
4586 aItLF.Initialize(aLFInv);
4587 for (; aItLF.More(); aItLF.Next()) {
4588 BRep_Builder().Add(aCFArt, aItLF.Value());
4589 aDMFImF.Bind(aItLF.Value(), aF);
4593 // make connexity blocks
4594 TopTools_ListOfShape aLCBArt;
4595 BOPTools_AlgoTools::MakeConnexityBlocks(aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt);
4598 TopTools_MapOfShape aMEAlone, aMEInvOnArt;
4600 TopTools_ListIteratorOfListOfShape aItLCBArt(aLCBArt);
4601 for (; aItLCBArt.More(); aItLCBArt.Next()) {
4602 const TopoDS_Shape& aCB = aItLCBArt.Value();
4604 // check if aCB contains splits of only one offset face
4605 TopTools_MapOfShape aMFArt;
4606 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
4607 for (; aExpF.More(); aExpF.Next()) {
4608 aMFArt.Add(aDMFImF.Find(aExpF.Current()));
4611 Standard_Boolean bAlone = (aMFArt.Extent() == 1);
4613 // vertices on invalid edges
4614 TopTools_MapOfShape aMVEInv;
4615 TopTools_MapOfShape aMFence;
4616 // edges that should not be marked as alone - edges having same origins as invalid ones
4617 TopTools_MapOfShape aMEAvoid;
4618 // map to find alone edges by looking for free vertices
4619 TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal;
4621 TopExp_Explorer aExpE(aCB, TopAbs_EDGE);
4622 for (; aExpE.More(); aExpE.Next()) {
4623 const TopoDS_Shape& aE = aExpE.Current();
4624 if (theInvEdges.Contains(aE)) {
4625 aMEInvOnArt.Add(aE);
4626 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
4627 aMVEInv.Add(aItV.Value());
4631 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4633 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4634 for (; aItLEOr.More(); aItLEOr.Next()) {
4635 TopTools_ListIteratorOfListOfShape aItLEIm(theOEImages.Find(aItLEOr.Value()));
4636 for (; aItLEIm.More(); aItLEIm.Next()) {
4637 aMEAvoid.Add(aItLEIm.Value());
4645 if (aMFence.Add(aE)) {
4646 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal);
4650 // find edges with free vertices
4651 Standard_Integer aNbV = aDMVEVal.Extent();
4652 for (i = 1; i <= aNbV; ++i) {
4653 const TopoDS_Shape& aV = aDMVEVal.FindKey(i);
4654 if (!aMVEInv.Contains(aV)) {
4658 const TopTools_ListOfShape& aLEV = aDMVEVal(i);
4659 if (aLEV.Extent() > 1) {
4663 const TopoDS_Shape& aE = aLEV.First();
4664 if (aMEAvoid.Contains(aE)) {
4670 // if this alone edge adds nothing to the intersection list
4671 // it means that the origin of this edge has been split and we need to
4672 // add the neighboring images of the same origins
4673 if (aDMSF.Find(aE).Extent() > 1) {
4677 // check also its vertices
4678 TopoDS_Iterator aItE(aE);
4679 for (; aItE.More(); aItE.Next()) {
4680 const TopoDS_Shape& aVE = aItE.Value();
4681 if (aDMSF.Find(aVE).Extent() > 2) {
4690 // the edge is useless - look for other images
4691 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4696 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4697 for (; aItLEOr.More(); aItLEOr.Next()) {
4698 const TopoDS_Shape& aEOr = aItLEOr.Value();
4700 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr);
4701 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
4702 for (; aItLEIm.More(); aItLEIm.Next()) {
4703 const TopoDS_Shape& aEIm = aItLEIm.Value();
4705 if (aMFence.Contains(aEIm)) {
4713 // Get all invalidities from all faces to be used for avoiding
4714 // repeated usage of the common edges
4715 TopTools_MapOfShape aMAllInvs;
4716 aNbInv = theInvFaces.Extent();
4717 for (k = 1; k <= aNbInv; ++k) {
4718 TopTools_ListIteratorOfListOfShape aIt(theInvFaces(k));
4719 for (; aIt.More(); aIt.Next()) {
4720 TopExp_Explorer aExp(aIt.Value(), TopAbs_EDGE);
4721 for (; aExp.More(); aExp.Next()) {
4722 const TopoDS_Shape& aE = aExp.Current();
4723 if (theInvEdges.Contains(aE) || aMEAlone.Contains(aE)) {
4725 TopoDS_Iterator aItV(aE);
4726 for (; aItV.More(); aItV.Next()) {
4727 aMAllInvs.Add(aItV.Value());
4734 // Bounding vertices of not trimmed edges
4735 TopTools_MapOfShape aMVBounds;
4737 TopTools_MapOfShape aMECheckExt;
4738 // Save connections between not trimmed edge and its trimmed parts
4739 TopTools_DataMapOfShapeListOfShape aDMEETrim;
4740 // Splits of the new edges
4741 TopTools_DataMapOfShapeListOfShape aEImages;
4744 // Keep connection between blocks of invalid edges to the lists of
4745 // found edges to be intersected for its treatment
4746 TopTools_IndexedDataMapOfShapeListOfShape aDMOENEdges;
4748 aNbInv = theInvFaces.Extent();
4749 for (k = 1; k <= aNbInv; ++k) {
4750 const TopoDS_Shape& aFInv = theInvFaces.FindKey(k);
4751 Standard_Boolean bSelfRebAvoid = theFSelfRebAvoid.Contains(aFInv);
4752 const TopTools_ListOfShape& aLFInv = theInvFaces(k);
4754 TopTools_ListOfShape aLCB;
4755 if (aLFInv.Extent() > 1) {
4756 // make compound of invalid faces
4757 TopoDS_Compound aCFInv;
4758 aBB.MakeCompound(aCFInv);
4760 TopTools_ListIteratorOfListOfShape aIt(aLFInv);
4761 for (; aIt.More(); aIt.Next()) {
4762 const TopoDS_Shape& aFIm = aIt.Value();
4763 aBB.Add(aCFInv, aFIm);
4766 // make connexity blocks
4767 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCB);
4773 Standard_Boolean bArtificial = theArtInvFaces.IsBound(aFInv);
4774 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
4775 for (; aItLCB.More(); aItLCB.Next()) {
4776 const TopoDS_Shape& aCBInv = aItLCB.Value();
4778 TopTools_MapOfShape aMEFence;
4780 TopoDS_Compound aCBE;
4781 aBB.MakeCompound(aCBE);
4783 TopExp_Explorer aExp(aCBInv, TopAbs_EDGE);
4784 for (; aExp.More(); aExp.Next()) {
4785 const TopoDS_Shape& aE = aExp.Current();
4786 if (theInvEdges.Contains(aE) || (bArtificial && aMEAlone.Contains(aE))) {
4787 if (aMEFence.Add(aE)) {
4793 // make connexity blocks of edges
4794 TopTools_ListOfShape aLCBE;
4795 BOPTools_AlgoTools::MakeConnexityBlocks(aCBE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4797 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
4798 for (; aItLCBE.More(); aItLCBE.Next()) {
4799 const TopoDS_Shape& aCBELoc = aItLCBE.Value();
4801 // map of edges and vertices of processing invalidity
4802 TopTools_IndexedMapOfShape aME;
4803 // map of vertices to trim the new edges
4804 TopTools_IndexedMapOfShape aMECV;
4805 TopExp::MapShapes(aCBELoc, TopAbs_EDGE, aME);
4807 TopExp::MapShapes(aCBELoc, TopAbs_VERTEX, aME);
4809 // Using the map <aME> find chain of faces to be intersected;
4811 // faces for intersection
4812 TopTools_IndexedMapOfShape aMFInt;
4813 // additional faces for intersection
4814 TopTools_IndexedMapOfShape aMFIntExt;
4815 // splits of faces for intersection
4816 TopTools_ListOfShape aLFInt;
4817 // faces to avoid intersection
4818 TopTools_IndexedMapOfShape aMFAvoid;
4820 FindFacesForIntersection(aFInv, aME, theFImages, aDMSF, aMVInvAll,
4821 theArtInvFaces, bArtificial, theSSInterfs, aMFAvoid, aMFInt, aMFIntExt, aLFInt);
4822 if (aMFInt.Extent() < 3) {
4823 // nothing to intersect
4827 // intersect the faces, but do not intersect the invalid ones
4828 // among each other (except for the artificially invalid faces)
4829 TopTools_IndexedMapOfShape aMEToInt;
4830 Standard_Integer aNb = aMFInt.Extent();
4831 for (i = 1; i <= aNb; ++i) {
4832 const TopoDS_Face& aFi = TopoDS::Face(aMFInt(i));
4833 if (bSelfRebAvoid && aFi.IsSame(aFInv)) {
4837 const TopTools_ListOfShape& aLFImi = theFImages.FindFromKey(aFi);
4839 TopTools_ListOfShape& aLFEi = aFLE.ChangeFromKey(aFi);
4841 TopTools_ListOfShape& aLFDone = aMDone.ChangeFind(aFi);
4843 for (j = i + 1; j <= aNb; ++j) {
4844 const TopoDS_Face& aFj = TopoDS::Face(aMFInt(j));
4845 if (bSelfRebAvoid && aFj.IsSame(aFInv)) {
4849 const TopTools_ListOfShape& aLFImj = theFImages.FindFromKey(aFj);
4851 TopTools_ListOfShape& aLFEj = aFLE.ChangeFromKey(aFj);
4853 // if there are some common edges between faces
4854 // we should use these edges and do not intersect again.
4855 TopTools_ListOfShape aLEC;
4856 FindCommonParts(aLFImi, aLFImj, aLEC);
4858 if (aLEC.Extent()) {
4859 // no need to intersect if we have common edges between faces
4860 Standard_Boolean bForceUse = aMFIntExt.Contains(aFi) || aMFIntExt.Contains(aFj);
4861 ProcessCommonEdges(aLEC, theInvEdges, theValidEdges, aME, theETrimEInf, aMEInfETrim,
4862 theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt);
4866 // check if both these faces are invalid and sharing edges
4867 if (theInvFaces.Contains(aFi) && theInvFaces.Contains(aFj) &&
4868 !theArtInvFaces.IsBound(aFi) && !theArtInvFaces.IsBound(aFj)) {
4872 // check if these two faces have already been treated
4873 aItLE.Initialize(aLFDone);
4874 for (; aItLE.More(); aItLE.Next()) {
4875 const TopoDS_Shape& aF = aItLE.Value();
4876 if (aF.IsSame(aFj)) {
4882 // use intersection line obtained on the previous steps
4883 // plus, find new origins for these lines
4884 UpdateIntersectedFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
4885 aLFEi, aLFEj, theEdgesOrigins, aMEToInt);
4889 if (aMFAvoid.Contains(aFi) || aMFAvoid.Contains(aFj)) {
4893 aLFDone.Append(aFj);
4894 aMDone.ChangeFind(aFj).Append(aFi);
4896 IntersectFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
4897 aLFEi, aLFEj, theEdgesOrigins, aMECV, aMEToInt);
4901 // intersect and trim edges for this chain
4902 IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV,
4903 aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages);
4905 Standard_Integer iE, aNbEToInt = aMEToInt.Extent();
4906 for (iE = 1; iE <= aNbEToInt; ++iE)
4908 const TopoDS_Shape& aEInt = aMEToInt(iE);
4909 TopExp_Explorer anExpE(aCBELoc, TopAbs_EDGE);
4910 for (; anExpE.More(); anExpE.Next())
4912 const TopoDS_Shape& aE = anExpE.Current();
4913 TopTools_ListOfShape* pLEToInt = aDMOENEdges.ChangeSeek(aE);
4915 pLEToInt = &aDMOENEdges(aDMOENEdges.Add(aE, TopTools_ListOfShape()));
4916 AppendToList(*pLEToInt, aEInt);
4923 // filter the obtained edges
4924 UpdateValidEdges(theFImages, aFLE, aDMOENEdges, aMVBounds, theSolids, theInvEdges, theInvertedEdges, aMEInvOnArt,
4925 aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins,
4926 theVertsToAvoid, theETrimEInf, aEImages, aDMEETrim, theModifiedEdges, theAsDes);
4929 //=======================================================================
4930 //function : PrepareFacesForIntersection
4931 //purpose : Preparation of the maps for analyzing intersections of the faces
4932 //=======================================================================
4933 void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4934 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4935 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4936 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4937 const Standard_Boolean bLookVertToAvoid,
4938 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
4939 TopTools_DataMapOfShapeListOfShape& theMDone,
4940 TopTools_DataMapOfShapeListOfShape& theDMSF,
4941 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
4942 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
4943 TopTools_DataMapOfShapeShape& theETrimEInf,
4944 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv)
4946 Standard_Integer i, aNb = theFToRebuild.Extent();
4947 for (i = 1; i <= aNb; ++i) {
4948 const TopoDS_Shape& aF = theFToRebuild.FindKey(i);
4950 TopTools_ListOfShape aLE;
4951 theFLE.Add(aF, aLE);
4952 theMDone.Bind(aF, aLE);
4954 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
4955 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
4956 for (; aItLF.More(); aItLF.Next()) {
4957 const TopoDS_Shape& aFIm = aItLF.Value();
4958 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4959 for (; aExp.More(); aExp.Next()) {
4960 const TopoDS_Shape& aE = aExp.Current();
4961 // save connection to untrimmed face
4962 TopTools_ListOfShape *pLF = theDMSF.ChangeSeek(aE);
4964 pLF = theDMSF.Bound(aE, TopTools_ListOfShape());
4966 AppendToList(*pLF, aF);
4968 // save connection to untrimmed edge
4969 const TopoDS_Shape& aEInf = theETrimEInf.Find(aE);
4970 TopTools_ListOfShape *pLETrim = theMEInfETrim.ChangeSeek(aEInf);
4972 pLETrim = theMEInfETrim.Bound(aEInf, TopTools_ListOfShape());
4974 AppendToList(*pLETrim, aE);
4976 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
4977 for (; aExpV.More(); aExpV.Next()) {
4978 const TopoDS_Shape& aV = aExpV.Current();
4979 // save connection to face
4980 TopTools_ListOfShape *pLFV = theDMSF.ChangeSeek(aV);
4982 pLFV = theDMSF.Bound(aV, TopTools_ListOfShape());
4984 AppendToList(*pLFV, aF);
4986 if (bLookVertToAvoid) {
4987 // save connection to edges
4988 TopTools_ListOfShape *pLEV = theDMVEFull.ChangeSeek(aV);
4990 pLEV = theDMVEFull.Bound(aV, TopTools_ListOfShape());
4992 AppendToList(*pLEV, aE);
4998 if (bLookVertToAvoid) {
4999 // get edges of invalid faces (from invalid splits only)
5000 const TopTools_ListOfShape *pLFInv = theInvFaces.Seek(aF);
5001 if (!pLFInv || theArtInvFaces.IsBound(aF)) {
5005 aItLF.Initialize(*pLFInv);
5006 for (; aItLF.More(); aItLF.Next()) {
5007 const TopoDS_Shape& aFInv = aItLF.Value();
5008 TopExp_Explorer aExp(aFInv, TopAbs_EDGE);
5009 for (; aExp.More(); aExp.Next()) {
5010 const TopoDS_Shape& aE = aExp.Current();
5011 TopTools_ListOfShape *pLF = theDMEFInv.ChangeSeek(aE);
5013 pLF = &theDMEFInv(theDMEFInv.Add(aE, TopTools_ListOfShape()));
5015 AppendToList(*pLF, aF);
5022 //=======================================================================
5023 //function : FindVerticesToAvoid
5024 //purpose : Looking for the invalid vertices
5025 //=======================================================================
5026 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
5027 const TopTools_IndexedMapOfShape& theInvEdges,
5028 const TopTools_IndexedMapOfShape& theValidEdges,
5029 const TopTools_MapOfShape& theInvertedEdges,
5030 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5031 const TopTools_DataMapOfShapeListOfShape& theOEImages,
5032 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
5033 TopTools_MapOfShape& theMVRInv)
5035 TopTools_MapOfShape aMFence;
5036 Standard_Integer i, aNb = theDMEFInv.Extent();
5037 for (i = 1; i <= aNb; ++i) {
5038 const TopTools_ListOfShape& aLFInv = theDMEFInv(i);
5039 if (aLFInv.Extent() == 1) {
5043 const TopoDS_Shape& aE = theDMEFInv.FindKey(i);
5044 if (!theInvEdges.Contains(aE) || theValidEdges.Contains(aE)) {
5048 if (!aMFence.Add(aE))
5051 TopTools_IndexedDataMapOfShapeListOfShape aMVEEdges;
5052 // Do not check the splitting vertices, but check only the ending ones
5053 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
5056 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
5057 for (; aItLEOr.More(); aItLEOr.Next())
5059 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aItLEOr.Value());
5060 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
5061 for (; aItLEIm.More(); aItLEIm.Next())
5063 aMFence.Add(aItLEIm.Value());
5064 TopExp::MapShapesAndAncestors(aItLEIm.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5070 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5073 Standard_Integer j, aNbV = aMVEEdges.Extent();
5074 for (j = 1; j <= aNbV; ++j)
5076 if (aMVEEdges(j).Extent() != 1)
5079 const TopoDS_Shape& aV = aMVEEdges.FindKey(j);
5080 if (!aMFence.Add(aV))
5082 const TopTools_ListOfShape *pLE = theDMVEFull.Seek(aV);
5089 // If all edges sharing the vertex are either invalid or
5090 // the vertex is connected to at least two inverted edges
5091 // mark the vertex to be avoided in the new splits
5092 Standard_Integer iNbEInverted = 0;
5093 Standard_Boolean bAllEdgesInv = Standard_True;
5094 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
5095 for (; aItLE.More(); aItLE.Next()) {
5096 const TopoDS_Shape& aEV = aItLE.Value();
5098 if (theInvertedEdges.Contains(aEV))
5102 bAllEdgesInv = theInvEdges.Contains(aEV);
5105 if (iNbEInverted > 1 || bAllEdgesInv)
5113 //=======================================================================
5114 //function : FindFacesForIntersection
5115 //purpose : Looking for the faces around each invalidity for intersection
5116 //=======================================================================
5117 void FindFacesForIntersection(const TopoDS_Shape& theFInv,
5118 const TopTools_IndexedMapOfShape& theME,
5119 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5120 const TopTools_DataMapOfShapeListOfShape& theDMSF,
5121 const TopTools_MapOfShape& theMVInvAll,
5122 const TopTools_DataMapOfShapeShape& theArtInvFaces,
5123 const Standard_Boolean theArtCase,
5124 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
5125 TopTools_IndexedMapOfShape& theMFAvoid,
5126 TopTools_IndexedMapOfShape& theMFInt,
5127 TopTools_IndexedMapOfShape& theMFIntExt,
5128 TopTools_ListOfShape& theLFImInt)
5130 Standard_Integer i, aNbE = theME.Extent();
5132 TopTools_IndexedMapOfShape aMShapes;
5134 for (i = 1; i <= aNbE; ++i) {
5135 const TopoDS_Shape& aS = theME(i);
5136 if (!theDMSF.IsBound(aS)) {
5140 // in artificial case we intersect the faces which are close to invalidity
5141 Standard_Boolean bAvoid = theArtCase ?
5142 ((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains(aS)) : Standard_False;
5144 const TopTools_ListOfShape& aLF = theDMSF.Find(aS);
5145 TopTools_ListIteratorOfListOfShape aItLF(aLF);
5146 for (; aItLF.More(); aItLF.Next()) {
5147 const TopoDS_Shape& aF = aItLF.Value();
5148 if (theMFInt.Contains(aF)) {
5152 if (bAvoid && theArtInvFaces.IsBound(aF)) {
5158 Standard_Boolean bUse = !aF.IsSame(theFInv);
5160 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5161 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5162 for (; aItLFIm.More(); aItLFIm.Next()) {
5163 const TopoDS_Shape& aFIm = aItLFIm.Value();
5164 theLFImInt.Append(aFIm);
5166 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMShapes);
5176 const TopTools_ListOfShape* pLFInv = theSSInterfs.Seek(theFInv);
5181 TopTools_MapOfShape aMF;
5182 TopTools_ListIteratorOfListOfShape aItLF(*pLFInv);
5183 for (; aItLF.More(); aItLF.Next()) {
5184 const TopoDS_Shape& aF = aItLF.Value();
5188 // the faces should be unique in each place
5189 TopoDS_Compound aCF;
5190 BRep_Builder().MakeCompound(aCF);
5192 TopTools_IndexedMapOfShape aMFToAdd;
5193 TopTools_DataMapOfShapeShape aDMFOr;
5195 for (i = 1; i <= aNbE; ++i) {
5196 const TopoDS_Shape& aS = theME(i);
5197 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aS);
5202 aItLF.Initialize(*pLF);
5203 for (; aItLF.More(); aItLF.Next()) {
5204 const TopoDS_Shape& aF = aItLF.Value();
5205 if (theMFInt.Contains(aF) || aMFToAdd.Contains(aF) || !aMF.Contains(aF)) {
5209 // check if the face has some connection to already added for intersection faces
5210 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5211 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5212 for (; aItLFIm.More(); aItLFIm.Next()) {
5213 const TopoDS_Shape& aFIm = aItLFIm.Value();
5214 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
5215 for (; aExp.More(); aExp.Next()) {
5216 if (aMShapes.Contains(aExp.Current())) {
5224 if (!aItLFIm.More()) {
5229 aItLFIm.Initialize(aLFIm);
5230 for (; aItLFIm.More(); aItLFIm.Next()) {
5231 const TopoDS_Shape& aFIm = aItLFIm.Value();
5232 aDMFOr.Bind(aFIm, aF);
5233 BRep_Builder().Add(aCF, aFIm);
5238 if (aMFToAdd.IsEmpty()) {
5242 TopTools_ListOfShape aLCB;
5243 BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
5245 if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1)) {
5249 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
5250 for (; aItLCB.More(); aItLCB.Next()) {
5251 const TopoDS_Shape& aCB = aItLCB.Value();
5253 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
5254 for (; aExpF.More(); aExpF.Next()) {
5255 const TopoDS_Shape& aFIm = aExpF.Current();
5256 aMFToAdd.Add(aDMFOr.Find(aFIm));
5259 if (aMFToAdd.Extent() == 1) {
5260 const TopoDS_Shape& aF = aMFToAdd(1);
5263 theMFIntExt.Add(aF);
5265 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5266 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5267 for (; aItLFIm.More(); aItLFIm.Next()) {
5268 const TopoDS_Shape& aFIm = aItLFIm.Value();
5269 theLFImInt.Append(aFIm);
5275 //=======================================================================
5276 //function : ProcessCommonEdges
5277 //purpose : Analyzing the common edges between splits of offset faces
5278 //=======================================================================
5279 void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
5280 const TopTools_IndexedMapOfShape& theInvEdges,
5281 const TopTools_IndexedMapOfShape& theValidEdges,
5282 const TopTools_IndexedMapOfShape& theME,
5283 const TopTools_DataMapOfShapeShape& theETrimEInf,
5284 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5285 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
5286 const TopTools_MapOfShape& theAllInvs,
5287 const Standard_Boolean theForceUse,
5288 TopTools_IndexedMapOfShape& theMECV,
5289 TopTools_MapOfShape& theMECheckExt,
5290 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5291 TopTools_ListOfShape& theLFEi,
5292 TopTools_ListOfShape& theLFEj,
5293 TopTools_IndexedMapOfShape& theMEToInt)
5295 TopTools_ListOfShape aLEC;
5296 // process common edges
5297 TopTools_ListIteratorOfListOfShape aItLE(theLEC);
5298 for (; aItLE.More(); aItLE.Next()) {
5299 const TopoDS_Shape& aEC = aItLE.Value();
5301 // check first if common edges are valid
5302 if (theInvEdges.Contains(aEC) && !theValidEdges.Contains(aEC)) {
5306 // common edge should have connection to current invalidity
5307 if (theME.Contains(aEC)) {
5312 TopoDS_Iterator aItV(aEC);
5313 for (; aItV.More(); aItV.Next()) {
5314 const TopoDS_Shape& aVE = aItV.Value();
5315 if (theME.Contains(aVE)) {
5322 Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
5328 aItLE.Initialize(theLEC);
5329 for (; aItLE.More(); aItLE.Next()) {
5330 const TopoDS_Shape& aEC = aItLE.Value();
5331 // check if all images of the origin of this edge
5332 // are not connected to any invalidity
5333 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5334 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5335 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5336 for (; aItLVE.More(); aItLVE.Next()) {
5337 const TopoDS_Shape& aECx = aItLVE.Value();
5338 if (theAllInvs.Contains(aECx) || theInvEdges.Contains(aECx)) {
5342 TopoDS_Iterator aItV(aECx);
5343 for (; aItV.More(); aItV.Next()) {
5344 if (theAllInvs.Contains(aItV.Value())) {
5349 // use only one element
5350 if (aLEC.IsEmpty()) {
5357 aItLE.Initialize(aLEC);
5358 for (; aItLE.More(); aItLE.Next()) {
5359 const TopoDS_Shape& aEC = aItLE.Value();
5361 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5363 // find the edges of the same original edge
5364 // and take their vertices as well
5365 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5366 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5367 for (; aItLVE.More(); aItLVE.Next()) {
5368 const TopoDS_Shape& aECx = aItLVE.Value();
5370 const TopTools_ListOfShape* pLEOr = theOEOrigins.Seek(aECx);
5371 if (!pLEOr || (pLEOr->Extent() == 1)) {
5372 TopExp::MapShapes(aECx, TopAbs_VERTEX, theMECV);
5376 // bind unlimited edge to its trimmed part in face to update maps of
5377 // images and origins in the future
5378 TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek(aEInt);
5380 pLTAdded = theDMEETrim.Bound(aEInt, TopTools_ListOfShape());
5382 AppendToList(*pLTAdded, aEC);
5384 else if (!theForceUse) {
5385 theMECheckExt.Add(aEInt);
5388 AppendToList(theLFEi, aEInt);
5389 AppendToList(theLFEj, aEInt);
5390 theMEToInt.Add(aEInt);
5394 //=======================================================================
5395 //function : UpdateIntersectedFaces
5396 //purpose : Updating the already interfered faces
5397 //=======================================================================
5398 void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
5399 const TopoDS_Shape& theFi,
5400 const TopoDS_Shape& theFj,
5401 const TopTools_ListOfShape& theLFInv,
5402 const TopTools_ListOfShape& theLFImi,
5403 const TopTools_ListOfShape& theLFImj,
5404 const TopTools_ListOfShape& theLFEi,
5405 const TopTools_ListOfShape& theLFEj,
5406 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5407 TopTools_IndexedMapOfShape& theMEToInt)
5409 // Find common edges in these two lists
5410 TopTools_MapOfShape aMEi;
5411 TopTools_ListIteratorOfListOfShape aItLE(theLFEi);
5412 for (; aItLE.More(); aItLE.Next()) {
5413 const TopoDS_Shape& aE = aItLE.Value();
5418 TopTools_IndexedMapOfShape aMEToFindOrigins;
5419 TopTools_ListOfShape aLEToFindOrigins;
5420 if (!theFi.IsSame(theFInv)) {
5421 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5423 if (!theFj.IsSame(theFInv)) {
5424 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5427 TopTools_ListOfShape aLEOrInit;
5428 aItLE.Initialize(aLEToFindOrigins);
5429 for (; aItLE.More(); aItLE.Next()) {
5430 const TopoDS_Shape& aEC = aItLE.Value();
5431 aMEToFindOrigins.Add(aEC);
5434 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5436 aItLE.Initialize(theLFEj);
5437 for (; aItLE.More(); aItLE.Next()) {
5438 const TopoDS_Shape& aE = aItLE.Value();
5439 if (aMEi.Contains(aE)) {
5441 if (aLEOrInit.Extent()) {
5442 if (theEdgesOrigins.IsBound(aE)) {
5443 TopTools_ListOfShape& aLEOr = theEdgesOrigins.ChangeFind(aE);
5444 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOrInit);
5445 for (; aItLEOr.More(); aItLEOr.Next()) {
5446 const TopoDS_Shape& aEOr = aItLEOr.Value();
5447 AppendToList(aLEOr, aEOr);
5451 theEdgesOrigins.Bind(aE, aLEOrInit);
5458 //=======================================================================
5459 //function : IntersectFaces
5460 //purpose : Intersection of the pair of faces
5461 //=======================================================================
5462 void IntersectFaces(const TopoDS_Shape& theFInv,
5463 const TopoDS_Shape& theFi,
5464 const TopoDS_Shape& theFj,
5465 const TopTools_ListOfShape& theLFInv,
5466 const TopTools_ListOfShape& theLFImi,
5467 const TopTools_ListOfShape& theLFImj,
5468 TopTools_ListOfShape& theLFEi,
5469 TopTools_ListOfShape& theLFEj,
5470 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5471 TopTools_IndexedMapOfShape& theMECV,
5472 TopTools_IndexedMapOfShape& theMEToInt)
5475 TopAbs_State aSide = TopAbs_OUT;
5476 TopTools_ListOfShape aLInt1, aLInt2;
5477 TopoDS_Edge aNullEdge;
5478 BRepOffset_Tool::Inter3D(TopoDS::Face(theFi), TopoDS::Face(theFj), aLInt1, aLInt2, aSide, aNullEdge);
5480 if (aLInt1.IsEmpty()) {
5484 // find common vertices for trimming edges
5485 TopTools_ListOfShape aLCV;
5486 TopTools_ListIteratorOfListOfShape aItLE;
5487 FindCommonParts(theLFImi, theLFImj, aLCV, TopAbs_VERTEX);
5488 if (aLCV.Extent() > 1) {
5489 aItLE.Initialize(aLCV);
5490 for (; aItLE.More(); aItLE.Next()) {
5491 const TopoDS_Shape& aCV = aItLE.Value();
5497 TopTools_IndexedMapOfShape aMEToFindOrigins;
5498 TopTools_ListOfShape aLEToFindOrigins;
5499 if (!theFi.IsSame(theFInv)) {
5500 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5502 if (!theFj.IsSame(theFInv)) {
5503 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5505 TopTools_ListOfShape aLEOrInit;
5506 aItLE.Initialize(aLEToFindOrigins);
5507 for (; aItLE.More(); aItLE.Next()) {
5508 const TopoDS_Shape& aEC = aItLE.Value();
5509 aMEToFindOrigins.Add(aEC);
5512 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5514 aItLE.Initialize(aLInt1);
5515 for (; aItLE.More(); aItLE.Next()) {
5516 const TopoDS_Shape& aEInt = aItLE.Value();
5517 theLFEi.Append(aEInt);
5518 theLFEj.Append(aEInt);
5520 if (aLEOrInit.Extent()) {
5521 theEdgesOrigins.Bind(aEInt, aLEOrInit);
5524 theMEToInt.Add(aEInt);
5528 //=======================================================================
5529 //function : FindOrigins
5530 //purpose : Looking for the origin edges
5531 //=======================================================================
5532 void FindOrigins(const TopTools_ListOfShape& theLFIm1,
5533 const TopTools_ListOfShape& theLFIm2,
5534 const TopTools_IndexedMapOfShape& theME,
5535 const TopTools_DataMapOfShapeListOfShape& theOrigins,
5536 TopTools_ListOfShape& theLEOr)
5539 TopTools_MapOfShape aMFence;
5540 TopExp_Explorer aExp;
5541 TopTools_ListIteratorOfListOfShape aIt, aItLE;
5543 for (i = 0; i < 2; ++i) {
5544 const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2;
5545 aIt.Initialize(aLF);
5546 for (; aIt.More(); aIt.Next()) {
5547 const TopoDS_Shape& aF = aIt.Value();
5549 aExp.Init(aF, TopAbs_EDGE);
5550 for (; aExp.More(); aExp.Next()) {
5551 const TopoDS_Shape& aE = aExp.Current();
5553 if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5554 const TopTools_ListOfShape& aLEOr = theOrigins.Find(aE);
5555 aItLE.Initialize(aLEOr);
5556 for (; aItLE.More(); aItLE.Next()) {
5557 const TopoDS_Shape& aEOr = aItLE.Value();
5559 if (aMFence.Add(aEOr) && (aEOr.ShapeType() == TopAbs_EDGE)) {
5560 theLEOr.Append(aEOr);
5562 } // for (; aItLE.More(); aItLE.Next()) {
5563 } // if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5564 } // aExp.Init(aF, TopAbs_EDGE);
5565 } // for (; aIt.More(); aIt.Next()) {
5566 } // for (i = 0; i < 2; ++i) {
5569 //=======================================================================
5570 //function : IntersectAndTrimEdges
5571 //purpose : Intersection of the new intersection edges among themselves
5572 //=======================================================================
5573 void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
5574 const TopTools_IndexedMapOfShape& theMFInt,
5575 const TopTools_IndexedMapOfShape& theMEInt,
5576 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5577 const TopTools_IndexedMapOfShape& theMSInv,
5578 const TopTools_IndexedMapOfShape& theMVE,
5579 const TopTools_MapOfShape& theVertsToAvoid,
5580 const TopTools_MapOfShape& theNewVertsToAvoid,
5581 const TopTools_MapOfShape& theMECheckExt,
5582 TopTools_MapOfShape& theMVBounds,
5583 TopTools_DataMapOfShapeListOfShape& theEImages)
5585 Standard_Integer i, aNb = theMEInt.Extent();
5590 TopTools_ListOfShape aLArgs;
5591 TopTools_MapOfShape aMFence;
5592 TopTools_ListIteratorOfListOfShape aIt, aIt1;
5593 TopExp_Explorer aExp;
5595 // get vertices from the splits of intersected faces.
5596 // vertices are taken from the edges close to invalidity
5598 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
5599 aNb = theMFInt.Extent();
5600 for (i = 1; i <= aNb; ++i) {
5601 const TopoDS_Shape& aF = theMFInt(i);
5602 const TopTools_ListOfShape& aLE = theFToRebuild.FindFromKey(aF);
5604 aIt.Initialize(aLE);
5605 for (; aIt.More(); aIt.Next()) {
5606 const TopoDS_Shape& aE = aIt.Value();
5607 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
5609 aExp.Init(aE, TopAbs_VERTEX);
5610 for (; aExp.More(); aExp.Next()) {
5611 const TopoDS_Shape& aV1 = aExp.Current();
5612 if (!theVertsToAvoid.Contains(aV1) && theMVE.Contains(aV1) && aMFence.Add(aV1)) {
5619 aNb = theMSInv.Extent();
5620 for (i = 1; i <= aNb; ++i) {
5621 const TopoDS_Shape& aV = theMSInv(i);
5622 if (aV.ShapeType() != TopAbs_VERTEX) {
5626 TopTools_ListOfShape *pLVE = aDMVE.ChangeSeek(aV);
5631 aIt.Initialize(*pLVE);
5632 for (; aIt.More(); aIt.Next()) {
5633 const TopoDS_Shape& aE = aIt.Value();
5635 aExp.Init(aE, TopAbs_VERTEX);
5636 for (; aExp.More(); aExp.Next()) {
5637 const TopoDS_Shape& aV1 = aExp.Current();
5638 if (!theVertsToAvoid.Contains(aV1) && aMFence.Add(aV1)) {
5645 // bounding vertices of untrimmed edges
5646 TopTools_ListOfShape aLVBounds;
5647 // new intersection edges
5648 TopTools_ListOfShape aLENew;
5649 // get edges to intersect
5650 TopTools_ListOfShape aLEInt;
5651 // Common intersection edges. Should be intersected separately
5652 TopTools_ListOfShape aLCE;
5654 aNb = theMEInt.Extent();
5655 for (i = 1; i <= aNb; ++i) {
5656 const TopoDS_Shape& aE = theMEInt(i);
5657 if (theMECheckExt.Contains(aE)) {
5658 // avoid trimming of the intersection edges by additional common edges
5663 if (!theDMEETrim.IsBound(aE)) {
5670 aExp.Init(aE, TopAbs_VERTEX);
5671 for (; aExp.More(); aExp.Next()) {
5672 const TopoDS_Shape& aV = aExp.Current();
5673 aLVBounds.Append(aV);
5678 BOPAlgo_Builder aGF;
5679 aGF.SetArguments(aLArgs);
5681 if (aGF.HasErrors()) {
5685 // update vertices to avoid with SD vertices
5686 aIt.Initialize(aLVBounds);
5687 for (; aIt.More(); aIt.Next()) {
5688 const TopoDS_Shape& aV = aIt.Value();
5689 const TopTools_ListOfShape& aLVIm = aGF.Modified(aV);
5690 if (aLVIm.IsEmpty()) {
5691 theMVBounds.Add(aV);
5694 const TopoDS_Shape& aVIm = aLVIm.First();
5695 theMVBounds.Add(aVIm);
5699 // find invalid splits of edges
5700 TopTools_MapOfShape aMEInv;
5701 GetInvalidEdges(theNewVertsToAvoid, theMVBounds, aGF, aMEInv);
5704 // get valid splits to intersect with the commons
5705 TopoDS_Compound aCEIm;
5706 aBB.MakeCompound(aCEIm);
5708 // remove the splits containing vertices from invalid edges
5709 aIt.Initialize(aLEInt);
5710 for (; aIt.More(); aIt.Next()) {
5711 const TopoDS_Shape& aE = aIt.Value();
5713 TopTools_ListOfShape aLEIm = aGF.Modified(aE);
5714 if (aLEIm.IsEmpty()) {
5718 aIt1.Initialize(aLEIm);
5719 for (; aIt1.More(); ) {
5720 const TopoDS_Shape& aEIm = aIt1.Value();
5722 if (aMEInv.Contains(aEIm)) {
5726 aBB.Add(aCEIm, aEIm);
5731 if (aLEIm.Extent()) {
5732 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
5734 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
5736 pLEIm->Append(aLEIm);
5740 if (!aLCE.Extent()) {
5744 // trim common edges by other intersection edges
5745 BOPAlgo_Builder aGFCE;
5746 aGFCE.SetArguments(aLCE);
5747 aGFCE.AddArgument(aCEIm);
5750 if (aGFCE.HasErrors()) {
5754 const BOPDS_PDS& pDS = aGFCE.PDS();
5755 TopTools_ListIteratorOfListOfShape aItLCE(aLCE);
5756 for (; aItLCE.More(); aItLCE.Next()) {
5757 const TopoDS_Shape& aE = aItLCE.Value();
5758 TopTools_ListOfShape aLEIm = aGFCE.Modified(aE);
5759 if (aLEIm.IsEmpty()) {
5763 // check if it's not coincide with some intersection edge
5764 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(pDS->PaveBlocks(pDS->Index(aE)));
5765 for (; aItLPB.More(); aItLPB.Next()) {
5766 if (pDS->IsCommonBlock(aItLPB.Value())) {
5767 // find with what it is a common
5768 const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock(aItLPB.Value())->PaveBlocks();
5769 BOPDS_ListIteratorOfListOfPaveBlock aItLPBC(aLPBC);
5770 for (; aItLPBC.More(); aItLPBC.Next()) {
5771 const TopoDS_Shape& aEC = pDS->Shape(aItLPBC.Value()->OriginalEdge());
5772 if (!theMECheckExt.Contains(aEC)) {
5776 if (aItLPBC.More()) {
5781 if (aItLPB.More()) {
5782 // avoid creation of unnecessary splits from commons which
5783 // coincide with intersection edges
5788 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
5790 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
5792 pLEIm->Append(aLEIm);
5794 // save bounding vertices
5795 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
5796 const TopoDS_Shape& aV = aItV.Value();
5797 const TopTools_ListOfShape& aLVIm = aGFCE.Modified(aV);
5798 theMVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
5803 //=======================================================================
5804 //function : GetInvalidEdges
5805 //purpose : Looking for the invalid edges by intersecting with invalid vertices
5806 //=======================================================================
5807 void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
5808 const TopTools_MapOfShape& theMVBounds,
5809 BOPAlgo_Builder& theGF,
5810 TopTools_MapOfShape& theMEInv)
5812 if (theVertsToAvoid.IsEmpty()) {
5816 TopTools_ListIteratorOfListOfShape aIt, aIt1;
5817 // get vertices created with intersection edges
5818 const TopoDS_Shape& aRes = theGF.Shape();
5819 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
5820 TopExp::MapShapesAndAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
5822 const BOPDS_PDS& pDS = theGF.PDS();
5824 // find invalid splits of edges
5825 // check if the vertex is invalid:
5826 // a. it may be the vertex SD with the vertices to avoid
5827 // b. or it may be the vertex which is created by the intersection
5828 // of only existing edges, i.e. no new intersection edges goes
5829 // through this vertex
5831 TopTools_MapOfShape aMVInv;
5832 Standard_Integer i, aNb = aDMVE.Extent();
5833 for (i = 1; i <= aNb; ++i) {
5834 const TopoDS_Vertex& aV = TopoDS::Vertex(aDMVE.FindKey(i));
5835 if (theMVBounds.Contains(aV)) {
5839 Standard_Integer nV = pDS->Index(aV);
5840 if ((nV >= 0) && !pDS->IsNewShape(nV)) {
5844 TopTools_MapIteratorOfMapOfShape aItM(theVertsToAvoid);
5845 for (; aItM.More(); aItM.Next()) {
5846 const TopoDS_Vertex& aVInv = *(TopoDS_Vertex*)&aItM.Value();
5847 Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV(aV, aVInv);
5855 const TopTools_ListOfShape& aLVE = aDMVE.FindFromKey(aV);
5856 aIt.Initialize(aLVE);
5857 for (; aIt.More(); aIt.Next()) {
5858 const TopoDS_Shape& aE = aIt.Value();
5865 //=======================================================================
5866 //function : UpdateValidEdges
5867 //purpose : Making the new splits and updating the maps
5868 //=======================================================================
5869 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5870 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
5871 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
5872 const TopTools_MapOfShape& theMVBounds,
5873 const TopoDS_Shape& theSolids,
5874 const TopTools_IndexedMapOfShape& theInvEdges,
5875 const TopTools_MapOfShape& theInvertedEdges,
5876 const TopTools_MapOfShape& theMEInvOnArt,
5877 TopTools_MapOfShape& theMECheckExt,
5878 TopTools_IndexedMapOfShape& theEdgesToAvoid,
5879 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5880 TopTools_DataMapOfShapeListOfShape& theOEImages,
5881 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
5882 TopTools_MapOfShape& theVertsToAvoid,
5883 TopTools_DataMapOfShapeShape& theETrimEInf,
5884 TopTools_DataMapOfShapeListOfShape& theEImages,
5885 TopTools_DataMapOfShapeListOfShape& theEETrim,
5886 TopTools_MapOfShape& theModifiedEdges,
5887 Handle(BRepAlgo_AsDes)& theAsDes)
5889 // update images and origins of edges, plus update AsDes
5892 TopTools_ListOfShape aLE;
5893 // back connection from edges to faces
5894 TopTools_DataMapOfShapeListOfShape aMELF;
5896 TopTools_MapOfShape aMETmp;
5897 Standard_Integer i, aNb = theFLE.Extent();
5898 for (i = 1; i <= aNb; ++i) {
5899 const TopoDS_Face& aF = TopoDS::Face(theFLE.FindKey(i));
5901 const TopTools_ListOfShape& aLEInt = theFLE(i);
5902 TopTools_ListIteratorOfListOfShape aItLE(aLEInt);
5903 for (; aItLE.More(); aItLE.Next()) {
5904 const TopoDS_Shape& aE = aItLE.Value();
5905 if ((theMECheckExt.Contains(aE) || aMETmp.Contains(aE)) && !theEImages.IsBound(aE)) {
5906 theMECheckExt.Remove(aE);
5910 TopTools_ListOfShape* pLF = aMELF.ChangeSeek(aE);
5912 pLF = aMELF.Bound(aE, TopTools_ListOfShape());
5919 if (aLE.IsEmpty()) {
5923 // bounding edges, that are going to be replaced
5924 TopTools_MapOfShape aMEB;
5926 // new intersection edges
5927 TopTools_MapOfShape aMENew;
5928 // map of old vertices
5929 TopTools_MapOfShape aMVOld;
5930 // back connection to untrimmed edges
5931 TopTools_DataMapOfShapeListOfShape aDMEOr;
5933 // trim the new intersection edges
5934 TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt,
5935 theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF);
5937 if (theEImages.IsEmpty())
5939 // No new splits is preserved
5940 // update intersection edges and exit
5941 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
5942 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
5948 // Make connexity blocks of the invalid edges
5949 // and treat each block separately
5951 // Compound of all invalid edges to make the blocks
5952 TopoDS_Compound aCEAll;
5953 aBB.MakeCompound(aCEAll);
5955 Standard_Integer aNbE = theOENEdges.Extent();
5956 for (i = 1; i <= aNbE; ++i)
5957 aBB.Add(aCEAll, theOENEdges.FindKey(i));
5959 // Separate the edges into blocks
5960 TopTools_ListOfShape aLBlocks;
5961 BOPTools_AlgoTools::MakeConnexityBlocks(aCEAll, TopAbs_VERTEX, TopAbs_EDGE, aLBlocks);
5963 // Perform intersection of the new splits for each block
5965 // Intersected splits
5966 TopTools_IndexedDataMapOfShapeListOfShape aMBlocksSp;
5968 TopTools_ListIteratorOfListOfShape aItLB(aLBlocks);
5969 for (; aItLB.More(); aItLB.Next())
5971 const TopoDS_Shape& aBlock = aItLB.Value();
5973 // Get the list of new edges for the block
5974 TopTools_ListOfShape aBlockLENew;
5977 TopTools_MapOfShape aMEFence;
5978 TopExp_Explorer anExpE(aBlock, TopAbs_EDGE);
5979 for (; anExpE.More(); anExpE.Next())
5981 const TopoDS_Shape& aE = anExpE.Current();
5982 const TopTools_ListOfShape& aLEInt = theOENEdges.FindFromKey(aE);
5983 TopTools_ListIteratorOfListOfShape aItLEInt(aLEInt);
5984 for (; aItLEInt.More(); aItLEInt.Next())
5986 if (aMEFence.Add(aItLEInt.Value()))
5987 aBlockLENew.Append(aItLEInt.Value());
5992 if (aBlockLENew.IsEmpty())
5995 // Get the splits of new edges to intersect
5996 TopTools_ListOfShape aLSplits;
5998 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
5999 for (; aItLE.More(); aItLE.Next())
6001 const TopoDS_Shape& aE = aItLE.Value();
6002 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
6003 if (!pLEIm || pLEIm->IsEmpty())
6006 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6007 for (; aItLEIm.More(); aItLEIm.Next())
6008 aLSplits.Append(aItLEIm.Value());
6011 if (aLSplits.IsEmpty())
6015 if (aLSplits.Extent() > 1)
6016 // Intersect the new splits among themselves to avoid self-intersections
6017 IntersectEdges(aLSplits, aBlockLENew, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6018 theEImages, theModifiedEdges, aDMEOr, aMELF, aCE);
6020 aCE = aLSplits.First();
6022 aMBlocksSp.Add(aCE, aBlockLENew);
6025 // Perform filtering of the edges in two steps:
6026 // - Check each block separately using localized bounds
6027 // taken only from the splits of faces of the current block;
6028 // - Intersect all splits together and filter the splits by all bounds.
6030 // FIRST STAGE - separate treatment of the blocks
6032 // Valid splits to be preserved on the first stage
6033 TopTools_MapOfShape aMEVal;
6035 // Blocks of valid edges on the first stage
6036 TopTools_ListOfShape aLValBlocks;
6038 // Context for caching the classification tools
6039 Handle(IntTools_Context) aCtx = new IntTools_Context;
6041 Standard_Integer aNbB = aMBlocksSp.Extent();
6042 for (i = 1; i <= aNbB; ++i)
6044 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6045 const TopTools_ListOfShape& aBlockLENew = aMBlocksSp(i);
6047 // Get all participating faces to get the bounds
6048 TopTools_ListOfShape aLFaces;
6049 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
6050 for (; aItLE.More(); aItLE.Next())
6052 const TopTools_ListOfShape *pLF = aMELF.Seek(aItLE.Value());
6055 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
6056 for (; aItLF.More(); aItLF.Next())
6057 AppendToList(aLFaces, aItLF.Value());
6060 // Localized bounds of the splits of the offset faces
6061 // to filter the new splits of the current block
6062 TopoDS_Shape aFilterBounds;
6063 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6065 // Filter the splits by bounds
6066 TopTools_MapOfShape aMEInvLoc;
6067 GetInvalidEdgesByBounds(aCE, aFilterBounds, theFImages, theSolids,
6068 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6069 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInvLoc);
6071 // Keep only valid edges of the block
6072 TopoDS_Compound aCEVal;
6073 aBB.MakeCompound(aCEVal);
6075 Standard_Boolean bKept = Standard_False;
6077 TopExp_Explorer anExpE(aCE, TopAbs_EDGE);
6078 for (; anExpE.More(); anExpE.Next())
6080 const TopoDS_Shape& aESp = anExpE.Current();
6081 if (!aMEInvLoc.Contains(aESp) && aMEVal.Add(aESp))
6083 aBB.Add(aCEVal, aESp);
6084 bKept = Standard_True;
6089 aLValBlocks.Append(aCEVal);
6092 // Filter the images of edges after the first filtering stage
6093 TopoDS_Shape aSplits1;
6094 FilterSplits(aLE, aMEVal, Standard_False, theEImages, aSplits1);
6096 if (aLValBlocks.IsEmpty())
6098 // update intersection edges
6099 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6100 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6104 // SECOND STAGE - Filter the remaining splits together
6106 // Add for intersection already removed new edges using them
6107 // as markers for other invalid edges
6108 aNbB = aMBlocksSp.Extent();
6109 for (i = 1; i <= aNbB; ++i)
6111 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6112 for (TopExp_Explorer anExp(aCE, TopAbs_EDGE); anExp.More(); anExp.Next())
6114 const TopoDS_Shape& aEIm = anExp.Current();
6115 if (aMENew.Contains(aEIm) && !aMEVal.Contains(aEIm))
6116 aLValBlocks.Append(aEIm);
6120 if (aLValBlocks.Extent() > 1)
6121 // intersect the new splits among themselves to avoid self-intersections
6122 IntersectEdges(aLValBlocks, aLE, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6123 theEImages, theModifiedEdges, aDMEOr, aMELF, aSplits1);
6125 aSplits1 = aLValBlocks.First();
6127 // Get all faces to get the bounds from their splits
6128 TopTools_ListOfShape aLFaces;
6129 for (i = 1; i <= theFImages.Extent(); ++i)
6130 aLFaces.Append(theFImages.FindKey(i));
6132 // Bounds of the splits of the offset faces to filter the new splits
6133 TopoDS_Shape aFilterBounds;
6134 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6136 // Filter the splits by intersection with bounds
6137 TopTools_MapOfShape aMEInv;
6138 GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids,
6139 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6140 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInv);
6142 // Filter the images of edges after the second filtering stage
6143 // and combine all valid edges into a single compound
6144 TopoDS_Shape aSplits;
6145 FilterSplits(aLE, aMEInv, Standard_True, theEImages, aSplits);
6147 // get bounds to update
6148 // we need to update the edges of all the affected faces
6149 TopTools_ListOfShape aLF;
6150 // prepare the vertices from new splits of edges
6151 TopTools_IndexedMapOfShape aMVSp;
6152 TopExp::MapShapes(aSplits, TopAbs_VERTEX, aMVSp);
6154 Standard_Integer aNbF = theFImages.Extent();
6155 for (i = 1; i <= aNbF; ++i) {
6156 const TopoDS_Shape& aF = theFImages.FindKey(i);
6157 if (theFLE.Contains(aF)) {
6162 // check the splits of faces to have vertices from splits
6163 const TopTools_ListOfShape& aLFIm = theFImages(i);
6164 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
6165 for (; aItLFIm.More(); aItLFIm.Next()) {
6166 const TopoDS_Shape& aFIm = aItLFIm.Value();
6168 TopExp_Explorer aExpV(aFIm, TopAbs_VERTEX);
6169 for (; aExpV.More(); aExpV.Next()) {
6170 const TopoDS_Shape& aV = aExpV.Current();
6171 if (aMVSp.Contains(aV)) {
6181 if (aItLFIm.More()) {
6186 // get bounds from splits of faces of aLF
6187 TopoDS_Shape aBounds;
6188 TopTools_ListOfShape aLAValid, aLABounds;
6189 GetBoundsToUpdate(aLF, theOEImages, theOEOrigins, aMEB,
6190 aLABounds, aLAValid, aBounds, theAsDes);
6192 // Intersect valid splits with bounds and update both
6193 BOPAlgo_Builder aGF;
6194 aGF.AddArgument(aBounds);
6195 aGF.AddArgument(aSplits);
6199 UpdateImages(aLE, theEImages, aGF, theModifiedEdges);
6201 // update new intersection edges
6202 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6203 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6206 UpdateImages(aLAValid, theOEImages, aGF, theModifiedEdges);
6207 UpdateOrigins(aLABounds, theOEOrigins, aGF);
6208 UpdateOrigins(aLABounds, theEdgesOrigins, aGF);
6209 UpdateIntersectedEdges(aLABounds, theETrimEInf, aGF);
6211 // update the EdgesToAvoid with the splits
6212 TopTools_IndexedMapOfShape aNewEdges;
6213 const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek(aSplits);
6215 TopTools_ListIteratorOfListOfShape aItSpIm(*pSplitsIm);
6216 for (; aItSpIm.More(); aItSpIm.Next()) {
6217 TopExp::MapShapes(aItSpIm.Value(), TopAbs_EDGE, aNewEdges);
6221 // Rebuild the map of edges to avoid, using the intersection results
6222 TopTools_IndexedMapOfShape aMEAvoid;
6223 // GF's data structure
6224 const BOPDS_PDS& pDS = aGF.PDS();
6226 aNbE = theEdgesToAvoid.Extent();
6227 for (i = 1; i <= aNbE; ++i)
6229 const TopoDS_Shape& aE = theEdgesToAvoid(i);
6230 const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
6232 // Only untouched and fully coinciding edges should be kept in the avoid map
6233 Standard_Boolean bKeep = aLEIm.IsEmpty();
6234 if (aLEIm.Extent() == 1 && aE.IsSame(aLEIm.First()))
6236 const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(pDS->Index(aE));
6237 if (aLPB.Extent() == 1)
6239 const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
6240 const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock(aPB);
6243 const BOPDS_ListOfPaveBlock& aLPBCB = aCB->PaveBlocks();
6244 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
6245 for (; aItLPB.More(); aItLPB.Next())
6247 if (pDS->PaveBlocks(aItLPB.Value()->OriginalEdge()).Extent() > 1)
6250 bKeep = !aItLPB.More();
6257 // keep the original edge
6262 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6263 for (; aItLEIm.More(); aItLEIm.Next())
6265 const TopoDS_Shape& aEIm = aItLEIm.Value();
6266 if (!aNewEdges.Contains(aEIm))
6270 theEdgesToAvoid = aMEAvoid;
6273 //=======================================================================
6274 //function : TrimNewIntersectionEdges
6276 //=======================================================================
6277 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
6278 const TopTools_DataMapOfShapeListOfShape& theEETrim,
6279 const TopTools_MapOfShape& theMVBounds,
6280 TopTools_MapOfShape& theMECheckExt,
6281 TopTools_DataMapOfShapeListOfShape& theEImages,
6282 TopTools_MapOfShape& theMEB,
6283 TopTools_MapOfShape& theMVOld,
6284 TopTools_MapOfShape& theMENew,
6285 TopTools_DataMapOfShapeListOfShape& theDMEOr,
6286 TopTools_DataMapOfShapeListOfShape& theMELF)
6288 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6289 aIt.Initialize(theLE);
6290 for (; aIt.More(); aIt.Next()) {
6291 const TopoDS_Shape& aE = aIt.Value();
6293 Standard_Boolean bCheckExt = theMECheckExt.Remove(aE);
6295 Standard_Boolean bOld = theEETrim.IsBound(aE);
6297 const TopTools_ListOfShape& aLET = theEETrim.Find(aE);
6298 aIt1.Initialize(aLET);
6299 for (; aIt1.More(); aIt1.Next()) {
6300 const TopoDS_Shape& aET = aIt1.Value();
6302 TopExp_Explorer aExpV(aET, TopAbs_VERTEX);
6303 for (; aExpV.More(); aExpV.Next()) {
6304 const TopoDS_Shape& aV = aExpV.Current();
6310 if (!theEImages.IsBound(aE)) {
6314 TopTools_ListOfShape& aLEIm = theEImages.ChangeFind(aE);
6315 if (aLEIm.IsEmpty()) {
6316 theEImages.UnBind(aE);
6321 TopTools_MapOfShape aMEVBounds;
6323 if (aLEIm.Extent() > 1) {
6324 TopTools_IndexedMapOfShape aMV;
6326 BOPAlgo_Builder aGFE;
6327 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6328 for (; aItLEIm.More(); aItLEIm.Next()) {
6329 const TopoDS_Shape& aEIm = aItLEIm.Value();
6330 aGFE.AddArgument(aEIm);
6331 TopExp::MapShapes(aEIm, TopAbs_VERTEX, aMV);
6334 // add two bounding vertices of this edge to the operation
6335 TopoDS_Vertex aV1, aV2;
6336 TopExp::Vertices(TopoDS::Edge(aE), aV1, aV2);
6338 aGFE.AddArgument(aV1);
6339 aGFE.AddArgument(aV2);
6344 if (!aGFE.HasErrors()) {
6345 // get images of bounding vertices to remove splits containing them
6346 // in case some of the bounding edges has been interfered
6347 // during operation it is necessary to update their images as well
6348 Standard_Integer iV, aNbV = aMV.Extent();
6349 for (iV = 1; iV <= aNbV; ++iV) {
6350 const TopoDS_Shape& aV = aMV(iV);
6351 if (theMVBounds.Contains(aV) || aV.IsSame(aV1) || aV.IsSame(aV2)) {
6352 const TopTools_ListOfShape& aLVIm = aGFE.Modified(aV);
6353 aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
6357 aCEIm = aGFE.Shape();
6361 aCEIm = aLEIm.First();
6366 TopExp_Explorer aExp(aCEIm, TopAbs_EDGE);
6367 for (; aExp.More(); aExp.Next()) {
6368 const TopoDS_Shape& aEIm = aExp.Current();
6370 // check the split not to contain bounding vertices
6371 TopoDS_Iterator aItV(aEIm);
6372 for (; aItV.More(); aItV.Next()) {
6373 const TopoDS_Shape& aV = aItV.Value();
6374 if (aMEVBounds.Contains(aV) || theMVBounds.Contains(aV)) {
6382 theDMEOr.Bound(aEIm, TopTools_ListOfShape())->Append(aE);
6386 if (aLEIm.IsEmpty()) {
6387 theEImages.UnBind(aE);
6390 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6391 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6392 for (; aItLEIm.More(); aItLEIm.Next()) {
6393 const TopoDS_Shape& aEIm = aItLEIm.Value();
6394 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6396 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6398 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6399 for (; aItLF.More(); aItLF.Next()) {
6400 AppendToList(*pLFEIm, aItLF.Value());
6404 theMECheckExt.Add(aEIm);
6414 //=======================================================================
6415 //function : IntersectEdges
6416 //purpose : Intersecting the trimmed edges to avoid self-intersections
6417 //=======================================================================
6418 void IntersectEdges(const TopTools_ListOfShape& theLA,
6419 const TopTools_ListOfShape& theLE,
6420 const TopTools_MapOfShape& theMVBounds,
6421 const TopTools_MapOfShape& theVertsToAvoid,
6422 TopTools_MapOfShape& theMENew,
6423 TopTools_MapOfShape& theMECheckExt,
6424 TopTools_DataMapOfShapeListOfShape& theEImages,
6425 TopTools_MapOfShape& theModifiedEdges,
6426 TopTools_DataMapOfShapeListOfShape& theDMEOr,
6427 TopTools_DataMapOfShapeListOfShape& theMELF,
6428 TopoDS_Shape& theSplits)
6430 BOPAlgo_Builder aGFA;
6431 aGFA.SetArguments(theLA);
6433 if (aGFA.HasErrors()) {
6434 // just copy input to the result
6435 TopoDS_Compound aSp;
6437 aBB.MakeCompound(aSp);
6438 TopTools_ListIteratorOfListOfShape anIt(theLA);
6439 for (; anIt.More(); anIt.Next()) {
6440 const TopoDS_Shape& aE = anIt.Value();
6447 UpdateImages(theLE, theEImages, aGFA, theModifiedEdges);
6449 // compound of valid splits
6450 theSplits = aGFA.Shape();
6452 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6454 // prepare list of edges to update
6455 TopTools_ListOfShape aLEInput;
6456 for (aIt.Initialize(theLA); aIt.More(); aIt.Next())
6458 TopExp_Explorer anExpE(aIt.Value(), TopAbs_EDGE);
6459 for (; anExpE.More(); anExpE.Next())
6460 aLEInput.Append(anExpE.Current());
6464 aIt.Initialize(aLEInput);
6465 for (; aIt.More(); aIt.Next()) {
6466 const TopoDS_Shape& aE = aIt.Value();
6467 if (!theMENew.Contains(aE))
6470 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
6471 if (aLEIm.IsEmpty())
6474 theMENew.Remove(aE);
6475 aIt1.Initialize(aLEIm);
6476 for (; aIt1.More(); aIt1.Next())
6477 theMENew.Add(aIt1.Value());
6480 // update edges after intersection for extended checking
6481 aIt.Initialize(aLEInput);
6482 for (; aIt.More(); aIt.Next()) {
6483 const TopoDS_Shape& aE = aIt.Value();
6484 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
6485 if (aLEIm.IsEmpty()) {
6489 if (theMECheckExt.Contains(aE)) {
6490 aIt1.Initialize(aLEIm);
6491 for (; aIt1.More(); aIt1.Next()) {
6492 theMECheckExt.Add(aIt1.Value());
6494 theMECheckExt.Remove(aE);
6497 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6498 aIt1.Initialize(aLEIm);
6499 for (; aIt1.More(); aIt1.Next()) {
6500 const TopoDS_Shape& aEIm = aIt1.Value();
6501 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6503 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6505 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6506 for (; aItLF.More(); aItLF.Next()) {
6507 AppendToList(*pLFEIm, aItLF.Value());
6512 TopTools_MapOfShape aMEInv;
6513 GetInvalidEdges(theVertsToAvoid, theMVBounds, aGFA, aMEInv);
6514 if (aMEInv.Extent()) {
6516 TopoDS_Compound aSp;
6518 aBB.MakeCompound(aSp);
6519 TopExp_Explorer aExp(theSplits, TopAbs_EDGE);
6520 for (; aExp.More(); aExp.Next()) {
6521 const TopoDS_Shape& aE = aExp.Current();
6522 if (!aMEInv.Contains(aE)) {
6530 UpdateOrigins(aLEInput, theDMEOr, aGFA);
6533 //=======================================================================
6534 //function : GetBounds
6535 //purpose : Getting edges from the splits of offset faces
6536 //=======================================================================
6537 void GetBounds(const TopTools_ListOfShape& theLFaces,
6538 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6539 const TopTools_MapOfShape& theMEB,
6540 TopoDS_Shape& theBounds)
6543 // Make compound of edges contained in the splits of faces
6544 TopoDS_Compound aBounds;
6545 aBB.MakeCompound(aBounds);
6547 TopTools_MapOfShape aMFence;
6549 TopTools_ListIteratorOfListOfShape aItLF(theLFaces);
6550 for (; aItLF.More(); aItLF.Next())
6552 const TopTools_ListOfShape* pLFIm = theFImages.Seek(aItLF.Value());
6555 TopTools_ListIteratorOfListOfShape aIt(*pLFIm);
6556 for (; aIt.More(); aIt.Next())
6558 const TopoDS_Shape& aFIm = aIt.Value();
6560 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
6561 for (; aExpE.More(); aExpE.Next())
6563 const TopoDS_Shape& aEIm = aExpE.Current();
6564 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6565 aBB.Add(aBounds, aEIm);
6570 theBounds = aBounds;
6573 //=======================================================================
6574 //function : GetBoundsToUpdate
6575 //purpose : Get bounding edges that should be updated
6576 //=======================================================================
6577 void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
6578 const TopTools_DataMapOfShapeListOfShape& theOEImages,
6579 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6580 const TopTools_MapOfShape& theMEB,
6581 TopTools_ListOfShape& theLABounds,
6582 TopTools_ListOfShape& theLAValid,
6583 TopoDS_Shape& theBounds,
6584 Handle(BRepAlgo_AsDes)& theAsDes)
6587 TopoDS_Compound aBounds;
6589 aBB.MakeCompound(aBounds);
6591 TopTools_MapOfShape aMAValid, aMFence;
6593 TopTools_ListIteratorOfListOfShape aItLF(theLF);
6594 for (; aItLF.More(); aItLF.Next()) {
6595 const TopoDS_Shape& aF = aItLF.Value();
6597 TopTools_IndexedMapOfShape aMDE;
6598 const TopTools_ListOfShape& aLFDes = theAsDes->Descendant(aF);
6599 TopTools_ListIteratorOfListOfShape aItLFDes(aLFDes);
6600 for (; aItLFDes.More(); aItLFDes.Next()) {
6601 const TopoDS_Shape& aED = aItLFDes.Value();
6602 const TopTools_ListOfShape *pLEDIm = theOEImages.Seek(aED);
6608 TopTools_ListIteratorOfListOfShape aItLEDIm(*pLEDIm);
6609 for (; aItLEDIm.More(); aItLEDIm.Next()) {
6610 const TopoDS_Shape& aEDIm = aItLEDIm.Value();
6615 Standard_Integer j, aNbE = aMDE.Extent();
6616 for (j = 1; j <= aNbE; ++j) {
6617 const TopoDS_Edge& aEIm = TopoDS::Edge(aMDE(j));
6619 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6620 aBB.Add(aBounds, aEIm);
6621 theLABounds.Append(aEIm);
6624 const TopTools_ListOfShape *pLO = theOEOrigins.Seek(aEIm);
6626 TopTools_ListIteratorOfListOfShape aItLO(*pLO);
6627 for (; aItLO.More(); aItLO.Next()) {
6628 const TopoDS_Shape& aEO = aItLO.Value();
6630 if (aMAValid.Add(aEO)) {
6631 theLAValid.Append(aEO);
6636 if (aMAValid.Add(aEIm)) {
6637 theLAValid.Append(aEIm);
6642 theBounds = aBounds;
6645 //=======================================================================
6646 //function : GetInvalidEdgesByBounds
6647 //purpose : Filter new splits by intersection with bounds
6648 //=======================================================================
6649 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
6650 const TopoDS_Shape& theBounds,
6651 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6652 const TopoDS_Shape& theSolids,
6653 const TopTools_IndexedMapOfShape& theInvEdges,
6654 const TopTools_MapOfShape& theMVOld,
6655 const TopTools_MapOfShape& theMENew,
6656 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
6657 const TopTools_DataMapOfShapeListOfShape& theMELF,
6658 const TopTools_DataMapOfShapeListOfShape& theEImages,
6659 const TopTools_MapOfShape& theMECheckExt,
6660 const TopTools_MapOfShape& theMEInvOnArt,
6661 Handle(IntTools_Context)& theCtx,
6662 TopTools_MapOfShape& theVertsToAvoid,
6663 TopTools_MapOfShape& theMEInv)
6665 // map splits to check the vertices of edges
6666 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6667 TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6669 BOPAlgo_Section aSec;
6670 aSec.AddArgument(theSplits);
6671 aSec.AddArgument(theBounds);
6676 TopTools_IndexedMapOfShape aMVInv;
6677 // vertices to check additionally by classification relatively to solid
6678 TopTools_MapOfShape aMVCheckAdd;
6679 // collect parts for removal
6680 const BOPDS_PDS& pDS = aSec.PDS();
6682 // check edge/edge intersections
6683 const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
6684 Standard_Integer i, aNb = aEEs.Length();
6685 for (i = 0; i < aNb; ++i) {
6686 const BOPDS_InterfEE& aEE = aEEs(i);
6688 const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1());
6689 const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2());
6691 if (!aEE.HasIndexNew()) {
6692 if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) {
6698 if (theInvEdges.Contains(aE2)) {
6702 if (theMEInvOnArt.Contains(aE2)) {
6703 // avoid checking of the vertices of the split edge intersected by
6704 // the invalid edge from artificial face
6705 TopoDS_Vertex aV1, aV2;
6706 TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2);
6707 if (aDMVE.Contains(aV1) && aDMVE.Contains(aV2)) {
6712 // add vertices of all images of the edge from splits for checking
6713 const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1);
6714 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr);
6715 for (; aItLEOr.More(); aItLEOr.Next()) {
6716 const TopoDS_Shape& aEOr = aItLEOr.Value();
6718 const TopTools_ListOfShape *pLEIm = theEImages.Seek(aEOr);
6721 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6722 for (; aItLEIm.More(); aItLEIm.Next()) {
6723 const TopoDS_Shape& aEIm = aItLEIm.Value();
6725 TopoDS_Iterator aItV(aEIm);
6726 for (; aItV.More(); aItV.Next()) {
6727 const TopoDS_Shape& aV = aItV.Value();
6728 if (!theMVOld.Contains(aV)) {
6730 aMVCheckAdd.Add(aV);
6737 // to avoid unnecessary filling of parts due to extra trim of the edges
6738 // process Edge/Edge interferences of type EDGE, i.e. common blocks and check
6739 // not the bounding vertices of the edges, but check the edge itself
6740 // to be lying on some face
6742 // all common blocks are contained in the result of SECTION operation
6743 // between sets of edges
6744 const TopoDS_Shape& aSecR = aSec.Shape();
6746 TopTools_IndexedMapOfShape aMSSec;
6747 TopExp::MapShapes(aSecR, aMSSec);
6749 const TopTools_DataMapOfShapeListOfShape& anIm = aSec.Images();
6750 for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
6752 const TopoDS_Shape& aE = aExp.Current();
6753 if (aSec.IsDeleted(aE)) {
6754 // no common blocks for this edge
6758 const TopTools_ListOfShape* pLEIm = anIm.Seek(aE);
6760 // no splits, i.e. completely coincides with some edge from boundary
6764 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6765 for (; aItLEIm.More(); aItLEIm.Next()) {
6766 const TopoDS_Shape& aEIm = aItLEIm.Value();
6767 if (!aMSSec.Contains(aEIm)) {
6768 // the edge included in section only partially.
6769 // the part not included in section may be excessive
6771 // check vertices of this edge - if one of them is new
6772 // the edge might be removed
6773 TopoDS_Vertex aV1, aV2;
6774 TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2);
6775 if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) {
6776 // add this edge for checking by making new vertex in the middle of the edge
6779 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l);
6780 BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion());
6781 // and adding this vertex for checking
6782 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
6790 // Add for check also the edges created from common between splits
6791 // of offset faces edges not connected to any invalidity.
6792 // These edges may also accidentally fill some part.
6793 TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt);
6794 for (; aItM.More(); aItM.Next()) {
6795 const TopoDS_Shape& aE = aItM.Value();
6797 // make new vertex in the middle of the edge
6800 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l);
6801 BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion());
6802 // add this vertex for checking
6803 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
6807 // add for check also the vertices connected only to new or old edges
6808 aNb = aDMVE.Extent();
6809 for (i = 1; i <= aNb; ++i) {
6810 const TopoDS_Shape& aV = aDMVE.FindKey(i);
6811 if (theMVOld.Contains(aV)) {
6815 Standard_Boolean bNew = Standard_False, bOld = Standard_False;
6816 const TopTools_ListOfShape& aLEx = aDMVE(i);
6817 TopTools_ListIteratorOfListOfShape aIt(aLEx);
6818 for (; aIt.More(); aIt.Next()) {
6819 const TopoDS_Shape& aE = aIt.Value();
6820 if (theMECheckExt.Contains(aE)) {
6824 if (theMENew.Contains(aE)) {
6825 bNew = Standard_True;
6828 bOld = Standard_True;
6836 if (!bNew || !bOld) {
6838 aMVCheckAdd.Remove(aV);
6842 // perform the checking of the vertices
6843 Standard_Integer iv, aNbIV = aMVInv.Extent();
6844 for (iv = 1; iv <= aNbIV; ++iv) {
6845 const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv));
6846 if (theMVOld.Contains(aV)) {
6850 const TopTools_ListOfShape* pLEInv = aDMVE.Seek(aV);
6854 // find faces by the edges to check the vertex
6855 TopTools_IndexedMapOfShape aMF;
6856 TopTools_ListIteratorOfListOfShape aItLE(*pLEInv);
6857 for (; aItLE.More(); aItLE.Next()) {
6858 const TopoDS_Shape& aE = aItLE.Value();
6859 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
6860 TopTools_ListIteratorOfListOfShape aItLF(aLF);
6861 for (; aItLF.More(); aItLF.Next()) {
6862 aMF.Add(aItLF.Value());
6866 // check the vertex to belong to some split of the faces
6867 Standard_Boolean bInvalid = Standard_True;
6869 Standard_Integer aNbF = aMF.Extent();
6870 for (i = 1; i <= aNbF && bInvalid; ++i) {
6871 const TopoDS_Face& aF = TopoDS::Face(aMF(i));
6872 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
6874 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
6875 for (; aItLF.More() && bInvalid; aItLF.Next()) {
6876 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
6877 TopExp_Explorer aExp(aFIm, TopAbs_VERTEX);
6878 for (; aExp.More() && bInvalid; aExp.Next()) {
6879 const TopoDS_Shape& aVF = aExp.Current();
6880 bInvalid = !aVF.IsSame(aV);
6885 Standard_Real U, V, aTol;
6886 Standard_Integer iStatus = theCtx->ComputeVF(aV, aF, U, V, aTol);
6888 // classify the point relatively faces
6889 gp_Pnt2d aP2d(U, V);
6890 aItLF.Initialize(aLFIm);
6891 for (; aItLF.More() && bInvalid; aItLF.Next()) {
6892 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
6893 bInvalid = !theCtx->IsPointInOnFace(aFIm, aP2d);
6899 if (bInvalid && aMVCheckAdd.Contains(aV)) {
6900 // the vertex is invalid for all faces
6901 // check the same vertex for the solids
6902 const gp_Pnt& aP = BRep_Tool::Pnt(aV);
6903 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
6905 TopExp_Explorer aExpS(theSolids, TopAbs_SOLID);
6906 for (; aExpS.More() && bInvalid; aExpS.Next()) {
6907 const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current());
6908 BRepClass3d_SolidClassifier& aSC = theCtx->SolidClassifier(aSol);
6909 aSC.Perform(aP, aTolV);
6910 bInvalid = (aSC.State() == TopAbs_OUT);
6915 theVertsToAvoid.Add(aV);
6916 aItLE.Initialize(*pLEInv);
6917 for (; aItLE.More(); aItLE.Next()) {
6918 theMEInv.Add(aItLE.Value());
6924 //=======================================================================
6925 //function : FilterSplits
6926 //purpose : Filter the images of edges from the invalid edges
6927 //=======================================================================
6928 void FilterSplits(const TopTools_ListOfShape& theLE,
6929 const TopTools_MapOfShape& theMEFilter,
6930 const Standard_Boolean theIsInv,
6931 TopTools_DataMapOfShapeListOfShape& theEImages,
6932 TopoDS_Shape& theSplits)
6934 TopoDS_Compound aSplits;
6935 BRep_Builder().MakeCompound(aSplits);
6936 TopTools_MapOfShape aMFence;
6938 TopTools_ListIteratorOfListOfShape aItLE(theLE);
6939 for (; aItLE.More(); aItLE.Next())
6941 const TopoDS_Shape& aE = aItLE.Value();
6942 TopTools_ListOfShape *pLEIm = theEImages.ChangeSeek(aE);
6946 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
6947 for (; aItLEIm.More();)
6949 const TopoDS_Shape& aEIm = aItLEIm.Value();
6950 if (theMEFilter.Contains(aEIm) == theIsInv)
6952 pLEIm->Remove(aItLEIm);
6956 if (aMFence.Add(aEIm))
6957 BRep_Builder().Add(aSplits, aEIm);
6961 if (pLEIm->IsEmpty())
6962 theEImages.UnBind(aE);
6964 theSplits = aSplits;
6967 //=======================================================================
6968 //function : UpdateNewIntersectionEdges
6969 //purpose : Updating the maps of images and origins of the offset edges
6970 //=======================================================================
6971 void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
6972 const TopTools_DataMapOfShapeListOfShape& theMELF,
6973 const TopTools_DataMapOfShapeListOfShape& theEImages,
6974 const TopTools_IndexedMapOfShape& theInvEdges,
6975 const TopTools_MapOfShape& theInvertedEdges,
6976 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
6977 TopTools_DataMapOfShapeListOfShape& theOEImages,
6978 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6979 TopTools_DataMapOfShapeShape& theETrimEInf,
6980 TopTools_DataMapOfShapeListOfShape& theEETrim,
6981 TopTools_MapOfShape& theModifiedEdges,
6982 Handle(BRepAlgo_AsDes)& theAsDes)
6984 TopTools_ListOfShape aLEImEmpty;
6985 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6986 // update global maps of images and origins with new splits
6987 aIt.Initialize(theLE);
6988 for (; aIt.More(); aIt.Next()) {
6989 const TopoDS_Shape& aE = aIt.Value();
6991 if (!theEImages.IsBound(aE)) {
6992 TopTools_ListOfShape* pLET = theEETrim.ChangeSeek(aE);
6997 TopTools_ListIteratorOfListOfShape aItLET(*pLET);
6998 for (; aItLET.More();) {
6999 const TopoDS_Shape& aET = aItLET.Value();
7000 if (!theInvEdges.Contains(aET) && !theInvertedEdges.Contains(aET)) {
7001 pLET->Remove(aItLET);
7008 if (pLET->IsEmpty()) {
7013 const TopTools_ListOfShape& aLENew =
7014 theEImages.IsBound(aE) ? theEImages.Find(aE) : aLEImEmpty;
7016 // save connection to untrimmed edge for the next steps
7017 aIt1.Initialize(aLENew);
7018 for (; aIt1.More(); aIt1.Next()) {
7019 const TopoDS_Shape& aET = aIt1.Value();
7020 theETrimEInf.Bind(aET, aE);
7021 theModifiedEdges.Add(aET);
7024 // check if it is existing edge
7025 if (!theEETrim.IsBound(aE)) {
7026 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
7028 // add this edge to AsDes
7029 aIt1.Initialize(aLF);
7030 for (; aIt1.More(); aIt1.Next()) {
7031 const TopoDS_Shape& aF = aIt1.Value();
7032 theAsDes->Add(aF, aE);
7035 // add aE to the images
7036 theOEImages.Bind(aE, aLENew);
7037 theModifiedEdges.Add(aE);
7040 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7041 for (; aItNew.More(); aItNew.Next()) {
7042 const TopoDS_Shape& aENew = aItNew.Value();
7043 if (theOEOrigins.IsBound(aENew)) {
7044 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7045 AppendToList(aEOrigins, aE);
7048 TopTools_ListOfShape aEOrigins;
7049 aEOrigins.Append(aE);
7050 theOEOrigins.Bind(aENew, aEOrigins);
7054 // update connection to initial origins
7055 if (theEdgesOrigins.IsBound(aE)) {
7056 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aE);
7057 aIt1.Initialize(aLENew);
7058 for (; aIt1.More(); aIt1.Next()) {
7059 const TopoDS_Shape& aENew = aIt1.Value();
7060 if (theEdgesOrigins.IsBound(aENew)) {
7061 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7062 TopTools_ListIteratorOfListOfShape aItOrInit(aLEOrInit);
7063 for (; aItOrInit.More(); aItOrInit.Next()) {
7064 const TopoDS_Shape& aEOr = aItOrInit.Value();
7065 AppendToList(aLENewOr, aEOr);
7069 theEdgesOrigins.Bind(aENew, aLEOrInit);
7078 const TopTools_ListOfShape& aLEOld = theEETrim.Find(aE);
7080 // list of initial origins
7081 TopTools_ListOfShape anInitOrigins;
7083 // it is necessary to replace the old edges with new ones
7084 aIt1.Initialize(aLEOld);
7085 for (; aIt1.More(); aIt1.Next()) {
7086 const TopoDS_Shape& aEOld = aIt1.Value();
7088 if (theOEOrigins.IsBound(aEOld)) {
7090 const TopTools_ListOfShape& aEOrigins = theOEOrigins.Find(aEOld);
7092 TopTools_ListIteratorOfListOfShape aItOr(aEOrigins);
7093 for (; aItOr.More(); aItOr.Next()) {
7094 const TopoDS_Shape& aEOr = aItOr.Value();
7096 theModifiedEdges.Add(aEOr);
7098 TopTools_ListOfShape& aEImages = theOEImages.ChangeFind(aEOr);
7100 // remove old edge from images
7101 TopTools_ListIteratorOfListOfShape aItIm(aEImages);
7102 for (; aItIm.More(); ) {
7103 const TopoDS_Shape& aEIm = aItIm.Value();
7104 if (aEIm.IsSame(aEOld)) {
7105 aEImages.Remove(aItIm);
7113 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7114 for (; aItNew.More(); aItNew.Next()) {
7115 const TopoDS_Shape& aENew = aItNew.Value();
7116 AppendToList(aEImages, aENew);
7117 if (theOEOrigins.IsBound(aENew)) {
7118 TopTools_ListOfShape& aENewOrigins = theOEOrigins.ChangeFind(aENew);
7119 AppendToList(aENewOrigins, aEOr);
7122 TopTools_ListOfShape aENewOrigins;
7123 aENewOrigins.Append(aEOr);
7124 theOEOrigins.Bind(aENew, aENewOrigins);
7131 theOEImages.Bind(aEOld, aLENew);
7133 theModifiedEdges.Add(aEOld);
7136 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7137 for (; aItNew.More(); aItNew.Next()) {
7138 const TopoDS_Shape& aENew = aItNew.Value();
7139 if (theOEOrigins.IsBound(aENew)) {
7140 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7141 AppendToList(aEOrigins, aEOld);
7144 TopTools_ListOfShape aEOrigins;
7145 aEOrigins.Append(aEOld);
7146 theOEOrigins.Bind(aENew, aEOrigins);
7151 // update connection to initial shape
7152 if (theEdgesOrigins.IsBound(aEOld)) {
7153 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aEOld);
7154 TopTools_ListIteratorOfListOfShape aItEOrInit(aLEOrInit);
7155 for (; aItEOrInit.More(); aItEOrInit.Next()) {
7156 const TopoDS_Shape& aEOrInit = aItEOrInit.Value();
7157 AppendToList(anInitOrigins, aEOrInit);
7162 if (anInitOrigins.Extent()) {
7163 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7164 for (; aItNew.More(); aItNew.Next()) {
7165 const TopoDS_Shape& aENew = aItNew.Value();
7166 if (theEdgesOrigins.IsBound(aENew)) {
7167 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7168 TopTools_ListIteratorOfListOfShape aItOrInit(anInitOrigins);
7169 for (; aItOrInit.More(); aItOrInit.Next()) {
7170 const TopoDS_Shape& aEOr = aItOrInit.Value();
7171 AppendToList(aLENewOr, aEOr);
7175 theEdgesOrigins.Bind(aENew, anInitOrigins);
7182 //=======================================================================
7183 //function : FillGaps
7184 //purpose : Fill possible gaps (holes) in the splits of the offset faces
7185 //=======================================================================
7186 void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
7188 Standard_Integer aNbF = theFImages.Extent();
7192 // Check the splits of offset faces on the free edges and fill the gaps (holes)
7193 // in created splits, otherwise the closed volume will not be possible to create.
7195 // Map the splits of faces to find free edges
7196 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
7197 for (Standard_Integer i = 1; i <= aNbF; ++i)
7199 TopTools_ListIteratorOfListOfShape itLF(theFImages(i));
7200 for (; itLF.More(); itLF.Next())
7201 TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
7204 // Analyze images of each offset face on the presence of free edges
7205 // and try to fill the holes
7206 for (Standard_Integer i = 1; i <= aNbF; ++i)
7208 TopTools_ListOfShape& aLFImages = theFImages(i);
7209 if (aLFImages.IsEmpty())
7212 // Collect all edges from the splits
7213 TopoDS_Compound anEdges;
7214 BRep_Builder().MakeCompound(anEdges);
7216 // Collect all free edges into a map with reverted orientation
7217 TopTools_MapOfOrientedShape aFreeEdgesMap;
7218 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7219 for (; itLF.More(); itLF.Next())
7221 const TopoDS_Shape& aFIm = itLF.Value();
7222 TopExp_Explorer anExpE(aFIm, TopAbs_EDGE);
7223 for (; anExpE.More(); anExpE.Next())
7225 const TopoDS_Shape& aE = anExpE.Current();
7226 if (aE.Orientation() != TopAbs_FORWARD &&
7227 aE.Orientation() != TopAbs_REVERSED)
7231 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey(aE);
7232 if (aLF.Extent() == 1)
7233 aFreeEdgesMap.Add(aE.Reversed());
7235 BRep_Builder().Add(anEdges, aE);
7239 if (aFreeEdgesMap.IsEmpty())
7243 // Free edges are found - fill the gaps by creating new splits
7244 // of the face using these free edges
7245 const TopoDS_Shape& aF = theFImages.FindKey(i);
7247 // Build new splits using all kept edges and among new splits
7248 // find those containing free edges
7249 TopTools_ListOfShape aLFNew;
7250 TopTools_DataMapOfShapeShape aDummy;
7252 BuildSplitsOfFace(TopoDS::Face(aF), anEdges, aDummy, aLFNew);
7254 // Find faces filling holes
7255 itLF.Initialize(aLFNew);
7256 for (; itLF.More(); itLF.Next())
7258 const TopoDS_Shape& aFNew = itLF.Value();
7259 TopExp_Explorer anExpE(aFNew, TopAbs_EDGE);
7260 for (; anExpE.More(); anExpE.Next())
7262 const TopoDS_Shape& aE = anExpE.Current();
7263 if (aFreeEdgesMap.Contains(aE))
7265 // Add face to splits
7266 aLFImages.Append(aFNew);
7274 //=======================================================================
7275 //function : FillHistory
7276 //purpose : Saving obtained results in history tools
7277 //=======================================================================
7278 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
7279 const TopTools_DataMapOfShapeListOfShape& theEImages,
7280 BRepAlgo_Image& theImage)
7282 Standard_Integer aNbF = theFImages.Extent();
7287 // Build compound of faces to see preliminary result
7288 TopoDS_Compound aDFaces;
7289 BRep_Builder().MakeCompound(aDFaces);
7292 // Map of kept edges
7293 TopTools_IndexedMapOfShape anEdgesMap;
7295 // Fill history for faces
7296 for (Standard_Integer i = 1; i <= aNbF; ++i)
7298 const TopTools_ListOfShape& aLFImages = theFImages(i);
7299 if (aLFImages.IsEmpty())
7302 // Add the splits to history map
7303 const TopoDS_Shape& aF = theFImages.FindKey(i);
7304 if (theImage.HasImage(aF))
7305 theImage.Add(aF, aLFImages);
7307 theImage.Bind(aF, aLFImages);
7309 // Collect edges from splits
7310 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7311 for (; itLF.More(); itLF.Next())
7313 const TopoDS_Shape& aFIm = itLF.Value();
7314 TopExp::MapShapes(aFIm, TopAbs_EDGE, anEdgesMap);
7317 BRep_Builder().Add(aDFaces, aFIm);
7322 // Fill history for edges (iteration by the map is safe because the
7323 // order is not important here)
7324 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(theEImages);
7325 for (; aItEIm.More(); aItEIm.Next())
7327 const TopoDS_Shape& aE = aItEIm.Key();
7328 const TopTools_ListOfShape& aLEIm = aItEIm.Value();
7330 Standard_Boolean bHasImage = theImage.HasImage(aE);
7331 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
7332 for (; aItLE.More(); aItLE.Next())
7334 const TopoDS_Shape& aEIm = aItLE.Value();
7335 if (anEdgesMap.Contains(aEIm))
7339 theImage.Add(aE, aEIm);
7343 theImage.Bind(aE, aEIm);
7344 bHasImage = Standard_True;
7351 //=======================================================================
7352 //function : ProcessMicroEdge
7353 //purpose : Checking if the edge is micro edge
7354 //=======================================================================
7355 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
7356 const Handle(IntTools_Context)& theCtx)
7358 TopoDS_Vertex aV1, aV2;
7359 TopExp::Vertices(theEdge, aV1, aV2);
7360 if (aV1.IsNull() || aV2.IsNull()) {
7361 return Standard_False;
7364 Standard_Boolean bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx);
7365 if (bMicro && BRepAdaptor_Curve(theEdge).GetType() == GeomAbs_Line) {
7366 Standard_Real aLen = BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
7367 BRep_Builder().UpdateVertex(aV1, aLen / 2.);
7368 BRep_Builder().UpdateVertex(aV2, aLen / 2.);
7374 //=======================================================================
7375 //function : UpdateOrigins
7376 //purpose : Updating origins
7377 //=======================================================================
7378 void UpdateOrigins(const TopTools_ListOfShape& theLA,
7379 TopTools_DataMapOfShapeListOfShape& theOrigins,
7380 BOPAlgo_Builder& theGF)
7382 TopTools_ListIteratorOfListOfShape aItA(theLA);
7383 for (; aItA.More(); aItA.Next()) {
7384 const TopoDS_Shape& aS = aItA.Value();
7386 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7387 if (aLSIm.IsEmpty()) {
7391 TopTools_ListOfShape aLSEmpt;
7392 TopTools_ListOfShape *pLS = theOrigins.ChangeSeek(aS);
7398 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7399 for (; aIt.More(); aIt.Next()) {
7400 const TopoDS_Shape& aSIm = aIt.Value();
7402 TopTools_ListOfShape *pLSOr = theOrigins.ChangeSeek(aSIm);
7404 // just bind the origins
7405 theOrigins.Bind(aSIm, *pLS);
7409 TopTools_ListIteratorOfListOfShape aIt1(*pLS);
7410 for (; aIt1.More(); aIt1.Next()) {
7411 const TopoDS_Shape& aS1 = aIt1.Value();
7412 AppendToList(*pLSOr, aS1);
7419 //=======================================================================
7420 //function : UpdateImages
7421 //purpose : Updating images of the shapes
7422 //=======================================================================
7423 void UpdateImages(const TopTools_ListOfShape& theLA,
7424 TopTools_DataMapOfShapeListOfShape& theImages,
7425 BOPAlgo_Builder& theGF,
7426 TopTools_MapOfShape& theModified)
7428 TopTools_ListIteratorOfListOfShape aIt(theLA);
7429 for (; aIt.More(); aIt.Next())
7431 const TopoDS_Shape& aS = aIt.Value();
7433 TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS);
7436 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7439 theImages.Bind(aS, aLSIm);
7440 theModified.Add(aS);
7445 TopTools_MapOfShape aMFence;
7446 TopTools_ListOfShape aLSImNew;
7448 Standard_Boolean bModified = Standard_False;
7450 // check modifications of the images
7451 TopTools_ListIteratorOfListOfShape aIt1(*pLSIm);
7452 for (; aIt1.More(); aIt1.Next())
7454 const TopoDS_Shape& aSIm = aIt1.Value();
7455 bModified |= TakeModified(aSIm, theGF.Images(), aLSImNew, &aMFence);
7461 theModified.Add(aS);
7466 //=======================================================================
7467 //function : UpdateIntersectedEdges
7468 //purpose : Saving connection from trimmed edges to not trimmed ones
7469 //=======================================================================
7470 void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
7471 TopTools_DataMapOfShapeShape& theETrimEInf,
7472 BOPAlgo_Builder& theGF)
7474 TopTools_ListIteratorOfListOfShape aItA(theLA);
7475 for (; aItA.More(); aItA.Next()) {
7476 const TopoDS_Shape& aS = aItA.Value();
7478 const TopoDS_Shape* pEInf = theETrimEInf.Seek(aS);
7483 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7484 if (aLSIm.IsEmpty()) {
7488 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7489 for (; aIt.More(); aIt.Next()) {
7490 const TopoDS_Shape& aEIm = aIt.Value();
7491 if (!theETrimEInf.IsBound(aEIm)) {
7492 theETrimEInf.Bind(aEIm, *pEInf);
7498 //=======================================================================
7499 //function : FindCommonParts
7500 //purpose : Looking for the parts of type <theType> contained in both lists
7501 //=======================================================================
7502 void FindCommonParts(const TopTools_ListOfShape& theLS1,
7503 const TopTools_ListOfShape& theLS2,
7504 TopTools_ListOfShape& theLSC,
7505 const TopAbs_ShapeEnum theType)
7507 // map shapes in the first list
7508 TopTools_IndexedMapOfShape aMS1;
7509 TopTools_ListIteratorOfListOfShape aIt(theLS1);
7510 for (; aIt.More(); aIt.Next()) {
7511 const TopoDS_Shape& aS = aIt.Value();
7512 TopExp::MapShapes(aS, theType, aMS1);
7515 if (aMS1.IsEmpty()) {
7519 TopTools_MapOfShape aMFence;
7520 // check for such shapes in the other list
7521 aIt.Initialize(theLS2);
7522 for (; aIt.More(); aIt.Next()) {
7523 const TopoDS_Shape& aS = aIt.Value();
7525 TopExp_Explorer aExp(aS, theType);
7526 for(; aExp.More(); aExp.Next()) {
7527 const TopoDS_Shape& aST = aExp.Current();
7529 if (aMS1.Contains(aST) && aMFence.Add(aST)) {
7536 //=======================================================================
7537 //function : NbPoints
7538 //purpose : Defines number of sample points to get average direction of the edge
7539 //=======================================================================
7540 Standard_Integer NbPoints(const TopoDS_Edge& theEdge)
7542 Standard_Integer aNbP;
7543 BRepAdaptor_Curve aBAC(theEdge);
7544 switch (aBAC.GetType()) {
7555 //=======================================================================
7556 //function : FindShape
7557 //purpose : Looking for the same sub-shape in the shape
7558 //=======================================================================
7559 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
7560 const TopoDS_Shape& theSWhere,
7561 const BRepOffset_Analyse* theAnalyse,
7562 TopoDS_Shape& theRes)
7564 Standard_Boolean bFound = Standard_False;
7565 TopAbs_ShapeEnum aType = theSWhat.ShapeType();
7566 TopExp_Explorer aExp(theSWhere, aType);
7567 for (; aExp.More(); aExp.Next()) {
7568 const TopoDS_Shape& aS = aExp.Current();
7569 if (aS.IsSame(theSWhat)) {
7571 bFound = Standard_True;
7576 if (!bFound && theAnalyse)
7578 const TopTools_ListOfShape *pLD = theAnalyse->Descendants (theSWhere);
7581 for (TopTools_ListOfShape::Iterator it (*pLD); it.More(); it.Next())
7583 const TopoDS_Shape& aS = it.Value();
7584 if (aS.IsSame (theSWhat))
7587 bFound = Standard_True;
7598 //=======================================================================
7599 //function : AppendToList
7600 //purpose : Add to a list only unique elements
7601 //=======================================================================
7602 void AppendToList(TopTools_ListOfShape& theList,
7603 const TopoDS_Shape& theShape)
7605 TopTools_ListIteratorOfListOfShape aIt(theList);
7606 for (; aIt.More(); aIt.Next()) {
7607 const TopoDS_Shape& aS = aIt.Value();
7608 if (aS.IsSame(theShape)) {
7612 theList.Append(theShape);
7615 //=======================================================================
7616 //function : AddToContainer
7617 //purpose : Set of methods to add a shape into container
7618 //=======================================================================
7619 static void AddToContainer(const TopoDS_Shape& theS,
7620 TopTools_ListOfShape& theList)
7622 theList.Append(theS);
7624 static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7625 TopTools_MapOfShape& theMap)
7627 return theMap.Add(theS);
7629 static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7630 TopTools_IndexedMapOfShape& theMap)
7632 const Standard_Integer aNb = theMap.Extent();
7633 const Standard_Integer anInd = theMap.Add(theS);
7636 static void AddToContainer(const TopoDS_Shape& theS,
7637 TopoDS_Shape& theSOut)
7639 BRep_Builder().Add(theSOut, theS);
7642 //=======================================================================
7643 //function : TakeModified
7644 //purpose : Check if the shape has images in the given images map.
7645 // Puts in the output map either the images or the shape itself.
7646 //=======================================================================
7647 template <class ContainerType, class FenceMapType>
7648 Standard_Boolean TakeModified(const TopoDS_Shape& theS,
7649 const TopTools_DataMapOfShapeListOfShape& theImages,
7650 ContainerType& theContainer,
7651 FenceMapType* theMFence)
7653 const TopTools_ListOfShape *pLSIm = theImages.Seek(theS);
7656 TopTools_ListIteratorOfListOfShape itLSIm(*pLSIm);
7657 for (; itLSIm.More(); itLSIm.Next())
7659 const TopoDS_Shape& aSIm = itLSIm.Value();
7660 if (!theMFence || AddToContainer(aSIm, *theMFence))
7661 AddToContainer(aSIm, theContainer);
7663 return Standard_True;
7667 if (!theMFence || AddToContainer(theS, *theMFence))
7668 AddToContainer(theS, theContainer);
7669 return Standard_False;