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