如果我们有两个yearly-monthly
对象代表一个矩形的两个角,那么就是一个区域:
> dput(test)
structure(list(user_id = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1), time = structure(c(1498262400,
1500595200, 1496534400, 1499126400, 1494547200, 1501200000, 1494374400,
1484524800, 1503100800, 1485820800), class = c("POSIXct", "POSIXt"
)), plan = c("monthly", "monthly", "monthly", "monthly", "yearly",
"yearly", "yearly", "yearly", "yearly", "monthly")), .Names = c("user_id",
"time", "plan"), row.names = c(NA, -10L), class = "data.frame")
如何在这两个向量之间生成一个随机位置(它创建的矩形中的任何位置)?
我的想法是,与Vector2
和Vector2 corner1 = new Vector2(-5, -5);
Vector2 corner2 = new Vector2(5, 5);
的距离以及x1
和x2
的距离相同,并从该范围中执行随机值。
但是如果第一个向量是y1
而第二个向量是y2
怎么办?我将不得不添加一个负距离,我是对的吗?
最有效的方法是什么?
答案 0 :(得分:1)
这是一些示例代码,我将解释它的作用。首先你需要找到x1和x2之间的距离,y1和y2之间的距离得到总距离之间的随机值,然后减去该距离的一半,所以如果我们有总距离10,我们会得到一个随机数(0 - 10)减去5我们得到-5到5的范围。
int x1 = 5;
int x2 = -5;
int y1 = 5;
int y2 = -5;
Random rand = new Random();
int distanceX = Math.abs(x1 - x2);
int distanceY = Math.abs(y1 - y2);
int offsetX = (x1 + x2)/2;
int offsetY = (y1 + y2)/2;
int randX = (rand.nextInt(distanceX) - (distanceX/2)) + offsetX;
int randY = (rand.nextInt(distanceY) - (distanceY/2)) + offsetY;
System.out.println(randX + " " + randY);
您只需要使用Vector 2
distanceX = Math.abs(corner1.x - corner2.x);
...等 您可能需要根据Vector2包含的内容将整数更改为浮点数。
float randX = ((rand.nextFloat()*distanceX) - (distanceX/2));
答案 1 :(得分:1)
x和y的计算使用完全相同的方法,所以现在让我们只关注x。
Random rand = new Random();
float x1 = Math.min(corner1.x, corner2.x);
float x2 = Math.max(corner1.x, corner2.x);
float deltaX = x2 - x1;
float offsetX = rand.nextFloat() * deltaX;
float randomX = x1 + offsetX;
这有效地对x值进行排序,以便将较小的值称为x1
,将较大的值称为x2
,并计算它们之间的差异并将其存储在deltaX
中。< / p>
然后使用java.util.Random.nextFloat()
计算随机值,该值返回0.0(包括)和1.0(不包括)之间的值,并将随机值乘以delta。这给了我们一个随机值offsetX
,它介于零和两个值之间的总差异之间。
最后,我们必须将此随机偏移量添加到最小x值x1,以便随机点确实位于矩形内,介于x1(包括)和x2(不包括)之间。
请注意,我已将此直接写入Stack Overflow而未进行任何测试,因此您很有可能编写一些单元测试以确保您使用的任何方法都适用于各种值(负数) ,正面,两者的混合,零坐标等)。
(顺便说一下,我假设Vector2
类来自libgdx API,因为核心Java 8 API中没有这样的类。)
即使没有使用Math.min
和Math.max
对值进行排序,算法仍然有效(我已经通过单元测试确认了这一点),因此您可以简化方法:
public static float pickRandomPointBetween(float corner1, float corner2) {
if (corner1 == corner2) {
return corner1;
}
float delta = corner2 - corner1;
float offset = rand.nextFloat() * delta;
return corner1 + offset;
}
同样的方法适用于一对x或y值,并且无论corner1
的值是否小于,大于或等于corner2
的值,它都将起作用。请注意,检查corner1 == corner2
只是一个效率快捷方式,如果您知道您永远不会(或几乎从不)将相等的值传递给此方法,则可以删除它。 (单元测试通过或不通过快捷方式。)
要完成您的要求,您可以在两个矩形角内创建一个随机点,如下所示:
float randomX = pickRandomPointBetween(corner1.x, corner2.x);
float randomY = pickRandomPointBetween(corner1.y, corner2.y);
Vector2 randomPoint = new Vector2(randomX, randomY);
但为了保持你的代码整洁,这个逻辑可能应该放在一个专用的方法中,并给出一个明确的名称。