0030997: Foundation Classes - name correction of dump macros
[occt.git] / src / TopLoc / TopLoc_Location.cxx
1 // Created on: 1991-01-21
2 // Created by: Christophe MARION
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #define No_Standard_NoSuchObject
18
19
20 #include <gp_Trsf.hxx>
21 #include <Standard_ConstructionError.hxx>
22 #include <Standard_NoSuchObject.hxx>
23 #include <Standard_Dump.hxx>
24 #include <TopLoc_Datum3D.hxx>
25 #include <TopLoc_ItemLocation.hxx>
26 #include <TopLoc_Location.hxx>
27 #include <TopLoc_SListOfItemLocation.hxx>
28
29 static const gp_Trsf TheIdentity;
30
31 //=======================================================================
32 //function : TopLoc_Location
33 //purpose  : constructor Identity
34 //=======================================================================
35
36 TopLoc_Location::TopLoc_Location () 
37 {
38 }
39 //=======================================================================
40 //function : TopLoc_Location
41 //purpose  : constructor Datum
42 //=======================================================================
43
44 TopLoc_Location::TopLoc_Location (const Handle(TopLoc_Datum3D)& D)
45 {
46   myItems.Construct(TopLoc_ItemLocation(D,1));
47 }
48
49 //=======================================================================
50 //function : TopLoc_Location
51 //purpose  : 
52 //=======================================================================
53
54 TopLoc_Location::TopLoc_Location(const gp_Trsf& T)
55 {
56   Handle(TopLoc_Datum3D) D = new TopLoc_Datum3D(T);
57   myItems.Construct(TopLoc_ItemLocation(D,1));
58 }
59
60 //=======================================================================
61 //function : Transformation
62 //purpose  : 
63 //=======================================================================
64
65 const gp_Trsf& TopLoc_Location::Transformation() const
66 {
67   if (IsIdentity())
68     return TheIdentity;
69   else
70     return myItems.Value().myTrsf;
71 }
72
73 TopLoc_Location::operator gp_Trsf() const
74 {
75   return Transformation();
76 }
77
78 //=======================================================================
79 //function : Inverted
80 //purpose  : return the inverse
81 //=======================================================================
82
83 TopLoc_Location TopLoc_Location::Inverted () const
84 {
85   //
86   // the inverse of a Location is a chain in revert order
87   // with opposite powers and same Local
88   //
89   TopLoc_Location result;
90   TopLoc_SListOfItemLocation items = myItems;
91   while (items.More()) {
92     result.myItems.Construct(TopLoc_ItemLocation(items.Value().myDatum,
93                                                  -items.Value().myPower));
94     items.Next();
95   }
96   return result;
97 }
98
99 //=======================================================================
100 //function : Multiplied
101 //purpose  : operator *
102 //=======================================================================
103
104 TopLoc_Location TopLoc_Location::Multiplied(const TopLoc_Location& Other) const
105 {
106   // prepend the chain Other in front of this
107   // cancelling null exponents
108   
109   if (IsIdentity()) return Other;
110   if (Other.IsIdentity()) return *this;
111   
112   // prepend the queue of Other
113   TopLoc_Location result = Multiplied(Other.NextLocation());
114   // does the head of Other cancel the head of result
115
116   Standard_Integer p = Other.FirstPower();
117   if (!result.IsIdentity()) {
118     if (Other.FirstDatum() == result.FirstDatum()) {
119       p += result.FirstPower();
120       result.myItems.ToTail();
121     }
122   }
123   if (p != 0)
124     result.myItems.Construct(TopLoc_ItemLocation(Other.FirstDatum(),p));
125   return result;
126 }
127
128 //=======================================================================
129 //function : Divided
130 //purpose  : operator /   this*Other.Inverted()
131 //=======================================================================
132
133 TopLoc_Location TopLoc_Location::Divided (const TopLoc_Location& Other) const
134 {
135   return Multiplied(Other.Inverted());
136 }
137
138 //=======================================================================
139 //function : Predivided
140 //purpose  : return Other.Inverted() * this
141 //=======================================================================
142
143 TopLoc_Location TopLoc_Location::Predivided (const TopLoc_Location& Other) 
144      const
145 {
146   return Other.Inverted().Multiplied(*this);
147 }
148
149 //=======================================================================
150 //function : Powered
151 //purpose  : power elevation
152 //=======================================================================
153
154 TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const
155 {
156   if (IsIdentity()) return *this;
157   if (pwr == 1) return *this;
158   if (pwr == 0) return TopLoc_Location();
159   
160   // optimisation when just one element
161   if (myItems.Tail().IsEmpty()) {
162     TopLoc_Location result;
163     result.myItems.Construct(TopLoc_ItemLocation(FirstDatum(),
164                                                  FirstPower() * pwr));
165     return result;
166   }
167
168   if (pwr > 0) return Multiplied(Powered(pwr - 1));
169   else         return Inverted().Powered(-pwr);
170 }
171
172 //=======================================================================
173 // function : HashCode
174 // purpose  :
175 //=======================================================================
176 Standard_Integer TopLoc_Location::HashCode (const Standard_Integer theUpperBound) const
177 {
178   // the HashCode computed for a Location is the bitwise exclusive or
179   // of values computed for each element of the list
180   // to compute this value, the depth of the element is computed 
181   // the depth is the position of the element in the list
182   // this depth is multiplied by 3
183   // each element is an elementary Datum raised to a Power
184   // the Power is bitwise left shifted by depth
185   // this is added to the HashCode of the Datum
186   // this value is biwise rotated by depth
187   // the use of depth avoids getting the same result for two permutated lists.
188
189   Standard_Integer           depth = 0;
190   unsigned int               h     = 0;
191   TopLoc_SListOfItemLocation items = myItems;
192   while (items.More())
193   {
194     depth += 3;
195     unsigned int           i             = ::HashCode (items.Value().myDatum, theUpperBound);
196     const Standard_Integer aClampedDepth = depth % 32;
197     unsigned int           j             = ((i + items.Value().myPower) << aClampedDepth);
198     j                                    = j >> (32 - aClampedDepth) | j << aClampedDepth;
199     h ^= j;
200     items.Next ();
201   }
202   return ::HashCode (h, theUpperBound);
203 }
204
205 //=======================================================================
206 //function : IsEqual
207 //purpose  : operator ==
208 //=======================================================================
209
210 // two locations are Equal if the Items have the same LocalValues and Powers
211 // this is a recursive function to test it
212
213 Standard_Boolean TopLoc_Location::IsEqual (const TopLoc_Location& Other) const
214 {
215   const void** p = (const void**) &myItems;
216   const void** q = (const void**) &Other.myItems;
217   if (*p            == *q                  ) {return Standard_True ; }
218   if (IsIdentity()  || Other.IsIdentity()  ) {return Standard_False; }
219   if (FirstDatum()  != Other.FirstDatum()  ) {return Standard_False; }
220   if (FirstPower()  != Other.FirstPower()  ) {return Standard_False; }
221   else { return NextLocation() == Other.NextLocation();}
222 }
223
224 //=======================================================================
225 //function : IsDifferent
226 //purpose  : 
227 //=======================================================================
228
229 Standard_Boolean TopLoc_Location::IsDifferent
230   (const TopLoc_Location& Other) const
231 {
232   return !IsEqual(Other);
233 }
234
235 //=======================================================================
236 //function : DumpJson
237 //purpose  : 
238 //=======================================================================
239 void TopLoc_Location::DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth) const
240 {
241   OCCT_DUMP_CLASS_BEGIN (theOStream, TopLoc_Location);
242
243   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Transformation());
244   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, IsIdentity());
245 }
246
247 //=======================================================================
248 //function : ShallowDump
249 //purpose  : 
250 //=======================================================================
251
252 void TopLoc_Location::ShallowDump(Standard_OStream& S) const
253 {
254   S << "TopLoc_Location : ";
255   TopLoc_SListOfItemLocation items  = myItems;
256   if (items.IsEmpty()) S << "Identity"<<std::endl;
257   while (items.More()) {
258     S<<"\n";
259     S << "       Exponent : " << items.Value().myPower <<std::endl;
260     items.Value().myDatum->ShallowDump(S);
261     items.Next();
262   }
263   S << "\n";
264 }
265
266