1 // Created on: 2018-03-16
2 // Created by: Eugeny MALTCHIKOV
3 // Copyright (c) 2018 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef _BOPAlgo_MakePeriodic_HeaderFile
17 #define _BOPAlgo_MakePeriodic_HeaderFile
19 #include <Standard.hxx>
20 #include <Standard_DefineAlloc.hxx>
21 #include <Standard_Handle.hxx>
23 #include <BOPAlgo_Options.hxx>
24 #include <BRepTools_History.hxx>
25 #include <Standard_Boolean.hxx>
26 #include <TopoDS_Shape.hxx>
27 #include <TopTools_DataMapOfShapeShape.hxx>
29 //! BOPAlgo_MakePeriodic is the tool for making an arbitrary shape periodic
30 //! in 3D space in specified directions.
32 //! Periodicity of the shape means that the shape can be repeated in any
33 //! periodic direction any number of times without creation of the new
34 //! geometry or splits.
36 //! The idea is to make the shape look identical on the opposite sides of the
37 //! periodic directions, so when translating the copy of a shape on the period
38 //! there will be no coinciding parts of different dimensions.
40 //! If necessary the algorithm will trim the shape to fit it into the
41 //! requested period by splitting it by the planes limiting the shape's
44 //! For making the shape periodic in certain direction the algorithm performs
45 //! the following steps:
46 //! * Creates the copy of the shape and moves it on the period into negative
47 //! side of the requested direction;
48 //! * Splits the negative side of the shape by the moved copy, ensuring copying
49 //! of the geometry from positive side to negative;
50 //! * Creates the copy of the shape (with already split negative side) and moves
51 //! it on the period into the positive side of the requested direction;
52 //! * Splits the positive side of the shape by the moved copy, ensuring copying
53 //! of the geometry from negative side to positive.
55 //! The algorithm also associates the identical (or twin) shapes located
56 //! on the opposite sides of the result shape.
57 //! Using the *GetTwins()* method it is possible to get the twin shapes from
58 //! the opposite sides.
60 //! Algorithm also provides the methods to repeat the periodic shape in
61 //! periodic directions. The subsequent repetitions are performed on the
62 //! repeated shape, thus repeating the shape two times in X direction will
63 //! create result in three shapes (original plus two copies).
64 //! Single subsequent repetition will result already in 6 shapes.
65 //! The repetitions can be cleared and started over.
67 //! The algorithm supports History of shapes modifications, thus
68 //! it is possible to track how the shape has been changed to make it periodic
69 //! and what new shapes have been created during repetitions.
71 //! The algorithm supports the parallel processing mode, which allows faster
72 //! completion of the operations.
74 //! The algorithm supports the Error/Warning system and returns the following alerts:
75 //! - *BOPAlgo_AlertNoPeriodicityRequired* - Error alert is given if no periodicity
76 //! has been requested in any direction;
77 //! - *BOPAlgo_AlertUnableToTrim* - Error alert is given if the trimming of the shape
78 //! for fitting it into requested period has failed;
79 //! - *BOPAlgo_AlertUnableToMakeIdentical* - Error alert is given if splitting of the
80 //! shape by its moved copies has failed;
81 //! - *BOPAlgo_AlertUnableToRepeat* - Warning alert is given if the gluing of the repeated
82 //! shapes has failed.
84 //! Example of usage of the algorithm:
86 //! TopoDS_Shape aShape = ...; // The shape to make periodic
87 //! Standard_Boolean bMakeXPeriodic = ...; // Flag for making or not the shape periodic in X direction
88 //! Standard_Real aXPeriod = ...; // X period for the shape
89 //! Standard_Boolean isXTrimmed = ...; // Flag defining whether it is necessary to trimming
90 //! // the shape to fit to X period
91 //! Standard_Real aXFirst = ...; // Start of the X period
92 //! // (really necessary only if the trimming is requested)
93 //! Standard_Boolean bRunParallel = ...; // Parallel processing mode or single
95 //! BOPAlgo_MakePeriodic aPeriodicityMaker; // Periodicity maker
96 //! aPeriodicityMaker.SetShape(aShape); // Set the shape
97 //! aPeriodicityMaker.MakeXPeriodic(bMakePeriodic, aXPeriod); // Making the shape periodic in X direction
98 //! aPeriodicityMaker.SetTrimmed(isXTrimmed, aXFirst); // Trim the shape to fit X period
99 //! aPeriodicityMaker.SetRunParallel(bRunParallel); // Set the parallel processing mode
100 //! aPeriodicityMaker.Perform(); // Performing the operation
102 //! if (aPeriodicityMaker.HasErrors()) // Check for the errors
104 //! // errors treatment
105 //! Standard_SStream aSStream;
106 //! aPeriodicityMaker.DumpErrors(aSStream);
109 //! if (aPeriodicityMaker.HasWarnings()) // Check for the warnings
111 //! // warnings treatment
112 //! Standard_SStream aSStream;
113 //! aPeriodicityMaker.DumpWarnings(aSStream);
115 //! const TopoDS_Shape& aPeriodicShape = aPeriodicityMaker.Shape(); // Result periodic shape
118 //! aPeriodicityMaker.XRepeat(2); // Making repetitions
119 //! const TopoDS_Shape& aRepeat = aPeriodicityMaker.RepeatedShape(); // Getting the repeated shape
120 //! aPeriodicityMaker.ClearRepetitions(); // Clearing the repetitions
123 class BOPAlgo_MakePeriodic : public BOPAlgo_Options
127 DEFINE_STANDARD_ALLOC
129 public: //! @name Constructor
131 //! Empty constructor
132 BOPAlgo_MakePeriodic() : BOPAlgo_Options()
134 myRepeatPeriod[0] = myRepeatPeriod[1] = myRepeatPeriod[2] = 0.0;
138 public: //! @name Setting the shape to make it periodic
140 //! Sets the shape to make it periodic.
141 //! @param theShape [in] The shape to make periodic.
142 void SetShape(const TopoDS_Shape& theShape)
144 myInputShape = theShape;
148 public: //! @name Definition of the structure to keep all periodicity parameters
150 //! Structure to keep all periodicity parameters:
151 struct PeriodicityParams
158 //! Returns all previously set parameters to default values
161 myPeriodic[0] = myPeriodic[1] = myPeriodic[2] = Standard_False;
162 myPeriod[0] = myPeriod[1] = myPeriod[2] = 0.0;
163 myIsTrimmed[0] = myIsTrimmed[1] = myIsTrimmed[2] = Standard_True;
164 myPeriodFirst[0] = myPeriodFirst[1] = myPeriodFirst[2] = 0.0;
167 Standard_Boolean myPeriodic[3]; //!< Array of flags defining whether the shape should be
168 //! periodic in XYZ directions
169 Standard_Real myPeriod[3]; //!< Array of XYZ period values. Defining the period for any
170 //! direction the corresponding flag for that direction in
171 //! myPeriodic should be set to true
172 Standard_Boolean myIsTrimmed[3]; //!< Array of flags defining whether the input shape has to be
173 //! trimmed to fit the required period in the required direction
174 Standard_Real myPeriodFirst[3]; //!< Array of start parameters of the XYZ periods: required for trimming
178 public: //! @name Setters/Getters for periodicity parameters structure
180 //! Sets the periodicity parameters.
181 //! @param theParams [in] Periodicity parameters
182 void SetPeriodicityParameters(const PeriodicityParams& theParams)
184 myPeriodicityParams = theParams;
187 const PeriodicityParams& PeriodicityParameters() const
189 return myPeriodicityParams;
193 public: //! @name Methods for setting/getting periodicity info using ID as a direction
195 //! Sets the flag to make the shape periodic in specified direction:
196 //! - 0 - X direction;
197 //! - 1 - Y direction;
198 //! - 2 - Z direction.
200 //! @param theDirectionID [in] The direction's ID;
201 //! @param theIsPeriodic [in] Flag defining periodicity in given direction;
202 //! @param thePeriod [in] Required period in given direction.
203 void MakePeriodic(const Standard_Integer theDirectionID,
204 const Standard_Boolean theIsPeriodic,
205 const Standard_Real thePeriod = 0.0)
207 Standard_Integer id = ToDirectionID(theDirectionID);
208 myPeriodicityParams.myPeriodic[id] = theIsPeriodic;
209 myPeriodicityParams.myPeriod[id] = theIsPeriodic ? thePeriod : 0.0;
212 //! Returns the info about Periodicity of the shape in specified direction.
213 //! @param theDirectionID [in] The direction's ID.
214 Standard_Boolean IsPeriodic(const Standard_Integer theDirectionID) const
216 return myPeriodicityParams.myPeriodic[ToDirectionID(theDirectionID)];
219 //! Returns the Period of the shape in specified direction.
220 //! @param theDirectionID [in] The direction's ID.
221 Standard_Real Period(const Standard_Integer theDirectionID) const
223 Standard_Integer id = ToDirectionID(theDirectionID);
224 return myPeriodicityParams.myPeriodic[id] ? myPeriodicityParams.myPeriod[id] : 0.0;
228 public: //! @name Named methods for setting/getting info about shape's periodicity
230 //! Sets the flag to make the shape periodic in X direction.
231 //! @param theIsPeriodic [in] Flag defining periodicity in X direction;
232 //! @param thePeriod [in] Required period in X direction.
233 void MakeXPeriodic(const Standard_Boolean theIsPeriodic,
234 const Standard_Real thePeriod = 0.0)
236 MakePeriodic(0, theIsPeriodic, thePeriod);
239 //! Returns the info about periodicity of the shape in X direction.
240 Standard_Boolean IsXPeriodic() const { return IsPeriodic(0); }
242 //! Returns the XPeriod of the shape
243 Standard_Real XPeriod() const { return Period(0); }
245 //! Sets the flag to make the shape periodic in Y direction.
246 //! @param theIsPeriodic [in] Flag defining periodicity in Y direction;
247 //! @param thePeriod [in] Required period in Y direction.
248 void MakeYPeriodic(const Standard_Boolean theIsPeriodic,
249 const Standard_Real thePeriod = 0.0)
251 MakePeriodic(1, theIsPeriodic, thePeriod);
254 //! Returns the info about periodicity of the shape in Y direction.
255 Standard_Boolean IsYPeriodic() const { return IsPeriodic(1); }
257 //! Returns the YPeriod of the shape.
258 Standard_Real YPeriod() const { return Period(1); }
260 //! Sets the flag to make the shape periodic in Z direction.
261 //! @param theIsPeriodic [in] Flag defining periodicity in Z direction;
262 //! @param thePeriod [in] Required period in Z direction.
263 void MakeZPeriodic(const Standard_Boolean theIsPeriodic,
264 const Standard_Real thePeriod = 0.0)
266 MakePeriodic(2, theIsPeriodic, thePeriod);
269 //! Returns the info about periodicity of the shape in Z direction.
270 Standard_Boolean IsZPeriodic() const { return IsPeriodic(2); }
272 //! Returns the ZPeriod of the shape.
273 Standard_Real ZPeriod() const { return Period(2); }
276 public: //! @name Methods for setting/getting trimming info taking Direction ID as a parameter
278 //! Defines whether the input shape is already trimmed in specified direction
279 //! to fit the period in this direction.
280 //! Direction is defined by an ID:
281 //! - 0 - X direction;
282 //! - 1 - Y direction;
283 //! - 2 - Z direction.
285 //! If the shape is not trimmed it is required to set the first parameter
286 //! of the period in that direction.
287 //! The algorithm will make the shape fit into the period.
289 //! Before calling this method, the shape has to be set to be periodic in this direction.
291 //! @param theDirectionID [in] The direction's ID;
292 //! @param theIsTrimmed [in] The flag defining trimming of the shape in given direction;
293 //! @param theFirst [in] The first periodic parameter in the given direction.
294 void SetTrimmed(const Standard_Integer theDirectionID,
295 const Standard_Boolean theIsTrimmed,
296 const Standard_Real theFirst = 0.0)
298 Standard_Integer id = ToDirectionID(theDirectionID);
301 myPeriodicityParams.myIsTrimmed[id] = theIsTrimmed;
302 myPeriodicityParams.myPeriodFirst[id] = !theIsTrimmed ? theFirst : 0.0;
306 //! Returns whether the input shape was trimmed in the specified direction.
307 //! @param theDirectionID [in] The direction's ID.
308 Standard_Boolean IsInputTrimmed(const Standard_Integer theDirectionID) const
310 return myPeriodicityParams.myIsTrimmed[ToDirectionID(theDirectionID)];
313 //! Returns the first periodic parameter in the specified direction.
314 //! @param theDirectionID [in] The direction's ID.
315 Standard_Real PeriodFirst(const Standard_Integer theDirectionID) const
317 Standard_Integer id = ToDirectionID(theDirectionID);
318 return !myPeriodicityParams.myIsTrimmed[id] ? myPeriodicityParams.myPeriodFirst[id] : 0.0;
322 public: //! @name Named methods for setting/getting trimming info
324 //! Defines whether the input shape is already trimmed in X direction
325 //! to fit the X period. If the shape is not trimmed it is required
326 //! to set the first parameter for the X period.
327 //! The algorithm will make the shape fit into the period.
329 //! Before calling this method, the shape has to be set to be periodic in this direction.
331 //! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
332 //! in X direction to fit the X period;
333 //! @param theFirst [in] The first X periodic parameter.
334 void SetXTrimmed(const Standard_Boolean theIsTrimmed,
335 const Standard_Boolean theFirst = 0.0)
337 SetTrimmed(0, theIsTrimmed, theFirst);
340 //! Returns whether the input shape was already trimmed for X period.
341 Standard_Boolean IsInputXTrimmed() const
343 return IsInputTrimmed(0);
346 //! Returns the first parameter for the X period.
347 Standard_Real XPeriodFirst() const
349 return PeriodFirst(0);
352 //! Defines whether the input shape is already trimmed in Y direction
353 //! to fit the Y period. If the shape is not trimmed it is required
354 //! to set the first parameter for the Y period.
355 //! The algorithm will make the shape fit into the period.
357 //! Before calling this method, the shape has to be set to be periodic in this direction.
359 //! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
360 //! in Y direction to fit the Y period;
361 //! @param theFirst [in] The first Y periodic parameter.
362 void SetYTrimmed(const Standard_Boolean theIsTrimmed,
363 const Standard_Boolean theFirst = 0.0)
365 SetTrimmed(1, theIsTrimmed, theFirst);
368 //! Returns whether the input shape was already trimmed for Y period.
369 Standard_Boolean IsInputYTrimmed() const
371 return IsInputTrimmed(1);
374 //! Returns the first parameter for the Y period.
375 Standard_Real YPeriodFirst() const
377 return PeriodFirst(1);
380 //! Defines whether the input shape is already trimmed in Z direction
381 //! to fit the Z period. If the shape is not trimmed it is required
382 //! to set the first parameter for the Z period.
383 //! The algorithm will make the shape fit into the period.
385 //! Before calling this method, the shape has to be set to be periodic in this direction.
387 //! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
388 //! in Z direction to fit the Z period;
389 //! @param theFirst [in] The first Z periodic parameter.
390 void SetZTrimmed(const Standard_Boolean theIsTrimmed,
391 const Standard_Boolean theFirst = 0.0)
393 SetTrimmed(2, theIsTrimmed, theFirst);
396 //! Returns whether the input shape was already trimmed for Z period.
397 Standard_Boolean IsInputZTrimmed() const
399 return IsInputTrimmed(2);
402 //! Returns the first parameter for the Z period.
403 Standard_Real ZPeriodFirst() const
405 return PeriodFirst(2);
408 public: //! @name Performing the operation
410 //! Makes the shape periodic in necessary directions
411 Standard_EXPORT void Perform();
414 public: //! @name Using the algorithm to repeat the shape
416 //! Performs repetition of the shape in specified direction
417 //! required number of times.
418 //! Negative value of times means that the repetition should
419 //! be perform in negative direction.
420 //! Makes the repeated shape a base for following repetitions.
422 //! @param theDirectionID [in] The direction's ID;
423 //! @param theTimes [in] Requested number of repetitions.
424 Standard_EXPORT const TopoDS_Shape& RepeatShape(const Standard_Integer theDirectionID,
425 const Standard_Integer theTimes);
427 //! Repeats the shape in X direction specified number of times.
428 //! Negative value of times means that the repetition should be
429 //! perform in negative X direction.
430 //! Makes the repeated shape a base for following repetitions.
432 //! @param theTimes [in] Requested number of repetitions.
433 const TopoDS_Shape& XRepeat(const Standard_Integer theTimes)
435 return RepeatShape(0, theTimes);
438 //! Repeats the shape in Y direction specified number of times.
439 //! Negative value of times means that the repetition should be
440 //! perform in negative Y direction.
441 //! Makes the repeated shape a base for following repetitions.
443 //! @param theTimes [in] Requested number of repetitions.
444 const TopoDS_Shape& YRepeat(const Standard_Integer theTimes)
446 return RepeatShape(1, theTimes);
449 //! Repeats the shape in Z direction specified number of times.
450 //! Negative value of times means that the repetition should be
451 //! perform in negative Z direction.
452 //! Makes the repeated shape a base for following repetitions.
454 //! @param theTimes [in] Requested number of repetitions.
455 const TopoDS_Shape& ZRepeat(const Standard_Integer theTimes)
457 return RepeatShape(2, theTimes);
461 public: //! @name Starting the repetitions over
463 //! Returns the repeated shape
464 const TopoDS_Shape& RepeatedShape() const { return myRepeatedShape; }
466 //! Clears all performed repetitions.
467 //! The next repetition will be performed on the base shape.
468 void ClearRepetitions()
470 myRepeatPeriod[0] = myRepeatPeriod[1] = myRepeatPeriod[2] = 0.0;
471 myRepeatedShape.Nullify();
472 myRepeatedTwins.Clear();
473 if (!myHistory.IsNull())
476 if (!mySplitHistory.IsNull())
477 myHistory->Merge(mySplitHistory);
481 public: //! @name Obtaining the result shape
483 //! Returns the resulting periodic shape
484 const TopoDS_Shape& Shape() const { return myShape; }
487 public: //! @name Getting the identical shapes
489 //! Returns the identical shapes for the given shape located
490 //! on the opposite periodic side.
491 //! Returns empty list in case the shape has no twin.
493 //! @param theS [in] Shape to get the twins for.
494 const TopTools_ListOfShape& GetTwins(const TopoDS_Shape& theS) const
496 static TopTools_ListOfShape empty;
497 const TopTools_ListOfShape* aTwins =
498 myRepeatedTwins.IsEmpty() ? myTwins.Seek(theS) : myRepeatedTwins.Seek(theS);
499 return (aTwins ? *aTwins : empty);
503 public: //! @name Getting the History of the algorithm
505 //! Returns the History of the algorithm
506 const Handle(BRepTools_History)& History() const
511 public: //! @name Clearing the algorithm from previous runs
513 //! Clears the algorithm from previous runs
516 BOPAlgo_Options::Clear();
517 myPeriodicityParams.Clear();
519 if (!mySplitHistory.IsNull())
520 mySplitHistory->Clear();
521 if (!myHistory.IsNull())
528 public: //! @name Conversion of the integer to ID of periodic direction
530 //! Converts the integer to ID of periodic direction
531 static Standard_Integer ToDirectionID(const Standard_Integer theDirectionID)
533 return Abs(theDirectionID % 3);
537 protected: //! @name Protected methods performing the operation
539 //! Checks the validity of input data
540 Standard_EXPORT void CheckData();
542 //! Trims the shape to fit to the periodic bounds
543 Standard_EXPORT void Trim();
545 //! Makes the shape identical on opposite sides
546 Standard_EXPORT void MakeIdentical();
548 //! Splits the negative side of the shape with the geometry
549 //! located on the positive side copying the geometry from
550 //! positive side to the negative.
551 Standard_EXPORT void SplitNegative();
553 //! Splits the positive side of the shape with the geometry
554 //! located on the negative side of the shape.
555 //! Ensures that the geometries on the opposite sides will
557 //! Associates the identical opposite sub-shapes.
558 Standard_EXPORT void SplitPositive();
560 //! Splits the shape by the given tools, copying the geometry of coinciding
561 //! parts from the given tools to the split shape.
562 //! @param theTools [in] The tools to split the shape and take the geometry
563 //! for coinciding parts.
564 //! @param theSplitShapeHistory [out] The history of shape split
565 //! @param theSplitToolsHistory [out] The history of tools modifications during the split
566 Standard_EXPORT void SplitShape(const TopTools_ListOfShape& theTools,
567 Handle(BRepTools_History) theSplitShapeHistory = NULL,
568 Handle(BRepTools_History) theSplitToolsHistory = NULL);
570 //! Updates the map of twins after periodic shape repetition.
571 //! @param theTranslationHistory [in] The history of translation of the periodic shape.
572 //! @param theGluingHistory [in] The history of gluing of the repeated shapes.
573 Standard_EXPORT void UpdateTwins(const BRepTools_History& theTranslationHistory,
574 const BRepTools_History& theGluingHistory);
577 protected: //! @name Fields
580 TopoDS_Shape myInputShape; //!< Input shape to make periodic
582 PeriodicityParams myPeriodicityParams; //!< Periodicity parameters
585 TopoDS_Shape myShape; //!< Resulting periodic shape (base for repetitions)
586 TopoDS_Shape myRepeatedShape; //!< Resulting shape after making repetitions of the base
587 Standard_Real myRepeatPeriod[3]; //!< XYZ repeat period
588 TopTools_DataMapOfShapeListOfShape myRepeatedTwins; //!< Map of associations of the identical sub-shapes
589 //! after repetition of the periodic shape
592 TopTools_DataMapOfShapeListOfShape myTwins; //!< Map of associations of the identical sub-shapes
593 //! located on the opposite sides of the shape
596 Handle(BRepTools_History) mySplitHistory; //!< Split history - history of shapes modification
597 //! after the split for making the shape periodic
598 Handle(BRepTools_History) myHistory; //!< Final history of shapes modifications
599 //! (to include the history of shape repetition)
603 #endif // _BOPAlgo_MakePeriodic_HeaderFile