# Rosetta Code: Circles of given radius through two points

Tell us what’s happening:
Describe your issue in detail here.
Floating point rounding issue… Wrong floating-point data being appended to the final array. Where specifically do I need to append the statement internally in order to accommodate the final appending process…?

I would do this via

[details]
Math.floor(expr*10000)/10000;

``````  **Your code so far**
``````
``````const hDist = (p1,p2) => Math.hypot(...p1.map((e, i) => e-p2[i]))/2;
const pAng = (p1,p2) => Math.atan(p1.map((e,i) => e-p2[i]).reduce(
(p, c) => c/p, 1));
const solveF = (p,r) => t => [r*Math.cos(t)+p[0], r*Math.sin(t)+p[1]];
const diamPts = (p1,p2) => p1.map((e,i) => e+(p2[i]-e)/2);
const getCircles = (...args) => {
const [p1,p2,s] = args;
const solve = solveF(p1,s), halfDist = hDist(p1,p2);
let debugMsg = `p1: \${p1}, p2: \${p2}, r:\${s}`;
console.log(`\${debugMsg}`);
let msg = `Result: `, dCheck = Math.sign(s-halfDist), newArr = [];
switch (dCheck) {
case 0:
s ? newArr.push(diamPts(p1,p2)) : (msg='Radius Zero');
break;
case 1:
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
} else {
let theta = pAng(p1,p2), theta2 = Math.acos(halfDist/s);
[1,-1].map(e => solve(theta + e*theta2)).forEach(e =>
newArr.push(e));
}
break;
case -1:
msg ='No intersection. Points further apart than circle diameter';
break;
}
console.log(`BEFORE: newArr: \${newArr}`);
newArr.forEach((el) => el = [Math.floor(el[0]*10000)/10000,
Math.floor(el[1]*10000)/10000]);
console.log(`AFTER: newArr: \${newArr}`);
return (msg !=`Result: `) ? (msg): newArr;
};
``````
``````  **Your browser information:**
``````

