0025545: TopLoc_Location::Transformation() provokes data races
[occt.git] / src / TopLoc / TopLoc_Location.cxx
CommitLineData
b311480e 1// Created on: 1991-01-21
2// Created by: Christophe MARION
3// Copyright (c) 1991-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 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>
7fd59977 25
f24125b9 26static const gp_Trsf TheIdentity;
7fd59977 27
7fd59977 28//=======================================================================
29//function : TopLoc_Location
30//purpose : constructor Identity
31//=======================================================================
32
33TopLoc_Location::TopLoc_Location ()
34{
35}
36//=======================================================================
37//function : TopLoc_Location
38//purpose : constructor Datum
39//=======================================================================
40
41TopLoc_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
51TopLoc_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
62const gp_Trsf& TopLoc_Location::Transformation() const
63{
ee6bb37b 64 if (IsIdentity())
7fd59977 65 return TheIdentity;
ee6bb37b 66 else
67 return myItems.Value().myTrsf;
7fd59977 68}
69
70TopLoc_Location::operator gp_Trsf() const
71{
72 return Transformation();
73}
74
75//=======================================================================
76//function : Inverted
77//purpose : return the inverse
78//=======================================================================
79
80TopLoc_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
101TopLoc_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
130TopLoc_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
140TopLoc_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
151TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const
152{
ee6bb37b 153 if (IsIdentity()) return *this;
7fd59977 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
174Standard_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;
ec6a1aa7 192 unsigned int i = ::HashCode (items.Value().myDatum, upper);
7fd59977 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
209Standard_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
225Standard_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
236void 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