Python 查找由具有x、y、w、h像素坐标的矩形覆盖的瓷砖的坐标

Python 查找由具有x、y、w、h像素坐标的矩形覆盖的瓷砖的坐标,python,algorithm,math,geometry,coordinates,Python,Algorithm,Math,Geometry,Coordinates,假设我有一个使用16x16像素的基于平铺的系统。如何找出由浮点像素单位定义的矩形所覆盖的平铺 例如 rect(x=16.0,y=16.0, w=1.0, h=1.0) -> tile(x=1, y=1, w=1, h=1) rect(x=16.0,y=16.0, w=16.0, h=16.0) -> tile(x=1, y=1, w=1, h=1) (still within same tile) rect(x=24.0,y=24.0, w=8.0, y=8.0) -> (x=

假设我有一个使用16x16像素的基于平铺的系统。如何找出由浮点像素单位定义的矩形所覆盖的平铺

例如

rect(x=16.0,y=16.0, w=1.0, h=1.0) -> tile(x=1, y=1, w=1, h=1)
rect(x=16.0,y=16.0, w=16.0, h=16.0) -> tile(x=1, y=1, w=1, h=1) (still within same tile)
rect(x=24.0,y=24.0, w=8.0, y=8.0) -> (x=1,y=1,w=1,h=1) (still within same tile)
rect(x=24.0,y=24.0, w=8.1, y=8.1) -> (x=1,y=1,w=2,h=2)
唯一可靠的方法是使用循环。有更好的办法吗?除以16,在边缘情况下给出了错误的答案。下面是我在python中使用的一些示例代码:

#!/usr/bin/env python

import math

TILE_W = 16
TILE_H = 16

def get_tile(x,y,w,h):
    t_x = int(x / TILE_W)
    t_x2 = t_x
    while t_x2*TILE_W < (x+w):
        t_x2 += 1
    t_w = t_x2-t_x

    t_y = int( y / TILE_H)
    t_y2 = t_y
    while t_y2*TILE_H < (y+h):
        t_y2 += 1
    t_h = t_y2-t_y

    return t_x,t_y,t_w,t_h

(x,y) = 16.0,16.0
(w,h) = 1.0, 1.0
assert get_tile(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0,16.0
(w,h) = 15.0, 15.0
assert get_tile(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0,16.0
(w,h) = 16.0, 16.0
assert get_tile(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0,16.0
(w,h) = 16.1, 16.1
assert get_tile(x,y,w,h) == (1,1,2,2)

(x,y) = 24.0, 24.0
(w,h) = 1.0, 1.0
assert get_tile(x,y,w,h) == (1,1,1,1)

(x,y) = 24.0, 24.0
(w,h) = 8.0, 8.0
assert get_tile(x,y,w,h) == (1,1,1,1)

(x,y) = 24.0, 24.0
(w,h) = 8.1, 8.1
assert get_tile(x,y,w,h) == (1,1,2,2)

(x,y) = 24.0, 24.0
(w,h) = 9.0, 9.0
assert get_tile(x,y,w,h) == (1,1,2,2)
#/usr/bin/env python
输入数学
瓷砖W=16
瓷砖H=16
def get_tile(x,y,w,h):
t_x=int(x/TILE_W)
t_x2=t_x
当t_x2*TILE_W<(x+W)时:
t_x2+=1
t_w=t_x2-t_x
t_y=int(y/TILE_H)
t_y2=t_y
当t_y2*瓦片高度<(y+H)时:
t_y2+=1
t_h=t_y2-t_y
返回t_x,t_y,t_w,t_h
(x,y)=16.0,16.0
(w,h)=1.0,1.0
断言get_tile(x,y,w,h)==(1,1,1,1)
(x,y)=16.0,16.0
(w,h)=15.0,15.0
断言get_tile(x,y,w,h)==(1,1,1,1)
(x,y)=16.0,16.0
(w,h)=16.0,16.0
断言get_tile(x,y,w,h)==(1,1,1,1)
(x,y)=16.0,16.0
(w,h)=16.1,16.1
断言get_tile(x,y,w,h)==(1,1,2,2)
(x,y)=24.0,24.0
(w,h)=1.0,1.0
断言get_tile(x,y,w,h)==(1,1,1,1)
(x,y)=24.0,24.0
(w,h)=8.0,8.0
断言get_tile(x,y,w,h)==(1,1,1,1)
(x,y)=24.0,24.0
(w,h)=8.1,8.1
断言get_tile(x,y,w,h)==(1,1,2,2)
(x,y)=24.0,24.0
(w,h)=9.0,9.0
断言get_tile(x,y,w,h)==(1,1,2,2)

这是通过测试用例的一个,告诉我是否有任何边缘用例

TILE_W = TILE_H = 16

from math import floor, ceil

def get_tile2(x,y,w,h):
    x1 = int(x/TILE_W)
    y1 = int(y/TILE_H)
    x2 = int((x+w)/TILE_W)
    y2 = int((y+h)/TILE_H)
    if (x+w)%16 == 0: #edge case
        x2-=1
    if (y+h)%16 == 0: #edge case
        y2-=1
    tw = x2-x1 + 1
    th = y2-y1 + 1
    return x1, y1, tw, th

(x,y) = 16.0, 16.0
(w,h) = 1.0, 1.0
assert get_tile2(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0, 16.0
(w,h) = 15.0, 15.0
assert get_tile2(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0, 16.0
(w,h) = 16.0, 16.0
assert get_tile2(x,y,w,h) == (1,1,1,1)

(x,y) = 16.0, 16.0 
(w,h) = 16.1, 16.1
assert get_tile2(x,y,w,h) == (1,1,2,2)

我现在正在明确检查边缘情况,但请注意浮点比较有时可能看起来不明显,结果可能不符合预期。

在除以平铺宽度之前,您可以尝试将像素坐标与整数对齐:

xlower = int(floor(x))
xupper = int(ceil(x + w))

这也许可以再浓缩一点,但给你

def get_tile(x,y,w,h):

    x1 = int(x / TILE_W)
    x2 = (x + w) / TILE_W

    y1 = int(y / TILE_H)
    y2 = (x + w) / TILE_H

    if int(x2) == x2:
        x2 = int(x2 - 1)
    else:
        x2 = int(x2)

    if int(y2) == y2:
        y2 = int(y2 - 1)
    else:
        y2 = int(y2)

    tw = x2 - x1 + 1
    th = y2 - y1 + 1

    return x1, y1, tw, th

Matt的错误修复解决方案:

from __future__ import division
import math

TILE_W = TILE_H = 16

def get_tile(x,y,w,h):
    x1 = int(math.floor(x/TILE_W))
    x2 = int(math.ceil((x + w)/TILE_W))
    y1 = int(math.floor(y/TILE_H))
    y2 = int(math.ceil((y + h)/TILE_H))
    return x1, y1, x2-x1, y2-y1

这在问题中所述的以下情况下失败:(x,y)=16.0,16.0(w,h)=16.1,16.1对于相同的结果,天花板/地板解决方案不是更优雅吗?这是我过去一直使用的解决方案。当瓷砖边缘正好是瓷砖宽度/高度的倍数时,地板和天花板就不合适了。埃里克:你能举一个你正在考虑的边缘情况的例子吗?这里发布的两个解决方案都通过了问题中所述的案例。