API Documentation
Loading...
Searching...
No Matches
TreeSorter.h
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Tree
28File: TreeSorter
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Buffer.h>
34#include <NDEVR/Vector.h>
35#include <NDEVR/Bounds.h>
36#include <NDEVR/Median.h>
37#include <NDEVR/TypeInfo.h>
38#include <NDEVR/Dictionary.h>
39#include <NDEVR/ProgressInfo.h>
40#include <algorithm>
41
42#include <NDEVR/OpenMP.h>
43#ifdef _WIN32
44 #include <execution>
45#endif
46#if NDEVR_SUPPORTS_THREADING
47#define TREE_SORTER_USE_THREAD 0
48#ifdef TREE_SORTER_USE_THREAD
49 #include <NDEVR/BasicThread.h>
50#endif
51#else
52#define TREE_SORTER_USE_THREAD 0
53#endif
54namespace NDEVR
55{
56 template<uint01 t_dims, class t_type>
58 {
59 public:
60 void getList(uint01 dimension, uint04 start, uint04 end, Buffer<uint04>& values, uint04 index_offset)
61 {
62 uint04 size = end - start;
63 values.setAll(center_ordered[dimension], index_offset, start, size);
64 }
65 protected:
66 static void _sortList(const Buffer<bool>& list_sorter, Buffer<uint04>& list, Buffer<uint04>& temp, uint04 start, uint04 end)
67 {
68 temp.clear();
69 temp.setSize(end - start);
70 uint04 temp_location = 0;
71 uint04 left_location = start;
72 for (uint04 i = start; i < end; i++)
73 {
74 if (list_sorter[list[i]])
75 {
76 list[left_location++] = list[i];
77 }
78 else
79 {
80 temp[temp_location++] = list[i];
81 }
82 }
83 list.setAll(temp, left_location, temp_location);
84
85 }
86 protected:
90 };
91
92 template<uint01 t_dims, class t_type>
93 class TreeBoundarySorter : public TreeSorterBase<t_dims, t_type>
94 {
95 public:
96 template<bool t_has_nans, class t_list_type>
97 void createCenterSortList(const Buffer<uint04>& indices, const t_list_type& locations, ProgressInfo* progress)
98 {
99 if(progress) progress->addMessage("Creating tree sort list");
100 uint04 size = indices.size();
101 TreeSorterBase<t_dims, t_type>::temp_memory.setSize(locations.size());
102 TreeSorterBase<t_dims, t_type>::temp_array.ensureCapacity((size / 2) + 1);
104
105 for(uint04 i = 0; i < size; i++)
106 {
108 }
109 if (progress) progress->addMessage("Sorting boundary");
110 m_uses_boundary = false;
111 for (uint01 dimension = 1; dimension < t_dims; ++dimension)
113 for (uint01 dimension = 0; dimension < t_dims; ++dimension)
114 sortList<t_has_nans>(dimension, locations, Buffer<Bounds<t_dims, t_type>>(), progress);
115 }
116 template<bool t_has_nans, class t_list_type>
117 void createBoundarySortList(const Buffer<uint04>& indices, const t_list_type& locations, ProgressInfo* progress)
118 {
119 if (progress) progress->addMessage("Creating tree sort list");
120 uint04 size = indices.size();
121 TreeSorterBase<t_dims, t_type>::temp_memory.setSize(locations.size());
122 TreeSorterBase<t_dims, t_type>::temp_array.ensureCapacity((size / 2) + 1);
124
127 centers.setSize(locations.size());
128 bounds.setSize(locations.size());
129 for (uint04 i = 0; i < size; i++)
130 {
132 }
133 if (progress) progress->addMessage("Sorting boundary");
134 m_uses_boundary = true;
135 for (uint04 i = 0; i < locations.size(); i++)
136 {
137 auto value = locations[i].template as<t_dims, t_type>();
138 centers[i] = value.center();
139 bounds[i] = Bounds<t_dims, t_type>(value);
140 lib_assert(isNaN(centers[i]) || bounds[i].contains(centers[i]), "Tree Sorter: Bounds did not contain center");
141 }
142 for (uint01 dimension = 1; dimension < t_dims; ++dimension)
144 for (uint01 dimension = 0; dimension < t_dims; ++dimension)
145 sortList<t_has_nans>(dimension, centers, bounds, progress);
146 }
147 template<bool t_has_nans, class t_list_type>
148 void createHashSortList(const Buffer<uint04>& indices, const t_list_type& locations, ProgressInfo* progress)
149 {
150 if (progress) progress->addMessage("Creating tree sort list");
151 uint04 size = indices.size();
153 TreeSorterBase<t_dims, t_type>::temp_array.ensureCapacity((size / 2) + 1);
155
158 for (uint04 i = 0; i < size; i++)
159 {
161 }
162 if (progress) progress->addMessage("Sorting boundary");
163 m_uses_boundary = true;
164 for (uint04 i = 0; i < indices.size(); i++)
165 {
166 auto value = locations[indices[i]].template as<t_dims, t_type>();
167 centers[indices[i]] = value.center();
168 bounds[indices[i]] = Bounds<t_dims, t_type>(value);
169 }
170 for (uint01 dimension = 1; dimension < t_dims; ++dimension)
172 for (uint01 dimension = 0; dimension < t_dims; ++dimension)
173 {
174 sortList<t_has_nans>(dimension, centers, bounds, progress);
175 }
176 }
177 template<bool t_has_nans, class t_center_buffer, class t_bounds_buffer>
178 void sortList(uint01 dimension, const t_center_buffer& centers, const t_bounds_buffer& bounds, ProgressInfo* progress)
179 {
180 if (progress)
181 {
183 switch (dimension)
184 {
185 case 0: progress->addMessage("Sorting dimension 1"); break;
186 case 1: progress->addMessage("Sorting dimension 2"); break;
187 case 2: progress->addMessage("Sorting dimension 3"); break;
188 case 3: progress->addMessage("Sorting dimension 4"); break;
189 }
190 }
191#ifdef _WIN32
192 std::sort(std::execution::par_unseq, TreeSorterBase<t_dims, t_type>::center_ordered[dimension].begin(), TreeSorterBase<t_dims, t_type>::center_ordered[dimension].end(), [&centers, dimension](uint04 a, uint04 b)
193#else
194 std::sort(TreeSorterBase<t_dims, t_type>::center_ordered[dimension].begin(), TreeSorterBase<t_dims, t_type>::center_ordered[dimension].end(), [&centers, dimension](uint04 a, uint04 b)
195#endif
196 {
197 const auto a_val = centers[a][dimension];
198 const auto b_val = centers[b][dimension];
199 if(t_has_nans)
200 {
201 if (isNaN(a_val) != isNaN(b_val))
202 return isNaN(a_val);
203 }
204 return (a_val < b_val);
205 });
206 if (m_uses_boundary)
207 {
208 if (progress) progress->addMessage("Bounding Box sorting");
211#ifdef _WIN32
212 std::sort(std::execution::par_unseq, min_ordered[dimension].begin(), min_ordered[dimension].end(), [&bounds, dimension](uint04 a, uint04 b)
213#else
214 std::sort(min_ordered[dimension].begin(), min_ordered[dimension].end(), [&bounds, dimension](uint04 a, uint04 b)
215#endif
216 {
217 const auto& a_val = bounds[a][MIN][dimension];
218 const auto& b_val = bounds[b][MIN][dimension];
219 if(t_has_nans)
220 {
221 if (isNaN(a_val) != isNaN(b_val))
222 return isNaN(a_val);
223 }
224 return (a_val < b_val);
225 });
226#ifdef _WIN32
227 std::sort(std::execution::par_unseq, max_ordered[dimension].begin(), max_ordered[dimension].end(), [&bounds, dimension](uint04 a, uint04 b)
228#else
229 std::sort(max_ordered[dimension].begin(), max_ordered[dimension].end(), [&bounds, dimension](uint04 a, uint04 b)
230#endif
231 {
232 auto a_val = bounds[a][MAX][dimension];
233 auto b_val = bounds[b][MAX][dimension];
234 if (isNaN(a_val) != isNaN(b_val))
235 return isNaN(a_val);
236 return (a_val < b_val);
237 });
238 }
239 if (progress) progress->setProgress(1.0f);
240 }
241
242
243 template<class t_list_type>
244 Bounds<t_dims, t_type> getBounds(uint04 start, uint04 finish, const t_list_type& locations) const
245 {
247 if (m_uses_boundary)
248 {
249 for (uint01 dim = 0; dim < t_dims; ++dim)
250 {
251 box[MIN][dim] = Bounds<t_dims, t_type>(locations[min_ordered[dim][start]].template as<t_dims, t_type>())[MIN][dim];
252 box[MAX][dim] = Bounds<t_dims, t_type>(locations[max_ordered[dim][finish - 1]].template as<t_dims, t_type>())[MAX][dim];
253 }
254 }
255 else
256 {
257 for (uint01 dim = 0; dim < t_dims; ++dim)
258 {
259 box[MIN][dim] = locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][start]].template as<t_dims, t_type>().center()[dim];
260 box[MAX][dim] = locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][finish - 1]].template as<t_dims, t_type>().center()[dim];
261 }
262 }
263 return box;
264 }
265 template<class t_list_type>
266 Vector<2, Bounds<t_dims, t_type>> getMedianBounds(uint01 dimension, uint04 start, uint04 end, const t_list_type& locations)
267 {
268 Vector<2, Bounds<t_dims, t_type>> bounds;//The bounds on each side of the median
269 const uint04 median_location = ((end - start) / 2) + start;
270 for(uint04 i = start; i < median_location; ++i)
271 {
273 }
274 for (uint04 i = median_location; i < end; ++i)
275 {
277 }
278 for (uint01 dim = 0; dim < t_dims; ++dim)
279 {
280 if (m_uses_boundary)
281 {
283 {
284 bounds[0][MIN][dim] = Bounds<t_dims, t_type>(locations[min_ordered[dim][start]].template as<t_dims, t_type>())[MIN][dim];
285 for (uint04 n = start + 1; n < end; ++n)
286 {
288 {
289 bounds[1][MIN][dim] = Bounds<t_dims, t_type>(locations[min_ordered[dim][n]].template as<t_dims, t_type>())[MIN][dim];
290 break;
291 }
292 }
293 }
294 else
295 {
296 bounds[1][MIN][dim] = Bounds<t_dims, t_type>(locations[min_ordered[dim][start]].template as<t_dims, t_type>())[MIN][dim];
297 for (uint04 n = start + 1; n < end; ++n)
298 {
300 {
301 bounds[0][MIN][dim] = Bounds<t_dims, t_type>(locations[min_ordered[dim][n]].template as<t_dims, t_type>())[MIN][dim];
302 break;
303 }
304 }
305 }
307 {
308 bounds[0][MAX][dim] = Bounds<t_dims, t_type>(locations[max_ordered[dim][end - 1]].template as<t_dims, t_type>())[MAX][dim];
309 for (uint04 n = end - 2; n >= start && !isNaN(n); --n)
310 {
312 {
313 bounds[1][MAX][dim] = Bounds<t_dims, t_type>(locations[max_ordered[dim][n]].template as<t_dims, t_type>())[MAX][dim];
314 break;
315 }
316 }
317 }
318 else
319 {
320 bounds[1][MAX][dim] = Bounds<t_dims, t_type>(locations[max_ordered[dim][end - 1]].template as<t_dims, t_type>())[MAX][dim];
321 for (uint04 n = end - 2; n >= start && !isNaN(n); --n)
322 {
324 {
325 bounds[0][MAX][dim] = Bounds<t_dims, t_type>(locations[max_ordered[dim][n]].template as<t_dims, t_type>())[MAX][dim];
326 break;
327 }
328 }
329 }
330 }
331 else
332 {
334 {
335 bounds[0][MIN][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][start]].template as<t_dims, t_type>())[MIN][dim];
336 for (uint04 n = start + 1; n < end; ++n)
337 {
339 {
340 bounds[1][MIN][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][n]].template as<t_dims, t_type>())[MIN][dim];
341 break;
342 }
343 }
344 }
345 else
346 {
347 bounds[1][MIN][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][start]].template as<t_dims, t_type>())[MIN][dim];
348 for (uint04 n = start + 1; n < end; ++n)
349 {
351 {
352 bounds[0][MIN][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][n]].template as<t_dims, t_type>())[MIN][dim];
353 break;
354 }
355 }
356 }
358 {
359 bounds[0][MAX][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][end - 1]].template as<t_dims, t_type>())[MAX][dim];
360 for (uint04 n = end - 2; n >= start && !isNaN(n); --n)
361 {
363 {
364 bounds[1][MAX][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][n]].template as<t_dims, t_type>())[MAX][dim];
365 break;
366 }
367 }
368 }
369 else
370 {
371 bounds[1][MAX][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][end - 1]].template as<t_dims, t_type>())[MAX][dim];
372 for (uint04 n = end - 2; n >= start && !isNaN(n); --n)
373 {
375 {
376 bounds[0][MAX][dim] = Bounds<t_dims, t_type>(locations[TreeSorterBase<t_dims, t_type>::center_ordered[dim][n]].template as<t_dims, t_type>())[MAX][dim];
377 break;
378 }
379 }
380 }
381 }
382 }
383 return bounds;
384 }
385
386 uint04 getMedian(uint01 dimension, uint04 start, uint04 end)
387 {
388 const uint04 median_location = ((end - start) / 2) + start;
389 for (uint04 i = start; i < median_location; i++)
390 {
392 }
393 for (uint04 i = median_location; i < end; i++)
394 {
396 }
397 for (uint01 dim = 0; dim < t_dims; ++dim)
398 {
399 if (dimension != dim)
400 {
402 }
403 if (m_uses_boundary)
404 {
407 }
408 }
409 return TreeSorterBase<t_dims, t_type>::center_ordered[dimension][median_location];
410 }
411
412 protected:
415 bool m_uses_boundary = true;
416 };
417
418 template<class t_type>
420
421}
#define lib_assert(expression, message)
Asserts some logic in the code. Disabled in non debug mode by default. Can be re-enabled in release u...
Definition LibAssert.h:70
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:57
constexpr t_vertex center() const
Returns the center of the bounds.
Definition Bounds.hpp:156
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:64
void setAll(const t_o_type *src, t_index_type offset, t_index_type size)
Definition Buffer.hpp:1313
constexpr t_index_type size() const
Definition Buffer.hpp:1461
void setSize(t_index_type new_size)
Definition Buffer.hpp:1413
void clear()
Definition Buffer.hpp:572
Definition Dictionary.h:48
Definition ProgressInfo.hpp:43
virtual bool setProgress(fltp04 percent)=0
virtual bool addMessage(const LogMessage &message)=0
Definition TreeSorter.h:94
void createHashSortList(const Buffer< uint04 > &indices, const t_list_type &locations, ProgressInfo *progress)
Definition TreeSorter.h:148
void createCenterSortList(const Buffer< uint04 > &indices, const t_list_type &locations, ProgressInfo *progress)
Definition TreeSorter.h:97
uint04 getMedian(uint01 dimension, uint04 start, uint04 end)
Definition TreeSorter.h:386
bool m_uses_boundary
Definition TreeSorter.h:415
void sortList(uint01 dimension, const t_center_buffer &centers, const t_bounds_buffer &bounds, ProgressInfo *progress)
Definition TreeSorter.h:178
void createBoundarySortList(const Buffer< uint04 > &indices, const t_list_type &locations, ProgressInfo *progress)
Definition TreeSorter.h:117
Buffer< uint04 > max_ordered[t_dims]
Definition TreeSorter.h:414
Buffer< uint04 > min_ordered[t_dims]
Definition TreeSorter.h:413
Bounds< t_dims, t_type > getBounds(uint04 start, uint04 finish, const t_list_type &locations) const
Definition TreeSorter.h:244
Vector< 2, Bounds< t_dims, t_type > > getMedianBounds(uint01 dimension, uint04 start, uint04 end, const t_list_type &locations)
Definition TreeSorter.h:266
Definition TreeSorter.h:58
void getList(uint01 dimension, uint04 start, uint04 end, Buffer< uint04 > &values, uint04 index_offset)
Definition TreeSorter.h:60
Buffer< bool > temp_memory
Definition TreeSorter.h:87
Buffer< uint04 > temp_array
Definition TreeSorter.h:88
Buffer< uint04 > center_ordered[t_dims]
Definition TreeSorter.h:89
static void _sortList(const Buffer< bool > &list_sorter, Buffer< uint04 > &list, Buffer< uint04 > &temp, uint04 start, uint04 end)
Definition TreeSorter.h:66
Definition TreeSorter.h:419
An element of a vector space. An element of the real coordinate space Rn Basis vector,...
Definition Vector.hpp:62
Definition ACIColor.h:37
@ MIN
Definition BaseValues.hpp:226
@ MAX
Definition BaseValues.hpp:227
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:98
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
Definition BaseValues.hpp:272