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

📄 gdiam.c

📁 任意给定三维空间的点集
💻 C
📖 第 1 页 / 共 5 页
字号:
    //printf( "addPairHeap( ?, %p, %p, ? )\n", left, right );    pair_diam.update_diam( p, q, proj );    //printf( "old_diam; %g\n", diam );    //diam = max( diam, pnt_distance( p, q ) );    //printf( "new_diam; %g\n", diam );        GFSPPair  pair;        pair.init( left, right, proj,               pnt_distance( p, q, proj ) );    if  ( pair.maxDiam() <= pair_diam.distance )        return;    //printf( "pair.maxDiam: %g, father.maxDiam: %g\n",    //        pair.maxDiam(),  father.maxDiam() );    //printf( "pair_diam.distance: %g\n", pair_diam.distance );    //pnt_dump( proj );    heap.push( pair );}void  GTreeDiamAlg::split_pair_proj( GFSPPair  & pair,                                     g_heap_pairs_p  & heap, double  eps,                                     gdiam_point  proj ){    bool  f_is_left_splitable, f_is_right_splitable;        //printf( "pair.maxDiam: %g, limit: %g\n",    //        pair.maxDiam(), ((1.0 + eps) * pair_diam.distance ));    if  ( pair.maxDiam() <= ((1.0 + eps) * pair_diam.distance ))        return;        if  ( pair.isBelowThreshold( threshold_brute ) ) {        pair.directDiameter( tree, pair_diam, proj );        return;    }    //printf( "Curr pair: (%p, %p)\n", pair.get_left(), pair.get_right() );    f_is_left_splitable = pair.get_left()->isSplitable();    f_is_right_splitable = pair.get_right()->isSplitable();    assert( f_is_left_splitable  ||  f_is_right_splitable );    if ( f_is_left_splitable )        tree.split_node( pair.get_left() );    if ( f_is_right_splitable )        tree.split_node( pair.get_right() );        if  ( f_is_left_splitable           &&  f_is_right_splitable ) {        addPairHeap( heap,                      pair.get_left()->get_left(),                     pair.get_right()->get_left(),                     proj, pair );        addPairHeap( heap,                      pair.get_left()->get_left(),                     pair.get_right()->get_right(),                     proj, pair );        // to avoid exponential blowup        if  ( pair.get_left() != pair.get_right() )            addPairHeap( heap,                          pair.get_left()->get_right(),                         pair.get_right()->get_left(),                         proj, pair );        addPairHeap( heap,                      pair.get_left()->get_right(),                     pair.get_right()->get_right(),                     proj, pair );        return;    }    if  ( f_is_left_splitable ) {        addPairHeap( heap,                     pair.get_left()->get_left(),                     pair.get_right(), proj, pair );        addPairHeap( heap,                      pair.get_left()->get_right(),                     pair.get_right(), proj, pair );        return;    }    if  ( f_is_right_splitable ) {        addPairHeap( heap,                      pair.get_left(),                     pair.get_right()->get_left(), proj, pair );        addPairHeap( heap,                      pair.get_left(),                     pair.get_right()->get_right(), proj, pair );        return;    }}void  GTreeDiamAlg::split_pair( GFSPPair  & pair,                                g_heap_pairs_p  & heap,                                double  eps ){    bool  f_is_left_splitable, f_is_right_splitable;        if  ( pair.maxDiam() <= ((1.0 + eps) * pair_diam.distance ))        return;        if  ( pair.isBelowThreshold( threshold_brute ) ) {        pair.directDiameter( tree, pair_diam );        return;    }        f_is_left_splitable = pair.get_left()->isSplitable();    f_is_right_splitable = pair.get_right()->isSplitable();    assert( f_is_left_splitable  ||  f_is_right_splitable );    if ( f_is_left_splitable )        tree.split_node( pair.get_left() );    if ( f_is_right_splitable )        tree.split_node( pair.get_right() );        if  ( f_is_left_splitable           &&  f_is_right_splitable ) {        addPairHeap( heap,                      pair.get_left()->get_left(),                     pair.get_right()->get_left() );        addPairHeap( heap,                      pair.get_left()->get_left(),                     pair.get_right()->get_right() );        // to avoid exponential blowup        if  ( pair.get_left() != pair.get_right() )            addPairHeap( heap,                          pair.get_left()->get_right(),                         pair.get_right()->get_left() );        addPairHeap( heap,                      pair.get_left()->get_right(),                     pair.get_right()->get_right() );        return;    }    if  ( f_is_left_splitable ) {        addPairHeap( heap,                     pair.get_left()->get_left(),                     pair.get_right() );        addPairHeap( heap,                      pair.get_left()->get_right(),                     pair.get_right() );        return;    }    if  ( f_is_right_splitable ) {        addPairHeap( heap,                      pair.get_left(),                     pair.get_right()->get_left() );        addPairHeap( heap,                      pair.get_left(),                     pair.get_right()->get_right() );        return;    }}GPointPair   gdiam_approx_diam( gdiam_point  * start, int  size,                                gdiam_real  eps ){    //gdiam_real  diam;    GPointPair  pair;    GTreeDiamAlg  * pAlg = new  GTreeDiamAlg( start, size, UDM_SIMPLE );    pAlg->compute_by_heap( eps );    pair = pAlg->getDiameter();    delete  pAlg;    return  pair;}GPointPair   gdiam_approx_diam_UDM( gdiam_point  * start, int  size,                                    gdiam_real  eps ){    //gdiam_real  diam;    GPointPair  pair;    GTreeDiamAlg  * pAlg = new  GTreeDiamAlg( start, size, UDM_BIG_SAMPLE );    pAlg->compute_by_heap( eps );    pair = pAlg->getDiameter();    delete  pAlg;    return  pair;}gdiam_point  * gdiam_convert( gdiam_real  * start, int  size ){    gdiam_point  * p_arr;    assert( start != NULL );    assert( size > 0 );    p_arr = (gdiam_point *)malloc( sizeof( gdiam_point ) * size );    assert( p_arr != NULL );    for  ( int  ind = 0; ind < size; ind++ )         p_arr[ ind ] = (gdiam_point)&(start[ ind * 3 ]);    return  p_arr;}GPointPair   gdiam_approx_diam_pair( gdiam_real  * start, int  size,                                     gdiam_real  eps ){    gdiam_point  * p_arr;    GPointPair  pair;    p_arr = gdiam_convert( start, size );    pair = gdiam_approx_diam( p_arr, size, eps );    free( p_arr );    return  pair;}GPointPair   gdiam_approx_diam_pair_UDM( gdiam_real  * start, int  size,                                         gdiam_real  eps ){    gdiam_point  * p_arr;    GPointPair  pair;    p_arr = gdiam_convert( start, size );    pair = gdiam_approx_diam_UDM( p_arr, size, eps );    free( p_arr );    return  pair;}gdiam_bbox   gdiam_approx_const_mvbb( gdiam_point  * start, int  size,                                      gdiam_real  eps,                                       GBBox  * p_ap_bbox )    {    //gdiam_real  diam;    GPointPair  pair, pair_2;    GTreeDiamAlg  * pAlg = new  GTreeDiamAlg( start, size, UDM_SIMPLE );    pAlg->compute_by_heap( eps );    pair = pAlg->getDiameter();    /* Comput ethe resulting diameter */    gdiam_point_t  dir, dir_2, dir_3;    dir[ 0 ] = pair.p[ 0 ] - pair.q[ 0 ];    dir[ 1 ] = pair.p[ 1 ] - pair.q[ 1 ];    dir[ 2 ] = pair.p[ 2 ] - pair.q[ 2 ];        pnt_normalize( dir );    //    printf( "Before computing second direction!\n" );    //fflush( stdout );    pAlg->compute_by_heap_proj( eps, dir );    //printf( "second direction computed!\n" );    //fflush( stdout );    pair_2 = pAlg->getDiameter();    dir_2[ 0 ] = pair_2.p[ 0 ] - pair_2.q[ 0 ];    dir_2[ 1 ] = pair_2.p[ 1 ] - pair_2.q[ 1 ];    dir_2[ 2 ] = pair_2.p[ 2 ] - pair_2.q[ 2 ];        gdiam_real prd;    prd = pnt_dot_prod( dir, dir_2 );    dir_2[ 0 ] = dir_2[ 0 ] - prd * dir[ 0 ];    dir_2[ 1 ] = dir_2[ 1 ] - prd * dir[ 1 ];    dir_2[ 2 ] = dir_2[ 2 ] - prd * dir[ 2 ];    pnt_normalize( dir );    pnt_normalize( dir_2 );    pnt_cross_prod( dir, dir_2, dir_3 );    pnt_normalize( dir_3 );    gdiam_bbox  bbox;    GBBox  ap_bbox;    if  ( ( pnt_length( dir_2 ) < 1e-6 )          &&  ( pnt_length( dir_3 ) < 1e-6 ) )         gdiam_generate_orthonormal_base( dir, dir_2, dir_3 );    if  ( ( pnt_length( dir ) == 0.0 )           ||  ( pnt_length( dir_2 ) < 1e-6 )          ||  ( pnt_length( dir_3 ) < 1e-6 ) ) {        gdiam_generate_orthonormal_base( dir, dir_2, dir_3 );        pnt_dump( dir );        pnt_dump( dir_2 );        pnt_dump( dir_3 );        fflush( stdout );        fflush( stderr );        assert( false );    }    bbox.init( dir, dir_2, dir_3 );    ap_bbox.init();    for  ( int  ind = 0; ind < size; ind++ ) {        bbox.bound( start[ ind ] );        ap_bbox.bound( start[ ind ] );    }    //printf( "Axis parallel bounding box:\n" );    //ap_bbox.dump();    //printf( "Arbitrarily oriented bounding box:\n" );    //bbox.dump();    delete  pAlg;    if  ( ap_bbox.volume() < bbox.volume() )         bbox.init( ap_bbox );    if  ( p_ap_bbox != NULL )        *p_ap_bbox = ap_bbox;    return  bbox;}gdiam_bbox   gdiam_approx_const_mvbb( gdiam_real  * start, int  size,                                      gdiam_real  eps ){    gdiam_point  * p_arr;    gdiam_bbox  gbbox;    p_arr = gdiam_convert( start, size );    gbbox = gdiam_approx_const_mvbb( p_arr, size, eps, NULL );    free( p_arr );    return   gbbox;}/*----------------------------------------------------------------------- * Code for computing best bounding box in a given drection \*-----------------------------------------------------------------------*/void  gdiam_generate_orthonormal_base( gdiam_point  in,                                       gdiam_point  out1,                                       gdiam_point  out2 ){    assert( pnt_length( in ) > 0.0 );    pnt_normalize( in );    // stupid cases..    if  ( in[ 0 ] == 0.0 ) {        if  ( in[ 1 ] == 0.0 ) {            pnt_init_normalize( out1, 1, 0, 0 );            pnt_init_normalize( out2, 0, 1, 0 );            return;        }        if  ( in[ 2 ] == 0.0 ) {            pnt_init_normalize( out1, 1, 0, 0 );            pnt_init_normalize( out2, 0, 0, 1 );            return;        }                pnt_init_normalize( out1, 0, -in[ 2 ], in[ 1 ] );        pnt_init_normalize( out2, 1, 0, 0 );        return;    }    if  ( ( in[ 1 ] == 0.0 )  &&  ( in[ 2 ] == 0.0 ) )  {        pnt_init_normalize( out1, 0, 1, 0 );        pnt_init_normalize( out2, 0, 0, 1 );        return;    }    if  ( in[ 1 ] == 0.0 ) {        pnt_init_normalize( out1, -in[ 2 ], 0, in[ 0 ] );        pnt_init_normalize( out2, 0, 1, 0 );        return;    }        if  ( in[ 2 ] == 0.0 ) {        pnt_init_normalize( out1, -in[ 1 ], in[ 0 ], 0 );        pnt_init_normalize( out2, 0, 0, 1 );        return;    }    // all entries in the vector are not zero.    pnt_init_normalize( out1, -in[ 1 ], in[ 0 ], 0 );    pnt_cross_prod( in, out1, out2 );        pnt_normalize( out2 );}class  point2d{public:    gdiam_real  x, y;    gdiam_point  src;    void  init( gdiam_point  pnt,                gdiam_point  base_x,                gdiam_point  base_y ) {        src = pnt;        x = pnt_dot_prod( pnt, base_x );        y = pnt_dot_prod( pnt, base_y );    }    gdiam_real  dist( const point2d  & pnt ) {        return  sqrt( ( x - pnt.x ) * ( x - pnt.x )                      + ( y - pnt.y ) * ( y - pnt.y ) );    }    void  dump() const {        printf( "(%g, %g)\n", x, y );    }    bool  equal( const point2d  & pnt ) const {        return  ( ( x == pnt.x )  &&  ( y == pnt.y ) );    }    bool  equal_real( const point2d  & pnt ) const {        return  ( ( fabs( x - pnt.x ) < 1e-8 )                  && ( fabs( y - pnt.y ) < 1e-8 ) );    }};typedef  point2d  * point2d_ptr;class  vec_point_2d : public std::vector<point2d_ptr> {};inline ldouble     Area( const point2d  & a,                         const point2d  & b,                        const point2d  & c ){    double  x1, y1, x2, y2, len;    x1 = b.x - a.x;    y1 = b.y - a.y;    x2 = c.x - a.x;    y2 = c.y - a.y;    if  ( ( x1 != 0.0 )  ||  ( y1 != 0.0 ) ) {        len = sqrt( x1 * x1 + y1 * y1 );        x1 /= len;        y1 /= len;    }    if  ( ( x2 != 0.0 )  ||  ( y2 != 0.0 ) ) {        len = sqrt( x2 * x2 + y2 * y2 );        x2 /= len;        y2 /= len;    }    ldouble  area;    area = x1 * y2 - x2 * y1;    //area = (ldouble)a.x * (ldouble)b.y - (ldouble)a.y * (ldouble)b.x +    //    (ldouble)a.y * (ldouble)c.x - (ldouble)a.x * (ldouble)c.y +    //    (ldouble)b.x * (ldouble)c.y - (ldouble)c.x * (ldouble)b.y;    //printf( "area: %g\n", area );    return  area;}inline int     AreaSign( const point2d  & a,                          const point2d  & b,                         const point2d  & c ){    ldouble  area;    area = a.x * b.y - a.y * b.x +        a.y * c.x - a.x * c.y +        b.x * c.y - c.x * b.y;

⌨️ 快捷键说明

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