diff --git a/README.md b/README.md index f607d2f..4a4804a 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Shapes with position in space: - [scalar2](https://axelpale.github.io/affineplane/docs/API.html#affineplanescalar2), a second-order measure (area), `ss` - [scalar3](https://axelpale.github.io/affineplane/docs/API.html#affineplanescalar3), a third-order measure (volume), `sss` - [segment2](https://axelpale.github.io/affineplane/docs/API.html#affineplanesegment2), a line segment in 2D space, `[{x,y},{x,y}]` +- [segment2](https://axelpale.github.io/affineplane/docs/API.html#affineplanesegment3), a line segment in 3D space, `[{x,y,z},{x,y,z}]` - [size2](https://axelpale.github.io/affineplane/docs/API.html#affineplanesize2), a rectangle size in 2D, `{w,h}` - [size3](https://axelpale.github.io/affineplane/docs/API.html#affineplanesize3), a cuboid size in 3D, `{w,h,d}` - [sphere2](https://axelpale.github.io/affineplane/docs/API.html#affineplanesphere2), a circle in 2D, `{x,y,r}` diff --git a/docs/API.md b/docs/API.md index 727f4db..ba128d8 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,5 +1,5 @@ -# Affineplane API Documentation v2.17.0 +# Affineplane API Documentation v2.17.1 Welcome to affineplane API reference documentation. These docs are generated with [yamdog](https://axelpale.github.io/yamdog/). diff --git a/lib/sphere2/collisionArea.js b/lib/sphere2/collisionArea.js index a47d7ff..60782fb 100644 --- a/lib/sphere2/collisionArea.js +++ b/lib/sphere2/collisionArea.js @@ -29,22 +29,23 @@ module.exports = (c, cc) => { return 0 } - if (d === 0) { - // Concentric circles. Area of the smaller is the overlap. + if (d + Math.min(r, rr) <= Math.max(r, rr)) { + // Nested circles. Area of the smaller is the overlap. if (r <= rr) { return Math.PI * r2 } return Math.PI * rr2 } - if (d > r + rr) { + if (d >= r + rr) { // Circles too distant. Just for optimization. return 0 } - const area = r2 * Math.acos((d2 + r2 - rr2) / (2 * d * r)) + - rr2 * Math.acos((d2 + rr2 - r2) / (2 * d * rr)) - - 0.5 * Math.sqrt((-d + r + rr) * (d + r - rr) * (d - r + rr) * (d + r + rr)) + const acosr = Math.acos((d2 + r2 - rr2) / (2 * d * r)) + const acosrr = Math.acos((d2 + rr2 - r2) / (2 * d * rr)) + const dddd = (-d + r + rr) * (d + r - rr) * (d - r + rr) * (d + r + rr) + const area = r2 * acosr + rr2 * acosrr - 0.5 * Math.sqrt(dddd) return area } diff --git a/lib/version.js b/lib/version.js index e1e57ac..e541e5c 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1,2 +1,2 @@ // Generated by genversion. -module.exports = '2.17.0' +module.exports = '2.17.1' diff --git a/package.json b/package.json index 1b93a93..0e5df71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "affineplane", - "version": "2.17.0", + "version": "2.17.1", "description": "Affine geometry library for 2D and 3D spaces", "keywords": [ "affine", diff --git a/test/sphere2/collisionArea.test.js b/test/sphere2/collisionArea.test.js index 08d82c5..100ab56 100644 --- a/test/sphere2/collisionArea.test.js +++ b/test/sphere2/collisionArea.test.js @@ -1,4 +1,6 @@ const sphere2 = require('../../lib/sphere2') +const sqrt = Math.sqrt +const acos = Math.acos module.exports = (ts) => { ts.test('case: basic collisionArea', (t) => { @@ -25,7 +27,21 @@ module.exports = (ts) => { // overlap = 2 * segment // segment = π/3 - sqrt(3)/4 (2 * Math.PI / 3) - Math.sqrt(3) / 2, - 'spheres overlap' + 'spheres overlap, sector angle < 180' + ) + + t.almostEqual( + sphere2.collisionArea({ x: 0, y: 0, r: 3 }, { x: 2, y: 0, r: 2 }), + // overlap = small circle - small circle segment + large circle segment + 4 * Math.PI + 9 * acos(3 / 4) - 4 * acos(1 / 8) - 3 * sqrt(7) / 2, + 'spheres overlap, sector angle > 180' + ) + + t.almostEqual( + sphere2.collisionArea({ x: 967, y: 485, r: 212 }, { x: 667, y: 485, r: 825 }), + // overlap = small circle + Math.PI * 212 * 212, + 'real world numbers' ) t.end()