【问题标题】:Get spiral index from location in 1d, 3d从 1d、3d 中的位置获取螺旋索引
【发布时间】:2020-10-22 13:10:50
【问题描述】:

基于已知的 {x,y,z,...} 坐标,我正在寻找位置的索引。提供了一个二维 (2d) 解决方案here。 我现在正在尝试将其扩展到其他两个维度:1d 和 3d(并可能推广到更高维度)。

对于 1d,我最终得到了以下算法(Matlab 代码),其中步行在轴的右侧和左侧之间交替:

n = 20; %number of values
X = -n/2:n/2; %X values (1d)

%we want 'p' the index of the location:
for i=1:numel(X)
    if(X(i) > 0)
        p(i) = 2*X(i)-1;
    else
        p(i) = -2*X(i);
    end
end

产生以下索引:

但是,我很难将索引应该如何在 3d 中进行可视化(即索引如何通过 3d 中的节点)。我主要对 C/C++ 解决方案感兴趣,但任何其他语言都可以。

编辑 反映 @Spektre cmets 和建议:我的目标是找到一组 3d 坐标 {x,y,z} 的索引。这可以看作是将 3d 坐标映射到一组索引 (1d) 的一种方式。螺旋提供了一种在 2d 中执行此类任务的便捷方式,但不能在 3d 中扩展。

【问题讨论】:

  • 嗯,你的主要问题是你使用术语“螺旋”,它是 2D 对象/构造......我不认为它可以扩展到不同的维度(仍然被称为螺旋)。甚至您的 1D 也是有问题的(最好将其称为 1D 切割螺旋)。因此,要移动到 3D 或更多,您需要首先确定这些东西应该做什么:(用单折线/曲线覆盖(超)体积什么形状(弯曲,矩形)?但是这不会像螺旋线圈一样螺旋半径/尺寸增加的超球体/超立方体...
  • 另外,您可能想研究 空间填充曲线,例如 2D/3D hilbert curve 可能与您想要实现的目标不同...那么什么图案/形状3D 你想描述更多吗?
  • @Spektre 感谢您提供有趣的链接。在超球面上均匀分布点可能会解决我的问题。但是,我的目标是找到反问题:即找到索引而不是位置 {x,y,z,...}),我需要这个 ot 快。更准确地说,我想将一组坐标 {x,y,z,...} 映射到 1D 中,螺旋索引在 2D 中提供了一种方便(而且非常快速)的解决方案。但是,正如您所说,这不能扩展到 nD,我将在主题中反映这一点。
  • @Spektre 回复非常有趣!我会去 cube_map 听起来很适合我的问题!谢谢你,准备好后我会标记你的答案。
  • 我将 cmets 移入 answer 并添加了更多内容...我还稍微清除了 cmets... 另外我认为您应该在谷歌上搜索 butterfly shuffling索引/地址的位反转 ...我觉得他们可以在没有任何测角学的情况下轻松转换为您的模式(但它只是感觉所以我可能错了)

标签: algorithm


【解决方案1】:

以及您选择线/正方形/立方体状螺丝线圈来填充您的 1D/2D/3D 空间,如下所示:

我愿意:

  1. 实施line/square/cube 地图

    这些将映射在一维索引ix 和已知“半径”的坐标之间。这将类似于:

    查看成员函数:ix2dirdir2ix,它们在索引和方向向量之间进行映射。不需要存储表面数据你只需要这些转换函数。但是,您需要调整它们,以便点/索引的顺序代表您想要的模式......在 1D 中,2D 很容易,但对于 3D,我会选择类似于立方体上的表面螺旋之类的东西:

    不要忘记以不同的方式处理 3D 中的偶数和奇数螺钉(镜像),以便螺钉在正确的位置连接...

    为了完整起见,立方体贴图就像 3D 系统中的单个螺钉,它固定立方体的表面,并且可以在方向矢量 dir 和 1D 索引 ix 之间来回转换。它用于加速图形和几何中的算法......我认为它的第一个用途是用于 Bump Mapping 快速矢量归一化。通过使用 cube_map,您可以轻松地在任何维度上进行类比,甚至是 2D、1D,您只需使用 square_map 和 Line_map 而无需任何算法更改。在转换为立方体/正方形地图后,我在 OBB 2D/3D 上对其进行了测试,算法保持不变,只是向量具有不同数量的坐标(没有它们,算法非常不同)。

  2. 创建/导出方程/LUT,描述半径覆盖的点数(包括螺钉内部)

    所以函数返回r 拧在一起的线圈中的点数。这将是一个系列,因此方程应该很容易推导/推断。让我们称之为:

    points = volume(r);
    
  3. 现在转换ix -> (x,y,z...)

    首先找出你的ix是哪个半径r

    volume(r) <= ix < volume(r+1)
    

    简单的 for 循环可以,但更好的是 二分搜索r。然后将您的ix 转换为线/正方形/立方体地图中的索引iy

    iy = ix-volume(r);
    

    现在只需使用ix2dir(iy) 函数来获取您的点位置...

  4. 反向转换(x,y,z...) -&gt; ix

    r = max(|x|,|y|,|z|,...)
    iy = dir2ix(x,y,z,...)
    ix = volume(r-1) + iy
    

【讨论】:

    猜你喜欢
    • 2012-04-15
    • 2022-10-15
    • 1970-01-01
    • 2012-07-27
    • 2013-12-14
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多