You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.3 KiB
72 lines
2.3 KiB
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; |
|
}
|
|
|