因此,我正在创建一个虚拟地图软件,它本质上是将坐标分解成区域。区域由定义的边界坐标列表(使区域的外部边缘相互连接的坐标)组成。
有了这个软件,我需要随机选择每个区域的点,居住在区域边界坐标内。每个区域是不同的,可以有更多甚至更少的边,但至少有3个边,但没有最大边。
目前,我有一个解决方案,我只需生成随机数,直到数字在该区域内。但是,由于区域的数量(在很小到很大的值范围内有很大的不同边界坐标)&点的数量(可能是1-100+),这种策略证明效率很低(需要很长时间才能完成运行)。我想听听人们的想法,甚至是关于如何优化它的经验/工作,这样它就不会那么缓慢了。
我创建了一个小型演示应用程序来更好地解释情况.
#include "stdafx.h"
#include <vector>
#include <random>
const int GenerateRandomNumberBetween(
const int start,
const int end)
{
const int stable_end = ((end < start) ? start : end);
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_int_distribution<int> distribution(start, stable_end);
return distribution(generator); // generates number in the range the distribution value
}
class Area
{
public:
Area()
{
// Define a primitive area for this example, but please note that this is a very basic area, and most areas are acctually much larger and have many more sides...
// This sample area creates a triangle.
//(-2, 2);
boundaries_x_coordinates.push_back(-2);
boundaries_y_coordinates.push_back(2);
//(2, 2);
boundaries_x_coordinates.push_back(2);
boundaries_y_coordinates.push_back(2);
//(-2, 2);
boundaries_x_coordinates.push_back(-2);
boundaries_y_coordinates.push_back(-2);
}
const bool InArea(
const int x,
const int y)
{
// This function works just fine, and can be ignored... I just included it to show that we check if the new coordinates are indeed within the given Area.
int minX = 0;
int maxX = 0;
int minY = 0;
int maxY = 0;
for (int i = 0; i < boundaries_x_coordinates.size(); i++)
{
if (boundaries_x_coordinates[0] < minX)
{
minX = boundaries_x_coordinates[0];
}
if (boundaries_x_coordinates[0] > maxX)
{
maxX = boundaries_x_coordinates[0];
}
if (boundaries_y_coordinates[1] < minY)
{
minY = boundaries_y_coordinates[1];
}
if (boundaries_y_coordinates[1] > maxY)
{
maxY = boundaries_y_coordinates[1];
}
}
if (boundaries_x_coordinates.size() < 3)
{
return false;
}
else if (x < minX || x > maxX || y < minY || y > maxY)
{
return false;
}
else
{
size_t i, j, c = 0;
for (i = 0, j = boundaries_x_coordinates.size() - 1; i < boundaries_x_coordinates.size(); j = i++)
{
if (((boundaries_y_coordinates[i] > y) != (boundaries_y_coordinates[j] > y)) &&
(x < (boundaries_x_coordinates[j] - boundaries_x_coordinates[i]) * (y - boundaries_y_coordinates[i]) /
(boundaries_y_coordinates[j] - boundaries_y_coordinates[i]) + boundaries_x_coordinates[i]))
{
c = !c;
}
}
return (c == 0) ? false : true;
}
}
std::vector<int> GenerateRandomPointInsideArea()
{
int minX = 0, maxX = 0, minY = 0, maxY = 0;
for (int i = 0; i < boundaries_x_coordinates.size(); i++)
{
if (boundaries_x_coordinates[i] < minX)
{
minX = boundaries_x_coordinates[i];
}
if (boundaries_x_coordinates[i] > maxX)
{
maxX = boundaries_x_coordinates[i];
}
if (boundaries_y_coordinates[i] < minY)
{
minY = boundaries_y_coordinates[i];
}
if (boundaries_y_coordinates[i] > maxY)
{
maxY = boundaries_y_coordinates[i];
}
}
// The problem is here, this do while statement takes a tremendous of time to execute in realistic Areas simply because it takes a
// long time to generate all the random coordinates inside the area (sometimes could be as little as 1 coordinate set, sometimes could be 100).
int random_x = 0;
int random_y = 0;
do
{
random_x = GenerateRandomNumberBetween(minX, maxX);
random_y = GenerateRandomNumberBetween(minY, maxY);
} while (!InArea(random_x, random_y));
std::vector<int> random_coordinates;
random_coordinates.push_back(random_x);
random_coordinates.push_back(random_y);
return random_coordinates;
}
private:
std::vector<int> boundaries_x_coordinates;
std::vector<int> boundaries_y_coordinates;
};
int main()
{
Area* sample_area = new Area();
std::vector<int> random_coordinates = sample_area->GenerateRandomPointInsideArea();
printf("Random Coordinate: (%i, %i)\n", random_coordinates[0], random_coordinates[1]);
// Pause to see results.
system("pause");
return 0;
}样本输出将输出区域内的坐标集.在这个特定的例子中,我第一次运行它的输出:
Random Coordinate: (-1, 1)我读过,把这个区域划分成三角形,然后选择一个随机的三角形,在这个三角形内生成一个随机坐标是最好的解决方案。但我不知道如何用一个区域坐标集合来生成三角形,如果我能做到的话.为什么我不直接用那个技术来选择一个随机坐标?
-编辑
多亏了马特·蒂默曼,我才得以解决这个问题,进一步研究了这个问题,并应用了马特在下文中所解释的大部分内容。
如果其他人在这个问题上有困难,下面是我想出的(主要是Matt提到的,有一些变化)。
1)将多边形三角剖分成多个三角形,在我的例子中,我需要一个简单而轻量级的C++解决方案,并提供0图形界面。我设法在网上找到了一个叫做三角网的工人阶级,Triangulation.shtml。
2)利用加权概率随机选取三角形。如果一个三角形占原始多边形的80%,那么它应该被选择大约80%的时间。
在这个过程中,我做了一些研究,找到了一些变化,其中最简单的就是我选择的(如下面所示)。
3)一旦你选择了一个三角形,就会在这个三角形内产生一个一致随机点。这可以通过使用这一公式来实现:
P = (1 - sqrt(r1)) * A + (sqrt(r1) * (1 - r2)) * B + (sqrt(r1) * r2) * C其中r1和r2是0到1之间的随机数,如本文第4.2节所述.http://www.cs.princeton.edu/~funk/tog02.pdf
你完蛋了,这就够了!
或者,您可以继续使用Matt的建议,这两种方法在任何情况下似乎都是完美的。这是..。
3)复制三角形,并与原三角形生成平行四边形。使用下列公式:
M=(A+C)/2
P4=M-(B-M)
Where...
M is a midpoint in the original triangle where the copied triangle will connect.
A,B,C are the 3 vertices in the original triangle
P4 is the new point the forms the parallelogram with the other 3 points of the original triangle.4)从平行四边形内部产生一个随机数,在平行四边形的最小值、最大值x和y值之间生成一个随机x和y值,直到你在平行四边形内。5)如果随机坐标位于复制的三角形内部,则将其映射到原三角形中的对应点,如果没有完成。
发布于 2016-10-14 00:45:09
https://stackoverflow.com/questions/40033166
复制相似问题