--- title: Circles of given radius through two points id: 5951815dd895584b06884620 challengeType: 5 forumTopicId: 302231 --- ## Description
Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points. Exceptions:
## Instructions
Implement a function that takes two points and a radius and returns the two circles through those points. For each resulting circle, provide the coordinates for the center of each circle rounded to four decimal digits. Return each coordinate as an array, and coordinates as an array of arrays. For edge cases, return the following: Sample inputs:
      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0
## Tests
```yml tests: - text: getCircles should be a function. testString: assert(typeof getCircles === 'function'); - text: getCircles([0.1234, 0.9876], [0.8765, 0.2345], 2.0) should return [[1.8631, 1.9742], [-0.8632, -0.7521]]. testString: assert.deepEqual(getCircles(...testCases[0]), answers[0]); - text: getCircles([0.0000, 2.0000], [0.0000, 0.0000], 1.0) should return [0, 1] testString: assert.deepEqual(getCircles(...testCases[1]), answers[1]); - text: getCircles([0.1234, 0.9876], [0.1234, 0.9876], 2.0) should return Coincident point. Infinite solutions testString: assert.deepEqual(getCircles(...testCases[2]), answers[2]); - text: getCircles([0.1234, 0.9876], [0.8765, 0.2345], 0.5) should return No intersection. Points further apart than circle diameter testString: assert.deepEqual(getCircles(...testCases[3]), answers[3]); - text: getCircles([0.1234, 0.9876], [0.1234, 0.9876], 0.0) should return Radius Zero testString: assert.deepEqual(getCircles(...testCases[4]), answers[4]); ```
## Challenge Seed
```js function getCircles(...args) { return true; } ```
### After Test
```js const testCases = [ [[0.1234, 0.9876], [0.8765, 0.2345], 2.0], [[0.0000, 2.0000], [0.0000, 0.0000], 1.0], [[0.1234, 0.9876], [0.1234, 0.9876], 2.0], [[0.1234, 0.9876], [0.8765, 0.2345], 0.5], [[0.1234, 0.9876], [0.1234, 0.9876], 0.0] ]; const answers = [ [[1.8631, 1.9742], [-0.8632, -0.7521]], [0, 1], 'Coincident point. Infinite solutions', 'No intersection. Points further apart than circle diameter', 'Radius Zero' ]; ```
## Solution
```js 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 => [parseFloat((r * Math.cos(t) + p[0]).toFixed(4)), parseFloat((r * Math.sin(t) + p[1]).toFixed(4))]; const diamPoints = (p1, p2) => p1.map((e, i) => parseFloat((e + (p2[i] - e) / 2).toFixed(4))); function getCircles(...args) { const [p1, p2, s] = args; const solve = solveF(p1, s); const halfDist = hDist(p1, p2); let msg = []; switch (Math.sign(s - halfDist)) { case 0: msg = s ? diamPoints(p1, p2) : 'Radius Zero'; break; case 1: if (!halfDist) { msg = 'Coincident point. Infinite solutions'; } else { const theta = pAng(p1, p2); const theta2 = Math.acos(halfDist / s); [1, -1].map(e => solve(theta + e * theta2)).forEach( e => msg.push(e)); } break; case -1: msg = 'No intersection. Points further apart than circle diameter'; break; default: msg = 'Reached the default'; } return msg; } ```