具有纹理 UV 映射的 HEALPix
HEALPix with texture UV mapping
我找到了 HEALpix 算法的实现 this is the dokumentation
而且输出看起来非常好。
下图显示了纬度/经度转换为 HEALpix 区域。
x 轴从 0 到 2 * pi。 y 轴从 0 到 pi。灰色表示以灰色编码的 HEALpix 像素。
Nside = 1
Nside = 2
Nside = 4
Nside = 8
不同的灰度值是我必须使用的纹理的 ID。这意味着,每个 HEALpix 像素代表一个纹理。缺少的部分是每个 HEALpix 像素内的 UV 映射,如下所示:
nSide = 1 带 UV 贴图
现在我正在使用函数:
void ang2pix_ring( const long nside, double theta, double phi, long *ipix)
这给了我正确的纹理 ID。但我不知道如何计算每个 HEALpix 像素的 UV 贴图。
有没有办法计算 HEALpix 像素 lat/lon 坐标中的所有四个角?或者更好的是直接计算 UV 坐标?
顺便说一句:我正在使用 RING 方案。但是如果NESTED方案计算起来更简单我也会改成那个。
经过大量研究,我找到了解决这个问题的方法:
首先,我将方案更改为 NESTED。使用 NESTED 方案和非常高的 nSide 值 (8192),
的返回值
void ang2pix_ring( const long nside, double theta, double phi, long *ipix)
函数返回一个 long 值,其中 UV 坐标可以通过以下方式读出:
第26位到第30位表示级别0(仅12个HEALPix像素)。
通过使用更高的级别,从 30 到 26 的位 - (级别 * 2) 代表 HEALPix 像素。
剩下的 26 - (level * 2) - 1 直到 bit 1 以下列方式编码 UV texture-coordinates:
奇数位收缩一次代表U坐标,偶数位收缩一次代表V坐标。
要将这些 UV-coordinates 的响应收缩值除以 pow(2, (26 - level * 2) / 2) 的值。
代码超过1000字:
unsigned long ignoreEverySecondBit(unsigned long value, bool odd, unsigned int countBits)
{
unsigned long result = 0;
unsigned long mask = odd == true ? 0b1 : 0b10;
countBits = countBits / 2;
for (int i = 0; i < countBits; ++i)
{
if ((value & mask) != 0)
{
result += std::pow(2, i);
}
mask = mask << 2;
}
return result;
}
//calculate the HEALPix values:
latLonToHealPixNESTED(nSide, theta, phi, &pix);
result.level = level;
result.texture = pix >> (26 - level * 2);
result.u = static_cast<float>(ignoreEverySecondBit(pix, true, 26 - level * 2));
result.v = static_cast<float>(ignoreEverySecondBit(pix, false, 26 - level * 2));
result.u = result.u / pow(2, (26 - level * 2) / 2);
result.v = result.v / pow(2, (26 - level * 2) / 2);
当然还有几张图片来展示结果。蓝色值代表textureID,红色值代表U-coordinate,绿色值代表V-coordinate:
0级
1 级
2 级
3 级
4 级
我希望这个解决方案也能帮助到其他人。
我找到了 HEALpix 算法的实现 this is the dokumentation 而且输出看起来非常好。
下图显示了纬度/经度转换为 HEALpix 区域。 x 轴从 0 到 2 * pi。 y 轴从 0 到 pi。灰色表示以灰色编码的 HEALpix 像素。
Nside = 1
Nside = 2
Nside = 4
Nside = 8
不同的灰度值是我必须使用的纹理的 ID。这意味着,每个 HEALpix 像素代表一个纹理。缺少的部分是每个 HEALpix 像素内的 UV 映射,如下所示:
nSide = 1 带 UV 贴图
现在我正在使用函数:
void ang2pix_ring( const long nside, double theta, double phi, long *ipix)
这给了我正确的纹理 ID。但我不知道如何计算每个 HEALpix 像素的 UV 贴图。 有没有办法计算 HEALpix 像素 lat/lon 坐标中的所有四个角?或者更好的是直接计算 UV 坐标?
顺便说一句:我正在使用 RING 方案。但是如果NESTED方案计算起来更简单我也会改成那个。
经过大量研究,我找到了解决这个问题的方法:
首先,我将方案更改为 NESTED。使用 NESTED 方案和非常高的 nSide 值 (8192),
的返回值void ang2pix_ring( const long nside, double theta, double phi, long *ipix)
函数返回一个 long 值,其中 UV 坐标可以通过以下方式读出:
第26位到第30位表示级别0(仅12个HEALPix像素)。
通过使用更高的级别,从 30 到 26 的位 - (级别 * 2) 代表 HEALPix 像素。
剩下的 26 - (level * 2) - 1 直到 bit 1 以下列方式编码 UV texture-coordinates:
奇数位收缩一次代表U坐标,偶数位收缩一次代表V坐标。 要将这些 UV-coordinates 的响应收缩值除以 pow(2, (26 - level * 2) / 2) 的值。
代码超过1000字:
unsigned long ignoreEverySecondBit(unsigned long value, bool odd, unsigned int countBits)
{
unsigned long result = 0;
unsigned long mask = odd == true ? 0b1 : 0b10;
countBits = countBits / 2;
for (int i = 0; i < countBits; ++i)
{
if ((value & mask) != 0)
{
result += std::pow(2, i);
}
mask = mask << 2;
}
return result;
}
//calculate the HEALPix values:
latLonToHealPixNESTED(nSide, theta, phi, &pix);
result.level = level;
result.texture = pix >> (26 - level * 2);
result.u = static_cast<float>(ignoreEverySecondBit(pix, true, 26 - level * 2));
result.v = static_cast<float>(ignoreEverySecondBit(pix, false, 26 - level * 2));
result.u = result.u / pow(2, (26 - level * 2) / 2);
result.v = result.v / pow(2, (26 - level * 2) / 2);
当然还有几张图片来展示结果。蓝色值代表textureID,红色值代表U-coordinate,绿色值代表V-coordinate:
0级
1 级
2 级
3 级
4 级
我希望这个解决方案也能帮助到其他人。