Search code examples
d3.jsgeo

How to translate MKT expression to D3 options on Albers projection?


This is the standard MKT expression (here also translated to Proj.4 string) of Albers conicEqualArea for official Statistical Grid of Brazil:

PROJCS["Conica_Equivalente_de_Albers_Brasil",
    GEOGCS["GCS_SIRGAS2000",
        DATUM["D_SIRGAS2000",
            SPHEROID["Geodetic_Reference_System_of_1980",6378137,298.2572221009113]],
        PRIMEM["Greenwich",0],
        UNIT["Degree",0.017453292519943295]],
    PROJECTION["Albers"],
    PARAMETER["standard_parallel_1",-2],
    PARAMETER["standard_parallel_2",-22],
    PARAMETER["latitude_of_origin",-12],
    PARAMETER["central_meridian",-54],
    PARAMETER["false_easting",5000000],
    PARAMETER["false_northing",10000000],
    UNIT["Meter",1]]

The DATUM is the WGS 84 ("SIRGAS2000" is a alias for it).

How to translate all details to the D3.js v5 parametrization?

I try the obvious, as center and parallels, but it was not sufficient

var projection = d3.geoConicEqualArea()
  .parallels([-2,-22])  // IS IT?
  .scale(815)
  //.rotate([??,??]) // HERE THE PROBLEM... 
  .center([-54, -12])  // IS IT?

PS: where the D3 documentation for it? The D3 source-code of geoConicEqualArea() have no clues.


Solution

  • The parts that translate to a d3 Albers projection are as follows:

        PROJECTION["Albers"],
        PARAMETER["standard_parallel_1",-2],
        PARAMETER["standard_parallel_2",-22],
        PARAMETER["latitude_of_origin",-12],
        PARAMETER["central_meridian",-54],
    

    You have the parallels, now you need to rotate. Also note, for any D3 projection, the rotation is applied to the centering coordinates. Generally, you'll want to rotate on the x and center on the y:

    d3.geoAlbers()
     .parallels([-2,-22])
     .center([0,-12])
     .rotate([54,0])
     .translate([width/2,height/2])
     .scale(k)
    

    I've rotated in the opposite direction along the x axis (rotated the earth under me so that I'm overtop of the central meridian, hence my rotation by -x). I've then centered on the y. Lastly I translate so that the intersection of the central longitude and meridian is centered in the map and apply a scale value that is appropriate.

    If I want to center on a different area but keep the projection the same, I can modify projection.center(), but keep in mind that the coordinates provided here are relative to the rotation. I can also use projection.fitSize() or projection.fitExtent(), both of which set 'translate' and 'scale' values for the projection. None of center/scale/translate change the distortion in the D3 projection.

    Of course this isn't a true replication of your projection as the coordinate space units are pixels, you will remain unable to measure distances in meters directly without some extra work.

    See also