泊松盘采样(Poisson Disk Sampling)生成均匀随机点
当需要生成随机点且要求随机点自然均匀的分布时,使用泊松盘采样就较为适合。
但该方法与统计学上的概念关联不大,这个只相当于点在面积上服从泊松分布,
而实现这个结果有很多做法。
最终效果:

圆形为含半径的点,圆形的中心代表生成点
B站有一个不错的搬运教程(Bridson方法):
https://www.bilibili.com/video/BV1KV411x7LM
另外Bridson文章里说蓝噪声(BlueNoise)也基于此方法生成
我做了些修改,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public static class PoissonDiscSampling
{
public static List<Vector3> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 32)
{
bool IsValid(Vector3 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List<Vector3> points, int[,] grid)
{
if (candidate.x - radius >= 0f && candidate.x + radius < sampleRegionSize.x && candidate.z - radius >= 0f && candidate.z + radius < sampleRegionSize.y)
{
int cellX = Mathf.RoundToInt(candidate.x / cellSize);
int cellZ = Mathf.RoundToInt(candidate.z / cellSize);
int searchStartX = Mathf.Max(0, cellX - 3);
int searchEndX = Mathf.Min(cellX + 3, grid.GetLength(0) - 1);
int searchStartZ = Mathf.Max(0, cellZ - 3);
int searchEndZ = Mathf.Min(cellZ + 3, grid.GetLength(1) - 1);
//如果要检测其它格子内的球,需要遍历周围6个格子 for (int x = searchStartX; x <= searchEndX; x++)
{
for (int z = searchStartZ; z <= searchEndZ; z++)
{
int pointIndex = grid[x, z] - 1;//存长度不存索引,取时减1,0就变成了-1,不需要初始化数组了
if (pointIndex != -1)
{
float dst = (candidate - points[pointIndex]).magnitude;
if (dst < radius * 2f)
{
return false;
}
}
}
} return true;
} return false;
} float cellSize = radius / Mathf.Sqrt(2); int[,] grid = new int[Mathf.CeilToInt(sampleRegionSize.x / cellSize), Mathf.CeilToInt(sampleRegionSize.y / cellSize)];
List<Vector3> points = new List<Vector3>();
List<Vector3> spawnPoints = new List<Vector3>(); spawnPoints.Add(new Vector3(sampleRegionSize.x / 2f, 0f, sampleRegionSize.y / 2f));
while (spawnPoints.Count > 0)
{
int spawnIndex = Random.Range(0, spawnPoints.Count);
Vector3 spawnCenter = spawnPoints[spawnIndex]; bool candidateAccepted = false;
for (int i = 0; i < numSamplesBeforeRejection; i++)
{
float angle = Random.value * Mathf.PI * 2f;
Vector3 dir = new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle));
Vector3 candidate = spawnCenter + dir * Random.Range(2f, 3f) * radius; if (IsValid(candidate, sampleRegionSize, cellSize, radius, points, grid))
{
points.Add(candidate);
spawnPoints.Add(candidate);
grid[Mathf.RoundToInt(candidate.x / cellSize), Mathf.RoundToInt(candidate.z / cellSize)] = points.Count;
candidateAccepted = true;
break;
}
}
if (!candidateAccepted)
{
spawnPoints.RemoveAt(spawnIndex);
}
} return points;
}
}
测试代码如下:
using System.Collections.Generic;
using UnityEngine; public class Test : MonoBehaviour
{
public float radius = 0.3f;
public Vector2 sampleRegionSize = new Vector2(3f, 3f);
private List<Vector3> mPoints; private void OnEnable()
{
mPoints = PossonDiscSampling.GeneratePoints(radius, sampleRegionSize);
} private void OnDrawGizmos()
{
if (mPoints == null) return; float cellSize = radius / Mathf.Sqrt(2); Color cacheColor = Gizmos.color;
Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
for (float x = 0; x < sampleRegionSize.x; x += cellSize)
{
for (float z = 0; z < sampleRegionSize.y; z += cellSize)
Gizmos.DrawWireCube(new Vector3(x, 0f, z), new Vector3(cellSize, 0f, cellSize));
}//生成对应采样点的调试方格
Gizmos.color = cacheColor; for (int i = 0; i < mPoints.Count; i++)
{
Vector3 vector = mPoints[i]; Gizmos.DrawWireSphere(vector, radius); int x = Mathf.FloorToInt(vector.x / cellSize);
int z = Mathf.FloorToInt(vector.z / cellSize); Gizmos.DrawWireCube(new Vector3(x, 0f, z) * cellSize, new Vector3(cellSize, 0f, cellSize));
//生成当前点所属方格
}
}
}
对于该做法还可以做如下应用层面的扩展:
1.扩展到3D空间,一些鸟的移动轨迹可以直接用这个做路点寻路
2.可以尝试在UV上分布,然后映射到3D空间
3.可以基于这个做三角剖分(https://www.cnblogs.com/hont/p/15310157.html)
泊松盘采样(Poisson Disk Sampling)生成均匀随机点的更多相关文章
- Golang生成区间随机整数
package main import ( "fmt" "math/rand" "time" ) func main() { rand.Se ...
- C#使用 RNGCryptoServiceProvider 生成强随机字符串
为了生成更加可靠的随机数,微软在System.Security.Cryptography命名空间下提供一个名为system.Security.Cryptography.RNGCryptoService ...
- .NET使用Bogus生成大量随机数据
.NET如何生成大量随机数据 在演示Demo.数据库脱敏.性能测试中,有时需要生成大量随机数据.Bogus就是.NET中优秀的高性能.合理.支持多语言的随机数据生成库. Bogus的Github链接: ...
- .NET使用Bogus生成大量随机数据(转载)
原文地址:https://www.cnblogs.com/sdflysha/p/20190821-generate-lorem-data.html 在演示Demo.数据库脱敏.性能测试中,有时需要生成 ...
- 如何生成均匀随机数 C++
#include <iostream> #include <fstream> #include <cstdlib> #include <ctime> u ...
- Python Random模块生成伪随机数字
This module implements pseudo-random number generators for various distributions. 对于整数,有一个范围的均匀选择: 对 ...
- 【代码实现】PHP生成各种随机验证码
原文地址:http://www.phpthinking.com/archives/531 验证码在WEB应用中很重要,通经常使用来防止用户恶意提交表单,如恶意注冊和登录.论坛恶意灌水等.本文将通过实例 ...
- 按条件生成j随机json包:randomjson
前端开发中,在做前后端分离的时候,经常需要手写json数据,有2个问题特别揪心: 1,数据是写死的,不能按一定的条件随机生成长度不一,内容不一的数据 2,写数组的时候,如果有很多条,需要一条一条地写, ...
- [实例]JAVA生成字母+随机数字并生成文件
package com.ishow.control.code; import java.io.*; import java.text.SimpleDateFormat; import java.uti ...
- Python_生成大量随机信息
#coding=utf-8 import random import string import codecs ''' 演示如何使用Python标准库random来生成随机数据,这在需要 ''' #常 ...
随机推荐
- redis的延迟双删策略
1,redis数据为什么会存在和数据库数据不一致的问题 在多线程并发情况下,假设有两个数据库修改请求,为保证数据库与redis的数据一致性,修改请求的实现中需要修改数据库后,级联修改redis中的数据 ...
- zbar:Qt调用zbar做条码识别
编译: zbar Windows编译:https://gitee.com/vvvj/zbar-windows 下载下来后,直接使用vs来编译就可以了. zbar官网:https://zbar.sour ...
- jsPDF 添加 中文字体 分页打印 移除空白页
jsPDF2.5版本 默认不支持utf-8的字体 具体看官方的说明,默认是不支持中文的.要使用中文需要自己添加字体. 1 将字体转换为base64编码 然后引入.也可以直接引入二进制文件,但没试过这个 ...
- Redis Stack功能介绍及redis-om-dotnet使用示例
为了简化开发人员对较新的 Redis 模块及其提供的功能的体验,同时简化支持其功能的文档和客户端.以帮助开发人员从开始使用 Redis 的那一刻起,就能充分提高工作效率.Redis Stack诞生了. ...
- ThinkPHP6.x 使用指南
PHP 版本:PHP 8.1.0 框架版本:ThinkPHP 6 编辑工具:PHPStorm 2021.3.3 系统环境:Windows 10 0x01 概述 (1)简介 ThinkPHP 框架简称 ...
- Java使用ganymed工具包执行LINUX命令教程
了解更多开发技巧,请访问,架构师小跟班官网:https://www.jiagou1216.compackage com.jiagou;import ch.ethz.ssh2.Connection;im ...
- 千万级可观测数据采集器--iLogtail代码完整开源
简介: 2022年6月29日,阿里云iLogtail开源后迎来首次重大更新,正式发布完整功能的iLogtail社区版.本次更新开源全部C++核心代码,该版本在内核能力上首次对齐企业版,开发者可以构建出 ...
- 基于信通院 Serverless 工具链模型的实践:Serverless Devs
简介: Serverless Devs 作为开源开放的开发者工具,参编中国信通院<基于无服务器架构的工具链能力要求>标准,为行业统一规范发挥助推作用! 作者 | 江昱(阿里云 Serve ...
- 使用Databricks+Mlflow进行机器学习模型的训练和部署【Databricks 数据洞察公开课】
简介: 介绍如何使用Databricks和MLflow搭建机器学习生命周期管理平台,实现从数据准备.模型训练.参数和性能指标追踪.以及模型部署的全流程. 作者:李锦桂 阿里云开源大数据平台开发工程 ...
- DDD as Code:如何用代码诠释领域驱动设计?
简介: 相较于常规的MVC架构,DDD更抽象.更难以理解,各个开发者对DDD的解释也不尽相同.那么哪种设计方式才更好?在学习时如何知道哪种DDD更正统,没有被别人带歪?本文尝试使用"DDD ...