提问人:Famosi 提问时间:11/3/2021 更新时间:11/20/2021 访问量:193
给定一个网格,找出哪些方块被半径为 R 的圆形物体占据
Given a Grid, find which Blocks are occupied by a circular object of radius R
问:
从标题中可以猜到,我正在尝试解决以下问题。
给定一个大小为 NxN 的网格和一个半径为 R 的圆形物体 O,中心 C 位于 (x_c, y_c),找出哪些块被 O 占据。
示例如下图所示:
在该示例中,我预计输出为 [1,2,5,6]。
如果有人有建议或资源,我将不胜感激。
答:
-2赞
Mario Abbruscato
11/5/2021
#1
我使用了 Python3 和 OpenCv,但它可以用任何语言完成。
源:
import cv2
import numpy as np
import math
def drawgrid(im,xv,yv,cx,cy,r):
#params: image,grid_width,grid_height,circle_x,circle_y,circle_radius
cellcoords = set() #i use set for unique values
h,w,d = im.shape
#cell width,height
cew = int(w/xv)
ceh = int(h/yv)
#center of circle falls in this cells's coords
nx = int(cx / cew )
ny = int(cy / ceh )
cellcoords.add((nx,ny))
for deg in range(0,360,1):
cirx = cx+math.cos(deg)*r
ciry = cy+math.sin(deg)*r
#find cell coords of the circumference point
nx = int(cirx / cew )
ny = int(ciry / ceh )
cellcoords.add((nx,ny))
#grid,circle colors
red = (0,0,255)
green = (0,255,0)
#drawing red lines
for ix in range(xv):
lp1 = (cew * ix , 0)
lp2 = (cew * ix , h)
cv2.line(im,lp1,lp2,red,1)
for iy in range(yv):
lp1 = (0 , ceh * iy)
lp2 = (w , ceh * iy)
cv2.line(im,lp1,lp2,red,1)
#drawing green circle
cpoint = (int(cx),int(cy))
cv2.circle(im,cpoint,r,green)
print("cells coords:",cellcoords)
imw=500
imh=500
im = np.ndarray((imh,imw,3),dtype="uint8")
drawgrid(im,9,5, 187,156 ,50)
cv2.imshow("grid",im)
cv2.waitKey(0)
输出:单元格坐标:{(3, 2), (3, 1), (2, 1), (2, 2), (4, 1)}
cells coords are zero based x,y.
So ...
1° cell top left is at (0,0)
2° cell is at (1,0)
3° cell is at (2,0)
1° cell of 2° row is at (0,1)
2° cell of 2° row is at (1,1)
3° cell of 2° row is at (2,1)
and so on ...
Getting cell number from cell coordinates might be fun for you
评论
1赞
Matt Timmermans
11/20/2021
不适用于非常大的圆圈,不会返回圆盘内部的大多数单元格。也很慢。
0赞
Mario Abbruscato
11/20/2021
显然,如果您需要它们,只需在找到的单元格之间添加单元格即可。为了加快这个过程,你可以在 for 循环语句中使用更大的角度步骤。或者更确切地说,所有那些距离圆心小于圆半径的单元格。
1赞
Matt Timmermans
11/21/2021
实际上,没有一个角度步长可以可靠地完成工作。你总是会错过一个正方形的一角,它戳在两点之间。
0赞
Matt Timmermans
11/20/2021
#2
查找受影响的行范围:
miny = floor(y_c-r);
maxy = ceil(y_c+r)-1;
对于每一行,通过将圆与具有最大交集的水平线相交来找到列的范围。有3种情况:
for (y=miny; y<=maxy; ++y) {
if (y+1 < y_c)
ytest = y+1;
else if (y > y_c)
ytest = y;
else
ytest = y_c;
// solve (x-x_c)^2 + (ytest-y_c)^2 = r^2
ydist2 = (ytest-y_c)*(ytest-y_c);
xdiff = sqrt(r*r - ydist2);
minx = floor(x_c - xdiff);
maxx = ceil(x_c + xdiff)-1;
for (x=minx; x<=maxx; ++x)
output(x,y);
}
评论