1 // Created on: 2016
2 // Created by: Eugeny MALTCHIKOV
3 // Copyright (c) 2016 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
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.
20
21
22 #include <BRepOffset_MakeOffset.hxx>
23
24 #include <Precision.hxx>
25 #include <TopoDS.hxx>
26
27 #include <BRepAlgo_AsDes.hxx>
28 #include <BRepAlgo_Image.hxx>
29
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32
33 #include <BRepLib.hxx>
34 #include <BRepTools.hxx>
35
36 #include <BRepAdaptor_Curve.hxx>
37
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40
41 #include <TopTools_DataMapOfShapeInteger.hxx>
42
43 #include <BRepOffset_Tool.hxx>
44
45 #include <BRepClass3d_SolidClassifier.hxx>
46
47 #include <BOPDS_DS.hxx>
48
49 #include <BOPAlgo_Builder.hxx>
50 #include <BOPAlgo_BuilderFace.hxx>
51 #include <BOPAlgo_MakerVolume.hxx>
52 #include <BOPAlgo_PaveFiller.hxx>
53 #include <BOPAlgo_Section.hxx>
54 #include <BOPAlgo_Splitter.hxx>
55
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_DataMapOfShapeShape.hxx>
58 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
59 #include <TopTools_MapOfOrientedShape.hxx>
60
61 #include <BOPTools_AlgoTools3D.hxx>
62 #include <BOPTools_AlgoTools.hxx>
63 #include <BOPTools_AlgoTools2D.hxx>
64 #include <BOPTools_Set.hxx>
65
66 #include <IntTools_Context.hxx>
67 #include <IntTools_ShrunkRange.hxx>
68
69 #ifdef OFFSET_DEBUG
70 #include <BRepAlgoAPI_Check.hxx>
71 #endif
72
73 typedef NCollection_DataMap<TopoDS_Shape,
74 TopTools_MapOfShape,
75 TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeMapOfShape;
76
77 typedef NCollection_DataMap<TopoDS_Shape,
78 TopTools_IndexedMapOfShape,
79 TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeIndexedMapOfShape;
80
81
82 namespace {
83
84 //=======================================================================
85 //function : AddToContainer
86 //purpose : Set of methods to add a shape into container
87 //=======================================================================
AddToContainer(const TopoDS_Shape & theS,TopTools_ListOfShape & theList)88 static void AddToContainer (const TopoDS_Shape& theS,
89 TopTools_ListOfShape& theList)
90 {
91 theList.Append (theS);
92 }
AddToContainer(const TopoDS_Shape & theS,TopTools_MapOfShape & theMap)93 static Standard_Boolean AddToContainer (const TopoDS_Shape& theS,
94 TopTools_MapOfShape& theMap)
95 {
96 return theMap.Add (theS);
97 }
AddToContainer(const TopoDS_Shape & theS,TopTools_IndexedMapOfShape & theMap)98 static Standard_Boolean AddToContainer (const TopoDS_Shape& theS,
99 TopTools_IndexedMapOfShape& theMap)
100 {
101 const Standard_Integer aNb = theMap.Extent();
102 const Standard_Integer anInd = theMap.Add (theS);
103 return anInd > aNb;
104 }
AddToContainer(const TopoDS_Shape & theS,TopoDS_Shape & theSOut)105 static void AddToContainer (const TopoDS_Shape& theS,
106 TopoDS_Shape& theSOut)
107 {
108 BRep_Builder().Add (theSOut, theS);
109 }
110
111 //=======================================================================
112 //function : TakeModified
113 //purpose : Check if the shape has images in the given images map.
114 // Puts in the output map either the images or the shape itself.
115 //=======================================================================
116 template <class ContainerType, class FenceMapType>
TakeModified(const TopoDS_Shape & theS,const TopTools_DataMapOfShapeListOfShape & theImages,ContainerType & theContainer,FenceMapType * theMFence)117 static Standard_Boolean TakeModified (const TopoDS_Shape& theS,
118 const TopTools_DataMapOfShapeListOfShape& theImages,
119 ContainerType& theContainer,
120 FenceMapType* theMFence)
121 {
122 const TopTools_ListOfShape* pLSIm = theImages.Seek (theS);
123 if (pLSIm)
124 {
125 TopTools_ListIteratorOfListOfShape itLSIm (*pLSIm);
126 for (; itLSIm.More(); itLSIm.Next())
127 {
128 const TopoDS_Shape& aSIm = itLSIm.Value();
129 if (!theMFence || AddToContainer (aSIm, *theMFence))
130 AddToContainer (aSIm, theContainer);
131 }
132 return Standard_True;
133 }
134 else
135 {
136 if (!theMFence || AddToContainer (theS, *theMFence))
137 AddToContainer (theS, theContainer);
138 return Standard_False;
139 }
140 }
141
142 template <class ContainerType>
TakeModified(const TopoDS_Shape & theS,const TopTools_DataMapOfShapeListOfShape & theImages,ContainerType & theMapOut)143 static Standard_Boolean TakeModified (const TopoDS_Shape& theS,
144 const TopTools_DataMapOfShapeListOfShape& theImages,
145 ContainerType& theMapOut)
146 {
147 TopTools_MapOfShape* aDummy = NULL;
148 return TakeModified (theS, theImages, theMapOut, aDummy);
149 }
150
151 //=======================================================================
152 //function : hasData
153 //purpose : Checks if container has any data in it
154 //=======================================================================
155 template <class Container>
hasData(const Container * theData)156 static Standard_Boolean hasData (const Container* theData)
157 {
158 return (theData && !theData->IsEmpty());
159 }
160
161 //=======================================================================
162 //function : AppendToList
163 //purpose : Add to a list only unique elements
164 //=======================================================================
AppendToList(TopTools_ListOfShape & theList,const TopoDS_Shape & theShape)165 static void AppendToList (TopTools_ListOfShape& theList,
166 const TopoDS_Shape& theShape)
167 {
168 for (TopTools_ListOfShape::Iterator it (theList); it.More(); it.Next())
169 {
170 const TopoDS_Shape& aS = it.Value();
171 if (aS.IsSame (theShape))
172 {
173 return;
174 }
175 }
176 theList.Append (theShape);
177 }
178
179 //=======================================================================
180 //function : ProcessMicroEdge
181 //purpose : Checking if the edge is micro edge
182 //=======================================================================
ProcessMicroEdge(const TopoDS_Edge & theEdge,const Handle (IntTools_Context)& theCtx)183 static Standard_Boolean ProcessMicroEdge (const TopoDS_Edge& theEdge,
184 const Handle(IntTools_Context)& theCtx)
185 {
186 TopoDS_Vertex aV1, aV2;
187 TopExp::Vertices (theEdge, aV1, aV2);
188 if (aV1.IsNull() || aV2.IsNull())
189 {
190 return Standard_False;
191 }
192
193 Standard_Boolean bMicro = BOPTools_AlgoTools::IsMicroEdge (theEdge, theCtx);
194 if (bMicro && BRepAdaptor_Curve (theEdge).GetType() == GeomAbs_Line)
195 {
196 Standard_Real aLen = BRep_Tool::Pnt (aV1).Distance (BRep_Tool::Pnt (aV2));
197 BRep_Builder().UpdateVertex (aV1, aLen / 2.);
198 BRep_Builder().UpdateVertex (aV2, aLen / 2.);
199 }
200
201 return bMicro;
202 }
203
204 //=======================================================================
205 //function : UpdateOrigins
206 //purpose : Updating origins
207 //=======================================================================
UpdateOrigins(const TopTools_ListOfShape & theLA,TopTools_DataMapOfShapeListOfShape & theOrigins,BOPAlgo_Builder & theGF)208 static void UpdateOrigins (const TopTools_ListOfShape& theLA,
209 TopTools_DataMapOfShapeListOfShape& theOrigins,
210 BOPAlgo_Builder& theGF)
211 {
212 for (TopTools_ListOfShape::Iterator aItA (theLA); aItA.More(); aItA.Next())
213 {
214 const TopoDS_Shape& aS = aItA.Value();
215
216 const TopTools_ListOfShape& aLSIm = theGF.Modified (aS);
217 if (aLSIm.IsEmpty())
218 {
219 continue;
220 }
221
222 TopTools_ListOfShape aLSEmpt;
223 TopTools_ListOfShape* pLS = theOrigins.ChangeSeek (aS);
224 if (!pLS)
225 {
226 pLS = &aLSEmpt;
227 pLS->Append (aS);
228 }
229
230 for (TopTools_ListOfShape::Iterator aIt (aLSIm); aIt.More(); aIt.Next())
231 {
232 const TopoDS_Shape& aSIm = aIt.Value();
233 if (TopTools_ListOfShape* pLSOr = theOrigins.ChangeSeek (aSIm))
234 {
235 // merge two lists
236 for (TopTools_ListOfShape::Iterator aIt1 (*pLS); aIt1.More(); aIt1.Next())
237 {
238 AppendToList (*pLSOr, aIt1.Value());
239 }
240 }
241 else
242 {
243 theOrigins.Bind (aSIm, *pLS);
244 }
245 }
246 }
247 }
248
249 //=======================================================================
250 //function : UpdateImages
251 //purpose : Updating images of the shapes
252 //=======================================================================
UpdateImages(const TopTools_ListOfShape & theLA,TopTools_DataMapOfShapeListOfShape & theImages,BOPAlgo_Builder & theGF,TopTools_MapOfShape & theModified)253 static void UpdateImages (const TopTools_ListOfShape& theLA,
254 TopTools_DataMapOfShapeListOfShape& theImages,
255 BOPAlgo_Builder& theGF,
256 TopTools_MapOfShape& theModified)
257 {
258 for (TopTools_ListOfShape::Iterator aIt (theLA); aIt.More(); aIt.Next())
259 {
260 const TopoDS_Shape& aS = aIt.Value();
261
262 TopTools_ListOfShape* pLSIm = theImages.ChangeSeek (aS);
263 if (!pLSIm)
264 {
265 const TopTools_ListOfShape& aLSIm = theGF.Modified (aS);
266 if (aLSIm.Extent())
267 {
268 theImages.Bind (aS, aLSIm);
269 theModified.Add (aS);
270 }
271 continue;
272 }
273
274 TopTools_MapOfShape aMFence;
275 TopTools_ListOfShape aLSImNew;
276
277 Standard_Boolean bModified = Standard_False;
278
279 // check modifications of the images
280 for (TopTools_ListOfShape::Iterator aIt1 (*pLSIm); aIt1.More(); aIt1.Next())
281 {
282 const TopoDS_Shape& aSIm = aIt1.Value();
283 bModified |= TakeModified (aSIm, theGF.Images(), aLSImNew, &aMFence);
284 }
285
286 if (bModified)
287 {
288 *pLSIm = aLSImNew;
289 theModified.Add (aS);
290 }
291 }
292 }
293
294 //=======================================================================
295 //function : FindCommonParts
296 //purpose : Looking for the parts of type <theType> contained in both lists
297 //=======================================================================
FindCommonParts(const TopTools_ListOfShape & theLS1,const TopTools_ListOfShape & theLS2,TopTools_ListOfShape & theLSC,const TopAbs_ShapeEnum theType=TopAbs_EDGE)298 static void FindCommonParts (const TopTools_ListOfShape& theLS1,
299 const TopTools_ListOfShape& theLS2,
300 TopTools_ListOfShape& theLSC,
301 const TopAbs_ShapeEnum theType = TopAbs_EDGE)
302 {
303 // map shapes in the first list
304 TopTools_IndexedMapOfShape aMS1;
305 for (TopTools_ListOfShape::Iterator aIt (theLS1); aIt.More(); aIt.Next())
306 {
307 const TopoDS_Shape& aS = aIt.Value();
308 TopExp::MapShapes (aS, theType, aMS1);
309 }
310 if (aMS1.IsEmpty())
311 {
312 return;
313 }
314
315 // check for such shapes in the other list
316 TopTools_MapOfShape aMFence;
317 for (TopTools_ListOfShape::Iterator aIt (theLS2); aIt.More(); aIt.Next())
318 {
319 const TopoDS_Shape& aS = aIt.Value();
320
321 TopExp_Explorer aExp (aS, theType);
322 for (; aExp.More(); aExp.Next())
323 {
324 const TopoDS_Shape& aST = aExp.Current();
325 if (aMS1.Contains (aST) && aMFence.Add (aST))
326 {
327 theLSC.Append (aST);
328 }
329 }
330 }
331 }
332
333 //=======================================================================
334 //function : NbPoints
335 //purpose : Defines number of sample points to get average direction of the edge
336 //=======================================================================
NbPoints(const TopoDS_Edge & theEdge)337 static Standard_Integer NbPoints (const TopoDS_Edge& theEdge)
338 {
339 BRepAdaptor_Curve aBAC (theEdge);
340 switch (aBAC.GetType())
341 {
342 case GeomAbs_Line:
343 return 1;
344 default:
345 return 11;
346 }
347 }
348
349 //=======================================================================
350 //function : FindShape
351 //purpose : Looking for the same sub-shape in the shape
352 //=======================================================================
FindShape(const TopoDS_Shape & theSWhat,const TopoDS_Shape & theSWhere,const BRepOffset_Analyse * theAnalyse,TopoDS_Shape & theRes)353 static Standard_Boolean FindShape (const TopoDS_Shape& theSWhat,
354 const TopoDS_Shape& theSWhere,
355 const BRepOffset_Analyse* theAnalyse,
356 TopoDS_Shape& theRes)
357 {
358 Standard_Boolean bFound = Standard_False;
359 TopAbs_ShapeEnum aType = theSWhat.ShapeType();
360 TopExp_Explorer aExp (theSWhere, aType);
361 for (; aExp.More(); aExp.Next())
362 {
363 const TopoDS_Shape& aS = aExp.Current();
364 if (aS.IsSame (theSWhat))
365 {
366 theRes = aS;
367 bFound = Standard_True;
368 break;
369 }
370 }
371
372 if (!bFound && theAnalyse)
373 {
374 const TopTools_ListOfShape* pLD = theAnalyse->Descendants (theSWhere);
375 if (pLD)
376 {
377 for (TopTools_ListOfShape::Iterator it (*pLD); it.More(); it.Next())
378 {
379 const TopoDS_Shape& aS = it.Value();
380 if (aS.IsSame (theSWhat))
381 {
382 theRes = aS;
383 bFound = Standard_True;
384 break;
385 }
386 }
387 }
388 }
389
390 return bFound;
391 }
392
393 //=======================================================================
394 //function : BuildSplitsOfTrimmedFace
395 //purpose : Building the splits of offset face
396 //=======================================================================
BuildSplitsOfTrimmedFace(const TopoDS_Face & theFace,const TopoDS_Shape & theEdges,TopTools_ListOfShape & theLFImages,const Message_ProgressRange & theRange)397 static void BuildSplitsOfTrimmedFace (const TopoDS_Face& theFace,
398 const TopoDS_Shape& theEdges,
399 TopTools_ListOfShape& theLFImages,
400 const Message_ProgressRange& theRange)
401 {
402 BOPAlgo_Splitter aSplitter;
403 //
404 aSplitter.AddArgument (theFace);
405 aSplitter.AddArgument (theEdges);
406 aSplitter.SetToFillHistory (Standard_False);
407 aSplitter.Perform (theRange);
408 if (aSplitter.HasErrors())
409 {
410 return;
411 }
412 //
413 // splits of the offset shape
414 for (TopExp_Explorer anExp (aSplitter.Shape(), TopAbs_FACE); anExp.More(); anExp.Next())
415 {
416 theLFImages.Append (anExp.Current());
417 }
418 }
419
420 //=======================================================================
421 //function : BuildSplitsOfFace
422 //purpose : Building the splits of offset face
423 //=======================================================================
BuildSplitsOfFace(const TopoDS_Face & theFace,const TopoDS_Shape & theEdges,TopTools_DataMapOfShapeShape & theFacesOrigins,TopTools_ListOfShape & theLFImages)424 static void BuildSplitsOfFace (const TopoDS_Face& theFace,
425 const TopoDS_Shape& theEdges,
426 TopTools_DataMapOfShapeShape& theFacesOrigins,
427 TopTools_ListOfShape& theLFImages)
428 {
429 theLFImages.Clear();
430 //
431 // take edges to split the face
432 TopTools_ListOfShape aLE;
433 TopExp_Explorer aExp (theEdges, TopAbs_EDGE);
434 for (; aExp.More(); aExp.Next())
435 {
436 TopoDS_Edge aE = TopoDS::Edge (aExp.Current());
437 aE.Orientation (TopAbs_FORWARD);
438 aLE.Append (aE);
439 aE.Orientation (TopAbs_REVERSED);
440 aLE.Append (aE);
441 }
442 //
443 TopoDS_Face aFF = theFace;
444 TopAbs_Orientation anOr = theFace.Orientation();
445 aFF.Orientation (TopAbs_FORWARD);
446 //
447 // build pcurves for edges on the face
448 BRepLib::BuildPCurveForEdgesOnPlane (aLE, aFF);
449 //
450 // build splits of faces
451 BOPAlgo_BuilderFace aBF;
452 aBF.SetFace (aFF);
453 aBF.SetShapes (aLE);
454 aBF.Perform();
455 if (aBF.HasErrors())
456 {
457 return;
458 }
459 //
460 const TopTools_ListOfShape& aLFSp = aBF.Areas();
461 TopTools_ListIteratorOfListOfShape aItLF (aLFSp);
462 for (; aItLF.More(); aItLF.Next())
463 {
464 TopoDS_Shape& aFSp = aItLF.ChangeValue();
465 aFSp.Orientation (anOr);
466 theLFImages.Append (aFSp);
467 //
468 theFacesOrigins.Bind (aFSp, theFace);
469 }
470 }
471
472 //=======================================================================
473 //function : GetAverageTangent
474 //purpose : Computes average tangent vector along the curve
475 //=======================================================================
GetAverageTangent(const TopoDS_Shape & theS,const Standard_Integer theNbP)476 static gp_Vec GetAverageTangent (const TopoDS_Shape& theS,
477 const Standard_Integer theNbP)
478 {
479 gp_Vec aVA;
480 TopExp_Explorer aExp (theS, TopAbs_EDGE);
481 for (; aExp.More(); aExp.Next())
482 {
483 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
484 //
485 Standard_Real aT1, aT2;
486 const Handle(Geom_Curve)& aC = BRep_Tool::Curve (aE, aT1, aT2);
487 //
488 gp_Pnt aP;
489 gp_Vec aV, aVSum;
490 Standard_Real aT = aT1;
491 Standard_Real aDt = (aT2 - aT1) / theNbP;
492 while (aT <= aT2)
493 {
494 aC->D1 (aT, aP, aV);
495 aVSum += aV.Normalized();
496 aT += aDt;
497 }
498 //
499 if (aE.Orientation() == TopAbs_REVERSED)
500 {
501 aVSum.Reverse();
502 }
503 //
504 aVA += aVSum;
505 }
506 return aVA;
507 }
508 }
509
510 //=======================================================================
511 //function : BRepOffset_BuildOffsetFaces
512 //purpose : Auxiliary local class that is used here for building splits
513 // of offset faces, that are further used for building volumes.
514 //=======================================================================
515 class BRepOffset_BuildOffsetFaces
516 {
517 public: //! @name Constructor
518 //! Constructor, taking the history tool to be filled
BRepOffset_BuildOffsetFaces(BRepAlgo_Image & theImage)519 BRepOffset_BuildOffsetFaces (BRepAlgo_Image& theImage) :
520 myFaces (NULL),
521 myAnalyzer (NULL),
522 myEdgesOrigins (NULL),
523 myFacesOrigins (NULL),
524 myETrimEInf (NULL),
525 myImage (&theImage)
526 {
527 myContext = new IntTools_Context();
528 }
529
530 public: //! @name Setting data
531
532 //! Sets faces to build splits
SetFaces(const TopTools_ListOfShape & theFaces)533 void SetFaces (const TopTools_ListOfShape& theFaces) { myFaces = &theFaces; }
534
535 //! Sets ascendants/descendants information
SetAsDesInfo(const Handle (BRepAlgo_AsDes)& theAsDes)536 void SetAsDesInfo (const Handle(BRepAlgo_AsDes)& theAsDes) { myAsDes = theAsDes; }
537
538 //! Sets the analysis info of the input shape
SetAnalysis(const BRepOffset_Analyse & theAnalyse)539 void SetAnalysis (const BRepOffset_Analyse& theAnalyse) { myAnalyzer = &theAnalyse; }
540
541 //! Sets origins of the offset edges (from original shape)
SetEdgesOrigins(TopTools_DataMapOfShapeListOfShape & theEdgesOrigins)542 void SetEdgesOrigins (TopTools_DataMapOfShapeListOfShape& theEdgesOrigins) { myEdgesOrigins = &theEdgesOrigins; }
543
544 //! Sets origins of the offset faces (from original shape)
SetFacesOrigins(TopTools_DataMapOfShapeShape & theFacesOrigins)545 void SetFacesOrigins (TopTools_DataMapOfShapeShape& theFacesOrigins) { myFacesOrigins = &theFacesOrigins; }
546
547 //! Sets infinite (extended) edges for the trimmed ones
SetInfEdges(TopTools_DataMapOfShapeShape & theETrimEInf)548 void SetInfEdges (TopTools_DataMapOfShapeShape& theETrimEInf) { myETrimEInf = &theETrimEInf; }
549
550 public: //! @name Public methods to build the splits
551
552 //! Build splits of already trimmed faces
553 void BuildSplitsOfTrimmedFaces (const Message_ProgressRange& theRange);
554
555 //! Building splits of not-trimmed offset faces.
556 //! For the cases in which invalidities will be found, these invalidities will be rebuilt.
557 void BuildSplitsOfExtendedFaces (const Message_ProgressRange& theRange);
558
559 private: //! @name private methods performing the job
560
561 private: //! @name Intersection and post-treatment of edges
562
563 //! Intersection of the trimmed edges among themselves
564 void IntersectTrimmedEdges (const Message_ProgressRange& theRange);
565
566 //! Saving connection from trimmed edges to not trimmed ones
567 void UpdateIntersectedEdges (const TopTools_ListOfShape& theLA,
568 BOPAlgo_Builder& theGF);
569
570 //! Getting edges from AsDes map to build the splits of faces
571 Standard_Boolean GetEdges (const TopoDS_Face& theFace,
572 TopoDS_Shape& theEdges,
573 TopTools_IndexedMapOfShape* theInv = nullptr);
574
575 //! Looks for the invalid edges (edges with changed orientation)
576 //! in the splits of offset faces
577 void FindInvalidEdges (const TopoDS_Face& theF,
578 const TopTools_ListOfShape& theLFImages,
579 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
580 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
581 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
582 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
583 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
584 TopTools_MapOfShape& theEdgesInvalidByVertex,
585 TopTools_MapOfShape& theEdgesValidByVertex,
586 const Message_ProgressRange& theRange);
587
588 //! Additional method to look for invalid edges
589 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
590 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
591 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
592 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges);
593
594 //! Checks if the edge has been inverted
595 Standard_Boolean CheckInverted (const TopoDS_Edge& theEIm,
596 const TopoDS_Face& theFOr,
597 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
598 const TopTools_IndexedMapOfShape& theMEdges);
599
600 //! Looking for the invalid faces containing inverted edges that can be safely removed
601 void RemoveInvalidSplitsByInvertedEdges (TopTools_IndexedMapOfShape& theMERemoved);
602
603 //! Makes inverted edges located inside loop of invalid edges, invalid as well
604 void MakeInvertedEdgesInvalid (const TopTools_ListOfShape& theLFOffset);
605
606 //! Checks if it is possible to remove the block containing inverted edges
607 Standard_Boolean CheckInvertedBlock (const TopoDS_Shape& theCB,
608 const TopTools_ListOfShape& theLCBF,
609 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
610 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll);
611
612 //! Updating the maps of images and origins of the offset edges
613 void FilterEdgesImages (const TopoDS_Shape& theS);
614
615 //! Checks additionally the unchecked edges originated from vertices
616 void CheckEdgesCreatedByVertex();
617
618 //! Filtering the invalid edges according to currently invalid faces
619 void FilterInvalidEdges (const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
620 const TopTools_IndexedMapOfShape& theMERemoved);
621
622 private: //! @name Checking faces
623
624 //! Build splits of faces
625 void BuildSplitsOfFaces (const Message_ProgressRange& theRange);
626
627 //! Looking for the invalid faces by analyzing their invalid edges
628 void FindInvalidFaces (TopTools_ListOfShape& theLFImages,
629 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
630 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
631 const TopTools_MapOfShape& theMENeutral,
632 const TopTools_MapOfShape& theEdgesInvalidByVertex,
633 const TopTools_MapOfShape& theEdgesValidByVertex,
634 const TopTools_MapOfShape& theMFHoles,
635 TopTools_IndexedMapOfShape& theMFInvInHole,
636 TopTools_ListOfShape& theInvFaces,
637 TopTools_ListOfShape& theInvertedFaces);
638
639 //! Find faces inside holes wires from the original face
640 void FindFacesInsideHoleWires (const TopoDS_Face& theFOrigin,
641 const TopoDS_Face& theFOffset,
642 const TopTools_ListOfShape& theLFImages,
643 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
644 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
645 TopTools_MapOfShape& theMFHoles);
646
647 //! Removing invalid splits of faces from valid
648 void RemoveInvalidSplitsFromValid (const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE);
649
650 //! Looking for the inside faces that can be safely removed
651 void RemoveInsideFaces (const TopTools_ListOfShape& theInvertedFaces,
652 const TopTools_IndexedMapOfShape& theMFToCheckInt,
653 const TopTools_IndexedMapOfShape& theMFInvInHole,
654 const TopoDS_Shape& theFHoles,
655 TopTools_IndexedMapOfShape& theMERemoved,
656 TopTools_IndexedMapOfShape& theMEInside,
657 const Message_ProgressRange& theRange);
658
659 //! Looking for the connections between faces not to miss some necessary intersection
660 void ShapesConnections (const TopTools_DataMapOfShapeShape& theDMFOr,
661 BOPAlgo_Builder& theBuilder);
662
663 //! Remove isolated invalid hanging parts
664 void RemoveHangingParts (const BOPAlgo_MakerVolume& theMV,
665 const TopTools_DataMapOfShapeShape& theDMFImF,
666 const TopTools_IndexedMapOfShape& theMFInv,
667 TopTools_MapOfShape& theMFToRem);
668
669 //! Removing valid splits according to results of intersection
670 void RemoveValidSplits (const TopTools_MapOfShape& theSpRem,
671 BOPAlgo_Builder& theGF,
672 TopTools_IndexedMapOfShape& theMERemoved);
673
674 //! Removing invalid splits according to the results of intersection
675 void RemoveInvalidSplits (const TopTools_MapOfShape& theSpRem,
676 BOPAlgo_Builder& theGF,
677 TopTools_IndexedMapOfShape& theMERemoved);
678
679 //! Filtering of the invalid faces
680 void FilterInvalidFaces (const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
681 const TopTools_IndexedMapOfShape& theMERemoved);
682
683 //! Checks if the face is artificially invalid
684 Standard_Boolean CheckIfArtificial (const TopoDS_Shape& theF,
685 const TopTools_ListOfShape& theLFImages,
686 const TopoDS_Shape& theCE,
687 const TopTools_IndexedMapOfShape& theMapEInv,
688 TopTools_MapOfShape& theMENInv);
689
690 //! Looking for the faces that have to be rebuilt:
691 //! * Faces close to invalidity
692 //! * Faces containing some invalid parts
693 void FindFacesToRebuild();
694
695 //! Intersection of the faces that should be rebuild to resolve all invalidities
696 void IntersectFaces (TopTools_MapOfShape& theVertsToAvoid,
697 const Message_ProgressRange& theRange);
698
699 //! Preparation of the maps for analyzing intersections of the faces
700 void PrepareFacesForIntersection (const Standard_Boolean theLookVertToAvoid,
701 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
702 TopTools_DataMapOfShapeListOfShape& theMDone,
703 TopTools_DataMapOfShapeListOfShape& theDMSF,
704 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
705 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
706 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv);
707
708 //! Looking for the invalid vertices
709 void FindVerticesToAvoid (const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
710 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
711 TopTools_MapOfShape& theMVRInv);
712
713 //! Looking for the faces around each invalidity for intersection
714 void FindFacesForIntersection (const TopoDS_Shape& theFInv,
715 const TopTools_IndexedMapOfShape& theME,
716 const TopTools_DataMapOfShapeListOfShape& theDMSF,
717 const TopTools_MapOfShape& theMVInvAll,
718 const Standard_Boolean theArtCase,
719 TopTools_IndexedMapOfShape& theMFAvoid,
720 TopTools_IndexedMapOfShape& theMFInt,
721 TopTools_IndexedMapOfShape& theMFIntExt,
722 TopTools_ListOfShape& theLFImInt);
723
724 //! Analyzing the common edges between splits of offset faces
725 void ProcessCommonEdges (const TopTools_ListOfShape& theLEC,
726 const TopTools_IndexedMapOfShape& theME,
727 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
728 const TopTools_MapOfShape& theAllInvs,
729 const Standard_Boolean theForceUse,
730 TopTools_IndexedMapOfShape& theMECV,
731 TopTools_MapOfShape& theMECheckExt,
732 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
733 TopTools_ListOfShape& theLFEi,
734 TopTools_ListOfShape& theLFEj,
735 TopTools_IndexedMapOfShape& theMEToInt);
736
737 //! Updating the already interfered faces
738 void UpdateIntersectedFaces (const TopoDS_Shape& theFInv,
739 const TopoDS_Shape& theFi,
740 const TopoDS_Shape& theFj,
741 const TopTools_ListOfShape& theLFInv,
742 const TopTools_ListOfShape& theLFImi,
743 const TopTools_ListOfShape& theLFImj,
744 const TopTools_ListOfShape& theLFEi,
745 const TopTools_ListOfShape& theLFEj,
746 TopTools_IndexedMapOfShape& theMEToInt);
747
748 //! Intersection of the pair of faces
749 void IntersectFaces (const TopoDS_Shape& theFInv,
750 const TopoDS_Shape& theFi,
751 const TopoDS_Shape& theFj,
752 const TopTools_ListOfShape& theLFInv,
753 const TopTools_ListOfShape& theLFImi,
754 const TopTools_ListOfShape& theLFImj,
755 TopTools_ListOfShape& theLFEi,
756 TopTools_ListOfShape& theLFEj,
757 TopTools_IndexedMapOfShape& theMECV,
758 TopTools_IndexedMapOfShape& theMEToInt);
759
760 //! Intersection of the new intersection edges among themselves
761 void IntersectAndTrimEdges (const TopTools_IndexedMapOfShape& theMFInt,
762 const TopTools_IndexedMapOfShape& theMEInt,
763 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
764 const TopTools_IndexedMapOfShape& theMSInv,
765 const TopTools_IndexedMapOfShape& theMVE,
766 const TopTools_MapOfShape& theVertsToAvoid,
767 const TopTools_MapOfShape& theNewVertsToAvoid,
768 const TopTools_MapOfShape& theMECheckExt,
769 TopTools_MapOfShape& theMVBounds,
770 TopTools_DataMapOfShapeListOfShape& theEImages);
771
772 //! Looking for the invalid edges by intersecting with invalid vertices
773 void GetInvalidEdges (const TopTools_MapOfShape& theVertsToAvoid,
774 const TopTools_MapOfShape& theMVBounds,
775 BOPAlgo_Builder& theGF,
776 TopTools_MapOfShape& theMEInv);
777
778 //! Making the new splits and updating the maps
779 void UpdateValidEdges (const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
780 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
781 const TopTools_MapOfShape& theMVBounds,
782 const TopTools_MapOfShape& theMEInvOnArt,
783 TopTools_MapOfShape& theMECheckExt,
784 TopTools_MapOfShape& theVertsToAvoid,
785 TopTools_DataMapOfShapeListOfShape& theEImages,
786 TopTools_DataMapOfShapeListOfShape& theEETrim,
787 const Message_ProgressRange& theRange);
788
789 //! Trims intersection edges
790 void TrimNewIntersectionEdges (const TopTools_ListOfShape& theLE,
791 const TopTools_DataMapOfShapeListOfShape& theEETrim,
792 const TopTools_MapOfShape& theMVBounds,
793 TopTools_MapOfShape& theMECheckExt,
794 TopTools_DataMapOfShapeListOfShape& theEImages,
795 TopTools_MapOfShape& theMEB,
796 TopTools_MapOfShape& theMVOld,
797 TopTools_MapOfShape& theMENew,
798 TopTools_DataMapOfShapeListOfShape& theDMEOr,
799 TopTools_DataMapOfShapeListOfShape& theMELF);
800
801 //! Intersecting the trimmed edges to avoid self-intersections
802 void IntersectEdges (const TopTools_ListOfShape& theLA,
803 const TopTools_ListOfShape& theLE,
804 const TopTools_MapOfShape& theMVBounds,
805 const TopTools_MapOfShape& theVertsToAvoid,
806 TopTools_MapOfShape& theMENew,
807 TopTools_MapOfShape& theMECheckExt,
808 TopTools_DataMapOfShapeListOfShape& theEImages,
809 TopTools_DataMapOfShapeListOfShape& theDMEOr,
810 TopTools_DataMapOfShapeListOfShape& theMELF,
811 TopoDS_Shape& theSplits);
812
813 //! Getting edges from the splits of offset faces
814 void GetBounds (const TopTools_ListOfShape& theLFaces,
815 const TopTools_MapOfShape& theMEB,
816 TopoDS_Shape& theBounds);
817
818 //! Get bounding edges that should be updated
819 void GetBoundsToUpdate (const TopTools_ListOfShape& theLF,
820 const TopTools_MapOfShape& theMEB,
821 TopTools_ListOfShape& theLABounds,
822 TopTools_ListOfShape& theLAValid,
823 TopoDS_Shape& theBounds);
824
825 //! Filter new splits by intersection with bounds
826 void GetInvalidEdgesByBounds (const TopoDS_Shape& theSplits,
827 const TopoDS_Shape& theBounds,
828 const TopTools_MapOfShape& theMVOld,
829 const TopTools_MapOfShape& theMENew,
830 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
831 const TopTools_DataMapOfShapeListOfShape& theMELF,
832 const TopTools_DataMapOfShapeListOfShape& theEImages,
833 const TopTools_MapOfShape& theMECheckExt,
834 const TopTools_MapOfShape& theMEInvOnArt,
835 TopTools_MapOfShape& theVertsToAvoid,
836 TopTools_MapOfShape& theMEInv);
837
838 //! Filter the images of edges from the invalid edges
839 void FilterSplits (const TopTools_ListOfShape& theLE,
840 const TopTools_MapOfShape& theMEFilter,
841 const Standard_Boolean theIsInv,
842 TopTools_DataMapOfShapeListOfShape& theEImages,
843 TopoDS_Shape& theSplits);
844
845 //! Updating the maps of images and origins of the offset edges
846 void UpdateNewIntersectionEdges (const TopTools_ListOfShape& theLE,
847 const TopTools_DataMapOfShapeListOfShape& theMELF,
848 const TopTools_DataMapOfShapeListOfShape& theEImages,
849 TopTools_DataMapOfShapeListOfShape& theEETrim);
850
851 private:
852
853 //! Fill possible gaps (holes) in the splits of the offset faces
854 void FillGaps (const Message_ProgressRange& theRange);
855
856 //! Saving obtained results in history tools
857 void FillHistory();
858
859 private:
860 // Input data
861 const TopTools_ListOfShape* myFaces; //!< Input faces which have to be split
862 Handle(BRepAlgo_AsDes) myAsDes; //!< Ascendants/descendants of the edges faces
863 const BRepOffset_Analyse* myAnalyzer; //!< Analyzer of the input parameters
864
865 TopTools_DataMapOfShapeListOfShape* myEdgesOrigins; //!< Origins of the offset edges (binding between offset edge and original edge)
866 TopTools_DataMapOfShapeShape* myFacesOrigins; //!< Origins of the offset faces (binding between offset face and original face)
867 TopTools_DataMapOfShapeShape* myETrimEInf; //!< Binding between trimmed and infinite edge
868
869 // Intermediate data
870 TopTools_DataMapOfShapeListOfShape myOEImages; //!< Images of the offset edges
871 TopTools_DataMapOfShapeListOfShape myOEOrigins; //!< Origins of the splits of offset edges
872 TopTools_IndexedDataMapOfShapeListOfShape myOFImages; //!< Images of the offset edges
873
874 TopTools_IndexedMapOfShape myInvalidEdges; //!< Edges considered invalid (orientation is changed) in some split of face
875 TopTools_IndexedMapOfShape myValidEdges; //!< Edges considered valid (orientation is kept) in some split of face
876 TopTools_IndexedMapOfShape myInvertedEdges; //!< Edges considered inverted (vertices swapped) in some split of face
877 TopTools_IndexedMapOfShape myEdgesToAvoid; //!< Splits of edges to be avoided when building splits of faces
878 TopTools_MapOfShape myLastInvEdges; //!< Edges marked invalid on the current step and to be avoided on the next step
879 TopTools_MapOfShape myModifiedEdges; //!< Edges to be used for building splits
880
881 TopTools_IndexedDataMapOfShapeListOfShape myInvalidFaces; //!< Invalid faces - splits of offset faces consisting of invalid edges
882 TopTools_DataMapOfShapeShape myArtInvalidFaces; //!< Artificially invalid faces - valid faces intentionally marked invalid
883 //! to be rebuilt on the future steps in the situations when invalid edges
884 //! are present, but invalid faces not
885 TopTools_DataMapOfShapeInteger myAlreadyInvFaces; //!< Count number of the same face being marked invalid to avoid infinite
886 //! rebuilding of the same face
887 TopTools_DataMapOfShapeListOfShape myFNewHoles; //!< Images of the hole faces of the original face
888
889 TopTools_DataMapOfShapeListOfShape mySSInterfs; //!< Intersection information, used to collect intersection pairs during rebuild
890 NCollection_DataMap <TopoDS_Shape,
891 BRepOffset_DataMapOfShapeMapOfShape,
892 TopTools_ShapeMapHasher> myIntersectionPairs; //!< All possible intersection pairs, used to avoid some of the intersections
893
894 TopTools_IndexedDataMapOfShapeListOfShape myFacesToRebuild; //!< Faces that have to be rebuilt (invalid and close to invalid faces)
895 TopTools_MapOfShape myFSelfRebAvoid; //!< Faces that have to be avoided when rebuilding splits of the same offset face
896
897 TopoDS_Shape mySolids; //!< Solids built from the splits of faces
898
899 // Auxiliary tools
900 Handle(IntTools_Context) myContext;
901
902 // Output
903 BRepAlgo_Image* myImage; //!< History of modifications
904 };
905
906 //=======================================================================
907 //function : BuildSplitsOfTrimmedFaces
908 //purpose :
909 //=======================================================================
BuildSplitsOfTrimmedFaces(const Message_ProgressRange & theRange)910 void BRepOffset_BuildOffsetFaces::BuildSplitsOfTrimmedFaces (const Message_ProgressRange& theRange)
911 {
912 if (!hasData (myFaces))
913 {
914 return;
915 }
916
917 TopTools_DataMapOfShapeListOfShape anEdgesOrigins;
918 if (!myEdgesOrigins)
919 {
920 myEdgesOrigins = &anEdgesOrigins;
921 }
922
923 Message_ProgressScope aPS (theRange, "Building splits of trimmed faces", 5);
924
925 // Fuse all edges
926 IntersectTrimmedEdges (aPS.Next (1));
927
928 Message_ProgressScope aPSLoop (aPS.Next (4), NULL, myFaces->Extent());
929 for (TopTools_ListOfShape::Iterator aItLF (*myFaces); aItLF.More(); aItLF.Next())
930 {
931 if (!aPSLoop.More())
932 {
933 return;
934 }
935 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
936
937 TopoDS_Shape aCE;
938 Standard_Boolean bFound = GetEdges (aF, aCE);
939
940 // split the face by the edges
941 if (!bFound)
942 {
943 if (!myImage->HasImage (aF))
944 {
945 myOFImages (myOFImages.Add (aF, TopTools_ListOfShape())).Append (aF);
946 }
947 continue;
948 }
949
950 TopTools_ListOfShape aLFImages;
951 BuildSplitsOfTrimmedFace (aF, aCE, aLFImages, aPSLoop.Next());
952
953 myOFImages.Add (aF, aLFImages);
954 }
955 // Fill history for faces and edges
956 FillHistory();
957 }
958
959 //=======================================================================
960 //function : BuildSplitsOfExtendedFaces
961 //purpose :
962 //=======================================================================
BuildSplitsOfExtendedFaces(const Message_ProgressRange & theRange)963 void BRepOffset_BuildOffsetFaces::BuildSplitsOfExtendedFaces (const Message_ProgressRange& theRange)
964 {
965 // Check input data
966 if (!hasData (myFaces) || !hasData (myEdgesOrigins) || !hasData (myFacesOrigins) || !hasData (myETrimEInf))
967 {
968 return;
969 }
970
971 Message_ProgressScope aPS (theRange, "Building splits of extended faces", 100.);
972 // Scope has to be added into a loop of undefined size.
973 // In general there are about 2 to 5 loops performed, each time
974 // decreasing complexity. So reserve for each next loop smaller time.
975 // Reserve also 4% on filling gaps after the faces are built.
976 Standard_Real aWhole = 100. - 4.;
977
978 // Fusing all trimmed offset edges to avoid self-intersections in the splits
979 IntersectTrimmedEdges (aPS.Next());
980 if (!aPS.More())
981 {
982 return;
983 }
984 // vertices to avoid
985 TopTools_MapOfShape aVertsToAvoid;
986
987 // Limit total number of attempts by 10. This should be extra, as each invalid face can be
988 // rebuilt only three times. So, in general, there are about 2-5 loops done.
989 const Standard_Integer aNbMaxAttempts = 10;
990 // First progress portion is the half of the whole. Each next step is half of the previous:
991 // 48%, 24%, 12%, 6% and so on. This way in three loops it will already be 84%,
992 // and in four - 90%. So even if the loop will stop earlier, the not advanced scope
993 // will be acceptable.
994 Standard_Real aPart = aWhole / 2.;
995 for (Standard_Integer iCount = 1; iCount <= aNbMaxAttempts; ++iCount, aPart /= 2.)
996 {
997 if (!aPS.More())
998 {
999 return;
1000 }
1001 // Clear the data before further faces construction
1002 myInvalidFaces.Clear();
1003 myArtInvalidFaces.Clear();
1004 myInvalidEdges.Clear();
1005 myInvertedEdges.Clear();
1006 mySSInterfs.Clear();
1007 myIntersectionPairs.Clear();
1008 mySolids.Nullify();
1009 myFacesToRebuild.Clear();
1010 myFSelfRebAvoid.Clear();
1011
1012 // Split progress range on
1013 // * building faces basing on currently available edges and
1014 // * rebuilding faces basing on edges classification
1015 Message_ProgressScope aPSLoop (aPS.Next (aPart), NULL, 10.);
1016
1017 // Build splits of the faces having new intersection edges
1018 BuildSplitsOfFaces (aPSLoop.Next (7.));
1019 if (myInvalidFaces.IsEmpty())
1020 {
1021 break;
1022 }
1023
1024 // Find faces to rebuild
1025 FindFacesToRebuild();
1026 if (myFacesToRebuild.IsEmpty())
1027 {
1028 break;
1029 }
1030
1031 // Perform new intersections
1032 myModifiedEdges.Clear();
1033 IntersectFaces (aVertsToAvoid, aPSLoop.Next (3.));
1034 }
1035
1036 // Fill possible gaps in the splits of offset faces to increase possibility of
1037 // creating closed volume from these splits
1038 FillGaps (aPS.Next (4.));
1039
1040 // Fill history for faces and edges
1041 FillHistory();
1042 }
1043
1044 //=======================================================================
1045 //function : UpdateIntersectedEdges
1046 //purpose : Saving connection from trimmed edges to not trimmed ones
1047 //=======================================================================
UpdateIntersectedEdges(const TopTools_ListOfShape & theLA,BOPAlgo_Builder & theGF)1048 void BRepOffset_BuildOffsetFaces::UpdateIntersectedEdges (const TopTools_ListOfShape& theLA,
1049 BOPAlgo_Builder& theGF)
1050 {
1051 for (TopTools_ListOfShape::Iterator aItA (theLA); aItA.More(); aItA.Next())
1052 {
1053 const TopoDS_Shape& aS = aItA.Value();
1054 const TopoDS_Shape* pEInf = myETrimEInf->Seek (aS);
1055 if (!pEInf)
1056 {
1057 continue;
1058 }
1059
1060 const TopTools_ListOfShape& aLSIm = theGF.Modified (aS);
1061 if (aLSIm.IsEmpty())
1062 {
1063 continue;
1064 }
1065
1066 for (TopTools_ListOfShape::Iterator aIt (aLSIm); aIt.More(); aIt.Next())
1067 {
1068 const TopoDS_Shape& aEIm = aIt.Value();
1069 if (!myETrimEInf->IsBound (aEIm))
1070 {
1071 myETrimEInf->Bind (aEIm, *pEInf);
1072 }
1073 }
1074 }
1075 }
1076
1077 //=======================================================================
1078 //function : IntersectTrimmedEdges
1079 //purpose :
1080 //=======================================================================
IntersectTrimmedEdges(const Message_ProgressRange & theRange)1081 void BRepOffset_BuildOffsetFaces::IntersectTrimmedEdges (const Message_ProgressRange& theRange)
1082 {
1083 // get edges to intersect from descendants of the offset faces
1084 TopTools_ListOfShape aLS;
1085 //
1086 Message_ProgressScope aPS (theRange, NULL, 2);
1087 TopTools_ListIteratorOfListOfShape aItLF (*myFaces);
1088 for (; aItLF.More(); aItLF.Next())
1089 {
1090 if (!aPS.More())
1091 {
1092 return;
1093 }
1094 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1095 //
1096 const TopTools_ListOfShape& aLE = myAsDes->Descendant (aF);
1097 TopTools_ListIteratorOfListOfShape aItLE (aLE);
1098 for (; aItLE.More(); aItLE.Next())
1099 {
1100 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1101 //
1102 if (ProcessMicroEdge (aE, myContext))
1103 {
1104 continue;
1105 }
1106 //
1107 if (myModifiedEdges.Add (aE))
1108 {
1109 aLS.Append (aE);
1110 }
1111 }
1112 }
1113 //
1114 if (aLS.Extent() < 2)
1115 {
1116 // nothing to intersect
1117 return;
1118 }
1119 //
1120 // perform intersection of the edges
1121 BOPAlgo_Builder aGFE;
1122 aGFE.SetArguments (aLS);
1123 aGFE.Perform (aPS.Next());
1124 if (aGFE.HasErrors())
1125 {
1126 return;
1127 }
1128 //
1129 TopTools_ListOfShape aLA;
1130 // fill map with edges images
1131 Message_ProgressScope aPSLoop (aPS.Next(), NULL, aLS.Size());
1132 for (TopTools_ListOfShape::Iterator aIt (aLS); aIt.More(); aIt.Next(), aPSLoop.Next())
1133 {
1134 if (!aPSLoop.More())
1135 {
1136 return;
1137 }
1138 const TopoDS_Shape& aE = aIt.Value();
1139 const TopTools_ListOfShape& aLEIm = aGFE.Modified (aE);
1140 if (aLEIm.IsEmpty())
1141 {
1142 continue;
1143 }
1144 //
1145 aLA.Append (aE);
1146 // save images
1147 myOEImages.Bind (aE, aLEIm);
1148 // save origins
1149 TopTools_ListIteratorOfListOfShape aItLE (aLEIm);
1150 for (; aItLE.More(); aItLE.Next())
1151 {
1152 const TopoDS_Shape& aEIm = aItLE.Value();
1153 if (TopTools_ListOfShape* pLEOr = myOEOrigins.ChangeSeek (aEIm))
1154 {
1155 AppendToList (*pLEOr, aE);
1156 }
1157 else
1158 {
1159 myOEOrigins.Bound (aEIm, TopTools_ListOfShape())->Append (aE);
1160 }
1161 }
1162 }
1163 //
1164 UpdateOrigins (aLA, *myEdgesOrigins, aGFE);
1165 UpdateIntersectedEdges (aLA, aGFE);
1166 }
1167
1168 //=======================================================================
1169 //function : BuildSplitsOfFaces
1170 //purpose : Building the splits of offset faces and
1171 // looking for the invalid splits
1172 //=======================================================================
BuildSplitsOfFaces(const Message_ProgressRange & theRange)1173 void BRepOffset_BuildOffsetFaces::BuildSplitsOfFaces (const Message_ProgressRange& theRange)
1174 {
1175 BRep_Builder aBB;
1176 Standard_Integer i, aNb;
1177 //
1178 // processed faces
1179 TopTools_ListOfShape aLFDone;
1180 // extended face - map of neutral edges, i.e. in one split - valid and in other - invalid
1181 BRepOffset_DataMapOfShapeMapOfShape aDMFMNE;
1182 // map of valid edges for each face
1183 BRepOffset_DataMapOfShapeMapOfShape aDMFMVE;
1184 // map of invalid edges for each face
1185 BRepOffset_DataMapOfShapeIndexedMapOfShape aDMFMIE;
1186 // map of valid inverted edges for the face
1187 BRepOffset_DataMapOfShapeMapOfShape aDMFMVIE;
1188 // map of splits to check for internals
1189 TopTools_IndexedMapOfShape aMFToCheckInt;
1190 // map of edges created from vertex and marked as invalid
1191 TopTools_MapOfShape aMEdgeInvalidByVertex;
1192 // map of edges created from vertex and marked as valid
1193 TopTools_MapOfShape aMEdgeValidByVertex;
1194 // connection map from old edges to new ones
1195 TopTools_DataMapOfShapeListOfShape aDMEOrLEIm;
1196 //
1197 // Outer range
1198 Message_ProgressScope aPSOuter (theRange, NULL, 10.);
1199 // build splits of faces
1200 Message_ProgressScope aPSBF (aPSOuter.Next (3.), "Building faces", 2 * myFaces->Extent());
1201 TopTools_ListOfShape::Iterator aItLF (*myFaces);
1202 for (; aItLF.More(); aItLF.Next(), aPSBF.Next())
1203 {
1204 if (!aPSBF.More())
1205 {
1206 return;
1207 }
1208 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1209 //
1210 TopTools_ListOfShape* pLFIm = myOFImages.ChangeSeek (aF);
1211 if (pLFIm && pLFIm->IsEmpty())
1212 {
1213 continue;
1214 }
1215 // get edges by which the face should be split
1216 TopoDS_Shape aCE;
1217 TopTools_IndexedMapOfShape aMapEInv;
1218 Standard_Boolean bFound = GetEdges (aF, aCE, &aMapEInv);
1219 if (!bFound)
1220 {
1221 continue;
1222 }
1223 //
1224 #ifdef OFFSET_DEBUG
1225 // check the found edges on self-intersection
1226 BRepAlgoAPI_Check aChecker (aCE);
1227 if (!aChecker.IsValid())
1228 {
1229 std::cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n";
1230 }
1231 #endif
1232 // build splits
1233 TopTools_ListOfShape aLFImages;
1234 BuildSplitsOfFace (aF, aCE, *myFacesOrigins, aLFImages);
1235 //
1236 if (aMapEInv.Extent())
1237 {
1238 // check if all possible faces are built
1239 TopTools_MapOfShape aMENInv;
1240 Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
1241 CheckIfArtificial (aF, aLFImages, aCE, aMapEInv, aMENInv);
1242 //
1243 // try to build splits using invalid edges
1244 TopoDS_Compound aCE1;
1245 aBB.MakeCompound (aCE1);
1246 aBB.Add (aCE1, aCE);
1247 for (i = 1; i <= aMapEInv.Extent(); ++i)
1248 {
1249 aBB.Add (aCE1, aMapEInv (i));
1250 }
1251 //
1252 TopTools_ListOfShape aLFImages1;
1253 BuildSplitsOfFace (aF, aCE1, *myFacesOrigins, aLFImages1);
1254 //
1255 // check if the rebuilding has added some new faces to the splits
1256 for (TopTools_ListIteratorOfListOfShape aItLFIm (aLFImages1); aItLFIm.More();)
1257 {
1258 Standard_Boolean bAllInv = Standard_True;
1259 const TopoDS_Shape& aFIm = aItLFIm.Value();
1260 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
1261 for (; aExpE.More(); aExpE.Next())
1262 {
1263 const TopoDS_Shape& aE = aExpE.Current();
1264 if (!aMapEInv.Contains (aE))
1265 {
1266 bAllInv = Standard_False;
1267 if (!aMENInv.Contains (aE))
1268 {
1269 break;
1270 }
1271 }
1272 }
1273 //
1274 if (!aExpE.More())
1275 {
1276 if (bAllInv)
1277 {
1278 aMFToCheckInt.Add (aFIm);
1279 }
1280 aLFImages1.Remove (aItLFIm);
1281 }
1282 else
1283 {
1284 aItLFIm.Next();
1285 }
1286 }
1287 //
1288 if (bArtificialCase)
1289 {
1290 if (aLFImages.Extent() == aLFImages1.Extent())
1291 {
1292 bArtificialCase = Standard_False;
1293 }
1294 else
1295 {
1296 aLFImages = aLFImages1;
1297 }
1298 }
1299 //
1300 if (bArtificialCase)
1301 {
1302 TopTools_IndexedMapOfShape aMEInv;
1303 // make the face invalid
1304 myArtInvalidFaces.Bind (aF, aCE);
1305 //
1306 *pLFIm = aLFImages;
1307 TopTools_ListIteratorOfListOfShape aItLFIm (aLFImages);
1308 for (; aItLFIm.More(); aItLFIm.Next())
1309 {
1310 const TopoDS_Shape& aFIm = aItLFIm.Value();
1311 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
1312 for (; aExpE.More(); aExpE.Next())
1313 {
1314 const TopoDS_Shape& aE = aExpE.Current();
1315 if (aMapEInv.Contains (aE))
1316 {
1317 myInvalidEdges.Add (aE);
1318 aMEInv.Add (aE);
1319 }
1320 else
1321 {
1322 myValidEdges.Add (aE);
1323 }
1324 }
1325 }
1326 //
1327 aDMFMIE.Bind (aF, aMEInv);
1328 aLFDone.Append (aF);
1329 //
1330 continue;
1331 }
1332 }
1333
1334 // find invalid edges
1335 FindInvalidEdges (aF, aLFImages, aDMFMVE, aDMFMNE, aDMFMIE, aDMFMVIE,
1336 aDMEOrLEIm, aMEdgeInvalidByVertex, aMEdgeValidByVertex, aPSBF.Next());
1337
1338 // save the new splits
1339 if (!pLFIm)
1340 {
1341 pLFIm = &myOFImages (myOFImages.Add (aF, TopTools_ListOfShape()));
1342 }
1343 else
1344 {
1345 pLFIm->Clear();
1346 }
1347 pLFIm->Append (aLFImages);
1348 //
1349 aLFDone.Append (aF);
1350 }
1351 //
1352 if (myInvalidEdges.IsEmpty() && myArtInvalidFaces.IsEmpty() && aDMFMIE.IsEmpty())
1353 {
1354 return;
1355 }
1356
1357 // Additional step to find invalid edges by checking unclassified edges
1358 // in the splits of SD faces
1359 FindInvalidEdges (aLFDone, aDMFMIE, aDMFMVE, aDMFMNE);
1360
1361 // Additional step to mark inverted edges located inside loops
1362 // of invalid edges as invalid as well
1363 MakeInvertedEdgesInvalid (aLFDone);
1364
1365 #ifdef OFFSET_DEBUG
1366 // show invalid edges
1367 TopoDS_Compound aCEInv1;
1368 BRep_Builder().MakeCompound (aCEInv1);
1369 Standard_Integer aNbEInv = myInvalidEdges.Extent();
1370 for (i = 1; i <= aNbEInv; ++i)
1371 {
1372 const TopoDS_Shape& aE = myInvalidEdges (i);
1373 BRep_Builder().Add (aCEInv1, aE);
1374 }
1375 // show valid edges
1376 TopoDS_Compound aCEVal1;
1377 BRep_Builder().MakeCompound (aCEVal1);
1378 aNbEInv = myValidEdges.Extent();
1379 for (i = 1; i <= aNbEInv; ++i)
1380 {
1381 const TopoDS_Shape& aE = myValidEdges (i);
1382 BRep_Builder().Add (aCEVal1, aE);
1383 }
1384 // show inverted edges
1385 TopoDS_Compound aCEInverted;
1386 BRep_Builder().MakeCompound (aCEInverted);
1387 for (i = 1; i <= myInvertedEdges.Extent(); ++i)
1388 {
1389 BRep_Builder().Add (aCEInverted, myInvertedEdges(i));
1390 }
1391 #endif
1392
1393 #ifdef OFFSET_DEBUG
1394 // Show all obtained splits of faces
1395 TopoDS_Compound aCFIm1;
1396 BRep_Builder().MakeCompound (aCFIm1);
1397 #endif
1398
1399 // Build Edge-Face connectivity map to find faces which removal
1400 // may potentially lead to creation of the holes in the faces
1401 // preventing from obtaining closed volume in the result
1402 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
1403 const Standard_Integer aNbF = myOFImages.Extent();
1404 for (i = 1; i <= aNbF; ++i)
1405 {
1406 TopTools_ListIteratorOfListOfShape itLFIm (myOFImages (i));
1407 for (; itLFIm.More(); itLFIm.Next())
1408 {
1409 TopExp::MapShapesAndAncestors (itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
1410 #ifdef OFFSET_DEBUG
1411 BRep_Builder().Add (aCFIm1, itLFIm.Value());
1412 #endif
1413 }
1414 }
1415
1416 TopTools_MapOfShape anEmptyMap;
1417 // invalid faces inside the holes
1418 TopTools_IndexedMapOfShape aMFInvInHole;
1419 // all hole faces
1420 TopoDS_Compound aFHoles;
1421 aBB.MakeCompound (aFHoles);
1422 // Find the faces containing only the inverted edges and the invalid ones
1423 TopTools_ListOfShape anInvertedFaces;
1424
1425 Message_ProgressScope aPSIF (aPSOuter.Next (2.), "Checking validity of faces", aLFDone.Extent());
1426 // find invalid faces
1427 // considering faces containing only invalid edges as invalid
1428 aItLF.Initialize (aLFDone);
1429 for (; aItLF.More(); aItLF.Next(), aPSIF.Next())
1430 {
1431 if (!aPSIF.More())
1432 {
1433 return;
1434 }
1435 const TopoDS_Face& aF = TopoDS::Face (aItLF.Value());
1436 TopTools_ListOfShape& aLFImages = myOFImages.ChangeFromKey (aF);
1437 //
1438 TopTools_ListOfShape aLFInv;
1439 Standard_Boolean bArtificialCase = myArtInvalidFaces.IsBound (aF);
1440 if (bArtificialCase)
1441 {
1442 aLFInv = aLFImages;
1443 }
1444 else
1445 {
1446 // neutral edges
1447 const TopTools_MapOfShape* pMNE = aDMFMNE.ChangeSeek (aF);
1448 if (!pMNE)
1449 {
1450 pMNE = &anEmptyMap;
1451 }
1452 // find faces inside holes wires
1453 TopTools_MapOfShape aMFHoles;
1454 const TopoDS_Face& aFOr = TopoDS::Face (myFacesOrigins->Find (aF));
1455 FindFacesInsideHoleWires (aFOr, aF, aLFImages, aDMEOrLEIm, anEFMap, aMFHoles);
1456 //
1457 TopTools_MapIteratorOfMapOfShape aItMH (aMFHoles);
1458 for (; aItMH.More(); aItMH.Next())
1459 {
1460 aBB.Add (aFHoles, aItMH.Value());
1461 }
1462 //
1463 // find invalid faces
1464 FindInvalidFaces (aLFImages, aDMFMVE, aDMFMIE, *pMNE, aMEdgeInvalidByVertex,
1465 aMEdgeValidByVertex, aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
1466 }
1467 //
1468 if (aLFInv.Extent())
1469 {
1470 if (myAlreadyInvFaces.IsBound (aF))
1471 {
1472 if (myAlreadyInvFaces.Find (aF) > 2)
1473 {
1474 if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase)
1475 {
1476 aLFImages.Clear();
1477 }
1478 //
1479 aLFInv.Clear();
1480 }
1481 }
1482 myInvalidFaces.Add (aF, aLFInv);
1483 }
1484 }
1485 //
1486 if (myInvalidFaces.IsEmpty())
1487 {
1488 myInvalidEdges.Clear();
1489 return;
1490 }
1491 //
1492 #ifdef OFFSET_DEBUG
1493 // show invalid faces
1494 TopoDS_Compound aCFInv1;
1495 BRep_Builder().MakeCompound (aCFInv1);
1496 Standard_Integer aNbFInv = myInvalidFaces.Extent();
1497 for (i = 1; i <= aNbFInv; ++i)
1498 {
1499 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
1500 TopTools_ListIteratorOfListOfShape aItLFInv (aLFInv);
1501 for (; aItLFInv.More(); aItLFInv.Next())
1502 {
1503 const TopoDS_Shape& aFIm = aItLFInv.Value();
1504 BRep_Builder().Add (aCFInv1, aFIm);
1505 }
1506 }
1507 #endif
1508 //
1509 TopTools_IndexedMapOfShape aMERemoved;
1510 // remove invalid splits of faces using inverted edges
1511 RemoveInvalidSplitsByInvertedEdges (aMERemoved);
1512 if (myInvalidFaces.IsEmpty())
1513 {
1514 myInvalidEdges.Clear();
1515 return;
1516 }
1517 //
1518 // remove invalid splits from valid splits
1519 RemoveInvalidSplitsFromValid (aDMFMVIE);
1520 //
1521 // remove inside faces
1522 TopTools_IndexedMapOfShape aMEInside;
1523 RemoveInsideFaces (anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles,
1524 aMERemoved, aMEInside, aPSOuter.Next (5.));
1525 //
1526 // make compound of valid splits
1527 TopoDS_Compound aCFIm;
1528 aBB.MakeCompound (aCFIm);
1529 //
1530 aNb = myOFImages.Extent();
1531 for (i = 1; i <= aNb; ++i)
1532 {
1533 const TopTools_ListOfShape& aLFIm = myOFImages (i);
1534 aItLF.Initialize (aLFIm);
1535 for (; aItLF.More(); aItLF.Next())
1536 {
1537 const TopoDS_Shape& aFIm = aItLF.Value();
1538 aBB.Add (aCFIm, aFIm);
1539 }
1540 }
1541 //
1542 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
1543 TopExp::MapShapesAndAncestors (aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
1544 //
1545 // filter maps of images and origins
1546 FilterEdgesImages (aCFIm);
1547 //
1548 // filter invalid faces
1549 FilterInvalidFaces (aDMEF, aMEInside);
1550 aNb = myInvalidFaces.Extent();
1551 if (!aNb)
1552 {
1553 myInvalidEdges.Clear();
1554 return;
1555 }
1556 //
1557 #ifdef OFFSET_DEBUG
1558 // show invalid faces
1559 TopoDS_Compound aCFInv;
1560 BRep_Builder().MakeCompound (aCFInv);
1561 aNbFInv = myInvalidFaces.Extent();
1562 for (i = 1; i <= aNbFInv; ++i)
1563 {
1564 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
1565 TopTools_ListIteratorOfListOfShape aItLFInv (aLFInv);
1566 for (; aItLFInv.More(); aItLFInv.Next())
1567 {
1568 const TopoDS_Shape& aFIm = aItLFInv.Value();
1569 BRep_Builder().Add (aCFInv, aFIm);
1570 }
1571 }
1572 #endif
1573 //
1574 // filter invalid edges
1575 FilterInvalidEdges (aDMFMIE, aMERemoved);
1576 //
1577 // Check additionally validity of edges originated from vertices.
1578 CheckEdgesCreatedByVertex();
1579
1580 #ifdef OFFSET_DEBUG
1581 // show invalid edges
1582 TopoDS_Compound aCEInv;
1583 BRep_Builder().MakeCompound (aCEInv);
1584 aNbEInv = myInvalidEdges.Extent();
1585 for (i = 1; i <= aNbEInv; ++i)
1586 {
1587 const TopoDS_Shape& aE = myInvalidEdges (i);
1588 BRep_Builder().Add (aCEInv, aE);
1589 }
1590 #endif
1591 //
1592 myLastInvEdges.Clear();
1593 aNb = myInvalidEdges.Extent();
1594 for (i = 1; i <= aNb; ++i)
1595 {
1596 const TopoDS_Shape& aE = myInvalidEdges (i);
1597 myEdgesToAvoid.Add (aE);
1598 myLastInvEdges.Add (aE);
1599 }
1600 //
1601 aNb = myInvalidFaces.Extent();
1602 for (i = 1; i <= aNb; ++i)
1603 {
1604 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
1605 if (myAlreadyInvFaces.IsBound (aF))
1606 {
1607 myAlreadyInvFaces.ChangeFind (aF)++;
1608 }
1609 else
1610 {
1611 myAlreadyInvFaces.Bind (aF, 1);
1612 }
1613 }
1614 }
1615
1616 //=======================================================================
1617 //function : GetEdges
1618 //purpose : Getting edges from AsDes map to build the splits of faces
1619 //=======================================================================
GetEdges(const TopoDS_Face & theFace,TopoDS_Shape & theEdges,TopTools_IndexedMapOfShape * theInvMap)1620 Standard_Boolean BRepOffset_BuildOffsetFaces::GetEdges (const TopoDS_Face& theFace,
1621 TopoDS_Shape& theEdges,
1622 TopTools_IndexedMapOfShape* theInvMap)
1623 {
1624 // get boundary edges
1625 TopTools_MapOfShape aMFBounds;
1626 TopExp_Explorer aExp (theFace, TopAbs_EDGE);
1627 for (; aExp.More(); aExp.Next())
1628 {
1629 const TopoDS_Shape& aE = aExp.Current();
1630 if (const TopTools_ListOfShape* pLEIm = myOEImages.Seek (aE))
1631 {
1632 for (TopTools_ListOfShape::Iterator aItLE (*pLEIm); aItLE.More(); aItLE.Next())
1633 {
1634 aMFBounds.Add (aItLE.Value());
1635 }
1636 }
1637 else
1638 {
1639 aMFBounds.Add (aE);
1640 }
1641 }
1642
1643 BRep_Builder aBB;
1644 Standard_Boolean bFound (Standard_False), bUpdate (Standard_False);
1645 // the resulting edges
1646 TopoDS_Compound anEdges;
1647 aBB.MakeCompound (anEdges);
1648 // Fence map
1649 TopTools_MapOfShape aMEFence;
1650 // the edges by which the offset face should be split
1651 const TopTools_ListOfShape& aLE = myAsDes->Descendant (theFace);
1652 TopTools_ListIteratorOfListOfShape aItLE (aLE);
1653 for (; aItLE.More(); aItLE.Next())
1654 {
1655 const TopoDS_Edge& aE = TopoDS::Edge (aItLE.Value());
1656 //
1657 if (!bUpdate)
1658 {
1659 bUpdate = myModifiedEdges.Contains (aE);
1660 }
1661 //
1662 const TopTools_ListOfShape* pLEIm = myOEImages.Seek (aE);
1663 if (pLEIm)
1664 {
1665 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
1666 for (; aItLEIm.More(); aItLEIm.Next())
1667 {
1668 const TopoDS_Edge& aEIm = TopoDS::Edge (aItLEIm.Value());
1669 //
1670 if (!aMEFence.Add (aEIm))
1671 continue;
1672
1673 if (myEdgesToAvoid.Contains (aEIm))
1674 {
1675 if (theInvMap)
1676 {
1677 theInvMap->Add (aEIm);
1678 }
1679 if (!bUpdate)
1680 {
1681 bUpdate = myLastInvEdges.Contains (aEIm);
1682 }
1683 continue;
1684 }
1685 // check for micro edge
1686 if (ProcessMicroEdge (aEIm, myContext))
1687 {
1688 continue;
1689 }
1690 //
1691 aBB.Add (anEdges, aEIm);
1692 if (!bFound)
1693 {
1694 bFound = !aMFBounds.Contains (aEIm);
1695 }
1696 //
1697 if (!bUpdate)
1698 {
1699 bUpdate = myModifiedEdges.Contains (aEIm);
1700 }
1701 }
1702 }
1703 else
1704 {
1705 if (myEdgesToAvoid.Contains (aE))
1706 {
1707 if (theInvMap)
1708 {
1709 theInvMap->Add (aE);
1710 }
1711 if (!bUpdate)
1712 {
1713 bUpdate = myLastInvEdges.Contains (aE);
1714 }
1715 continue;
1716 }
1717 //
1718 if (ProcessMicroEdge (aE, myContext))
1719 {
1720 continue;
1721 }
1722 aBB.Add (anEdges, aE);
1723 if (!bFound)
1724 {
1725 bFound = !aMFBounds.Contains (aE);
1726 }
1727 }
1728 }
1729 //
1730 theEdges = anEdges;
1731 return bFound && bUpdate;
1732 }
1733
1734
1735 //=======================================================================
1736 //function : CheckIfArtificial
1737 //purpose : Checks if the face is artificially invalid
1738 //=======================================================================
CheckIfArtificial(const TopoDS_Shape & theF,const TopTools_ListOfShape & theLFImages,const TopoDS_Shape & theCE,const TopTools_IndexedMapOfShape & theMapEInv,TopTools_MapOfShape & theMENInv)1739 Standard_Boolean BRepOffset_BuildOffsetFaces::CheckIfArtificial (const TopoDS_Shape& theF,
1740 const TopTools_ListOfShape& theLFImages,
1741 const TopoDS_Shape& theCE,
1742 const TopTools_IndexedMapOfShape& theMapEInv,
1743 TopTools_MapOfShape& theMENInv)
1744 {
1745 // all boundary edges should be used
1746 TopTools_IndexedMapOfShape aMEUsed;
1747 TopTools_ListIteratorOfListOfShape aItLFIm (theLFImages);
1748 for (; aItLFIm.More(); aItLFIm.Next())
1749 {
1750 const TopoDS_Shape& aFIm = aItLFIm.Value();
1751 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMEUsed);
1752 TopExp::MapShapes (aFIm, TopAbs_VERTEX, aMEUsed);
1753 }
1754 //
1755 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
1756 TopExp::MapShapesAndAncestors (theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
1757 //
1758 Standard_Integer i, aNb = theMapEInv.Extent();
1759 for (i = 1; i <= aNb; ++i)
1760 {
1761 const TopoDS_Shape& aEInv = theMapEInv (i);
1762 TopExp_Explorer aExpV (aEInv, TopAbs_VERTEX);
1763 for (; aExpV.More(); aExpV.Next())
1764 {
1765 const TopoDS_Shape& aVEInv = aExpV.Current();
1766 const TopTools_ListOfShape* pLENInv = aMVE.Seek (aVEInv);
1767 if (pLENInv)
1768 {
1769 TopTools_ListIteratorOfListOfShape aItLEInv (*pLENInv);
1770 for (; aItLEInv.More(); aItLEInv.Next())
1771 {
1772 const TopoDS_Shape& aENInv = aItLEInv.Value();
1773 if (!aMEUsed.Contains (aENInv))
1774 {
1775 theMENInv.Add (aENInv);
1776 }
1777 }
1778 }
1779 }
1780 }
1781 //
1782 if (theMENInv.IsEmpty())
1783 {
1784 return Standard_False;
1785 }
1786 //
1787 TopTools_IndexedMapOfShape aMEFound;
1788 TopExp::MapShapes (theCE, TopAbs_EDGE, aMEFound);
1789 //
1790 const TopTools_ListOfShape& aLE = myAsDes->Descendant (theF);
1791 TopTools_ListIteratorOfListOfShape aItLE (aLE);
1792 for (; aItLE.More(); aItLE.Next())
1793 {
1794 const TopoDS_Edge& aE = TopoDS::Edge (aItLE.Value());
1795 //
1796 if (myOEImages.IsBound (aE))
1797 {
1798 Standard_Boolean bChecked = Standard_False;
1799 const TopTools_ListOfShape& aLEIm = myOEImages.Find (aE);
1800 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
1801 for (; aItLEIm.More(); aItLEIm.Next())
1802 {
1803 const TopoDS_Edge& aEIm = TopoDS::Edge (aItLEIm.Value());
1804 if (!aMEFound.Contains (aEIm) || theMENInv.Contains (aEIm))
1805 {
1806 continue;
1807 }
1808 //
1809 bChecked = Standard_True;
1810 if (aMEUsed.Contains (aEIm))
1811 {
1812 break;
1813 }
1814 }
1815 //
1816 if (bChecked && !aItLEIm.More())
1817 {
1818 break;
1819 }
1820 }
1821 else
1822 {
1823 if (aMEFound.Contains (aE) && !theMENInv.Contains (aE) && !aMEUsed.Contains (aE))
1824 {
1825 break;
1826 }
1827 }
1828 }
1829 //
1830 return aItLE.More();
1831 }
1832
1833 //=======================================================================
1834 //function : FindInvalidEdges
1835 //purpose : Looking for the invalid edges
1836 //=======================================================================
FindInvalidEdges(const TopoDS_Face & theF,const TopTools_ListOfShape & theLFImages,BRepOffset_DataMapOfShapeMapOfShape & theDMFMVE,BRepOffset_DataMapOfShapeMapOfShape & theDMFMNE,BRepOffset_DataMapOfShapeIndexedMapOfShape & theDMFMIE,BRepOffset_DataMapOfShapeMapOfShape & theDMFMVIE,TopTools_DataMapOfShapeListOfShape & theDMEOrLEIm,TopTools_MapOfShape & theEdgesInvalidByVertex,TopTools_MapOfShape & theEdgesValidByVertex,const Message_ProgressRange & theRange)1837 void BRepOffset_BuildOffsetFaces::FindInvalidEdges (const TopoDS_Face& theF,
1838 const TopTools_ListOfShape& theLFImages,
1839 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
1840 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
1841 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
1842 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
1843 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
1844 TopTools_MapOfShape& theEdgesInvalidByVertex,
1845 TopTools_MapOfShape& theEdgesValidByVertex,
1846 const Message_ProgressRange& theRange)
1847 {
1848 // Edge is considered as invalid in the following cases:
1849 // 1. Its orientation on the face has changed comparing to the originals edge and face;
1850 // 2. The vertices of the edge have changed places comparing to the originals edge and face.
1851 //
1852 // The edges created from vertices, i.e. as intersection between two faces connected only
1853 // by VERTEX, will also be checked on validity. For these edges the correct orientation will
1854 // be defined by the edges on the original face adjacent to the connection vertex
1855
1856 // original face
1857 const TopoDS_Face& aFOr = *(TopoDS_Face*)&myFacesOrigins->Find (theF);
1858 // invalid edges
1859 TopTools_IndexedMapOfShape aMEInv;
1860 // valid edges
1861 TopTools_MapOfShape aMEVal;
1862 // internal edges
1863 TopTools_MapOfShape aMEInt;
1864 //
1865 // maps for checking the inverted edges
1866 TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
1867 TopTools_IndexedMapOfShape aMEdges;
1868 // back map from the original shapes to their offset images
1869 TopTools_DataMapOfShapeListOfShape anImages;
1870 //
1871 Message_ProgressScope aPS (theRange, "Checking validity of edges", 2 * theLFImages.Extent());
1872 TopTools_ListIteratorOfListOfShape aItLF (theLFImages);
1873 for (; aItLF.More(); aItLF.Next(), aPS.Next())
1874 {
1875 if (!aPS.More())
1876 {
1877 return;
1878 }
1879 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1880 //
1881 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
1882 for (; aExp.More(); aExp.Next())
1883 {
1884 const TopoDS_Shape& aE = aExp.Current();
1885 // keep all edges
1886 aMEdges.Add (aE);
1887 //
1888 // keep connection from edges to faces
1889 TopTools_ListOfShape* pLF = aDMEF.ChangeSeek (aE);
1890 if (!pLF)
1891 {
1892 pLF = &aDMEF (aDMEF.Add (aE, TopTools_ListOfShape()));
1893 }
1894 AppendToList (*pLF, aFIm);
1895 //
1896 // keep connection from vertices to edges
1897 TopoDS_Iterator aItV (aE);
1898 for (; aItV.More(); aItV.Next())
1899 {
1900 const TopoDS_Shape& aV = aItV.Value();
1901 //
1902 TopTools_ListOfShape* pLE = aDMVE.ChangeSeek (aV);
1903 if (!pLE)
1904 {
1905 pLE = &aDMVE (aDMVE.Add (aV, TopTools_ListOfShape()));
1906 }
1907 AppendToList (*pLE, aE);
1908 }
1909
1910 // back map from original edges to their offset images
1911 const TopTools_ListOfShape* pLOr = myEdgesOrigins->Seek (aE);
1912 if (!pLOr)
1913 continue;
1914 for (TopTools_ListOfShape::Iterator itOr (*pLOr); itOr.More(); itOr.Next())
1915 {
1916 const TopoDS_Shape& aSOr = itOr.Value();
1917 TopoDS_Shape aSInF;
1918 if (!FindShape (aSOr, aFOr, myAnalyzer, aSInF))
1919 continue;
1920 TopTools_ListOfShape* pImages = anImages.ChangeSeek (aSInF);
1921 if (!pImages)
1922 pImages = anImages.Bound (aSInF, TopTools_ListOfShape());
1923 AppendToList (*pImages, aE);
1924 }
1925 }
1926 }
1927 //
1928 // the map will be used to find the edges on the original face
1929 // adjacent to the same vertex. It will be filled at first necessity;
1930 TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
1931 //
1932 aItLF.Initialize (theLFImages);
1933 for (; aItLF.More(); aItLF.Next(), aPS.Next())
1934 {
1935 if (!aPS.More())
1936 {
1937 return;
1938 }
1939 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1940 //
1941 // valid edges for this split
1942 TopTools_MapOfShape aMVE;
1943 // invalid edges for this split
1944 TopTools_IndexedMapOfShape aMIE;
1945 //
1946 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
1947 for (; aExp.More(); aExp.Next())
1948 {
1949 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
1950 //
1951 if (aEIm.Orientation() == TopAbs_INTERNAL)
1952 {
1953 aMEInt.Add (aEIm);
1954 continue;
1955 }
1956 //
1957 const TopTools_ListOfShape* pLEOr = myEdgesOrigins->Seek (aEIm);
1958 if (!pLEOr || pLEOr->IsEmpty())
1959 {
1960 continue;
1961 }
1962 //
1963 Standard_Integer aNbVOr = 0;
1964 TopTools_ListIteratorOfListOfShape aItLEO (*pLEOr);
1965 for (; aItLEO.More(); aItLEO.Next())
1966 {
1967 if (aItLEO.Value().ShapeType() == TopAbs_VERTEX)
1968 {
1969 ++aNbVOr;
1970 }
1971 }
1972 if (aNbVOr > 1 && (pLEOr->Extent() - aNbVOr) > 1)
1973 continue;
1974 //
1975 TopTools_MapOfShape aME, aMV, aMF;
1976 Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
1977 Standard_Integer aNbP = NbPoints (aEIm), aNbInv = 0;
1978 Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
1979 (aNbVOr == 1 &&
1980 aDMEF.FindFromKey (aEIm).Extent() == 1 &&
1981 !myOEOrigins.IsBound (aEIm));
1982 //
1983 aItLEO.Initialize (*pLEOr);
1984 for (; aItLEO.More(); aItLEO.Next())
1985 {
1986 const TopoDS_Shape& aSOr = aItLEO.Value();
1987 Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
1988 //
1989 TopoDS_Shape aEOrF;
1990 if (bVertex)
1991 {
1992 // for some cases it is impossible to check the validity of the edge
1993 if (!bUseVertex)
1994 {
1995 continue;
1996 }
1997 // find edges on the original face adjacent to this vertex
1998 if (aDMVEFOr.IsEmpty())
1999 {
2000 // fill the map
2001 TopExp::MapShapesAndAncestors (aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
2002 }
2003 //
2004 TopTools_ListOfShape* pLEFOr = aDMVEFOr.ChangeSeek (aSOr);
2005 if (pLEFOr)
2006 {
2007 TopoDS_Compound aCEOr;
2008 BRep_Builder().MakeCompound (aCEOr);
2009 // Avoid classification of edges originated from vertices
2010 // located between tangent edges
2011 Standard_Boolean bAllTgt = Standard_True;
2012 TopTools_ListIteratorOfListOfShape aItLEFOr (*pLEFOr);
2013 gp_Vec aVRef = GetAverageTangent (aItLEFOr.Value(), aNbP);
2014 for (; aItLEFOr.More(); aItLEFOr.Next())
2015 {
2016 const TopoDS_Shape& aEOr = aItLEFOr.Value();
2017 BRep_Builder().Add (aCEOr, aEOr);
2018
2019 gp_Vec aVCur = GetAverageTangent (aEOr, aNbP);
2020 if (!aVRef.IsParallel (aVCur, Precision::Angular()))
2021 bAllTgt = Standard_False;
2022 }
2023 if (!bAllTgt)
2024 aEOrF = aCEOr;
2025 }
2026 }
2027 else
2028 {
2029 FindShape (aSOr, aFOr, myAnalyzer, aEOrF);
2030 //
2031 TopTools_ListOfShape* pLEIm = theDMEOrLEIm.ChangeSeek (aSOr);
2032 if (!pLEIm)
2033 {
2034 pLEIm = theDMEOrLEIm.Bound (aSOr, TopTools_ListOfShape());
2035 }
2036 AppendToList (*pLEIm, aEIm);
2037 }
2038 //
2039 if (aEOrF.IsNull())
2040 {
2041 // the edge has not been found
2042 continue;
2043 }
2044
2045 if (bVertex)
2046 {
2047 TopTools_MapOfShape aMVTotal;
2048 Standard_Integer aNbChecked = 0;
2049 // Just check if the original edges sharing the vertex do not share it any more.
2050 for (TopoDS_Iterator it (aEOrF); it.More(); it.Next())
2051 {
2052 const TopoDS_Shape& aEOr = it.Value();
2053 const TopTools_ListOfShape* aLIm = anImages.Seek (aEOr);
2054 if (!aLIm)
2055 continue;
2056 ++aNbChecked;
2057 TopTools_IndexedDataMapOfShapeListOfShape aMVLoc;
2058 for (TopTools_ListOfShape::Iterator itLIM (*aLIm); itLIM.More(); itLIM.Next())
2059 TopExp::MapShapesAndAncestors (itLIM.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVLoc);
2060 for (Standard_Integer i = 1; i <= aMVLoc.Extent(); ++i)
2061 {
2062 if (aMVLoc (i).Extent() > 1 && !aMVTotal.Add (aMVLoc.FindKey (i)))
2063 {
2064 bInvalid = Standard_True;
2065 theEdgesInvalidByVertex.Add (aEIm);
2066 break;
2067 }
2068 }
2069 if (bInvalid)
2070 break;
2071 }
2072 if (!bInvalid && aNbChecked < 2)
2073 continue;
2074 else
2075 theEdgesValidByVertex.Add (aEIm);
2076 }
2077 else
2078 {
2079 //
2080 // Check orientations of the image edge and original edge.
2081 // In case the 3d curves are having the same direction the orientations
2082 // must be the same. Otherwise the orientations should also be different.
2083 //
2084 // get average tangent vector for each curve taking into account
2085 // the orientations of the edges, i.e. the edge is reversed
2086 // the vector is reversed as well
2087 gp_Vec aVSum1 = GetAverageTangent (aEIm, aNbP);
2088 gp_Vec aVSum2 = GetAverageTangent (aEOrF, aNbP);
2089 //
2090 aVSum1.Normalize();
2091 aVSum2.Normalize();
2092 //
2093 Standard_Real aCos = aVSum1.Dot (aVSum2);
2094 if (Abs (aCos) < 0.9999)
2095 {
2096 continue;
2097 }
2098 //
2099 aME.Add (aEOrF);
2100 TopExp_Explorer aExpE (aEOrF, TopAbs_VERTEX);
2101 for (; aExpE.More(); aExpE.Next())
2102 {
2103 const TopoDS_Shape& aV = aExpE.Current();
2104 aMV.Add (aV);
2105 }
2106 if (myAnalyzer)
2107 {
2108 for (TopTools_ListOfShape::Iterator itFA (myAnalyzer->Ancestors (aEOrF));
2109 itFA.More(); itFA.Next())
2110 aMF.Add (itFA.Value());
2111 }
2112 //
2113 if (aCos < Precision::Confusion())
2114 {
2115 bInvalid = Standard_True;
2116 aNbInv++;
2117 }
2118 }
2119 bChecked = Standard_True;
2120 }
2121 //
2122 if (!bChecked)
2123 {
2124 continue;
2125 }
2126 //
2127 Standard_Boolean bLocalOnly = (aNbVOr > 1 && (pLEOr->Extent() - aNbVOr) > 1);
2128 Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
2129 if (aNbE > 1 && aNbV == 2 * aNbE)
2130 {
2131 Standard_Boolean bSkip = Standard_True;
2132
2133 // It seems the edge originated from not connected edges and cannot be
2134 // considered as correctly classified as it may fill some undesired parts.
2135 // Still, allow the edge to be accounted for local analysis if it is:
2136 // * originated from more than two faces
2137 // * unanimously considered valid or invalid
2138 // * not a boundary edge in the splits
2139 if (aMF.Extent() > 2 && (aNbInv == 0 || aNbInv == aNbE))
2140 {
2141 if (theLFImages.Extent() > 2)
2142 {
2143 TopoDS_Iterator itV (aEIm);
2144 for (; itV.More(); itV.Next())
2145 {
2146 TopTools_ListOfShape::Iterator itE (aDMVE.FindFromKey (itV.Value()));
2147 for (; itE.More(); itE.Next())
2148 if (aDMEF.FindFromKey (itE.Value()).Extent() < 2)
2149 break;
2150 if (itE.More())
2151 break;
2152 }
2153 bSkip = itV.More();
2154 }
2155 }
2156 if (bSkip)
2157 continue;
2158 else
2159 bLocalOnly = Standard_True;
2160 }
2161 //
2162 if (bInvalid)
2163 {
2164 if (!bLocalOnly)
2165 myInvalidEdges.Add (aEIm);
2166 aMIE.Add (aEIm);
2167 aMEInv.Add (aEIm);
2168 continue;
2169 }
2170 //
2171 // check if the edge has been inverted
2172 Standard_Boolean bInverted = !aNbE || bLocalOnly ? Standard_False :
2173 CheckInverted (aEIm, aFOr, aDMVE, aMEdges);
2174 //
2175 if (!bInverted || !aNbVOr)
2176 {
2177 if (!bLocalOnly)
2178 myValidEdges.Add (aEIm);
2179 aMVE.Add (aEIm);
2180 aMEVal.Add (aEIm);
2181 }
2182 }
2183 //
2184 // valid edges
2185 if (aMVE.Extent())
2186 {
2187 theDMFMVE.Bind (aFIm, aMVE);
2188 }
2189 //
2190 // invalid edges
2191 if (aMIE.Extent())
2192 {
2193 theDMFMIE.Bind (aFIm, aMIE);
2194 }
2195 }
2196 //
2197 // process invalid edges:
2198 // check for the inverted edges
2199 TopTools_MapOfShape aMVIE;
2200 // fill neutral edges
2201 TopTools_MapOfShape aMNE;
2202 //
2203 Standard_Integer i, aNbEInv = aMEInv.Extent();
2204 for (i = 1; i <= aNbEInv; ++i)
2205 {
2206 const TopoDS_Shape& aEIm = aMEInv (i);
2207 //
2208 // neutral edges - on the splits of the same offset face
2209 // it is valid for one split and invalid for other
2210 if (aMEVal.Contains (aEIm))
2211 {
2212 aMNE.Add (aEIm);
2213 continue;
2214 }
2215 //
2216 // the inverted images of the origins of invalid edges should also be invalid
2217 if (!myInvertedEdges.Contains (aEIm))
2218 {
2219 continue;
2220 }
2221 //
2222 const TopTools_ListOfShape* pLOEOr = myOEOrigins.Seek (aEIm);
2223 if (!pLOEOr)
2224 {
2225 continue;
2226 }
2227 //
2228 TopTools_ListIteratorOfListOfShape aItLOEOr (*pLOEOr);
2229 for (; aItLOEOr.More(); aItLOEOr.Next())
2230 {
2231 const TopoDS_Shape& aOEOr = aItLOEOr.Value();
2232 const TopTools_ListOfShape& aLEIm1 = myOEImages.Find (aOEOr);
2233 //
2234 TopTools_ListIteratorOfListOfShape aItLEIm1 (aLEIm1);
2235 for (; aItLEIm1.More(); aItLEIm1.Next())
2236 {
2237 const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
2238 if (aMEdges.Contains (aEIm1) &&
2239 !aMEInv.Contains (aEIm1) && !aMEInt.Contains (aEIm1) &&
2240 myInvertedEdges.Contains (aEIm1))
2241 {
2242 myInvalidEdges.Add (aEIm1);
2243 aMVIE.Add (aEIm1);
2244 }
2245 }
2246 }
2247 }
2248 //
2249 if (aMNE.Extent())
2250 {
2251 theDMFMNE.Bind (theF, aMNE);
2252 }
2253 //
2254 if (aMVIE.Extent())
2255 {
2256 theDMFMVIE.Bind (theF, aMVIE);
2257 }
2258 }
2259
2260 namespace {
2261 //=======================================================================
2262 //function : addAsNeutral
2263 //purpose : Adds as the edge into corresponding maps making it neutral
2264 //=======================================================================
addAsNeutral(const TopoDS_Shape & theE,const TopoDS_Shape & theFInv,const TopoDS_Shape & theFVal,BRepOffset_DataMapOfShapeIndexedMapOfShape & theLocInvEdges,BRepOffset_DataMapOfShapeMapOfShape & theLocValidEdges)2265 static void addAsNeutral (const TopoDS_Shape& theE,
2266 const TopoDS_Shape& theFInv,
2267 const TopoDS_Shape& theFVal,
2268 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2269 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges)
2270 {
2271 TopTools_IndexedMapOfShape* pMEInv = theLocInvEdges.ChangeSeek (theFInv);
2272 if (!pMEInv)
2273 pMEInv = theLocInvEdges.Bound (theFInv, TopTools_IndexedMapOfShape());
2274 pMEInv->Add (theE);
2275
2276 TopTools_MapOfShape* pMEVal = theLocValidEdges.ChangeSeek (theFVal);
2277 if (!pMEVal)
2278 pMEVal = theLocValidEdges.Bound (theFVal, TopTools_MapOfShape());
2279 pMEVal->Add (theE);
2280 }
2281
2282 }
2283 //=======================================================================
2284 //function : FindInvalidEdges
2285 //purpose : Additional method to look for invalid edges
2286 //=======================================================================
FindInvalidEdges(const TopTools_ListOfShape & theLFOffset,BRepOffset_DataMapOfShapeIndexedMapOfShape & theLocInvEdges,BRepOffset_DataMapOfShapeMapOfShape & theLocValidEdges,BRepOffset_DataMapOfShapeMapOfShape & theNeutralEdges)2287 void BRepOffset_BuildOffsetFaces::FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
2288 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2289 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
2290 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges)
2291 {
2292 // 1. Find edges unclassified in faces
2293 // 2. Find SD faces in which the same edge is classified
2294 // 3. Check if the edge is neutral in face in which it wasn't classified
2295
2296 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aMEUnclassified;
2297 TopTools_DataMapOfShapeShape aFSplitFOffset;
2298
2299 // Avoid artificial faces
2300 TopTools_MapOfShape aNewFaces;
2301 if (myAnalyzer)
2302 {
2303 TopTools_MapOfShape aMapNewTmp;
2304 for (TopTools_ListOfShape::Iterator it (myAnalyzer->NewFaces()); it.More(); it.Next())
2305 aMapNewTmp.Add (it.Value());
2306
2307 for (TopTools_ListOfShape::Iterator it (theLFOffset); it.More(); it.Next())
2308 {
2309 const TopoDS_Shape& aFOffset = it.Value();
2310 const TopoDS_Shape& aFOrigin = myFacesOrigins->Find (aFOffset);
2311 if (aMapNewTmp.Contains (aFOrigin))
2312 aNewFaces.Add (aFOffset);
2313 }
2314 }
2315
2316 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
2317 for (TopTools_ListOfShape::Iterator itLFO (theLFOffset); itLFO.More(); itLFO.Next())
2318 {
2319 const TopoDS_Shape& aF = itLFO.Value();
2320 if (aNewFaces.Contains (aF))
2321 continue;
2322
2323 const TopTools_ListOfShape& aLFImages = myOFImages.FindFromKey (aF);
2324 for (TopTools_ListOfShape::Iterator itLF (aLFImages); itLF.More(); itLF.Next())
2325 {
2326 const TopoDS_Shape& aFIm = itLF.Value();
2327
2328 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFMap);
2329
2330 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFIm);
2331 const TopTools_MapOfShape* pMEValid = theLocValidEdges.Seek (aFIm);
2332
2333 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
2334 {
2335 const TopoDS_Shape& aE = expE.Current();
2336 if (myInvalidEdges.Contains (aE) != myValidEdges.Contains (aE))
2337 {
2338 // edge is classified in some face
2339
2340 if ((!pMEInvalid || !pMEInvalid->Contains (aE)) &&
2341 (!pMEValid || !pMEValid->Contains (aE)))
2342 {
2343 // but not in the current one
2344 TopTools_MapOfShape* pMap = aMEUnclassified.ChangeSeek (aE);
2345 if (!pMap)
2346 pMap = &aMEUnclassified (aMEUnclassified.Add (aE, TopTools_MapOfShape()));
2347 pMap->Add (aFIm);
2348
2349 aFSplitFOffset.Bind (aFIm, aF);
2350 }
2351 }
2352 }
2353 }
2354 }
2355
2356 if (aMEUnclassified.IsEmpty())
2357 return;
2358
2359 // Analyze unclassified edges
2360 const Standard_Integer aNbE = aMEUnclassified.Extent();
2361 for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
2362 {
2363 const TopoDS_Shape& aE = aMEUnclassified.FindKey (iE);
2364 const TopTools_MapOfShape& aMFUnclassified = aMEUnclassified (iE);
2365
2366 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
2367
2368 for (TopTools_ListOfShape::Iterator itLF (aLF); itLF.More(); itLF.Next())
2369 {
2370 const TopoDS_Shape& aFClassified = itLF.Value();
2371 if (aMFUnclassified.Contains (aFClassified))
2372 continue;
2373
2374 BOPTools_Set anEdgeSetClass;
2375 anEdgeSetClass.Add (aFClassified, TopAbs_EDGE);
2376
2377 TopoDS_Shape aEClassified;
2378 FindShape (aE, aFClassified, NULL, aEClassified);
2379 TopAbs_Orientation anOriClass = aEClassified.Orientation();
2380
2381 gp_Dir aDNClass;
2382 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aEClassified), TopoDS::Face (aFClassified), aDNClass);
2383
2384 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFClassified);
2385 Standard_Boolean isInvalid = pMEInvalid && pMEInvalid->Contains (aE);
2386
2387 for (TopTools_MapOfShape::Iterator itM (aMFUnclassified); itM.More(); itM.Next())
2388 {
2389 const TopoDS_Shape& aFUnclassified = itM.Value();
2390
2391 BOPTools_Set anEdgeSetUnclass;
2392 anEdgeSetUnclass.Add (aFUnclassified, TopAbs_EDGE);
2393
2394 if (anEdgeSetClass.IsEqual (anEdgeSetUnclass))
2395 {
2396 gp_Dir aDNUnclass;
2397 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aE), TopoDS::Face (aFUnclassified), aDNUnclass);
2398
2399 Standard_Boolean isSameOri = aDNClass.IsEqual (aDNUnclass, Precision::Angular());
2400
2401 // Among other splits of the same face find those where the edge is contained with different
2402 // orientation
2403 const TopoDS_Shape& aFOffset = aFSplitFOffset.Find (aFUnclassified);
2404 const TopTools_ListOfShape& aLFSplits = myOFImages.FindFromKey (aFOffset);
2405 TopTools_ListOfShape::Iterator itLFSp (aLFSplits);
2406 for (; itLFSp.More(); itLFSp.Next())
2407 {
2408 const TopoDS_Shape& aFSp = itLFSp.Value();
2409
2410 if (!aFSp.IsSame (aFUnclassified) && aMFUnclassified.Contains (aFSp))
2411 {
2412 TopoDS_Shape aEUnclassified;
2413 FindShape (aE, aFSp, NULL, aEUnclassified);
2414
2415 TopAbs_Orientation anOriUnclass = aEUnclassified.Orientation();
2416 if (!isSameOri)
2417 anOriUnclass = TopAbs::Reverse (anOriUnclass);
2418
2419 if (anOriClass != anOriUnclass)
2420 {
2421 // make the edge neutral for the face
2422 TopTools_MapOfShape* pMENeutral = theNeutralEdges.ChangeSeek (aFOffset);
2423 if (!pMENeutral)
2424 pMENeutral = theNeutralEdges.Bound (aFOffset, TopTools_MapOfShape());
2425 pMENeutral->Add (aE);
2426
2427 if (isInvalid && isSameOri)
2428 {
2429 // make edge invalid in aFUnclassified and valid in aFSp
2430 addAsNeutral (aE, aFClassified, aFSp, theLocInvEdges, theLocValidEdges);
2431 }
2432 else
2433 {
2434 // make edge invalid in aFSp and valid in aFUnclassified
2435 addAsNeutral (aE, aFSp, aFClassified, theLocInvEdges, theLocValidEdges);
2436 }
2437 }
2438 }
2439 }
2440 if (itLFSp.More())
2441 break;
2442 }
2443 }
2444 }
2445 }
2446 }
2447
2448 //=======================================================================
2449 //function : MakeInvertedEdgesInvalid
2450 //purpose : Makes inverted edges located inside loop of invalid edges, invalid as well
2451 //=======================================================================
MakeInvertedEdgesInvalid(const TopTools_ListOfShape & theLFOffset)2452 void BRepOffset_BuildOffsetFaces::MakeInvertedEdgesInvalid (const TopTools_ListOfShape& theLFOffset)
2453 {
2454 if (myInvalidEdges.IsEmpty() || myInvertedEdges.IsEmpty())
2455 return;
2456
2457 // Map all invalid edges
2458 TopoDS_Compound aCBEInv;
2459 BRep_Builder().MakeCompound (aCBEInv);
2460 for (Standard_Integer i = 1; i <= myInvalidEdges.Extent(); ++i)
2461 {
2462 BRep_Builder().Add (aCBEInv, myInvalidEdges (i));
2463 }
2464
2465 // Make loops of invalid edges
2466 TopTools_ListOfShape aLCB;
2467 BOPTools_AlgoTools::MakeConnexityBlocks (aCBEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCB);
2468
2469 // Analyze each loop on closeness and use only closed ones
2470 TopTools_DataMapOfShapeShape aDMVCB;
2471
2472 for (TopTools_ListOfShape::Iterator itLCB (aLCB); itLCB.More(); itLCB.Next())
2473 {
2474 const TopoDS_Shape& aCB = itLCB.Value();
2475
2476 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
2477 TopExp::MapShapesAndAncestors (aCB, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
2478 Standard_Boolean isClosed = Standard_True;
2479 for (Standard_Integer iV = 1; iV <= aDMVE.Extent(); ++iV)
2480 {
2481 if (aDMVE (iV).Extent() != 2)
2482 {
2483 isClosed = Standard_False;
2484 break;
2485 }
2486 }
2487 if (!isClosed)
2488 continue;
2489
2490 // Bind loop to each vertex of the loop
2491 for (Standard_Integer iV = 1; iV <= aDMVE.Extent(); ++iV)
2492 {
2493 aDMVCB.Bind (aDMVE.FindKey (iV), aCB);
2494 }
2495 }
2496
2497 // Check if any inverted edges of offset faces are locked inside the loops of invalid edges.
2498 // Make such edges invalid as well.
2499 for (TopTools_ListOfShape::Iterator itLF (theLFOffset); itLF.More(); itLF.Next())
2500 {
2501 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (itLF.Value());
2502 for (TopTools_ListOfShape::Iterator itLFIm (aLFIm); itLFIm.More(); itLFIm.Next())
2503 {
2504 for (TopExp_Explorer expE (itLFIm.Value(), TopAbs_EDGE); expE.More(); expE.Next())
2505 {
2506 const TopoDS_Edge& aE = TopoDS::Edge (expE.Current());
2507 if (!myInvalidEdges.Contains (aE) && myInvertedEdges.Contains (aE))
2508 {
2509 const TopoDS_Shape* pCB1 = aDMVCB.Seek (TopExp::FirstVertex (aE));
2510 const TopoDS_Shape* pCB2 = aDMVCB.Seek (TopExp::LastVertex (aE));
2511 if (pCB1 && pCB2 && pCB1->IsSame (*pCB2))
2512 {
2513 myInvalidEdges.Add (aE);
2514 }
2515 }
2516 }
2517 }
2518 }
2519 }
2520
2521 //=======================================================================
2522 //function : FindInvalidFaces
2523 //purpose : Looking for the invalid faces by analyzing their invalid edges
2524 //=======================================================================
FindInvalidFaces(TopTools_ListOfShape & theLFImages,const BRepOffset_DataMapOfShapeMapOfShape & theDMFMVE,const BRepOffset_DataMapOfShapeIndexedMapOfShape & theDMFMIE,const TopTools_MapOfShape & theMENeutral,const TopTools_MapOfShape & theEdgesInvalidByVertex,const TopTools_MapOfShape & theEdgesValidByVertex,const TopTools_MapOfShape & theMFHoles,TopTools_IndexedMapOfShape & theMFInvInHole,TopTools_ListOfShape & theInvFaces,TopTools_ListOfShape & theInvertedFaces)2525 void BRepOffset_BuildOffsetFaces::FindInvalidFaces (TopTools_ListOfShape& theLFImages,
2526 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
2527 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
2528 const TopTools_MapOfShape& theMENeutral,
2529 const TopTools_MapOfShape& theEdgesInvalidByVertex,
2530 const TopTools_MapOfShape& theEdgesValidByVertex,
2531 const TopTools_MapOfShape& theMFHoles,
2532 TopTools_IndexedMapOfShape& theMFInvInHole,
2533 TopTools_ListOfShape& theInvFaces,
2534 TopTools_ListOfShape& theInvertedFaces)
2535 {
2536 // The face should be considered as invalid in the following cases:
2537 // 1. It has been reverted, i.e. at least two not connected edges
2538 // have changed orientation (i.e. invalid). In this case all edges,
2539 // should be invalid for that face, because edges have also been reverted;
2540 // 2. All checked edges of the face are invalid for this face;
2541 // The face should be removed from the splits in the following cases:
2542 // 1. All checked edges of the face are invalid for this one, but valid for
2543 // some other face in this list of splits.
2544 // The face will be kept in the following cases:
2545 // 1. Some of the edges are valid for this face.
2546 Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
2547 Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
2548 Standard_Boolean bIsInvalidByInverted, bHasInverted;
2549 Standard_Integer aNbChecked;
2550 //
2551 Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
2552 //
2553 // neutral edges to remove
2554 TopTools_IndexedMapOfShape aMENRem;
2555 //
2556 // faces for post treat
2557 TopTools_ListOfShape aLFPT;
2558 //
2559 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
2560 TopTools_ListIteratorOfListOfShape aItLF (theLFImages);
2561 for (; aItLF.More(); aItLF.Next())
2562 {
2563 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2564 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
2565 }
2566
2567 aItLF.Initialize (theLFImages);
2568 for (; aItLF.More(); )
2569 {
2570 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2571 //
2572 // valid edges for this split
2573 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
2574 // invalid edges for this split
2575 const TopTools_IndexedMapOfShape* pMIE = theDMFMIE.Seek (aFIm);
2576 //
2577 bHasValid = Standard_False;
2578 bAllValid = Standard_True;
2579 bAllInvalid = Standard_True;
2580 bHasReallyInvalid = Standard_False;
2581 bAllInvNeutral = Standard_True;
2582 bIsInvalidByInverted = Standard_True;
2583 bHasInverted = Standard_False;
2584 aNbChecked = 0;
2585 //
2586 const TopoDS_Wire& aWIm = BRepTools::OuterWire (aFIm);
2587 TopExp_Explorer aExp (aWIm, TopAbs_EDGE);
2588 for (; aExp.More(); aExp.Next())
2589 {
2590 const TopoDS_Shape& aEIm = aExp.Current();
2591 //
2592 bValid = myValidEdges.Contains (aEIm);
2593 bInvalid = myInvalidEdges.Contains (aEIm);
2594 bNeutral = theMENeutral.Contains (aEIm);
2595 //
2596 if (!bValid && !bInvalid && !bNeutral)
2597 {
2598 // edge has not been checked for some reason
2599 continue;
2600 }
2601
2602 // skip not-boundary edges originated from vertex
2603 if ((theEdgesInvalidByVertex.Contains (aEIm) ||
2604 theEdgesValidByVertex.Contains (aEIm)) &&
2605 aDMEF.FindFromKey (aEIm).Extent() != 1)
2606 continue;
2607
2608 ++aNbChecked;
2609 //
2610 bInvalidLoc = pMIE && pMIE->Contains (aEIm);
2611 bHasReallyInvalid = bInvalid && bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains (aEIm);
2612 if (bHasReallyInvalid)
2613 {
2614 break;
2615 }
2616 //
2617 bValidLoc = pMVE && pMVE->Contains (aEIm);
2618 bInverted = myInvertedEdges.Contains (aEIm);
2619 if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid)
2620 {
2621 bInvalid = bInverted;
2622 }
2623 //
2624 if (bValidLoc && bNeutral)
2625 {
2626 bHasValid = Standard_True;
2627 }
2628 //
2629 bAllValid &= bValidLoc;
2630 bAllInvalid &= (bInvalid || bInvalidLoc);
2631 bAllInvNeutral &= (bAllInvalid && bNeutral);
2632 bIsInvalidByInverted &= (bInvalidLoc || bInverted);
2633 bHasInverted |= bInverted;
2634 }
2635 //
2636 if (!aNbChecked)
2637 {
2638 aItLF.Next();
2639 continue;
2640 }
2641 //
2642 if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1))
2643 {
2644 if (bHasInverted)
2645 {
2646 // The part seems to be filled due to overlapping of parts rather than
2647 // due to multi-connection of faces. No need to remove the part.
2648 aItLF.Next();
2649 continue;
2650 }
2651 // remove edges from neutral
2652 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMENRem);
2653 // remove face
2654 theLFImages.Remove (aItLF);
2655 continue;
2656 }
2657 //
2658 if (bHasReallyInvalid || (bAllInvalid &&
2659 !(bHasValid || bAllValid) &&
2660 !(bAllInvNeutral && (aNbChecked == 1))))
2661 {
2662 theInvFaces.Append (aFIm);
2663 if (theMFHoles.Contains (aFIm))
2664 {
2665 theMFInvInHole.Add (aFIm);
2666 }
2667 aItLF.Next();
2668 continue;
2669 }
2670 //
2671 if (theMFHoles.Contains (aFIm))
2672 {
2673 // remove edges from neutral
2674 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMENRem);
2675 // remove face
2676 theLFImages.Remove (aItLF);
2677 continue;
2678 }
2679 //
2680 if (bIsInvalidByInverted && !(bHasValid || bAllValid))
2681 {
2682 // The face contains only the inverted and locally invalid edges
2683 theInvertedFaces.Append (aFIm);
2684 }
2685
2686 if (!bAllInvNeutral)
2687 {
2688 aLFPT.Append (aFIm);
2689 }
2690 else
2691 {
2692 // remove edges from neutral
2693 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMENRem);
2694 }
2695 aItLF.Next();
2696 }
2697 //
2698 if (aLFPT.IsEmpty() || aMENRem.IsEmpty())
2699 {
2700 return;
2701 }
2702
2703 // check the splits once more
2704 aItLF.Initialize (aLFPT);
2705 for (; aItLF.More(); aItLF.Next())
2706 {
2707 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2708 //
2709 // valid edges for this split
2710 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
2711 //
2712 bHasValid = Standard_False;
2713 bAllValid = Standard_True;
2714 bAllInvalid = Standard_True;
2715 //
2716 const TopoDS_Wire& aWIm = BRepTools::OuterWire (aFIm);
2717 TopExp_Explorer aExp (aWIm, TopAbs_EDGE);
2718 for (; aExp.More(); aExp.Next())
2719 {
2720 const TopoDS_Shape& aEIm = aExp.Current();
2721 //
2722 bValid = myValidEdges.Contains (aEIm);
2723 bInvalid = myInvalidEdges.Contains (aEIm);
2724 bNeutral = theMENeutral.Contains (aEIm) && !aMENRem.Contains (aEIm);
2725 bValidLoc = pMVE && pMVE->Contains (aEIm);
2726 //
2727 if (!bInvalid && bTreatInvertedAsInvalid)
2728 {
2729 bInvalid = myInvertedEdges.Contains (aEIm);
2730 }
2731 //
2732 if (bValidLoc && bNeutral)
2733 {
2734 bHasValid = Standard_True;
2735 }
2736 //
2737 bAllValid = bAllValid && bValidLoc;
2738 bAllInvalid = bAllInvalid && bInvalid;
2739 }
2740 //
2741 if (bAllInvalid && !bHasValid && !bAllValid)
2742 {
2743 theInvFaces.Append (aFIm);
2744 }
2745 }
2746 }
2747
2748 //=======================================================================
2749 //function : FindFacesInsideHoleWires
2750 //purpose : Find faces inside holes wires from the original face
2751 //=======================================================================
FindFacesInsideHoleWires(const TopoDS_Face & theFOrigin,const TopoDS_Face & theFOffset,const TopTools_ListOfShape & theLFImages,const TopTools_DataMapOfShapeListOfShape & theDMEOrLEIm,const TopTools_IndexedDataMapOfShapeListOfShape & theEFMap,TopTools_MapOfShape & theMFHoles)2752 void BRepOffset_BuildOffsetFaces::FindFacesInsideHoleWires (const TopoDS_Face& theFOrigin,
2753 const TopoDS_Face& theFOffset,
2754 const TopTools_ListOfShape& theLFImages,
2755 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
2756 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
2757 TopTools_MapOfShape& theMFHoles)
2758 {
2759 if (theLFImages.IsEmpty())
2760 {
2761 return;
2762 }
2763 //
2764 // find all hole wires in the original face
2765 TopTools_ListOfShape aLHoleWires;
2766 const TopoDS_Wire& anOuterWire = BRepTools::OuterWire (theFOrigin);
2767 TopExp_Explorer aExpW (theFOrigin, TopAbs_WIRE);
2768 for (; aExpW.More(); aExpW.Next())
2769 {
2770 const TopoDS_Wire& aHoleWire = TopoDS::Wire (aExpW.Current());
2771 if (!aHoleWire.IsSame (anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL)
2772 {
2773 aLHoleWires.Append (aHoleWire);
2774 }
2775 }
2776 //
2777 if (aLHoleWires.IsEmpty())
2778 {
2779 // no holes in the face
2780 return;
2781 }
2782 //
2783 TopTools_ListOfShape* pLFNewHoles = myFNewHoles.ChangeSeek (theFOrigin);
2784 //
2785 if (!pLFNewHoles)
2786 {
2787 pLFNewHoles = myFNewHoles.Bound (theFOrigin, TopTools_ListOfShape());
2788 }
2789 if (pLFNewHoles->IsEmpty())
2790 {
2791 //
2792 // find the faces representing holes in the images of the faces:
2793 // 1. for each original hole wire try to build its image
2794 // 2. build the new planar face from the images
2795 //
2796 // map vertices and edges of the splits
2797 TopTools_IndexedMapOfShape aMESplits;
2798 TopTools_ListIteratorOfListOfShape aItLF (theLFImages);
2799 for (; aItLF.More(); aItLF.Next())
2800 {
2801 TopExp::MapShapes (aItLF.Value(), TopAbs_EDGE, aMESplits);
2802 }
2803 //
2804 TopTools_ListIteratorOfListOfShape aItLW (aLHoleWires);
2805 for (; aItLW.More(); aItLW.Next())
2806 {
2807 const TopoDS_Wire& aHoleWire = TopoDS::Wire (aItLW.Value());
2808 // find images of all edges of the original wire
2809 TopTools_IndexedMapOfShape aMEImWire;
2810 TopoDS_Iterator aItE (aHoleWire);
2811 for (; aItE.More(); aItE.Next())
2812 {
2813 const TopoDS_Shape& aEOr = aItE.Value();
2814 const TopTools_ListOfShape* pLEIm = theDMEOrLEIm.Seek (aEOr);
2815 if (!pLEIm || pLEIm->IsEmpty())
2816 {
2817 continue;
2818 }
2819 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
2820 for (; aItLEIm.More(); aItLEIm.Next())
2821 {
2822 const TopoDS_Shape& aEIm = aItLEIm.Value();
2823 if (aMESplits.Contains (aEIm))
2824 {
2825 aMEImWire.Add (aEIm);
2826 }
2827 }
2828 }
2829 //
2830 if (aMEImWire.IsEmpty())
2831 {
2832 continue;
2833 }
2834 //
2835 // build new planar face using these edges
2836 TopTools_ListOfShape aLE;
2837 Standard_Integer i, aNbE = aMEImWire.Extent();
2838 for (i = 1; i <= aNbE; ++i)
2839 {
2840 aLE.Append (aMEImWire (i).Oriented (TopAbs_FORWARD));
2841 aLE.Append (aMEImWire (i).Oriented (TopAbs_REVERSED));
2842 }
2843 //
2844 BOPAlgo_BuilderFace aBF;
2845 aBF.SetFace (TopoDS::Face (theFOffset.Oriented (TopAbs_FORWARD)));
2846 aBF.SetShapes (aLE);
2847 aBF.Perform();
2848 //
2849 const TopTools_ListOfShape& aLFNew = aBF.Areas();
2850 if (aLFNew.IsEmpty())
2851 {
2852 continue;
2853 }
2854 //
2855 // check if outer edges in the new faces are not inverted
2856 // because the inverted edges mean that the hole has been
2857 // filled during offset and there will be no faces to remove
2858 TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew;
2859 TopTools_ListIteratorOfListOfShape aItLFNew (aLFNew);
2860 for (; aItLFNew.More(); aItLFNew.Next())
2861 {
2862 TopExp::MapShapesAndAncestors (aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew);
2863 }
2864 //
2865 aNbE = aDMEFNew.Extent();
2866 for (i = 1; i <= aNbE; ++i)
2867 {
2868 if (aDMEFNew (i).Extent() == 1)
2869 {
2870 const TopoDS_Shape& aE = aDMEFNew.FindKey (i);
2871 if (myInvertedEdges.Contains (aE))
2872 {
2873 break;
2874 }
2875 }
2876 }
2877 //
2878 if (i <= aNbE)
2879 {
2880 continue;
2881 }
2882 //
2883 aItLFNew.Initialize (aLFNew);
2884 for (; aItLFNew.More(); aItLFNew.Next())
2885 {
2886 pLFNewHoles->Append (aItLFNew.Value());
2887 }
2888 }
2889 }
2890
2891 // Build Edge-Face map for splits of current offset face
2892 TopTools_IndexedDataMapOfShapeListOfShape anEFSplitsMap;
2893 // Build Edge-Face map for holes
2894 TopTools_IndexedDataMapOfShapeListOfShape anEFHolesMap;
2895
2896 // among the splits of the offset face find those that are
2897 // located inside the hole faces
2898 TopTools_ListIteratorOfListOfShape aItLF (theLFImages);
2899 for (; aItLF.More(); aItLF.Next())
2900 {
2901 const TopoDS_Face& aFIm = TopoDS::Face (aItLF.Value());
2902 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFSplitsMap);
2903 // get the point inside the face and classify it relatively hole faces
2904 gp_Pnt aP3D;
2905 gp_Pnt2d aP2D;
2906 Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace (aFIm, aP3D, aP2D, myContext);
2907 if (iErr)
2908 {
2909 continue;
2910 }
2911 //
2912 Standard_Real aTol = BRep_Tool::Tolerance (aFIm);
2913 //
2914 TopTools_ListIteratorOfListOfShape aItLFNew (*pLFNewHoles);
2915 for (; aItLFNew.More(); aItLFNew.Next())
2916 {
2917 const TopoDS_Face& aFNew = TopoDS::Face (aItLFNew.Value());
2918 if (myContext->IsValidPointForFace (aP3D, aFNew, aTol))
2919 {
2920 // the face is classified as IN
2921 theMFHoles.Add (aFIm);
2922 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFHolesMap);
2923 break;
2924 }
2925 }
2926 }
2927
2928 // Out of all found holes find those which cannot be removed
2929 // by checking their connectivity to splits of other offset faces.
2930 // These are the faces, which will create uncovered holes if removed.
2931 const Standard_Integer aNbE = anEFHolesMap.Extent();
2932 for (Standard_Integer i = 1; i <= aNbE; ++i)
2933 {
2934 const TopoDS_Shape& anEdge = anEFHolesMap.FindKey (i);
2935 const TopTools_ListOfShape& aLFHoles = anEFHolesMap (i);
2936 // Check if the edge is outer for holes
2937 if (aLFHoles.Extent() != 1)
2938 continue;
2939
2940 const TopoDS_Shape& aFHole = aLFHoles.First();
2941 if (!theMFHoles.Contains (aFHole))
2942 // Already removed
2943 continue;
2944
2945 // Check if the edge is not outer for splits
2946 const TopTools_ListOfShape& aLSplits = anEFSplitsMap.FindFromKey (anEdge);
2947 if (aLSplits.Extent() == 1)
2948 continue;
2949
2950 // Check if edge is only connected to splits of the current offset face
2951 const TopTools_ListOfShape& aLFAll = theEFMap.FindFromKey (anEdge);
2952 if (aLFAll.Extent() == 2)
2953 // Avoid removal of the hole from the splits
2954 theMFHoles.Remove (aFHole);
2955 }
2956 }
2957
2958 //=======================================================================
2959 //function : CheckInverted
2960 //purpose : Checks if the edge has been inverted
2961 //=======================================================================
CheckInverted(const TopoDS_Edge & theEIm,const TopoDS_Face & theFOr,const TopTools_IndexedDataMapOfShapeListOfShape & theDMVE,const TopTools_IndexedMapOfShape & theMEdges)2962 Standard_Boolean BRepOffset_BuildOffsetFaces::CheckInverted (const TopoDS_Edge& theEIm,
2963 const TopoDS_Face& theFOr,
2964 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
2965 const TopTools_IndexedMapOfShape& theMEdges)
2966 {
2967 // It is necessary to compare the direction from first vertex
2968 // to the last vertex on the original edge with the
2969 // same direction on the new edge. If the directions
2970 // will be different - the edge has been inverted.
2971 //
2972 TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
2973 TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
2974 //
2975 Standard_Integer i;
2976 // find vertices of the offset shape
2977 TopExp::Vertices (theEIm, aVI1, aVI2);
2978 //
2979 // find images
2980 TopTools_ListOfShape aLEImages;
2981 if (myOEOrigins.IsBound (theEIm))
2982 {
2983 TopoDS_Wire anImages;
2984 BRep_Builder().MakeWire (anImages);
2985 //
2986 TopTools_MapOfShape aMImFence;
2987 const TopTools_ListOfShape& aLOffsetOr = myOEOrigins.Find (theEIm);
2988 TopTools_ListIteratorOfListOfShape aItOffset (aLOffsetOr);
2989 for (; aItOffset.More(); aItOffset.Next())
2990 {
2991 const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
2992 const TopTools_ListOfShape& aLImages = myOEImages.Find (aEOffsetOr);
2993 //
2994 TopTools_ListIteratorOfListOfShape aItImages (aLImages);
2995 for (; aItImages.More(); aItImages.Next())
2996 {
2997 const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
2998 if (theMEdges.Contains (anIm) && aMImFence.Add (anIm))
2999 {
3000 BRep_Builder().Add (anImages, anIm);
3001 aLEImages.Append (anIm);
3002 }
3003 }
3004 }
3005 //
3006 // find alone vertices
3007 TopoDS_Vertex aVW1, aVW2;
3008 TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
3009 TopExp::MapShapesAndAncestors (anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
3010 //
3011 TopTools_ListOfShape aLVAlone;
3012 Standard_Integer aNb = aDMImVE.Extent();
3013 for (i = 1; i <= aNb; ++i)
3014 {
3015 const TopTools_ListOfShape& aLImE = aDMImVE (i);
3016 if (aLImE.Extent() == 1)
3017 {
3018 aLVAlone.Append (aDMImVE.FindKey (i));
3019 }
3020 }
3021 //
3022 if (aLVAlone.Extent() > 1)
3023 {
3024 aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
3025 aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
3026 //
3027 // check distances
3028 const gp_Pnt& aPI1 = BRep_Tool::Pnt (aVI1);
3029 const gp_Pnt& aPW1 = BRep_Tool::Pnt (aVW1);
3030 const gp_Pnt& aPW2 = BRep_Tool::Pnt (aVW2);
3031 //
3032 Standard_Real aDist1 = aPI1.SquareDistance (aPW1);
3033 Standard_Real aDist2 = aPI1.SquareDistance (aPW2);
3034 //
3035 if (aDist1 < aDist2)
3036 {
3037 aVI1 = aVW1;
3038 aVI2 = aVW2;
3039 }
3040 else
3041 {
3042 aVI1 = aVW2;
3043 aVI2 = aVW1;
3044 }
3045 }
3046 }
3047 else
3048 {
3049 aLEImages.Append (theEIm);
3050 }
3051 //
3052 // Find edges connected to these vertices
3053 const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey (aVI1);
3054 const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey (aVI2);
3055 //
3056 // Find vertices on the original face corresponding to vertices on the offset edge
3057 //
3058 // find original edges for both lists
3059 TopTools_ListOfShape aLOE1, aLOE2;
3060 for (i = 0; i < 2; ++i)
3061 {
3062 const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
3063 TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
3064 //
3065 TopTools_MapOfShape aMFence;
3066 //
3067 TopTools_ListIteratorOfListOfShape aItLIE (aLIE);
3068 for (; aItLIE.More(); aItLIE.Next())
3069 {
3070 const TopoDS_Shape& aEI = aItLIE.Value();
3071 if (myEdgesOrigins->IsBound (aEI))
3072 {
3073 const TopTools_ListOfShape& aLEOrigins = myEdgesOrigins->Find (aEI);
3074 //
3075 TopTools_ListIteratorOfListOfShape aItLOE (aLEOrigins);
3076 for (; aItLOE.More(); aItLOE.Next())
3077 {
3078 const TopoDS_Shape& aEO = aItLOE.Value();
3079 if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add (aEO))
3080 {
3081 TopoDS_Shape aEOin;
3082 if (FindShape (aEO, theFOr, NULL, aEOin))
3083 {
3084 AppendToList (aLOE, aEO);
3085 }
3086 }
3087 }
3088 }
3089 }
3090 }
3091 //
3092 if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2)
3093 {
3094 return Standard_False;
3095 }
3096 //
3097 // find vertices common for the max number of edges in the lists
3098 for (i = 0; i < 2; ++i)
3099 {
3100 const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
3101 TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
3102
3103 TopTools_IndexedDataMapOfShapeListOfShape aDMVELoc;
3104 for (TopTools_ListOfShape::Iterator itLOE (aLOE); itLOE.More(); itLOE.Next())
3105 {
3106 TopExp::MapShapesAndAncestors (itLOE.Value(), TopAbs_VERTEX, TopAbs_EDGE, aDMVELoc);
3107 }
3108
3109 Standard_Integer aNbEMax = 0;
3110 for (Standard_Integer j = 1; j <= aDMVELoc.Extent(); ++j)
3111 {
3112 Standard_Integer aNbE = aDMVELoc (j).Extent();
3113 if (aNbE > 1 && aNbE > aNbEMax)
3114 {
3115 aVO = TopoDS::Vertex (aDMVELoc.FindKey (j));
3116 aNbEMax = aNbE;
3117 }
3118 }
3119 if (aVO.IsNull())
3120 {
3121 return Standard_False;
3122 }
3123 }
3124
3125 if (aVO1.IsSame (aVO2))
3126 {
3127 return Standard_False;
3128 }
3129 //
3130 // check positions of the offset and original vertices
3131 const gp_Pnt& aPI1 = BRep_Tool::Pnt (aVI1);
3132 const gp_Pnt& aPI2 = BRep_Tool::Pnt (aVI2);
3133 const gp_Pnt& aPO1 = BRep_Tool::Pnt (aVO1);
3134 const gp_Pnt& aPO2 = BRep_Tool::Pnt (aVO2);
3135 //
3136 gp_Vec aVI (aPI1, aPI2);
3137 gp_Vec aVO (aPO1, aPO2);
3138 //
3139 Standard_Real anAngle = aVI.Angle (aVO);
3140 Standard_Boolean bInverted = Abs (anAngle - M_PI) < 1.e-4;
3141 if (bInverted)
3142 {
3143 TopTools_ListIteratorOfListOfShape aItLEIm (aLEImages);
3144 for (; aItLEIm.More(); aItLEIm.Next())
3145 {
3146 const TopoDS_Shape& aEInvr = aItLEIm.Value();
3147 myInvertedEdges.Add (aEInvr);
3148 }
3149 }
3150 return bInverted;
3151 }
3152
3153 namespace {
3154 //=======================================================================
3155 //function : GetVerticesOnEdges
3156 //purpose : Get vertices from the given shape belonging to the given edges
3157 //=======================================================================
GetVerticesOnEdges(const TopoDS_Shape & theCB,const TopTools_IndexedMapOfShape & theEdges,TopTools_MapOfShape & theVerticesOnEdges,TopTools_MapOfShape & theAllVertices)3158 static void GetVerticesOnEdges (const TopoDS_Shape& theCB,
3159 const TopTools_IndexedMapOfShape& theEdges,
3160 TopTools_MapOfShape& theVerticesOnEdges,
3161 TopTools_MapOfShape& theAllVertices)
3162 {
3163 TopExp_Explorer aExp (theCB, TopAbs_EDGE);
3164 for (; aExp.More(); aExp.Next())
3165 {
3166 const TopoDS_Shape& aE = aExp.Current();
3167 Standard_Boolean isOnGivenEdges = theEdges.Contains (aE);
3168 for (TopoDS_Iterator aItV (aE); aItV.More(); aItV.Next())
3169 {
3170 theAllVertices.Add (aItV.Value());
3171 if (isOnGivenEdges)
3172 {
3173 theVerticesOnEdges.Add (aItV.Value());
3174 }
3175 }
3176 }
3177 }
3178 }
3179
3180 //=======================================================================
3181 //function : CheckInvertedBlock
3182 //purpose : Checks if it is possible to remove the block containing inverted edges
3183 //=======================================================================
CheckInvertedBlock(const TopoDS_Shape & theCB,const TopTools_ListOfShape & theLCBF,BRepOffset_DataMapOfShapeMapOfShape & theDMCBVInverted,BRepOffset_DataMapOfShapeMapOfShape & theDMCBVAll)3184 Standard_Boolean BRepOffset_BuildOffsetFaces::CheckInvertedBlock (const TopoDS_Shape& theCB,
3185 const TopTools_ListOfShape& theLCBF,
3186 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
3187 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll)
3188 {
3189 // For possible removal of the block:
3190 // 1. There should be more than just one face in the block
3191 if (theCB.NbChildren() < 2)
3192 {
3193 return Standard_False;
3194 }
3195 //
3196 // 2. The block should at least contain two connected inverted edges with
3197 // different origins (not just two images/splits of the same edge)
3198 TopTools_MapOfShape aMECBInv;
3199 TopoDS_Compound aCECBInv;
3200 BRep_Builder().MakeCompound (aCECBInv);
3201 //
3202 TopExp_Explorer aExp (theCB, TopAbs_EDGE);
3203 for (; aExp.More(); aExp.Next())
3204 {
3205 const TopoDS_Shape& aE = aExp.Current();
3206 if (myInvertedEdges.Contains (aE))
3207 {
3208 if (aMECBInv.Add (aE))
3209 {
3210 BRep_Builder().Add (aCECBInv, aE);
3211 }
3212 }
3213 }
3214 //
3215 if (aMECBInv.Extent() < 2)
3216 {
3217 return Standard_False;
3218 }
3219 //
3220 // check that the edges are connected and different
3221 TopTools_ListOfShape aLCBE;
3222 BOPTools_AlgoTools::MakeConnexityBlocks (aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
3223 //
3224 TopTools_ListIteratorOfListOfShape aItLCBE (aLCBE);
3225 for (; aItLCBE.More(); aItLCBE.Next())
3226 {
3227 const TopoDS_Shape& aCBE = aItLCBE.Value();
3228 // count the unique edges in the block
3229 Standard_Integer aNbUnique = 0;
3230 TopTools_MapOfShape aMEOrigins;
3231 TopoDS_Iterator aItE (aCBE);
3232 for (; aItE.More(); aItE.Next())
3233 {
3234 const TopoDS_Shape& aE = aItE.Value();
3235 const TopTools_ListOfShape* pLEOr = myOEOrigins.Seek (aE);
3236 if (!pLEOr)
3237 {
3238 aMEOrigins.Add (aE);
3239 ++aNbUnique;
3240 continue;
3241 }
3242 TopTools_ListIteratorOfListOfShape aItLEOr (*pLEOr);
3243 for (; aItLEOr.More(); aItLEOr.Next())
3244 {
3245 const TopoDS_Shape& aEOr = aItLEOr.Value();
3246 if (aMEOrigins.Add (aEOr))
3247 {
3248 ++aNbUnique;
3249 }
3250 }
3251 }
3252 //
3253 if (aNbUnique >= 2)
3254 {
3255 break;
3256 }
3257 }
3258 //
3259 if (!aItLCBE.More())
3260 {
3261 return Standard_False;
3262 }
3263 //
3264 // 3. the block should not contain inverted edges which vertices
3265 // are contained in other blocks
3266 //
3267 // collect vertices from inverted edges and compare them with
3268 // vertices from other blocks
3269 TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek (theCB);
3270 TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek (theCB);
3271 if (!pMVInverted)
3272 {
3273 pMVInverted = theDMCBVInverted.Bound (theCB, TopTools_MapOfShape());
3274 pMVAll = theDMCBVAll.Bound (theCB, TopTools_MapOfShape());
3275 //
3276 GetVerticesOnEdges (theCB, myInvertedEdges, *pMVInverted, *pMVAll);
3277 }
3278 //
3279 TopTools_ListIteratorOfListOfShape aItLCB1 (theLCBF);
3280 for (; aItLCB1.More(); aItLCB1.Next())
3281 {
3282 const TopoDS_Shape& aCB1 = aItLCB1.Value();
3283 if (aCB1.IsSame (theCB))
3284 {
3285 continue;
3286 }
3287 //
3288 // collect vertices from inverted edges
3289 TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek (aCB1);
3290 TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek (aCB1);
3291 if (!pMVInverted1)
3292 {
3293 pMVInverted1 = theDMCBVInverted.Bound (aCB1, TopTools_MapOfShape());
3294 pMVAll1 = theDMCBVAll.Bound (aCB1, TopTools_MapOfShape());
3295 //
3296 GetVerticesOnEdges (aCB1, myInvertedEdges, *pMVInverted1, *pMVAll1);
3297 }
3298 //
3299 if (pMVInverted->HasIntersection (*pMVAll1))
3300 {
3301 return Standard_False;
3302 }
3303 }
3304 //
3305 return Standard_True;
3306 }
3307
3308 //=======================================================================
3309 //function : RemoveInvalidSplitsByInvertedEdges
3310 //purpose : Looking for the invalid faces containing inverted edges
3311 // that can be safely removed
3312 //=======================================================================
RemoveInvalidSplitsByInvertedEdges(TopTools_IndexedMapOfShape & theMERemoved)3313 void BRepOffset_BuildOffsetFaces::RemoveInvalidSplitsByInvertedEdges (TopTools_IndexedMapOfShape& theMERemoved)
3314 {
3315 if (myInvertedEdges.IsEmpty())
3316 {
3317 return;
3318 }
3319 //
3320 // check the faces on regularity, i.e. the splits of the same face
3321 // should not be connected only by vertex. Such irregular splits
3322 // will have to be rebuilt and cannot be removed.
3323 //
3324 BRep_Builder aBB;
3325 TopTools_IndexedMapOfShape aMEAvoid;
3326 TopTools_DataMapOfShapeListOfShape aDMVF;
3327 Standard_Integer aNb = myOFImages.Extent(), i;
3328 for (i = 1; i <= aNb; ++i)
3329 {
3330 const TopTools_ListOfShape& aLFIm = myOFImages (i);
3331 //
3332 TopoDS_Compound aCFIm;
3333 aBB.MakeCompound (aCFIm);
3334 //
3335 TopTools_DataMapOfShapeListOfShape aDMEF;
3336 TopTools_ListIteratorOfListOfShape aIt (aLFIm);
3337 for (; aIt.More(); aIt.Next())
3338 {
3339 const TopoDS_Shape& aF = aIt.Value();
3340 aBB.Add (aCFIm, aF);
3341 //
3342 // make a map to use only outer edges
3343 TopExp_Explorer aExp (aF, TopAbs_EDGE);
3344 for (; aExp.More(); aExp.Next())
3345 {
3346 const TopoDS_Shape& aE = aExp.Current();
3347 //
3348 TopTools_ListOfShape* pLF = aDMEF.ChangeSeek (aE);
3349 if (!pLF)
3350 {
3351 pLF = aDMEF.Bound (aE, TopTools_ListOfShape());
3352 }
3353 else
3354 {
3355 // internal edges should not be used
3356 aMEAvoid.Add (aE);
3357 }
3358 AppendToList (*pLF, aF);
3359 }
3360 //
3361 // fill connection map of the vertices of inverted edges to faces
3362 aExp.Init (aF, TopAbs_VERTEX);
3363 for (; aExp.More(); aExp.Next())
3364 {
3365 const TopoDS_Shape& aV = aExp.Current();
3366 //
3367 TopTools_ListOfShape* pLF = aDMVF.ChangeSeek (aV);
3368 if (!pLF)
3369 {
3370 pLF = aDMVF.Bound (aV, TopTools_ListOfShape());
3371 }
3372 AppendToList (*pLF, aF);
3373 }
3374 }
3375 //
3376 // for the splits to be regular they should form only one block
3377 TopTools_ListOfShape aLCBF;
3378 BOPTools_AlgoTools::MakeConnexityBlocks (aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
3379 if (aLCBF.Extent() == 1)
3380 {
3381 continue;
3382 }
3383 //
3384 // check if the inverted edges create the irregularity
3385 BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll;
3386 //
3387 TopTools_ListIteratorOfListOfShape aItLCB (aLCBF);
3388 for (; aItLCB.More(); aItLCB.Next())
3389 {
3390 const TopoDS_Shape& aCB = aItLCB.Value();
3391 //
3392 // check if it is possible to remove the block
3393 if (!CheckInvertedBlock (aCB, aLCBF, aDMCBVInverted, aDMCBVAll))
3394 {
3395 // non of the edges in this block should be removed
3396 TopExp::MapShapes (aCB, TopAbs_EDGE, aMEAvoid);
3397 continue;
3398 }
3399 }
3400 }
3401 //
3402 // all edges not included in aMEAvoid can be removed
3403 TopTools_MapOfShape aMERem;
3404 for (Standard_Integer iInverted = 1; iInverted <= myInvertedEdges.Extent(); ++iInverted)
3405 {
3406 const TopoDS_Shape& aE = myInvertedEdges (iInverted);
3407 if (!aMEAvoid.Contains (aE))
3408 {
3409 TopoDS_Iterator aIt (aE);
3410 for (; aIt.More(); aIt.Next())
3411 {
3412 const TopoDS_Shape& aV = aIt.Value();
3413 const TopTools_ListOfShape* pLF = aDMVF.Seek (aV);
3414 if (pLF && (pLF->Extent() > 3))
3415 {
3416 aMERem.Add (aE);
3417 break;
3418 }
3419 }
3420 }
3421 }
3422 //
3423 if (aMERem.IsEmpty())
3424 {
3425 return;
3426 }
3427 //
3428 // all invalid faces containing these edges can be removed
3429 TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
3430 TopTools_MapOfShape aMFRem;
3431 TopTools_IndexedMapOfShape aMFToUpdate;
3432 aNb = myInvalidFaces.Extent();
3433 for (i = 1; i <= aNb; ++i)
3434 {
3435 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
3436 TopTools_ListOfShape& aLFIm = myInvalidFaces (i);
3437 //
3438 TopTools_ListIteratorOfListOfShape aIt (aLFIm);
3439 for (; aIt.More(); )
3440 {
3441 const TopoDS_Shape& aFIm = aIt.Value();
3442 //
3443 // to be removed the face should have at least two not connected
3444 // inverted edges
3445 TopoDS_Compound aCEInv;
3446 aBB.MakeCompound (aCEInv);
3447 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
3448 for (; aExp.More(); aExp.Next())
3449 {
3450 const TopoDS_Shape& aE = aExp.Current();
3451 if (aMERem.Contains (aE))
3452 {
3453 aBB.Add (aCEInv, aE);
3454 }
3455 }
3456 //
3457 // check connectivity
3458 TopTools_ListOfShape aLCBE;
3459 BOPTools_AlgoTools::MakeConnexityBlocks (aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
3460 //
3461 if (aLCBE.Extent() >= 2)
3462 {
3463 aMFToUpdate.Add (aF);
3464 aMFRem.Add (aFIm);
3465 aLFIm.Remove (aIt);
3466 }
3467 else
3468 {
3469 aIt.Next();
3470 }
3471 }
3472 //
3473 if (aLFIm.Extent())
3474 {
3475 aInvFaces.Add (aF, aLFIm);
3476 }
3477 }
3478 //
3479 if (aMFRem.IsEmpty())
3480 {
3481 return;
3482 }
3483 //
3484 myInvalidFaces = aInvFaces;
3485 // remove from splits
3486 aNb = aMFToUpdate.Extent();
3487 for (i = 1; i <= aNb; ++i)
3488 {
3489 const TopoDS_Shape& aF = aMFToUpdate (i);
3490 TopTools_ListOfShape& aLFIm = myOFImages.ChangeFromKey (aF);
3491 //
3492 TopTools_ListIteratorOfListOfShape aIt (aLFIm);
3493 for (; aIt.More(); )
3494 {
3495 const TopoDS_Shape& aFIm = aIt.Value();
3496 if (aMFRem.Contains (aFIm))
3497 {
3498 TopExp::MapShapes (aFIm, TopAbs_EDGE, theMERemoved);
3499 aLFIm.Remove (aIt);
3500 }
3501 else
3502 {
3503 aIt.Next();
3504 }
3505 }
3506 }
3507 }
3508
3509 //=======================================================================
3510 //function : RemoveInvalidSplitsFromValid
3511 //purpose : Removing invalid splits of faces from valid
3512 //=======================================================================
RemoveInvalidSplitsFromValid(const BRepOffset_DataMapOfShapeMapOfShape & theDMFMVIE)3513 void BRepOffset_BuildOffsetFaces::RemoveInvalidSplitsFromValid (const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE)
3514 {
3515 // Decide whether to remove the found invalid faces or not.
3516 // The procedure is the following:
3517 // 1. Make connexity blocks from invalid faces;
3518 // 2. Find free edges in this blocks;
3519 // 3. If all free edges are valid for the faces - remove block.
3520 //
3521 TopTools_MapOfShape aMFence, aMFToRem;
3522 TopoDS_Compound aCFInv;
3523 BRep_Builder aBB;
3524 aBB.MakeCompound (aCFInv);
3525 TopTools_ListIteratorOfListOfShape aItLF;
3526 //
3527 // make compound of invalid faces
3528 TopTools_DataMapOfShapeShape aDMIFOF;
3529 Standard_Integer i, aNb = myInvalidFaces.Extent();
3530 for (i = 1; i <= aNb; ++i)
3531 {
3532 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
3533 // artificially invalid faces should not be removed
3534 if (myArtInvalidFaces.IsBound (aF))
3535 {
3536 continue;
3537 }
3538 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
3539 aItLF.Initialize (aLFInv);
3540 for (; aItLF.More(); aItLF.Next())
3541 {
3542 const TopoDS_Shape& aFIm = aItLF.Value();
3543 if (aMFence.Add (aFIm))
3544 {
3545 aBB.Add (aCFInv, aFIm);
3546 aDMIFOF.Bind (aFIm, aF);
3547 }
3548 }
3549 }
3550 //
3551 // make connexity blocks
3552 TopTools_ListOfShape aLCBInv;
3553 BOPTools_AlgoTools::MakeConnexityBlocks (aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
3554 //
3555 // analyze each block
3556 aItLF.Initialize (aLCBInv);
3557 for (; aItLF.More(); aItLF.Next())
3558 {
3559 const TopoDS_Shape& aCB = aItLF.Value();
3560 //
3561 // if connexity block contains only one face - it should be removed;
3562 TopExp_Explorer aExp (aCB, TopAbs_FACE);
3563 aExp.Next();
3564 if (aExp.More())
3565 {
3566 // check if there are valid images left
3567 aExp.Init (aCB, TopAbs_FACE);
3568 for (; aExp.More(); aExp.Next())
3569 {
3570 const TopoDS_Shape& aFIm = aExp.Current();
3571 const TopoDS_Shape& aF = aDMIFOF.Find (aFIm);
3572 //
3573 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
3574 const TopTools_ListOfShape& aLFInv = myInvalidFaces.FindFromKey (aF);
3575 //
3576 if (aLFIm.Extent() == aLFInv.Extent())
3577 {
3578 break;
3579 }
3580 }
3581 }
3582 //
3583 if (!aExp.More())
3584 {
3585 aExp.Init (aCB, TopAbs_FACE);
3586 for (; aExp.More(); aExp.Next())
3587 {
3588 const TopoDS_Shape& aF = aExp.Current();
3589 aMFToRem.Add (aF);
3590 }
3591 continue;
3592 }
3593 //
3594 // remove faces connected by inverted edges
3595 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3596 TopExp::MapShapesAndAncestors (aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3597 //
3598 TopTools_DataMapOfShapeListOfShape aDMFF;
3599 aExp.Init (aCB, TopAbs_FACE);
3600 for (; aExp.More(); aExp.Next())
3601 {
3602 const TopoDS_Shape& aFCB = aExp.Current();
3603 const TopoDS_Shape& aF = aDMIFOF.Find (aFCB);
3604 TopTools_ListOfShape* pList = aDMFF.ChangeSeek (aF);
3605 if (!pList)
3606 pList = aDMFF.Bound (aF, TopTools_ListOfShape());
3607 pList->Append (aFCB);
3608 }
3609
3610 for (TopTools_DataMapOfShapeListOfShape::Iterator itM (aDMFF); itM.More(); itM.Next())
3611 {
3612 const TopoDS_Shape& aF = itM.Key();
3613 const TopTools_MapOfShape* pValidInverted = theDMFMVIE.Seek (aF);
3614
3615 // either remove all of these faces or none.
3616 const TopTools_ListOfShape& aLFCB = itM.Value();
3617 TopTools_ListOfShape::Iterator itL (aLFCB);
3618 for (; itL.More(); itL.Next())
3619 {
3620 const TopoDS_Shape& aFCB = itL.Value();
3621 TopExp_Explorer aExpE (aFCB, TopAbs_EDGE);
3622 for (; aExpE.More(); aExpE.Next())
3623 {
3624 const TopoDS_Shape& aECB = aExpE.Current();
3625 if (pValidInverted && pValidInverted->Contains (aECB))
3626 break;
3627 if (aDMEF.FindFromKey (aECB).Extent() > 1)
3628 {
3629 if (!myInvertedEdges.Contains (aECB))
3630 break;
3631 }
3632 }
3633 if (!aExpE.More())
3634 // if one removed - remove all
3635 break;
3636 }
3637 if (itL.More())
3638 {
3639 for (itL.Initialize (aLFCB); itL.More(); itL.Next())
3640 {
3641 aMFToRem.Add (itL.Value());
3642 }
3643 }
3644 }
3645 }
3646 //
3647 if (aMFToRem.Extent())
3648 {
3649 // remove invalid faces from images
3650 aNb = myInvalidFaces.Extent();
3651 for (i = 1; i <= aNb; ++i)
3652 {
3653 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
3654 TopTools_ListOfShape& aLFImages = myOFImages.ChangeFromKey (aF);
3655 aItLF.Initialize (aLFImages);
3656 for (; aItLF.More();)
3657 {
3658 const TopoDS_Shape& aFIm = aItLF.Value();
3659 if (aMFToRem.Contains (aFIm))
3660 {
3661 aLFImages.Remove (aItLF);
3662 }
3663 else
3664 {
3665 aItLF.Next();
3666 }
3667 }
3668 }
3669 }
3670 }
3671
3672 namespace {
3673 //=======================================================================
3674 //function : buildPairs
3675 //purpose : builds pairs of shapes
3676 //=======================================================================
buildPairs(const TopTools_IndexedMapOfShape & theSMap,BRepOffset_DataMapOfShapeMapOfShape & theIntPairs)3677 static void buildPairs (const TopTools_IndexedMapOfShape& theSMap,
3678 BRepOffset_DataMapOfShapeMapOfShape& theIntPairs)
3679 {
3680 const Standard_Integer aNbS = theSMap.Extent();
3681 if (aNbS < 2)
3682 return;
3683 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3684 {
3685 const TopoDS_Shape& aS = theSMap (it1);
3686 if (!theIntPairs.IsBound (aS))
3687 theIntPairs.Bind (aS, TopTools_MapOfShape());
3688 }
3689
3690 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3691 {
3692 const TopoDS_Shape& aS1 = theSMap (it1);
3693 TopTools_MapOfShape& aMap1 = theIntPairs (aS1);
3694 for (Standard_Integer it2 = it1 + 1; it2 <= aNbS; ++it2)
3695 {
3696 const TopoDS_Shape& aS2 = theSMap (it2);
3697 aMap1.Add (aS2);
3698 theIntPairs (aS2).Add (aS1);
3699 }
3700 }
3701 }
3702
3703 //=======================================================================
3704 //function : buildIntersectionPairs
3705 //purpose : builds intersection pairs
3706 //=======================================================================
buildIntersectionPairs(const TopTools_IndexedDataMapOfShapeListOfShape & myOFImages,const TopTools_IndexedDataMapOfShapeListOfShape & myInvalidFaces,const BOPAlgo_Builder & theBuilder,const TopTools_MapOfShape & theMFRemoved,const TopTools_DataMapOfShapeShape & theFOrigins,NCollection_DataMap<TopoDS_Shape,BRepOffset_DataMapOfShapeMapOfShape,TopTools_ShapeMapHasher> & theIntPairs)3707 static void buildIntersectionPairs (const TopTools_IndexedDataMapOfShapeListOfShape& myOFImages,
3708 const TopTools_IndexedDataMapOfShapeListOfShape& myInvalidFaces,
3709 const BOPAlgo_Builder& theBuilder,
3710 const TopTools_MapOfShape& theMFRemoved,
3711 const TopTools_DataMapOfShapeShape& theFOrigins,
3712 NCollection_DataMap<TopoDS_Shape,
3713 BRepOffset_DataMapOfShapeMapOfShape,
3714 TopTools_ShapeMapHasher>& theIntPairs)
3715 {
3716 TopAbs_ShapeEnum aCType = TopAbs_VERTEX;
3717 // Build connection map from vertices to faces
3718 TopTools_IndexedDataMapOfShapeListOfShape aDMVF;
3719 TopExp::MapShapesAndAncestors (theBuilder.Shape(), aCType, TopAbs_FACE, aDMVF);
3720
3721 const TopTools_DataMapOfShapeListOfShape& anImages = theBuilder.Images();
3722 const TopTools_DataMapOfShapeListOfShape& anOrigins = theBuilder.Origins();
3723
3724 // Find all faces connected to the not removed faces and build intersection pairs among them.
3725 // For removed faces intersect only those connected to each other.
3726
3727 for (Standard_Integer iF = 1; iF <= myInvalidFaces.Extent(); ++iF)
3728 {
3729 const TopoDS_Shape& aFInv = myInvalidFaces.FindKey (iF);
3730
3731 TopoDS_Compound aCF, aCFRem;
3732 BRep_Builder().MakeCompound (aCF);
3733 BRep_Builder().MakeCompound (aCFRem);
3734
3735 for (Standard_Integer iC = 0; iC < 2; ++iC)
3736 {
3737 const TopTools_ListOfShape& aLF = !iC ? myInvalidFaces (iF) : myOFImages.FindFromKey (aFInv);
3738
3739 for (TopTools_ListOfShape::Iterator it (aLF); it.More(); it.Next())
3740 {
3741 TopTools_ListOfShape aLFIm;
3742 TakeModified (it.Value(), anImages, aLFIm);
3743
3744 for (TopTools_ListOfShape::Iterator itIm (aLFIm); itIm.More(); itIm.Next())
3745 {
3746 const TopoDS_Shape& aFIm = itIm.Value();
3747
3748 if (theMFRemoved.Contains (aFIm))
3749 BRep_Builder().Add (aCFRem, aFIm);
3750 else
3751 BRep_Builder().Add (aCF, aFIm);
3752 }
3753 }
3754 }
3755
3756 TopTools_ListOfShape aLCB;
3757 BOPTools_AlgoTools::MakeConnexityBlocks (aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
3758
3759 if (aLCB.IsEmpty())
3760 continue;
3761
3762 BRepOffset_DataMapOfShapeMapOfShape* pFInterMap =
3763 theIntPairs.Bound (aFInv, BRepOffset_DataMapOfShapeMapOfShape());
3764
3765 // build pairs for not removed faces
3766 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3767 {
3768 const TopoDS_Shape& aCB = itCB.Value();
3769
3770 TopTools_IndexedMapOfShape aMFInter;
3771 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3772 {
3773 const TopoDS_Shape& aCS = exp.Current();
3774 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3775 if (!pLFV)
3776 continue;
3777
3778 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3779 {
3780 const TopoDS_Shape& aFConnected = itFV.Value();
3781
3782 TopTools_ListOfShape aLFOr;
3783 TakeModified (aFConnected, anOrigins, aLFOr);
3784 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3785 {
3786 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3787 if (pFOr)
3788 aMFInter.Add (*pFOr);
3789 }
3790 }
3791 }
3792
3793 // build intersection pairs
3794 buildPairs (aMFInter, *pFInterMap);
3795 }
3796
3797 aLCB.Clear();
3798 BOPTools_AlgoTools::MakeConnexityBlocks (aCFRem, TopAbs_EDGE, TopAbs_FACE, aLCB);
3799
3800 if (aLCB.IsEmpty())
3801 continue;
3802
3803 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3804 {
3805 const TopoDS_Shape& aCB = itCB.Value();
3806
3807 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3808 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3809 {
3810 const TopoDS_Shape& aCS = exp.Current();
3811 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3812 if (!pLFV)
3813 continue;
3814
3815 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3816 {
3817 const TopoDS_Shape& aFConnected = itFV.Value();
3818 TopExp::MapShapesAndAncestors (aFConnected, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3819 }
3820 }
3821
3822 for (Standard_Integer iE = 1; iE <= aDMEF.Extent(); ++iE)
3823 {
3824 const TopTools_ListOfShape& aLFConnected = aDMEF (iE);
3825 if (aLFConnected.Extent() < 2)
3826 continue;
3827
3828 TopTools_IndexedMapOfShape aMFInter;
3829 for (TopTools_ListOfShape::Iterator itLF (aLFConnected); itLF.More(); itLF.Next())
3830 {
3831 const TopoDS_Shape& aFConnected = itLF.Value();
3832
3833 TopTools_ListOfShape aLFOr;
3834 TakeModified (aFConnected, anOrigins, aLFOr);
3835 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3836 {
3837 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3838 if (pFOr)
3839 aMFInter.Add (*pFOr);
3840 }
3841 }
3842
3843 buildPairs (aMFInter, *pFInterMap);
3844 }
3845 }
3846 }
3847 }
3848
3849 }
3850
3851 //=======================================================================
3852 //function : RemoveInsideFaces
3853 //purpose : Looking for the inside faces that can be safely removed
3854 //=======================================================================
RemoveInsideFaces(const TopTools_ListOfShape & theInvertedFaces,const TopTools_IndexedMapOfShape & theMFToCheckInt,const TopTools_IndexedMapOfShape & theMFInvInHole,const TopoDS_Shape & theFHoles,TopTools_IndexedMapOfShape & theMERemoved,TopTools_IndexedMapOfShape & theMEInside,const Message_ProgressRange & theRange)3855 void BRepOffset_BuildOffsetFaces::RemoveInsideFaces (const TopTools_ListOfShape& theInvertedFaces,
3856 const TopTools_IndexedMapOfShape& theMFToCheckInt,
3857 const TopTools_IndexedMapOfShape& theMFInvInHole,
3858 const TopoDS_Shape& theFHoles,
3859 TopTools_IndexedMapOfShape& theMERemoved,
3860 TopTools_IndexedMapOfShape& theMEInside,
3861 const Message_ProgressRange& theRange)
3862 {
3863 TopTools_ListOfShape aLS;
3864 TopTools_MapOfShape aMFence;
3865 TopTools_IndexedMapOfShape aMFInv;
3866 TopTools_ListIteratorOfListOfShape aItLF;
3867 TopTools_DataMapOfShapeShape aDMFImF;
3868 //
3869 Message_ProgressScope aPS (theRange, "Looking for inside faces", 10);
3870 Standard_Integer i, aNb = myOFImages.Extent();
3871 for (i = 1; i <= aNb; ++i)
3872 {
3873 if (!aPS.More())
3874 {
3875 return;
3876 }
3877 const TopoDS_Shape& aF = myOFImages.FindKey (i);
3878 // to avoid intersection of the splits of the same
3879 // offset faces among themselves make compound of the
3880 // splits and use it as one argument
3881 TopoDS_Compound aCFImi;
3882 BRep_Builder().MakeCompound (aCFImi);
3883 //
3884 for (Standard_Integer j = 0; j < 2; ++j)
3885 {
3886 const TopTools_ListOfShape* pLFSp = !j ? myInvalidFaces.Seek (aF) : &myOFImages (i);
3887 if (!pLFSp)
3888 {
3889 continue;
3890 }
3891 //
3892 aItLF.Initialize (*pLFSp);
3893 for (; aItLF.More(); aItLF.Next())
3894 {
3895 const TopoDS_Shape& aFIm = aItLF.Value();
3896 if (aMFence.Add (aFIm))
3897 {
3898 BRep_Builder().Add (aCFImi, aFIm);
3899 aDMFImF.Bind (aFIm, aF);
3900 if (!j)
3901 {
3902 aMFInv.Add (aFIm);
3903 }
3904 }
3905 }
3906 }
3907 //
3908 aLS.Append (aCFImi);
3909 }
3910 //
3911 // to make the solids more complete add for intersection also the faces
3912 // consisting only of invalid edges and not included into splits
3913 aNb = theMFToCheckInt.Extent();
3914 for (i = 1; i <= aNb; ++i)
3915 {
3916 const TopoDS_Shape& aFSp = theMFToCheckInt (i);
3917 if (aMFence.Add (aFSp))
3918 {
3919 aLS.Append (aFSp);
3920 }
3921 }
3922 //
3923 BOPAlgo_MakerVolume aMV;
3924 aMV.SetArguments (aLS);
3925 aMV.SetIntersect (Standard_True);
3926 aMV.Perform (aPS.Next (9));
3927 if (aMV.HasErrors())
3928 return;
3929
3930 //
3931 // get shapes connection for using in the rebuilding process
3932 // for the cases in which some of the intersection left undetected
3933 ShapesConnections (aDMFImF, aMV);
3934 //
3935 // find faces to remove
3936 const TopoDS_Shape& aSols = aMV.Shape();
3937 //
3938 TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
3939 TopExp::MapShapesAndAncestors (aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
3940 //
3941 aNb = aDMFS.Extent();
3942 if (!aNb)
3943 {
3944 return;
3945 }
3946 //
3947 // To use the created solids for classifications, firstly, it is necessary
3948 // to check them on validity - the created solids should be complete,
3949 // i.e. all faces should be included.
3950 //
3951 TopTools_MapOfShape aMFToRem;
3952 // Check completeness
3953 if (aMV.HasDeleted())
3954 {
3955 TopTools_IndexedMapOfShape aMEHoles;
3956 TopExp::MapShapes (theFHoles, TopAbs_EDGE, aMEHoles);
3957
3958 // Map edges of the solids to check the connectivity
3959 // of the removed invalid splits
3960 TopTools_IndexedMapOfShape aMESols;
3961 TopExp::MapShapes (aSols, TopAbs_EDGE, aMESols);
3962
3963 // perform additional check on faces
3964 aNb = myOFImages.Extent();
3965 for (i = 1; i <= aNb; ++i)
3966 {
3967 if (!aPS.More())
3968 {
3969 return;
3970 }
3971 const TopTools_ListOfShape& aLFIm = myOFImages (i);
3972 if (aLFIm.IsEmpty())
3973 {
3974 continue;
3975 }
3976
3977 const TopoDS_Shape& aF = myOFImages.FindKey (i);
3978 Standard_Boolean bInvalid = myInvalidFaces.Contains (aF);
3979 // For invalid faces it is allowed to be at least connected
3980 // to the solids, otherwise the solids are considered as broken
3981 Standard_Boolean bConnected = Standard_False;
3982
3983 Standard_Boolean bFaceKept = Standard_False;
3984 aItLF.Initialize (aLFIm);
3985 for (; aItLF.More(); aItLF.Next())
3986 {
3987 const TopoDS_Shape& aFIm = aItLF.Value();
3988 if (!aMV.IsDeleted (aFIm))
3989 {
3990 bFaceKept = Standard_True;
3991 continue;
3992 }
3993 //
3994 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
3995 for (; aExpE.More(); aExpE.Next())
3996 {
3997 if (aMEHoles.Contains (aExpE.Current()))
3998 {
3999 bFaceKept = Standard_True;
4000 aMFToRem.Add (aFIm);
4001 break;
4002 }
4003 if (!bFaceKept && bInvalid && !bConnected)
4004 bConnected = aMESols.Contains (aExpE.Current());
4005 }
4006 }
4007 //
4008 if (!bFaceKept && !bConnected)
4009 {
4010 return;
4011 }
4012 }
4013 }
4014 //
4015 TopTools_IndexedMapOfShape aMEBoundary;
4016 aNb = aDMFS.Extent();
4017 for (i = 1; i <= aNb; ++i)
4018 {
4019 const TopoDS_Shape& aFIm = aDMFS.FindKey (i);
4020 const TopTools_ListOfShape& aLSol = aDMFS (i);
4021 if (aLSol.Extent() > 1)
4022 {
4023 aMFToRem.Add (aFIm);
4024 }
4025 else if (aFIm.Orientation() != TopAbs_INTERNAL)
4026 {
4027 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMEBoundary);
4028 }
4029 }
4030
4031 // Tool for getting the splits of faces
4032 const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
4033
4034 // update invalid faces with images
4035 aNb = aMFInv.Extent();
4036 for (i = 1; i <= aNb; ++i)
4037 {
4038 const TopoDS_Shape& aFInv = aMFInv (i);
4039 TakeModified (aFInv, aMVIms, aMFInv);
4040 }
4041
4042 // Take into account the faces invalid by inverted edges
4043 for (TopTools_ListOfShape::Iterator itLF (theInvertedFaces); itLF.More(); itLF.Next())
4044 TakeModified (itLF.Value(), aMVIms, aMFInv);
4045
4046 // check if the invalid faces inside the holes are really invalid:
4047 // check its normal direction - if it has changed relatively the
4048 // original face the offset face is invalid and should be kept for rebuilding
4049 Standard_Integer aNbFH = theMFInvInHole.Extent();
4050 for (i = 1; i <= aNbFH; ++i)
4051 {
4052 if (!aPS.More())
4053 {
4054 return;
4055 }
4056 const TopoDS_Shape& aFInv = theMFInvInHole (i);
4057 TopTools_ListOfShape aLFInvIm = aMV.Modified (aFInv);
4058 if (aLFInvIm.IsEmpty())
4059 {
4060 aLFInvIm.Append (aFInv);
4061 }
4062 //
4063 const TopoDS_Shape* pFOffset = aDMFImF.Seek (aFInv);
4064 if (!pFOffset)
4065 {
4066 continue;
4067 }
4068 TopTools_ListIteratorOfListOfShape aItLFInv (aLFInvIm);
4069 for (; aItLFInv.More(); aItLFInv.Next())
4070 {
4071 const TopoDS_Shape& aFInvIm = aItLFInv.Value();
4072 const TopTools_ListOfShape* pLSols = aDMFS.Seek (aFInvIm);
4073 if (!pLSols || pLSols->Extent() != 1)
4074 {
4075 continue;
4076 }
4077 //
4078 const TopoDS_Shape& aFSol = pLSols->First();
4079 //
4080 TopoDS_Shape aFx;
4081 if (!FindShape (aFInvIm, aFSol, NULL, aFx))
4082 {
4083 continue;
4084 }
4085 //
4086 if (BRepOffset_Tool::CheckPlanesNormals (TopoDS::Face (aFx), TopoDS::Face (*pFOffset)))
4087 {
4088 // the normal direction has not changed, thus the face can be removed
4089 aMFToRem.Add (aFInvIm);
4090 }
4091 }
4092 }
4093 //
4094 TopoDS_Compound aSolids;
4095 BRep_Builder().MakeCompound (aSolids);
4096 TopTools_MapOfShape aMFKeep;
4097 //
4098 TopExp_Explorer aExpS (aSols, TopAbs_SOLID);
4099 for (; aExpS.More(); aExpS.Next())
4100 {
4101 if (!aPS.More())
4102 {
4103 return;
4104 }
4105 const TopoDS_Shape& aSol = aExpS.Current();
4106 //
4107 Standard_Boolean bAllInv (Standard_True), bAllRemoved (Standard_True);
4108
4109 for (TopExp_Explorer aExpF (aSol, TopAbs_FACE); aExpF.More(); aExpF.Next())
4110 {
4111 const TopoDS_Shape& aFS = aExpF.Current();
4112 //
4113 if (aFS.Orientation() == TopAbs_INTERNAL)
4114 {
4115 aMFToRem.Add (aFS);
4116 continue;
4117 }
4118
4119 if (aMFToRem.Contains (aFS))
4120 continue;
4121
4122 bAllRemoved = false;
4123 bAllInv &= aMFInv.Contains (aFS);
4124 }
4125 //
4126 if (bAllInv && !bAllRemoved)
4127 {
4128 // remove invalid faces but keep those that have already been marked for removal
4129 TopExp_Explorer aExpF (aSol, TopAbs_FACE);
4130 for (; aExpF.More(); aExpF.Next())
4131 {
4132 const TopoDS_Shape& aFS = aExpF.Current();
4133 //
4134 if (aMFToRem.Contains (aFS))
4135 {
4136 if (!aMFKeep.Add (aFS))
4137 {
4138 aMFKeep.Remove (aFS);
4139 }
4140 }
4141 else
4142 {
4143 aMFToRem.Add (aFS);
4144 }
4145 }
4146 }
4147 else
4148 {
4149 BRep_Builder().Add (aSolids, aSol);
4150 mySolids = aSolids;
4151 }
4152 }
4153 //
4154 TopTools_MapIteratorOfMapOfShape aItM (aMFKeep);
4155 for (; aItM.More(); aItM.Next())
4156 {
4157 aMFToRem.Remove (aItM.Value());
4158 }
4159
4160 // Remove the invalid hanging parts external to the solids
4161 RemoveHangingParts (aMV, aDMFImF, aMFInv, aMFToRem);
4162
4163 // Remove newly found internal and hanging faces
4164 RemoveValidSplits (aMFToRem, aMV, theMERemoved);
4165 RemoveInvalidSplits (aMFToRem, aMV, theMERemoved);
4166 //
4167 // Get inside faces from the removed ones comparing them with boundary edges
4168 aNb = theMERemoved.Extent();
4169 for (i = 1; i <= aNb; ++i)
4170 {
4171 const TopoDS_Shape& aE = theMERemoved (i);
4172 if (!aMEBoundary.Contains (aE))
4173 {
4174 theMEInside.Add (aE);
4175 }
4176 }
4177
4178 // build all possible intersection pairs basing on the intersection results
4179 // taking into account removed faces.
4180 if (aMFToRem.Extent())
4181 buildIntersectionPairs (myOFImages, myInvalidFaces, aMV, aMFToRem, aDMFImF, myIntersectionPairs);
4182 }
4183
4184 //=======================================================================
4185 //function : ShapesConnections
4186 //purpose : Looking for the connections between faces not to miss
4187 // some necessary intersection
4188 //=======================================================================
ShapesConnections(const TopTools_DataMapOfShapeShape & theDMFOr,BOPAlgo_Builder & theBuilder)4189 void BRepOffset_BuildOffsetFaces::ShapesConnections (const TopTools_DataMapOfShapeShape& theDMFOr,
4190 BOPAlgo_Builder& theBuilder)
4191 {
4192 // update invalid edges with images and keep connection to original edge
4193 TopTools_DataMapOfShapeListOfShape aDMEOr;
4194 Standard_Integer aNb = myInvalidEdges.Extent();
4195 for (Standard_Integer i = 1; i <= aNb; ++i)
4196 {
4197 const TopoDS_Shape& aEInv = myInvalidEdges (i);
4198 const TopTools_ListOfShape& aLEIm = theBuilder.Modified (aEInv);
4199 if (aLEIm.IsEmpty())
4200 {
4201 aDMEOr.Bound (aEInv, TopTools_ListOfShape())->Append (aEInv);
4202 continue;
4203 }
4204 //
4205 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
4206 for (; aItLEIm.More(); aItLEIm.Next())
4207 {
4208 const TopoDS_Shape& aEIm = aItLEIm.Value();
4209 //
4210 TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek (aEIm);
4211 if (!pLEOr)
4212 {
4213 pLEOr = aDMEOr.Bound (aEIm, TopTools_ListOfShape());
4214 }
4215 AppendToList (*pLEOr, aEInv);
4216 }
4217 }
4218 //
4219 // get shapes connections for using in the rebuilding process
4220 const BOPDS_PDS& pDS = theBuilder.PDS();
4221 // analyze all Face/Face intersections
4222 const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
4223 Standard_Integer iInt, aNbFF = aFFs.Length();
4224 for (iInt = 0; iInt < aNbFF; ++iInt)
4225 {
4226 const BOPDS_InterfFF& aFF = aFFs (iInt);
4227 const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
4228 Standard_Integer aNbC = aVNC.Length();
4229 if (!aNbC)
4230 {
4231 continue;
4232 }
4233 //
4234 const TopoDS_Shape& aFIm1 = pDS->Shape (aFF.Index1());
4235 const TopoDS_Shape& aFIm2 = pDS->Shape (aFF.Index2());
4236 //
4237 const TopoDS_Shape* pF1 = theDMFOr.Seek (aFIm1);
4238 const TopoDS_Shape* pF2 = theDMFOr.Seek (aFIm2);
4239 //
4240 if (!pF1 || !pF2)
4241 {
4242 continue;
4243 }
4244 //
4245 if (pF1->IsSame (*pF2))
4246 {
4247 continue;
4248 }
4249 //
4250 Standard_Boolean bInv1 = myInvalidFaces.Contains (*pF1);
4251 Standard_Boolean bInv2 = myInvalidFaces.Contains (*pF2);
4252 //
4253 if (!bInv1 && !bInv2)
4254 {
4255 continue;
4256 }
4257 //
4258 // check if it is real Face/Face intersection
4259 TopTools_MapOfShape aMEInt;
4260 for (Standard_Integer iC = 0; iC < aNbC; ++iC)
4261 {
4262 const BOPDS_Curve& aNC = aVNC (iC);
4263 const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
4264 BOPDS_ListIteratorOfListOfPaveBlock aItLPB (aLPB);
4265 for (; aItLPB.More(); aItLPB.Next())
4266 {
4267 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
4268 Standard_Integer nEInt;
4269 if (aPB->HasEdge (nEInt))
4270 {
4271 const TopoDS_Shape& aEInt = pDS->Shape (nEInt);
4272 aMEInt.Add (aEInt);
4273 }
4274 }
4275 }
4276 //
4277 if (aMEInt.IsEmpty())
4278 {
4279 continue;
4280 }
4281 //
4282 // check if invalid edges of the face are in the same splits with intersection edges
4283 for (Standard_Integer i = 0; i < 2; ++i)
4284 {
4285 if ((!i && !bInv1) || (i && !bInv2))
4286 {
4287 continue;
4288 }
4289 //
4290 const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
4291 const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
4292 const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
4293 //
4294 Standard_Boolean bFound = Standard_False;
4295 //
4296 TopTools_ListOfShape aLFIm = theBuilder.Modified (aFIm);
4297 if (aLFIm.IsEmpty())
4298 {
4299 aLFIm.Append (aFIm);
4300 }
4301 //
4302 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
4303 for (; aItLFIm.More(); aItLFIm.Next())
4304 {
4305 const TopoDS_Shape& aFImIm = aItLFIm.Value();
4306 //
4307 Standard_Boolean bInv (Standard_False), bInt (Standard_False);
4308 TopExp_Explorer aExpE (aFImIm, TopAbs_EDGE);
4309 for (; aExpE.More(); aExpE.Next())
4310 {
4311 const TopoDS_Shape& aE = aExpE.Current();
4312 if (!bInv)
4313 {
4314 bInv = aDMEOr.IsBound (aE);
4315 }
4316 if (!bInt)
4317 {
4318 bInt = aMEInt.Contains (aE);
4319 }
4320 if (bInv && bInt)
4321 {
4322 break;
4323 }
4324 }
4325 //
4326 if (!bInt || !bInv)
4327 {
4328 continue;
4329 }
4330 //
4331 bFound = Standard_True;
4332 //
4333 // append opposite face to all invalid edges in the split
4334 aExpE.Init (aFImIm, TopAbs_EDGE);
4335 for (; aExpE.More(); aExpE.Next())
4336 {
4337 const TopoDS_Shape& aE = aExpE.Current();
4338 const TopTools_ListOfShape* pLEOr = aDMEOr.Seek (aE);
4339 if (!pLEOr)
4340 {
4341 continue;
4342 }
4343 //
4344 TopTools_ListIteratorOfListOfShape aItLE (*pLEOr);
4345 for (; aItLE.More(); aItLE.Next())
4346 {
4347 const TopoDS_Shape& aEOr = aItLE.Value();
4348 TopTools_ListOfShape* pLFE = mySSInterfs.ChangeSeek (aEOr);
4349 if (!pLFE)
4350 {
4351 pLFE = mySSInterfs.Bound (aEOr, TopTools_ListOfShape());
4352 }
4353 AppendToList (*pLFE, aFOp);
4354 }
4355 }
4356 }
4357 if (bFound)
4358 {
4359 // save connection between offset faces
4360 TopTools_ListOfShape* pLF = mySSInterfs.ChangeSeek (aF);
4361 if (!pLF)
4362 {
4363 pLF = mySSInterfs.Bound (aF, TopTools_ListOfShape());
4364 }
4365 AppendToList (*pLF, aFOp);
4366 }
4367 }
4368 }
4369 }
4370
4371 //=======================================================================
4372 //function : RemoveHangingParts
4373 //purpose : Remove isolated invalid hanging parts
4374 //=======================================================================
RemoveHangingParts(const BOPAlgo_MakerVolume & theMV,const TopTools_DataMapOfShapeShape & theDMFImF,const TopTools_IndexedMapOfShape & theMFInv,TopTools_MapOfShape & theMFToRem)4375 void BRepOffset_BuildOffsetFaces::RemoveHangingParts (const BOPAlgo_MakerVolume& theMV,
4376 const TopTools_DataMapOfShapeShape& theDMFImF,
4377 const TopTools_IndexedMapOfShape& theMFInv,
4378 TopTools_MapOfShape& theMFToRem)
4379 {
4380 // Map the faces of the result solids to filter them from avoided faces
4381 TopTools_IndexedMapOfShape aMFS;
4382 TopExp::MapShapes (theMV.Shape(), TopAbs_FACE, aMFS);
4383
4384 BRep_Builder aBB;
4385 // Build compound of all faces not included into solids
4386 TopoDS_Compound aCFHangs;
4387 aBB.MakeCompound (aCFHangs);
4388
4389 // Tool for getting the splits of faces
4390 const TopTools_DataMapOfShapeListOfShape& aMVIms = theMV.Images();
4391
4392 TopTools_ListIteratorOfListOfShape aItLArgs (theMV.Arguments());
4393 for (; aItLArgs.More(); aItLArgs.Next())
4394 {
4395 TopExp_Explorer anExpF (aItLArgs.Value(), TopAbs_FACE);
4396 for (; anExpF.More(); anExpF.Next())
4397 {
4398 const TopoDS_Shape& aF = anExpF.Current();
4399 TakeModified (aF, aMVIms, aCFHangs, &aMFS);
4400 }
4401 }
4402
4403 // Make connexity blocks of all hanging parts and check that they are isolated
4404 TopTools_ListOfShape aLCBHangs;
4405 BOPTools_AlgoTools::MakeConnexityBlocks (aCFHangs, TopAbs_EDGE, TopAbs_FACE, aLCBHangs);
4406 if (aLCBHangs.IsEmpty())
4407 return;
4408
4409 // To be removed, the block should contain invalid splits of offset faces and should
4410 // meet one of the following conditions:
4411 // 1. The block should not be connected to any invalid parts (Faces or Edges)
4412 // contained in solids;
4413 // 2. The block should be isolated from other faces, i.e. it should consist of
4414 // the splits of the single offset face.
4415
4416 // Map the edges and vertices of the result solids to check connectivity
4417 // of the hanging blocks to invalid parts contained in solids
4418 TopTools_IndexedDataMapOfShapeListOfShape aDMEF, aDMVE;
4419 TopExp::MapShapesAndAncestors (theMV.Shape(), TopAbs_EDGE, TopAbs_FACE, aDMEF);
4420 TopExp::MapShapesAndAncestors (theMV.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
4421
4422 // Update invalid edges with intersection results
4423 TopTools_MapOfShape aMEInv;
4424 Standard_Integer i, aNbE = myInvalidEdges.Extent();
4425 for (i = 1; i <= aNbE; ++i)
4426 TakeModified (myInvalidEdges (i), aMVIms, aMEInv);
4427
4428 // Update inverted edges with intersection results
4429 TopTools_MapOfShape aMEInverted;
4430 for (Standard_Integer iInv = 1; iInv <= myInvertedEdges.Extent(); ++iInv)
4431 TakeModified (myInvertedEdges (iInv), aMVIms, aMEInverted);
4432
4433 // Tool for getting the origins of the splits
4434 const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
4435
4436 // Find hanging blocks to remove
4437 TopTools_ListOfShape aBlocksToRemove;
4438
4439 TopTools_ListIteratorOfListOfShape aItLCBH (aLCBHangs);
4440 for (; aItLCBH.More(); aItLCBH.Next())
4441 {
4442 const TopoDS_Shape& aCBH = aItLCBH.Value();
4443
4444 // Remove the block containing the inverted edges
4445 Standard_Boolean bHasInverted = Standard_False;
4446 TopExp_Explorer anExpE (aCBH, TopAbs_EDGE);
4447 for (; anExpE.More() && !bHasInverted; anExpE.Next())
4448 {
4449 const TopoDS_Shape& aE = anExpE.Current();
4450 bHasInverted = !aDMEF.Contains (aE) &&
4451 aMEInverted.Contains (aE);
4452 }
4453
4454 if (bHasInverted)
4455 {
4456 aBlocksToRemove.Append (aCBH);
4457 continue;
4458 }
4459
4460 // Check the block to contain invalid split
4461 Standard_Boolean bHasInvalidFace = Standard_False;
4462 // Check connectivity to invalid parts
4463 Standard_Boolean bIsConnected = Standard_False;
4464 TopTools_IndexedMapOfShape aBlockME;
4465 TopExp::MapShapes (aCBH, TopAbs_EDGE, aBlockME);
4466 // Map to collect all original faces
4467 TopTools_MapOfShape aMOffsetF;
4468
4469 TopExp_Explorer anExpF (aCBH, TopAbs_FACE);
4470 for (; anExpF.More(); anExpF.Next())
4471 {
4472 const TopoDS_Shape& aF = anExpF.Current();
4473 // Check block to contain invalid face
4474 if (!bHasInvalidFace)
4475 bHasInvalidFace = theMFInv.Contains (aF);
4476
4477 // Check block for connectivity to invalid parts
4478 if (!bIsConnected)
4479 {
4480 // check edges
4481 anExpE.Init (aF, TopAbs_EDGE);
4482 for (; anExpE.More() && !bIsConnected; anExpE.Next())
4483 {
4484 const TopoDS_Shape& aE = anExpE.Current();
4485 const TopTools_ListOfShape* pLF = aDMEF.Seek (aE);
4486 if (pLF)
4487 {
4488 TopTools_ListIteratorOfListOfShape aItLF (*pLF);
4489 for (; aItLF.More() && !bIsConnected; aItLF.Next())
4490 bIsConnected = theMFInv.Contains (aItLF.Value());
4491 }
4492 }
4493 // check vertices
4494 if (!bIsConnected)
4495 {
4496 TopExp_Explorer anExpV (aF, TopAbs_VERTEX);
4497 for (; anExpV.More() && !bIsConnected; anExpV.Next())
4498 {
4499 const TopoDS_Shape& aV = anExpV.Current();
4500 const TopTools_ListOfShape* pLE = aDMVE.Seek (aV);
4501 if (pLE)
4502 {
4503 TopTools_ListIteratorOfListOfShape aItLE (*pLE);
4504 for (; aItLE.More() && !bIsConnected; aItLE.Next())
4505 bIsConnected = !aBlockME.Contains (aItLE.Value()) &&
4506 aMEInv.Contains (aItLE.Value());
4507 }
4508 }
4509 }
4510 }
4511
4512 // Check block to be isolated
4513 const TopTools_ListOfShape* pLFOr = aMVOrs.Seek (aF);
4514 if (pLFOr)
4515 {
4516 TopTools_ListIteratorOfListOfShape aItLFOr (*pLFOr);
4517 for (; aItLFOr.More(); aItLFOr.Next())
4518 {
4519 const TopoDS_Shape* pFOffset = theDMFImF.Seek (aItLFOr.Value());
4520 if (pFOffset)
4521 aMOffsetF.Add (*pFOffset);
4522 }
4523 }
4524 else
4525 {
4526 const TopoDS_Shape* pFOffset = theDMFImF.Seek (aF);
4527 if (pFOffset)
4528 aMOffsetF.Add (*pFOffset);
4529 }
4530 }
4531
4532 Standard_Boolean bRemove = bHasInvalidFace &&
4533 (!bIsConnected || aMOffsetF.Extent() == 1);
4534
4535 if (bRemove)
4536 aBlocksToRemove.Append (aCBH);
4537 }
4538
4539 // remove the invalidated blocks
4540 aItLCBH.Initialize (aBlocksToRemove);
4541 for (; aItLCBH.More(); aItLCBH.Next())
4542 {
4543 const TopoDS_Shape& aCBH = aItLCBH.Value();
4544 TopExp_Explorer anExpF (aCBH, TopAbs_FACE);
4545 for (; anExpF.More(); anExpF.Next())
4546 theMFToRem.Add (anExpF.Current());
4547 }
4548 }
4549
4550 //=======================================================================
4551 //function : RemoveValidSplits
4552 //purpose : Removing valid splits according to results of intersection
4553 //=======================================================================
RemoveValidSplits(const TopTools_MapOfShape & theSpRem,BOPAlgo_Builder & theGF,TopTools_IndexedMapOfShape & theMERemoved)4554 void BRepOffset_BuildOffsetFaces::RemoveValidSplits (const TopTools_MapOfShape& theSpRem,
4555 BOPAlgo_Builder& theGF,
4556 TopTools_IndexedMapOfShape& theMERemoved)
4557 {
4558 Standard_Integer i, aNb = myOFImages.Extent();
4559 if (!aNb)
4560 {
4561 return;
4562 }
4563 //
4564 for (i = 1; i <= aNb; ++i)
4565 {
4566 TopTools_ListOfShape& aLSIm = myOFImages (i);
4567 TopTools_ListIteratorOfListOfShape aIt (aLSIm);
4568 for (; aIt.More(); )
4569 {
4570 const TopoDS_Shape& aSIm = aIt.Value();
4571 if (theSpRem.Contains (aSIm))
4572 {
4573 TopExp::MapShapes (aSIm, TopAbs_EDGE, theMERemoved);
4574 aLSIm.Remove (aIt);
4575 continue;
4576 }
4577 //
4578 // check if all its images are have to be removed
4579 const TopTools_ListOfShape& aLSImIm = theGF.Modified (aSIm);
4580 if (aLSImIm.Extent())
4581 {
4582 Standard_Boolean bAllRem = Standard_True;
4583 TopTools_ListIteratorOfListOfShape aIt1 (aLSImIm);
4584 for (; aIt1.More(); aIt1.Next())
4585 {
4586 const TopoDS_Shape& aSImIm = aIt1.Value();
4587 if (theSpRem.Contains (aSImIm))
4588 {
4589 TopExp::MapShapes (aSImIm, TopAbs_EDGE, theMERemoved);
4590 }
4591 else
4592 {
4593 bAllRem = Standard_False;
4594 }
4595 }
4596 //
4597 if (bAllRem)
4598 {
4599 TopExp::MapShapes (aSIm, TopAbs_EDGE, theMERemoved);
4600 aLSIm.Remove (aIt);
4601 continue;
4602 }
4603 }
4604 aIt.Next();
4605 }
4606 }
4607 }
4608
4609 //=======================================================================
4610 //function : RemoveInvalidSplits
4611 //purpose : Removing invalid splits according to the results of intersection
4612 //=======================================================================
RemoveInvalidSplits(const TopTools_MapOfShape & theSpRem,BOPAlgo_Builder & theGF,TopTools_IndexedMapOfShape & theMERemoved)4613 void BRepOffset_BuildOffsetFaces::RemoveInvalidSplits (const TopTools_MapOfShape& theSpRem,
4614 BOPAlgo_Builder& theGF,
4615 TopTools_IndexedMapOfShape& theMERemoved)
4616 {
4617 Standard_Integer i, aNb = myInvalidFaces.Extent();
4618 if (!aNb)
4619 {
4620 return;
4621 }
4622 //
4623 for (i = 1; i <= aNb; ++i)
4624 {
4625 const TopoDS_Shape& aS = myInvalidFaces.FindKey (i);
4626 Standard_Boolean bArt = myArtInvalidFaces.IsBound (aS);
4627 //
4628 TopTools_ListOfShape& aLSIm = myInvalidFaces (i);
4629 TopTools_ListIteratorOfListOfShape aIt (aLSIm);
4630 for (; aIt.More();)
4631 {
4632 const TopoDS_Shape& aSIm = aIt.Value();
4633 if (theSpRem.Contains (aSIm))
4634 {
4635 TopExp::MapShapes (aSIm, TopAbs_EDGE, theMERemoved);
4636 aLSIm.Remove (aIt);
4637 continue;
4638 }
4639 //
4640 // check if all its images are have to be removed
4641 const TopTools_ListOfShape& aLSImIm = theGF.Modified (aSIm);
4642 if (aLSImIm.IsEmpty())
4643 {
4644 aIt.Next();
4645 continue;
4646 }
4647 //
4648 Standard_Boolean bAllRem = Standard_True;
4649 TopTools_IndexedMapOfShape aMERemoved;
4650 TopTools_ListIteratorOfListOfShape aIt1 (aLSImIm);
4651 for (; aIt1.More(); aIt1.Next())
4652 {
4653 const TopoDS_Shape& aSImIm = aIt1.Value();
4654 if (theSpRem.Contains (aSImIm))
4655 {
4656 TopExp::MapShapes (aSImIm, TopAbs_EDGE, aMERemoved);
4657 }
4658 else
4659 {
4660 bAllRem = Standard_False;
4661 }
4662 }
4663 //
4664 if (bAllRem)
4665 {
4666 aLSIm.Remove (aIt);
4667 continue;
4668 }
4669 //
4670 if (bArt)
4671 {
4672 aIt.Next();
4673 continue;
4674 }
4675 //
4676 // remove the face from invalid if all invalid edges of this face
4677 // have been marked for removal
4678 TopExp_Explorer aExpE (aSIm, TopAbs_EDGE);
4679 for (; aExpE.More(); aExpE.Next())
4680 {
4681 const TopoDS_Shape& aEInv = aExpE.Current();
4682 if (myInvalidEdges.Contains (aEInv) && !aMERemoved.Contains (aEInv))
4683 {
4684 break;
4685 }
4686 }
4687 if (!aExpE.More())
4688 {
4689 TopExp::MapShapes (aSIm, TopAbs_EDGE, theMERemoved);
4690 aLSIm.Remove (aIt);
4691 }
4692 else
4693 {
4694 aIt.Next();
4695 }
4696 }
4697 }
4698 }
4699
4700 //=======================================================================
4701 //function : FilterEdgesImages
4702 //purpose : Updating the maps of images and origins of the offset edges
4703 //=======================================================================
FilterEdgesImages(const TopoDS_Shape & theS)4704 void BRepOffset_BuildOffsetFaces::FilterEdgesImages (const TopoDS_Shape& theS)
4705 {
4706 // map edges
4707 TopTools_IndexedMapOfShape aME;
4708 TopExp::MapShapes (theS, TopAbs_EDGE, aME);
4709 //
4710 myOEOrigins.Clear();
4711 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM (myOEImages);
4712 for (; aItDM.More(); aItDM.Next())
4713 {
4714 const TopoDS_Shape& aE = aItDM.Key();
4715 TopTools_ListOfShape& aLEIm = aItDM.ChangeValue();
4716 //
4717 TopTools_ListIteratorOfListOfShape aIt (aLEIm);
4718 for (; aIt.More(); )
4719 {
4720 const TopoDS_Shape& aEIm = aIt.Value();
4721 // filter images
4722 if (!aME.Contains (aEIm))
4723 {
4724 // remove the image
4725 // edges with no images left should be kept in the map
4726 // to avoid their usage when building the splits of faces
4727 aLEIm.Remove (aIt);
4728 continue;
4729 }
4730 //
4731 // save origins
4732 if (myOEOrigins.IsBound (aEIm))
4733 {
4734 AppendToList (myOEOrigins.ChangeFind (aEIm), aE);
4735 }
4736 else
4737 {
4738 TopTools_ListOfShape aLOr;
4739 aLOr.Append (aE);
4740 myOEOrigins.Bind (aEIm, aLOr);
4741 }
4742 //
4743 aIt.Next();
4744 }
4745 }
4746 }
4747
4748 //=======================================================================
4749 //function : FilterInvalidFaces
4750 //purpose : Filtering of the invalid faces
4751 //=======================================================================
FilterInvalidFaces(const TopTools_IndexedDataMapOfShapeListOfShape & theDMEF,const TopTools_IndexedMapOfShape & theMERemoved)4752 void BRepOffset_BuildOffsetFaces::FilterInvalidFaces (const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
4753 const TopTools_IndexedMapOfShape& theMERemoved)
4754 {
4755 //
4756 // filter invalid faces, considering faces having only valid
4757 // images left with non-free edges as valid
4758 // do not remove invalid faces if it creates free edges
4759 //
4760 TopTools_IndexedDataMapOfShapeListOfShape aReallyInvFaces;
4761 // Edge-Face connexity map of all splits, both invalid and valid
4762 TopTools_IndexedDataMapOfShapeListOfShape aDMEFAll;
4763 TopTools_ListIteratorOfListOfShape aItLF;
4764 //
4765 const Standard_Integer aNb = myInvalidFaces.Extent();
4766 for (Standard_Integer i = 1; i <= aNb; ++i)
4767 {
4768 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
4769 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
4770 //
4771 if (myArtInvalidFaces.IsBound (aF))
4772 {
4773 if (aLFInv.IsEmpty())
4774 {
4775 myArtInvalidFaces.UnBind (aF);
4776 }
4777 else
4778 {
4779 aReallyInvFaces.Add (aF, aLFInv);
4780 }
4781 continue;
4782 }
4783 //
4784 if (aLFInv.IsEmpty())
4785 {
4786 continue;
4787 }
4788 //
4789 TopTools_ListOfShape& aLFIm = myOFImages.ChangeFromKey (aF);
4790 Standard_Boolean bInvalid = aLFIm.IsEmpty();
4791 //
4792 if (!bInvalid)
4793 {
4794 // check two lists on common splits
4795 aItLF.Initialize (aLFInv);
4796 for (; aItLF.More(); aItLF.Next())
4797 {
4798 const TopoDS_Shape& aFInv = aItLF.Value();
4799 //
4800 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
4801 for (; aItLFIm.More(); aItLFIm.Next())
4802 {
4803 const TopoDS_Shape& aFIm = aItLFIm.Value();
4804 //
4805 if (aFInv.IsSame (aFIm))
4806 {
4807 break;
4808 }
4809 }
4810 //
4811 if (aItLFIm.More())
4812 {
4813 break;
4814 }
4815 }
4816 //
4817 bInvalid = aItLF.More();
4818 }
4819 //
4820 if (!bInvalid)
4821 {
4822 // check for free edges
4823 for (Standard_Integer j = 0; !bInvalid && j < 2; ++j)
4824 {
4825 const TopTools_ListOfShape& aLI = !j ? aLFIm : aLFInv;
4826 aItLF.Initialize (aLI);
4827 for (; aItLF.More(); aItLF.Next())
4828 {
4829 const TopoDS_Shape& aFIm = aItLF.Value();
4830 //
4831 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
4832 for (; aExp.More(); aExp.Next())
4833 {
4834 const TopoDS_Shape& aE = aExp.Current();
4835 if (!theMERemoved.Contains (aE))
4836 {
4837 const TopTools_ListOfShape* pLEF = theDMEF.Seek (aE);
4838 if (pLEF && pLEF->Extent() == 1)
4839 {
4840 break;
4841 }
4842 }
4843 }
4844 //
4845 if (aExp.More())
4846 {
4847 break;
4848 }
4849 }
4850 bInvalid = aItLF.More();
4851 }
4852 }
4853 if (bInvalid)
4854 {
4855 if (aDMEFAll.IsEmpty())
4856 {
4857 aDMEFAll = theDMEF;
4858 for (Standard_Integer iF = 1; iF <= aNb; ++iF)
4859 for (TopTools_ListOfShape::Iterator itLFInv (myInvalidFaces (iF)); itLFInv.More(); itLFInv.Next())
4860 TopExp::MapShapesAndAncestors (itLFInv.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFAll);
4861 }
4862
4863 TopTools_MapOfShape aLocalSplits;
4864 for (Standard_Integer j = 0; j < 2; ++j)
4865 for (aItLF.Initialize ((!j ? aLFIm : aLFInv)); aItLF.More(); aItLF.Next())
4866 aLocalSplits.Add (aItLF.Value());
4867
4868 // Check if all invalid edges are located inside the split and do not touch
4869 // any other faces both invalid and valid
4870 aItLF.Initialize (aLFInv);
4871 for (; aItLF.More(); aItLF.Next())
4872 {
4873 const TopoDS_Shape& aFIm = aItLF.Value();
4874 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
4875 for (; aExp.More(); aExp.Next())
4876 {
4877 const TopoDS_Shape& aE = aExp.Current();
4878 if (myInvalidEdges.Contains (aE) && !theMERemoved.Contains (aE))
4879 {
4880 const TopTools_ListOfShape& aLF = aDMEFAll.FindFromKey (aE);
4881 TopTools_ListOfShape::Iterator itLF (aLF);
4882 for (; itLF.More(); itLF.Next())
4883 {
4884 if (!aLocalSplits.Contains (itLF.Value()))
4885 break;
4886 }
4887 if (itLF.More())
4888 break;
4889 }
4890 }
4891 if (aExp.More())
4892 break;
4893 }
4894 bInvalid = aItLF.More();
4895 if (!bInvalid)
4896 {
4897 aItLF.Initialize (aLFInv);
4898 for (; aItLF.More(); aItLF.Next())
4899 AppendToList (aLFIm, aItLF.Value());
4900 }
4901 }
4902 //
4903 if (bInvalid)
4904 {
4905 aReallyInvFaces.Add (aF, aLFInv);
4906 }
4907 }
4908 //
4909 myInvalidFaces = aReallyInvFaces;
4910 }
4911
4912 //=======================================================================
4913 //function : CheckEdgesCreatedByVertex
4914 //purpose : Checks additionally the unchecked edges originated from vertices
4915 //=======================================================================
CheckEdgesCreatedByVertex()4916 void BRepOffset_BuildOffsetFaces::CheckEdgesCreatedByVertex()
4917 {
4918 // Mark the unchecked edges contained in invalid faces as invalid
4919 const Standard_Integer aNbF = myInvalidFaces.Extent();
4920 for (Standard_Integer i = 1; i <= aNbF; ++i)
4921 {
4922 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
4923 if (myArtInvalidFaces.IsBound (aF))
4924 continue;
4925
4926 const TopTools_ListOfShape& aLFIm = myInvalidFaces (i);
4927 for (TopTools_ListOfShape::Iterator it (aLFIm); it.More(); it.Next())
4928 {
4929 const TopoDS_Shape& aFIm = it.Value();
4930 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
4931 {
4932 const TopoDS_Shape& aE = expE.Current();
4933 if (myInvalidEdges.Contains (aE)
4934 || myValidEdges.Contains (aE))
4935 {
4936 continue;
4937 }
4938
4939 // check if this edges is not created from vertex and mark it as invalid
4940 const TopTools_ListOfShape* pLEOr = myEdgesOrigins->Seek (aE);
4941 if (!pLEOr)
4942 continue;
4943 TopTools_ListOfShape::Iterator itLEO (*pLEOr);
4944 for (; itLEO.More(); itLEO.Next())
4945 {
4946 if (itLEO.Value().ShapeType() != TopAbs_VERTEX)
4947 break;
4948 }
4949 if (!itLEO.More())
4950 {
4951 myInvalidEdges.Add (aE);
4952 }
4953 }
4954 }
4955 }
4956 }
4957
4958 //=======================================================================
4959 //function : FilterInvalidEdges
4960 //purpose : Filtering the invalid edges according to currently invalid faces
4961 //=======================================================================
FilterInvalidEdges(const BRepOffset_DataMapOfShapeIndexedMapOfShape & theDMFMIE,const TopTools_IndexedMapOfShape & theMERemoved)4962 void BRepOffset_BuildOffsetFaces::FilterInvalidEdges (const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
4963 const TopTools_IndexedMapOfShape& theMERemoved)
4964 {
4965 TopoDS_Compound aCEInv;
4966 TopTools_IndexedMapOfShape aMEInv;
4967 BRep_Builder aBB;
4968 aBB.MakeCompound (aCEInv);
4969 TopTools_ListIteratorOfListOfShape aItLF;
4970 //
4971 Standard_Integer i, aNb = myInvalidFaces.Extent();
4972 for (i = 1; i <= aNb; ++i)
4973 {
4974 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
4975 aItLF.Initialize (aLFInv);
4976 for (; aItLF.More(); aItLF.Next())
4977 {
4978 const TopoDS_Shape& aFIm = aItLF.Value();
4979 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMEInv);
4980 //
4981 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
4982 for (; aExpE.More(); aExpE.Next())
4983 {
4984 const TopoDS_Shape& aE = aExpE.Current();
4985 if (myInvalidEdges.Contains (aE))
4986 {
4987 aBB.Add (aCEInv, aE);
4988 }
4989 }
4990 }
4991 }
4992 //
4993 // remove edges which have been marked for removal
4994 TopTools_IndexedMapOfShape aMEInvToAvoid;
4995 TopTools_ListOfShape aLCBE;
4996 BOPTools_AlgoTools::MakeConnexityBlocks (aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4997 //
4998 TopTools_ListIteratorOfListOfShape aItLCBE (aLCBE);
4999 for (; aItLCBE.More(); aItLCBE.Next())
5000 {
5001 const TopoDS_Shape& aCBE = aItLCBE.Value();
5002 TopExp_Explorer aExpCB (aCBE, TopAbs_EDGE);
5003 for (; aExpCB.More(); aExpCB.Next())
5004 {
5005 const TopoDS_Shape& aE = aExpCB.Current();
5006 if (!theMERemoved.Contains (aE))
5007 {
5008 break;
5009 }
5010 }
5011 //
5012 if (!aExpCB.More())
5013 {
5014 TopExp::MapShapes (aCBE, TopAbs_EDGE, aMEInvToAvoid);
5015 }
5016 }
5017 //
5018 TopTools_IndexedMapOfShape aReallyInvEdges;
5019 //
5020 aNb = myInvalidFaces.Extent();
5021 for (i = 1; i <= aNb; ++i)
5022 {
5023 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
5024 if (myArtInvalidFaces.IsBound (aF))
5025 {
5026 const TopTools_IndexedMapOfShape& aMIE = theDMFMIE.Find (aF);
5027 const Standard_Integer aNbIE = aMIE.Extent();
5028 for (Standard_Integer iE = 1; iE <= aNbIE; ++iE)
5029 {
5030 const TopoDS_Shape& aE = aMIE (iE);
5031 if (aMEInv.Contains (aE) && !aMEInvToAvoid.Contains (aE))
5032 {
5033 aReallyInvEdges.Add (aE);
5034 }
5035 }
5036 }
5037 else
5038 {
5039 const TopTools_ListOfShape& aLFInv = myInvalidFaces (i);
5040 aItLF.Initialize (aLFInv);
5041 for (; aItLF.More(); aItLF.Next())
5042 {
5043 const TopoDS_Shape& aFIm = aItLF.Value();
5044 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
5045 for (; aExpE.More(); aExpE.Next())
5046 {
5047 const TopoDS_Shape& aE = aExpE.Current();
5048 if (myInvalidEdges.Contains (aE) && !aMEInvToAvoid.Contains (aE))
5049 {
5050 aReallyInvEdges.Add (aE);
5051 }
5052 }
5053 }
5054 }
5055 }
5056 //
5057 myInvalidEdges = aReallyInvEdges;
5058 }
5059
5060 //=======================================================================
5061 //function : FindFacesToRebuild
5062 //purpose : Looking for the faces that have to be rebuilt:
5063 // 1. Faces close to invalidity
5064 // 2. Faces containing some invalid parts
5065 //=======================================================================
FindFacesToRebuild()5066 void BRepOffset_BuildOffsetFaces::FindFacesToRebuild()
5067 {
5068 Standard_Integer i, aNb = myOFImages.Extent();
5069 if (!aNb)
5070 {
5071 return;
5072 }
5073 //
5074 Standard_Boolean bRebuild;
5075 TopTools_ListIteratorOfListOfShape aItLF;
5076 TopTools_ListOfShape aLEValid;
5077 TopTools_MapOfShape aMFence, aMEReb, aMFReb;
5078 TopExp_Explorer aExp;
5079 //
5080 TopTools_DataMapOfShapeListOfShape aDMFLV;
5081 // get edges from invalid faces
5082 aNb = myInvalidFaces.Extent();
5083 for (i = 1; i <= aNb; i++)
5084 {
5085 const TopoDS_Shape& aF = myInvalidFaces.FindKey (i);
5086 aMFence.Clear();
5087 TopTools_ListOfShape aLVAvoid;
5088 const TopTools_ListOfShape& aLFIm = myInvalidFaces (i);
5089 aItLF.Initialize (aLFIm);
5090 for (; aItLF.More(); aItLF.Next())
5091 {
5092 const TopoDS_Shape& aFIm = aItLF.Value();
5093 aExp.Init (aFIm, TopAbs_EDGE);
5094 for (; aExp.More(); aExp.Next())
5095 {
5096 const TopoDS_Shape& aE = aExp.Current();
5097 aMEReb.Add (aE);
5098 if (myInvalidEdges.Contains (aE))
5099 {
5100 TopExp_Explorer aExpV (aE, TopAbs_VERTEX);
5101 for (; aExpV.More(); aExpV.Next())
5102 {
5103 const TopoDS_Shape& aV = aExpV.Current();
5104 if (aMFence.Add (aV))
5105 {
5106 aLVAvoid.Append (aV);
5107 aMEReb.Add (aV);
5108 }
5109 }
5110 }
5111 }
5112 }
5113 //
5114 if (aLVAvoid.Extent())
5115 {
5116 aDMFLV.Bind (aF, aLVAvoid);
5117 }
5118 //
5119 const TopTools_ListOfShape* pLF = mySSInterfs.Seek (aF);
5120 if (pLF)
5121 {
5122 TopTools_ListIteratorOfListOfShape aItLFE (*pLF);
5123 for (; aItLFE.More(); aItLFE.Next())
5124 {
5125 const TopoDS_Shape& aFE = aItLFE.Value();
5126 aMFReb.Add (aFE);
5127 }
5128 }
5129 }
5130 //
5131 // get face to rebuild
5132 aNb = myOFImages.Extent();
5133 for (i = 1; i <= aNb; i++)
5134 {
5135 const TopoDS_Shape& aF = myOFImages.FindKey (i);
5136 const TopTools_ListOfShape& aLFIm = myOFImages (i);
5137 TopTools_MapOfShape aMVAvoid;
5138 if (aDMFLV.IsBound (aF))
5139 {
5140 const TopTools_ListOfShape& aLVAvoid = aDMFLV.Find (aF);
5141 TopTools_ListIteratorOfListOfShape aItLV (aLVAvoid);
5142 for (; aItLV.More(); aItLV.Next())
5143 {
5144 const TopoDS_Shape& aV = aItLV.Value();
5145 aMVAvoid.Add (aV);
5146 }
5147 }
5148 //
5149 bRebuild = aMFReb.Contains (aF);
5150 aLEValid.Clear();
5151 aMFence.Clear();
5152 //
5153 aItLF.Initialize (aLFIm);
5154 for (; aItLF.More(); aItLF.Next())
5155 {
5156 const TopoDS_Shape& aFIm = aItLF.Value();
5157 aExp.Init (aFIm, TopAbs_EDGE);
5158 for (; aExp.More(); aExp.Next())
5159 {
5160 const TopoDS_Edge& anEIm = TopoDS::Edge (aExp.Current());
5161 if (!myInvalidEdges.Contains (anEIm))
5162 {
5163 if (aMFence.Add (anEIm))
5164 {
5165 aLEValid.Append (anEIm);
5166 }
5167 }
5168 //
5169 if (!bRebuild)
5170 {
5171 bRebuild = aMEReb.Contains (anEIm);
5172 }
5173 //
5174 if (!bRebuild)
5175 {
5176 // check vertices
5177 TopExp_Explorer aExpV (anEIm, TopAbs_VERTEX);
5178 for (; aExpV.More() && !bRebuild; aExpV.Next())
5179 {
5180 const TopoDS_Shape& aV = aExpV.Current();
5181 if (!aMVAvoid.Contains (aV))
5182 {
5183 bRebuild = aMEReb.Contains (aV);
5184 }
5185 }
5186 }
5187 }
5188 }
5189 //
5190 if (!bRebuild)
5191 {
5192 bRebuild = aLFIm.Extent() && myInvalidFaces.Contains (aF);
5193 if (bRebuild)
5194 {
5195 myFSelfRebAvoid.Add (aF);
5196 }
5197 }
5198 //
5199 if (bRebuild)
5200 {
5201 myFacesToRebuild.Add (aF, aLEValid);
5202 }
5203 }
5204 }
5205
5206 //=======================================================================
5207 //function : IntersectFaces
5208 //purpose : Intersection of the faces that should be rebuild to resolve all invalidities
5209 //=======================================================================
IntersectFaces(TopTools_MapOfShape & theVertsToAvoid,const Message_ProgressRange & theRange)5210 void BRepOffset_BuildOffsetFaces::IntersectFaces (TopTools_MapOfShape& theVertsToAvoid,
5211 const Message_ProgressRange& theRange)
5212 {
5213 Standard_Integer aNbFR = myFacesToRebuild.Extent();
5214 if (!aNbFR)
5215 {
5216 return;
5217 }
5218
5219 Message_ProgressScope aPSOuter (theRange, "Rebuilding invalid faces", 10);
5220 //
5221 Standard_Integer i, j, k, aNbInv;
5222 TopTools_ListIteratorOfListOfShape aItLF, aItLE;
5223 //
5224 // get vertices from invalid edges
5225 TopTools_MapOfShape aMVInv, aMVInvAll;
5226 aNbInv = myInvalidEdges.Extent();
5227 for (i = 1; i <= aNbInv; ++i)
5228 {
5229 const TopoDS_Shape& aEInv = myInvalidEdges (i);
5230 Standard_Boolean bValid = myValidEdges.Contains (aEInv);
5231 for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next())
5232 {
5233 const TopoDS_Shape& aV = aExp.Current();
5234 aMVInvAll.Add (aV);
5235 if (!bValid)
5236 {
5237 aMVInv.Add (aV);
5238 }
5239 }
5240 }
5241 //
5242 Standard_Boolean bLookVertToAvoid = (aMVInv.Extent() > 0);
5243 //
5244 TopTools_DataMapOfShapeListOfShape aDMSF, aMDone, aMEInfETrim, aDMVEFull;
5245 TopTools_IndexedDataMapOfShapeListOfShape aFLE, aDMEFInv;
5246 //
5247 // Add all faces to rebuild to outgoing map <aFLE>,
5248 // plus link edges and vertices to the faces to
5249 // define intersection faces
5250 PrepareFacesForIntersection (bLookVertToAvoid, aFLE, aMDone, aDMSF, aMEInfETrim, aDMVEFull, aDMEFInv);
5251
5252 // Find vertices to avoid while trimming the edges.
5253 // These vertices are taken from the invalid edges common between
5254 // splits of different invalid, but not artificially, faces.
5255 // Additional condition for these vertices is that all
5256 // edges adjacent to this vertex must be either invalid
5257 // or contained in invalid faces
5258 TopTools_MapOfShape aMVRInv = theVertsToAvoid;
5259 FindVerticesToAvoid (aDMEFInv, aDMVEFull, aMVRInv);
5260 //
5261 aPSOuter.Next();
5262 if (!aPSOuter.More())
5263 {
5264 return;
5265 }
5266
5267 // The faces should be intersected selectively -
5268 // intersect only faces neighboring to the same invalid face
5269 // and connected to its invalid edges;
5270 // when dealing with artificially invalid faces for intersection to be
5271 // complete we need to use not only invalid edges, but also the
5272 // edges connected to invalid ones
5273
5274 // find blocks of artificially invalid faces
5275 TopTools_DataMapOfShapeShape aDMFImF;
5276 TopoDS_Compound aCFArt;
5277 BRep_Builder().MakeCompound (aCFArt);
5278 TopTools_DataMapIteratorOfDataMapOfShapeShape aItM (myArtInvalidFaces);
5279 for (; aItM.More(); aItM.Next())
5280 {
5281 const TopoDS_Shape& aF = aItM.Key();
5282 const TopTools_ListOfShape& aLFInv = myInvalidFaces.FindFromKey (aF);
5283 aItLF.Initialize (aLFInv);
5284 for (; aItLF.More(); aItLF.Next())
5285 {
5286 BRep_Builder().Add (aCFArt, aItLF.Value());
5287 aDMFImF.Bind (aItLF.Value(), aF);
5288 }
5289 }
5290 //
5291 // make connexity blocks
5292 TopTools_ListOfShape aLCBArt;
5293 BOPTools_AlgoTools::MakeConnexityBlocks (aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt);
5294 //
5295 // alone edges
5296 TopTools_MapOfShape aMEAlone, aMEInvOnArt;
5297 //
5298 Message_ProgressScope aPSArt (aPSOuter.Next(), NULL, aLCBArt.Extent());
5299 TopTools_ListIteratorOfListOfShape aItLCBArt (aLCBArt);
5300 for (; aItLCBArt.More(); aItLCBArt.Next(), aPSArt.Next())
5301 {
5302 if (!aPSArt.More())
5303 {
5304 return;
5305 }
5306 const TopoDS_Shape& aCB = aItLCBArt.Value();
5307 //
5308 // check if aCB contains splits of only one offset face
5309 TopTools_MapOfShape aMFArt;
5310 TopExp_Explorer aExpF (aCB, TopAbs_FACE);
5311 for (; aExpF.More(); aExpF.Next())
5312 {
5313 aMFArt.Add (aDMFImF.Find (aExpF.Current()));
5314 }
5315 //
5316 Standard_Boolean bAlone = (aMFArt.Extent() == 1);
5317 //
5318 // vertices on invalid edges
5319 TopTools_MapOfShape aMVEInv;
5320 TopTools_MapOfShape aMFence;
5321 // edges that should not be marked as alone - edges having same origins as invalid ones
5322 TopTools_MapOfShape aMEAvoid;
5323 // map to find alone edges by looking for free vertices
5324 TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal;
5325 //
5326 TopExp_Explorer aExpE (aCB, TopAbs_EDGE);
5327 for (; aExpE.More(); aExpE.Next())
5328 {
5329 const TopoDS_Shape& aE = aExpE.Current();
5330 if (myInvalidEdges.Contains (aE))
5331 {
5332 aMEInvOnArt.Add (aE);
5333 for (TopoDS_Iterator aItV (aE); aItV.More(); aItV.Next())
5334 {
5335 aMVEInv.Add (aItV.Value());
5336 }
5337 //
5338 if (bAlone)
5339 {
5340 const TopTools_ListOfShape* pLEOr = myOEOrigins.Seek (aE);
5341 if (pLEOr)
5342 {
5343 TopTools_ListIteratorOfListOfShape aItLEOr (*pLEOr);
5344 for (; aItLEOr.More(); aItLEOr.Next())
5345 {
5346 TopTools_ListIteratorOfListOfShape aItLEIm (myOEImages.Find (aItLEOr.Value()));
5347 for (; aItLEIm.More(); aItLEIm.Next())
5348 {
5349 aMEAvoid.Add (aItLEIm.Value());
5350 }
5351 }
5352 }
5353 }
5354 continue;
5355 }
5356 //
5357 if (aMFence.Add (aE))
5358 {
5359 TopExp::MapShapesAndAncestors (aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal);
5360 }
5361 }
5362 //
5363 // find edges with free vertices
5364 Standard_Integer aNbV = aDMVEVal.Extent();
5365 for (i = 1; i <= aNbV; ++i)
5366 {
5367 const TopoDS_Shape& aV = aDMVEVal.FindKey (i);
5368 if (!aMVEInv.Contains (aV))
5369 {
5370 continue;
5371 }
5372 //
5373 const TopTools_ListOfShape& aLEV = aDMVEVal (i);
5374 if (aLEV.Extent() > 1)
5375 {
5376 continue;
5377 }
5378 //
5379 const TopoDS_Shape& aE = aLEV.First();
5380 if (aMEAvoid.Contains (aE))
5381 {
5382 continue;
5383 }
5384 //
5385 aMEAlone.Add (aE);
5386 //
5387 // if this alone edge adds nothing to the intersection list
5388 // it means that the origin of this edge has been split and we need to
5389 // add the neighboring images of the same origins
5390 if (aDMSF.Find (aE).Extent() > 1)
5391 {
5392 continue;
5393 }
5394 //
5395 // check also its vertices
5396 TopoDS_Iterator aItE (aE);
5397 for (; aItE.More(); aItE.Next())
5398 {
5399 const TopoDS_Shape& aVE = aItE.Value();
5400 if (aDMSF.Find (aVE).Extent() > 2)
5401 {
5402 break;
5403 }
5404 }
5405 //
5406 if (aItE.More())
5407 {
5408 continue;
5409 }
5410 //
5411 // the edge is useless - look for other images
5412 const TopTools_ListOfShape* pLEOr = myOEOrigins.Seek (aE);
5413 if (!pLEOr)
5414 {
5415 continue;
5416 }
5417 //
5418 TopTools_ListIteratorOfListOfShape aItLEOr (*pLEOr);
5419 for (; aItLEOr.More(); aItLEOr.Next())
5420 {
5421 const TopoDS_Shape& aEOr = aItLEOr.Value();
5422 //
5423 const TopTools_ListOfShape& aLEIm = myOEImages.Find (aEOr);
5424 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
5425 for (; aItLEIm.More(); aItLEIm.Next())
5426 {
5427 const TopoDS_Shape& aEIm = aItLEIm.Value();
5428 //
5429 if (aMFence.Contains (aEIm))
5430 {
5431 aMEAlone.Add (aEIm);
5432 }
5433 }
5434 }
5435 }
5436 }
5437 //
5438 // Get all invalidities from all faces to be used for avoiding
5439 // repeated usage of the common edges
5440 TopTools_MapOfShape aMAllInvs;
5441 aNbInv = myInvalidFaces.Extent();
5442 for (k = 1; k <= aNbInv; ++k)
5443 {
5444 TopTools_ListIteratorOfListOfShape aIt (myInvalidFaces (k));
5445 for (; aIt.More(); aIt.Next())
5446 {
5447 TopExp_Explorer aExp (aIt.Value(), TopAbs_EDGE);
5448 for (; aExp.More(); aExp.Next())
5449 {
5450 const TopoDS_Shape& aE = aExp.Current();
5451 if (myInvalidEdges.Contains (aE) || aMEAlone.Contains (aE))
5452 {
5453 aMAllInvs.Add (aE);
5454 TopoDS_Iterator aItV (aE);
5455 for (; aItV.More(); aItV.Next())
5456 {
5457 aMAllInvs.Add (aItV.Value());
5458 }
5459 }
5460 }
5461 }
5462 }
5463 //
5464 // Bounding vertices of not trimmed edges
5465 TopTools_MapOfShape aMVBounds;
5466 //
5467 TopTools_MapOfShape aMECheckExt;
5468 // Save connections between not trimmed edge and its trimmed parts
5469 TopTools_DataMapOfShapeListOfShape aDMEETrim;
5470 // Splits of the new edges
5471 TopTools_DataMapOfShapeListOfShape aEImages;
5472 BRep_Builder aBB;
5473
5474 // Keep connection between blocks of invalid edges to the lists of
5475 // found edges to be intersected for its treatment
5476 TopTools_IndexedDataMapOfShapeListOfShape aDMOENEdges;
5477
5478 aNbInv = myInvalidFaces.Extent();
5479 Message_ProgressScope aPSInter (aPSOuter.Next (5), NULL, aNbInv);
5480 for (k = 1; k <= aNbInv; ++k)
5481 {
5482 if (!aPSInter.More())
5483 {
5484 return;
5485 }
5486 const TopoDS_Shape& aFInv = myInvalidFaces.FindKey (k);
5487 Standard_Boolean bSelfRebAvoid = myFSelfRebAvoid.Contains (aFInv);
5488 const TopTools_ListOfShape& aLFInv = myInvalidFaces (k);
5489 //
5490 TopTools_ListOfShape aLCB;
5491 if (aLFInv.Extent() > 1)
5492 {
5493 // make compound of invalid faces
5494 TopoDS_Compound aCFInv;
5495 aBB.MakeCompound (aCFInv);
5496 //
5497 TopTools_ListIteratorOfListOfShape aIt (aLFInv);
5498 for (; aIt.More(); aIt.Next())
5499 {
5500 const TopoDS_Shape& aFIm = aIt.Value();
5501 aBB.Add (aCFInv, aFIm);
5502 }
5503 //
5504 // make connexity blocks
5505 BOPTools_AlgoTools::MakeConnexityBlocks (aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCB);
5506 }
5507 else
5508 {
5509 aLCB = aLFInv;
5510 }
5511 //
5512 Message_ProgressScope aPSCB (aPSInter.Next(), NULL, aLCB.Extent());
5513 Standard_Boolean bArtificial = myArtInvalidFaces.IsBound (aFInv);
5514 TopTools_ListIteratorOfListOfShape aItLCB (aLCB);
5515 for (; aItLCB.More(); aItLCB.Next())
5516 {
5517 if (!aPSCB.More())
5518 {
5519 return;
5520 }
5521 const TopoDS_Shape& aCBInv = aItLCB.Value();
5522 //
5523 TopTools_MapOfShape aMEFence;
5524 //
5525 TopoDS_Compound aCBE;
5526 aBB.MakeCompound (aCBE);
5527 //
5528 TopExp_Explorer aExp (aCBInv, TopAbs_EDGE);
5529 for (; aExp.More(); aExp.Next())
5530 {
5531 const TopoDS_Shape& aE = aExp.Current();
5532 if (myInvalidEdges.Contains (aE) || (bArtificial && aMEAlone.Contains (aE)))
5533 {
5534 if (aMEFence.Add (aE))
5535 {
5536 aBB.Add (aCBE, aE);
5537 }
5538 }
5539 }
5540 //
5541 // make connexity blocks of edges
5542 TopTools_ListOfShape aLCBE;
5543 BOPTools_AlgoTools::MakeConnexityBlocks (aCBE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
5544 //
5545 Message_ProgressScope aPSCBE (aPSCB.Next(), NULL, aLCBE.Extent());
5546 TopTools_ListIteratorOfListOfShape aItLCBE (aLCBE);
5547 for (; aItLCBE.More(); aItLCBE.Next())
5548 {
5549 if (!aPSCBE.More())
5550 {
5551 return;
5552 }
5553 const TopoDS_Shape& aCBELoc = aItLCBE.Value();
5554 //
5555 // map of edges and vertices of processing invalidity
5556 TopTools_IndexedMapOfShape aME;
5557 // map of vertices to trim the new edges
5558 TopTools_IndexedMapOfShape aMECV;
5559 TopExp::MapShapes (aCBELoc, TopAbs_EDGE, aME);
5560 aMECV = aME;
5561 TopExp::MapShapes (aCBELoc, TopAbs_VERTEX, aME);
5562 //
5563 // Using the map <aME> find chain of faces to be intersected;
5564 //
5565 // faces for intersection
5566 TopTools_IndexedMapOfShape aMFInt;
5567 // additional faces for intersection
5568 TopTools_IndexedMapOfShape aMFIntExt;
5569 // splits of faces for intersection
5570 TopTools_ListOfShape aLFInt;
5571 // faces to avoid intersection
5572 TopTools_IndexedMapOfShape aMFAvoid;
5573 //
5574 FindFacesForIntersection (aFInv, aME, aDMSF, aMVInvAll, bArtificial, aMFAvoid, aMFInt, aMFIntExt, aLFInt);
5575 if (aMFInt.Extent() < 3)
5576 {
5577 // nothing to intersect
5578 aPSCBE.Next();
5579 continue;
5580 }
5581 //
5582 const BRepOffset_DataMapOfShapeMapOfShape* pMFInter = myIntersectionPairs.Seek (aFInv);
5583 // intersect the faces, but do not intersect the invalid ones
5584 // among each other (except for the artificially invalid faces)
5585 TopTools_IndexedMapOfShape aMEToInt;
5586 Standard_Integer aNb = aMFInt.Extent();
5587 Message_ProgressScope aPSIntPair (aPSCBE.Next(), NULL, aNb);
5588 for (i = 1; i <= aNb; ++i, aPSIntPair.Next())
5589 {
5590 if (!aPSIntPair.More())
5591 {
5592 return;
5593 }
5594 const TopoDS_Face& aFi = TopoDS::Face (aMFInt (i));
5595 if (bSelfRebAvoid && aFi.IsSame (aFInv))
5596 {
5597 continue;
5598 }
5599 //
5600 const TopTools_ListOfShape& aLFImi = myOFImages.FindFromKey (aFi);
5601 //
5602 TopTools_ListOfShape& aLFEi = aFLE.ChangeFromKey (aFi);
5603 //
5604 TopTools_ListOfShape& aLFDone = aMDone.ChangeFind (aFi);
5605 //
5606 const TopTools_MapOfShape* pInterFi = !pMFInter ? 0 : pMFInter->Seek (aFi);
5607 if (pMFInter && !pInterFi)
5608 continue;
5609
5610 for (j = i + 1; j <= aNb; ++j)
5611 {
5612 const TopoDS_Face& aFj = TopoDS::Face (aMFInt (j));
5613 if (bSelfRebAvoid && aFj.IsSame (aFInv))
5614 {
5615 continue;
5616 }
5617 //
5618 if (pInterFi && !pInterFi->Contains (aFj))
5619 continue;
5620
5621 const TopTools_ListOfShape& aLFImj = myOFImages.FindFromKey (aFj);
5622 //
5623 TopTools_ListOfShape& aLFEj = aFLE.ChangeFromKey (aFj);
5624 //
5625 // if there are some common edges between faces
5626 // we should use these edges and do not intersect again.
5627 TopTools_ListOfShape aLEC;
5628 FindCommonParts (aLFImi, aLFImj, aLEC);
5629 //
5630 if (aLEC.Extent())
5631 {
5632 // no need to intersect if we have common edges between faces
5633 Standard_Boolean bForceUse = aMFIntExt.Contains (aFi) || aMFIntExt.Contains (aFj);
5634 ProcessCommonEdges (aLEC, aME, aMEInfETrim, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt);
5635 continue;
5636 }
5637 //
5638 // check if both these faces are invalid and sharing edges
5639 if (myInvalidFaces.Contains (aFi) && myInvalidFaces.Contains (aFj) &&
5640 !myArtInvalidFaces.IsBound (aFi) && !myArtInvalidFaces.IsBound (aFj))
5641 {
5642 continue;
5643 }
5644 //
5645 // check if these two faces have already been treated
5646 aItLE.Initialize (aLFDone);
5647 for (; aItLE.More(); aItLE.Next())
5648 {
5649 const TopoDS_Shape& aF = aItLE.Value();
5650 if (aF.IsSame (aFj))
5651 {
5652 break;
5653 }
5654 }
5655 //
5656 if (aItLE.More())
5657 {
5658 // use intersection line obtained on the previous steps
5659 // plus, find new origins for these lines
5660 UpdateIntersectedFaces (aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj, aLFEi, aLFEj, aMEToInt);
5661 continue;
5662 }
5663 //
5664 if (aMFAvoid.Contains (aFi) || aMFAvoid.Contains (aFj))
5665 {
5666 continue;
5667 }
5668 //
5669 aLFDone.Append (aFj);
5670 aMDone.ChangeFind (aFj).Append (aFi);
5671 //
5672 IntersectFaces (aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj, aLFEi, aLFEj, aMECV, aMEToInt);
5673 }
5674 }
5675 //
5676 // intersect and trim edges for this chain
5677 IntersectAndTrimEdges (aMFInt, aMEToInt, aDMEETrim, aME, aMECV,
5678 aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages);
5679 //
5680 Standard_Integer iE, aNbEToInt = aMEToInt.Extent();
5681 for (iE = 1; iE <= aNbEToInt; ++iE)
5682 {
5683 const TopoDS_Shape& aEInt = aMEToInt (iE);
5684 TopExp_Explorer anExpE (aCBELoc, TopAbs_EDGE);
5685 for (; anExpE.More(); anExpE.Next())
5686 {
5687 const TopoDS_Shape& aE = anExpE.Current();
5688 TopTools_ListOfShape* pLEToInt = aDMOENEdges.ChangeSeek (aE);
5689 if (!pLEToInt)
5690 pLEToInt = &aDMOENEdges (aDMOENEdges.Add (aE, TopTools_ListOfShape()));
5691 AppendToList (*pLEToInt, aEInt);
5692 }
5693 }
5694 }
5695 }
5696 }
5697 //
5698 // filter the obtained edges
5699 UpdateValidEdges (aFLE, aDMOENEdges, aMVBounds, aMEInvOnArt, aMECheckExt,
5700 theVertsToAvoid, aEImages, aDMEETrim, aPSOuter.Next (3));
5701 }
5702
5703 //=======================================================================
5704 //function : PrepareFacesForIntersection
5705 //purpose : Preparation of the maps for analyzing intersections of the faces
5706 //=======================================================================
PrepareFacesForIntersection(const Standard_Boolean theLookVertToAvoid,TopTools_IndexedDataMapOfShapeListOfShape & theFLE,TopTools_DataMapOfShapeListOfShape & theMDone,TopTools_DataMapOfShapeListOfShape & theDMSF,TopTools_DataMapOfShapeListOfShape & theMEInfETrim,TopTools_DataMapOfShapeListOfShape & theDMVEFull,TopTools_IndexedDataMapOfShapeListOfShape & theDMEFInv)5707 void BRepOffset_BuildOffsetFaces::PrepareFacesForIntersection (const Standard_Boolean theLookVertToAvoid,
5708 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
5709 TopTools_DataMapOfShapeListOfShape& theMDone,
5710 TopTools_DataMapOfShapeListOfShape& theDMSF,
5711 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5712 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5713 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv)
5714 {
5715 Standard_Integer i, aNb = myFacesToRebuild.Extent();
5716 for (i = 1; i <= aNb; ++i)
5717 {
5718 const TopoDS_Shape& aF = myFacesToRebuild.FindKey (i);
5719 //
5720 TopTools_ListOfShape aLE;
5721 theFLE.Add (aF, aLE);
5722 theMDone.Bind (aF, aLE);
5723 //
5724 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
5725 TopTools_ListIteratorOfListOfShape aItLF (aLFIm);
5726 for (; aItLF.More(); aItLF.Next())
5727 {
5728 const TopoDS_Shape& aFIm = aItLF.Value();
5729 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
5730 for (; aExp.More(); aExp.Next())
5731 {
5732 const TopoDS_Shape& aE = aExp.Current();
5733 // save connection to untrimmed face
5734 TopTools_ListOfShape* pLF = theDMSF.ChangeSeek (aE);
5735 if (!pLF)
5736 {
5737 pLF = theDMSF.Bound (aE, TopTools_ListOfShape());
5738 }
5739 AppendToList (*pLF, aF);
5740 //
5741 // save connection to untrimmed edge
5742 const TopoDS_Shape& aEInf = myETrimEInf->Find (aE);
5743 TopTools_ListOfShape* pLETrim = theMEInfETrim.ChangeSeek (aEInf);
5744 if (!pLETrim)
5745 {
5746 pLETrim = theMEInfETrim.Bound (aEInf, TopTools_ListOfShape());
5747 }
5748 AppendToList (*pLETrim, aE);
5749 //
5750 TopExp_Explorer aExpV (aE, TopAbs_VERTEX);
5751 for (; aExpV.More(); aExpV.Next())
5752 {
5753 const TopoDS_Shape& aV = aExpV.Current();
5754 // save connection to face
5755 TopTools_ListOfShape* pLFV = theDMSF.ChangeSeek (aV);
5756 if (!pLFV)
5757 {
5758 pLFV = theDMSF.Bound (aV, TopTools_ListOfShape());
5759 }
5760 AppendToList (*pLFV, aF);
5761 //
5762 if (theLookVertToAvoid)
5763 {
5764 // save connection to edges
5765 TopTools_ListOfShape* pLEV = theDMVEFull.ChangeSeek (aV);
5766 if (!pLEV)
5767 {
5768 pLEV = theDMVEFull.Bound (aV, TopTools_ListOfShape());
5769 }
5770 AppendToList (*pLEV, aE);
5771 }
5772 }
5773 }
5774 }
5775 //
5776 if (theLookVertToAvoid)
5777 {
5778 // get edges of invalid faces (from invalid splits only)
5779 const TopTools_ListOfShape* pLFInv = myInvalidFaces.Seek (aF);
5780 if (!pLFInv || myArtInvalidFaces.IsBound (aF))
5781 {
5782 continue;
5783 }
5784 //
5785 aItLF.Initialize (*pLFInv);
5786 for (; aItLF.More(); aItLF.Next())
5787 {
5788 const TopoDS_Shape& aFInv = aItLF.Value();
5789 TopExp_Explorer aExp (aFInv, TopAbs_EDGE);
5790 for (; aExp.More(); aExp.Next())
5791 {
5792 const TopoDS_Shape& aE = aExp.Current();
5793 TopTools_ListOfShape* pLF = theDMEFInv.ChangeSeek (aE);
5794 if (!pLF)
5795 {
5796 pLF = &theDMEFInv (theDMEFInv.Add (aE, TopTools_ListOfShape()));
5797 }
5798 AppendToList (*pLF, aF);
5799 }
5800 }
5801 }
5802 }
5803 }
5804
5805 //=======================================================================
5806 //function : FindVerticesToAvoid
5807 //purpose : Looking for the invalid vertices
5808 //=======================================================================
FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape & theDMEFInv,const TopTools_DataMapOfShapeListOfShape & theDMVEFull,TopTools_MapOfShape & theMVRInv)5809 void BRepOffset_BuildOffsetFaces::FindVerticesToAvoid (const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
5810 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5811 TopTools_MapOfShape& theMVRInv)
5812 {
5813 TopTools_MapOfShape aMFence;
5814 Standard_Integer i, aNb = theDMEFInv.Extent();
5815 for (i = 1; i <= aNb; ++i)
5816 {
5817 const TopTools_ListOfShape& aLFInv = theDMEFInv (i);
5818 if (aLFInv.Extent() == 1)
5819 {
5820 continue;
5821 }
5822 //
5823 const TopoDS_Shape& aE = theDMEFInv.FindKey (i);
5824 if (!myInvalidEdges.Contains (aE) || myValidEdges.Contains (aE))
5825 {
5826 continue;
5827 }
5828
5829 if (!aMFence.Add (aE))
5830 continue;
5831
5832 TopTools_IndexedDataMapOfShapeListOfShape aMVEEdges;
5833 // Do not check the splitting vertices, but check only the ending ones
5834 const TopTools_ListOfShape* pLEOr = myOEOrigins.Seek (aE);
5835 if (pLEOr)
5836 {
5837 TopTools_ListIteratorOfListOfShape aItLEOr (*pLEOr);
5838 for (; aItLEOr.More(); aItLEOr.Next())
5839 {
5840 const TopTools_ListOfShape& aLEIm = myOEImages.Find (aItLEOr.Value());
5841 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
5842 for (; aItLEIm.More(); aItLEIm.Next())
5843 {
5844 aMFence.Add (aItLEIm.Value());
5845 TopExp::MapShapesAndAncestors (aItLEIm.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5846 }
5847 }
5848 }
5849 else
5850 {
5851 TopExp::MapShapesAndAncestors (aE, TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5852 }
5853
5854 Standard_Integer j, aNbV = aMVEEdges.Extent();
5855 for (j = 1; j <= aNbV; ++j)
5856 {
5857 if (aMVEEdges (j).Extent() != 1)
5858 continue;
5859
5860 const TopoDS_Shape& aV = aMVEEdges.FindKey (j);
5861 if (!aMFence.Add (aV))
5862 continue;
5863 const TopTools_ListOfShape* pLE = theDMVEFull.Seek (aV);
5864 if (!pLE)
5865 {
5866 // isolated vertex
5867 theMVRInv.Add (aV);
5868 continue;
5869 }
5870 //
5871 // If all edges sharing the vertex are either invalid or
5872 // the vertex is connected to at least two inverted edges
5873 // mark the vertex to be avoided in the new splits
5874 Standard_Integer iNbEInverted = 0;
5875 Standard_Boolean bAllEdgesInv = Standard_True;
5876 TopTools_ListIteratorOfListOfShape aItLE (*pLE);
5877 for (; aItLE.More(); aItLE.Next())
5878 {
5879 const TopoDS_Shape& aEV = aItLE.Value();
5880
5881 if (myInvertedEdges.Contains (aEV))
5882 ++iNbEInverted;
5883
5884 if (bAllEdgesInv)
5885 bAllEdgesInv = myInvalidEdges.Contains (aEV);
5886 }
5887
5888 if (iNbEInverted > 1 || bAllEdgesInv)
5889 {
5890 theMVRInv.Add (aV);
5891 }
5892 }
5893 }
5894 }
5895
5896 //=======================================================================
5897 //function : FindFacesForIntersection
5898 //purpose : Looking for the faces around each invalidity for intersection
5899 //=======================================================================
FindFacesForIntersection(const TopoDS_Shape & theFInv,const TopTools_IndexedMapOfShape & theME,const TopTools_DataMapOfShapeListOfShape & theDMSF,const TopTools_MapOfShape & theMVInvAll,const Standard_Boolean theArtCase,TopTools_IndexedMapOfShape & theMFAvoid,TopTools_IndexedMapOfShape & theMFInt,TopTools_IndexedMapOfShape & theMFIntExt,TopTools_ListOfShape & theLFImInt)5900 void BRepOffset_BuildOffsetFaces::FindFacesForIntersection (const TopoDS_Shape& theFInv,
5901 const TopTools_IndexedMapOfShape& theME,
5902 const TopTools_DataMapOfShapeListOfShape& theDMSF,
5903 const TopTools_MapOfShape& theMVInvAll,
5904 const Standard_Boolean theArtCase,
5905 TopTools_IndexedMapOfShape& theMFAvoid,
5906 TopTools_IndexedMapOfShape& theMFInt,
5907 TopTools_IndexedMapOfShape& theMFIntExt,
5908 TopTools_ListOfShape& theLFImInt)
5909 {
5910 Standard_Integer i, aNbE = theME.Extent();
5911 //
5912 TopTools_IndexedMapOfShape aMShapes;
5913 //
5914 for (i = 1; i <= aNbE; ++i)
5915 {
5916 const TopoDS_Shape& aS = theME (i);
5917 if (!theDMSF.IsBound (aS))
5918 {
5919 continue;
5920 }
5921 //
5922 // in artificial case we intersect the faces which are close to invalidity
5923 Standard_Boolean bAvoid = theArtCase ?
5924 ((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains (aS)) : Standard_False;
5925 //
5926 const TopTools_ListOfShape& aLF = theDMSF.Find (aS);
5927 TopTools_ListIteratorOfListOfShape aItLF (aLF);
5928 for (; aItLF.More(); aItLF.Next())
5929 {
5930 const TopoDS_Shape& aF = aItLF.Value();
5931 if (theMFInt.Contains (aF))
5932 {
5933 continue;
5934 }
5935 //
5936 if (bAvoid && myArtInvalidFaces.IsBound (aF))
5937 {
5938 theMFAvoid.Add (aF);
5939 }
5940 //
5941 theMFInt.Add (aF);
5942 //
5943 Standard_Boolean bUse = !aF.IsSame (theFInv);
5944 //
5945 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
5946 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
5947 for (; aItLFIm.More(); aItLFIm.Next())
5948 {
5949 const TopoDS_Shape& aFIm = aItLFIm.Value();
5950 theLFImInt.Append (aFIm);
5951 if (bUse)
5952 {
5953 TopExp::MapShapes (aFIm, TopAbs_EDGE, aMShapes);
5954 }
5955 }
5956 }
5957 }
5958 //
5959 if (theArtCase)
5960 {
5961 return;
5962 }
5963 //
5964 const TopTools_ListOfShape* pLFInv = mySSInterfs.Seek (theFInv);
5965 if (!pLFInv)
5966 {
5967 return;
5968 }
5969 //
5970 TopTools_MapOfShape aMF;
5971 TopTools_ListIteratorOfListOfShape aItLF (*pLFInv);
5972 for (; aItLF.More(); aItLF.Next())
5973 {
5974 const TopoDS_Shape& aF = aItLF.Value();
5975 aMF.Add (aF);
5976 }
5977 //
5978 // the faces should be unique in each place
5979 TopoDS_Compound aCF;
5980 BRep_Builder().MakeCompound (aCF);
5981 //
5982 TopTools_IndexedMapOfShape aMFToAdd;
5983 TopTools_DataMapOfShapeShape aDMFOr;
5984 //
5985 for (i = 1; i <= aNbE; ++i)
5986 {
5987 const TopoDS_Shape& aS = theME (i);
5988 const TopTools_ListOfShape* pLF = mySSInterfs.Seek (aS);
5989 if (!pLF)
5990 {
5991 continue;
5992 }
5993 //
5994 aItLF.Initialize (*pLF);
5995 for (; aItLF.More(); aItLF.Next())
5996 {
5997 const TopoDS_Shape& aF = aItLF.Value();
5998 if (theMFInt.Contains (aF) || aMFToAdd.Contains (aF) || !aMF.Contains (aF))
5999 {
6000 continue;
6001 }
6002 //
6003 // check if the face has some connection to already added for intersection faces
6004 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
6005 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
6006 for (; aItLFIm.More(); aItLFIm.Next())
6007 {
6008 const TopoDS_Shape& aFIm = aItLFIm.Value();
6009 TopExp_Explorer aExp (aFIm, TopAbs_EDGE);
6010 for (; aExp.More(); aExp.Next())
6011 {
6012 if (aMShapes.Contains (aExp.Current()))
6013 {
6014 break;
6015 }
6016 }
6017 if (aExp.More())
6018 {
6019 break;
6020 }
6021 }
6022 if (!aItLFIm.More())
6023 {
6024 continue;
6025 }
6026 //
6027 aMFToAdd.Add (aF);
6028 aItLFIm.Initialize (aLFIm);
6029 for (; aItLFIm.More(); aItLFIm.Next())
6030 {
6031 const TopoDS_Shape& aFIm = aItLFIm.Value();
6032 aDMFOr.Bind (aFIm, aF);
6033 BRep_Builder().Add (aCF, aFIm);
6034 }
6035 }
6036 }
6037 //
6038 if (aMFToAdd.IsEmpty())
6039 {
6040 return;
6041 }
6042 //
6043 TopTools_ListOfShape aLCB;
6044 BOPTools_AlgoTools::MakeConnexityBlocks (aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
6045 //
6046 if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1))
6047 {
6048 return;
6049 }
6050 //
6051 TopTools_ListIteratorOfListOfShape aItLCB (aLCB);
6052 for (; aItLCB.More(); aItLCB.Next())
6053 {
6054 const TopoDS_Shape& aCB = aItLCB.Value();
6055 aMFToAdd.Clear();
6056 TopExp_Explorer aExpF (aCB, TopAbs_FACE);
6057 for (; aExpF.More(); aExpF.Next())
6058 {
6059 const TopoDS_Shape& aFIm = aExpF.Current();
6060 aMFToAdd.Add (aDMFOr.Find (aFIm));
6061 }
6062 //
6063 if (aMFToAdd.Extent() == 1)
6064 {
6065 const TopoDS_Shape& aF = aMFToAdd (1);
6066 //
6067 theMFInt.Add (aF);
6068 theMFIntExt.Add (aF);
6069 //
6070 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
6071 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
6072 for (; aItLFIm.More(); aItLFIm.Next())
6073 {
6074 const TopoDS_Shape& aFIm = aItLFIm.Value();
6075 theLFImInt.Append (aFIm);
6076 }
6077 }
6078 }
6079 }
6080
6081 //=======================================================================
6082 //function : ProcessCommonEdges
6083 //purpose : Analyzing the common edges between splits of offset faces
6084 //=======================================================================
ProcessCommonEdges(const TopTools_ListOfShape & theLEC,const TopTools_IndexedMapOfShape & theME,const TopTools_DataMapOfShapeListOfShape & theMEInfETrim,const TopTools_MapOfShape & theAllInvs,const Standard_Boolean theForceUse,TopTools_IndexedMapOfShape & theMECV,TopTools_MapOfShape & theMECheckExt,TopTools_DataMapOfShapeListOfShape & theDMEETrim,TopTools_ListOfShape & theLFEi,TopTools_ListOfShape & theLFEj,TopTools_IndexedMapOfShape & theMEToInt)6085 void BRepOffset_BuildOffsetFaces::ProcessCommonEdges (const TopTools_ListOfShape& theLEC,
6086 const TopTools_IndexedMapOfShape& theME,
6087 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
6088 const TopTools_MapOfShape& theAllInvs,
6089 const Standard_Boolean theForceUse,
6090 TopTools_IndexedMapOfShape& theMECV,
6091 TopTools_MapOfShape& theMECheckExt,
6092 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
6093 TopTools_ListOfShape& theLFEi,
6094 TopTools_ListOfShape& theLFEj,
6095 TopTools_IndexedMapOfShape& theMEToInt)
6096 {
6097 TopTools_ListOfShape aLEC;
6098 // process common edges
6099 TopTools_ListIteratorOfListOfShape aItLE (theLEC);
6100 for (; aItLE.More(); aItLE.Next())
6101 {
6102 const TopoDS_Shape& aEC = aItLE.Value();
6103 //
6104 // check first if common edges are valid
6105 if (myInvalidEdges.Contains (aEC) && !myValidEdges.Contains (aEC))
6106 {
6107 continue;
6108 }
6109 //
6110 // common edge should have connection to current invalidity
6111 if (theME.Contains (aEC))
6112 {
6113 aLEC.Append (aEC);
6114 continue;
6115 }
6116 //
6117 TopoDS_Iterator aItV (aEC);
6118 for (; aItV.More(); aItV.Next())
6119 {
6120 const TopoDS_Shape& aVE = aItV.Value();
6121 if (theME.Contains (aVE))
6122 {
6123 aLEC.Append (aEC);
6124 break;
6125 }
6126 }
6127 }
6128 //
6129 Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
6130 if (bUseOnlyInf)
6131 {
6132 if (theForceUse)
6133 {
6134 aLEC = theLEC;
6135 }
6136 else
6137 {
6138 aItLE.Initialize (theLEC);
6139 for (; aItLE.More(); aItLE.Next())
6140 {
6141 const TopoDS_Shape& aEC = aItLE.Value();
6142 // check if all images of the origin of this edge
6143 // are not connected to any invalidity
6144 const TopoDS_Shape& aEInt = myETrimEInf->Find (aEC);
6145 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find (aEInt);
6146 TopTools_ListIteratorOfListOfShape aItLVE (aLVE);
6147 for (; aItLVE.More(); aItLVE.Next())
6148 {
6149 const TopoDS_Shape& aECx = aItLVE.Value();
6150 if (theAllInvs.Contains (aECx) || myInvalidEdges.Contains (aECx))
6151 {
6152 return;
6153 }
6154 //
6155 TopoDS_Iterator aItV (aECx);
6156 for (; aItV.More(); aItV.Next())
6157 {
6158 if (theAllInvs.Contains (aItV.Value()))
6159 {
6160 return;
6161 }
6162 }
6163 }
6164 // use only one element
6165 if (aLEC.IsEmpty())
6166 {
6167 aLEC.Append (aEC);
6168 }
6169 }
6170 }
6171 }
6172 //
6173 aItLE.Initialize (aLEC);
6174 for (; aItLE.More(); aItLE.Next())
6175 {
6176 const TopoDS_Shape& aEC = aItLE.Value();
6177 //
6178 const TopoDS_Shape& aEInt = myETrimEInf->Find (aEC);
6179 if (!bUseOnlyInf)
6180 {
6181 // find the edges of the same original edge
6182 // and take their vertices as well
6183 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find (aEInt);
6184 TopTools_ListIteratorOfListOfShape aItLVE (aLVE);
6185 for (; aItLVE.More(); aItLVE.Next())
6186 {
6187 const TopoDS_Shape& aECx = aItLVE.Value();
6188 //
6189 const TopTools_ListOfShape* pLEOr = myOEOrigins.Seek (aECx);
6190 if (!pLEOr || (pLEOr->Extent() == 1))
6191 {
6192 TopExp::MapShapes (aECx, TopAbs_VERTEX, theMECV);
6193 }
6194 }
6195 //
6196 // bind unlimited edge to its trimmed part in face to update maps of
6197 // images and origins in the future
6198 TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek (aEInt);
6199 if (!pLTAdded)
6200 {
6201 pLTAdded = theDMEETrim.Bound (aEInt, TopTools_ListOfShape());
6202 }
6203 AppendToList (*pLTAdded, aEC);
6204 }
6205 else if (!theForceUse)
6206 {
6207 theMECheckExt.Add (aEInt);
6208 }
6209 //
6210 AppendToList (theLFEi, aEInt);
6211 AppendToList (theLFEj, aEInt);
6212 theMEToInt.Add (aEInt);
6213 }
6214 }
6215
6216 namespace {
6217 //=======================================================================
6218 //function : FindOrigins
6219 //purpose : Looking for the origin edges
6220 //=======================================================================
FindOrigins(const TopTools_ListOfShape & theLFIm1,const TopTools_ListOfShape & theLFIm2,const TopTools_IndexedMapOfShape & theME,const TopTools_DataMapOfShapeListOfShape & theOrigins,TopTools_ListOfShape & theLEOr)6221 static void FindOrigins (const TopTools_ListOfShape& theLFIm1,
6222 const TopTools_ListOfShape& theLFIm2,
6223 const TopTools_IndexedMapOfShape& theME,
6224 const TopTools_DataMapOfShapeListOfShape& theOrigins,
6225 TopTools_ListOfShape& theLEOr)
6226 {
6227 TopTools_MapOfShape aMFence;
6228 for (Standard_Integer i = 0; i < 2; ++i)
6229 {
6230 const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2;
6231 TopTools_ListOfShape::Iterator aIt (aLF);
6232 for (; aIt.More(); aIt.Next())
6233 {
6234 const TopoDS_Shape& aF = aIt.Value();
6235 //
6236 TopExp_Explorer aExp (aF, TopAbs_EDGE);
6237 for (; aExp.More(); aExp.Next())
6238 {
6239 const TopoDS_Shape& aE = aExp.Current();
6240 //
6241 if (theME.Contains (aE) && theOrigins.IsBound (aE))
6242 {
6243 const TopTools_ListOfShape& aLEOr = theOrigins.Find (aE);
6244 TopTools_ListOfShape::Iterator aItLE (aLEOr);
6245 for (; aItLE.More(); aItLE.Next())
6246 {
6247 const TopoDS_Shape& aEOr = aItLE.Value();
6248 //
6249 if (aMFence.Add (aEOr) && (aEOr.ShapeType() == TopAbs_EDGE))
6250 {
6251 theLEOr.Append (aEOr);
6252 }
6253 }
6254 }
6255 }
6256 }
6257 }
6258 }
6259 }
6260
6261 //=======================================================================
6262 //function : UpdateIntersectedFaces
6263 //purpose : Updating the already interfered faces
6264 //=======================================================================
UpdateIntersectedFaces(const TopoDS_Shape & theFInv,const TopoDS_Shape & theFi,const TopoDS_Shape & theFj,const TopTools_ListOfShape & theLFInv,const TopTools_ListOfShape & theLFImi,const TopTools_ListOfShape & theLFImj,const TopTools_ListOfShape & theLFEi,const TopTools_ListOfShape & theLFEj,TopTools_IndexedMapOfShape & theMEToInt)6265 void BRepOffset_BuildOffsetFaces::UpdateIntersectedFaces (const TopoDS_Shape& theFInv,
6266 const TopoDS_Shape& theFi,
6267 const TopoDS_Shape& theFj,
6268 const TopTools_ListOfShape& theLFInv,
6269 const TopTools_ListOfShape& theLFImi,
6270 const TopTools_ListOfShape& theLFImj,
6271 const TopTools_ListOfShape& theLFEi,
6272 const TopTools_ListOfShape& theLFEj,
6273 TopTools_IndexedMapOfShape& theMEToInt)
6274 {
6275 // Find common edges in these two lists
6276 TopTools_MapOfShape aMEi;
6277 TopTools_ListIteratorOfListOfShape aItLE (theLFEi);
6278 for (; aItLE.More(); aItLE.Next())
6279 {
6280 const TopoDS_Shape& aE = aItLE.Value();
6281 aMEi.Add (aE);
6282 }
6283 //
6284 // find origins
6285 TopTools_IndexedMapOfShape aMEToFindOrigins;
6286 TopTools_ListOfShape aLEToFindOrigins;
6287 if (!theFi.IsSame (theFInv))
6288 {
6289 FindCommonParts (theLFImi, theLFInv, aLEToFindOrigins);
6290 }
6291 if (!theFj.IsSame (theFInv))
6292 {
6293 FindCommonParts (theLFImj, theLFInv, aLEToFindOrigins);
6294 }
6295 //
6296 TopTools_ListOfShape aLEOrInit;
6297 aItLE.Initialize (aLEToFindOrigins);
6298 for (; aItLE.More(); aItLE.Next())
6299 {
6300 const TopoDS_Shape& aEC = aItLE.Value();
6301 aMEToFindOrigins.Add (aEC);
6302 }
6303 //
6304 FindOrigins (theLFImi, theLFImj, aMEToFindOrigins, *myEdgesOrigins, aLEOrInit);
6305 //
6306 aItLE.Initialize (theLFEj);
6307 for (; aItLE.More(); aItLE.Next())
6308 {
6309 const TopoDS_Shape& aE = aItLE.Value();
6310 if (aMEi.Contains (aE))
6311 {
6312 theMEToInt.Add (aE);
6313 if (aLEOrInit.Extent())
6314 {
6315 if (myEdgesOrigins->IsBound (aE))
6316 {
6317 TopTools_ListOfShape& aLEOr = myEdgesOrigins->ChangeFind (aE);
6318 TopTools_ListIteratorOfListOfShape aItLEOr (aLEOrInit);
6319 for (; aItLEOr.More(); aItLEOr.Next())
6320 {
6321 const TopoDS_Shape& aEOr = aItLEOr.Value();
6322 AppendToList (aLEOr, aEOr);
6323 }
6324 }
6325 else
6326 {
6327 myEdgesOrigins->Bind (aE, aLEOrInit);
6328 }
6329 }
6330 }
6331 }
6332 }
6333
6334 //=======================================================================
6335 //function : IntersectFaces
6336 //purpose : Intersection of the pair of faces
6337 //=======================================================================
IntersectFaces(const TopoDS_Shape & theFInv,const TopoDS_Shape & theFi,const TopoDS_Shape & theFj,const TopTools_ListOfShape & theLFInv,const TopTools_ListOfShape & theLFImi,const TopTools_ListOfShape & theLFImj,TopTools_ListOfShape & theLFEi,TopTools_ListOfShape & theLFEj,TopTools_IndexedMapOfShape & theMECV,TopTools_IndexedMapOfShape & theMEToInt)6338 void BRepOffset_BuildOffsetFaces::IntersectFaces (const TopoDS_Shape& theFInv,
6339 const TopoDS_Shape& theFi,
6340 const TopoDS_Shape& theFj,
6341 const TopTools_ListOfShape& theLFInv,
6342 const TopTools_ListOfShape& theLFImi,
6343 const TopTools_ListOfShape& theLFImj,
6344 TopTools_ListOfShape& theLFEi,
6345 TopTools_ListOfShape& theLFEj,
6346 TopTools_IndexedMapOfShape& theMECV,
6347 TopTools_IndexedMapOfShape& theMEToInt)
6348 {
6349 // intersect faces
6350 TopAbs_State aSide = TopAbs_OUT;
6351 TopTools_ListOfShape aLInt1, aLInt2;
6352 TopoDS_Edge aNullEdge;
6353 TopoDS_Face aNullFace;
6354 BRepOffset_Tool::Inter3D (TopoDS::Face (theFi), TopoDS::Face (theFj), aLInt1, aLInt2, aSide,
6355 aNullEdge, aNullFace, aNullFace);
6356 //
6357 if (aLInt1.IsEmpty())
6358 {
6359 return;
6360 }
6361 //
6362 // find common vertices for trimming edges
6363 TopTools_ListOfShape aLCV;
6364 TopTools_ListIteratorOfListOfShape aItLE;
6365 FindCommonParts (theLFImi, theLFImj, aLCV, TopAbs_VERTEX);
6366 if (aLCV.Extent() > 1)
6367 {
6368 aItLE.Initialize (aLCV);
6369 for (; aItLE.More(); aItLE.Next())
6370 {
6371 const TopoDS_Shape& aCV = aItLE.Value();
6372 theMECV.Add (aCV);
6373 }
6374 }
6375 //
6376 // find origins
6377 TopTools_IndexedMapOfShape aMEToFindOrigins;
6378 TopTools_ListOfShape aLEToFindOrigins;
6379 if (!theFi.IsSame (theFInv))
6380 {
6381 FindCommonParts (theLFImi, theLFInv, aLEToFindOrigins);
6382 }
6383 if (!theFj.IsSame (theFInv))
6384 {
6385 FindCommonParts (theLFImj, theLFInv, aLEToFindOrigins);
6386 }
6387 TopTools_ListOfShape aLEOrInit;
6388 aItLE.Initialize (aLEToFindOrigins);
6389 for (; aItLE.More(); aItLE.Next())
6390 {
6391 const TopoDS_Shape& aEC = aItLE.Value();
6392 aMEToFindOrigins.Add (aEC);
6393 }
6394 //
6395 FindOrigins (theLFImi, theLFImj, aMEToFindOrigins, *myEdgesOrigins, aLEOrInit);
6396 //
6397 aItLE.Initialize (aLInt1);
6398 for (; aItLE.More(); aItLE.Next())
6399 {
6400 const TopoDS_Shape& aEInt = aItLE.Value();
6401 theLFEi.Append (aEInt);
6402 theLFEj.Append (aEInt);
6403 //
6404 if (aLEOrInit.Extent())
6405 {
6406 myEdgesOrigins->Bind (aEInt, aLEOrInit);
6407 }
6408 //
6409 theMEToInt.Add (aEInt);
6410 }
6411 }
6412
6413
6414 //=======================================================================
6415 //function : IntersectAndTrimEdges
6416 //purpose : Intersection of the new intersection edges among themselves
6417 //=======================================================================
IntersectAndTrimEdges(const TopTools_IndexedMapOfShape & theMFInt,const TopTools_IndexedMapOfShape & theMEInt,const TopTools_DataMapOfShapeListOfShape & theDMEETrim,const TopTools_IndexedMapOfShape & theMSInv,const TopTools_IndexedMapOfShape & theMVE,const TopTools_MapOfShape & theVertsToAvoid,const TopTools_MapOfShape & theNewVertsToAvoid,const TopTools_MapOfShape & theMECheckExt,TopTools_MapOfShape & theMVBounds,TopTools_DataMapOfShapeListOfShape & theEImages)6418 void BRepOffset_BuildOffsetFaces::IntersectAndTrimEdges (const TopTools_IndexedMapOfShape& theMFInt,
6419 const TopTools_IndexedMapOfShape& theMEInt,
6420 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
6421 const TopTools_IndexedMapOfShape& theMSInv,
6422 const TopTools_IndexedMapOfShape& theMVE,
6423 const TopTools_MapOfShape& theVertsToAvoid,
6424 const TopTools_MapOfShape& theNewVertsToAvoid,
6425 const TopTools_MapOfShape& theMECheckExt,
6426 TopTools_MapOfShape& theMVBounds,
6427 TopTools_DataMapOfShapeListOfShape& theEImages)
6428 {
6429 Standard_Integer i, aNb = theMEInt.Extent();
6430 if (!aNb)
6431 {
6432 return;
6433 }
6434 //
6435 TopTools_ListOfShape aLArgs;
6436 TopTools_MapOfShape aMFence;
6437 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6438 TopExp_Explorer aExp;
6439 //
6440 // get vertices from the splits of intersected faces.
6441 // vertices are taken from the edges close to invalidity
6442 //
6443 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6444 aNb = theMFInt.Extent();
6445 for (i = 1; i <= aNb; ++i)
6446 {
6447 const TopoDS_Shape& aF = theMFInt (i);
6448 const TopTools_ListOfShape& aLE = myFacesToRebuild.FindFromKey (aF);
6449 //
6450 aIt.Initialize (aLE);
6451 for (; aIt.More(); aIt.Next())
6452 {
6453 const TopoDS_Shape& aE = aIt.Value();
6454 TopExp::MapShapesAndAncestors (aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6455 //
6456 aExp.Init (aE, TopAbs_VERTEX);
6457 for (; aExp.More(); aExp.Next())
6458 {
6459 const TopoDS_Shape& aV1 = aExp.Current();
6460 if (!theVertsToAvoid.Contains (aV1) && theMVE.Contains (aV1) && aMFence.Add (aV1))
6461 {
6462 aLArgs.Append (aV1);
6463 }
6464 }
6465 }
6466 }
6467 //
6468 aNb = theMSInv.Extent();
6469 for (i = 1; i <= aNb; ++i)
6470 {
6471 const TopoDS_Shape& aV = theMSInv (i);
6472 if (aV.ShapeType() != TopAbs_VERTEX)
6473 {
6474 continue;
6475 }
6476 //
6477 TopTools_ListOfShape* pLVE = aDMVE.ChangeSeek (aV);
6478 if (!pLVE)
6479 {
6480 continue;
6481 }
6482 //
6483 aIt.Initialize (*pLVE);
6484 for (; aIt.More(); aIt.Next())
6485 {
6486 const TopoDS_Shape& aE = aIt.Value();
6487 //
6488 aExp.Init (aE, TopAbs_VERTEX);
6489 for (; aExp.More(); aExp.Next())
6490 {
6491 const TopoDS_Shape& aV1 = aExp.Current();
6492 if (!theVertsToAvoid.Contains (aV1) && aMFence.Add (aV1))
6493 {
6494 aLArgs.Append (aV1);
6495 }
6496 }
6497 }
6498 }
6499 //
6500 // bounding vertices of untrimmed edges
6501 TopTools_ListOfShape aLVBounds;
6502 // new intersection edges
6503 TopTools_ListOfShape aLENew;
6504 // get edges to intersect
6505 TopTools_ListOfShape aLEInt;
6506 // Common intersection edges. Should be intersected separately
6507 TopTools_ListOfShape aLCE;
6508 //
6509 aNb = theMEInt.Extent();
6510 for (i = 1; i <= aNb; ++i)
6511 {
6512 const TopoDS_Shape& aE = theMEInt (i);
6513 if (theMECheckExt.Contains (aE))
6514 {
6515 // avoid trimming of the intersection edges by additional common edges
6516 aLCE.Append (aE);
6517 continue;
6518 }
6519 //
6520 if (!theDMEETrim.IsBound (aE))
6521 {
6522 aLENew.Append (aE);
6523 }
6524 //
6525 aLEInt.Append (aE);
6526 aLArgs.Append (aE);
6527 //
6528 aExp.Init (aE, TopAbs_VERTEX);
6529 for (; aExp.More(); aExp.Next())
6530 {
6531 const TopoDS_Shape& aV = aExp.Current();
6532 aLVBounds.Append (aV);
6533 }
6534 }
6535 //
6536 // Intersect Edges
6537 BOPAlgo_Builder aGF;
6538 aGF.SetArguments (aLArgs);
6539 aGF.Perform();
6540 if (aGF.HasErrors())
6541 {
6542 return;
6543 }
6544 //
6545 // update vertices to avoid with SD vertices
6546 aIt.Initialize (aLVBounds);
6547 for (; aIt.More(); aIt.Next())
6548 {
6549 const TopoDS_Shape& aV = aIt.Value();
6550 const TopTools_ListOfShape& aLVIm = aGF.Modified (aV);
6551 if (aLVIm.IsEmpty())
6552 {
6553 theMVBounds.Add (aV);
6554 }
6555 else
6556 {
6557 const TopoDS_Shape& aVIm = aLVIm.First();
6558 theMVBounds.Add (aVIm);
6559 }
6560 }
6561 //
6562 // find invalid splits of edges
6563 TopTools_MapOfShape aMEInv;
6564 GetInvalidEdges (theNewVertsToAvoid, theMVBounds, aGF, aMEInv);
6565 //
6566 BRep_Builder aBB;
6567 // get valid splits to intersect with the commons
6568 TopoDS_Compound aCEIm;
6569 aBB.MakeCompound (aCEIm);
6570 //
6571 // remove the splits containing vertices from invalid edges
6572 aIt.Initialize (aLEInt);
6573 for (; aIt.More(); aIt.Next())
6574 {
6575 const TopoDS_Shape& aE = aIt.Value();
6576 //
6577 TopTools_ListOfShape aLEIm = aGF.Modified (aE);
6578 if (aLEIm.IsEmpty())
6579 {
6580 continue;
6581 }
6582 //
6583 aIt1.Initialize (aLEIm);
6584 for (; aIt1.More(); )
6585 {
6586 const TopoDS_Shape& aEIm = aIt1.Value();
6587 //
6588 if (aMEInv.Contains (aEIm))
6589 {
6590 aLEIm.Remove (aIt1);
6591 }
6592 else
6593 {
6594 aBB.Add (aCEIm, aEIm);
6595 aIt1.Next();
6596 }
6597 }
6598 //
6599 if (aLEIm.Extent())
6600 {
6601 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek (aE);
6602 if (!pLEIm)
6603 {
6604 pLEIm = theEImages.Bound (aE, TopTools_ListOfShape());
6605 }
6606 pLEIm->Append (aLEIm);
6607 }
6608 }
6609 //
6610 if (!aLCE.Extent())
6611 {
6612 return;
6613 }
6614 //
6615 // trim common edges by other intersection edges
6616 BOPAlgo_Builder aGFCE;
6617 aGFCE.SetArguments (aLCE);
6618 aGFCE.AddArgument (aCEIm);
6619 aGFCE.Perform();
6620 //
6621 if (aGFCE.HasErrors())
6622 {
6623 return;
6624 }
6625 //
6626 const BOPDS_PDS& pDS = aGFCE.PDS();
6627 TopTools_ListIteratorOfListOfShape aItLCE (aLCE);
6628 for (; aItLCE.More(); aItLCE.Next())
6629 {
6630 const TopoDS_Shape& aE = aItLCE.Value();
6631 TopTools_ListOfShape aLEIm = aGFCE.Modified (aE);
6632 if (aLEIm.IsEmpty())
6633 {
6634 continue;
6635 }
6636 //
6637 // check if it's not coincide with some intersection edge
6638 BOPDS_ListIteratorOfListOfPaveBlock aItLPB (pDS->PaveBlocks (pDS->Index (aE)));
6639 for (; aItLPB.More(); aItLPB.Next())
6640 {
6641 if (pDS->IsCommonBlock (aItLPB.Value()))
6642 {
6643 // find with what it is a common
6644 const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock (aItLPB.Value())->PaveBlocks();
6645 BOPDS_ListIteratorOfListOfPaveBlock aItLPBC (aLPBC);
6646 for (; aItLPBC.More(); aItLPBC.Next())
6647 {
6648 const TopoDS_Shape& aEC = pDS->Shape (aItLPBC.Value()->OriginalEdge());
6649 if (!theMECheckExt.Contains (aEC))
6650 {
6651 break;
6652 }
6653 }
6654 if (aItLPBC.More())
6655 {
6656 break;
6657 }
6658 }
6659 }
6660 if (aItLPB.More())
6661 {
6662 // avoid creation of unnecessary splits from commons which
6663 // coincide with intersection edges
6664 continue;
6665 }
6666 //
6667 // save the images
6668 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek (aE);
6669 if (!pLEIm)
6670 {
6671 pLEIm = theEImages.Bound (aE, TopTools_ListOfShape());
6672 }
6673 pLEIm->Append (aLEIm);
6674 //
6675 // save bounding vertices
6676 for (TopoDS_Iterator aItV (aE); aItV.More(); aItV.Next())
6677 {
6678 const TopoDS_Shape& aV = aItV.Value();
6679 const TopTools_ListOfShape& aLVIm = aGFCE.Modified (aV);
6680 theMVBounds.Add (aLVIm.IsEmpty() ? aV : aLVIm.First());
6681 }
6682 }
6683 }
6684
6685 //=======================================================================
6686 //function : GetInvalidEdges
6687 //purpose : Looking for the invalid edges by intersecting with invalid vertices
6688 //=======================================================================
GetInvalidEdges(const TopTools_MapOfShape & theVertsToAvoid,const TopTools_MapOfShape & theMVBounds,BOPAlgo_Builder & theGF,TopTools_MapOfShape & theMEInv)6689 void BRepOffset_BuildOffsetFaces::GetInvalidEdges (const TopTools_MapOfShape& theVertsToAvoid,
6690 const TopTools_MapOfShape& theMVBounds,
6691 BOPAlgo_Builder& theGF,
6692 TopTools_MapOfShape& theMEInv)
6693 {
6694 if (theVertsToAvoid.IsEmpty())
6695 {
6696 return;
6697 }
6698 //
6699 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6700 // get vertices created with intersection edges
6701 const TopoDS_Shape& aRes = theGF.Shape();
6702 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6703 TopExp::MapShapesAndAncestors (aRes, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6704 //
6705 const BOPDS_PDS& pDS = theGF.PDS();
6706 //
6707 // find invalid splits of edges
6708 // check if the vertex is invalid:
6709 // a. it may be the vertex SD with the vertices to avoid
6710 // b. or it may be the vertex which is created by the intersection
6711 // of only existing edges, i.e. no new intersection edges goes
6712 // through this vertex
6713 //
6714 TopTools_MapOfShape aMVInv;
6715 Standard_Integer i, aNb = aDMVE.Extent();
6716 for (i = 1; i <= aNb; ++i)
6717 {
6718 const TopoDS_Vertex& aV = TopoDS::Vertex (aDMVE.FindKey (i));
6719 if (theMVBounds.Contains (aV))
6720 {
6721 continue;
6722 }
6723 //
6724 Standard_Integer nV = pDS->Index (aV);
6725 if ((nV >= 0) && !pDS->IsNewShape (nV))
6726 {
6727 continue;
6728 }
6729 //
6730 TopTools_MapIteratorOfMapOfShape aItM (theVertsToAvoid);
6731 for (; aItM.More(); aItM.Next())
6732 {
6733 const TopoDS_Vertex& aVInv = *(TopoDS_Vertex*)&aItM.Value();
6734 Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV (aV, aVInv);
6735 if (!iFlag)
6736 {
6737 aMVInv.Add (aV);
6738 break;
6739 }
6740 }
6741 //
6742 if (aItM.More())
6743 {
6744 const TopTools_ListOfShape& aLVE = aDMVE.FindFromKey (aV);
6745 aIt.Initialize (aLVE);
6746 for (; aIt.More(); aIt.Next())
6747 {
6748 const TopoDS_Shape& aE = aIt.Value();
6749 theMEInv.Add (aE);
6750 }
6751 }
6752 }
6753 }
6754
6755 //=======================================================================
6756 //function : UpdateValidEdges
6757 //purpose : Making the new splits and updating the maps
6758 //=======================================================================
UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape & theFLE,const TopTools_IndexedDataMapOfShapeListOfShape & theOENEdges,const TopTools_MapOfShape & theMVBounds,const TopTools_MapOfShape & theMEInvOnArt,TopTools_MapOfShape & theMECheckExt,TopTools_MapOfShape & theVertsToAvoid,TopTools_DataMapOfShapeListOfShape & theEImages,TopTools_DataMapOfShapeListOfShape & theEETrim,const Message_ProgressRange & theRange)6759 void BRepOffset_BuildOffsetFaces::UpdateValidEdges (const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
6760 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
6761 const TopTools_MapOfShape& theMVBounds,
6762 const TopTools_MapOfShape& theMEInvOnArt,
6763 TopTools_MapOfShape& theMECheckExt,
6764 TopTools_MapOfShape& theVertsToAvoid,
6765 TopTools_DataMapOfShapeListOfShape& theEImages,
6766 TopTools_DataMapOfShapeListOfShape& theEETrim,
6767 const Message_ProgressRange& theRange)
6768 {
6769 Message_ProgressScope aPSOuter (theRange, "Updating edges", 10);
6770 // update images and origins of edges, plus update AsDes
6771 //
6772 // new edges
6773 TopTools_ListOfShape aLE;
6774 // back connection from edges to faces
6775 TopTools_DataMapOfShapeListOfShape aMELF;
6776 //
6777 TopTools_MapOfShape aMETmp;
6778 Standard_Integer i, aNb = theFLE.Extent();
6779 for (i = 1; i <= aNb; ++i)
6780 {
6781 const TopoDS_Face& aF = TopoDS::Face (theFLE.FindKey (i));
6782 //
6783 const TopTools_ListOfShape& aLEInt = theFLE (i);
6784 TopTools_ListIteratorOfListOfShape aItLE (aLEInt);
6785 for (; aItLE.More(); aItLE.Next())
6786 {
6787 const TopoDS_Shape& aE = aItLE.Value();
6788 if ((theMECheckExt.Contains (aE) || aMETmp.Contains (aE)) && !theEImages.IsBound (aE))
6789 {
6790 theMECheckExt.Remove (aE);
6791 aMETmp.Add (aE);
6792 continue;
6793 }
6794 TopTools_ListOfShape* pLF = aMELF.ChangeSeek (aE);
6795 if (!pLF)
6796 {
6797 pLF = aMELF.Bound (aE, TopTools_ListOfShape());
6798 aLE.Append (aE);
6799 }
6800 pLF->Append (aF);
6801 }
6802 }
6803 //
6804 if (aLE.IsEmpty())
6805 {
6806 return;
6807 }
6808 //
6809 // bounding edges, that are going to be replaced
6810 TopTools_MapOfShape aMEB;
6811 //
6812 // new intersection edges
6813 TopTools_MapOfShape aMENew;
6814 // map of old vertices
6815 TopTools_MapOfShape aMVOld;
6816 // back connection to untrimmed edges
6817 TopTools_DataMapOfShapeListOfShape aDMEOr;
6818 //
6819 // trim the new intersection edges
6820 TrimNewIntersectionEdges (aLE, theEETrim, theMVBounds, theMECheckExt,
6821 theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF);
6822 //
6823 if (theEImages.IsEmpty())
6824 {
6825 // No new splits is preserved
6826 // update intersection edges and exit
6827 UpdateNewIntersectionEdges (aLE, aMELF, theEImages, theEETrim);
6828 return;
6829 }
6830
6831 aPSOuter.Next();
6832 if (!aPSOuter.More())
6833 {
6834 return;
6835 }
6836
6837 BRep_Builder aBB;
6838
6839 // Make connexity blocks of the invalid edges
6840 // and treat each block separately
6841
6842 // Compound of all invalid edges to make the blocks
6843 TopoDS_Compound aCEAll;
6844 aBB.MakeCompound (aCEAll);
6845
6846 Standard_Integer aNbE = theOENEdges.Extent();
6847 for (i = 1; i <= aNbE; ++i)
6848 aBB.Add (aCEAll, theOENEdges.FindKey (i));
6849
6850 // Separate the edges into blocks
6851 TopTools_ListOfShape aLBlocks;
6852 BOPTools_AlgoTools::MakeConnexityBlocks (aCEAll, TopAbs_VERTEX, TopAbs_EDGE, aLBlocks);
6853
6854 // Perform intersection of the new splits for each block
6855
6856 // Intersected splits
6857 TopTools_IndexedDataMapOfShapeListOfShape aMBlocksSp;
6858
6859 Message_ProgressScope aPSB (aPSOuter.Next(), NULL, aLBlocks.Extent());
6860 TopTools_ListIteratorOfListOfShape aItLB (aLBlocks);
6861 for (; aItLB.More(); aItLB.Next(), aPSB.Next())
6862 {
6863 if (!aPSB.More())
6864 {
6865 return;
6866 }
6867 const TopoDS_Shape& aBlock = aItLB.Value();
6868
6869 // Get the list of new edges for the block
6870 TopTools_ListOfShape aBlockLENew;
6871 {
6872 // Fence map
6873 TopTools_MapOfShape aMEFence;
6874 TopExp_Explorer anExpE (aBlock, TopAbs_EDGE);
6875 for (; anExpE.More(); anExpE.Next())
6876 {
6877 const TopoDS_Shape& aE = anExpE.Current();
6878 const TopTools_ListOfShape& aLEInt = theOENEdges.FindFromKey (aE);
6879 TopTools_ListIteratorOfListOfShape aItLEInt (aLEInt);
6880 for (; aItLEInt.More(); aItLEInt.Next())
6881 {
6882 if (aMEFence.Add (aItLEInt.Value()))
6883 aBlockLENew.Append (aItLEInt.Value());
6884 }
6885 }
6886 }
6887
6888 if (aBlockLENew.IsEmpty())
6889 continue;
6890
6891 // Get the splits of new edges to intersect
6892 TopTools_ListOfShape aLSplits;
6893
6894 TopTools_ListIteratorOfListOfShape aItLE (aBlockLENew);
6895 for (; aItLE.More(); aItLE.Next())
6896 {
6897 const TopoDS_Shape& aE = aItLE.Value();
6898 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek (aE);
6899 if (!pLEIm || pLEIm->IsEmpty())
6900 continue;
6901
6902 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
6903 for (; aItLEIm.More(); aItLEIm.Next())
6904 aLSplits.Append (aItLEIm.Value());
6905 }
6906
6907 if (aLSplits.IsEmpty())
6908 continue;
6909
6910 TopoDS_Shape aCE;
6911 if (aLSplits.Extent() > 1)
6912 // Intersect the new splits among themselves to avoid self-intersections
6913 IntersectEdges (aLSplits, aBlockLENew, theMVBounds, theVertsToAvoid,
6914 aMENew, theMECheckExt, theEImages, aDMEOr, aMELF, aCE);
6915 else
6916 aCE = aLSplits.First();
6917
6918 aMBlocksSp.Add (aCE, aBlockLENew);
6919 }
6920
6921 // Perform filtering of the edges in two steps:
6922 // - Check each block separately using localized bounds
6923 // taken only from the splits of faces of the current block;
6924 // - Intersect all splits together and filter the splits by all bounds.
6925
6926 // FIRST STAGE - separate treatment of the blocks
6927
6928 // Valid splits to be preserved on the first stage
6929 TopTools_MapOfShape aMEVal;
6930
6931 // Blocks of valid edges on the first stage
6932 TopTools_ListOfShape aLValBlocks;
6933
6934 Standard_Integer aNbB = aMBlocksSp.Extent();
6935 Message_ProgressScope aPSBSp (aPSOuter.Next(), NULL, aNbB);
6936 for (i = 1; i <= aNbB; ++i, aPSBSp.Next())
6937 {
6938 if (!aPSBSp.More())
6939 {
6940 return;
6941 }
6942 const TopoDS_Shape& aCE = aMBlocksSp.FindKey (i);
6943 const TopTools_ListOfShape& aBlockLENew = aMBlocksSp (i);
6944
6945 // Get all participating faces to get the bounds
6946 TopTools_ListOfShape aLFaces;
6947 TopTools_ListIteratorOfListOfShape aItLE (aBlockLENew);
6948 for (; aItLE.More(); aItLE.Next())
6949 {
6950 const TopTools_ListOfShape* pLF = aMELF.Seek (aItLE.Value());
6951 if (!pLF)
6952 continue;
6953 TopTools_ListIteratorOfListOfShape aItLF (*pLF);
6954 for (; aItLF.More(); aItLF.Next())
6955 AppendToList (aLFaces, aItLF.Value());
6956 }
6957
6958 // Localized bounds of the splits of the offset faces
6959 // to filter the new splits of the current block
6960 TopoDS_Shape aFilterBounds;
6961 GetBounds (aLFaces, aMEB, aFilterBounds);
6962
6963 // Filter the splits by bounds
6964 TopTools_MapOfShape aMEInvLoc;
6965 GetInvalidEdgesByBounds (aCE, aFilterBounds, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6966 theMECheckExt, theMEInvOnArt, theVertsToAvoid, aMEInvLoc);
6967
6968 // Keep only valid edges of the block
6969 TopoDS_Compound aCEVal;
6970 aBB.MakeCompound (aCEVal);
6971
6972 Standard_Boolean bKept = Standard_False;
6973
6974 TopExp_Explorer anExpE (aCE, TopAbs_EDGE);
6975 for (; anExpE.More(); anExpE.Next())
6976 {
6977 const TopoDS_Shape& aESp = anExpE.Current();
6978 if (!aMEInvLoc.Contains (aESp) && aMEVal.Add (aESp))
6979 {
6980 aBB.Add (aCEVal, aESp);
6981 bKept = Standard_True;
6982 }
6983 }
6984
6985 if (bKept)
6986 aLValBlocks.Append (aCEVal);
6987 }
6988
6989 // Filter the images of edges after the first filtering stage
6990 TopoDS_Shape aSplits1;
6991 FilterSplits (aLE, aMEVal, Standard_False, theEImages, aSplits1);
6992
6993 if (aLValBlocks.IsEmpty())
6994 {
6995 // update intersection edges
6996 UpdateNewIntersectionEdges (aLE, aMELF, theEImages, theEETrim);
6997 return;
6998 }
6999
7000 aPSOuter.Next();
7001 if (!aPSOuter.More())
7002 {
7003 return;
7004 }
7005
7006 // SECOND STAGE - Filter the remaining splits together
7007
7008 // Add for intersection already removed new edges using them
7009 // as markers for other invalid edges
7010 aNbB = aMBlocksSp.Extent();
7011 for (i = 1; i <= aNbB; ++i)
7012 {
7013 const TopoDS_Shape& aCE = aMBlocksSp.FindKey (i);
7014 for (TopExp_Explorer anExp (aCE, TopAbs_EDGE); anExp.More(); anExp.Next())
7015 {
7016 const TopoDS_Shape& aEIm = anExp.Current();
7017 if (aMENew.Contains (aEIm) && !aMEVal.Contains (aEIm))
7018 aLValBlocks.Append (aEIm);
7019 }
7020 }
7021
7022 if (aLValBlocks.Extent() > 1)
7023 // intersect the new splits among themselves to avoid self-intersections
7024 IntersectEdges (aLValBlocks, aLE, theMVBounds, theVertsToAvoid, aMENew,
7025 theMECheckExt, theEImages, aDMEOr, aMELF, aSplits1);
7026 else
7027 aSplits1 = aLValBlocks.First();
7028
7029 aPSOuter.Next();
7030 if (!aPSOuter.More())
7031 {
7032 return;
7033 }
7034
7035 // Get all faces to get the bounds from their splits
7036 TopTools_ListOfShape aLFaces;
7037 for (i = 1; i <= myOFImages.Extent(); ++i)
7038 aLFaces.Append (myOFImages.FindKey (i));
7039
7040 // Bounds of the splits of the offset faces to filter the new splits
7041 TopoDS_Shape aFilterBounds;
7042 GetBounds (aLFaces, aMEB, aFilterBounds);
7043
7044 // Filter the splits by intersection with bounds
7045 TopTools_MapOfShape aMEInv;
7046 GetInvalidEdgesByBounds (aSplits1, aFilterBounds, aMVOld, aMENew, aDMEOr, aMELF,
7047 theEImages, theMECheckExt, theMEInvOnArt, theVertsToAvoid, aMEInv);
7048
7049 // Filter the images of edges after the second filtering stage
7050 // and combine all valid edges into a single compound
7051 TopoDS_Shape aSplits;
7052 FilterSplits (aLE, aMEInv, Standard_True, theEImages, aSplits);
7053
7054 aPSOuter.Next();
7055 if (!aPSOuter.More())
7056 {
7057 return;
7058 }
7059
7060 // get bounds to update
7061 // we need to update the edges of all the affected faces
7062 TopTools_ListOfShape aLF;
7063 // prepare the vertices from new splits of edges
7064 TopTools_IndexedMapOfShape aMVSp;
7065 TopExp::MapShapes (aSplits, TopAbs_VERTEX, aMVSp);
7066 //
7067 Standard_Integer aNbF = myOFImages.Extent();
7068 for (i = 1; i <= aNbF; ++i)
7069 {
7070 const TopoDS_Shape& aF = myOFImages.FindKey (i);
7071 if (theFLE.Contains (aF))
7072 {
7073 aLF.Append (aF);
7074 continue;
7075 }
7076 //
7077 // check the splits of faces to have vertices from splits
7078 const TopTools_ListOfShape& aLFIm = myOFImages (i);
7079 TopTools_ListIteratorOfListOfShape aItLFIm (aLFIm);
7080 for (; aItLFIm.More(); aItLFIm.Next())
7081 {
7082 const TopoDS_Shape& aFIm = aItLFIm.Value();
7083 //
7084 TopExp_Explorer aExpV (aFIm, TopAbs_VERTEX);
7085 for (; aExpV.More(); aExpV.Next())
7086 {
7087 const TopoDS_Shape& aV = aExpV.Current();
7088 if (aMVSp.Contains (aV))
7089 {
7090 break;
7091 }
7092 }
7093 //
7094 if (aExpV.More())
7095 {
7096 break;
7097 }
7098 }
7099 //
7100 if (aItLFIm.More())
7101 {
7102 aLF.Append (aF);
7103 }
7104 }
7105 //
7106 // get bounds from splits of faces of aLF
7107 TopoDS_Shape aBounds;
7108 TopTools_ListOfShape aLAValid, aLABounds;
7109 GetBoundsToUpdate (aLF, aMEB, aLABounds, aLAValid, aBounds);
7110 //
7111 // Intersect valid splits with bounds and update both
7112 BOPAlgo_Builder aGF;
7113 aGF.AddArgument (aBounds);
7114 aGF.AddArgument (aSplits);
7115 aGF.Perform (aPSOuter.Next (3));
7116 //
7117 // update splits
7118 UpdateImages (aLE, theEImages, aGF, myModifiedEdges);
7119 //
7120 // update new intersection edges
7121 UpdateNewIntersectionEdges (aLE, aMELF, theEImages, theEETrim);
7122 //
7123 // update bounds
7124 UpdateImages (aLAValid, myOEImages, aGF, myModifiedEdges);
7125 UpdateOrigins (aLABounds, myOEOrigins, aGF);
7126 UpdateOrigins (aLABounds, *myEdgesOrigins, aGF);
7127 UpdateIntersectedEdges (aLABounds, aGF);
7128 //
7129 // update the EdgesToAvoid with the splits
7130 TopTools_IndexedMapOfShape aNewEdges;
7131 const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek (aSplits);
7132 if (pSplitsIm)
7133 {
7134 TopTools_ListIteratorOfListOfShape aItSpIm (*pSplitsIm);
7135 for (; aItSpIm.More(); aItSpIm.Next())
7136 {
7137 TopExp::MapShapes (aItSpIm.Value(), TopAbs_EDGE, aNewEdges);
7138 }
7139 }
7140 //
7141 // Rebuild the map of edges to avoid, using the intersection results
7142 TopTools_IndexedMapOfShape aMEAvoid;
7143 // GF's data structure
7144 const BOPDS_PDS& pDS = aGF.PDS();
7145
7146 aNbE = myEdgesToAvoid.Extent();
7147 for (i = 1; i <= aNbE; ++i)
7148 {
7149 const TopoDS_Shape& aE = myEdgesToAvoid (i);
7150 const TopTools_ListOfShape& aLEIm = aGF.Modified (aE);
7151
7152 // Only untouched and fully coinciding edges should be kept in the avoid map
7153 Standard_Boolean bKeep = aLEIm.IsEmpty();
7154 if (aLEIm.Extent() == 1 && aE.IsSame (aLEIm.First()))
7155 {
7156 const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks (pDS->Index (aE));
7157 if (aLPB.Extent() == 1)
7158 {
7159 const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
7160 const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock (aPB);
7161 if (!aCB.IsNull())
7162 {
7163 const BOPDS_ListOfPaveBlock& aLPBCB = aCB->PaveBlocks();
7164 BOPDS_ListIteratorOfListOfPaveBlock aItLPB (aLPBCB);
7165 for (; aItLPB.More(); aItLPB.Next())
7166 {
7167 if (pDS->PaveBlocks (aItLPB.Value()->OriginalEdge()).Extent() > 1)
7168 break;
7169 }
7170 bKeep = !aItLPB.More();
7171 }
7172 }
7173 }
7174
7175 if (bKeep)
7176 {
7177 // keep the original edge
7178 aMEAvoid.Add (aE);
7179 continue;
7180 }
7181
7182 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
7183 for (; aItLEIm.More(); aItLEIm.Next())
7184 {
7185 const TopoDS_Shape& aEIm = aItLEIm.Value();
7186 if (!aNewEdges.Contains (aEIm))
7187 aMEAvoid.Add (aEIm);
7188 }
7189 }
7190 myEdgesToAvoid = aMEAvoid;
7191 }
7192
7193 //=======================================================================
7194 //function : TrimNewIntersectionEdges
7195 //purpose :
7196 //=======================================================================
TrimNewIntersectionEdges(const TopTools_ListOfShape & theLE,const TopTools_DataMapOfShapeListOfShape & theEETrim,const TopTools_MapOfShape & theMVBounds,TopTools_MapOfShape & theMECheckExt,TopTools_DataMapOfShapeListOfShape & theEImages,TopTools_MapOfShape & theMEB,TopTools_MapOfShape & theMVOld,TopTools_MapOfShape & theMENew,TopTools_DataMapOfShapeListOfShape & theDMEOr,TopTools_DataMapOfShapeListOfShape & theMELF)7197 void BRepOffset_BuildOffsetFaces::TrimNewIntersectionEdges (const TopTools_ListOfShape& theLE,
7198 const TopTools_DataMapOfShapeListOfShape& theEETrim,
7199 const TopTools_MapOfShape& theMVBounds,
7200 TopTools_MapOfShape& theMECheckExt,
7201 TopTools_DataMapOfShapeListOfShape& theEImages,
7202 TopTools_MapOfShape& theMEB,
7203 TopTools_MapOfShape& theMVOld,
7204 TopTools_MapOfShape& theMENew,
7205 TopTools_DataMapOfShapeListOfShape& theDMEOr,
7206 TopTools_DataMapOfShapeListOfShape& theMELF)
7207 {
7208 TopTools_ListIteratorOfListOfShape aIt, aIt1;
7209 aIt.Initialize (theLE);
7210 for (; aIt.More(); aIt.Next())
7211 {
7212 const TopoDS_Shape& aE = aIt.Value();
7213 //
7214 Standard_Boolean bCheckExt = theMECheckExt.Remove (aE);
7215 //
7216 Standard_Boolean bOld = theEETrim.IsBound (aE);
7217 if (bOld)
7218 {
7219 const TopTools_ListOfShape& aLET = theEETrim.Find (aE);
7220 aIt1.Initialize (aLET);
7221 for (; aIt1.More(); aIt1.Next())
7222 {
7223 const TopoDS_Shape& aET = aIt1.Value();
7224 theMEB.Add (aET);
7225 TopExp_Explorer aExpV (aET, TopAbs_VERTEX);
7226 for (; aExpV.More(); aExpV.Next())
7227 {
7228 const TopoDS_Shape& aV = aExpV.Current();
7229 theMVOld.Add (aV);
7230 }
7231 }
7232 }
7233 //
7234 if (!theEImages.IsBound (aE))
7235 {
7236 continue;
7237 }
7238 //
7239 TopTools_ListOfShape& aLEIm = theEImages.ChangeFind (aE);
7240 if (aLEIm.IsEmpty())
7241 {
7242 theEImages.UnBind (aE);
7243 continue;
7244 }
7245 //
7246 TopoDS_Shape aCEIm;
7247 TopTools_MapOfShape aMEVBounds;
7248 //
7249 if (aLEIm.Extent() > 1)
7250 {
7251 TopTools_IndexedMapOfShape aMV;
7252 // fuse these parts
7253 BOPAlgo_Builder aGFE;
7254 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
7255 for (; aItLEIm.More(); aItLEIm.Next())
7256 {
7257 const TopoDS_Shape& aEIm = aItLEIm.Value();
7258 aGFE.AddArgument (aEIm);
7259 TopExp::MapShapes (aEIm, TopAbs_VERTEX, aMV);
7260 }
7261 //
7262 // add two bounding vertices of this edge to the operation
7263 TopoDS_Vertex aV1, aV2;
7264 TopExp::Vertices (TopoDS::Edge (aE), aV1, aV2);
7265 //
7266 aGFE.AddArgument (aV1);
7267 aGFE.AddArgument (aV2);
7268 aMV.Add (aV1);
7269 aMV.Add (aV2);
7270 //
7271 aGFE.Perform();
7272 if (!aGFE.HasErrors())
7273 {
7274 // get images of bounding vertices to remove splits containing them
7275 // in case some of the bounding edges has been interfered
7276 // during operation it is necessary to update their images as well
7277 Standard_Integer iV, aNbV = aMV.Extent();
7278 for (iV = 1; iV <= aNbV; ++iV)
7279 {
7280 const TopoDS_Shape& aV = aMV (iV);
7281 if (theMVBounds.Contains (aV) || aV.IsSame (aV1) || aV.IsSame (aV2))
7282 {
7283 const TopTools_ListOfShape& aLVIm = aGFE.Modified (aV);
7284 aMEVBounds.Add (aLVIm.IsEmpty() ? aV : aLVIm.First());
7285 }
7286 }
7287 //
7288 aCEIm = aGFE.Shape();
7289 }
7290 }
7291 else
7292 {
7293 aCEIm = aLEIm.First();
7294 }
7295 //
7296 aLEIm.Clear();
7297 //
7298 TopExp_Explorer aExp (aCEIm, TopAbs_EDGE);
7299 for (; aExp.More(); aExp.Next())
7300 {
7301 const TopoDS_Shape& aEIm = aExp.Current();
7302 //
7303 // check the split not to contain bounding vertices
7304 TopoDS_Iterator aItV (aEIm);
7305 for (; aItV.More(); aItV.Next())
7306 {
7307 const TopoDS_Shape& aV = aItV.Value();
7308 if (aMEVBounds.Contains (aV) || theMVBounds.Contains (aV))
7309 {
7310 break;
7311 }
7312 }
7313 //
7314 if (!aItV.More())
7315 {
7316 aLEIm.Append (aEIm);
7317 //
7318 theDMEOr.Bound (aEIm, TopTools_ListOfShape())->Append (aE);
7319 }
7320 }
7321 //
7322 if (aLEIm.IsEmpty())
7323 {
7324 theEImages.UnBind (aE);
7325 }
7326 else
7327 {
7328 const TopTools_ListOfShape& aLFE = theMELF.Find (aE);
7329 TopTools_ListIteratorOfListOfShape aItLEIm (aLEIm);
7330 for (; aItLEIm.More(); aItLEIm.Next())
7331 {
7332 const TopoDS_Shape& aEIm = aItLEIm.Value();
7333 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek (aEIm);
7334 if (!pLFEIm)
7335 {
7336 pLFEIm = theMELF.Bound (aEIm, TopTools_ListOfShape());
7337 }
7338 TopTools_ListIteratorOfListOfShape aItLF (aLFE);
7339 for (; aItLF.More(); aItLF.Next())
7340 {
7341 AppendToList (*pLFEIm, aItLF.Value());
7342 }
7343 //
7344 if (bCheckExt)
7345 {
7346 theMECheckExt.Add (aEIm);
7347 }
7348 else if (!bOld)
7349 {
7350 theMENew.Add (aEIm);
7351 }
7352 }
7353 }
7354 }
7355 }
7356
7357 //=======================================================================
7358 //function : IntersectEdges
7359 //purpose : Intersecting the trimmed edges to avoid self-intersections
7360 //=======================================================================
IntersectEdges(const TopTools_ListOfShape & theLA,const TopTools_ListOfShape & theLE,const TopTools_MapOfShape & theMVBounds,const TopTools_MapOfShape & theVertsToAvoid,TopTools_MapOfShape & theMENew,TopTools_MapOfShape & theMECheckExt,TopTools_DataMapOfShapeListOfShape & theEImages,TopTools_DataMapOfShapeListOfShape & theDMEOr,TopTools_DataMapOfShapeListOfShape & theMELF,TopoDS_Shape & theSplits)7361 void BRepOffset_BuildOffsetFaces::IntersectEdges (const TopTools_ListOfShape& theLA,
7362 const TopTools_ListOfShape& theLE,
7363 const TopTools_MapOfShape& theMVBounds,
7364 const TopTools_MapOfShape& theVertsToAvoid,
7365 TopTools_MapOfShape& theMENew,
7366 TopTools_MapOfShape& theMECheckExt,
7367 TopTools_DataMapOfShapeListOfShape& theEImages,
7368 TopTools_DataMapOfShapeListOfShape& theDMEOr,
7369 TopTools_DataMapOfShapeListOfShape& theMELF,
7370 TopoDS_Shape& theSplits)
7371 {
7372 BOPAlgo_Builder aGFA;
7373 aGFA.SetArguments (theLA);
7374 aGFA.Perform();
7375 if (aGFA.HasErrors())
7376 {
7377 // just copy input to the result
7378 TopoDS_Compound aSp;
7379 BRep_Builder aBB;
7380 aBB.MakeCompound (aSp);
7381 TopTools_ListIteratorOfListOfShape anIt (theLA);
7382 for (; anIt.More(); anIt.Next())
7383 {
7384 const TopoDS_Shape& aE = anIt.Value();
7385 aBB.Add (aSp, aE);
7386 }
7387 theSplits = aSp;
7388 return;
7389 }
7390 //
7391 UpdateImages (theLE, theEImages, aGFA, myModifiedEdges);
7392 //
7393 // compound of valid splits
7394 theSplits = aGFA.Shape();
7395 //
7396 TopTools_ListIteratorOfListOfShape aIt, aIt1;
7397
7398 // prepare list of edges to update
7399 TopTools_ListOfShape aLEInput;
7400 for (aIt.Initialize (theLA); aIt.More(); aIt.Next())
7401 {
7402 TopExp_Explorer anExpE (aIt.Value(), TopAbs_EDGE);
7403 for (; anExpE.More(); anExpE.Next())
7404 aLEInput.Append (anExpE.Current());
7405 }
7406
7407 // update new edges
7408 aIt.Initialize (aLEInput);
7409 for (; aIt.More(); aIt.Next())
7410 {
7411 const TopoDS_Shape& aE = aIt.Value();
7412 if (!theMENew.Contains (aE))
7413 continue;
7414
7415 const TopTools_ListOfShape& aLEIm = aGFA.Modified (aE);
7416 if (aLEIm.IsEmpty())
7417 continue;
7418
7419 theMENew.Remove (aE);
7420 aIt1.Initialize (aLEIm);
7421 for (; aIt1.More(); aIt1.Next())
7422 theMENew.Add (aIt1.Value());
7423 }
7424 //
7425 // update edges after intersection for extended checking
7426 aIt.Initialize (aLEInput);
7427 for (; aIt.More(); aIt.Next())
7428 {
7429 const TopoDS_Shape& aE = aIt.Value();
7430 const TopTools_ListOfShape& aLEIm = aGFA.Modified (aE);
7431 if (aLEIm.IsEmpty())
7432 {
7433 continue;
7434 }
7435 //
7436 if (theMECheckExt.Contains (aE))
7437 {
7438 aIt1.Initialize (aLEIm);
7439 for (; aIt1.More(); aIt1.Next())
7440 {
7441 theMECheckExt.Add (aIt1.Value());
7442 }
7443 theMECheckExt.Remove (aE);
7444 }
7445 //
7446 const TopTools_ListOfShape& aLFE = theMELF.Find (aE);
7447 aIt1.Initialize (aLEIm);
7448 for (; aIt1.More(); aIt1.Next())
7449 {
7450 const TopoDS_Shape& aEIm = aIt1.Value();
7451 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek (aEIm);
7452 if (!pLFEIm)
7453 {
7454 pLFEIm = theMELF.Bound (aEIm, TopTools_ListOfShape());
7455 }
7456 TopTools_ListIteratorOfListOfShape aItLF (aLFE);
7457 for (; aItLF.More(); aItLF.Next())
7458 {
7459 AppendToList (*pLFEIm, aItLF.Value());
7460 }
7461 }
7462 }
7463 //
7464 TopTools_MapOfShape aMEInv;
7465 GetInvalidEdges (theVertsToAvoid, theMVBounds, aGFA, aMEInv);
7466 if (aMEInv.Extent())
7467 {
7468 // update shape
7469 TopoDS_Compound aSp;
7470 BRep_Builder aBB;
7471 aBB.MakeCompound (aSp);
7472 TopExp_Explorer aExp (theSplits, TopAbs_EDGE);
7473 for (; aExp.More(); aExp.Next())
7474 {
7475 const TopoDS_Shape& aE = aExp.Current();
7476 if (!aMEInv.Contains (aE))
7477 {
7478 aBB.Add (aSp, aE);
7479 }
7480 }
7481 theSplits = aSp;
7482 }
7483 //
7484 // update origins
7485 UpdateOrigins (aLEInput, theDMEOr, aGFA);
7486 }
7487
7488 //=======================================================================
7489 //function : GetBounds
7490 //purpose : Getting edges from the splits of offset faces
7491 //=======================================================================
GetBounds(const TopTools_ListOfShape & theLFaces,const TopTools_MapOfShape & theMEB,TopoDS_Shape & theBounds)7492 void BRepOffset_BuildOffsetFaces::GetBounds (const TopTools_ListOfShape& theLFaces,
7493 const TopTools_MapOfShape& theMEB,
7494 TopoDS_Shape& theBounds)
7495 {
7496 BRep_Builder aBB;
7497 // Make compound of edges contained in the splits of faces
7498 TopoDS_Compound aBounds;
7499 aBB.MakeCompound (aBounds);
7500 // Fence map
7501 TopTools_MapOfShape aMFence;
7502
7503 TopTools_ListIteratorOfListOfShape aItLF (theLFaces);
7504 for (; aItLF.More(); aItLF.Next())
7505 {
7506 const TopTools_ListOfShape* pLFIm = myOFImages.Seek (aItLF.Value());
7507 if (!pLFIm)
7508 continue;
7509 TopTools_ListIteratorOfListOfShape aIt (*pLFIm);
7510 for (; aIt.More(); aIt.Next())
7511 {
7512 const TopoDS_Shape& aFIm = aIt.Value();
7513 //
7514 TopExp_Explorer aExpE (aFIm, TopAbs_EDGE);
7515 for (; aExpE.More(); aExpE.Next())
7516 {
7517 const TopoDS_Shape& aEIm = aExpE.Current();
7518 if (!theMEB.Contains (aEIm) && aMFence.Add (aEIm))
7519 {
7520 aBB.Add (aBounds, aEIm);
7521 }
7522 }
7523 }
7524 }
7525 theBounds = aBounds;
7526 }
7527
7528 //=======================================================================
7529 //function : GetBoundsToUpdate
7530 //purpose : Get bounding edges that should be updated
7531 //=======================================================================
GetBoundsToUpdate(const TopTools_ListOfShape & theLF,const TopTools_MapOfShape & theMEB,TopTools_ListOfShape & theLABounds,TopTools_ListOfShape & theLAValid,TopoDS_Shape & theBounds)7532 void BRepOffset_BuildOffsetFaces::GetBoundsToUpdate (const TopTools_ListOfShape& theLF,
7533 const TopTools_MapOfShape& theMEB,
7534 TopTools_ListOfShape& theLABounds,
7535 TopTools_ListOfShape& theLAValid,
7536 TopoDS_Shape& theBounds)
7537 {
7538 // get all edges
7539 TopoDS_Compound aBounds;
7540 BRep_Builder aBB;
7541 aBB.MakeCompound (aBounds);
7542 //
7543 TopTools_MapOfShape aMAValid, aMFence;
7544 //
7545 TopTools_ListIteratorOfListOfShape aItLF (theLF);
7546 for (; aItLF.More(); aItLF.Next())
7547 {
7548 const TopoDS_Shape& aF = aItLF.Value();
7549 //
7550 TopTools_IndexedMapOfShape aMDE;
7551 const TopTools_ListOfShape& aLFDes = myAsDes->Descendant (aF);
7552 TopTools_ListIteratorOfListOfShape aItLFDes (aLFDes);
7553 for (; aItLFDes.More(); aItLFDes.Next())
7554 {
7555 const TopoDS_Shape& aED = aItLFDes.Value();
7556 const TopTools_ListOfShape* pLEDIm = myOEImages.Seek (aED);
7557 if (!pLEDIm)
7558 {
7559 aMDE.Add (aED);
7560 continue;
7561 }
7562 //
7563 TopTools_ListIteratorOfListOfShape aItLEDIm (*pLEDIm);
7564 for (; aItLEDIm.More(); aItLEDIm.Next())
7565 {
7566 const TopoDS_Shape& aEDIm = aItLEDIm.Value();
7567 aMDE.Add (aEDIm);
7568 }
7569 }
7570 //
7571 Standard_Integer j, aNbE = aMDE.Extent();
7572 for (j = 1; j <= aNbE; ++j)
7573 {
7574 const TopoDS_Edge& aEIm = TopoDS::Edge (aMDE (j));
7575 //
7576 if (!theMEB.Contains (aEIm) && aMFence.Add (aEIm))
7577 {
7578 aBB.Add (aBounds, aEIm);
7579 theLABounds.Append (aEIm);
7580 }
7581 //
7582 const TopTools_ListOfShape* pLO = myOEOrigins.Seek (aEIm);
7583 if (pLO)
7584 {
7585 TopTools_ListIteratorOfListOfShape aItLO (*pLO);
7586 for (; aItLO.More(); aItLO.Next())
7587 {
7588 const TopoDS_Shape& aEO = aItLO.Value();
7589 //
7590 if (aMAValid.Add (aEO))
7591 {
7592 theLAValid.Append (aEO);
7593 }
7594 }
7595 }
7596 else
7597 {
7598 if (aMAValid.Add (aEIm))
7599 {
7600 theLAValid.Append (aEIm);
7601 }
7602 }
7603 }
7604 }
7605 theBounds = aBounds;
7606 }
7607
7608 //=======================================================================
7609 //function : GetInvalidEdgesByBounds
7610 //purpose : Filter new splits by intersection with bounds
7611 //=======================================================================
GetInvalidEdgesByBounds(const TopoDS_Shape & theSplits,const TopoDS_Shape & theBounds,const TopTools_MapOfShape & theMVOld,const TopTools_MapOfShape & theMENew,const TopTools_DataMapOfShapeListOfShape & theDMEOr,const TopTools_DataMapOfShapeListOfShape & theMELF,const TopTools_DataMapOfShapeListOfShape & theEImages,const TopTools_MapOfShape & theMECheckExt,const TopTools_MapOfShape & theMEInvOnArt,TopTools_MapOfShape & theVertsToAvoid,TopTools_MapOfShape & theMEInv)7612 void BRepOffset_BuildOffsetFaces::GetInvalidEdgesByBounds (const TopoDS_Shape& theSplits,
7613 const TopoDS_Shape& theBounds,
7614 const TopTools_MapOfShape& theMVOld,
7615 const TopTools_MapOfShape& theMENew,
7616 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
7617 const TopTools_DataMapOfShapeListOfShape& theMELF,
7618 const TopTools_DataMapOfShapeListOfShape& theEImages,
7619 const TopTools_MapOfShape& theMECheckExt,
7620 const TopTools_MapOfShape& theMEInvOnArt,
7621 TopTools_MapOfShape& theVertsToAvoid,
7622 TopTools_MapOfShape& theMEInv)
7623 {
7624 // map splits to check the vertices of edges
7625 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
7626 TopExp::MapShapesAndAncestors (theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
7627 //
7628 BOPAlgo_Section aSec;
7629 aSec.AddArgument (theSplits);
7630 aSec.AddArgument (theBounds);
7631 //
7632 aSec.Perform();
7633 //
7634 // invalid vertices
7635 TopTools_IndexedMapOfShape aMVInv;
7636 // vertices to check additionally by classification relatively to solid
7637 TopTools_MapOfShape aMVCheckAdd;
7638 // collect parts for removal
7639 const BOPDS_PDS& pDS = aSec.PDS();
7640 //
7641 // check edge/edge intersections
7642 const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
7643 Standard_Integer i, aNb = aEEs.Length();
7644 for (i = 0; i < aNb; ++i)
7645 {
7646 const BOPDS_InterfEE& aEE = aEEs (i);
7647 //
7648 const TopoDS_Shape& aE1 = pDS->Shape (aEE.Index1());
7649 const TopoDS_Shape& aE2 = pDS->Shape (aEE.Index2());
7650 //
7651 if (!aEE.HasIndexNew())
7652 {
7653 if (theMECheckExt.Contains (aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE))
7654 {
7655 theMEInv.Add (aE1);
7656 }
7657 continue;
7658 }
7659 //
7660 if (myInvalidEdges.Contains (aE2))
7661 {
7662 theMEInv.Add (aE1);
7663 }
7664 //
7665 if (theMEInvOnArt.Contains (aE2))
7666 {
7667 // avoid checking of the vertices of the split edge intersected by
7668 // the invalid edge from artificial face
7669 TopoDS_Vertex aV1, aV2;
7670 TopExp::Vertices (TopoDS::Edge (aE2), aV1, aV2);
7671 if (aDMVE.Contains (aV1) && aDMVE.Contains (aV2))
7672 {
7673 continue;
7674 }
7675 }
7676 //
7677 // add vertices of all images of the edge from splits for checking
7678 const TopTools_ListOfShape& aLEOr = theDMEOr.Find (aE1);
7679 TopTools_ListIteratorOfListOfShape aItLEOr (aLEOr);
7680 for (; aItLEOr.More(); aItLEOr.Next())
7681 {
7682 const TopoDS_Shape& aEOr = aItLEOr.Value();
7683 //
7684 const TopTools_ListOfShape* pLEIm = theEImages.Seek (aEOr);
7685 if (!pLEIm)
7686 continue;
7687 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
7688 for (; aItLEIm.More(); aItLEIm.Next())
7689 {
7690 const TopoDS_Shape& aEIm = aItLEIm.Value();
7691 //
7692 TopoDS_Iterator aItV (aEIm);
7693 for (; aItV.More(); aItV.Next())
7694 {
7695 const TopoDS_Shape& aV = aItV.Value();
7696 if (!theMVOld.Contains (aV))
7697 {
7698 aMVInv.Add (aV);
7699 aMVCheckAdd.Add (aV);
7700 }
7701 }
7702 }
7703 }
7704 }
7705 //
7706 // to avoid unnecessary filling of parts due to extra trim of the edges
7707 // process Edge/Edge interferences of type EDGE, i.e. common blocks and check
7708 // not the bounding vertices of the edges, but check the edge itself
7709 // to be lying on some face
7710 //
7711 // all common blocks are contained in the result of SECTION operation
7712 // between sets of edges
7713 const TopoDS_Shape& aSecR = aSec.Shape();
7714 //
7715 TopTools_IndexedMapOfShape aMSSec;
7716 TopExp::MapShapes (aSecR, aMSSec);
7717 //
7718 const TopTools_DataMapOfShapeListOfShape& anIm = aSec.Images();
7719 for (TopExp_Explorer aExp (theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
7720 {
7721 const TopoDS_Shape& aE = aExp.Current();
7722 if (aSec.IsDeleted (aE))
7723 {
7724 // no common blocks for this edge
7725 continue;
7726 }
7727 //
7728 const TopTools_ListOfShape* pLEIm = anIm.Seek (aE);
7729 if (!pLEIm)
7730 {
7731 // no splits, i.e. completely coincides with some edge from boundary
7732 continue;
7733 }
7734 //
7735 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
7736 for (; aItLEIm.More(); aItLEIm.Next())
7737 {
7738 const TopoDS_Shape& aEIm = aItLEIm.Value();
7739 if (!aMSSec.Contains (aEIm))
7740 {
7741 // the edge included in section only partially.
7742 // the part not included in section may be excessive
7743 //
7744 // check vertices of this edge - if one of them is new
7745 // the edge might be removed
7746 TopoDS_Vertex aV1, aV2;
7747 TopExp::Vertices (TopoDS::Edge (aEIm), aV1, aV2);
7748 if (!theMVOld.Contains (aV1) || !theMVOld.Contains (aV2))
7749 {
7750 // add this edge for checking by making new vertex in the middle of the edge
7751 TopoDS_Vertex aV;
7752 Standard_Real f, l;
7753 const Handle(Geom_Curve)& aC = BRep_Tool::Curve (TopoDS::Edge (aEIm), f, l);
7754 BRep_Builder().MakeVertex (aV, aC->Value ((f + l) * 0.5), Precision::Confusion());
7755 // and adding this vertex for checking
7756 aDMVE.ChangeFromIndex (aDMVE.Add (aV, TopTools_ListOfShape())).Append (aE);
7757 aMVInv.Add (aV);
7758 break;
7759 }
7760 }
7761 }
7762 }
7763 //
7764 // Add for check also the edges created from common between splits
7765 // of offset faces edges not connected to any invalidity.
7766 // These edges may also accidentally fill some part.
7767 TopTools_MapIteratorOfMapOfShape aItM (theMECheckExt);
7768 for (; aItM.More(); aItM.Next())
7769 {
7770 const TopoDS_Shape& aE = aItM.Value();
7771 //
7772 // make new vertex in the middle of the edge
7773 TopoDS_Vertex aV;
7774 Standard_Real f, l;
7775 const Handle(Geom_Curve)& aC = BRep_Tool::Curve (TopoDS::Edge (aE), f, l);
7776 BRep_Builder().MakeVertex (aV, aC->Value ((f + l) * 0.5), Precision::Confusion());
7777 // add this vertex for checking
7778 aDMVE.ChangeFromIndex (aDMVE.Add (aV, TopTools_ListOfShape())).Append (aE);
7779 aMVInv.Add (aV);
7780 }
7781 //
7782 // add for check also the vertices connected only to new or old edges
7783 aNb = aDMVE.Extent();
7784 for (i = 1; i <= aNb; ++i)
7785 {
7786 const TopoDS_Shape& aV = aDMVE.FindKey (i);
7787 if (theMVOld.Contains (aV))
7788 {
7789 continue;
7790 }
7791 //
7792 Standard_Boolean bNew = Standard_False, bOld = Standard_False;
7793 const TopTools_ListOfShape& aLEx = aDMVE (i);
7794 TopTools_ListIteratorOfListOfShape aIt (aLEx);
7795 for (; aIt.More(); aIt.Next())
7796 {
7797 const TopoDS_Shape& aE = aIt.Value();
7798 if (theMECheckExt.Contains (aE))
7799 {
7800 continue;
7801 }
7802 //
7803 if (theMENew.Contains (aE))
7804 {
7805 bNew = Standard_True;
7806 }
7807 else
7808 {
7809 bOld = Standard_True;
7810 }
7811 //
7812 if (bNew && bOld)
7813 {
7814 break;
7815 }
7816 }
7817 //
7818 if (!bNew || !bOld)
7819 {
7820 aMVInv.Add (aV);
7821 aMVCheckAdd.Remove (aV);
7822 }
7823 }
7824 //
7825 // perform the checking of the vertices
7826 Standard_Integer iv, aNbIV = aMVInv.Extent();
7827 for (iv = 1; iv <= aNbIV; ++iv)
7828 {
7829 const TopoDS_Vertex& aV = TopoDS::Vertex (aMVInv (iv));
7830 if (theMVOld.Contains (aV))
7831 {
7832 continue;
7833 }
7834 //
7835 const TopTools_ListOfShape* pLEInv = aDMVE.Seek (aV);
7836 if (!pLEInv)
7837 {
7838 continue;
7839 }
7840 // find faces by the edges to check the vertex
7841 TopTools_IndexedMapOfShape aMF;
7842 TopTools_ListIteratorOfListOfShape aItLE (*pLEInv);
7843 for (; aItLE.More(); aItLE.Next())
7844 {
7845 const TopoDS_Shape& aE = aItLE.Value();
7846 const TopTools_ListOfShape& aLF = theMELF.Find (aE);
7847 TopTools_ListIteratorOfListOfShape aItLF (aLF);
7848 for (; aItLF.More(); aItLF.Next())
7849 {
7850 aMF.Add (aItLF.Value());
7851 }
7852 }
7853 //
7854 // check the vertex to belong to some split of the faces
7855 Standard_Boolean bInvalid = Standard_True;
7856 //
7857 Standard_Integer aNbF = aMF.Extent();
7858 for (i = 1; i <= aNbF && bInvalid; ++i)
7859 {
7860 const TopoDS_Face& aF = TopoDS::Face (aMF (i));
7861 const TopTools_ListOfShape& aLFIm = myOFImages.FindFromKey (aF);
7862 //
7863 TopTools_ListIteratorOfListOfShape aItLF (aLFIm);
7864 for (; aItLF.More() && bInvalid; aItLF.Next())
7865 {
7866 const TopoDS_Face& aFIm = TopoDS::Face (aItLF.Value());
7867 TopExp_Explorer aExp (aFIm, TopAbs_VERTEX);
7868 for (; aExp.More() && bInvalid; aExp.Next())
7869 {
7870 const TopoDS_Shape& aVF = aExp.Current();
7871 bInvalid = !aVF.IsSame (aV);
7872 }
7873 }
7874 //
7875 if (bInvalid)
7876 {
7877 Standard_Real U, V, aTol;
7878 Standard_Integer iStatus = myContext->ComputeVF (aV, aF, U, V, aTol);
7879 if (!iStatus)
7880 {
7881 // classify the point relatively faces
7882 gp_Pnt2d aP2d (U, V);
7883 aItLF.Initialize (aLFIm);
7884 for (; aItLF.More() && bInvalid; aItLF.Next())
7885 {
7886 const TopoDS_Face& aFIm = TopoDS::Face (aItLF.Value());
7887 bInvalid = !myContext->IsPointInOnFace (aFIm, aP2d);
7888 }
7889 }
7890 }
7891 }
7892 //
7893 if (bInvalid && aMVCheckAdd.Contains (aV))
7894 {
7895 // the vertex is invalid for all faces
7896 // check the same vertex for the solids
7897 const gp_Pnt& aP = BRep_Tool::Pnt (aV);
7898 Standard_Real aTolV = BRep_Tool::Tolerance (aV);
7899 //
7900 TopExp_Explorer aExpS (mySolids, TopAbs_SOLID);
7901 for (; aExpS.More() && bInvalid; aExpS.Next())
7902 {
7903 const TopoDS_Solid& aSol = TopoDS::Solid (aExpS.Current());
7904 BRepClass3d_SolidClassifier& aSC = myContext->SolidClassifier (aSol);
7905 aSC.Perform (aP, aTolV);
7906 bInvalid = (aSC.State() == TopAbs_OUT);
7907 }
7908 }
7909 //
7910 if (bInvalid)
7911 {
7912 theVertsToAvoid.Add (aV);
7913 aItLE.Initialize (*pLEInv);
7914 for (; aItLE.More(); aItLE.Next())
7915 {
7916 theMEInv.Add (aItLE.Value());
7917 }
7918 }
7919 }
7920 }
7921
7922 //=======================================================================
7923 //function : FilterSplits
7924 //purpose : Filter the images of edges from the invalid edges
7925 //=======================================================================
FilterSplits(const TopTools_ListOfShape & theLE,const TopTools_MapOfShape & theMEFilter,const Standard_Boolean theIsInv,TopTools_DataMapOfShapeListOfShape & theEImages,TopoDS_Shape & theSplits)7926 void BRepOffset_BuildOffsetFaces::FilterSplits (const TopTools_ListOfShape& theLE,
7927 const TopTools_MapOfShape& theMEFilter,
7928 const Standard_Boolean theIsInv,
7929 TopTools_DataMapOfShapeListOfShape& theEImages,
7930 TopoDS_Shape& theSplits)
7931 {
7932 TopoDS_Compound aSplits;
7933 BRep_Builder().MakeCompound (aSplits);
7934 TopTools_MapOfShape aMFence;
7935
7936 TopTools_ListIteratorOfListOfShape aItLE (theLE);
7937 for (; aItLE.More(); aItLE.Next())
7938 {
7939 const TopoDS_Shape& aE = aItLE.Value();
7940 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek (aE);
7941 if (!pLEIm)
7942 continue;
7943
7944 TopTools_ListIteratorOfListOfShape aItLEIm (*pLEIm);
7945 for (; aItLEIm.More();)
7946 {
7947 const TopoDS_Shape& aEIm = aItLEIm.Value();
7948 if (theMEFilter.Contains (aEIm) == theIsInv)
7949 {
7950 pLEIm->Remove (aItLEIm);
7951 continue;
7952 }
7953
7954 if (aMFence.Add (aEIm))
7955 BRep_Builder().Add (aSplits, aEIm);
7956 aItLEIm.Next();
7957 }
7958
7959 if (pLEIm->IsEmpty())
7960 theEImages.UnBind (aE);
7961 }
7962 theSplits = aSplits;
7963 }
7964
7965 //=======================================================================
7966 //function : UpdateNewIntersectionEdges
7967 //purpose : Updating the maps of images and origins of the offset edges
7968 //=======================================================================
UpdateNewIntersectionEdges(const TopTools_ListOfShape & theLE,const TopTools_DataMapOfShapeListOfShape & theMELF,const TopTools_DataMapOfShapeListOfShape & theEImages,TopTools_DataMapOfShapeListOfShape & theEETrim)7969 void BRepOffset_BuildOffsetFaces::UpdateNewIntersectionEdges (const TopTools_ListOfShape& theLE,
7970 const TopTools_DataMapOfShapeListOfShape& theMELF,
7971 const TopTools_DataMapOfShapeListOfShape& theEImages,
7972 TopTools_DataMapOfShapeListOfShape& theEETrim)
7973 {
7974 TopTools_ListOfShape aLEImEmpty;
7975 TopTools_ListIteratorOfListOfShape aIt, aIt1;
7976 // update global maps of images and origins with new splits
7977 aIt.Initialize (theLE);
7978 for (; aIt.More(); aIt.Next())
7979 {
7980 const TopoDS_Shape& aE = aIt.Value();
7981 //
7982 if (!theEImages.IsBound (aE))
7983 {
7984 TopTools_ListOfShape* pLET = theEETrim.ChangeSeek (aE);
7985 if (!pLET)
7986 {
7987 continue;
7988 }
7989 //
7990 TopTools_ListIteratorOfListOfShape aItLET (*pLET);
7991 for (; aItLET.More();)
7992 {
7993 const TopoDS_Shape& aET = aItLET.Value();
7994 if (!myInvalidEdges.Contains (aET) && !myInvertedEdges.Contains (aET))
7995 {
7996 pLET->Remove (aItLET);
7997 }
7998 else
7999 {
8000 aItLET.Next();
8001 }
8002 }
8003 //
8004 if (pLET->IsEmpty())
8005 {
8006 continue;
8007 }
8008 }
8009 // new images
8010 const TopTools_ListOfShape& aLENew =
8011 theEImages.IsBound (aE) ? theEImages.Find (aE) : aLEImEmpty;
8012 //
8013 // save connection to untrimmed edge for the next steps
8014 aIt1.Initialize (aLENew);
8015 for (; aIt1.More(); aIt1.Next())
8016 {
8017 const TopoDS_Shape& aET = aIt1.Value();
8018 myETrimEInf->Bind (aET, aE);
8019 myModifiedEdges.Add (aET);
8020 }
8021 //
8022 // check if it is existing edge
8023 if (!theEETrim.IsBound (aE))
8024 {
8025 const TopTools_ListOfShape& aLF = theMELF.Find (aE);
8026 // the edge is new
8027 // add this edge to AsDes
8028 aIt1.Initialize (aLF);
8029 for (; aIt1.More(); aIt1.Next())
8030 {
8031 const TopoDS_Shape& aF = aIt1.Value();
8032 myAsDes->Add (aF, aE);
8033 }
8034 //
8035 // add aE to the images
8036 myOEImages.Bind (aE, aLENew);
8037 myModifiedEdges.Add (aE);
8038 //
8039 // add to origins
8040 TopTools_ListIteratorOfListOfShape aItNew (aLENew);
8041 for (; aItNew.More(); aItNew.Next())
8042 {
8043 const TopoDS_Shape& aENew = aItNew.Value();
8044 if (myOEOrigins.IsBound (aENew))
8045 {
8046 TopTools_ListOfShape& aEOrigins = myOEOrigins.ChangeFind (aENew);
8047 AppendToList (aEOrigins, aE);
8048 }
8049 else
8050 {
8051 TopTools_ListOfShape aEOrigins;
8052 aEOrigins.Append (aE);
8053 myOEOrigins.Bind (aENew, aEOrigins);
8054 }
8055 }
8056 //
8057 // update connection to initial origins
8058 if (myEdgesOrigins->IsBound (aE))
8059 {
8060 const TopTools_ListOfShape& aLEOrInit = myEdgesOrigins->Find (aE);
8061 aIt1.Initialize (aLENew);
8062 for (; aIt1.More(); aIt1.Next())
8063 {
8064 const TopoDS_Shape& aENew = aIt1.Value();
8065 if (myEdgesOrigins->IsBound (aENew))
8066 {
8067 TopTools_ListOfShape& aLENewOr = myEdgesOrigins->ChangeFind (aENew);
8068 TopTools_ListIteratorOfListOfShape aItOrInit (aLEOrInit);
8069 for (; aItOrInit.More(); aItOrInit.Next())
8070 {
8071 const TopoDS_Shape& aEOr = aItOrInit.Value();
8072 AppendToList (aLENewOr, aEOr);
8073 }
8074 }
8075 else
8076 {
8077 myEdgesOrigins->Bind (aENew, aLEOrInit);
8078 }
8079 }
8080 }
8081 //
8082 continue;
8083 }
8084 //
8085 // old images
8086 const TopTools_ListOfShape& aLEOld = theEETrim.Find (aE);
8087 //
8088 // list of initial origins
8089 TopTools_ListOfShape anInitOrigins;
8090 //
8091 // it is necessary to replace the old edges with new ones
8092 aIt1.Initialize (aLEOld);
8093 for (; aIt1.More(); aIt1.Next())
8094 {
8095 const TopoDS_Shape& aEOld = aIt1.Value();
8096 //
8097 if (myOEOrigins.IsBound (aEOld))
8098 {
8099 // get its origins
8100 const TopTools_ListOfShape& aEOrigins = myOEOrigins.Find (aEOld);
8101 //
8102 TopTools_ListIteratorOfListOfShape aItOr (aEOrigins);
8103 for (; aItOr.More(); aItOr.Next())
8104 {
8105 const TopoDS_Shape& aEOr = aItOr.Value();
8106 //
8107 myModifiedEdges.Add (aEOr);
8108 //
8109 TopTools_ListOfShape& aEImages = myOEImages.ChangeFind (aEOr);
8110 //
8111 // remove old edge from images
8112 TopTools_ListIteratorOfListOfShape aItIm (aEImages);
8113 for (; aItIm.More(); )
8114 {
8115 const TopoDS_Shape& aEIm = aItIm.Value();
8116 if (aEIm.IsSame (aEOld))
8117 {
8118 aEImages.Remove (aItIm);
8119 }
8120 else
8121 {
8122 aItIm.Next();
8123 }
8124 }
8125 //
8126 // add new images
8127 TopTools_ListIteratorOfListOfShape aItNew (aLENew);
8128 for (; aItNew.More(); aItNew.Next())
8129 {
8130 const TopoDS_Shape& aENew = aItNew.Value();
8131 AppendToList (aEImages, aENew);
8132 if (myOEOrigins.IsBound (aENew))
8133 {
8134 TopTools_ListOfShape& aENewOrigins = myOEOrigins.ChangeFind (aENew);
8135 AppendToList (aENewOrigins, aEOr);
8136 }
8137 else
8138 {
8139 TopTools_ListOfShape aENewOrigins;
8140 aENewOrigins.Append (aEOr);
8141 myOEOrigins.Bind (aENew, aENewOrigins);
8142 }
8143 }
8144 }
8145 }
8146 else
8147 {
8148 // add to images
8149 myOEImages.Bind (aEOld, aLENew);
8150 //
8151 myModifiedEdges.Add (aEOld);
8152 //
8153 // add to origins
8154 TopTools_ListIteratorOfListOfShape aItNew (aLENew);
8155 for (; aItNew.More(); aItNew.Next())
8156 {
8157 const TopoDS_Shape& aENew = aItNew.Value();
8158 if (myOEOrigins.IsBound (aENew))
8159 {
8160 TopTools_ListOfShape& aEOrigins = myOEOrigins.ChangeFind (aENew);
8161 AppendToList (aEOrigins, aEOld);
8162 }
8163 else
8164 {
8165 TopTools_ListOfShape aEOrigins;
8166 aEOrigins.Append (aEOld);
8167 myOEOrigins.Bind (aENew, aEOrigins);
8168 }
8169 }
8170 }
8171 //
8172 // update connection to initial shape
8173 if (myEdgesOrigins->IsBound (aEOld))
8174 {
8175 const TopTools_ListOfShape& aLEOrInit = myEdgesOrigins->Find (aEOld);
8176 TopTools_ListIteratorOfListOfShape aItEOrInit (aLEOrInit);
8177 for (; aItEOrInit.More(); aItEOrInit.Next())
8178 {
8179 const TopoDS_Shape& aEOrInit = aItEOrInit.Value();
8180 AppendToList (anInitOrigins, aEOrInit);
8181 }
8182 }
8183 }
8184 //
8185 if (anInitOrigins.Extent())
8186 {
8187 TopTools_ListIteratorOfListOfShape aItNew (aLENew);
8188 for (; aItNew.More(); aItNew.Next())
8189 {
8190 const TopoDS_Shape& aENew = aItNew.Value();
8191 if (myEdgesOrigins->IsBound (aENew))
8192 {
8193 TopTools_ListOfShape& aLENewOr = myEdgesOrigins->ChangeFind (aENew);
8194 TopTools_ListIteratorOfListOfShape aItOrInit (anInitOrigins);
8195 for (; aItOrInit.More(); aItOrInit.Next())
8196 {
8197 const TopoDS_Shape& aEOr = aItOrInit.Value();
8198 AppendToList (aLENewOr, aEOr);
8199 }
8200 }
8201 else
8202 {
8203 myEdgesOrigins->Bind (aENew, anInitOrigins);
8204 }
8205 }
8206 }
8207 }
8208 }
8209
8210 //=======================================================================
8211 //function : FillGaps
8212 //purpose : Fill possible gaps (holes) in the splits of the offset faces
8213 //=======================================================================
FillGaps(const Message_ProgressRange & theRange)8214 void BRepOffset_BuildOffsetFaces::FillGaps (const Message_ProgressRange& theRange)
8215 {
8216 Standard_Integer aNbF = myOFImages.Extent();
8217 if (!aNbF)
8218 return;
8219
8220 Message_ProgressScope aPS (theRange, "Filling gaps", 2 * aNbF);
8221
8222 // Check the splits of offset faces on the free edges and fill the gaps (holes)
8223 // in created splits, otherwise the closed volume will not be possible to create.
8224
8225 // Map the splits of faces to find free edges
8226 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
8227 for (Standard_Integer i = 1; i <= aNbF; ++i, aPS.Next())
8228 {
8229 if (!aPS.More())
8230 {
8231 return;
8232 }
8233
8234 TopTools_ListIteratorOfListOfShape itLF (myOFImages (i));
8235 for (; itLF.More(); itLF.Next())
8236 TopExp::MapShapesAndAncestors (itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
8237 }
8238
8239 // Analyze images of each offset face on the presence of free edges
8240 // and try to fill the holes
8241 for (Standard_Integer i = 1; i <= aNbF; ++i, aPS.Next())
8242 {
8243 if (!aPS.More())
8244 {
8245 return;
8246 }
8247
8248 TopTools_ListOfShape& aLFImages = myOFImages (i);
8249 if (aLFImages.IsEmpty())
8250 continue;
8251
8252 // Collect all edges from the splits
8253 TopoDS_Compound anEdges;
8254 BRep_Builder().MakeCompound (anEdges);
8255
8256 // Collect all free edges into a map with reverted orientation
8257 TopTools_MapOfOrientedShape aFreeEdgesMap;
8258 TopTools_ListIteratorOfListOfShape itLF (aLFImages);
8259 for (; itLF.More(); itLF.Next())
8260 {
8261 const TopoDS_Shape& aFIm = itLF.Value();
8262 TopExp_Explorer anExpE (aFIm, TopAbs_EDGE);
8263 for (; anExpE.More(); anExpE.Next())
8264 {
8265 const TopoDS_Shape& aE = anExpE.Current();
8266 if (aE.Orientation() != TopAbs_FORWARD &&
8267 aE.Orientation() != TopAbs_REVERSED)
8268 // Skip internals
8269 continue;
8270
8271 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
8272 if (aLF.Extent() == 1)
8273 aFreeEdgesMap.Add (aE.Reversed());
8274
8275 BRep_Builder().Add (anEdges, aE);
8276 }
8277 }
8278
8279 if (aFreeEdgesMap.IsEmpty())
8280 // No free edges
8281 continue;
8282
8283 // Free edges are found - fill the gaps by creating new splits
8284 // of the face using these free edges
8285 const TopoDS_Shape& aF = myOFImages.FindKey (i);
8286
8287 // Build new splits using all kept edges and among new splits
8288 // find those containing free edges
8289 TopTools_ListOfShape aLFNew;
8290 TopTools_DataMapOfShapeShape aDummy;
8291
8292 BuildSplitsOfFace (TopoDS::Face (aF), anEdges, aDummy, aLFNew);
8293
8294 // Find faces filling holes
8295 itLF.Initialize (aLFNew);
8296 for (; itLF.More(); itLF.Next())
8297 {
8298 const TopoDS_Shape& aFNew = itLF.Value();
8299 TopExp_Explorer anExpE (aFNew, TopAbs_EDGE);
8300 for (; anExpE.More(); anExpE.Next())
8301 {
8302 const TopoDS_Shape& aE = anExpE.Current();
8303 if (aFreeEdgesMap.Contains (aE))
8304 {
8305 // Add face to splits
8306 aLFImages.Append (aFNew);
8307 break;
8308 }
8309 }
8310 }
8311 }
8312 }
8313
8314 //=======================================================================
8315 //function : FillHistory
8316 //purpose : Saving obtained results in history tools
8317 //=======================================================================
FillHistory()8318 void BRepOffset_BuildOffsetFaces::FillHistory()
8319 {
8320 Standard_Integer aNbF = myOFImages.Extent();
8321 if (!aNbF)
8322 {
8323 return;
8324 }
8325
8326 #ifdef OFFSET_DEBUG
8327 // Build compound of faces to see preliminary result
8328 TopoDS_Compound aDFaces;
8329 BRep_Builder().MakeCompound (aDFaces);
8330 #endif
8331
8332 // Map of kept edges
8333 TopTools_IndexedMapOfShape anEdgesMap;
8334
8335 // Fill history for faces
8336 for (Standard_Integer i = 1; i <= aNbF; ++i)
8337 {
8338 const TopTools_ListOfShape& aLFImages = myOFImages (i);
8339 if (aLFImages.IsEmpty())
8340 {
8341 continue;
8342 }
8343
8344 // Add the splits to history map
8345 const TopoDS_Shape& aF = myOFImages.FindKey (i);
8346 if (myImage->HasImage (aF))
8347 myImage->Add (aF, aLFImages);
8348 else
8349 myImage->Bind (aF, aLFImages);
8350
8351 // Collect edges from splits
8352 TopTools_ListIteratorOfListOfShape itLF (aLFImages);
8353 for (; itLF.More(); itLF.Next())
8354 {
8355 const TopoDS_Shape& aFIm = itLF.Value();
8356 TopExp::MapShapes (aFIm, TopAbs_EDGE, anEdgesMap);
8357
8358 #ifdef OFFSET_DEBUG
8359 BRep_Builder().Add (aDFaces, aFIm);
8360 #endif
8361 }
8362 }
8363
8364 // Fill history for edges (iteration by the map is safe because the
8365 // order is not important here)
8366 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm (myOEImages);
8367 for (; aItEIm.More(); aItEIm.Next())
8368 {
8369 const TopoDS_Shape& aE = aItEIm.Key();
8370 const TopTools_ListOfShape& aLEIm = aItEIm.Value();
8371
8372 Standard_Boolean bHasImage = myImage->HasImage (aE);
8373 TopTools_ListIteratorOfListOfShape aItLE (aLEIm);
8374 for (; aItLE.More(); aItLE.Next())
8375 {
8376 const TopoDS_Shape& aEIm = aItLE.Value();
8377 if (anEdgesMap.Contains (aEIm))
8378 {
8379 if (bHasImage)
8380 {
8381 myImage->Add (aE, aEIm);
8382 }
8383 else
8384 {
8385 myImage->Bind (aE, aEIm);
8386 bHasImage = Standard_True;
8387 }
8388 }
8389 }
8390 }
8391 }
8392
8393
8394 //=======================================================================
8395 //function : BuildSplitsOfTrimmedFaces
8396 //purpose : Building splits of already trimmed faces
8397 //=======================================================================
BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape & theLF,const Handle (BRepAlgo_AsDes)& theAsDes,BRepAlgo_Image & theImage,const Message_ProgressRange & theRange)8398 void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces (const TopTools_ListOfShape& theLF,
8399 const Handle(BRepAlgo_AsDes)& theAsDes,
8400 BRepAlgo_Image& theImage,
8401 const Message_ProgressRange& theRange)
8402 {
8403 BRepOffset_BuildOffsetFaces aBFTool (theImage);
8404 aBFTool.SetFaces (theLF);
8405 aBFTool.SetAsDesInfo (theAsDes);
8406 aBFTool.BuildSplitsOfTrimmedFaces (theRange);
8407 }
8408
8409 //=======================================================================
8410 //function : BuildSplitsOfExtendedFaces
8411 //purpose : Building splits of not-trimmed offset faces.
8412 // For the cases in which invalidity will be found,
8413 // these invalidities will be rebuilt.
8414 //=======================================================================
BuildSplitsOfExtendedFaces(const TopTools_ListOfShape & theLF,const BRepOffset_Analyse & theAnalyse,const Handle (BRepAlgo_AsDes)& theAsDes,TopTools_DataMapOfShapeListOfShape & theEdgesOrigins,TopTools_DataMapOfShapeShape & theFacesOrigins,TopTools_DataMapOfShapeShape & theETrimEInf,BRepAlgo_Image & theImage,const Message_ProgressRange & theRange)8415 void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces (const TopTools_ListOfShape& theLF,
8416 const BRepOffset_Analyse& theAnalyse,
8417 const Handle(BRepAlgo_AsDes)& theAsDes,
8418 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
8419 TopTools_DataMapOfShapeShape& theFacesOrigins,
8420 TopTools_DataMapOfShapeShape& theETrimEInf,
8421 BRepAlgo_Image& theImage,
8422 const Message_ProgressRange& theRange)
8423 {
8424 BRepOffset_BuildOffsetFaces aBFTool (theImage);
8425 aBFTool.SetFaces (theLF);
8426 aBFTool.SetAsDesInfo (theAsDes);
8427 aBFTool.SetAnalysis (theAnalyse);
8428 aBFTool.SetEdgesOrigins (theEdgesOrigins);
8429 aBFTool.SetFacesOrigins (theFacesOrigins);
8430 aBFTool.SetInfEdges (theETrimEInf);
8431 aBFTool.BuildSplitsOfExtendedFaces (theRange);
8432 }
8433