Algorithm 折叠三维立方体上的选定点

Algorithm 折叠三维立方体上的选定点,algorithm,multidimensional-array,getselection,cubes,Algorithm,Multidimensional Array,Getselection,Cubes,我正在尝试为以下3D立方体选择问题找到一个有效的算法: 想象一个二维点阵列(让它成为x大小的正方形)并称之为边 为了便于计算,让我们将max声明为size-1 创建一个六面立方体,左下侧保持0,0,右上侧保持max,max。 使用z跟踪单个立方体所在的一侧,y向上,x向右 public class Point3D { public int x,y,z; public Point3D(){} public Point3D(int X, int Y, int Z) {

我正在尝试为以下3D立方体选择问题找到一个有效的算法:

想象一个二维点阵列(让它成为x大小的正方形)并称之为边

为了便于计算,让我们将max声明为size-1 创建一个六面立方体,左下侧保持0,0,右上侧保持max,max。 使用z跟踪单个立方体所在的一侧,y向上,x向右

public class Point3D {
    public int x,y,z;

    public Point3D(){}
    public Point3D(int X, int Y, int Z) {
        x = X;
        y = Y;
        z = Z;
    }
}

Point3D[,,] CreateCube(int size)
{
    Point3D[,,] Cube = new Point3D[6, size, size];
    for(int z=0;z<6;z++)
    {           
        for(int y=0;y<size;y++)
        {
            for(int x=0;x<size;x++)
            {
                Cube[z,y,x] = new Point3D(x,y,z);
            }
        }
    }
    return Cube;
}
要选择加号,我们可以检测给定方向是否适合当前侧。 否则我们会发现立方体位于接触中心点的一侧

将4个函数与以下内容一起使用:

private T GetUpFrom<T>(T[,,] dataSet, Point3D point) where T : class {
    if(point.y < max)
        return dataSet[point.z, point.y + 1, point.x];
    else {
        switch(point.z) {
            case 0: return dataSet[1, point.x, max];      // x+
            case 1: return dataSet[5, max, max - point.x];// y+
            case 2: return dataSet[1, 0, point.x];        // z+
            case 3: return dataSet[1, max - point.x, 0];  // x-
            case 4: return dataSet[2, max, point.x];      // y-
            case 5: return dataSet[1, max, max - point.x];// z-
        }
    }
    return null;
}
private T GetUpFrom(T[,]数据集,点3d点),其中T:class{
如果(点y<最大值)
返回数据集[点.z,点.y+1,点.x];
否则{
开关(点z){
案例0:返回数据集[1,point.x,max];//x+
案例1:返回数据集[5,max,max-point.x];//y+
案例2:返回数据集[1,0,point.x];//z+
案例3:返回数据集[1,max-point.x,0];//x-
案例4:返回数据集[2,max,point.x];//y-
案例5:返回数据集[1,max,max-point.x];//z-
}
}
返回null;
}
现在我想找到一种方法,在一个随机点上选择任意形状(如预定义的随机斑点)。 但可以将其调整为正方形或锯齿形圆形

实际表面积将被扭曲并折叠到角落上,这很好,不需要补偿(想象一下,将一个贴纸放在立方体的角落上,如果角落与贴纸的中心相匹配,则需要移除贴纸的四分之一才能粘贴并折叠到角落上)。这也是我们想要的效果

不允许重复选择,因此将选择两次的多维数据集需要以某种方式进行过滤(或以不发生重复的方式进行计算)。这可能是一个简单的操作,比如使用HashSet或List,并使用helper函数检查条目是否唯一(这很好,因为选择总是远远低于最大1000个cubes)

包含多维数据集侧面的类中此函数的委托如下所示: 代表T[]选择形状(点3D点,整数大小)

目前,我正在考虑检查立方体的每一侧,以查看选择的哪一部分位于该一侧

计算选择的哪一部分位于所选点3D的同一侧是很简单的,因为我们不需要平移位置,只需要平移边界。 接下来是5个平移,然后检查其他5个面,查看所选区域的一部分是否在该面上

我对解决这样的问题越来越生疏了,所以我想知道是否有人能更好地解决这个问题

@ArghCleargh要求进一步解释:

我们将使用6边的立方体,尺寸为16。每边有16x16个点。 存储为一个三维数组,我使用z表示side,y,x,这样数组将使用:new Point3D[z,y,x]启动,它对锯齿状数组的工作方式几乎相同,锯齿状数组在默认情况下是可序列化的(这也很好)[z][y][x],但需要对每个子数组分别进行初始化

让我们选择一个大小为5x5的正方形,以选定点为中心。 要找到这样一个5x5平方减法,并将2添加到所讨论的轴上:x-2到x+2,y-2到y+2

随机选择UBG a边,我们选择的点是z=0(立方体的x+边),y=6,x=6

6-2和6+2均在侧面16 x 16阵列的限制范围内,易于选择

然而,将选择点移动到x=0和y=6将证明更具挑战性。 因为x-2需要查看我们选择的一侧左边的一侧。 幸运的是,我们选择了边0或x+,因为只要我们不在立方体的顶部或底部,也不在立方体的顶部或底部,所有轴都是x+=右,y+=上。 所以要得到左边的坐标只需要减去max(size-1)-x。记住大小=16,最大值=15,x=0-2=-2,最大值-x=13。 因此,这一侧的分段为x=13到15,y=4到8。 将此添加到我们可以在原始侧选择的部分将给出整个选择

将选择值更改为0,6将被证明更为复杂,因为现在我们无法隐藏在知道所有轴轻松对齐的安全后面。可能需要进行一些轮换。只有4种可能的翻译,因此仍然可以管理

转移到0,0才是真正开始出现问题的地方。 就像现在一样,左右两边都需要绕到另一边。更进一步,因为即使是细分的部分也会有一个区域落在外面。 对这个伤口唯一的安慰是我们不在乎选择的重叠部分。 因此,我们可以在可能的情况下跳过它们,或者稍后从结果中过滤它们

现在,我们从“法线轴”一侧移动到底部一侧,我们需要旋转并匹配正确的坐标,以便点正确环绕边

由于每一侧的轴都在立方体中折叠,因此某些轴可能需要翻转或旋转以选择正确的点


问题仍然是,是否有更好的解决方案来选择立方体上位于某个区域内的所有点。也许我可以给每一方一个平移矩阵,并在世界空间中测试坐标?

找到了一个非常好的解决方案,只需要很少的努力即可实现

为大小为n+2的空心立方体创建存储,其中n是数据中包含的立方体的大小。这满足了以下条件:侧面相互接触,但不重叠或共享某些点

这将通过创建使用笛卡尔坐标的查找数组来简化计算和转换。 使用单个平移函数获取
private T GetUpFrom<T>(T[,,] dataSet, Point3D point) where T : class {
    if(point.y < max)
        return dataSet[point.z, point.y + 1, point.x];
    else {
        switch(point.z) {
            case 0: return dataSet[1, point.x, max];      // x+
            case 1: return dataSet[5, max, max - point.x];// y+
            case 2: return dataSet[1, 0, point.x];        // z+
            case 3: return dataSet[1, max - point.x, 0];  // x-
            case 4: return dataSet[2, max, point.x];      // y-
            case 5: return dataSet[1, max, max - point.x];// z-
        }
    }
    return null;
}