示例:
假设我的画布分辨率为512x512。我试图让它的坐标如下:
第一步:将每个画布划分为笛卡尔坐标象限
_____ _____ | | | | 2 | 1 | |_____|_____| | | | | 3 | 4 | |_____|_____|
第二步:将每个象限划分为另外四个象限,并在旧象限后添加新的象限ID,如下所示:
_____ _____ _____ _____ | | | | | | 22 | 21 | 12 | 11 | |_____|_____|_____|_____| | | | | | | 23 | 24 | 13 | 14 | |_____|_____|_____|_____| | | | | | | 32 | 31 | 42 | 41 | |_____|_____|_____|_____| | | | | | | 33 | 34 | 43 | 44 | |_____|_____|_____|_____|
依此类推......
_____ _____ _____ _____ _____ _____ _____ _____ | | | | | | | | | | 222 | 221 | 212 | 211 | 122 | 121 | 112 | 111 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 223 | 224 | 213 | 214 | 123 | 124 | 113 | 114 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 232 | 231 | 242 | 241 | 132 | 131 | 142 | 141 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 233 | 234 | 243 | 244 | 133 | 134 | 143 | 144 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 322 | 321 | 312 | 311 | 422 | 421 | 412 | 411 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 323 | 324 | 313 | 314 | 423 | 424 | 413 | 414 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 332 | 331 | 342 | 341 | 432 | 431 | 442 | 441 | |_____|_____|_____|_____|_____|_____|_____|_____| | | | | | | | | | | 333 | 334 | 343 | 344 | 433 | 434 | 443 | 444 | |_____|_____|_____|_____|_____|_____|_____|_____|
直到象限数等于像素数
我试图在这里讨论如何实现此功能。
首先我想做一个函数,它将获得imageData
索引并返回它的象限id。但是这样每次调用函数时我都要做一些重(?)计算
或者从imageData
生成一个新数组,并在需要时通过索引访问其元素。
我确信有几种方法可以解决这个问题。递归方法很有趣,是否可以在更大的画布上?
我的朋友向我指出了下面的一段代码,它们做了一些非常相似的事情,但是我正在努力追踪这里发生的事情:
for (var y = 0; y < 512; y++)
for (var x = 0; x < 512; x++){
var s = "";
for (var b = 1; b <= 256; b *= 2){
var yb = y & b;
var xb = x & b;
s = String.fromCharCode(49 + (xb != yb) + yb / b * 2) + s;
}
}
我没有获得二进制数学或魔术49
数字?这是一串"1"
。用它作为起点是个好主意吗?
答案 0 :(得分:1)
假设您的图片有2 ^ p宽度==高度 像素的每个(x,y)坐标将具有在p位上编码的x和y 现在很好的是象限坐标只是x和y坐标的交错:
我们可以一点一点地写x,如下:
x = x(p-1) x(p-2) ... x2 x1 x0
和y as:
x = y(p-1) y(p-2) ... y2 y1 y0
然后q是x和y的交错:
q = x(p-1)y(p-1) x(p-2)y(p-2) ... x2y2 x1y1 x0y0
q是您要搜索的象限坐标,除了它的构建如下:
_____ _____
| | |
| 0 | 2 |
|_____|_____|
| | |
| 1 | 3 |
|_____|_____|
也许这个方案更加清晰:
x = 0 x = 1
_____________
| | |
| 00 | 10 | y = 0
|______|______|
| | |
| 01 | 11 | y = 1 (figures inside are in binary form)
|______|______|
实际上在上面的方案中,x由第一位编码,y由第二位编码。
更一般地说,最上面的一个象限只依赖于x中的高位和y中的高位。
你可以快速想象,如果x> 255我们在右边,否则我们在左边。同样适用于y:如果y <= 255我们在顶部,如果y> 255,我们不是。测试x> 255是否与测试x&amp; 256 =&gt;测试最重要的位是否设置。
事实上,如果你仔细考虑,所有分辨率都会出现完全相同的方案:比如我们在象限00上。现在看看我们是否在这个象限的左边或右边,我们将x与127进行比较。对于y 。所以实际上我们正在测试x和y的第二位。
所以你可以看到,两个两个,(x,y)点的交错位描述了象限[xp-1yp-1],[xp-2yp-2],......,[ x2y2],[x1y1],[x0y0]
现在您可以找到代码,http://jsbin.com/cavifito/1/edit?js,console
x,y - &gt;象限坐标函数是非常简单的位糖化:
var widthLog=10; // 2^10 = 1024 X 1024 picture
function getQuadrant(x,y) {
var q=0;
var mask = 1 << (widthLog-1) ;
for (var i=0; i<widthLog; i++) {
q<<=1;
q |= ((x & mask ) == mask);
q<<=1;
q |= ((y & mask) == mask);
x<<=1; y<<=1;
}
return q;
}
另一方面,象限坐标 - &gt; (x,y)函数是:
function getCoords(q, pt) {
var x=0, y=0;
var mask = 1 << (2*(widthLog)-1) ;
for (var i=0; i<widthLog; i++) {
x<<=1;
x |= ((q & mask)==mask);
q<<=1;
y<<=1;
y |= ((q & mask)==mask);
q<<=1;
}
pt.x = x;
pt.y = y;
}
这是一个方便的功能,可以将象限变为人类可读的数字(每个数字代表一个象限)。
function quadrantToNum ( q ) {
var res = 0;
var bitIndex = 2*widthLog ;
var mask = 3 << (bitIndex);
while ( mask ) {
var qi = (q & mask) >> bitIndex ;
bitIndex -=2 ;
mask >>= 2;
res = 10*res + qi ;
}
return res;
}
widthLog = 2 / width = 4的结果:
00 02 20 22
01 03 21 23
10 12 30 32
11 13 31 33
widthLog = 3 / width = 8的结果:
000 002 020 022 200 202 220 222
001 003 021 023 201 203 221 223
010 012 030 032 210 212 230 232
011 013 031 033 211 213 231 233
100 102 120 122 300 302 320 322
101 103 121 123 301 303 321 323
110 112 130 132 310 312 330 332
111 113 131 133 311 313 331 333
答案 1 :(得分:0)
如果x坐标是(big-endian)二进制中的abcdefghi
且y坐标是二进制的jklmnopqr
,那么base-4中表示的象限数是(达到一致)交织ajbkcldmenfogphqir
的象限重新编号。这里有一些比特笨拙的C代码用于32位坐标(为了其他目的而编写)。
uint64_t expand(int32_t x) {
uint64_t n = (uint32_t)((int64_t)x - INT32_MIN);
n = (n | (n << 16)) & UINT64_C(0x0000ffff0000ffff);
n = (n | (n << 8)) & UINT64_C(0x00ff00ff00ff00ff);
n = (n | (n << 4)) & UINT64_C(0x0f0f0f0f0f0f0f0f);
n = (n | (n << 2)) & UINT64_C(0x3333333333333333);
return (n | (n << 1)) & UINT64_C(0x5555555555555555);
}
int32_t unexpand(uint64_t n) {
n &= UINT64_C(0x5555555555555555);
n = (n | (n >> 1)) & UINT64_C(0x3333333333333333);
n = (n | (n >> 2)) & UINT64_C(0x0f0f0f0f0f0f0f0f);
n = (n | (n >> 4)) & UINT64_C(0x00ff00ff00ff00ff);
n = (n | (n >> 8)) & UINT64_C(0x0000ffff0000ffff);
return (int32_t)((int64_t)(uint32_t)(n | (n >> 16)) + INT32_MIN);
}
uint64_t z_rank(struct Point p) {
return expand(p.x) | (expand(p.y) << 1);
}
struct Point z_unrank(uint64_t n) {
return (struct Point){unexpand(n), unexpand(n >> 1)};
}
如果由于某种原因需要字符串,那么一次剥离两个低位,就像这样。
var s = "";
while (n > 0) {
s = (n & 3) + s;
n >>= 2;
}