动态创建有限的n维坐标系,该坐标系具有来自轴向坐标的整数坐标

Creating dynamically a finite n-dimensional coordinate system with integer coordinates from axial coordinates

本文关键字:坐标系 坐标 整数 创建 动态      更新时间:2023-09-26

我试图通过首先创建轴向坐标,在有限的n维坐标系中动态创建一个位置列表。系统只有整数作为坐标值。轴坐标是AxCrd对象。AxCrd对象有两个属性:

  1. AxCrd.dim是坐标标注的句柄或名称。例如,"x"或"y"
  2. AxCrd.crd是坐标的值。这是一个整数。例如,-4或3

我试图编写一个函数,接受所有生成的AxCrd对象作为输入,并输出我试图创建的n维空间中所有位置的列表作为Crd对象。Crd对象有两个属性:

  1. Crd.dims是一个数组,包含坐标的所有尺寸控制柄。这个数组的长度是n,也就是说,等于维度的数量。

  2. Crd.crds是包含上述维度的所有坐标值的数组。这个数组的排序很重要,因为坐标的维度应该与坐标值具有相同的元素编号。Ie.如果维度"z"是第二个元素,那么crds[2]是维度"z"的坐标值。

例如,假设我使用以下构造函数:

function AxCrd(dim,crd) { this.dim = dim, this.crd = crd }
function Crd(dims,crds) { this.dims = dims, this.crds = crds }

在我实际的预期用途中,大多数维度都有九个值:四个负值、四个正值和一个零值。但为了简洁起见,我们假设我有三个维度,因此:

var input = [];
input.push(new AxCrd("x", -1));
input.push(new AxCrd("x", 1));
input.push(new AxCrd("y", -1));
input.push(new AxCrd("y", 1));
input.push(new AxCrd("z", -1));
input.push(new AxCrd("z", 1));
input.push(new AxCrd("d", -1));
input.push(new AxCrd("d", 1));

正如你所看到的,有三个维度,每个维度只有两个坐标值。我正在尝试编写一个函数,在给定上述输入的情况下,该函数将创建新的Crd对象,如下所示:

var ret = [];
ret.push(new Crd(["x","y","z","d"],[-1,-1,-1,-1]));
ret.push(new Crd(["x","y","z","d"],[ 1,-1,-1,-1]));
ret.push(new Crd(["x","y","z","d"],[-1, 1,-1,-1]));
ret.push(new Crd(["x","y","z","d"],[ 1, 1,-1,-1]));
ret.push(new Crd(["x","y","z","d"],[-1,-1, 1,-1]));
ret.push(new Crd(["x","y","z","d"],[ 1,-1, 1,-1]));
ret.push(new Crd(["x","y","z","d"],[-1, 1, 1,-1]));
ret.push(new Crd(["x","y","z","d"],[ 1, 1, 1,-1]));
ret.push(new Crd(["x","y","z","d"],[-1,-1,-1, 1]));
ret.push(new Crd(["x","y","z","d"],[ 1,-1,-1, 1]));
ret.push(new Crd(["x","y","z","d"],[-1, 1,-1, 1]));
ret.push(new Crd(["x","y","z","d"],[ 1, 1,-1, 1]));
ret.push(new Crd(["x","y","z","d"],[-1,-1, 1, 1]));
ret.push(new Crd(["x","y","z","d"],[ 1,-1, 1, 1]));
ret.push(new Crd(["x","y","z","d"],[-1, 1, 1, 1]));
ret.push(new Crd(["x","y","z","d"],[ 1, 1, 1, 1]));

对于n维空间,我该怎么做?

如果我理解你的问题,你需要一个所有维度名称到其索引的映射(称之为dim_map应该是dim_map['x'] = 0; dim_map['y'] = 1;...)。然后,在进行转换时,将键用作dims,查找index = dim_map[AxCrd.dim]的索引,并将这些值分配给相应的元素(Crd.crds[index] = AxCrd.crd)。

我不完全确定这是你想要的,因为你的例子看起来很混乱。我不知道为什么你为每个AxCrd构造两个Crd,或者为什么其他一些值似乎发生了变化。

递归似乎是处理这类问题的正确方法。这里有一个简单的递归函数,它返回点的数组作为结果。它还将维度的名称存储在作为函数参数传递的数组中。

function rec(i, input, dimensions)
{
   // find the name of the current dimension
   var currentd = input[i].dim;
   dimensions.push(currentd);
   // find how many elements in the current dimension
   var j = i;
   while (j < input.length && input[j].dim == currentd) ++j;
   // create a tail of results
   var tail = [];
   if (j < input.length) {
      tail = rec(j, input, dimensions);
   }
   // create a result by appending tail to all possible coordinates in the current dimension
   var result = [];
   for (; i < j; i++) {
       if (tail.length == 0) {
           result.push([input[i].crd]);
       } else {
           for (var k = 0; k < tail.length; k++) {
               result.push([input[i].crd].concat(tail[k]));
           }
       }
   }
   return result;
}

这个函数不会创建Crd对象,但你可以很容易地修改它。用法示例:

var dimensions = [];
var result = rec(0, input, dimensions);
console.log(JSON.stringify(dimensions));
for (var i = 0; i < result.length; i++) {
  console.log(JSON.stringify(result[i]));
}

输出(假设input与您的示例相同):

["x","y","z","d"]
[-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]

看起来就像是在寻找每个子数组项的所有可能组合,或者笛卡尔乘积。这可以递归计算:

function product(array) {
    if (array.length == 0) return [[]];
    var head = array[0];
    var tail = product(array.slice(1));
    var res = [];
    for (var i = 0; i < head.length; i++) {
        for (var j = 0; j < tail.length; j++) {
            res.push([head[i]].concat(tail[j]));
        }
    }
    return res;
}

Ans这样使用它:

var input = [
    [-1, 1],    // x
    [-1, 1],    // y
    [-1, 1],    // z
    [-1, 1],    // d
];
var prod = product(input);
for (var i = 0; i < prod.length; i++) {
    console.log(i, prod[i]);
}

上面的函数是在假定传递的数组是数组的情况下工作的。没有人试图检测到这一点。

您可以将生成的数组添加到列表中,而不是打印。我不知道为什么每次添加坐标时都要创建一个新的坐标系。难道你不应该只创建一次坐标系并传递一个参考吗?我也支持Sorin,因为你可能想要一个按字母查找维度的地图。你的课堂设计似乎过于复杂。

我想要做的事情似乎几乎可以通过以下功能实现:

function makeAllCoordinates(arr) {
  if (arr.length === 0) { return []; }
  else if (arr.length === 1) { return arr[0]; }
  else {
    var result = [];
    var allCases = makeAllCoordinates(arr.slice(1));
    for (var c in allCases) {
      for (var i = 0; i < arr[0].length; i++) {
        result.push((arr[0][i] + allCases[c]).split(",")); }}
    return result; }}

结果是一个9×9×9。这个数字是正确的。但是,每个数组只有一个成员,这是一个由六个重复的"[object object]"组成的字符串。我需要它们是六个AxCrd对象的唯一数组,而不是这样的字符串。数组的顺序无关紧要。这样修改这个函数有困难吗?

无论如何,我希望这个回复能澄清我想做什么的歧义。