在由不同颜色的立方体制成的网格中,如何找到匹配的簇?

时间:2018-01-07 18:28:59

标签: javascript algorithm sorting vector three.js

定义群集

任何一组相同颜色的立方体,触摸面平面,而不是角落。

一个簇会形成一个实心的几何形状。

帮助可视化问题

假设这些乐高积木中的每一个都是1x1单位大。

legos

在一个简化的代码示例中 - 让我们看一下由2x2x2多维数据集组成的1x1x1网格:

var mesh = [ 

  // First layer   ( x, y, z )
  new THREE.Vector3( 0, 0, 0 ),
  new THREE.Vector3( 0, 0, 1 ),
  new THREE.Vector3( 1, 0, 0 ),
  new THREE.Vector3( 1, 0, 1 )

  //Second layer   ( x, y, z )
  new THREE.Vector3( 0, 1, 0 ),
  new THREE.Vector3( 0, 1, 1 ),
  new THREE.Vector3( 1, 1, 0 ),
  new THREE.Vector3( 1, 1, 1 )
];

enter image description here

网格中的每个立方体都有一个颜色:

//Indexes of mesh array sorted by color
var colors = {
  red: [0, 1, 4, 6],
  green: [2, 3, 5, 7]
}

2 个答案:

答案 0 :(得分:3)

这可以通过flood fill来解决。维基百科页面对两个方面具有指导意义:

Flood-fill (node, target-color, replacement-color):
 1. If target-color is equal to replacement-color, return.
 2. If the color of node is not equal to target-color, return.
 3. Set the color of node to replacement-color.
 4. Perform Flood-fill (one step to the south of node, target-color, replacement-color).
    Perform Flood-fill (one step to the north of node, target-color, replacement-color).
    Perform Flood-fill (one step to the west of node, target-color, replacement-color).
    Perform Flood-fill (one step to the east of node, target-color, replacement-color).
 5. Return.

如果它们的距离为1,则可以通过观察两个单元格是相邻的来扩展到三维,或者更简单地说如果它们在一个维度上相差一个,那么您可以迭代所有六个邻居而不是四个邻居尺寸。

答案 1 :(得分:0)

以下是使用我的n-dimensional-flood-fill npm软件包的网格的工作示例:

// It's easier to use floodFill if you represent your mesh as nested arrays:
var mesh = [
  [
    // 0,0,0  0,0,1
    ["red", "red"],

    // 0,1,0  0,1,1
    ["red", "green"],
  ],
  [
    // 1,0,0  1,0,1
    ["green", "green"],

    // 1,1,0  1,1,1
    ["red", "green"]
  ]
];

var redFill = floodFill({
  getter: function (x, y, z) { return mesh[x][y][z] },
  seed: [0, 0, 0]
});

var greenFill = floodFill({
  getter: function (x, y, z) { return mesh[x][y][z] },
  seed: [1, 1, 1]
});

console.log("redFill: " + JSON.stringify(redFill.flooded));
// redFill: [[0,0,0],[0,1,0],[1,1,0],[0,0,1]]

console.log("greenFill: " + JSON.stringify(greenFill.flooded));
// greenFill: [[1,1,1],[1,0,1],[1,0,0],[0,1,1]]

如果要使用其他表示形式,则可以写一个不同的getter

如您所见,您需要为要填充的每个区域运行floodFill。要查找网格的所有区域,可以从每个可能的起始坐标运行floodFill,但已淹没在其中一个区域中的区域除外。这将是相当有效的,但是可能有更复杂的方法可以在一次通过中找到所有区域。