无法生成体素球体
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
- 将点集过滤为
q
由 radius
和 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];
}
}
}
我正在尝试为具有给定半径的球体生成坐标,但我只能设法生成一个圆柱体,我并没有真正弄清楚原因。这是我当前的代码:
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
- 将点集过滤为
q
由radius
和 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];
}
}
}