如何判断坐标点是否落在任意角度旋转的NxN网格线上?
任意旋转角度网格线命中判断实现方案
核心思路
我们可以通过坐标逆变换的思路抹平旋转带来的复杂度:把待判断的点反向旋转网格的偏移角度,得到该点在未旋转的标准正交网格下的坐标,再判断坐标是否靠近标准网格的横向/纵向基准线即可。
具体实现
首先需要注意:浮点数运算存在精度误差,不能直接使用==判断相等,需要引入容差参数控制判定的宽松度。
import math # 可配置参数 BOX_SIZE = 2 # 单个方格的边长 ROTATION_DEG = 45 # 网格旋转角度(角度制) EPS = 1e-3 # 判定容差,数值越大判定范围越宽,可根据线宽调整 # 预计算旋转参数,避免重复运算 theta = math.radians(ROTATION_DEG) cos_theta = math.cos(theta) sin_theta = math.sin(theta) def on_grid(x: float, y: float) -> bool: # 1. 对点做逆旋转变换,得到标准正交网格下的坐标 u = x * cos_theta + y * sin_theta v = -x * sin_theta + y * cos_theta # 2. 计算u、v到最近的网格线的距离 distance_u = abs(u - round(u / BOX_SIZE) * BOX_SIZE) distance_v = abs(v - round(v / BOX_SIZE) * BOX_SIZE) # 3. 只要任意一个方向距离小于容差,即认为落在网格线上 return distance_u < EPS or distance_v < EPS
逻辑说明
- 逆旋转计算:正向旋转θ度的矩阵是
[[cosθ, -sinθ], [sinθ, cosθ]],反向旋转对应θ取负值,代入后就得到代码中的u、v计算逻辑 - 容差参数
EPS:可以根据实际场景的网格线宽度调整,例如线宽为0.1时,设为0.05即可刚好覆盖整条线的范围 - 适配所有角度:当旋转角度为0时,就是普通横竖网格的判定逻辑;旋转角度为45度时,和你原有45度场景的判定逻辑兼容
- 原点偏移适配:如果你的网格基准原点不是全局坐标(0,0),只需在逆旋转前先将点坐标减去基准原点坐标即可。
原有45度代码的局限性
你之前的代码本质是判断x - y是否为BOX_SIZE的整数倍,仅对应旋转45度的网格中某一方向的线条,既没有覆盖另一方向的45度线条,也没有适配其他旋转角度的坐标映射关系。
内容的提问来源于stack exchange,提问作者Robert Townley
相关产品推荐
相关产品推荐

