【问题标题】:Distribute points on mesh according to density根据密度在网格上分布点
【发布时间】:2017-04-14 03:51:40
【问题描述】:

给定一个(可能是开放的)具有密度纹理的网格和一些点,我需要根据网格上的密度分布这些点。

到目前为止,我已经提出了几种解决方案,其中一些有效,而另一些则无效。我尝试的算法之一是通过弹簧连接点并模拟分布直到平衡(或直到解决方案适合用户需要)。来源Retiling Polygonal Surfaces 不幸的是,对于更多的点(> 2k)来说,这有点慢,所以我需要一个可行的解决方案来处理更多的点。

我已经有了一些想法,但我想知道是否有一些标准解决方案。我尝试了谷歌,但我使用的关键字(分布密度离散)只出现了处理除我之外的其他问题的页面。因此,如果您指出要搜索的正确词,我已经很高兴了。

【问题讨论】:

    标签: algorithm mesh approximation


    【解决方案1】:

    一般来说,在具有任意密度函数的任意空间中,您可以通过rejection sampling 得到一个合理的近似值。

    • 找到您的最大密度D
    • 随机选择一个点p
    • [0,D)范围内选择一个随机数r
    • 如果p 处的密度大于r,请接受p 作为您的点之一。

    我不确定这是否容易适用于您的案例。在网格上生成随机的、均匀分布的点本身就是一个棘手的问题。我能想到的唯一解决方案是计算网格中每个三角形的面积,随机选择一个概率与其面积成正比的三角形,然后在三角形内选择一个random point。我相信您可以在 N 个三角形上以 O(logN) 的时间进行此选择。

    但考虑到您可能会丢弃大部分这些点,这可能会比您当前的方法更糟糕,因为网格足够大并且密度函数足够令人不快(即最大值远大于平均值) .


    像任何一种随机抽样一样,它需要相当多的点才能开始类似于底层分布;一小组点可能看起来或多或少是随机的。但是您也许可以通过某种准随机的点放置方法来解决这个问题(即使是大集合,它也可能会产生更好的结果)。

    想到的一件事是上述方法和@BlackBear 算法的混合。您可以计算每个三角形的面积和平均密度,并使用它来决定每个三角形必须包含多少点。然后,要将点实际放置在三角形内,请使用拒绝采样方法。

    【讨论】:

    • 我已经尝试过这种方法,并且对目前的结果感到满意。但我怀疑这只有在有足够的种子点时才有效。
    • 你是对的。我想到了如何解决这个问题;检查我的编辑。
    【解决方案2】:

    这是我的想法:

    1. 将密度纹理分割成相等的矩形部分;
    2. 为每个部分计算一个介于 0.0 和 1.0 之间的数字,其中 1.0 表示“点的最高密度”,而 0.0 表示相反,“根本没有点”;
    3. 通过将要放置的点的总数除以所有平均值的总和,计算对应于 1.0 值的点数;
    4. 那你就知道每个矩形要画多少个点,所以要均匀地画出来;

    现在,矩形越小,得到的结果就越精确。我做了一个小测试程序(C# 使用慢速方法,即位图上的 GetPixel 和 SetPixel),这是结果,假设 10k 点,256x256 px 图像。图片显示了算法在 2^2、10^2、50^2 和 90^2 部分的工作:

    这是基准:

    parts   time
    ------------------------
    2      00:00:00.7957087
    10     00:00:00.6713345
    50     00:00:00.5873524
    90     00:00:00.4153544
    

    【讨论】:

    • 这个分布一旦映射到网格上会不会有点偏斜?
    • @NickBarnes:是的,它会的。但是密度纹理也会倾斜,所以点会跟随纹理
    • 我已经考虑过了,但有一个问题:边缘可见伪影。看看你的照片,你会看到线条。但也许我会为此找到解决方案。主要目标是:“看起来好像”,因此它不需要 100% 准确:)。除此之外,我认为该方法也可以直接用于三角形(尽管它可能有点棘手)。跨度>
    • @Nobody:我认为出现这些伪影是因为点太多,图像太小
    • 可能是,但我有一个类似的算法,它创建了相反的伪影(边缘上有更多点),我认为这是因为有硬边。我认为以某种方式从离散的矩形(或三角形)中抽象出来并在没有这些边界的通用表面上进行计算会很好,但我不知道。
    【解决方案3】:

    根据任意函数分布点云的问题与dithering 灰度图像到黑白图像是同构的。 algorithms 都具有与 O(N) 成正比的运行时复杂度(其中 N 是原始图像/位图/网格/任何内容中的点数),使用拜耳矩阵 ordered dithering 等简单方法仅执行一次浮点比较每点,更复杂的 error diffusion 方法运行时间更像 O(24N),但产生的结果更好,伪影更少。

    使用简单的高斯密度函数,简单的拜耳矩阵方法可以在小至 32x32 矩阵的情况下产生出奇的好结果:

    给定相关矩阵,可以直接生成基于矩阵的有序抖动:

    matrix = generate_bayer(32);
    for (y=0; y<height; y++) {
      for (var x=0; x<width; x++) {
        i = x % matrix.length;
        j = y % matrix.length;
    
        function_val = gaussian(x, y);  #returns a value 0<=x<=1
        scaled_val = function_val * matrix.length * matrix.length;  #scale to the max element in the matrix
        if (scaled_val > matrix[j][i]) {
          draw_pixel(x, y);
        }
      }
    }
    

    生成矩阵稍微复杂一些,但这里有一种迭代方法,用于边长为 2 的幂的矩阵:

    //size should be a power of 2, and is the length of a side of the matrix
    function generate_bayer(size) {
      base = [[0, 2],
              [3, 1]];
      old_matrix = base;
      mult = 4;
    
      //successively double the size of the matrix, using the previous one as the base
      while (old_matrix.length < size) {
        //generate a new matrix of the proper dimensions
        new_size = old_matrix.length * 2;
        matrix = new Array[new_size][new_size];
    
        for (y=0; y<old_matrix.length; y++) {
          for (x=0; x<old_matrix[y].length; x++) {
            //fill in the new 4x4 submatrix
            matrix[y*2]    [x*2]     = old_matrix[y][x] + (mult * base[0][0]);
            matrix[y*2]    [x*2 + 1] = old_matrix[y][x] + (mult * base[0][1]);
            matrix[y*2 + 1][x*2]     = old_matrix[y][x] + (mult * base[1][0]);
            matrix[y*2 + 1][x*2 + 1] = old_matrix[y][x] + (mult * base[1][1]);
          }
        }
    
        mult *= 4;
        old_matrix = matrix;
      }
      return old_matrix;
    }
    

    【讨论】:

    • 一目了然,我不知道如何将黑点的数量限制在所需的阈值。你能详细说明一下吗?
    • 你可以通过将函数乘以一个标量来控制点密度的尺度,所以往回推,你可以推导出一个函数F(f, m) = P,其中f是密度函数, m 是标量乘数,P 是点数。然后你只需要用你想要的 P 来求解 m 的函数。由于分析地表达这个函数可能很困难,你可能需要使用优化方法(即二分搜索)来求解 m。跨度>
    • 另外,如果函数结果不是连续的并且获得精确的字符数对您很重要,您可以随机拒绝点以将数字调整为您想要的数字。
    • 拒绝会扭曲结果分布,所以我想只有当点数已经接近所需数量时才可行。无论如何,这是一个好主意。不幸的是,我不再处理这个问题,但如果我有更多时间,我很想尝试这个。
    猜你喜欢
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多