| 1 | import clipRectangle from "../clip/rectangle.js";
|
|---|
| 2 | import identity from "../identity.js";
|
|---|
| 3 | import {transformer} from "../transform.js";
|
|---|
| 4 | import {fitExtent, fitSize, fitWidth, fitHeight} from "./fit.js";
|
|---|
| 5 | import {cos, degrees, radians, sin} from "../math.js";
|
|---|
| 6 |
|
|---|
| 7 | export default function() {
|
|---|
| 8 | var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, // scale, translate and reflect
|
|---|
| 9 | alpha = 0, ca, sa, // angle
|
|---|
| 10 | x0 = null, y0, x1, y1, // clip extent
|
|---|
| 11 | kx = 1, ky = 1,
|
|---|
| 12 | transform = transformer({
|
|---|
| 13 | point: function(x, y) {
|
|---|
| 14 | var p = projection([x, y])
|
|---|
| 15 | this.stream.point(p[0], p[1]);
|
|---|
| 16 | }
|
|---|
| 17 | }),
|
|---|
| 18 | postclip = identity,
|
|---|
| 19 | cache,
|
|---|
| 20 | cacheStream;
|
|---|
| 21 |
|
|---|
| 22 | function reset() {
|
|---|
| 23 | kx = k * sx;
|
|---|
| 24 | ky = k * sy;
|
|---|
| 25 | cache = cacheStream = null;
|
|---|
| 26 | return projection;
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | function projection (p) {
|
|---|
| 30 | var x = p[0] * kx, y = p[1] * ky;
|
|---|
| 31 | if (alpha) {
|
|---|
| 32 | var t = y * ca - x * sa;
|
|---|
| 33 | x = x * ca + y * sa;
|
|---|
| 34 | y = t;
|
|---|
| 35 | }
|
|---|
| 36 | return [x + tx, y + ty];
|
|---|
| 37 | }
|
|---|
| 38 | projection.invert = function(p) {
|
|---|
| 39 | var x = p[0] - tx, y = p[1] - ty;
|
|---|
| 40 | if (alpha) {
|
|---|
| 41 | var t = y * ca + x * sa;
|
|---|
| 42 | x = x * ca - y * sa;
|
|---|
| 43 | y = t;
|
|---|
| 44 | }
|
|---|
| 45 | return [x / kx, y / ky];
|
|---|
| 46 | };
|
|---|
| 47 | projection.stream = function(stream) {
|
|---|
| 48 | return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
|
|---|
| 49 | };
|
|---|
| 50 | projection.postclip = function(_) {
|
|---|
| 51 | return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
|
|---|
| 52 | };
|
|---|
| 53 | projection.clipExtent = function(_) {
|
|---|
| 54 | return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
|
|---|
| 55 | };
|
|---|
| 56 | projection.scale = function(_) {
|
|---|
| 57 | return arguments.length ? (k = +_, reset()) : k;
|
|---|
| 58 | };
|
|---|
| 59 | projection.translate = function(_) {
|
|---|
| 60 | return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
|
|---|
| 61 | }
|
|---|
| 62 | projection.angle = function(_) {
|
|---|
| 63 | return arguments.length ? (alpha = _ % 360 * radians, sa = sin(alpha), ca = cos(alpha), reset()) : alpha * degrees;
|
|---|
| 64 | };
|
|---|
| 65 | projection.reflectX = function(_) {
|
|---|
| 66 | return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
|
|---|
| 67 | };
|
|---|
| 68 | projection.reflectY = function(_) {
|
|---|
| 69 | return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
|
|---|
| 70 | };
|
|---|
| 71 | projection.fitExtent = function(extent, object) {
|
|---|
| 72 | return fitExtent(projection, extent, object);
|
|---|
| 73 | };
|
|---|
| 74 | projection.fitSize = function(size, object) {
|
|---|
| 75 | return fitSize(projection, size, object);
|
|---|
| 76 | };
|
|---|
| 77 | projection.fitWidth = function(width, object) {
|
|---|
| 78 | return fitWidth(projection, width, object);
|
|---|
| 79 | };
|
|---|
| 80 | projection.fitHeight = function(height, object) {
|
|---|
| 81 | return fitHeight(projection, height, object);
|
|---|
| 82 | };
|
|---|
| 83 |
|
|---|
| 84 | return projection;
|
|---|
| 85 | }
|
|---|