summaryrefslogtreecommitdiff
path: root/src/circle.js
diff options
context:
space:
mode:
authorPirate Praveen <praveen@debian.org>2017-10-09 11:57:35 +0530
committerPirate Praveen <praveen@debian.org>2017-10-09 11:57:35 +0530
commit3db5c79f87119a5b46ab63cbfa6050700a978117 (patch)
treece0bc40cb6a86a7c0e20c6c9cbde83e18b1d9c44 /src/circle.js
Import Upstream version 1.9.0
Diffstat (limited to 'src/circle.js')
-rw-r--r--src/circle.js72
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;
+}