簡體   English   中英

n維超立方體中的連接點

[英]connecting points in n-dimensional hyper cube

我正在嘗試在不使用 p3d 渲染器的情況下在處理中創建類似 3d 的草圖。 我已經設法制作了一個立方體,但為此我硬編碼了所有坐標和連接,一旦你想添加另一個維度,它就會開始變得有點無聊。 所以我創建了一個函數來創建所有坐標:

float[][] cube(int dims, float w) {
  int outputSize = (int)pow(2, dims);
  float[] temp = new float[dims];
  float[][] res = new float[outputSize][dims];
  Arrays.fill(temp, w);
  res[0] = temp.clone();
  for (int i = 0; i < outputSize - 1; i++) {
    for (int j = dims - 1; true; j--) {
      temp[j] *= -1;
      if (temp[j] < 0) {
        break; 
      }
    }
    res[i + 1] = temp.clone();
  }
  return res;
}

它只是通過使用二進制來工作,因此輸入 (2, 1) 立方體將是:

[[1, 1], [1, -1], [-1, 1], [-1, -1]]

它工作正常,但問題是它只返回角落,但不返回連接角,但我找不到一種有效的方法來做到這一點。 我需要另一個函數來返回要連接的索引的內容。

下面是給定上面的數組,函數應該做什么的例子:

[[0, 1], [1, 3], [3, 2], [2, 0]]

(內部數組的順序可能不同)

是否有任何已知的算法來連接 n 維立方體的角?

如果其他點生成有幫助,我可以更改其他功能。

這是一種迭代生成坐標和索引的方法:

  • 從一個維度為n的立方體開始
  • 制作兩個立方體副本,並在第n + 1個軸上的每個極值坐標(例如 -1 和 +1)上放置一個
  • 制作邊以連接立方體上的每對對應頂點

在此處輸入圖片說明

您已經知道頂點數V(n) = 2^n 由於添加到n + 1立方體的邊數等於此(所有對應的頂點對)加上復制的n立方體的邊數,因此邊數的遞推關系為:

E(n) = 2 * E(n - 1) + V(n - 1)   // copies + joining edges
E(1) = 1                         // base case for n = 1

-->  E(n) = n * 2^(n - 1)

n  | E(n)
-------------
1  | 1
2  | 4
3  | 12
4  | 32
5  | 80

這允許在復制新多維數據集/添加新邊時預先分配所需邊的數量並計算索引偏移量。


代碼:

// edge index
class Edge
{
   public int A, B;
   public Edge(int a, int b)
   {
      A = a; B = b;
   }
   public Edge shift(int n)
   {
      return new Edge(A + n, B + n);
   }
}

// cube class
class Cube
{
   // I'll leave out the get-functions etc here
   private float[][] m_verts;
   private Edge[] m_edges;
   public Cube(float[][] v, Edge[] e)
   {
      m_verts = v;
      m_edges = e;
   }
}

Cube cube_N(int dims, float w)
{
   // base case
   if (dims < 1)
      return null;

   // calculate buffer sizes
   int dpow2 = 1 << dims;
   int numVerts = dpow2;
   int numEdges = dims * (dpow2 / 2);

   // buffers
   float[] temp = new float[dims];
   float[][] verts = new float[numVerts][];
   Edge[] edges = new Edge[numEdges];

   // base case creation
   Arrays.fill(temp, w);
   verts[0] = temp.clone();
   edges[0] = new Edge(0, 1);

   // iterative step
   for (int i = 0; i < dims; i++)
   {
      int nV = 1 << i;
      int nE = i * (nV / 2);

      // copy + shift vertices
      for (int j = 0; j < nV; j++)
      {
         float[] v = verts[j].clone();
         v[i] = -w;
         verts[nV + j] = v;
      }

      // copy + shift previous edges
      for (int j = 0; j < nE; j++)
      {
         edges[nE + j] = edges[j].shift(nV);
      }

      // create new edges to join cube copies
      int off = nE * 2;
      for (int j = 0; j < nV; j++)
      {
         edges[off + j] = new Edge(j, nV + j);
      }
   }

   return new Cube(verts, edges);
}

n = 3結果:

verts:
[1, 1,  1], [-1, 1,  1], [1, -1,  1], [-1, -1,  1],
[1, 1, -1], [-1, 1, -1], [1, -1, -1], [-1, -1, -1]
edges:
[0, 1], [2, 3], [0, 2], [1, 3], [4, 5], [6, 7],
[4, 6], [5, 7], [0, 4], [1, 5], [2, 6], [3, 7]

n = 4結果:

verts: 
[1, 1,  1,  1], [-1, 1,  1,  1], [1, -1,  1,  1], [-1, -1,  1,  1],
[1, 1, -1,  1], [-1, 1, -1,  1], [1, -1, -1,  1], [-1, -1, -1,  1],
[1, 1,  1, -1], [-1, 1,  1, -1], [1, -1,  1, -1], [-1, -1,  1, -1],
[1, 1, -1, -1], [-1, 1, -1, -1], [1, -1, -1, -1], [-1, -1, -1, -1]

edges:
[0 ,  1], [2 ,  3], [0 ,  2], [1 ,  3], [4,  5], [6 ,  7], [4 ,  6], [5 ,  7],
[0 ,  4], [1 ,  5], [2 ,  6], [3 ,  7], [8,  9], [10, 11], [8 , 10], [9 , 11],
[12, 13], [14, 15], [12, 14], [13, 15], [8, 12], [9 , 13], [10, 14], [11, 15],
[0 ,  8], [1 ,  9], [2 , 10], [3 , 11], [4, 12], [5 , 13], [6 , 14], [7 , 15]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM