如何将网格行列索引转换为笛卡尔坐标系并实现坐标访问
实现笛卡尔坐标访问网格元素的方案
问题背景
我生成了一个带内切圆的方形网格,圆内元素值为1,方形其他区域为0,现有实现代码如下:
import numpy as np from typing import List, Tuple def collect(x: int, y: int, sigma: float =3.0) -> List[Tuple[int, int]]: """ 创建某点邻域内的点集合 """ neighborhood = [] X = int(sigma) for i in range(-X, X + 1): Y = int(pow(sigma * sigma - i * i, 1/2)) for j in range(-Y, Y + 1): neighborhood.append((x + i, y + j)) return neighborhood def plotter(sigma: float =3.0) -> None: """ 绘制二进制网格 """ arr = np.zeros([sigma * 2 + 1] * 2) points = collect(int(sigma), int(sigma), sigma) # 将圆内(含边界)的像素值设为1 for p in points: R, C = p arr[R][C] = 1 print(arr) grid = plotter(10) print(grid) print(grid.shape)
我希望进行如下改进:当前通过grid[R][C](R为行索引、C为列索引)访问网格元素,如何将R、C索引转换为笛卡尔坐标系?在sigma=10的场景下,坐标系范围应为[-10, 10],中心为(0,0)。最终要实现通过如grid[-2][3]这样的笛卡尔坐标直接访问对应位置的元素值(0或1)。
我尝试了如下象限判断的代码,但存在语法问题:
for x in range(len(grid)): for y in range(len(grid[x])): if (x > len(grid)/2 and y < len(grid)/2): print ("lies in First quadrant") elif (x < len(grid)/2 and y >len(grid)/20): print ("lies in Second quadrant") elif (x < len(grid)/2 and y > len(grid)/2): print ("lies in Third quadrant") elif (x > len(grid)/2 0 and y < len(grid)/2): print ("lies in Fourth quadrant") elif (x == len(grid)//2 and y < len(grid)/2): print ("lies at positive y axis") elif (x == len(grid)//2 and y < len(grid)/2): print ("lies at negative y axis") elif (y == len(grid)//2 and x < len(grid)/2): print ("lies at negative x axis") elif (y == len(grid)//2 and x > len(grid)/2): print ("lies at positive x axis") elif((x == len(grid)//2 and y == len(grid)/2): print ("lies at origin")
核心逻辑
要实现笛卡尔坐标直接访问,关键是建立数组索引与笛卡尔坐标的一一映射:
- 网格边长为
2*sigma+1,数组的中心索引为sigma(比如sigma=10时,网格是21x21,中心索引是10),对应笛卡尔坐标的原点(0,0) - 笛卡尔坐标转数组索引的公式:
- 行索引
R = sigma + y_cartesian(笛卡尔y轴对应数组行方向:y=-10→R=0,y=0→R=10,y=10→R=20) - 列索引
C = sigma + x_cartesian(笛卡尔x轴对应数组列方向:x=-10→C=0,x=0→C=10,x=10→C=20)
- 行索引
- 由于numpy原生数组不支持自定义索引规则,我们可以用类封装网格,通过
__getitem__方法实现笛卡尔坐标的解析与转换
实现代码
import numpy as np from typing import List, Tuple def collect(x: int, y: int, sigma: float =3.0) -> List[Tuple[int, int]]: """生成某点邻域内的点集合""" neighborhood = [] X = int(sigma) for i in range(-X, X + 1): Y = int(pow(sigma * sigma - i * i, 1/2)) for j in range(-Y, Y + 1): neighborhood.append((x + i, y + j)) return neighborhood class CartesianGrid: def __init__(self, sigma: float =3.0): self.sigma = int(sigma) self.size = 2 * self.sigma + 1 self.grid = np.zeros((self.size, self.size), dtype=int) # 生成圆内点并赋值为1 center_idx = self.sigma points = collect(center_idx, center_idx, self.sigma) for R, C in points: self.grid[R][C] = 1 def __getitem__(self, coords): # 支持grid[y_cart, x_cart]或grid[y_cart][x_cart]的访问方式 if isinstance(coords, tuple): y_cart, x_cart = coords else: # 处理单索引情况,返回整行 y_cart = coords return [self[y_cart, x] for x in range(-self.sigma, self.sigma+1)] # 转换为数组索引 R = self.sigma + y_cart C = self.sigma + x_cart # 检查坐标是否合法 if not (0 <= R < self.size and 0 <= C < self.size): raise IndexError(f"笛卡尔坐标({y_cart}, {x_cart})超出网格范围[-{self.sigma}, {self.sigma}]") return self.grid[R][C] # 测试sigma=10的场景 grid = CartesianGrid(10) # 访问笛卡尔坐标(-2, 3) print(grid[-2, 3]) # 访问中心原点(0, 0) print(grid[0, 0]) # 访问边缘坐标(10, 10) print(grid[10, 10]) # 访问整行y=-5 print(grid[-5])
原尝试代码的问题
你写的象限判断代码存在多处问题:
- 语法错误:
elif (x > len(grid)/2 0 and y < len(grid)/2)多了多余的0;elif((x == len(grid)//2 and y == len(grid)/2)缺少右括号 - 逻辑笔误:
y >len(grid)/20应为y > len(grid)/2 - 重复条件:两个
x == len(grid)//2 and y < len(grid)/2的分支重复,导致后续的负y轴判断永远不会触发 - 逻辑混淆:直接用数组索引判断象限,没有先将索引转换为笛卡尔坐标,导致象限判断完全错误
内容的提问来源于stack exchange,提问作者user19811784
相关产品推荐
相关产品推荐

