import {cartesian, cartesianNormalizeInPlace, spherical} from "./cartesian.js"; import constant from "./constant.js"; import {acos, cos, degrees, epsilon, radians, sin, tau} from "./math.js"; import {rotateRadians} from "./rotation.js"; // 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; }