16#ifndef B2AABB_INTERSECTION_H_
17#define B2AABB_INTERSECTION_H_
25#include "b2ppconfig.h"
47template <
typename AABBOX,
typename PAIR_INTERSECTION_LIST>
48class AABBIntersection {
50 static const int min_size_to_go_to_sort = 64;
51 static const int min_size_to_go_to_scanning = 128;
54 AABBOX* box_begin, AABBOX* box_end, PAIR_INTERSECTION_LIST& pair_intersection_list_)
55 : pair_intersection_list(pair_intersection_list_), level(0), dim(0), rand_gen(0) {
56 std::fill_n(current_box.min, AABBOX::ndim, std::numeric_limits<double>::lowest());
57 std::fill_n(current_box.max, AABBOX::ndim, std::numeric_limits<double>::max());
58 current_list_box.reserve(box_end - box_begin);
59 for (; box_begin != box_end; ++box_begin) { current_list_box.push_back(box_begin); }
62 void compute() { rec_compute(current_list_box.begin(), current_list_box.end()); }
65 PAIR_INTERSECTION_LIST& pair_intersection_list;
70 double min[AABBOX::ndim];
71 double max[AABBOX::ndim];
75 typedef std::vector<AABBOX*> current_list_box_t;
76 current_list_box_t current_list_box;
77 typedef std::vector<std::pair<
78 typename current_list_box_t::const_iterator,
79 typename current_list_box_t::const_iterator> >
81 stack_node_box_t stack_node_box;
82 double buffer_pivot[min_size_to_go_to_sort * 2];
85 NotInBox(
const AABox& box_) : box(box_) {}
86 bool operator()(
const AABBOX* b)
const {
87 for (
int d = 0; d != AABBOX::ndim; ++d) {
88 if (b->min[d] > box.min[d] || b->max[d] < box.max[d]) {
return true; }
95 struct NotInInterval {
96 NotInInterval(
const double min_,
const double max_,
int dim_)
97 : min(min_), max(max_), dim(dim_) {}
98 bool operator()(
const AABBOX* b)
const {
return b->min[dim] > min || b->max[dim] < max; }
105 Left(
double pivot_,
int dim_) : pivot(pivot_), dim(dim_) {}
106 bool operator()(
const AABBOX* b)
const {
return b->min[dim] < pivot; }
112 Right(
double pivot_,
int dim_) : pivot(pivot_), dim(dim_) {}
113 bool operator()(
const AABBOX* b)
const {
return b->max[dim] <= pivot; }
118 struct ScanningSort {
119 bool operator()(
const AABBOX* a,
const AABBOX* b)
const {
return a->min[0] < b->min[0]; }
123 bool get_random(
size_t s,
size_t& i) {
124#if B2_SIZEOF_SIZE_T == 4
125 rand_gen = 1103515245u * rand_gen + 12345u;
127 return rand_gen & 2147483649u;
128#elif B2_SIZEOF_SIZE_T == 8
129 rand_gen = 2862933555777941757lu * rand_gen + 3037000493lu;
131 return rand_gen & 9223372036854775809lu;
133#error "Unimplemented for this sizeof(size_t)"
137 double get_approx_median_pivot(
138 const typename current_list_box_t::iterator begin,
139 const typename current_list_box_t::iterator end,
int h = 3) {
142 if (get_random(end - begin, i)) {
143 const double r = begin[i]->min[dim];
144 if (r < current_box.min[dim]) {
145 return current_box.max[dim];
150 const double r = begin[i]->max[dim];
151 if (r > current_box.max[dim]) {
152 return current_box.min[dim];
158 const double a1 = get_approx_median_pivot(begin, end, h);
159 const double a2 = get_approx_median_pivot(begin, end, h);
160 const double a3 = get_approx_median_pivot(begin, end, h);
161 return a1 < a2 ? (a2 < a3 ? a2 : a3) : (a1 < a3 ? a1 : a3);
165 double get_median_pivot(
166 typename current_list_box_t::iterator begin,
167 const typename current_list_box_t::iterator end) {
168 double* ptr = buffer_pivot;
169 while (begin != end) {
170 if ((*begin)->min[dim] > current_box.min[dim]) { *ptr++ = (*begin)->min[dim]; }
171 if ((*begin)->max[dim] < current_box.max[dim]) { *ptr++ = (*begin)->max[dim]; }
174 double* ptr_half = &buffer_pivot[0] + (ptr - buffer_pivot) / 2;
175 std::nth_element(&buffer_pivot[0], ptr_half, ptr);
179 static bool aabb_aabb_intersection(
const AABBOX& a,
const AABBOX& b) {
180 for (
int i = 0; i != AABBOX::ndim; ++i) {
181 if (!(a.min[i] < b.max[i] && a.max[i] > b.min[i])) {
return false; }
186 static bool scanning_aabb_aabb_intersection(
const AABBOX& a,
const AABBOX& b) {
187 for (
int i = 1; i != AABBOX::ndim; ++i) {
188 if (!(a.min[i] < b.max[i] && a.max[i] > b.min[i])) {
return false; }
195 typename current_list_box_t::iterator begin,
196 const typename current_list_box_t::iterator end) {
203 if (end - begin < min_size_to_go_to_scanning) {
204 std::sort(begin, end, ScanningSort());
205 for (; begin != end; ++begin) {
206 for (
typename current_list_box_t::const_iterator i = begin + 1; i < end; ++i) {
208 if ((*begin)->max[0] <= (*i)->min[0]) {
break; }
209 if (scanning_aabb_aabb_intersection(**begin, **i)) {
210 pair_intersection_list.add(*begin, *i);
213 if (aabb_aabb_intersection(**begin, **i)) {
214 pair_intersection_list.add(*begin, *i);
218 for (
typename stack_node_box_t::const_iterator st = stack_node_box.begin();
219 st != stack_node_box.end(); ++st) {
220 for (
typename current_list_box_t::const_iterator i = st->first; i != st->second;
222 pair_intersection_list.add(*begin, *i);
227 typename current_list_box_t::iterator start_node;
231 start_node = std::partition(
232 begin, end, NotInInterval(current_box.min[dim], current_box.max[dim], dim));
234 if (start_node == begin) {
235 start_node = std::partition(start_node, end, NotInBox(current_box));
236 if (start_node != begin) {
237 if (start_node != end) {
238 stack_node_box.push_back(
239 typename stack_node_box_t::value_type(start_node, end));
241 dim = ++level % AABBOX::ndim;
242 rec_compute(begin, start_node);
243 dim = --level % AABBOX::ndim;
247 if (start_node - begin < min_size_to_go_to_sort) {
248 pivot = get_median_pivot(begin, start_node);
250 pivot = get_approx_median_pivot(begin, start_node);
254 start_node = std::partition(start_node, end, NotInBox(current_box));
255 if (start_node != end) {
256 stack_node_box.push_back(
257 typename stack_node_box_t::value_type(start_node, end));
260 typename current_list_box_t::iterator ptr_pivot =
261 std::partition(begin, start_node, Left(pivot, dim));
263 if (begin != ptr_pivot) {
264 std::swap(current_box.max[dim], pivot);
265 dim = ++level % AABBOX::ndim;
266 rec_compute(begin, ptr_pivot);
267 dim = --level % AABBOX::ndim;
268 std::swap(current_box.max[dim], pivot);
269 ptr_pivot = std::partition(begin, ptr_pivot, Right(pivot, dim));
272 if (ptr_pivot != start_node) {
273 std::swap(current_box.min[dim], pivot);
274 dim = ++level % AABBOX::ndim;
275 rec_compute(ptr_pivot, start_node);
276 dim = --level % AABBOX::ndim;
277 std::swap(current_box.min[dim], pivot);
280 if (start_node != end) {
281 if (start_node != begin) { stack_node_box.pop_back(); }
282 for (; start_node != end; ++start_node) {
283 for (
typename current_list_box_t::const_iterator i = start_node + 1; i < end;
285 pair_intersection_list.add(*start_node, *i);
287 for (
typename stack_node_box_t::const_iterator st = stack_node_box.begin();
288 st != stack_node_box.end(); ++st) {
289 for (
typename current_list_box_t::const_iterator i = st->first;
290 i != st->second; ++i) {
291 pair_intersection_list.add(*start_node, *i);
467template <
typename AABBOX,
typename PAIR_INTERSECTION_LIST>
468inline void get_aabb_intersection(
469 AABBOX* box_begin, AABBOX* box_end, PAIR_INTERSECTION_LIST& pair_intersection) {
470 AABBIntersection<AABBOX, PAIR_INTERSECTION_LIST>(box_begin, box_end, pair_intersection)
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32