我代表我的2D空间(考虑一个窗口),其中每个像素显示为2D数组中的单元格。即,100x100窗口由相同尺寸的阵列表示。
现在在窗口中给出一个点,如果我绘制一个半径为r
的圆,我想找到该圆中的所有点。
我想我会检查半径周围的方形区域中的每个点,side = 2*r
,如果它位于圆圈中或不存在。我会用正常的距离公式吗?
因此,可能如下:
for (x=center-radius ; x<center+radius ; x++){
for (y=center-radius ; y<center+radius; y++) {
if (inside) {
// Do something
}
}
}
它会满足我的目的吗?我可以加快速度吗?
答案 0 :(得分:13)
它能满足我的目的吗?
对于你的100x100,是的。
我可以加快速度吗?
是。例如,您可以:
代码:
for (x = xCenter - radius ; x <= xCenter; x++)
{
for (y = yCenter - radius ; y <= yCenter; y++)
{
// we don't have to take the square root, it's slow
if ((x - xCenter)*(x - xCenter) + (y - yCenter)*(y - yCenter) <= r*r)
{
xSym = xCenter - (x - xCenter);
ySym = yCenter - (y - yCenter);
// (x, y), (x, ySym), (xSym , y), (xSym, ySym) are in the circle
}
}
}
这大约是加速的4倍。
JS tests了解此处提供的解决方案。对称性是我电脑上最快的。三角函数presented by Niet the Dark Absol非常聪明,但它涉及昂贵的数学函数,如sin
和acos
,这会对性能产生负面影响。
答案 1 :(得分:6)
您可以绕过条件检查的需要:
for(x=center-radius; x<center+radius; x++) {
yspan = radius*sin(acos((center-x)/radius));
for(y=center-yspan; y<center+yspan; y++) {
// (x,y) is inside the circle
}
}
如果需要,您可以round(yspan)
。
答案 2 :(得分:2)
您可以通过尽可能多地在循环外计算来获得加速。也没有必要做毕达哥拉斯定理平方根...只是保持一切平方。最后一次加速可以通过仅对圆的四分之一进行数学计算(因为它是对称的)...当找到匹配时,你只需将其复制到其他三个季度。
radiusSquared = radius*radius;
rightEdge = centerX+radius;
bottomEdge = centerY+radius;
for(x = centerX; x <= rightEdge; x++){
xSquared = x*x;
for(y = centerY; y <= bottomEdge; y++){
ySquared = y*y;
distSquared = xSquared+ySquared;
if(distSquared <= radiusSquared){
// Get positions for the other quadrants.
otherX = centerX-(x-centerX);
otherY = centerY-(y-centerY);
// Do something for all four quadrants.
doSomething(x, y);
doSomething(x, otherY);
doSomething(otherX, y);
doSomething(otherX, otherY);
}
}
}
答案 3 :(得分:0)
( ( xPos - centreX)^2 + (yPos - centreY)^2 ) <= radius^2
其中xPos
和yPos
是您要检查的点的坐标,然后该点位于您的圈内。
答案 4 :(得分:0)
似乎是对的。你可以通过找到minY然后从当前X的-rangeY到+ rangeY做DoSomething来使它快一点。
for(dx=0;dx<rad; dx++)
{
rangeY = 0;
while (!inside(x, rangeY)) //inside == check if x*x + y*y <r*r
rangeY++;
for(y=center-rangeY;y<center+rangeY;y++)
{
DoSomething(centerX - dx, y);
DoSomething(centerX + dx, y); }
}
答案 5 :(得分:0)
要获取圆圈内所有点的列表,您应该使用:
var radius = 100, r2 = radius * radius;
var circle = [];
for (var dx = -radius; dx <= radius; dx++) {
var h = Math.sqrt(r2 - dx * dx) | 0;
for (var dy = -h; dy <= h; dy++) {
circle.push([dx, dy])
}
}
请参阅http://jsperf.com/circles/2,了解其他解决方案的分析。
答案 6 :(得分:-2)
我知道这个问题有一个公认的答案,但我有一个更简单的解决方案。其他答案让我感到困惑,因为我不知道center
,xcenter
,ycenter
是什么,而且函数背后的数学原因是无法解释的,我跋涉发现数学解决方案我自己的。
我的等式非常简单:
cx
是圆圈中心的x点
cy
是圆圈中心的y点
rad
是圆的半径
我的等式/函数所做的是通过计算给定半径的每个可能点来计算点,并且它增加并减去cx
和cy
的偏移。
//Creates an array filled with numbers
function range(begin, end) {
for (var i = begin, arr = []; i < end; i++) {
arr.push(i);
}
return arr;
}
function calculateAllPointsInCircle(cx, cy, rad) {
var rang = range(-rad, rad + 1);
var px = [];
var py = [];
var xy = [];
for (var i = 0; i < rang.length; i++) {
var x = cx + rang[i];
px.push(x);
for (var l - rang.length - 1; l > 0; l--) {
var y = cy + rang[l];
if (!py.indexOf(y)===-1) { py.push(y); }
xy.push(x+','+y);
}
}
return {
x: x,
y: y,
xy: xy
}
}
表现远高于其他答案:http://jsperf.com/point-in-circle/4
您可以使用数学方法检查我的方程式,该方程将验证给定点是否在圆圈内x*x + y*y <= r*r
或x^2 + y^2 <= r^2
编辑 - 超级压缩ES6版本:
function range(begin, end) {
for (let i = begin; i < end; ++i) {
yield i;
}
}
function calculateAllPointsInCircle(cx, cy, rad) {
return {
x: [cx + i for (i of range(-rad, rad + 1))],
y: [cy + i for (i of range(-rad, rad + 1))]
};
}