diff options
author | Pirate Praveen <praveen@debian.org> | 2017-10-09 11:57:35 +0530 |
---|---|---|
committer | Pirate Praveen <praveen@debian.org> | 2017-10-09 11:57:35 +0530 |
commit | 3db5c79f87119a5b46ab63cbfa6050700a978117 (patch) | |
tree | ce0bc40cb6a86a7c0e20c6c9cbde83e18b1d9c44 /src/circle.js |
Import Upstream version 1.9.0
Diffstat (limited to 'src/circle.js')
-rw-r--r-- | src/circle.js | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/circle.js b/src/circle.js new file mode 100644 index 0000000..9dbdbef --- /dev/null +++ b/src/circle.js @@ -0,0 +1,72 @@ +import {cartesian, cartesianNormalizeInPlace, spherical} from "./cartesian"; +import constant from "./constant"; +import {acos, cos, degrees, epsilon, radians, sin, tau} from "./math"; +import {rotateRadians} from "./rotation"; + +// Generates a circle centered at [0°, 0°], with a given radius and precision. +export function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = cos(radius), + sinRadius = sin(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]); + stream.point(point[0], point[1]); + } +} + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau; +} + +export default function() { + var center = constant([0, 0]), + radius = constant(90), + precision = constant(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees, x[1] *= degrees; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius; + }; + + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision; + }; + + return circle; +} |