⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 segment_tree.h

📁 很多二维 三维几何计算算法 C++ 类库
💻 H
字号:
// Copyright (c) 2004  Max-Planck-Institute Saarbruecken (Germany).// All rights reserved.//// This file is part of CGAL (www.cgal.org); you may redistribute it under// the terms of the Q Public License version 1.0.// See the file LICENSE.QPL distributed with CGAL.//// Licensees holding a valid commercial license may use this file in// accordance with the commercial license agreement provided with the software.//// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.3-branch/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h $// $Id: segment_tree.h 37975 2007-04-06 08:29:24Z afabri $// //// Author(s)     : Lutz Kettner  <kettner@mpi-sb.mpg.de>//                 Andreas Meyer <ameyer@mpi-sb.mpg.de>#ifndef CGAL_BOX_INTERSECTION_D_SEGMENT_TREE_H#define CGAL_BOX_INTERSECTION_D_SEGMENT_TREE_H#include <CGAL/basic.h>#include <CGAL/Box_intersection_d/box_limits.h>#include <CGAL/Random.h>#include <algorithm>#include <iterator>#include <functional>#include <cstdlib>#include <cmath>#include <climits>#include <cstddef>CGAL_BEGIN_NAMESPACEnamespace Box_intersection_d {#define CGAL_BOX_INTERSECTION_DEBUG 0template< class ForwardIter1, class ForwardIter2,          class Callback, class Traits >void all_pairs( ForwardIter1 p_begin, ForwardIter1 p_end,                ForwardIter2 i_begin, ForwardIter2 i_end,                Callback callback, Traits , bool complete_case = false){    const int last_dim = Traits::dimension() - 1;    for( ForwardIter1 p = p_begin; p != p_end; ++p ) {        for( ForwardIter2 i = i_begin; i != i_end; ++i ) {            if ((complete_case && Traits::id(*p) >= Traits::id(*i))                || Traits::id(*p) == Traits::id(*i))                continue;            for( int dim = 0; dim <= last_dim; ++dim )                if( !Traits::does_intersect( *p, *i, dim ) )                    goto no_intersection1;            callback( *p, *i );        no_intersection1:            ;        }    }}template< class ForwardIter, class Callback, class Traits >void all_pairs( ForwardIter p_begin, ForwardIter p_end,                Callback callback, Traits){    const int last_dim = Traits::dimension() - 1;    // loops actually only up to p_end-1, but we stay with the forward iterator    // requirement and have one unnecessary but harmless additional iteration    for( ForwardIter p = p_begin; p != p_end; ++p ) {        ForwardIter i = p;        ++i;        for( ; i != p_end; ++i ) {            for( int dim = 0; dim <= last_dim; ++dim )                if( !Traits::does_intersect( *p, *i, dim ) )                    goto no_intersection1;            callback( *p, *i );        no_intersection1:            ;        }    }}template< class RandomAccessIter1, class RandomAccessIter2,          class Callback, class Traits >void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end,                   RandomAccessIter2 i_begin, RandomAccessIter2 i_end,                   Callback callback, Traits, int last_dim,                   bool in_order = true ){    typedef typename Traits::Compare Compare;    std::sort( p_begin, p_end, Compare( 0 ) );    std::sort( i_begin, i_end, Compare( 0 ) );    // for each box viewed as interval i    for( RandomAccessIter2 i = i_begin; i != i_end; ++i ) {        // look for the first box b with i.min <= p.min        for( ; p_begin != p_end && Traits::is_lo_less_lo( *p_begin, *i, 0 );             ++p_begin );        // look for all boxes with p.min < i.max        for( RandomAccessIter1 p = p_begin;             p != p_end && Traits::is_lo_less_hi( *p, *i, 0 );             ++p )        {            if( Traits::id( *p ) == Traits::id( *i ) )                continue;            for( int dim = 1; dim <= last_dim; ++dim )                if( !Traits::does_intersect( *p, *i, dim ) )                    goto no_intersection;            if( in_order )                callback( *p, *i );            else                callback( *i, *p );        no_intersection:            ;        }    }}template< class RandomAccessIter1, class RandomAccessIter2,          class Callback, class Traits >void modified_two_way_scan(    RandomAccessIter1 p_begin, RandomAccessIter1 p_end,    RandomAccessIter2 i_begin, RandomAccessIter2 i_end,    Callback callback, Traits, int last_dim,    bool in_order = true ){    typedef typename Traits::Compare Compare;    std::sort( p_begin, p_end, Compare( 0 ) );    std::sort( i_begin, i_end, Compare( 0 ) );    // for each box viewed as interval    while( i_begin != i_end && p_begin != p_end ) {        if( Traits::is_lo_less_lo( *i_begin, *p_begin, 0 ) ) {            for( RandomAccessIter1 p = p_begin;                 p != p_end && Traits::is_lo_less_hi( *p, *i_begin, 0 );                 ++p )            {                if( Traits::id( *p ) == Traits::id( *i_begin ) )                    continue;                for( int dim = 1; dim <= last_dim; ++dim )                    if( !Traits::does_intersect( *p, *i_begin, dim ) )                        goto no_intersection1;                if( Traits::contains_lo_point( *i_begin, *p, last_dim ) ) {                    if( in_order )                        callback( *p, *i_begin );                    else                        callback( *i_begin, *p );                }            no_intersection1:                ;            }            ++i_begin;        } else {            for( RandomAccessIter2 i = i_begin;                 i != i_end && Traits::is_lo_less_hi( *i, *p_begin, 0 );                 ++i )            {                if( Traits::id( *p_begin ) == Traits::id( *i ) )                    continue;                for( int dim = 1; dim <= last_dim; ++dim )                    if( !Traits::does_intersect( *p_begin, *i, dim ) )                        goto no_intersection2;                if( Traits::contains_lo_point( *i, *p_begin, last_dim ) ) {                    if( in_order )                        callback( *p_begin, *i );                    else                        callback( *i, *p_begin );                }            no_intersection2:                ;            }            ++p_begin;        }    }}template< class RandomAccessIter, class Predicate_traits >RandomAccessItermedian_of_three( RandomAccessIter a, RandomAccessIter b, RandomAccessIter c,                 Predicate_traits, int dim ){    if( Predicate_traits::is_lo_less_lo( *a, *b, dim ) )        if( Predicate_traits::is_lo_less_lo( *b, *c, dim ) )            return b;        else if( Predicate_traits::is_lo_less_lo( *a, *c, dim ) )            return c;        else            return a;    else if( Predicate_traits::is_lo_less_lo( *a, *c, dim ) )        return a;    else if( Predicate_traits::is_lo_less_lo( *b, *c, dim ) )        return c;    else        return b;}template< class RandomAccessIter, class Predicate_traits >RandomAccessIteriterative_radon( RandomAccessIter begin, RandomAccessIter end,                 Predicate_traits traits, int dim, int num_levels ){    if( num_levels < 0 ) {        const unsigned int rnd = CGAL::default_random.get_int( 0, INT_MAX );        return begin + rnd % std::distance( begin, end );    }    return median_of_three(         iterative_radon( begin, end, traits, dim, num_levels - 1 ),         iterative_radon( begin, end, traits, dim, num_levels - 1 ),         iterative_radon( begin, end, traits, dim, num_levels - 1 ),	 traits, dim );}// returns iterator for first element in [begin,end) which does not satisfy// the Split_Points_Predicate: [begin,mid) contains only points strictly less// than mi. so, elements from [mid,end) are equal or higher than mi.template< class RandomAccessIter, class Predicate_traits, class T >RandomAccessItersplit_points( RandomAccessIter begin, RandomAccessIter end,              Predicate_traits traits, int dim, T& mi ){    // magic formula    int levels = (int)(.91*std::log(((double)std::distance(begin,end))/137.0)+1);    levels = (levels <= 0) ? 1 : levels;    RandomAccessIter it = iterative_radon( begin, end, traits, dim, levels );    mi = Predicate_traits::min_coord( *it, dim );    return std::partition( begin, end,                           typename Predicate_traits::Lo_less( mi, dim ) );}#if CGAL_BOX_INTERSECTION_DEBUG static int level = -1; #define CGAL_BOX_INTERSECTION_DUMP(msg) { \   for( unsigned int i = level; i; --i ) \     std::cout << "  "; \    std::cout << msg; \  }#else #define CGAL_BOX_INTERSECTION_DUMP(msg) ;#endiftemplate< class ForwardIter, class Traits >void dump_points( ForwardIter begin, ForwardIter end, Traits traits,                  int dim ) {    while( begin != end ) {        std::cout << Traits::min_coord( *begin, dim ) << " ";        ++begin;    }    std::cout << std::endl;}template< class ForwardIter, class Traits >void dump_intervals( ForwardIter begin, ForwardIter end, Traits traits,                     int dim ) {    while( begin != end ) {        std::cout << "[" << Traits::min_coord( *begin, dim ) << ","                         << Traits::max_coord( *begin, dim ) << ") ";        ++begin;    }    std::cout << std::endl;}template< class ForwardIter, class  Traits >void dump_box_numbers( ForwardIter begin, ForwardIter end, Traits traits ) {    while( begin != end ) {        std::cout << Traits::id( *begin ) << " ";        ++begin;    }    std::cout << std::endl;}template< class T >struct Counter {   T& value;   Counter( T& value ) : value( value ) { ++value; }   ~Counter() { --value; }};template< class RandomAccessIter1, class RandomAccessIter2,          class Callback, class T, class Predicate_traits >void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end,                   RandomAccessIter2 i_begin, RandomAccessIter2 i_end,                   T lo, T hi,                   Callback callback, Predicate_traits traits,                   std::ptrdiff_t cutoff, int dim, bool in_order ){    typedef typename Predicate_traits::Spanning   Spanning;    typedef typename Predicate_traits::Lo_less    Lo_less;    typedef typename Predicate_traits::Hi_greater Hi_greater;    const T inf = box_limits< T >::inf();    const T sup = box_limits< T >::sup();#if CGAL_BOX_INTERSECTION_DEBUG    Counter<int> bla( level );    CGAL_BOX_INTERSECTION_DUMP("range: [" << lo << "," << hi << ") dim "                                           << dim << std::endl )    CGAL_BOX_INTERSECTION_DUMP("intervals: " )    //dump_box_numbers( i_begin, i_end, traits );    dump_intervals( i_begin, i_end, traits, dim );    CGAL_BOX_INTERSECTION_DUMP("points: " )    //dump_box_numbers( p_begin, p_end, traits );    dump_points( p_begin, p_end, traits, dim );#endif#if CGAL_SEGMENT_TREE_CHECK_INVARIANTS    {        // first: each point is inside segment [lo,hi)        for( RandomAccessIter1 it = p_begin; it != p_end; ++it ) {            CGAL_assertion( Lo_less( hi, dim )(*it) );            CGAL_assertion( Lo_less( lo, dim )(*it) == false );        }        // second: each interval intersects segment [lo,hi)        for( RandomAccessIter2 it = i_begin; it != i_end; ++it )            CGAL_assertion( Hi_greater(lo,dim)(*it) && Lo_less(hi,dim)(*it));    }#endif    if( p_begin == p_end || i_begin == i_end || lo >= hi )        return;    if( dim == 0 )  {        CGAL_BOX_INTERSECTION_DUMP( "dim = 0. scanning ... " << std::endl )        one_way_scan( p_begin, p_end, i_begin, i_end,                      callback, traits, dim, in_order );        return;    }    if( std::distance( p_begin, p_end ) < cutoff ||        std::distance( i_begin, i_end ) < cutoff  )    {        CGAL_BOX_INTERSECTION_DUMP( "scanning ... " << std::endl )        modified_two_way_scan( p_begin, p_end, i_begin, i_end,                               callback, traits, dim, in_order );        return;    }    RandomAccessIter2 i_span_end = lo == inf || hi == sup ? i_begin :        std::partition( i_begin, i_end, Spanning( lo, hi, dim ) );    if( i_begin != i_span_end ) {        CGAL_BOX_INTERSECTION_DUMP( "checking spanning intervals ... "                                     << std::endl )        // make two calls for roots of segment tree at next level.        segment_tree( p_begin, p_end, i_begin, i_span_end, inf, sup,                      callback, traits, cutoff, dim - 1,  in_order );        segment_tree( i_begin, i_span_end, p_begin, p_end, inf, sup,                      callback, traits, cutoff, dim - 1, !in_order );    }    T mi;    RandomAccessIter1 p_mid = split_points( p_begin, p_end, traits, dim, mi );    if( p_mid == p_begin || p_mid == p_end )  {        CGAL_BOX_INTERSECTION_DUMP( "unable to split points! ")        //dump_points( p_begin, p_end, traits, dim );        CGAL_BOX_INTERSECTION_DUMP( "performing modified two_way_san ... "                                      << std::endl )        modified_two_way_scan( p_begin, p_end, i_span_end, i_end,                               callback, traits, dim, in_order );        return;    }    RandomAccessIter2 i_mid;    // separate left intervals.    // left intervals have a low point strictly less than mi    i_mid = std::partition( i_span_end, i_end, Lo_less( mi, dim ) );    CGAL_BOX_INTERSECTION_DUMP("->left" << std::endl )    segment_tree( p_begin, p_mid, i_span_end, i_mid, lo, mi,                  callback, traits, cutoff, dim, in_order );    // separate right intervals.    // right intervals have a high point strictly higher than mi    i_mid = std::partition( i_span_end, i_end, Hi_greater( mi, dim ) );    CGAL_BOX_INTERSECTION_DUMP("->right"<< std::endl )    segment_tree( p_mid, p_end, i_span_end, i_mid, mi, hi,                  callback, traits, cutoff, dim, in_order );}#if CGAL_BOX_INTERSECTION_DEBUG #undef CGAL_BOX_INTERSECTION_DUMP#endif#undef CGAL_BOX_INTERSECTION_DEBUG} // end namespace Box_intersection_dCGAL_END_NAMESPACE#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -