均匀的生成圆和三角形内的随机点

2024-04-10 16:18
文章标签 生成 三角形 随机 均匀

本文主要是介绍均匀的生成圆和三角形内的随机点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、均匀生成圆内的随机点
我们知道生成矩形内的随机点比较容易,只要分别随机生成相应的横坐标和纵坐标,比如随机生成范围[-10,10]内横坐标x,随机生成范围[-20,20]内的纵坐标y,那么(x,y)就是生成的随机点。由此,我们很容易的想到了算法1

算法1(正确的):

每个圆对应一个外切矩形,我们随机生成矩形内的点,如果该点在圆内,就返回改点,否则重新生成直到生成的点在圆内。

该方法的缺点是有可能连续几次都生成不了符合要求的点。(可以求得:每次生成点时,该点有 image 的概率在圆内)

算法2(错误的):

可能有的人想到该方法,根据圆的解析式image (假设圆心在原点)我们可以先随机生成[-R, R]范围内横坐标x,然后生成image 范围内的随机数y,(x,y)就是需要的点。

我们写程序模拟了该过程,从下图可以看出,我们可以看到当x靠近圆的边缘使,y的范围减小,因此两边边缘的点较密集,靠近圆心的点较稀疏。

算法3(错误的):

还可以根据极坐标,圆内的点可以如下描述

x = r*sin(theta)

y = r*cos(theta)

其中0 <= r <= R, 0 <= theta < 360

先随机生成[0, 360)内的theta,然后随机生成[0, R]内的r。

theta固定后,当r越靠近R,即点越靠近圆的边缘,因此如果r是[0,R]等概率生成的,那么圆的边缘的点会比靠近圆心处要稀疏。

算法4(正确的):

和算法3一样还是根据极坐标

x = r*sin(theta)

y = r*cos(theta)

其中0 <= r <= R, 0 <= theta < 360

先随机生成[0, 360)内的theta,然后随机生成[0, 1]内的k, 且r = sqrt(k)*R。

根据根号函数的性质,这样使得r的分布在k靠近1(靠近边缘)的地方点变得较密,具体证明可参考here, 也可以参考论文“矩形和椭圆内均匀分布随机点定理及应用”,圆是椭圆的特例

以上的4个算法的代码如下(Python3.3):

import numpy as np
import matplotlib.pyplot as plt
import random
import math#博客算法1
def GeneratePointInCycle1(point_num, radius):for i in range(1, point_num+1):while True:x = random.uniform(-radius, radius)y = random.uniform(-radius, radius)if (x**2) + (y**2) < (radius**2):breakplt.plot(x, y, '*', color = "black")#博客算法2
def GeneratePointInCycle2(point_num, radius):for i in range(1, point_num+1):x = random.uniform(-radius, radius)y_max = math.sqrt(radius**2 - x**2)y = random.uniform(-y_max, y_max)plt.plot(x, y, '*', color = "black")#博客算法3
def GeneratePointInCycle3(point_num, radius):for i in range(1, point_num+1):theta = random.random()*2*pi;r = random.uniform(0, radius)x = r*math.sin(theta)y = r*math.cos(theta)plt.plot(x, y, '*', color = "black")#博客算法4
def GeneratePointInCycle4(point_num, radius):for i in range(1, point_num+1):theta = random.random()*2*pi;r = random.uniform(0, radius)x = math.sin(theta)* (r**0.5)y = math.cos(theta)* (r**0.5)plt.plot(x, y, '*', color = "black")      pi = np.pi
theta = np.linspace(0, pi*2, 1000)
R = 1
x = np.sin(theta)*R
y = np.cos(theta)*Rplt.figure(figsize=(6,6))
plt.plot(x,y,label = "cycle",color="red",linewidth=2)
plt.title("cycyle")
GeneratePointInCycle4(4000, R) #修改此处来显示不同算法的效果
plt.legend()
plt.show()

一、均匀生成三角形内的随机点

算法5(错误的)

对于三角形ABC和一点P,可以有如下的向量表示:

image

p点在三角形内部的充分必要条件是:1 >= u >= 0, 1 >= v >= 0, u+v <= 1。

先生成[0,1]的随机数u,然后生成[0, 1-u]内的随机数v,u、v生成后,就可以得到p点的坐标:

image

由下图可知,该算法生成的点在靠近A点处较浓密

如图所示,三角形ABC有与之对应的矩形ABNM,且矩形面积是三角形的两倍,三角形ADC和CMA全等,CDB和BNC全等。

