circle.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import {cartesian, cartesianNormalizeInPlace, spherical} from "./cartesian.js";
  2. import constant from "./constant.js";
  3. import {acos, cos, degrees, epsilon, radians, sin, tau} from "./math.js";
  4. import {rotateRadians} from "./rotation.js";
  5. // Generates a circle centered at [0°, 0°], with a given radius and precision.
  6. export function circleStream(stream, radius, delta, direction, t0, t1) {
  7. if (!delta) return;
  8. var cosRadius = cos(radius),
  9. sinRadius = sin(radius),
  10. step = direction * delta;
  11. if (t0 == null) {
  12. t0 = radius + direction * tau;
  13. t1 = radius - step / 2;
  14. } else {
  15. t0 = circleRadius(cosRadius, t0);
  16. t1 = circleRadius(cosRadius, t1);
  17. if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
  18. }
  19. for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
  20. point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
  21. stream.point(point[0], point[1]);
  22. }
  23. }
  24. // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
  25. function circleRadius(cosRadius, point) {
  26. point = cartesian(point), point[0] -= cosRadius;
  27. cartesianNormalizeInPlace(point);
  28. var radius = acos(-point[1]);
  29. return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau;
  30. }
  31. export default function() {
  32. var center = constant([0, 0]),
  33. radius = constant(90),
  34. precision = constant(6),
  35. ring,
  36. rotate,
  37. stream = {point: point};
  38. function point(x, y) {
  39. ring.push(x = rotate(x, y));
  40. x[0] *= degrees, x[1] *= degrees;
  41. }
  42. function circle() {
  43. var c = center.apply(this, arguments),
  44. r = radius.apply(this, arguments) * radians,
  45. p = precision.apply(this, arguments) * radians;
  46. ring = [];
  47. rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
  48. circleStream(stream, r, p, 1);
  49. c = {type: "Polygon", coordinates: [ring]};
  50. ring = rotate = null;
  51. return c;
  52. }
  53. circle.center = function(_) {
  54. return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center;
  55. };
  56. circle.radius = function(_) {
  57. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius;
  58. };
  59. circle.precision = function(_) {
  60. return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision;
  61. };
  62. return circle;
  63. }