53a73fc1 |
1 | // Created on: 2018-03-16 |
2 | // Created by: Eugeny MALTCHIKOV |
3 | // Copyright (c) 2018 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 | #include <BOPAlgo_MakePeriodic.hxx> |
17 | |
18 | #include <BOPAlgo_Alerts.hxx> |
19 | |
20 | #include <Bnd_Box.hxx> |
21 | |
22 | #include <BOPAlgo_Builder.hxx> |
23 | #include <BOPAlgo_PaveFiller.hxx> |
24 | |
25 | #include <BRepAlgoAPI_Common.hxx> |
26 | #include <BRepAlgoAPI_Splitter.hxx> |
27 | |
28 | #include <BRepBndLib.hxx> |
29 | |
30 | #include <BRepBuilderAPI_Transform.hxx> |
31 | |
32 | #include <BRepPrimAPI_MakeBox.hxx> |
33 | |
34 | #include <gp_Pln.hxx> |
35 | |
36 | #include <Precision.hxx> |
37 | |
38 | #include <TopoDS.hxx> |
39 | #include <TopoDS_Compound.hxx> |
40 | |
41 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
42 | |
43 | // Periodic/Trim/Repeat directions |
44 | static const gp_Dir MY_DIRECTIONS[3] = { gp::DX(), |
45 | gp::DY(), |
46 | gp::DZ() }; |
47 | |
48 | //======================================================================= |
49 | //function : Perform |
50 | //purpose : Performs the operation |
51 | //======================================================================= |
52 | void BOPAlgo_MakePeriodic::Perform() |
53 | { |
54 | // Check the validity of input data |
55 | CheckData(); |
56 | if (HasErrors()) |
57 | return; |
58 | |
59 | // Trim the shape to fit to the required period in |
60 | // required periodic directions |
61 | Trim(); |
62 | if (HasErrors()) |
63 | return; |
64 | |
65 | // Make the shape identical on the opposite sides in |
66 | // required periodic directions |
67 | MakeIdentical(); |
68 | if (HasErrors()) |
69 | return; |
70 | } |
71 | |
72 | //======================================================================= |
73 | //function : CheckData |
74 | //purpose : Checks the validity of input data |
75 | //======================================================================= |
76 | void BOPAlgo_MakePeriodic::CheckData() |
77 | { |
78 | if ( (!IsXPeriodic() || XPeriod() < Precision::Confusion()) |
79 | && (!IsYPeriodic() || YPeriod() < Precision::Confusion()) |
80 | && (!IsZPeriodic() || ZPeriod() < Precision::Confusion())) |
81 | { |
82 | // Add error informing the user that no periodicity is required |
83 | // or no valid period is set. |
84 | |
85 | AddError(new BOPAlgo_AlertNoPeriodicityRequired()); |
86 | return; |
87 | } |
88 | } |
89 | |
90 | //======================================================================= |
91 | //function : AddToShape |
92 | //purpose : Adds the shape <theWhat> to the shape <theWhere> |
93 | //======================================================================= |
94 | static void AddToShape(const TopoDS_Shape& theWhat, |
95 | TopoDS_Shape& theWhere) |
96 | { |
97 | if (theWhere.IsNull()) |
98 | BRep_Builder().MakeCompound(TopoDS::Compound(theWhere)); |
99 | BRep_Builder().Add(theWhere, theWhat); |
100 | } |
101 | //======================================================================= |
102 | //function : AddToShape |
103 | //purpose : Adds the shape in the list <theLWhat> to the shape <theWhere> |
104 | //======================================================================= |
105 | static void AddToShape(const TopTools_ListOfShape& theLWhat, |
106 | TopoDS_Shape& theWhere) |
107 | { |
108 | TopTools_ListIteratorOfListOfShape it(theLWhat); |
109 | for (; it.More(); it.Next()) |
110 | AddToShape(it.Value(), theWhere); |
111 | } |
112 | |
113 | //======================================================================= |
114 | //function : Trim |
115 | //purpose : Make the trim of the shape to fit to the periodic bounds. |
116 | //======================================================================= |
117 | void BOPAlgo_MakePeriodic::Trim() |
118 | { |
119 | // Check if trim is required at all |
120 | if (IsInputXTrimmed() && |
121 | IsInputYTrimmed() && |
122 | IsInputZTrimmed()) |
123 | return; |
124 | |
125 | // Compute bounding box for the shape to use it as a starting |
126 | // volume for trimming. If required, the volume will be modified |
127 | // to the requested trimming size in requested directions. |
128 | Bnd_Box aBox; |
129 | BRepBndLib::Add(myInputShape, aBox); |
130 | // Enlarge box to avoid overlapping with the shape |
131 | aBox.Enlarge(0.1 * sqrt(aBox.SquareExtent())); |
132 | |
133 | // Get Corner points of the bounding box |
134 | gp_Pnt aPMin = aBox.CornerMin(); |
135 | gp_Pnt aPMax = aBox.CornerMax(); |
136 | |
137 | // Update corner points according to the requested trim parameters |
138 | for (Standard_Integer i = 0; i < 3; ++i) |
139 | { |
140 | if (IsInputTrimmed(i)) |
141 | continue; |
142 | |
143 | aPMin.SetCoord(i + 1, PeriodFirst(i)); |
144 | aPMax.SetCoord(i + 1, PeriodFirst(i) + Period(i)); |
145 | } |
146 | |
147 | // Build Trimming solid using corner points |
148 | BRepPrimAPI_MakeBox aMBox(aPMin, aPMax); |
149 | const TopoDS_Shape& aTrimBox = aMBox.Solid(); |
150 | |
151 | // Perform trimming of the shape by solid |
152 | BRepAlgoAPI_Common aCommon; |
153 | // Set Object |
154 | TopTools_ListOfShape anObj; |
155 | anObj.Append(myInputShape); |
156 | aCommon.SetArguments(anObj); |
157 | // Set Tool |
158 | TopTools_ListOfShape aTool; |
159 | aTool.Append(aTrimBox); |
160 | aCommon.SetTools(aTool); |
161 | // Set the parallel processing mode |
162 | aCommon.SetRunParallel(myRunParallel); |
163 | // Build |
164 | aCommon.Build(); |
165 | if (aCommon.HasErrors()) |
166 | { |
167 | // Unable to trim the shape |
168 | // Merge errors from Common operation |
169 | myReport->Merge(aCommon.GetReport()); |
170 | // Add new error saving the shapes for analysis |
171 | TopoDS_Compound aWS; |
172 | AddToShape(myInputShape, aWS); |
173 | AddToShape(aTrimBox, aWS); |
174 | AddError(new BOPAlgo_AlertUnableToTrim(aWS)); |
175 | return; |
176 | } |
177 | // Get the trimmed shape |
178 | myShape = aCommon.Shape(); |
179 | // Fill the History for the object only |
180 | mySplitHistory = new BRepTools_History(); |
181 | mySplitHistory->Merge(anObj, aCommon); |
182 | } |
183 | |
184 | //======================================================================= |
185 | //function : MakeIdentical |
186 | //purpose : Make the shape look the same on the opposite sides in the |
187 | // required periodic directions. |
188 | //======================================================================= |
189 | void BOPAlgo_MakePeriodic::MakeIdentical() |
190 | { |
191 | if (myShape.IsNull()) |
192 | myShape = myInputShape; |
193 | |
194 | if (mySplitHistory.IsNull()) |
195 | mySplitHistory = new BRepTools_History; |
196 | |
197 | // Split the negative side of the shape with the geometry |
198 | // located on the positive side |
199 | SplitNegative(); |
200 | if (HasErrors()) |
201 | return; |
202 | |
203 | // Split the positive side of the shape with the geometry |
204 | // located on the negative side. |
205 | // Make sure that the opposite sides have identical geometries. |
206 | // Make associations between identical opposite shapes. |
207 | SplitPositive(); |
208 | |
209 | myHistory = new BRepTools_History(); |
210 | myHistory->Merge(mySplitHistory); |
211 | } |
212 | |
213 | //======================================================================= |
214 | //function : SplitNegative |
215 | //purpose : Split the negative side of the shape with the geometry |
216 | // located on the positive side. |
217 | //======================================================================= |
218 | void BOPAlgo_MakePeriodic::SplitNegative() |
219 | { |
220 | // Copy geometry from positive side of the shape to the negative first. |
221 | // So, translate the shape in negative periodic directions only. |
222 | // |
223 | // To avoid conflicts when copying geometries from positive periodic sides |
224 | // perform split of each periodic side in a separate operation. |
225 | for (Standard_Integer i = 0; i < 3; ++i) |
226 | { |
227 | if (!IsPeriodic(i)) |
228 | continue; |
229 | |
230 | // Translate the shape to the negative side |
231 | gp_Trsf aNegTrsf; |
232 | aNegTrsf.SetTranslationPart(Period(i) * MY_DIRECTIONS[i].Reversed()); |
233 | BRepBuilderAPI_Transform aNegT(myShape, aNegTrsf, Standard_False); |
234 | |
235 | // Split the negative side of the shape. |
236 | TopTools_ListOfShape aTools; |
237 | aTools.Append(aNegT.Shape()); |
238 | SplitShape(aTools, mySplitHistory); |
239 | } |
240 | } |
241 | |
242 | //======================================================================= |
243 | //function : AddTwin |
244 | //purpose : Associates the shape <theS> with the shape <theTwin> in the map. |
245 | //======================================================================= |
246 | static void AddTwin(const TopoDS_Shape& theS, |
247 | const TopoDS_Shape& theTwin, |
248 | TopTools_DataMapOfShapeListOfShape& theMap) |
249 | { |
250 | TopTools_ListOfShape *aTwins = theMap.ChangeSeek(theS); |
251 | if (!aTwins) |
252 | { |
253 | theMap.Bound(theS, TopTools_ListOfShape())->Append(theTwin); |
254 | return; |
255 | } |
256 | |
257 | // Check if the twin shape is not yet present in the list |
258 | TopTools_ListIteratorOfListOfShape itLT(*aTwins); |
259 | for (; itLT.More(); itLT.Next()) |
260 | { |
261 | if (theTwin.IsSame(itLT.Value())) |
262 | break; |
263 | } |
264 | |
265 | if (!itLT.More()) |
266 | aTwins->Append(theTwin); |
267 | } |
268 | |
269 | //======================================================================= |
270 | //function : SplitPositive |
271 | //purpose : Split the positive side of the shape with the geometry of the |
272 | // negative side. Associate the identical opposite sub-shapes. |
273 | //======================================================================= |
274 | void BOPAlgo_MakePeriodic::SplitPositive() |
275 | { |
276 | // Prepare map of the sub-shapes of the input shape to make |
277 | // associations of the opposite shapes |
278 | TopTools_IndexedMapOfShape aSubShapesMap; |
279 | TopExp::MapShapes(myShape, aSubShapesMap); |
280 | const Standard_Integer aNbS = aSubShapesMap.Extent(); |
281 | |
282 | // Translate the shape to the positive periodic directions to make the |
283 | // shapes look identical on the opposite sides. |
284 | TopTools_ListOfShape aTools; |
285 | |
286 | // Remember the history of shapes translation |
287 | TopTools_IndexedDataMapOfShapeListOfShape aTranslationHistMap; |
288 | |
289 | // Make translations for all periodic directions |
290 | for (Standard_Integer i = 0; i < 3; ++i) |
291 | { |
292 | if (!IsPeriodic(i)) |
293 | continue; |
294 | |
295 | // Translate the shape to the positive side |
296 | gp_Trsf aPosTrsf; |
297 | aPosTrsf.SetTranslationPart(Period(i) * MY_DIRECTIONS[i]); |
298 | BRepBuilderAPI_Transform aTranslator(myShape, aPosTrsf, Standard_False); |
299 | aTools.Append(aTranslator.Shape()); |
300 | |
301 | // Fill the translation history map |
302 | for (Standard_Integer j = 1; j <= aNbS; ++j) |
303 | { |
304 | const TopoDS_Shape& aS = aSubShapesMap(j); |
305 | if (BRepTools_History::IsSupportedType(aS)) |
306 | { |
307 | const TopTools_ListOfShape& aSM = aTranslator.Modified(aS); |
308 | TopTools_ListOfShape* pTS = aTranslationHistMap.ChangeSeek(aS); |
309 | if (!pTS) |
310 | pTS = &aTranslationHistMap(aTranslationHistMap.Add(aS, TopTools_ListOfShape())); |
311 | pTS->Append(aSM.First()); |
312 | } |
313 | } |
314 | } |
315 | |
316 | // Keep the split shape history and history of tools modifications |
317 | // during the split for making association of the opposite identical shapes |
318 | Handle(BRepTools_History) aSplitShapeHist = new BRepTools_History, |
319 | aSplitToolsHist = new BRepTools_History; |
320 | // Split the positive side of the shape |
321 | SplitShape(aTools, aSplitShapeHist, aSplitToolsHist); |
322 | if (HasErrors()) |
323 | return; |
324 | |
325 | mySplitHistory->Merge(aSplitShapeHist); |
326 | |
327 | // Make associations between identical opposite sub-shapes |
328 | const Standard_Integer aNbSH = aTranslationHistMap.Extent(); |
329 | for (Standard_Integer i = 1; i <= aNbSH; ++i) |
330 | { |
331 | const TopoDS_Shape* pS = &aTranslationHistMap.FindKey(i); |
332 | const TopTools_ListOfShape& aSIm = aSplitShapeHist->Modified(*pS); |
333 | if (aSIm.Extent() == 1) |
334 | pS = &aSIm.First(); |
335 | else if (aSIm.Extent() > 1) |
336 | continue; |
337 | |
338 | const TopTools_ListOfShape& aLTranslated = aTranslationHistMap(i); |
339 | |
340 | TopTools_ListIteratorOfListOfShape itLT(aLTranslated); |
341 | for (; itLT.More(); itLT.Next()) |
342 | { |
343 | const TopoDS_Shape& aT = itLT.Value(); |
344 | // Get shapes modifications during the split |
345 | const TopTools_ListOfShape& aTSplits = aSplitToolsHist->Modified(aT); |
346 | |
347 | // Associate the shapes to each other |
348 | TopTools_ListIteratorOfListOfShape itSp(aTSplits); |
349 | for (; itSp.More(); itSp.Next()) |
350 | { |
351 | const TopoDS_Shape& aSp = itSp.Value(); |
352 | AddTwin(*pS, aSp, myTwins); |
353 | AddTwin(aSp, *pS, myTwins); |
354 | } |
355 | } |
356 | } |
357 | } |
358 | |
359 | //======================================================================= |
360 | //function : SplitShape |
361 | //purpose : Splits the shape by the given tools |
362 | //======================================================================= |
363 | void BOPAlgo_MakePeriodic::SplitShape(const TopTools_ListOfShape& theTools, |
364 | Handle(BRepTools_History) theSplitShapeHistory, |
365 | Handle(BRepTools_History) theSplitToolsHistory) |
366 | { |
367 | // Make sure that the geometry from the tools will be copied to the split |
368 | // shape. For that, the tool shapes should be given to the Boolean Operations |
369 | // algorithm before the shape itself. This will make all coinciding parts |
370 | // use the geometry of the first argument. |
371 | |
372 | // Intersection tool for passing ordered arguments |
373 | BOPAlgo_PaveFiller anIntersector; |
374 | anIntersector.SetArguments(theTools); |
375 | // Add the shape |
376 | anIntersector.AddArgument(myShape); |
377 | // Use gluing to speed-up intersections |
378 | anIntersector.SetGlue(BOPAlgo_GlueShift); |
379 | // Use safe input mode, to avoid reusing geometry of the shape |
380 | anIntersector.SetNonDestructive(Standard_True); |
381 | // Set parallel processing mode |
382 | anIntersector.SetRunParallel(myRunParallel); |
383 | // Perform Intersection of the arguments |
384 | anIntersector.Perform(); |
385 | // Check for the errors |
386 | if (anIntersector.HasErrors()) |
387 | { |
388 | // Unable to split the shape on opposite sides |
389 | // Copy the intersection errors |
390 | myReport->Merge(anIntersector.GetReport()); |
391 | // Add new error saving the shapes for analysis |
392 | TopoDS_Compound aWS; |
393 | AddToShape(theTools, aWS); |
394 | AddToShape(myShape, aWS); |
395 | AddError(new BOPAlgo_AlertUnableToMakeIdentical(aWS)); |
396 | return; |
397 | } |
398 | |
399 | // Perform the splitting of the shape with the precomputed intersection results |
400 | BRepAlgoAPI_Splitter aSplitter(anIntersector); |
401 | // Set Object |
402 | TopTools_ListOfShape anObj; |
403 | anObj.Append(myShape); |
404 | aSplitter.SetArguments(anObj); |
405 | // Set Tools |
406 | aSplitter.SetTools(theTools); |
407 | // Use Gluing |
408 | aSplitter.SetGlue(BOPAlgo_GlueShift); |
409 | // Set parallel processing mode |
410 | aSplitter.SetRunParallel(myRunParallel); |
411 | // Perform splitting |
412 | aSplitter.Build(); |
413 | // Check for the errors |
414 | if (aSplitter.HasErrors()) |
415 | { |
416 | // Unable to split the shape on opposite sides |
417 | // Copy the splitter errors |
418 | myReport->Merge(aSplitter.GetReport()); |
419 | // Add new error saving the shape for analysis |
420 | TopoDS_Compound aWS; |
421 | AddToShape(theTools, aWS); |
422 | AddToShape(myShape, aWS); |
423 | AddError(new BOPAlgo_AlertUnableToMakeIdentical(aWS)); |
424 | return; |
425 | } |
426 | // Get the split shape |
427 | myShape = aSplitter.Shape(); |
428 | // Remember the split history |
429 | if (!theSplitShapeHistory.IsNull()) |
430 | theSplitShapeHistory->Merge(anObj, aSplitter); |
431 | if (!theSplitToolsHistory.IsNull()) |
432 | theSplitToolsHistory->Merge(theTools, aSplitter); |
433 | } |
434 | |
435 | //======================================================================= |
436 | //function : RepeatShape |
437 | //purpose : Repeats the shape in the required periodic direction |
438 | //======================================================================= |
439 | const TopoDS_Shape& BOPAlgo_MakePeriodic::RepeatShape(const Standard_Integer theDir, |
440 | const Standard_Integer theTimes) |
441 | { |
442 | if (myRepeatedShape.IsNull()) |
443 | myRepeatedShape = myShape; |
444 | |
445 | if (!IsPeriodic(theDir)) |
446 | return myRepeatedShape; |
447 | |
448 | if (theTimes == 0) |
449 | return myRepeatedShape; |
450 | |
451 | // Get the shape's period in the required direction |
452 | const Standard_Integer id = BOPAlgo_MakePeriodic::ToDirectionID(theDir); |
453 | if (myRepeatPeriod[id] < Precision::Confusion()) |
454 | myRepeatPeriod[id] = Period(id); |
455 | const Standard_Real aPeriod = myRepeatPeriod[id]; |
456 | |
457 | // Coefficient to define in which direction the repetition will be performed: |
458 | // theTimes is positive - in positive direction; |
459 | // theTimes is negative - in negative direction. |
460 | const Standard_Integer iDir = theTimes > 0 ? 1 : -1; |
461 | |
462 | // Create the translation history - all translated shapes will be |
463 | // created as Generated from the shape. |
464 | BRepTools_History aTranslationHistory; |
465 | TopTools_IndexedMapOfShape aSubShapesMap; |
466 | TopExp::MapShapes(myRepeatedShape, aSubShapesMap); |
467 | const Standard_Integer aNbS = aSubShapesMap.Extent(); |
468 | |
469 | // Add shapes for gluing |
470 | TopTools_ListOfShape aShapes; |
471 | // Add the shape itself |
472 | aShapes.Append(myRepeatedShape); |
473 | for (Standard_Integer i = 1; i <= aNbS; ++i) |
474 | { |
475 | const TopoDS_Shape& aS = aSubShapesMap(i); |
476 | if (BRepTools_History::IsSupportedType(aS)) |
477 | aTranslationHistory.AddGenerated(aS, aS); |
478 | } |
479 | |
480 | // Create translated copies of the shape |
481 | for (Standard_Integer i = 1; i <= Abs(theTimes); ++i) |
482 | { |
483 | gp_Trsf aTrsf; |
484 | aTrsf.SetTranslationPart(iDir * i * aPeriod * MY_DIRECTIONS[id]); |
485 | BRepBuilderAPI_Transform aTranslator(myRepeatedShape, aTrsf, Standard_False); |
486 | aShapes.Append(aTranslator.Shape()); |
487 | |
488 | // Fill the translation history |
489 | for (Standard_Integer j = 1; j <= aNbS; ++j) |
490 | { |
491 | const TopoDS_Shape& aS = aSubShapesMap(j); |
492 | if (BRepTools_History::IsSupportedType(aS)) |
493 | { |
494 | const TopTools_ListOfShape& aLT = aTranslator.Modified(aS); |
495 | aTranslationHistory.AddGenerated(aS, aLT.First()); |
496 | } |
497 | } |
498 | } |
499 | |
500 | // Update the history with the translation History |
501 | myHistory->Merge(aTranslationHistory); |
502 | |
503 | // Glue the translated shapes all together |
504 | BOPAlgo_Builder aGluer; |
505 | aGluer.SetArguments(aShapes); |
506 | // Avoid intersections of the sub-shapes |
507 | aGluer.SetGlue(BOPAlgo_GlueFull); |
508 | // Set parallel processing mode |
509 | aGluer.SetRunParallel(myRunParallel); |
510 | // Perform gluing |
511 | aGluer.Perform(); |
512 | if (aGluer.HasErrors()) |
513 | { |
514 | // Repetition in this direction is not possible |
515 | // Add warning saving the shapes for analysis |
516 | TopoDS_Compound aWS; |
517 | AddToShape(aShapes, aWS); |
518 | AddWarning(new BOPAlgo_AlertUnableToRepeat(aWS)); |
519 | return myRepeatedShape; |
520 | } |
521 | // Get glued shape |
522 | myRepeatedShape = aGluer.Shape(); |
523 | |
524 | // Update repetition period for the next repetitions |
525 | myRepeatPeriod[id] += Abs(theTimes) * myRepeatPeriod[id]; |
526 | |
527 | // Update history with the Gluing history |
528 | BRepTools_History aGluingHistory(aShapes, aGluer); |
529 | myHistory->Merge(aGluingHistory); |
530 | |
531 | // Update the map of twins after repetition |
532 | UpdateTwins(aTranslationHistory, aGluingHistory); |
533 | |
534 | return myRepeatedShape; |
535 | } |
536 | |
537 | //======================================================================= |
538 | //function : UpdateTwins |
539 | //purpose : Updates the map of twins after repetition |
540 | //======================================================================= |
541 | void BOPAlgo_MakePeriodic::UpdateTwins(const BRepTools_History& theTranslationHistory, |
542 | const BRepTools_History& theGluingHistory) |
543 | { |
544 | if (myTwins.IsEmpty()) |
545 | return; |
546 | |
547 | if (myRepeatedTwins.IsEmpty()) |
548 | myRepeatedTwins = myTwins; |
549 | |
550 | // New twins |
551 | TopTools_DataMapOfShapeListOfShape aNewTwinsMap; |
552 | |
553 | // Fence map to avoid repeated fill for the twins |
554 | TopTools_MapOfShape aMTwinsDone; |
555 | |
556 | // Update the map of twins with the new repeated shapes |
557 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itDMap(myRepeatedTwins); |
558 | for (; itDMap.More(); itDMap.Next()) |
559 | { |
560 | const TopoDS_Shape& aS = itDMap.Key(); |
561 | aMTwinsDone.Add(aS); |
562 | |
563 | const TopTools_ListOfShape& aLTwins = itDMap.Value(); |
564 | |
565 | // Check if the twins have not been already processed |
566 | TopTools_ListIteratorOfListOfShape itLT(aLTwins); |
567 | for (; itLT.More(); itLT.Next()) |
568 | { |
569 | if (aMTwinsDone.Contains(itLT.Value())) |
570 | break; |
571 | } |
572 | if (itLT.More()) |
573 | // Group of twins has already been processed |
574 | continue; |
575 | |
576 | // All shapes generated from the shape itself and generated |
577 | // from its twins will be the new twins for the shape |
578 | TopTools_IndexedMapOfShape aNewGroup; |
579 | itLT.Initialize(aLTwins); |
580 | |
581 | for (Standard_Boolean bShape = Standard_True; itLT.More();) |
582 | { |
583 | const TopoDS_Shape& aTwin = bShape ? aS : itLT.Value(); |
584 | const TopTools_ListOfShape& aLG = theTranslationHistory.Generated(aTwin); |
585 | TopTools_ListIteratorOfListOfShape itLG(aLG); |
586 | for (; itLG.More(); itLG.Next()) |
587 | { |
588 | const TopoDS_Shape& aG = itLG.Value(); |
589 | const TopTools_ListOfShape& aLM = theGluingHistory.Modified(aG); |
590 | if (aLM.IsEmpty()) |
591 | aNewGroup.Add(aG); |
592 | else |
593 | { |
594 | TopTools_ListIteratorOfListOfShape itLM(aLM); |
595 | for (; itLM.More(); itLM.Next()) |
596 | aNewGroup.Add(itLM.Value()); |
597 | } |
598 | } |
599 | |
600 | if (bShape) |
601 | bShape = Standard_False; |
602 | else |
603 | itLT.Next(); |
604 | } |
605 | |
606 | // Associate the twins to each other |
607 | const Standard_Integer aNbTwins = aNewGroup.Extent(); |
608 | for (Standard_Integer i = 1; i <= aNbTwins; ++i) |
609 | { |
610 | TopTools_ListOfShape* pTwins = aNewTwinsMap.Bound(aNewGroup(i), TopTools_ListOfShape()); |
611 | for (Standard_Integer j = 1; j <= aNbTwins; ++j) |
612 | if (i != j) pTwins->Append(aNewGroup(j)); |
613 | } |
614 | } |
615 | |
616 | myRepeatedTwins = aNewTwinsMap; |
617 | } |