我们可以先生成矩形ABNM内的随机点P,如果P刚好在三角形ABC中,那么符合要求;如果P不在三角形ABC中,P要么在AMC中,要么在BNC中,如图P在BNC中,我们求P关于BC中点的的中心对称点,该点一定在三角形中。P在AMC中同理。这样可以保重三角形外的点都可以均匀的一一对应到三角形内部。

后面的代码中,为了简化计算,我们假设AB是平行X轴的。
对于生成任意多边形内的随机点,我们可以把它分割成三角形,再来生成随机点。

算法5和算法6的代码如下(Python3.3):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as line
import random
import math#对应博客算法5
def GeneratePointInTriangle1(point_num, pointA, pointB, pointC):for i in range(1, point_num+1):u = random.uniform(0.0, 1.0)v = random.uniform(0.0, 1.0 - u)pointP = u*pointC + v*pointB + (1.0-u-v)*pointA;plt.plot(pointP[0], pointP[1], '*', color = "black")#根据向量叉乘计算三角形面积,参考 http://www.cnblogs.com/TenosDoIt/p/4024413.html
def ComputeTriangleArea(pointA, pointB, pointC):return math.fabs(np.cross(pointB - pointA, pointB - pointC)) / 2.0#判断点P是否在三角形ABC内,参考 http://www.cnblogs.com/TenosDoIt/p/4024413.html
def IsPointInTriangle(pointA, pointB, pointC, pointP):area_abc = ComputeTriangleArea(pointA, pointB, pointC)area_pab = ComputeTriangleArea(pointA, pointB, pointP)area_pbc = ComputeTriangleArea(pointP, pointB, pointC)area_pac = ComputeTriangleArea(pointP, pointA, pointC)return math.fabs(area_pab + area_pac + area_pbc - area_abc) < 0.000001#计算一个点关于某一点的中心对称点
def ComputeCentralSymmetryPoint(point_src, point_center):return np.array([point_center[0]*2-point_src[0], point_center[1]*2-point_src[1]])#对应博客算法6
def GeneratePointInTriangle2(point_num, pointA, pointB, pointC):for i in range(1, point_num+1):pointP = np.array([random.uniform(pointA[0], pointB[0]), random.uniform(pointA[1], pointC[1])])if not IsPointInTriangle(pointA, pointB, pointC, pointP):if pointP[0] > pointC[0]:pointP = ComputeCentralSymmetryPoint(pointP, np.array([(pointC[0] + pointB[0])/2, (pointC[1] + pointB[1])/2]))else:pointP = ComputeCentralSymmetryPoint(pointP, np.array([(pointC[0] + pointA[0])/2, (pointC[1] + pointA[1])/2]))plt.plot(pointP[0], pointP[1], '*', color = "black")        fig = plt.figure()
#三角形三个顶点
pointA = np.array([0,1])
pointB = np.array([3,1])
pointC = np.array([1,2])plt.plot([pointA[0],pointB[0]], [pointA[1],pointB[1]])
plt.plot([pointA[0],pointC[0]], [pointA[1],pointC[1]])
plt.plot([pointB[0],pointC[0]], [pointB[1],pointC[1]])GeneratePointInTriangle2(1500, pointA, pointB, pointC) #修改此处来显示不同算法的效果plt.ylim(0.5,2)
plt.xlim(0,3)
plt.show()

转自http://www.cnblogs.com/TenosDoIt/p/4025221.html

这篇关于均匀的生成圆和三角形内的随机点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/891544

相关文章

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

Python使用Pandas库将Excel数据叠加生成新DataFrame的操作指南

《Python使用Pandas库将Excel数据叠加生成新DataFrame的操作指南》在日常数据处理工作中,我们经常需要将不同Excel文档中的数据整合到一个新的DataFrame中,以便进行进一步... 目录一、准备工作二、读取Excel文件三、数据叠加四、处理重复数据(可选)五、保存新DataFram

SpringBoot生成和操作PDF的代码详解

《SpringBoot生成和操作PDF的代码详解》本文主要介绍了在SpringBoot项目下,通过代码和操作步骤,详细的介绍了如何操作PDF,希望可以帮助到准备通过JAVA操作PDF的你,项目框架用的... 目录本文简介PDF文件简介代码实现PDF操作基于PDF模板生成,并下载完全基于代码生成,并保存合并P

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

详解Java中如何使用JFreeChart生成甘特图

《详解Java中如何使用JFreeChart生成甘特图》甘特图是一种流行的项目管理工具,用于显示项目的进度和任务分配,在Java开发中,JFreeChart是一个强大的开源图表库,能够生成各种类型的图... 目录引言一、JFreeChart简介二、准备工作三、创建甘特图1. 定义数据集2. 创建甘特图3.

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文