2009-07-10 94 views
2

假设我有一个使用16x16像素的基于图块的系统。你将如何找出由浮点像素单元定义的矩形覆盖哪些图块?使用x,y,w,h像素坐标查找矩形覆盖的图块的坐标

用于例如,

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) 

回答

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) 

我现在明确地检查边缘情况下,一个,但请注意,某些时候浮点比较可能看起来并不明显,结果可能不如预期。

+0

这失败上下面的情况中的问题指出: (X,Y)= 16.0,16.0 (W,H)= 16.1, 16.1 – Mathieu 2009-07-11 18:24:39

0

您可以尝试对准你通过瓷砖的宽度除以之前像素坐标OT整数:

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

这也许可以浓缩有点多,但在这里你去。

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 
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