找到被矩形覆盖的瓷砖坐标,矩形的像素坐标为x,y,w,h

2 投票
4 回答
1110 浏览
提问于 2025-04-15 12:48

假设我有一个基于瓷砖的系统,使用的是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)

4 个回答

0

你可以试着在用瓦片宽度除之前,把你的像素坐标调整为整数。

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

这是一个可以通过你测试用例的代码,如果有任何特殊情况,请告诉我。

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)

我现在正在明确检查这些特殊情况,但要注意,浮点数比较有时候可能不太明显,结果可能和你预期的不一样。

1

马特的解决方案,包含了错误修复:

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

撰写回答