b311480e |
1 | // Created on: 2008-08-27 |
2 | // Created by: Vladislav ROMASHKO |
973c2be1 |
3 | // Copyright (c) 2008-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
7fd59977 |
16 | |
d5e4971b |
17 | #include <TColStd_ListIteratorOfListOfInteger.hxx> |
42cf5bc1 |
18 | #include <TColStd_ListOfInteger.hxx> |
19 | #include <Voxel_OctBoolDS.hxx> |
20 | #include <Voxel_TypeDef.hxx> |
d5e4971b |
21 | |
42cf5bc1 |
22 | #include <stdlib.h> |
7fd59977 |
23 | static Standard_Byte gbits[8] = {1, 2, 4, 8, 16, 32, 64, 128}; |
24 | static Standard_Byte gnbits[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128}; |
25 | static iXYZ xyz; |
26 | |
27 | // Empty constructor |
28 | Voxel_OctBoolDS::Voxel_OctBoolDS():Voxel_DS(),mySubVoxels(0) |
29 | { |
30 | |
31 | } |
32 | |
33 | // Constructor with intialization. |
34 | Voxel_OctBoolDS::Voxel_OctBoolDS(const Standard_Real x, const Standard_Real y, const Standard_Real z, |
35 | const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen, |
36 | const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz) |
37 | :Voxel_DS(),mySubVoxels(0) |
38 | { |
39 | Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz); |
40 | } |
41 | |
42 | // Initialization. |
43 | void Voxel_OctBoolDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z, |
44 | const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen, |
45 | const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz) |
46 | { |
47 | Destroy(); |
48 | |
49 | Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz); |
50 | |
51 | if (!myNbX || !myNbY || !myNbZ) |
52 | return; |
53 | |
54 | Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0)); |
55 | Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0)); |
56 | myData = (Standard_Address) calloc(nb_slices, sizeof(Standard_Byte*)); |
57 | } |
58 | |
59 | // Destructor |
60 | void Voxel_OctBoolDS::Destroy() |
61 | { |
62 | if (myData) |
63 | { |
64 | SetZero(); |
65 | free((Standard_Byte**)myData); |
66 | myData = 0; |
67 | if (mySubVoxels) |
68 | { |
69 | delete (iXYZBool*)mySubVoxels; |
70 | mySubVoxels = 0; |
71 | } |
72 | } |
73 | } |
74 | |
75 | void Voxel_OctBoolDS::SetZero() |
76 | { |
77 | if (myData) |
78 | { |
79 | Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0)); |
80 | Standard_Integer ix = 0, nb_slices = RealToInt(ceil(nb_bytes / 8.0)); |
81 | for (; ix < nb_slices; ix++) |
82 | { |
83 | if (((Standard_Byte**)myData)[ix]) |
84 | { |
85 | free(((Standard_Byte**)myData)[ix]); |
86 | ((Standard_Byte**)myData)[ix] = 0; |
87 | } |
88 | } |
89 | } |
90 | |
91 | if (mySubVoxels) |
92 | { |
93 | iXYZBool* map = (iXYZBool*) mySubVoxels; |
94 | map->Clear(); |
95 | } |
96 | } |
97 | |
98 | // Access to the boolean information attached to a particular voxel: |
99 | // Info: (ix >= 0 && ix < theNb_x), etc. |
100 | void Voxel_OctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz, |
101 | const Standard_Boolean data) |
102 | { |
103 | // All 8 sub-voxels have the same value. |
104 | // No need anymore to keep them in memory. |
105 | if (IsSplit(ix, iy, iz)) |
106 | { |
107 | UnSplit(ix, iy, iz); |
108 | } |
109 | |
110 | Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz; |
111 | Standard_Integer islice = ibit >> 6; |
112 | |
113 | if (!data && !((Standard_Byte**)myData)[islice]) |
114 | return; // don't allocate a slice of data for setting a 0 value |
115 | |
116 | // Allocate the slice if it is not done yet. |
117 | if (!((Standard_Byte**)myData)[islice]) |
118 | { |
119 | ((Standard_Byte**)myData)[islice] = (Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte)); |
120 | } |
121 | |
122 | // Index within 8 bytes of the slice. |
123 | Standard_Integer ibit_in_current_slice = ibit - (islice << 6); |
124 | Standard_Integer ibyte = ibit_in_current_slice >> 3; |
125 | |
126 | // Value (byte) |
127 | Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte]; |
128 | |
129 | // Position of data in the 8 bit-"value". |
130 | Standard_Integer shift = ibit_in_current_slice - (ibyte << 3); |
131 | |
132 | // Set data |
133 | if (data != ((value & gbits[shift]) ? Standard_True : Standard_False)) |
134 | { |
135 | if (data) |
136 | value |= gbits[shift]; |
137 | else |
138 | value &= gnbits[shift]; |
139 | ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte] = value; |
140 | } |
141 | } |
142 | |
143 | void Voxel_OctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz, |
144 | const Standard_Integer ioct, const Standard_Boolean data) |
145 | { |
146 | // If the voxel is not split yet, do it now. |
147 | if (!IsSplit(ix, iy, iz)) |
148 | { |
149 | Split(ix, iy, iz); |
150 | } |
151 | |
152 | // Voxel |
153 | xyz.ix = ix; |
154 | xyz.iy = iy; |
155 | xyz.iz = iz; |
156 | |
157 | // Take the value |
158 | Standard_Byte value = ((iXYZBool*)mySubVoxels)->Find(xyz); |
159 | |
160 | // Set data |
161 | if (data != ((value & gbits[ioct]) ? Standard_True : Standard_False)) |
162 | { |
163 | if (data) |
164 | value |= gbits[ioct]; |
165 | else |
166 | value &= gnbits[ioct]; |
167 | ((iXYZBool*)mySubVoxels)->ChangeFind(xyz) = value; |
168 | } |
169 | } |
170 | |
171 | Standard_Boolean Voxel_OctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const |
172 | { |
173 | Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz; |
174 | Standard_Integer islice = ibit >> 6; |
175 | |
176 | // If the slice of data is not allocated, it means that its values are 0. |
177 | if (!((Standard_Byte**)myData)[islice]) |
178 | return Standard_False; |
179 | |
180 | // Index within 8 bytes of the slice. |
181 | Standard_Integer ibit_in_current_slice = ibit - (islice << 6); |
182 | Standard_Integer ibyte = ibit_in_current_slice >> 3; |
183 | |
184 | // Value (byte) |
185 | Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte]; |
186 | |
187 | // Position of data in the 8 bit-"value". |
188 | Standard_Integer shift = ibit_in_current_slice - (ibyte << 3); |
189 | |
190 | return ((value & gbits[shift]) ? Standard_True : Standard_False); |
191 | } |
192 | |
193 | Standard_Boolean Voxel_OctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz, |
194 | const Standard_Integer ioct) const |
195 | { |
196 | // If the voxel is not split, return the value of the voxel. |
197 | if (!IsSplit(ix, iy, iz)) |
198 | { |
199 | return Get(ix, iy, iz); |
200 | } |
201 | |
202 | // Voxel |
203 | xyz.ix = ix; |
204 | xyz.iy = iy; |
205 | xyz.iz = iz; |
206 | |
207 | // Take the value |
208 | const Standard_Byte value = ((iXYZBool*)mySubVoxels)->Find(xyz); |
209 | |
210 | // Return data |
211 | return (value & gbits[ioct]) ? Standard_True : Standard_False; |
212 | } |
213 | |
214 | Standard_Boolean Voxel_OctBoolDS::IsSplit(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const |
215 | { |
216 | if (!mySubVoxels) |
217 | return Standard_False; |
218 | |
219 | // Voxel |
220 | xyz.ix = ix; |
221 | xyz.iy = iy; |
222 | xyz.iz = iz; |
223 | |
224 | return ((iXYZBool*)mySubVoxels)->IsBound(xyz); |
225 | } |
226 | |
227 | void Voxel_OctBoolDS::Split(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) |
228 | { |
229 | // Voxel |
230 | xyz.ix = ix; |
231 | xyz.iy = iy; |
232 | xyz.iz = iz; |
233 | |
234 | if (mySubVoxels) |
235 | { |
236 | if (!((iXYZBool*)mySubVoxels)->IsBound(xyz)) |
237 | { |
238 | ((iXYZBool*)mySubVoxels)->Bind(xyz, 0); |
239 | } |
240 | } |
241 | else |
242 | { |
243 | mySubVoxels = (Standard_Address) new iXYZBool; |
244 | ((iXYZBool*)mySubVoxels)->Bind(xyz, 0); |
245 | } |
246 | } |
247 | |
248 | void Voxel_OctBoolDS::UnSplit(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) |
249 | { |
250 | if (!mySubVoxels) |
251 | return; |
252 | |
253 | // Voxel |
254 | xyz.ix = ix; |
255 | xyz.iy = iy; |
256 | xyz.iz = iz; |
257 | |
258 | if (((iXYZBool*)mySubVoxels)->IsBound(xyz)) |
259 | { |
260 | ((iXYZBool*)mySubVoxels)->UnBind(xyz); |
261 | } |
262 | } |
263 | |
264 | void Voxel_OctBoolDS::OptimizeMemory() |
265 | { |
266 | if (!mySubVoxels) |
267 | return; |
268 | |
269 | Standard_Byte value; |
d5e4971b |
270 | TColStd_ListOfInteger ixs, iys, izs, values; |
7fd59977 |
271 | iXYZBool::Iterator itr(*((iXYZBool*)mySubVoxels)); |
272 | for (; itr.More(); itr.Next()) |
273 | { |
274 | value = itr.Value(); |
275 | if (value == 0 || value == 255) |
276 | { |
277 | xyz = itr.Key(); |
d5e4971b |
278 | ixs.Append(xyz.ix); |
279 | iys.Append(xyz.iy); |
280 | izs.Append(xyz.iz); |
281 | values.Append((Standard_Integer)value); |
7fd59977 |
282 | } |
283 | } |
284 | |
d5e4971b |
285 | TColStd_ListIteratorOfListOfInteger itrix(ixs), itriy(iys), itriz(izs), itrvalues(values); |
286 | for (; itrix.More(); itrix.Next(), itriy.Next(), itriz.Next(), itrvalues.Next()) |
287 | { |
288 | const Standard_Integer ix = itrix.Value(); |
289 | const Standard_Integer iy = itriy.Value(); |
290 | const Standard_Integer iz = itriz.Value(); |
51740958 |
291 | const Standard_Integer aValue = itrvalues.Value(); |
d5e4971b |
292 | |
51740958 |
293 | Set(ix, iy, iz, (aValue ? Standard_True : Standard_False)); |
d5e4971b |
294 | UnSplit(ix, iy, iz); |
295 | } |
296 | |
7fd59977 |
297 | // If the map is empty, release it. |
298 | if (((iXYZBool*)mySubVoxels)->IsEmpty()) |
299 | { |
300 | delete (iXYZBool*)mySubVoxels; |
301 | mySubVoxels = 0; |
302 | } |
303 | } |