博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Fast Poisson Disk Sampling
阅读量:5280 次
发布时间:2019-06-14

本文共 5816 字,大约阅读时间需要 19 分钟。

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

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

ContractedBlock.gif
ExpandedBlockStart.gif
2D 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*+ 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

你可能感兴趣的文章
Linux pipe函数
查看>>
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
程序的静态链接,动态链接和装载 (补充)
查看>>
关于本博客说明
查看>>
[Kaggle] Sentiment Analysis on Movie Reviews
查看>>
价值观
查看>>
mongodb命令----批量更改文档字段名
查看>>
国外常见互联网盈利创新模式
查看>>
android:scaleType属性
查看>>
shell脚本
查看>>
Upload Image to .NET Core 2.1 API
查看>>
【雷电】源代码分析(二)-- 进入游戏攻击
查看>>
Linux中防火墙centos
查看>>
[JS]递归对象或数组
查看>>
linux sed命令
查看>>
程序存储问题
查看>>
优雅地书写回调——Promise
查看>>
PHP的配置
查看>>
Struts框架----进度1
查看>>
Round B APAC Test 2017
查看>>