|
3313 | 3313 | }
|
3314 | 3314 | };
|
3315 | 3315 | };
|
| 3316 | + d3.geo.graticule = function() { |
| 3317 | + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; |
| 3318 | + function graticule() { |
| 3319 | + return { |
| 3320 | + type: "MultiLineString", |
| 3321 | + coordinates: lines() |
| 3322 | + }; |
| 3323 | + } |
| 3324 | + function lines() { |
| 3325 | + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { |
| 3326 | + return abs(x % DX) > ε; |
| 3327 | + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { |
| 3328 | + return abs(y % DY) > ε; |
| 3329 | + }).map(y)); |
| 3330 | + } |
| 3331 | + graticule.lines = function() { |
| 3332 | + return lines().map(function(coordinates) { |
| 3333 | + return { |
| 3334 | + type: "LineString", |
| 3335 | + coordinates: coordinates |
| 3336 | + }; |
| 3337 | + }); |
| 3338 | + }; |
| 3339 | + graticule.outline = function() { |
| 3340 | + return { |
| 3341 | + type: "Polygon", |
| 3342 | + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] |
| 3343 | + }; |
| 3344 | + }; |
| 3345 | + graticule.extent = function(_) { |
| 3346 | + if (!arguments.length) return graticule.minorExtent(); |
| 3347 | + return graticule.majorExtent(_).minorExtent(_); |
| 3348 | + }; |
| 3349 | + graticule.majorExtent = function(_) { |
| 3350 | + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; |
| 3351 | + X0 = +_[0][0], X1 = +_[1][0]; |
| 3352 | + Y0 = +_[0][1], Y1 = +_[1][1]; |
| 3353 | + if (X0 > X1) _ = X0, X0 = X1, X1 = _; |
| 3354 | + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; |
| 3355 | + return graticule.precision(precision); |
| 3356 | + }; |
| 3357 | + graticule.minorExtent = function(_) { |
| 3358 | + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; |
| 3359 | + x0 = +_[0][0], x1 = +_[1][0]; |
| 3360 | + y0 = +_[0][1], y1 = +_[1][1]; |
| 3361 | + if (x0 > x1) _ = x0, x0 = x1, x1 = _; |
| 3362 | + if (y0 > y1) _ = y0, y0 = y1, y1 = _; |
| 3363 | + return graticule.precision(precision); |
| 3364 | + }; |
| 3365 | + graticule.step = function(_) { |
| 3366 | + if (!arguments.length) return graticule.minorStep(); |
| 3367 | + return graticule.majorStep(_).minorStep(_); |
| 3368 | + }; |
| 3369 | + graticule.majorStep = function(_) { |
| 3370 | + if (!arguments.length) return [ DX, DY ]; |
| 3371 | + DX = +_[0], DY = +_[1]; |
| 3372 | + return graticule; |
| 3373 | + }; |
| 3374 | + graticule.minorStep = function(_) { |
| 3375 | + if (!arguments.length) return [ dx, dy ]; |
| 3376 | + dx = +_[0], dy = +_[1]; |
| 3377 | + return graticule; |
| 3378 | + }; |
| 3379 | + graticule.precision = function(_) { |
| 3380 | + if (!arguments.length) return precision; |
| 3381 | + precision = +_; |
| 3382 | + x = d3_geo_graticuleX(y0, y1, 90); |
| 3383 | + y = d3_geo_graticuleY(x0, x1, precision); |
| 3384 | + X = d3_geo_graticuleX(Y0, Y1, 90); |
| 3385 | + Y = d3_geo_graticuleY(X0, X1, precision); |
| 3386 | + return graticule; |
| 3387 | + }; |
| 3388 | + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); |
| 3389 | + }; |
| 3390 | + function d3_geo_graticuleX(y0, y1, dy) { |
| 3391 | + var y = d3.range(y0, y1 - ε, dy).concat(y1); |
| 3392 | + return function(x) { |
| 3393 | + return y.map(function(y) { |
| 3394 | + return [ x, y ]; |
| 3395 | + }); |
| 3396 | + }; |
| 3397 | + } |
| 3398 | + function d3_geo_graticuleY(x0, x1, dx) { |
| 3399 | + var x = d3.range(x0, x1 - ε, dx).concat(x1); |
| 3400 | + return function(y) { |
| 3401 | + return x.map(function(x) { |
| 3402 | + return [ x, y ]; |
| 3403 | + }); |
| 3404 | + }; |
| 3405 | + } |
3316 | 3406 | d3.geom = {};
|
3317 | 3407 | function d3_geom_pointX(d) {
|
3318 | 3408 | return d[0];
|
|
0 commit comments