Geometry 二维点分布展开算法

Geometry 二维点分布展开算法,geometry,2d,distribution,point,Geometry,2d,Distribution,Point,在2D像素阵列中,我需要一个高效的算法,该算法将选择最分散的像素的p% 通过选择点,然后反复调整靠得太近的点的位置,可以自适应地实现这一点。但这并不高效,因为它需要多次迭代和距离计算 它不一定是完美的,只需要尽可能有效地避免点群集。这样如何: 发现从每个点到另一点的距离总和。所以点A的和距离是dist(A,B)+dist(A,C)+dist(A,D)+ 对这些总距离进行排序 删除距离总和最小的点,直到达到所需的百分比 这可能足够准确,但如果不准确,您始终可以将步骤3替换为: 删除总和最小的点,如

在2D像素阵列中,我需要一个高效的算法,该算法将选择最分散的像素的p%

通过选择点,然后反复调整靠得太近的点的位置,可以自适应地实现这一点。但这并不高效,因为它需要多次迭代和距离计算

它不一定是完美的,只需要尽可能有效地避免点群集。

这样如何:

  • 发现从每个点到另一点的距离总和。所以点A的和距离是dist(A,B)+dist(A,C)+dist(A,D)+
  • 对这些总距离进行排序
  • 删除距离总和最小的点,直到达到所需的百分比
  • 这可能足够准确,但如果不准确,您始终可以将步骤3替换为:

    删除总和最小的点,如果需要删除更多点以达到所需百分比,请返回步骤1

    等等。现在我想知道。你是想从一组给定的点中找出分布最广的点,还是想从一个给定的数组中找出分布最广的点?这是完全不同的…但仍然非常困难。

    根据每个像素与所有其他像素的接近程度,计算每个像素的“密度”值如何。然后,重复移除最“密集”的像素,直到低于列表中剩余的p%

    您需要进行距离计算,以确定任意给定两点之间的密度,最多两次。第一次是在构建原始列表时-每个像素都需要与其他像素进行比较。第二种是当你从列表中删除一个像素时——你必须根据列表中剩余的每个像素计算删除的像素。这是为了说明每个像素被移除时密度值的变化-例如,相邻的两个像素的值非常高,但一旦移除一个,其余的像素的值可能非常低

    一些快速伪代码(注意,在本例中,高密度区域的数字较低)


    如果内存比计算时间更重要,则还可以将任意两点之间的距离存储在简单的二维阵列中。此外,与简单的距离不同,让距离计算成指数可能会有所帮助——这将避免类似两点几乎彼此重叠,但远离其他任何点,并且两者都能通过的情况。

    迭代扫雷船洪水填充方法将直观地显示出来

  • 对于每个单元格,找到两个最近的点并记录这两个距离的乘积
  • 具有最高产物的单元是连接到最远点的单元

  • 你想要一个泊松分布,但这很棘手。进行搜索会发现很多关于如何高效搜索的学术论文:

    Ooh!这个怎么样

    (由于我不知道你的矩阵是正方形还是其他什么,所以我假设它是正方形。)

    假设您有一个1000x1000阵列,您希望将47个点放入其中(我选择47,因此这是一个不寻常的数字,不能“很好地”匹配)

    取ceil(sqrt(47))…得到一个值(7)。因此,我们制作一个7x7的正方形,用47个像素填充它(有些是空白的),然后想象一下将其放置在阵列的一角

    现在,根据小(7x7)阵列到大阵列(1000x1000)的位置,将这些像素转换到新位置。一个简单的方程应该可以做到这一点…对于X坐标,例如:

    xBigArrayIndex = xSmallArrayIndex * 1000 / 7;
    
    然后你的像素将超级分散!而且它又好又快


    唯一的缺点是,只有当你的正方形以理想的间距开始时,这种方法才能完美地工作……如果你天真地填充它(从左上角开始,穿过,等等),你最终会得到一个稍微不理想的排列……因为转换后的像素不会完全到达大数组的右下角。但也许这已经足够好了?如果不是,可能是问题的较小子集更容易处理?

    您可以使用凸包算法,排除该算法将计算并重复的点,只要它达到您的p%标准, 或

    执行凸包算法步骤,检查外壳和外壳内部的点是否符合标准100%-p%

    这里有一些凸壳的演示

    这里你有更多的信息
    谢谢大家的回答

    最好的解决方案似乎是使用“预构建的构建块”:具有已选择单元的nxn阵列,并用这些单元覆盖像素阵列

    例如,覆盖率为12.5%的4 x 4阵列应为:

    0 0 1 0
    0 0 0 0
    1 0 0 0
    0 0 0 0
    
    覆盖率为6.3%:

    0 0 0 0
    0 1 0 0
    0 0 0 0
    0 0 0 0
    
    要获得这两个块之间的覆盖率百分比,只需根据到目前为止的总体实际覆盖率百分比的运行计数在这两个块之间交替。要覆盖的宽度不是4的倍数,请使用一些3x3块。为了更有效地覆盖更大的区域,只需使用更大的块

    这可以有效地覆盖整个阵列,而无需距离计算或浮点运算。

    像素的“最分散”选择是其Delaunay三角剖分由等边三角形组成的集合。通过将像素阵列分割为一组长方体,每个长方体的长度均大于其宽度,可以找到导致此三角剖分的点集。每个框为最终像素集贡献5个像素(每个角一个,加上框中心的中心节点)。诀窍是找到多少行和列的框将给你这个1:sqrt(3)的比率。不经过推导,这里是如何得到的:

    std::vector<PixelIndices> PickPixels(int width, int height, float percent)
    {
      int total_pixels = width*height;
      int desired_pixel_count = (int)total_pixels*percent;
    
      // split the region up into "boxes" with 4 corner nodes and a center node.
      // each box is sqrt(3) times taller than it is wide.
    
      // calculate how many columns of boxes
      float a = 1.155*height/(float)width;
      float b = .577*height/(float)width + 1;
      float c = 1 - desired_pixel_count;
      int num_columns = (int)((-b + sqrt(b*b -4*a*c))/(2*a));
    
      // Now calculate how many rows
      int num_rows = .577*height*num_columns/(float)width;
    
      // total number of pixels
      int actual_pixel_count = 2*num_rows*num_columns + num_rows + num_columns + 1;
    
      std::cout << "  Total pixels: " << total_pixels << std::endl;
      std::cout << "       Percent: " << percent << std::endl;
      std::cout << "Desired pixels: " << desired_pixel_count << std::endl;
      std::cout << " Actual pixels: " << actual_pixel_count << std::endl;
      std::cout << "   Number Rows: " << num_rows << std::endl;
      std::cout << "Number Columns: " << num_columns << std::endl;
    
      // Pre-allocate space for the pixels
      std::vector<PixelIndices> results;
      results.reserve(actual_pixel_count);
    
      // Now get the pixels, my integer math is probably wrong here, didn't test
      //  (didn't even finish, ran out of time)
      for (int row = 0; row <= num_rows; row++)
      {
        int row_index = row*height/num_rows;
    
        // Top of box
        for (int col = 0; col <= num_columns; col++)
        {
          int col_index = col*width/num_columns;
          results.push_back(PixelIndices(row_index, col_index));
        }
    
        // Middle of box
        if (row != num_columns)
        {
          for (int col = 0; col < num_columns; col++)
          {
             // I'll leave it to you to get this, I gotta go!
          }
        }
      }
    
      return results;
    }
    
    std::矢量像素(整数宽度、整数高度、浮点百分比)
    {
    int总像素=宽度*高度;
    int所需像素计数=(i
    
    std::vector<PixelIndices> PickPixels(int width, int height, float percent)
    {
      int total_pixels = width*height;
      int desired_pixel_count = (int)total_pixels*percent;
    
      // split the region up into "boxes" with 4 corner nodes and a center node.
      // each box is sqrt(3) times taller than it is wide.
    
      // calculate how many columns of boxes
      float a = 1.155*height/(float)width;
      float b = .577*height/(float)width + 1;
      float c = 1 - desired_pixel_count;
      int num_columns = (int)((-b + sqrt(b*b -4*a*c))/(2*a));
    
      // Now calculate how many rows
      int num_rows = .577*height*num_columns/(float)width;
    
      // total number of pixels
      int actual_pixel_count = 2*num_rows*num_columns + num_rows + num_columns + 1;
    
      std::cout << "  Total pixels: " << total_pixels << std::endl;
      std::cout << "       Percent: " << percent << std::endl;
      std::cout << "Desired pixels: " << desired_pixel_count << std::endl;
      std::cout << " Actual pixels: " << actual_pixel_count << std::endl;
      std::cout << "   Number Rows: " << num_rows << std::endl;
      std::cout << "Number Columns: " << num_columns << std::endl;
    
      // Pre-allocate space for the pixels
      std::vector<PixelIndices> results;
      results.reserve(actual_pixel_count);
    
      // Now get the pixels, my integer math is probably wrong here, didn't test
      //  (didn't even finish, ran out of time)
      for (int row = 0; row <= num_rows; row++)
      {
        int row_index = row*height/num_rows;
    
        // Top of box
        for (int col = 0; col <= num_columns; col++)
        {
          int col_index = col*width/num_columns;
          results.push_back(PixelIndices(row_index, col_index));
        }
    
        // Middle of box
        if (row != num_columns)
        {
          for (int col = 0; col < num_columns; col++)
          {
             // I'll leave it to you to get this, I gotta go!
          }
        }
      }
    
      return results;
    }