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