6f384eda4ae61e8738e2b4aaaadcb8138b8120f2
[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 #include <TopLoc_Location.ixx>
20 #include <Standard_NoSuchObject.hxx>
21 #include <TopLoc_Datum3D.hxx>
22 #include <TopLoc_SListOfItemLocation.hxx>
23 #include <TopLoc_ItemLocation.hxx>
24 #include <gp_Trsf.hxx>
25
26 static const gp_Trsf TheIdentity;
27
28 //=======================================================================
29 //function : TopLoc_Location
30 //purpose  : constructor Identity
31 //=======================================================================
32
33 TopLoc_Location::TopLoc_Location () 
34 {
35 }
36 //=======================================================================
37 //function : TopLoc_Location
38 //purpose  : constructor Datum
39 //=======================================================================
40
41 TopLoc_Location::TopLoc_Location (const Handle(TopLoc_Datum3D)& D)
42 {
43   myItems.Construct(TopLoc_ItemLocation(D,1));
44 }
45
46 //=======================================================================
47 //function : TopLoc_Location
48 //purpose  : 
49 //=======================================================================
50
51 TopLoc_Location::TopLoc_Location(const gp_Trsf& T)
52 {
53   Handle(TopLoc_Datum3D) D = new TopLoc_Datum3D(T);
54   myItems.Construct(TopLoc_ItemLocation(D,1));
55 }
56
57 //=======================================================================
58 //function : Transformation
59 //purpose  : 
60 //=======================================================================
61
62 const gp_Trsf& TopLoc_Location::Transformation() const
63 {
64   if (IsIdentity())
65     return TheIdentity;
66   else
67     return myItems.Value().myTrsf;
68 }
69
70 TopLoc_Location::operator gp_Trsf() const
71 {
72   return Transformation();
73 }
74
75 //=======================================================================
76 //function : Inverted
77 //purpose  : return the inverse
78 //=======================================================================
79
80 TopLoc_Location TopLoc_Location::Inverted () const
81 {
82   //
83   // the inverse of a Location is a chain in revert order
84   // with opposite powers and same Local
85   //
86   TopLoc_Location result;
87   TopLoc_SListOfItemLocation items = myItems;
88   while (items.More()) {
89     result.myItems.Construct(TopLoc_ItemLocation(items.Value().myDatum,
90                                                  -items.Value().myPower));
91     items.Next();
92   }
93   return result;
94 }
95
96 //=======================================================================
97 //function : Multiplied
98 //purpose  : operator *
99 //=======================================================================
100
101 TopLoc_Location TopLoc_Location::Multiplied(const TopLoc_Location& Other) const
102 {
103   // prepend the chain Other in front of this
104   // cancelling null exponents
105   
106   if (IsIdentity()) return Other;
107   if (Other.IsIdentity()) return *this;
108   
109   // prepend the queue of Other
110   TopLoc_Location result = Multiplied(Other.NextLocation());
111   // does the head of Other cancel the head of result
112
113   Standard_Integer p = Other.FirstPower();
114   if (!result.IsIdentity()) {
115     if (Other.FirstDatum() == result.FirstDatum()) {
116       p += result.FirstPower();
117       result.myItems.ToTail();
118     }
119   }
120   if (p != 0)
121     result.myItems.Construct(TopLoc_ItemLocation(Other.FirstDatum(),p));
122   return result;
123 }
124
125 //=======================================================================
126 //function : Divided
127 //purpose  : operator /   this*Other.Inverted()
128 //=======================================================================
129
130 TopLoc_Location TopLoc_Location::Divided (const TopLoc_Location& Other) const
131 {
132   return Multiplied(Other.Inverted());
133 }
134
135 //=======================================================================
136 //function : Predivided
137 //purpose  : return Other.Inverted() * this
138 //=======================================================================
139
140 TopLoc_Location TopLoc_Location::Predivided (const TopLoc_Location& Other) 
141      const
142 {
143   return Other.Inverted().Multiplied(*this);
144 }
145
146 //=======================================================================
147 //function : Powered
148 //purpose  : power elevation
149 //=======================================================================
150
151 TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const
152 {
153   if (IsIdentity()) return *this;
154   if (pwr == 1) return *this;
155   if (pwr == 0) return TopLoc_Location();
156   
157   // optimisation when just one element
158   if (myItems.Tail().IsEmpty()) {
159     TopLoc_Location result;
160     result.myItems.Construct(TopLoc_ItemLocation(FirstDatum(),
161                                                  FirstPower() * pwr));
162     return result;
163   }
164
165   if (pwr > 0) return Multiplied(Powered(pwr - 1));
166   else         return Inverted().Powered(-pwr);
167 }
168
169 //=======================================================================
170 //function : HashCode
171 //purpose  : 
172 //=======================================================================
173
174 Standard_Integer TopLoc_Location::HashCode(const Standard_Integer upper) const
175 {
176   // the HashCode computed for a Location is the bitwise exclusive or
177   // of values computed for each element of the list
178   // to compute this value, the depth of the element is computed 
179   // the depth is the position of the element in the list
180   // this depth is multiplied by 3
181   // each element is an elementary Datum raised to a Power
182   // the Power is bitwise left shifted by depth
183   // this is added to the HashCode of the Datum
184   // this value is biwise rotated by depth
185   // the use of depth avoids getting the same result for two permutated lists.
186
187   Standard_Integer depth = 0;
188   unsigned int h = 0;
189   TopLoc_SListOfItemLocation items = myItems;
190   while (items.More()) {
191     depth += 3;
192     unsigned int i = ::HashCode (items.Value().myDatum, upper);
193     unsigned int j = ( (i + items.Value().myPower) <<depth);
194     j = j>>(32-depth) | j<<depth;
195     h ^= j;
196     items.Next();
197   }
198   return h % upper;
199 }
200
201 //=======================================================================
202 //function : IsEqual
203 //purpose  : operator ==
204 //=======================================================================
205
206 // two locations are Equal if the Items have the same LocalValues and Powers
207 // this is a recursive function to test it
208
209 Standard_Boolean TopLoc_Location::IsEqual (const TopLoc_Location& Other) const
210 {
211   const void** p = (const void**) &myItems;
212   const void** q = (const void**) &Other.myItems;
213   if (*p            == *q                  ) {return Standard_True ; }
214   if (IsIdentity()  || Other.IsIdentity()  ) {return Standard_False; }
215   if (FirstDatum()  != Other.FirstDatum()  ) {return Standard_False; }
216   if (FirstPower()  != Other.FirstPower()  ) {return Standard_False; }
217   else { return NextLocation() == Other.NextLocation();}
218 }
219
220 //=======================================================================
221 //function : IsDifferent
222 //purpose  : 
223 //=======================================================================
224
225 Standard_Boolean TopLoc_Location::IsDifferent
226   (const TopLoc_Location& Other) const
227 {
228   return !IsEqual(Other);
229 }
230
231 //=======================================================================
232 //function : ShallowDump
233 //purpose  : 
234 //=======================================================================
235
236 void TopLoc_Location::ShallowDump(Standard_OStream& S) const
237 {
238   S << "TopLoc_Location : ";
239   TopLoc_SListOfItemLocation items  = myItems;
240   if (items.IsEmpty()) S << "Identity"<<endl;
241   while (items.More()) {
242     S<<"\n";
243     S << "       Exponent : " << items.Value().myPower <<endl;
244     items.Value().myDatum->ShallowDump(S);
245     items.Next();
246   }
247   S << "\n";
248 }
249
250