无法生成体素球体

Having trouble generating a voxel sphere

我正在尝试为具有给定半径的球体生成坐标,但我只能设法生成一个圆柱体,我并没有真正弄清楚原因。这是我当前的代码:

function makeSphere(radius){
          var sphere3D = {};

          var radiusX = radius + 0.5;
          var radiusY = radius + 0.5;
          var radiusZ = radius + 0.5;

          var invRadiusX = 1 / radiusX;
          var invRadiusY = 1 / radiusY;
          var invRadiusZ = 1 / radiusZ;

          var ceilRadiusX = Math.ceil(radiusX);
          var ceilRadiusY = Math.ceil(radiusY);
          var ceilRadiusZ = Math.ceil(radiusZ);

          var nextXn = 0;
          forX: for (var x = 0; x <= ceilRadiusX; ++x) {
            var xn = nextXn;
            nextXn = (x + 1) * invRadiusX;
            var nextYn = 0;
            forY: for (var y = 0; y <= ceilRadiusY; ++y) {
              var yn = nextYn;
              nextYn = (y + 1) * invRadiusY;
              var nextZn = 0;
              forZ: for (var z = 0; z <= ceilRadiusZ; ++z) {
                var zn = nextZn;
                nextZn = (z + 1) * invRadiusZ;

                var distanceSq = lengthSq(xn, yn, zn);
                if (distanceSq > 1) {
                    if (z == 0) {
                        if (y == 0) {
                            break forX;
                        }
                        break forY;
                    }
                    break forZ;
                }


                if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) {
                    continue;
                }


                  sphere3D[[x,y,z]] = true;
                sphere3D[[-x,y,z]] = true;
                sphere3D[[x,-y,z]] = true;
                sphere3D[[x,y,-z]] = true;
                sphere3D[[-x,-y,z]] = true;
                sphere3D[[x,-y,-z]] = true;
                sphere3D[[-x,y,-z]] = true;
                sphere3D[[-x,-y,-z]] = true;

              }
            }
          }
        }


        function lengthSq(x, y, z) {
            return (x * x) + (y * y) + (z * z);
        }

        function lengthSq(x, z) {
            return (x * x) + (z * z);
        }

这给出了 following output.

关于我哪里搞砸了有什么想法吗?在此先感谢您的关注。

不确定这是否能解决您的问题,但您不能有 2 个具有相同名称的函数。在您的情况下,即使参数不同,第二个 lengthSq() 也会取代第一个。

Javascript 中没有原生函数重载。但是,如果坚持使用处理多个参数的相同函数名称很重要,您可以尝试这些建议 Function overloading in Javascript - Best practices

如果您在您提供的代码之外的其他地方使用它,替代方法是将其重命名为 lengthSqXZ(x, z)。

这是一种可能更容易遵循的方法。您需要将代码分成四个部分:

  • 在特定的 n 维域内生成一组点 p
  • 将点集过滤为 qradius 和 n 维 origin
  • 定义的球面的 1 个单位内的点集
  • 反映在 origin 处相交的每个笛卡尔轴上的点集,以创建反射点集 r
  • 将点集 r 添加到对象 nSphere

下面是一组函数,可以解决每个问题以创建 n-sphere

// 0-sphere of radius 5 centered at [6]
console.log(makeNSphere(5, 6)); // { r: [6 - 5], [6 + 5] }
// 2-sphere of radius 2 centered at [0, 0, 0]
console.log(makeNSphere(2, 0, 0, 0));

function makeNSphere (radius, ...origin) {
  function onSurface (p) {
    const d = distance(
      p.map(
        (x, i) => x - origin[i]
      )
    );

    return Math.abs(d - radius) < 1;
  }

  const nSphere = {};
  const ps = range(
    ...origin.map(
      x => [x, x + radius + 1]
    )
  );
  const reflection = reflect(...origin);

  for (const q of where(ps, onSurface)) {
    for (const r of reflection(...q)) {
      nSphere[r] = true;
    }
  }

  return nSphere;
}

function distance (p) {
  let sum = 0;

  for (const x of p) {
    sum += x * x;
  }

  return Math.sqrt(sum);
}

function* range (constraints = [], ...rest) {
  const base = rest.length === 0;
  let begin = 0;
  let end = Infinity;
  let increment = 1;

  switch (constraints.length) {
    case 0: break;
    case 1: [end] = constraints; break;
    case 2: [begin, end] = constraints; break;
    default: [begin, end, increment] = constraints; break;
  }

  for (let i = begin; i < end; i += increment) {
    if (base) {
      yield [i];
      continue;
    }

    for (const a of range(...rest)) {
      yield [i, ...a];
    }
  }
}

function* where (ps, predicateFn) {
  for (const p of ps) {
    if (predicateFn(p)) {
      yield p;
    }
  }
}

function reflect (...axes) {
  return function* recurse (x, ...rest) {
    if (rest.length === 0) {
      yield* base(x);
      return;
    }

    for (const xs of recurse(...rest)) {
      yield* base(x, ...xs);
    }
  }

  function* base (x, ...rest) {
    yield [x, ...rest];

    const axis = axes[axes.length - rest.length - 1];
    const y = axis - (x - axis);

    if (x !== y) {
      yield [y, ...rest];
    }
  }
}