Reputation: 13
I'm trying to generate the coordinates for a sphere with a given radius, but am only managing to produce a cylinder and I'm not really figuring out why. Here's my current code:
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);
}
Which gives the following output.
Any ideas on where I'm messing up? Thanks in advance for your attention.
Upvotes: 1
Views: 157
Reputation: 51916
Here's an approach that might be easier to follow. You'll want to break your code up into four parts:
p
within a particular n-dimensional domainq
that are within 1 unit of a spherical surface defined by a radius
and n-dimensional origin
origin
to create the reflected set of points r
r
to an object nSphere
Below is a set of functions that address each of these concerns to create an 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];
}
}
}
Upvotes: 1
Reputation: 3785
Not sure if this solves you problem but you can't have 2 functions having the same name. In your case, the second lengthSq() will supersede the first one even if the parameters are different.
There is no native function overloading in Javascript. However you can try these suggestions if it important to stick with same function name that handle multiple parameters Function overloading in Javascript - Best practices
The alternative is to rename it as as lengthSqXZ(x, z) if you are using it elsewhere outside the code you have provided.
Upvotes: 0