toolkit/exemples/couple/javascript/d3/src/geo/albers.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 // Derived from Tom Carden's Albers implementation for Protovis.
       
     2 // http://gist.github.com/476238
       
     3 // http://mathworld.wolfram.com/AlbersEqual-AreaConicProjection.html
       
     4 
       
     5 d3.geo.albers = function() {
       
     6   var origin = [-98, 38],
       
     7       parallels = [29.5, 45.5],
       
     8       scale = 1000,
       
     9       translate = [480, 250],
       
    10       lng0, // d3_geo_radians * origin[0]
       
    11       n,
       
    12       C,
       
    13       p0;
       
    14 
       
    15   function albers(coordinates) {
       
    16     var t = n * (d3_geo_radians * coordinates[0] - lng0),
       
    17         p = Math.sqrt(C - 2 * n * Math.sin(d3_geo_radians * coordinates[1])) / n;
       
    18     return [
       
    19       scale * p * Math.sin(t) + translate[0],
       
    20       scale * (p * Math.cos(t) - p0) + translate[1]
       
    21     ];
       
    22   }
       
    23 
       
    24   albers.invert = function(coordinates) {
       
    25     var x = (coordinates[0] - translate[0]) / scale,
       
    26         y = (coordinates[1] - translate[1]) / scale,
       
    27         p0y = p0 + y,
       
    28         t = Math.atan2(x, p0y),
       
    29         p = Math.sqrt(x * x + p0y * p0y);
       
    30     return [
       
    31       (lng0 + t / n) / d3_geo_radians,
       
    32       Math.asin((C - p * p * n * n) / (2 * n)) / d3_geo_radians
       
    33     ];
       
    34   };
       
    35 
       
    36   function reload() {
       
    37     var phi1 = d3_geo_radians * parallels[0],
       
    38         phi2 = d3_geo_radians * parallels[1],
       
    39         lat0 = d3_geo_radians * origin[1],
       
    40         s = Math.sin(phi1),
       
    41         c = Math.cos(phi1);
       
    42     lng0 = d3_geo_radians * origin[0];
       
    43     n = .5 * (s + Math.sin(phi2));
       
    44     C = c * c + 2 * n * s;
       
    45     p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;
       
    46     return albers;
       
    47   }
       
    48 
       
    49   albers.origin = function(x) {
       
    50     if (!arguments.length) return origin;
       
    51     origin = [+x[0], +x[1]];
       
    52     return reload();
       
    53   };
       
    54 
       
    55   albers.parallels = function(x) {
       
    56     if (!arguments.length) return parallels;
       
    57     parallels = [+x[0], +x[1]];
       
    58     return reload();
       
    59   };
       
    60 
       
    61   albers.scale = function(x) {
       
    62     if (!arguments.length) return scale;
       
    63     scale = +x;
       
    64     return albers;
       
    65   };
       
    66 
       
    67   albers.translate = function(x) {
       
    68     if (!arguments.length) return translate;
       
    69     translate = [+x[0], +x[1]];
       
    70     return albers;
       
    71   };
       
    72 
       
    73   return reload();
       
    74 };
       
    75 
       
    76 // A composite projection for the United States, 960x500. The set of standard
       
    77 // parallels for each region comes from USGS, which is published here:
       
    78 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
       
    79 // TODO allow the composite projection to be rescaled?
       
    80 d3.geo.albersUsa = function() {
       
    81   var lower48 = d3.geo.albers();
       
    82 
       
    83   var alaska = d3.geo.albers()
       
    84       .origin([-160, 60])
       
    85       .parallels([55, 65]);
       
    86 
       
    87   var hawaii = d3.geo.albers()
       
    88       .origin([-160, 20])
       
    89       .parallels([8, 18]);
       
    90 
       
    91   var puertoRico = d3.geo.albers()
       
    92       .origin([-60, 10])
       
    93       .parallels([8, 18]);
       
    94 
       
    95   function albersUsa(coordinates) {
       
    96     var lon = coordinates[0],
       
    97         lat = coordinates[1];
       
    98     return (lat > 50 ? alaska
       
    99         : lon < -140 ? hawaii
       
   100         : lat < 21 ? puertoRico
       
   101         : lower48)(coordinates);
       
   102   }
       
   103 
       
   104   albersUsa.scale = function(x) {
       
   105     if (!arguments.length) return lower48.scale();
       
   106     lower48.scale(x);
       
   107     alaska.scale(x * .6);
       
   108     hawaii.scale(x);
       
   109     puertoRico.scale(x * 1.5);
       
   110     return albersUsa.translate(lower48.translate());
       
   111   };
       
   112 
       
   113   albersUsa.translate = function(x) {
       
   114     if (!arguments.length) return lower48.translate();
       
   115     var dz = lower48.scale() / 1000,
       
   116         dx = x[0],
       
   117         dy = x[1];
       
   118     lower48.translate(x);
       
   119     alaska.translate([dx - 400 * dz, dy + 170 * dz]);
       
   120     hawaii.translate([dx - 190 * dz, dy + 200 * dz]);
       
   121     puertoRico.translate([dx + 580 * dz, dy + 430 * dz]);
       
   122     return albersUsa;
       
   123   };
       
   124 
       
   125   return albersUsa.scale(lower48.scale());
       
   126 };