ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Fast Poisson Disk Sampling

2019-08-13 22:05:36  阅读:354  来源: 互联网

标签:int float Fast second Poisson Idx2 Disk true first


原文链接:http://www.cnblogs.com/Jedimaster/archive/2009/11/03/1595358.html

Coarse C++ implementation for "Fast Poisson disk sampling in arbitrary dimensions, R. Bridson, ACM SIGGRAPH 2007 Sketches Program".

在公司实在闲的蛋疼,于是做了个快速泊松碟采样的实现。

ContractedBlock.gifExpandedBlockStart.gif2D FPDS Code
/**
 * Copyright (c) Bo Zhou<bo.schwarzstein@gmail.com>
 * An 2D implementation of "Fast Poisson Disk Sampling in Arbitrary Dimensions, R. Bridson, ACM SIGGRAPH 2007 Sketches Program".
 * Anybody could use this code freely, if you feel it good or helpful, please tell me, thank you very much.
 */
 
#ifndef FPDS_HPP
#define FPDS_HPP

#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
 
#include <math.h>
#include <time.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <math.h>
#include <boost/multi_array.hpp>

// Define our basis data structure.
typedef std::pair<int,int> Index2D;
typedef std::pair<float,float> Point2D;

// Use C standard rand() to get uniform random number in (0,1)
inline float URand()
{
    return (float)rand() / (float)RAND_MAX;
}

// Calculate distance between 2 points.
inline float LengthSqrt(const Point2D& X, const Point2D& Y)
{
    float a = X.first - Y.first;
    float b = X.second - Y.second;
    return sqrtf( a*a + b*b );
}

