4033b4c3e977a43bd4ee60027fecebc88bfb22da
[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     unsigned int j = ((i + items.Value().myPower) << depth);
197     j              = j >> (32 - depth) | j << depth;
198     h ^= j;
199     items.Next ();
200   }
201   return ::HashCode (h, theUpperBound);
202 }
203
204 //=======================================================================
205 //function : IsEqual
206 //purpose  : operator ==
207 //=======================================================================
208
209 // two locations are Equal if the Items have the same LocalValues and Powers
210 // this is a recursive function to test it
211
212 Standard_Boolean TopLoc_Location::IsEqual (const TopLoc_Location& Other) const
213 {
214   const void** p = (const void**) &myItems;
215   const void** q = (const void**) &Other.myItems;
216   if (*p            == *q                  ) {return Standard_True ; }
217   if (IsIdentity()  || Other.IsIdentity()  ) {return Standard_False; }
218   if (FirstDatum()  != Other.FirstDatum()  ) {return Standard_False; }
219   if (FirstPower()  != Other.FirstPower()  ) {return Standard_False; }
220   else { return NextLocation() == Other.NextLocation();}
221 }
222
223 //=======================================================================
224 //function : IsDifferent
225 //purpose  : 
226 //=======================================================================
227
228 Standard_Boolean TopLoc_Location::IsDifferent
229   (const TopLoc_Location& Other) const
230 {
231   return !IsEqual(Other);
232 }
233
234 //=======================================================================
235 //function : DumpJson
236 //purpose  : 
237 //=======================================================================
238 void TopLoc_Location::DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth) const
239 {
240   DUMP_CLASS_BEGIN (theOStream, TopLoc_Location);
241
242   DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Transformation());
243   DUMP_FIELD_VALUE_NUMERICAL (theOStream, IsIdentity());
244 }
245
246 //=======================================================================
247 //function : ShallowDump
248 //purpose  : 
249 //=======================================================================
250
251 void TopLoc_Location::ShallowDump(Standard_OStream& S) const
252 {
253   S << "TopLoc_Location : ";
254   TopLoc_SListOfItemLocation items  = myItems;
255   if (items.IsEmpty()) S << "Identity"<<std::endl;
256   while (items.More()) {
257     S<<"\n";
258     S << "       Exponent : " << items.Value().myPower <<std::endl;
259     items.Value().myDatum->ShallowDump(S);
260     items.Next();
261   }
262   S << "\n";
263 }
264
265