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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #define No_Standard_NoSuchObject
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>
26 static const gp_Trsf TheIdentity;
28 //=======================================================================
29 //function : TopLoc_Location
30 //purpose : constructor Identity
31 //=======================================================================
33 TopLoc_Location::TopLoc_Location ()
36 //=======================================================================
37 //function : TopLoc_Location
38 //purpose : constructor Datum
39 //=======================================================================
41 TopLoc_Location::TopLoc_Location (const Handle(TopLoc_Datum3D)& D)
43 myItems.Construct(TopLoc_ItemLocation(D,1));
46 //=======================================================================
47 //function : TopLoc_Location
49 //=======================================================================
51 TopLoc_Location::TopLoc_Location(const gp_Trsf& T)
53 Handle(TopLoc_Datum3D) D = new TopLoc_Datum3D(T);
54 myItems.Construct(TopLoc_ItemLocation(D,1));
57 //=======================================================================
58 //function : Transformation
60 //=======================================================================
62 const gp_Trsf& TopLoc_Location::Transformation() const
67 return myItems.Value().myTrsf;
70 TopLoc_Location::operator gp_Trsf() const
72 return Transformation();
75 //=======================================================================
77 //purpose : return the inverse
78 //=======================================================================
80 TopLoc_Location TopLoc_Location::Inverted () const
83 // the inverse of a Location is a chain in revert order
84 // with opposite powers and same Local
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));
96 //=======================================================================
97 //function : Multiplied
98 //purpose : operator *
99 //=======================================================================
101 TopLoc_Location TopLoc_Location::Multiplied(const TopLoc_Location& Other) const
103 // prepend the chain Other in front of this
104 // cancelling null exponents
106 if (IsIdentity()) return Other;
107 if (Other.IsIdentity()) return *this;
109 // prepend the queue of Other
110 TopLoc_Location result = Multiplied(Other.NextLocation());
111 // does the head of Other cancel the head of result
113 Standard_Integer p = Other.FirstPower();
114 if (!result.IsIdentity()) {
115 if (Other.FirstDatum() == result.FirstDatum()) {
116 p += result.FirstPower();
117 result.myItems.ToTail();
121 result.myItems.Construct(TopLoc_ItemLocation(Other.FirstDatum(),p));
125 //=======================================================================
127 //purpose : operator / this*Other.Inverted()
128 //=======================================================================
130 TopLoc_Location TopLoc_Location::Divided (const TopLoc_Location& Other) const
132 return Multiplied(Other.Inverted());
135 //=======================================================================
136 //function : Predivided
137 //purpose : return Other.Inverted() * this
138 //=======================================================================
140 TopLoc_Location TopLoc_Location::Predivided (const TopLoc_Location& Other)
143 return Other.Inverted().Multiplied(*this);
146 //=======================================================================
148 //purpose : power elevation
149 //=======================================================================
151 TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const
153 if (IsIdentity()) return *this;
154 if (pwr == 1) return *this;
155 if (pwr == 0) return TopLoc_Location();
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));
165 if (pwr > 0) return Multiplied(Powered(pwr - 1));
166 else return Inverted().Powered(-pwr);
169 //=======================================================================
170 //function : HashCode
172 //=======================================================================
174 Standard_Integer TopLoc_Location::HashCode(const Standard_Integer upper) const
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.
187 Standard_Integer depth = 0;
189 TopLoc_SListOfItemLocation items = myItems;
190 while (items.More()) {
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;
201 //=======================================================================
203 //purpose : operator ==
204 //=======================================================================
206 // two locations are Equal if the Items have the same LocalValues and Powers
207 // this is a recursive function to test it
209 Standard_Boolean TopLoc_Location::IsEqual (const TopLoc_Location& Other) const
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();}
220 //=======================================================================
221 //function : IsDifferent
223 //=======================================================================
225 Standard_Boolean TopLoc_Location::IsDifferent
226 (const TopLoc_Location& Other) const
228 return !IsEqual(Other);
231 //=======================================================================
232 //function : ShallowDump
234 //=======================================================================
236 void TopLoc_Location::ShallowDump(Standard_OStream& S) const
238 S << "TopLoc_Location : ";
239 TopLoc_SListOfItemLocation items = myItems;
240 if (items.IsEmpty()) S << "Identity"<<endl;
241 while (items.More()) {
243 S << " Exponent : " << items.Value().myPower <<endl;
244 items.Value().myDatum->ShallowDump(S);