定期空间细分

时间:2009-09-08 22:20:57

标签: algorithm

我正在编写一个应用程序,它将N维轴对齐的边界框细分为较小的N维边界框,我需要一个能够做到这一点的算法。
例如:

在1维中,“边界框”仅为长度
例如{Min = 0,Max = 100}
这将细分为
{Min = 0,Max = 50}且{Min = 50,Max = 100}

在2维中,“边界框”是正方形
例如{Min = [0,0],Max = [100,100]}
将分为
{Min = [0,0],Max = [50,50]}
{Min = [0,50],Max = [50,100]}
{Min = [50,0],Max = [100,50]}
{Min = [50,50],Max = [100,100]}

依此类推,我需要的只是对算法的描述,语言并不特别重要,因为一旦我知道如何去做,我就可以把它翻译成选择的语言(在这种情况下是C#)

编辑::回答评论中的问题:

  • 细分必须始终相等(如 在例子中)
  • 边界是 浮动点,因此两个可分解性不是问题

3 个答案:

答案 0 :(得分:1)

将其分解为两个问题:迭代“最小”点的网格,并为最小点构建一个小方框。

对于您的第二种情况,{[0,0],[100,100]},deltaX = 50,deltaY = 50。网格是

[0,   0]
[0,  50]
[50,  0]
[50, 50]

从第一列构建第二列是非常简单的:

[ 0,  0] [ 50,  50]
[ 0, 50] [ 50, 100]
[50,  0] [100,  50]
[50, 50] [100, 100]

这是一个三维案例{[0,0,0],[100,100,60]},delta = [50,50,30]

[ 0,  0,  0] [ 50,  50, 30]
[ 0,  0, 30] [ 50,  50, 60]
[ 0, 50,  0] [ 50, 100, 30]
[ 0, 50, 30] [ 50, 100, 60]
[50,  0,  0] [100,  50, 30]
[50,  0, 30] [100,  50, 60]
[50, 50,  0] [100, 100, 30]
[50, 50, 30] [100, 100, 60]

答案 1 :(得分:1)

在所有维度(在Python中)拆分框的函数:

def halfboxes(box):
  result = [[]]
  for (a, b) in box:
    result = [r + [(a, (a+b)/2)] for r in result] + \
             [r + [((a+b)/2, b)] for r in result]
  return result

h = halfboxes([(0,100), (20, 100)])

# Results in h =
#   [[(0, 50), (20, 60)],  [(50, 100), (20, 60)],
#    [(0, 50), (60, 100)], [(50, 100), (60,100)]]

如果这是一个好的解决方案,也取决于您的性能要求。它会生成大量的数组副本,但效率并不高。但它对你的用例来说可能已经足够好了。

编辑:

更高效的版本,不会复制任何数组:

def halfboxes(box):
   # total number of resulting arrays
   resultscount = 2**len(box)

   # allocate |resultscount| arrays
   results = [[] for i in range(resultscount)]

   spread = 1
   for (a,b) in box:
      low  = (a, (a+b)/2)
      high = ((a+b)/2, b)
      for i in range(resultscount):
         # "magic" to append the high/low parts to the correct array
         if i % (spread*2) < spread:
            results[i].append(low)
         else:
            results[i].append(high)
      spread *= 2
   return results

这里没有复制数组,并且索引上的一些计算用于决定应该添加新边界的位置。

答案 2 :(得分:1)

  • 计算第一个框:

尺寸n:最小[0,0,0,..,0] - 最大[delta 1 / 2,delta 2 / 2,... ,delta n / 2]

  • 你的大盒子将被细分为2个 n 小盒子 - &gt;计算2 n transalations以应用于第一个框(包括[0,0,0,..,0]的翻译)

(当然下面的代码没有经过优化组织......)


using System;
using System.Collections.Generic;

namespace WindowsFormsApplication1
{
    public class Class1
    {
        public static List<Box> GetSmallBoxes(Box bigBox)
        {
            int translationCoef;
            List<Box> boxes = new List<Box>();                        
            Box box;

            for (int k = 0; k < Math.Pow(2, bigBox.Dimension); k++)
            {
                box = new Box(bigBox.Dimension);

                for (int d = 0; d < bigBox.Dimension; d++)
                {
                    translationCoef = ((int)(k / Math.Pow(2, bigBox.Dimension - d - 1)) % 2) == 0 ? 1 : 0;

                    box.Mins[d] = bigBox.Mins[d] + (bigBox.Deltas[d] / 2) * translationCoef;
                    box.Maxs[d] = bigBox.Mins[d] + (bigBox.Deltas[d] / 2) * (1 + translationCoef);
                }

                boxes.Add(box);
            }

            return boxes;
        }

        public static void Main()
        {
            Box bigBox = new Box(5);
            bigBox.Mins = new int[] { 0, 10, 30, 20, 40 };
            bigBox.Maxs = new int[] { 80, 50, 110, 40, 50 };
            List<Box> smallBoxes = Class1.GetSmallBoxes(bigBox);
        }
    }

    public class Box
    {
        public int Dimension;
        public int[] Mins;
        public int[] Maxs;

        public Box(int dimension)
        {
            Dimension = dimension;
            Mins = new int[dimension];
            Maxs = new int[dimension];
        }

        public int[] Deltas
        {
            get
            {
                int[] deltas = new int[Dimension];
                for (int i = 0; i < Dimension; i++)
                {
                    deltas[i] = Maxs[i] - Mins[i];
                }
                return deltas;
            }
        }

        public override string ToString()
        {
            string str;
            str = "Min[";
            foreach (int min in Mins)
            {
                str += min.ToString() + ", ";
            }
            str = str.Substring(0, str.Length - 2);
            str += "] -- Max[";
            foreach (int max in Maxs)
            {
                str += max.ToString() + ", ";
            }
            str = str.Substring(0, str.Length - 2);
            return str;
        }
    }
}