给定任何特定的矩形(x1,y1) - (x2,y2),如何在其周边生成随机点?
我已经提出了一些方法,但似乎应该采用一种非常规范的方法来实现它。
首先,我以为我会在矩形内生成一个随机点并将其夹到最近的一侧,但分布看起来并不均匀(点几乎从不落在短边上)。其次,我随机选了一个侧面然后在那边选择了一个随机点。代码有点笨拙而且也不统一 - 但是恰恰相反(短边有相同的机会获得积分作为长边)。最后,我一直在考虑将矩形“展开”成一行并在线上选择一个随机点。我认为这会产生统一的分布,但我想在走上这条道路之前我会问这里。
答案 0 :(得分:14)
你的最后一种方法就是我在阅读你的标题时所建议的。去吧。如果您选择一个概率与边长成比例的一侧,那么您的第二种方法(随机选择一侧)将起作用。
答案 1 :(得分:4)
这是Objective-c中正在展开的想法,似乎有效,不是吗:)。
//randomness macro
#define frandom (float)arc4random()/UINT64_C(0x100000000)
#define frandom_range(low,high) ((high-low)*frandom)+low
//this will pick a random point on the rect edge
- (CGPoint)pickPointOnRectEdge:(CGRect)edge {
CGPoint pick = CGPointMake(edge.origin.x, edge.origin.y);
CGFloat a = edge.size.height;
CGFloat b = edge.size.width;
CGFloat edgeLength = 2*a + 2*b;
float randomEdgeLength = frandom_range(0.0f, (float)edgeLength);
//going from bottom left counter-clockwise
if (randomEdgeLength<a) {
//left side a1
pick = CGPointMake(edge.origin.x, edge.origin.y + a);
} else if (randomEdgeLength < a+b) {
//top side b1
pick = CGPointMake(edge.origin.x + randomEdgeLength - a, edge.origin.y + edge.size.height );
} else if (randomEdgeLength < (a + b) + a) {
//right side a2
pick = CGPointMake(edge.origin.x + edge.size.width, edge.origin.y + randomEdgeLength - (a+b));
} else {
//bottom side b2
pick = CGPointMake(edge.origin.x + randomEdgeLength - (a + b + a), edge.origin.y);
}
return pick;
}
答案 2 :(得分:3)
如果通过'周边的随机点'你实际上意味着'从周长的均匀随机分布中选择的点',那么是的,你的'展开'方法是正确的。
但是应该提到的是,你以前的两种方法都限定是一个“周边的随机点”,只是非均匀分布。
答案 3 :(得分:2)
你最后的建议对我来说似乎最好。
将周长视为[长度为2*a + 2*b
]的单个长行,在其中生成一个随机数,计算该点在矩形上的位置[假设它从某个任意点开始,它不会这个问题。
它只需要一个随机,因此相对便宜[随机有时是昂贵的操作]。
它也是统一的,并且微不足道地证明它,偶然会有机会让你到达每个点[假设随机函数是均匀的,当然]。
答案 4 :(得分:1)
例如:
static Random random = new Random();
/** returns a point (x,y) uniformly distributed
* in the border of the rectangle 0<=x<=a, 0<=y<=b
*/
public static Point2D.Double randomRect(double a, double b) {
double x = random.nextDouble() * (2 * a + 2 * b);
if (x < a)
return new Point2D.Double(x, 0);
x -= a;
if (x < b)
return new Point2D.Double(a, x);
x -= b;
if (x < a)
return new Point2D.Double(x, b);
else
return new Point2D.Double(0, x-a);
}
答案 5 :(得分:1)
这是我的均匀分布实现(假设x1&lt; x2和y1&lt; y2):
void randomPointsOnPerimeter(int x1, int y1, int x2, int y2) {
int width = abs(x2 - x1);
int height = abs(y2 - y1);
int perimeter = (width * 2) + (height * 2);
// number of points proportional to perimeter
int n = (int)(perimeter / 8.0f);
for (int i = 0; i < n; i++) {
int x, y;
int dist = rand() % perimeter;
if (dist <= width) {
x = (rand() % width) + x1;
y = y1;
} else if (dist <= width + height) {
x = x2;
y = (rand() % height) + y1;
} else if (dist <= (width * 2) + height) {
x = (rand() % width) + x1;
y = y2;
} else {
x = x1;
y = (rand() % height) + y1;
}
// do something with (x, y)...
}
}
答案 6 :(得分:0)
这是我在Javascript中的实现
function pickPointOnRectEdge(width,height){
var randomPoint = Math.random() * (width * 2 + height * 2);
if (randomPoint > 0 && randomPoint < height){
return {
x: 0,
y: height - randomPoint
}
}
else if (randomPoint > height && randomPoint < (height + width)){
return {
x: randomPoint - height,
y: 0
}
}
else if (randomPoint > (height + width) && randomPoint < (height * 2 + width)){
return {
x: width,
y: randomPoint - (width + height)
}
}
else {
return {
x: width - (randomPoint - (height * 2 + width)),
y: height
}
}
}
答案 7 :(得分:0)