Brief

Implemented both CPU and GPU version, you could consider this as the basic playground to implement the more advanced feature such as support arbitrary shape in 2D space, or by radix-sort to restore the analytic shape of each Voronoi region etc. Another interesting application of JFA is the problem of 2D/3D level set reinitialization.

n = 16

n = 64

CPU

/**
* Copyright (c) 2014, Bo Zhou<Bo.Schwarzstein@gmail.com> and J CUBE Inc. Tokyo, Japan
* All rights reserved. * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the <organization>.
* 4. Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ #include <cmath>
#include <cstdlib>
#include <ctime> #include <ImathColor.h>
#include <ImathVec.h> #include <iostream>
#include <iterator>
#include <vector> int main( int Argc , char ** Argv )
{
-- Argc , ++ Argv ;
if ( Argc != )
{
return EXIT_FAILURE ;
} //
int NumSites = atoi( Argv[] ) ;
int Size = atoi( Argv[] ) ; // 1) Generate the 2D sites and the fill color.
//
std::vector< Imath::V2f > SiteVec ;
std::vector< int > SeedVecA( Size * Size , - ) ;
std::vector< Imath::C3c > RandomColorVec ;
if ( NumSites > )
{
srand( time(NULL) ) ; for ( int i = ; i < NumSites ; ++ i )
{
float X = static_cast< float >( rand() ) / RAND_MAX * Size ;
float Y = static_cast< float >( rand() ) / RAND_MAX * Size ; Imath::V2i Cell( static_cast< int >( floorf( X ) ) ,
static_cast< int >( floorf( Y ) ) ) ;
SiteVec.push_back( Imath::V2f( Cell.x + 0.5f , Cell.y + 0.5f ) ) ; SeedVecA[Cell.x + Cell.y * Size] = i ; Imath::C3c C( static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ,
static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ,
static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ) ;
RandomColorVec.push_back( C ) ;
}
}
else
{
NumSites = ; SiteVec.push_back( Imath::V2f( 0.5f , 0.5f ) ) ;
SeedVecA[] = ;
RandomColorVec.push_back( Imath::C3c( , , ) ) ;
}
std::vector< int > SeedVecB( SeedVecA ) ; //
const int SizeLowTwo = static_cast< int >( ceilf( logf( static_cast< float >( Size ) ) ) ) ; //
static const Imath::V2i OffsetArray[] = { Imath::V2i( - , - ) ,
Imath::V2i( , - ) ,
Imath::V2i( , - ) ,
Imath::V2i( - , ) ,
Imath::V2i( , ) ,
Imath::V2i( - , ) ,
Imath::V2i( , ) ,
Imath::V2i( , ) } ; int * Ping = & SeedVecA[] ;
int * Pong = & SeedVecB[] ; for ( int k = Size / ; k > ; k = k >> )
{
fprintf( stdout , "k = %d\n" , k ) ; for ( int y = ; y < Size ; ++ y )
{
for ( int x = ; x < Size ; ++ x )
{
const int CellIdx = x + y * Size ;
const int Seed = Ping[CellIdx] ;
if ( Seed > - )
{
Imath::V2i Cell( x , y ) ;
for ( int i = ; i < ; ++ i )
{
const Imath::V2i & FillCell = Cell + k * OffsetArray[i] ;
if ( FillCell.x >= && FillCell.x < Size && FillCell.y >= && FillCell.y < Size )
{
const int FillCellIdx = FillCell.x + FillCell.y * Size ;
const int FillSeed = Pong[FillCellIdx] ;
if ( FillSeed < )
{
Pong[FillCellIdx] = Seed ;
}
else
{
const Imath::V2f & FillP = Imath::V2f( FillCell.x + 0.5f , FillCell.y + 0.5f ) ;
if ( ( FillP - SiteVec[Seed] ).length() < ( FillP - SiteVec[FillSeed] ).length() )
{
Pong[FillCellIdx] = Seed ;
}
}
}
}
}
}
} std::copy( Pong , Pong + SeedVecA.size() , Ping ) ;
std::swap( Ping , Pong ) ;
} //
FILE * Output = fopen( Argv[] , "wb" ) ;
fprintf( Output , "P6\n%d %d\n255\n" , Size , Size ) ; std::vector< Imath::C3c > Pixels( Size * Size , Imath::C3c( ) ) ;
for ( int y = ; y < Size ; ++ y )
{
for ( int x = ; x < Size ; ++ x )
{
const int Seed = Pong[x + y * Size] ;
if ( Seed != - )
{
Pixels[x + y * Size] = RandomColorVec[Seed] ;
}
}
} for( std::vector< Imath::V2f >::const_iterator itr = SiteVec.begin() ; itr != SiteVec.end() ; ++ itr )
{
const int x = static_cast< int >( floorf( itr->x ) ) ;
const int y = static_cast< int >( floorf( itr->y ) ) ;
Pixels[x + y * Size] = Imath::C3c( , , ) ;
} fwrite( & Pixels[].x , , Pixels.size() , Output ) ;
fclose( Output ) ; return EXIT_SUCCESS ;
}

JFA CPU

GPU

/**
* Copyright (c) 2014, Bo Zhou<Bo.Schwarzstein@gmail.com> and J CUBE Inc. Tokyo, Japan
* All rights reserved. * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the <organization>.
* 4. Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ #include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime> #include <cuda_runtime.h>
#include <cuda_runtime_api.h> #include <iostream>
#include <iterator>
#include <vector> __global__ void Kernel( int SizeX , int SizeY , const float2 * SiteArray , const int * Ping , int * Pong , int k , int * Mutex )
{
//
const int CellX = threadIdx.x + blockIdx.x * blockDim.x ;
const int CellY = threadIdx.y + blockIdx.y * blockDim.y ; const int CellIdx = CellX + CellY * SizeX ;
const int Seed = Ping[CellIdx] ;
if ( Seed < )
{
return ;
} //
const int2 OffsetArray[] = { { - , - } ,
{ , - } ,
{ , - } ,
{ - , } ,
{ , } ,
{ - , } ,
{ , } ,
{ , } } ; for ( int i = ; i < ; ++ i )
{
const int FillCellX = CellX + k * OffsetArray[i].x ;
const int FillCellY = CellY + k * OffsetArray[i].y ;
if ( FillCellX >= && FillCellX < SizeX && FillCellY >= && FillCellY < SizeY )
{
//
const int FillCellIdx = FillCellX + FillCellY * SizeX ; // Lock
//
while ( atomicCAS( Mutex , - , FillCellIdx ) == FillCellIdx )
{
} const int FillSeed = Pong[FillCellIdx] ; if ( FillSeed < )
{
Pong[FillCellIdx] = Seed ;
}
else
{
float2 P = make_float2( FillCellX + 0.5f , FillCellY + 0.5f ) ; float2 A = SiteArray[Seed] ;
float2 PA = make_float2( A.x - P.x , A.y - P.y ) ;
float PALength = PA.x * PA.x + PA.y * PA.y ; const float2 B = SiteArray[FillSeed] ;
float2 PB = make_float2( B.x - P.x , B.y - P.y ) ;
float PBLength = PB.x * PB.x + PB.y * PB.y ; if ( PALength < PBLength )
{
Pong[FillCellIdx] = Seed ;
}
} // Release
//
atomicExch( Mutex , - ) ;
}
}
} int main( int Argc , char * Argv[] )
{
-- Argc , ++ Argv ;
if ( Argc != )
{
return EXIT_FAILURE ;
} //
int NumSites = atoi( Argv[] ) ;
int Size = atoi( Argv[] ) ; //
int NumCudaDevice = ;
cudaGetDeviceCount( & NumCudaDevice ) ;
if ( ! NumCudaDevice )
{
return EXIT_FAILURE ;
} //
//
std::vector< float2 > SiteVec ;
std::vector< int > SeedVec( Size * Size , - ) ;
std::vector< uchar3 > RandomColorVec ;
for ( int i = ; i < NumSites ; ++ i )
{
float X = static_cast< float >( rand() ) / RAND_MAX * Size ;
float Y = static_cast< float >( rand() ) / RAND_MAX * Size ;
int CellX = static_cast< int >( floorf( X ) ) ;
int CellY = static_cast< int >( floorf( Y ) ) ; SiteVec.push_back( make_float2( CellX + 0.5f , CellY + 0.5f ) ) ;
SeedVec[CellX + CellY * Size] = i ; RandomColorVec.push_back( make_uchar3( static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ,
static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ,
static_cast< unsigned char >( static_cast< float >( rand() ) / RAND_MAX * 255.0f ) ) ) ;
} //
size_t SiteSize = NumSites * sizeof( float2 ) ; float2 * SiteArray = NULL ;
cudaMalloc( & SiteArray , SiteSize ) ;
cudaMemcpy( SiteArray , & SiteVec[] , SiteSize , cudaMemcpyHostToDevice ) ; //
size_t BufferSize = Size * Size * sizeof( int ) ; int * Ping = NULL , * Pong = NULL ;
cudaMalloc( & Ping , BufferSize ) , cudaMemcpy( Ping , & SeedVec[] , BufferSize , cudaMemcpyHostToDevice ) ;
cudaMalloc( & Pong , BufferSize ) , cudaMemcpy( Pong , Ping , BufferSize , cudaMemcpyDeviceToDevice ) ; //
int * Mutex = NULL ;
cudaMalloc( & Mutex , sizeof( int ) ) , cudaMemset( Mutex , - , sizeof( int ) ) ; //
//
cudaDeviceProp CudaDeviceProperty ;
cudaGetDeviceProperties( & CudaDeviceProperty , ) ; dim3 BlockDim( CudaDeviceProperty.warpSize , CudaDeviceProperty.warpSize ) ;
dim3 GridDim( ( Size + BlockDim.x - ) / BlockDim.x ,
( Size + BlockDim.y - ) / BlockDim.y ) ; for ( int k = Size / ; k > ; k = k >> )
{
Kernel<<< GridDim , BlockDim >>>( Size , Size , SiteArray , Ping , Pong , k , Mutex ) ;
cudaDeviceSynchronize() ; cudaMemcpy( Ping , Pong , BufferSize , cudaMemcpyDeviceToDevice ) ;
std::swap( Ping , Pong ) ;
}
cudaMemcpy( & SeedVec[] , Pong , BufferSize , cudaMemcpyDeviceToHost ) ; //
cudaFree( SiteArray ) ;
cudaFree( Ping ) ;
cudaFree( Pong ) ;
cudaFree( Mutex ) ; //
//
FILE * Output = fopen( Argv[] , "wb" ) ;
fprintf( Output , "P6\n%d %d\n255\n" , Size , Size ) ; std::vector< uchar3 > Pixels( Size * Size ) ;
for ( int y = ; y < Size ; ++ y )
{
for ( int x = ; x < Size ; ++ x )
{
const int Seed = SeedVec[x + y * Size] ;
if ( Seed != - )
{
Pixels[x + y * Size] = RandomColorVec[Seed] ;
}
}
} for( std::vector< float2 >::const_iterator itr = SiteVec.begin() ; itr != SiteVec.end() ; ++ itr )
{
const int x = static_cast< int >( floorf( itr->x ) ) ;
const int y = static_cast< int >( floorf( itr->y ) ) ;
Pixels[x + y * Size] = make_uchar3( , , ) ;
} fwrite( & Pixels[].x , , Pixels.size() , Output ) ;
fclose( Output ) ; return EXIT_SUCCESS ;
}

JFA CUDA

Jump Flood Algorithms for Centroidal Voronoi Tessellation的更多相关文章

  1. Visulalization Voronoi in OpenSceneGraph

    Visulalization Voronoi in OpenSceneGraph eryar@163.com Abstract. In mathematics a Voronoi diagram is ...

  2. Computer Graphics Research Software

    Computer Graphics Research Software Helping you avoid re-inventing the wheel since 2009! Last update ...

  3. Delaunay Triangulation in OpenCascade

    Delaunay Triangulation in OpenCascade eryar@163.com 摘要:本文简要介绍了Delaunay三角剖分的基础理论,并使用OpenCascade的三角剖分算 ...

  4. [转载]John Burkardt搜集的FORTRAN源代码

    Over the years, I have collected, modified, adapted, adopted or created a number of software package ...

  5. LeetCode Questions List (LeetCode 问题列表)- Java Solutions

    因为在开始写这个博客之前,已经刷了100题了,所以现在还是有很多题目没有加进来,为了方便查找哪些没加进来,先列一个表可以比较清楚的查看,也方便给大家查找.如果有哪些题目的链接有错误,请大家留言和谅解, ...

  6. D3、EChart、HighChart绘图demol

    1.echarts:   <!DOCTYPE html>   <html>   <head>   <meta charset="utf-8" ...

  7. 软件项目技术点(1)——d3.interpolateZoom-在两个点之间平滑地缩放平移

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 软件参考d3的知识点 我们在软件中主要用到d3.js的核心函数d3.interpolateZoom - 在两个点之间平滑地缩放平移.请 ...

  8. 【机器学习具体解释】KNN分类的概念、误差率及其问题

    转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/50923056 勿在浮沙筑高台 KNN概念 KNN(K-Nearest Neig ...

  9. D3js-API介绍【英】

    Everything in D3 is scoped under the d3 namespace. D3 uses semantic versioning. You can find the cur ...

随机推荐

  1. [原创]K8Cscan插件之Weblogic漏洞扫描&通用GetShell Exploit

    [原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...

  2. python multiprocessing深度解析

    在写python多线程代码的时候,会用到multiprocessing这个包,这篇文章总结了一些这个包在多进程管理方面的一些原理和代码分析. 1. 问题一:是否需要显式调用pool的close和joi ...

  3. IntelliJ IDEA 代码字体大小的快捷键设置放大缩小(很实用)(图文详解)

    不多说,直接上干货!  这是在设置IntelliJ IDEA 代码字体的快捷键设置缩小: 怎么达到的了,就是ctrl + 你的鼠标滑扭往下  这是在设置IntelliJ IDEA 代码字体的快捷键设置 ...

  4. java--uploadify3.1多文件上传

    使用uploadify时,建议下载uploadify3.1文档.边做边看. 这是页面端: <label style="color:#15428B;font-weight:bold;&q ...

  5. 关于Flutter初始化流程,我必须告诉你的是...

    1. 引言 最近在做性能优化的时候发现,在混合栈开发中,第一次启动Flutter页面的耗时总会是第二次启动Flutter页面耗时的两倍左右,这样给人感觉很不好.分析发现第一次启动Flutter页面会做 ...

  6. linux http服务源码编译安装详解

    相信大家大多都听过linux 的编译安装,但它到底是怎么把源代码变为自己电脑里可以应用的软件哪?今天,小编就以httpd 为例详细讲解一下. 什么是编译安装——编译:将源代码变为机器可执行的代码文件. ...

  7. Go标准库:深入剖析Go template

    本文只关注Go text/template的底层结构,带上了很详细的图片以及示例帮助理解,有些地方也附带上了源码进行解释.有了本文的解释,对于Go template的语法以及html/template ...

  8. Python中return self的用法

      在Python中,有些开源项目中的方法返回结果为self. 对于不熟悉这种用法的读者来说,这无疑使人困扰,本文的目的就是给出这种语法的一个解释,并且给出几个例子.   在Python中,retur ...

  9. 【转载】ASP.NET MVC设置允许跨域访问

    默认情况下,浏览器端发送Ajax请求一般被禁止跨域访问,如A域名网站访问B域名网站的请求会被终止,在ASP.NET MVC项目中,我们可以配置相应的设置项,允许网站的接口跨域访问,主要需要设置Acce ...

  10. C# ThreadPool类(线程池)

    CLR线程池并不会在CLR初始化时立即建立线程,而是在应用程序要创建线程来运行任务时,线程池才初始化一个线程.线程池初始化时是没有线程的,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线 ...