泊松盘采样(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来生成随机数据,这在需要 ''' #常 ...
随机推荐
- 进阶 stack smashing--canary 报错利用 && environ泄露栈地址
进阶 stack smashing--canary 报错利用 && environ泄露栈地址 这部分是对进阶stack smashing的使用,以及对 environ的认识,我们可以看 ...
- .NET开源强大、易于使用的缓存框架 - FusionCache
前言 缓存在程序中扮演着提升性能.降低资源消耗.改善用户体验等重要角色,是构建高效.可伸缩.稳定的系统不可或缺的重要组成部分.今天大姚给大家分享一款.NET开源(基于MIT license).强大.易 ...
- JDBC数据库汇总Attack研究
前言 针对除Mysql的其它数据库的jdbc attack分析 H2 RCE 介绍 H2 是一个用 Java 开发的嵌入式数据库,它本身只是一个类库,即只有一个 jar 文件,可以直接嵌入到应用项目中 ...
- 如何使用XSSFWorkbook读取文本薄?
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18146625 出自[进步*于辰的博客] 1.文件兼容类 ...
- 文件上传之Webshell连接方法
"感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友.您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!" Websh ...
- 从 VLAN 到 IPVLAN: 聊聊虚拟网络设备及其在云原生中的应用
简介: 由于这篇文章真的很长,大量的篇幅在讲述内核的实现,如果你对这部分不感兴趣,那么在建议你在看完第一部分的三个问题后,思考一下,然后直接跳转到我们对问题的回答. 作者:张伟(谢石) 由于这篇文 ...
- 基于 Serverless 架构的头像漫画风处理小程序
简介: 当一个程序员想要个漫画风的头像时... 前言 我一直都想要有一个漫画版的头像,奈何手太笨,用了很多软件 "捏不出来",所以就在想着,是否可以基于 AI 实现这样一个功能, ...
- KubeNode:阿里巴巴云原生 容器基础设施运维实践
简介: 目前 KubeNode 已经覆盖了阿里巴巴集团的所有的 ASI 集群,接下来,将随着阿里巴巴集团"统一资源池"的项目,推进 KubeNode 覆盖更大的范围.更多的场景,让 ...
- 如何用Netty写一个高性能的分布式服务框架?
简介: Netty 是一个致力于创建高性能网络应用程序的成熟的 IO 框架.相比较与直接使用底层的 Java IO API,不需要先成为网络专家就可以基于 Netty 去构建复杂的网络应用.业界常见的 ...
- [GPT] 数据分析工具可以使用机器学习技术来预测未来趋势和提供数据可视化?
数据分析工具使用机器学习技术来预测未来趋势和提供数据可视化是靠谱的. 机器学习算法可以通过对历史数据的学习来发现数据中的模式和趋势,并利用这些模式和趋势来预测未来的趋势.这种方法已经被广泛应用于许 ...