User Agent is: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36`

Challenge: Circles of given radius through two points

`forEach` doesn’t mutate array on it own and it always returns `undefined`, callback function might mutate the array, but it’d be more complicated than this. Consider using `map` method instead.

1 Like

Got the map for nA1, new map that floats corresponding… It’s flipping me the bird by making the second mapped el to be off by (+/- 1.0e-4)…
Else, it worked perfectly… Thank you for the assist.

``````const hDist = (p1,p2) => Math.hypot(...p1.map((e, i) => e-p2[i]))/2;
const pAng = (p1,p2) => Math.atan(p1.map((e,i) => e-p2[i]).reduce(
(p, c) => c/p, 1));
const solveF = (p,r) => t => [r*Math.cos(t)+p[0], r*Math.sin(t)+p[1]];
const diamPts = (p1,p2) => p1.map((e,i) => e+(p2[i]-e)/2);
const getCircles = (...args) => {
const [p1,p2,s] = args;
const solve = solveF(p1,s), halfDist = hDist(p1,p2);
let debugMsg = `p1: \${p1}, p2: \${p2}, r:\${s}`;
console.log(`\${debugMsg}`);
let msg = `Result: `, dCheck = Math.sign(s-halfDist), newArr = [];
if (dCheck == 0){
s ? newArr.push(diamPts(p1,p2)) : (msg='Radius Zero');
} else if (dCheck ==1) {
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
} else {
let theta = pAng(p1,p2), theta2 = Math.acos(halfDist/s);
[1,-1].map(e => solve(theta + e*theta2)).forEach(e =>
newArr.push(e));
} } else if(dCheck == -1) {
msg ='No intersection. Points further apart than circle diameter';
}
let nA1 = newArr.map((el) => el = [(Math.floor(el[0]* 10000)/10000).toFixed(4),(Math.floor(el[1]*10000)/10000).toFixed(4)]);
let consoleStrDebug = `nA1:`;
if(nA1.length > 1) {consoleStrDebug += '['; }
for(let i=0; i < nA1.length; i++) {
let finalChar = (i < nA1.length-1) ? ', ':'';
consoleStrDebug +=`[\${nA1[i][0]},\${nA1[i][1]}]\${finalChar}`;
}
if(nA1.length > 1) {consoleStrDebug += ']'; }
console.log(`\${consoleStrDebug}\n`);
return (msg !=`Result: `) ? (msg): nA1;
};
``````

Take a closer look at the calculations rounding the coordinates. To be a little more specific consider what actually happens when `Math.floor` method is used on the number below a zero.

In other words,

(round(expr*10000)/10000).toFixed(4)

in order to allow for upwards/ downwards modification…

Yes. There’s left just one small detail with using `toFixed`. It returns string and number of decimals is always the number passed to it, even if that would be only `0`s. So it is here not needed.

``````const hDist = (p1,p2) => Math.hypot(...p1.map((e, i) => e-p2[i]))/2;
const pAng = (p1,p2) => Math.atan(p1.map((e,i) => e-p2[i]).reduce(
(p, c) => c/p, 1));
const solveF = (p,r) => t => [r*Math.cos(t)+p[0], r*Math.sin(t)+p[1]];
const diamPts = (p1,p2) => p1.map((e,i) => e+(p2[i]-e)/2);
const getCircles = (...args) => {
const [p1,p2,s] = args;
const solve = solveF(p1,s), halfDist = hDist(p1,p2);
let debugMsg = `p1: \${p1}, p2: \${p2}, r:\${s}`;
console.log(`\${debugMsg}`);
let msg = `Result: `, dCheck = Math.sign(s-halfDist), newArr = [];
if (dCheck == 0){
s ? newArr.push(diamPts(p1,p2)) : (msg='Radius Zero');
} else if (dCheck ==1) {
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
} else {
let theta = pAng(p1,p2), theta2 = Math.acos(halfDist/s);
[1,-1].map(e => solve(theta + e*theta2)).forEach(e =>
newArr.push(e));
} } else if(dCheck == -1) {
msg ='No intersection. Points further apart than circle diameter';
}
let nA1 = newArr.map((el) => el = [(Math.round(el[0]*10000)/10000),
(Math.round(el[1]*10000)/10000)]);
let consoleStrDebug = `nA1:`;
if(nA1.length > 1) { consoleStrDebug += '['; }
for(let i=0; i < nA1.length; i++) {
let finalChar = (i < nA1.length-1) ? ', ':'';
consoleStrDebug +=`[\${nA1[i][0]},\${nA1[i][1]}]\${finalChar}`;
}
if(nA1.length > 1) {consoleStrDebug += ']'; }
console.log(`\${consoleStrDebug}\n`);
return (msg !=`Result: `) ? (msg): nA1;
};
``````

// running tests

``````getCircles([0.0000, 2.0000], [0.0000, 0.0000], 1.0)
``````

should return

``````[0, 1]
``````
``````// tests completed
// console output
p1: 0.1234,0.9876, p2: 0.8765,0.2345, r:2
nA1:[[1.8631,1.9742], [-0.8632,-0.7521]]

p1: 0,2, p2: 0,0, r:1
nA1:[0,1]

p1: 0.1234,0.9876, p2: 0.1234,0.9876, r:2
nA1: p1: 0.1234,0.9876, p2: 0.8765,0.2345, r:0.5

nA1:

p1: 0.1234,0.9876, p2: 0.1234,0.9876, r:0
nA1:

``````

… Needless to say, it is really close, just something is going wrong…

Printing to console the actual return value should give some idea what’s wrong:

``````console.log(getCircles([0.0000, 2.0000], [0.0000, 0.0000], 1.0))
``````

It’s a multi-dim array… Bollocks…

``````const hDist = (p1,p2) => Math.hypot(...p1.map((e, i) => e-p2[i]))/2;
const pAng = (p1,p2) => Math.atan(p1.map((e,i) => e-p2[i]).reduce(
(p, c) => c/p, 1));
const solveF = (p,r) => t => [r*Math.cos(t)+p[0], r*Math.sin(t)+p[1]];
const diamPts = (p1,p2) => p1.map((e,i) => e+(p2[i]-e)/2);
const getCircles = (...args) => {
const [p1,p2,s] = args;
const solve = solveF(p1,s), halfDist = hDist(p1,p2);
let debugMsg = `p1: \${p1}, p2: \${p2}, r:\${s}`;
console.log(`\${debugMsg}`);
let msg = `Result: `, dCheck = Math.sign(s-halfDist), newArr = [];
if (dCheck == 0){
s ? newArr.push(diamPts(p1,p2)) : (msg='Radius Zero');
} else if (dCheck ==1) {
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
} else {
let theta = pAng(p1,p2), theta2 = Math.acos(halfDist/s);
[1,-1].map(e => solve(theta + e*theta2)).forEach(e =>
newArr.push(e));
} } else if(dCheck == -1) {
msg ='No intersection. Points further apart than circle diameter';
}
let nA1 = [];
for(let i=0; i< newArr.length; i++){
if(newArr.length == 1) {
nA1 = [(Math.round(newArr[i][0]*10000)/10000),
(Math.round(newArr[i][1]*10000)/10000)];
} else {
nA1.push([(Math.round(newArr[i][0]*10000)/10000),
(Math.round(newArr[i][1]*10000)/10000)]);
}
}
let consoleStrDebug = `nA1:`;
if(nA1.length > 1) { consoleStrDebug += '['; }
for(let i=0; i < nA1.length; i++) {
let finalChar = (i < nA1.length-1) ? ', ':'';
consoleStrDebug +=`[\${nA1[i][0]},\${nA1[i][1]}]\${finalChar}`;
}
if(nA1.length > 1) {consoleStrDebug += ']'; }
console.log(`\${consoleStrDebug}\n`);
return (msg !=`Result: `) ? (msg): nA1;
};
``````

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.