0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / Bnd / Bnd_Range.cxx
1 // Created on: 2016-06-07
2 // Created by: Nikolai BUKHALOV
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 #include <Bnd_Range.hxx>
18 #include <Standard_Dump.hxx>
19
20 //=======================================================================
21 //function : Common
22 //purpose  : 
23 //=======================================================================
24 void Bnd_Range::Common(const Bnd_Range& theOther)
25 {
26   if(theOther.IsVoid())
27   {
28     SetVoid();
29   }
30
31   if(IsVoid())
32   {
33     return;
34   }
35
36   myFirst = Max(myFirst, theOther.myFirst);
37   myLast = Min(myLast, theOther.myLast);
38 }
39
40 //=======================================================================
41 //function : Union
42 //purpose  : 
43 //=======================================================================
44 Standard_Boolean Bnd_Range::Union(const Bnd_Range& theOther)
45 {
46   if (IsVoid() || theOther.IsVoid())
47     return Standard_False;
48
49   if (myLast < theOther.myFirst)
50     return Standard_False;
51
52   if (myFirst > theOther.myLast)
53     return Standard_False;
54
55   myFirst = Min(myFirst, theOther.myFirst);
56   myLast = Max(myLast, theOther.myLast);
57
58   return Standard_True;
59 }
60
61 //=======================================================================
62 //function : IsIntersected
63 //purpose  : 
64 //=======================================================================
65 Standard_Integer Bnd_Range::IsIntersected(const Standard_Real theVal,
66                                           const Standard_Real thePeriod) const
67 {
68   if (IsVoid())
69     return Standard_False;
70
71   const Standard_Real aPeriod = Abs(thePeriod);
72   const Standard_Real aDF = myFirst - theVal,
73                       aDL = myLast - theVal;
74
75   if (aPeriod <= RealSmall())
76   { 
77     const Standard_Real aDelta = aDF*aDL;
78     if (IsEqual(aDelta, 0.0))
79       return 2;
80
81     if (aDelta > 0.0)
82       return 0;
83
84     return 1;
85   }
86
87   //If <this> intersects theVal then there exists an integer
88   //number N such as 
89   //    (myFirst <= theVal+aPeriod*N <= myLast) <=>
90   //    ((myFirst-theVal)/aPeriod <= N <= (myLast-theVal)/aPeriod).
91   //I.e. the interval [aDF/aPeriod, aDL/aPeriod] must contain at least one
92   //integer number.
93   //In this case, Floor(aDF/aPeriod) and Floor(aDL/aPeriod)
94   //return different values or aDF/aPeriod (aDL/aPeriod)
95   //is strictly integer number.
96   //Examples:
97   //  1. (aDF/aPeriod==2.8, aDL/aPeriod==3.5 =>
98   //        Floor(aDF/aPeriod) == 2, Floor(aDL/aPeriod) == 3.
99   //  2. aDF/aPeriod==2.0, aDL/aPeriod==2.6 =>
100   //        Floor(aDF/aPeriod) == Floor(aDL/aPeriod) == 2.
101
102   const Standard_Real aVal1 = aDF / aPeriod,
103                       aVal2 = aDL / aPeriod;
104   const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
105   const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
106   if (aPar1 != aPar2)
107   {//Interval (myFirst, myLast] intersects seam-edge
108     if (IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
109     {//aVal2 is an integer number => myLast lies ON the "seam-edge"
110       return 2;
111     }
112
113     return 1;
114   }
115
116   //Here, aPar1 == aPar2. 
117
118   if (IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
119   {//aVal1 is an integer number => myFirst lies ON the "seam-edge"
120     return 2;
121   }
122
123 #if 0
124   // This check is excess because always myFirst <= myLast.
125   // So, this condition is never satisfied.
126   if (IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
127   {//aVal2 is an integer number => myLast lies ON the "seam-edge"
128     return 2;
129   }
130 #endif
131
132   return 0;
133 }
134
135 //=======================================================================
136 //function : Split
137 //purpose  : 
138 //=======================================================================
139 void Bnd_Range::Split(const Standard_Real theVal,
140                       NCollection_List<Bnd_Range>& theList,
141                       const Standard_Real thePeriod) const
142 {
143   const Standard_Real aPeriod = Abs(thePeriod);
144   if (IsIntersected(theVal, aPeriod) != 1)
145   {
146     theList.Append(*this);
147     return;
148   }
149
150   const Standard_Boolean isPeriodic = (aPeriod > 0.0);
151
152   if (!isPeriodic)
153   {
154     theList.Append(Bnd_Range(myFirst, theVal));
155     theList.Append(Bnd_Range(theVal, myLast));
156     return;
157   }
158
159   Standard_Real aValPrev = theVal + aPeriod*Ceiling((myFirst - theVal) / aPeriod);
160
161   //Now, (myFirst <= aValPrev < myFirst+aPeriod).
162
163   if (aValPrev > myFirst)
164   {
165     theList.Append(Bnd_Range(myFirst, aValPrev));
166   }
167
168   for (Standard_Real aVal = aValPrev+aPeriod; aVal <= myLast; aVal += aPeriod)
169   {
170     theList.Append(Bnd_Range(aValPrev, aVal));
171     aValPrev = aVal;
172   }
173
174   if (aValPrev < myLast)
175   {
176     theList.Append(Bnd_Range(aValPrev, myLast));
177   }
178 }
179
180 // =======================================================================
181 // function : DumpJson
182 // purpose  :
183 // =======================================================================
184 void Bnd_Range::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
185 {
186   OCCT_DUMP_CLASS_BEGIN (theOStream, Bnd_Range)
187
188   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFirst)
189   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLast)
190 }