float FastPoissonDiskSampling2D(const float r, std::vector<Point2D>& PointList)
{
    PointList.clear();
    
    const int N = 2;
    const float SqrtN = sqrtf((float)N);
    const float R = r*SqrtN; // This R should be used to draw circle.
    const float RDivSqrtN = R / SqrtN;
    const int K = 30; // Paper suggested.
    const float CellSize = (float)N*RDivSqrtN;
    const int GridSize = (int)ceilf(1.0f/CellSize);
    const int INVALID_IDX = -1;
    
    // Allocate a grid to accelerate.
    // Each cell could have one and only one sampler.
    boost::multi_array<int,N> Grid( boost::extents[GridSize][GridSize] );
    memset( Grid.data(), INVALID_IDX, sizeof(int)*GridSize*GridSize );
    
    std::vector<int> ActiveList;
    
    Point2D P0;
    Index2D I0;
    
    P0.first = URand();
    P0.second = URand();
    I0.first = (int)floorf( P0.first*GridSize );
    I0.second = (int)floorf( P0.second*GridSize );
    
    ActiveList.push_back(0);
    PointList.push_back(P0);
    Grid[I0.first][I0.second] = 0;
    
    int Done = 1;
    while( ActiveList.size() != 0 )
    {
        // Initialize a sampler.
        size_t MagicIdx = (size_t)floorf( URand() * ActiveList.size() );
        size_t StartIdx = ActiveList[MagicIdx];
        Point2D StartPoint = PointList[ StartIdx ];

        bool Found = false;

        for( size_t i=0; i<K; ++i )
        {
            // Generate point in radius (R,2R)
            float t = URand()*M_PI*2.0;
            float r = URand()*R+R;
            float X = r*cosf( t );
            float Y = r*sinf( t );

            // Move to current center
            Point2D CurrentPoint;
            CurrentPoint.first = X+StartPoint.first;  
            CurrentPoint.second = Y+StartPoint.second;

            // Discard if out of domain
            if( CurrentPoint.first < 0.0f || CurrentPoint.first >= 1.0f )
                continue;

            if( CurrentPoint.second < 0.0f || CurrentPoint.second >= 1.0f )
                continue;

            // Which cell the test point located in
            Index2D TargetCell;
            TargetCell.first = (int)floorf( CurrentPoint.first / CellSize );
            TargetCell.second = (int)floorf( CurrentPoint.second / CellSize );

            if( TargetCell.first < 0 || TargetCell.first >= GridSize )
                continue;

            if( TargetCell.second < 0 || TargetCell.second >= GridSize )
                continue;


            if( Grid[TargetCell.first][TargetCell.second] != INVALID_IDX )
                continue;

            Index2D TCLeft( TargetCell );
            Index2D TCRight( TargetCell );
            Index2D TCDown( TargetCell );
            Index2D TCUp( TargetCell );

            Index2D TCLU( TargetCell );
            Index2D TCRU( TargetCell );
            Index2D TCLD( TargetCell );
            Index2D TCRD( TargetCell );

            bool A = false, B = false, C = false, D = false;
            bool E = false, F = false, G = false, H = false;

            TCLeft.first--;
            if( TCLeft.first > -1 )
            {
                int Idx2 = Grid[TCLeft.first][TCLeft.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        A = true;
                    }
                }else
                {
                    A = true;
                }
            }else
            {
                A = true;
            }

            TCRight.first++;
            if( TCRight.first < GridSize )
            {
                int Idx2 = Grid[TCRight.first][TCRight.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        B = true;
                    }
                }else
                {
                    B = true;
                }
            }else
            {
                B = true;
            }

            TCDown.second--;
            if( TCDown.second > -1 )
            {
                int Idx2 = Grid[TCDown.first][TCDown.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        C = true;
                    }
                }else
                {
                    C = true;
                }
            }else
            {
                C = true;
            }

            TCUp.second++;
            if( TCUp.second < GridSize )
            {
                int Idx2 = Grid[TCUp.first][TCUp.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        D = true;
                    }
                }else
                {
                    D = true;
                }
            }else
            {
                D = true;
            }

            // 4 Corner
            // Left Up
            TCLU.first--;TCLU.second++;
            if( TCLU.first > -1 && TCLU.second < GridSize )
            {

                int Idx2 = Grid[TCLU.first][TCLU.second];
                
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        E = true;
                    }
                }else
                {
                    E = true;
                }
            }else
            {
                E = true;
            }

            // Right Up
            TCRU.first++;TCRU.second++;
            if( TCRU.first < GridSize && TCRU.second < GridSize )
            {

                int Idx2 = Grid[TCRU.first][TCRU.second];
                
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        F = true;
                    }
                }else
                {
                    F = true;
                }
            }else
            {
                F = true;
            }

            // Left Bottom
            TCLD.first--;TCLD.second--;
            if( TCLD.first > -1 && TCLD.second > -1 )
            {
                int Idx2 = Grid[TCLD.first][TCLD.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        G = true;
                    }
                }else
                {
                    G = true;
                }
            }else
            {
                G = true;
            }

            // Right Bottom
            TCRD.first++;TCRD.second--;
            if( TCRD.first < GridSize && TCRD.second > -1 )
            {
                int Idx2 = Grid[TCRD.first][TCRD.second];
                if( Idx2 >= 0 )
                {
                    if( LengthSqrt( PointList[Idx2],CurrentPoint ) > R )
                    {
                        H = true;
                    }
                }else
                {
                    H = true;
                }
            }else
            {
                H = true;
            }

            if( A&B&C&D&E&F&G&H )
            {
                Grid[TargetCell.first][TargetCell.second] = Done;
                PointList.push_back(CurrentPoint);
                ActiveList.push_back(Done);            

                ++Done;
                Found = true;
                break;
            }
        }

        // We have to remove this test sampler from active list.
        if( Found == false && ActiveList.size() > 0 )
            ActiveList.erase( ActiveList.begin()+MagicIdx );
    }

    return R;
}

#endif

 

转载于:https://www.cnblogs.com/Jedimaster/archive/2009/11/03/1595358.html

标签:int,float,Fast,second,Poisson,Idx2,Disk,true,first
来源: https://blog.csdn.net/weixin_30852367/article/details/99481038

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有