Visualize.Geo.Projection (Visualize v0.2.35)

Copy Markdown View Source

Geographic projections for mapping spherical coordinates to a plane.

Transforms longitude/latitude coordinates to x/y pixel coordinates for rendering maps.

Supported Projections

Cylindrical

  • :mercator - Conformal cylindrical (web maps)
  • :transverse_mercator - Transverse Mercator (UTM zones)
  • :equirectangular - Simple plate carrée
  • :cylindrical_equal_area - Lambert cylindrical equal-area

Azimuthal

  • :orthographic - Globe/hemisphere view
  • :stereographic - Conformal azimuthal
  • :gnomonic - Gnomonic (great circles as straight lines)
  • :azimuthal_equal_area - Lambert azimuthal equal-area
  • :azimuthal_equidistant - Equidistant azimuthal

Conic

  • :albers - Albers equal-area conic
  • :conic_conformal - Lambert conformal conic
  • :conic_equal_area - Conic equal-area
  • :conic_equidistant - Conic equidistant

Pseudocylindrical

  • :mollweide - Mollweide equal-area
  • :sinusoidal - Sinusoidal equal-area
  • :eckert1 - Eckert I (rectilinear)
  • :eckert2 - Eckert II (equal-area)
  • :eckert3 - Eckert III
  • :eckert4 - Eckert IV equal-area
  • :eckert5 - Eckert V
  • :eckert6 - Eckert VI equal-area
  • :hammer - Hammer (Hammer-Aitoff) equal-area
  • :kavrayskiy7 - Kavrayskiy VII compromise
  • :wagner4 - Wagner IV equal-area
  • :wagner6 - Wagner VI compromise
  • :fahey - Fahey pseudocylindrical
  • :collignon - Collignon (triangular)
  • :loximuthal - Loximuthal (rhumb lines straight)

Compromise/Polyconic

  • :natural_earth - Natural Earth projection
  • :equal_earth - Equal Earth (modern equal-area, 2018)
  • :robinson - Robinson compromise
  • :winkel_tripel - Winkel tripel (National Geographic)
  • :aitoff - Aitoff pseudoazimuthal
  • :van_der_grinten - Van der Grinten (circular)
  • :miller - Miller cylindrical
  • :gall_peters - Gall-Peters equal-area cylindrical
  • :bonne - Bonne pseudoconic (heart-shaped)
  • :polyconic - American Polyconic

Examples

projection = Visualize.Geo.Projection.new(:mercator)
  |> Visualize.Geo.Projection.scale(100)
  |> Visualize.Geo.Projection.translate(200, 150)
  |> Visualize.Geo.Projection.center(-95, 40)

# Project a point
{x, y} = Visualize.Geo.Projection.project(projection, -122.4, 37.8)

# Inverse projection
{lon, lat} = Visualize.Geo.Projection.invert(projection, x, y)

Summary

Functions

Returns the projection's visible bounds as [x0, y0, x1, y1]

Sets the center point (longitude, latitude)

Sets the clip angle for azimuthal projections (in degrees)

Fits the projection to a list of {lon, lat} points (spec/07 §1.6, #475): d3-geo's fitExtent over points.

Fits the projection to the specified extent for the given GeoJSON bounds.

Inverse projection: converts pixel coordinates (x, y) to geographic (lon, lat).

Creates a new projection of the specified type

Sets the standard parallels for conic projections

Sets the precision (spec/07 §1.1): 0 draws the edge a path is clipped along as d3-geo does at precision(0), its interpolation points joined by straight segments; any other value samples that edge every degree (§2.2).

Projects a geographic point (longitude, latitude) to pixel coordinates (x, y).

Sets the rotation (lambda, phi, gamma), in degrees: d3-geo's projection.rotate at [-lambda, phi, gamma] (spec/07 §1.4).

Sets the scale factor

The projection's outline as a closed list of {x, y} pixel points (spec/07 §1.6): the sphere of d3-geo's {type: "Sphere"}.

Sets the translation offset

Types

projection_type()

@type projection_type() ::
  :mercator
  | :transverse_mercator
  | :equirectangular
  | :cylindrical_equal_area
  | :miller
  | :gall_peters
  | :orthographic
  | :stereographic
  | :gnomonic
  | :azimuthal_equal_area
  | :azimuthal_equidistant
  | :albers
  | :conic_conformal
  | :conic_equal_area
  | :conic_equidistant
  | :bonne
  | :polyconic
  | :mollweide
  | :sinusoidal
  | :eckert1
  | :eckert2
  | :eckert3
  | :eckert4
  | :eckert5
  | :eckert6
  | :hammer
  | :kavrayskiy7
  | :wagner4
  | :wagner6
  | :fahey
  | :collignon
  | :loximuthal
  | :natural_earth
  | :equal_earth
  | :robinson
  | :winkel_tripel
  | :aitoff
  | :van_der_grinten

t()

@type t() :: %Visualize.Geo.Projection{
  center: {number(), number()},
  clip_angle: number() | nil,
  parallels: {number(), number()},
  precision: number(),
  rotate: {number(), number(), number()},
  scale: number(),
  translate: {number(), number()},
  type: projection_type()
}

Functions

bounds(proj)

@spec bounds(t()) :: [number()]

Returns the projection's visible bounds as [x0, y0, x1, y1]

center(proj, lon, lat)

@spec center(t(), number(), number()) :: t()

Sets the center point (longitude, latitude)

clip_angle(proj, angle)

@spec clip_angle(t(), number() | nil) :: t()

Sets the clip angle for azimuthal projections (in degrees)

fit(proj, list, points)

@spec fit(t(), [[number()]], [{number(), number()}]) :: t()

Fits the projection to a list of {lon, lat} points (spec/07 §1.6, #475): d3-geo's fitExtent over points.

The points are projected at scale 150 and translate {0, 0}, and scale and translate are set so their projected bounds fill the pixel box [[x0, y0], [x1, y1]] on the tighter axis and are centred in it. center, rotate, clip_angle and parallels are untouched, so a Mercator projection stays Web-Mercator. An axis along which the points have no extent does not bound the scale; with no extent on either the scale is kept and the point is centred; with no projectable point the projection is returned unchanged.

Examples

iex> proj =
...>   Visualize.Geo.Projection.new(:mercator)
...>   |> Visualize.Geo.Projection.fit([[0, 0], [100, 100]], [{-10, 0}, {10, 0}])
iex> {x0, _} = Visualize.Geo.Projection.project(proj, -10, 0)
iex> {x1, _} = Visualize.Geo.Projection.project(proj, 10, 0)
iex> {Float.round(x0, 6), Float.round(x1, 6), proj.center}
{0.0, 100.0, {0, 0}}

fit_extent(proj, list1, list2)

@spec fit_extent(t(), [[number()]], [[number()]]) :: t()

Fits the projection to the specified extent for the given GeoJSON bounds.

extent is [[x0, y0], [x1, y1]] in pixels bounds is [[lon0, lat0], [lon1, lat1]] in degrees

invert(proj, x, y)

@spec invert(t(), number(), number()) :: {float(), float()} | nil

Inverse projection: converts pixel coordinates (x, y) to geographic (lon, lat).

new(type \\ :mercator)

@spec new(projection_type()) :: t()

Creates a new projection of the specified type

parallels(proj, phi0, phi1)

@spec parallels(t(), number(), number()) :: t()

Sets the standard parallels for conic projections

precision(proj, precision)

@spec precision(t(), number()) :: t()

Sets the precision (spec/07 §1.1): 0 draws the edge a path is clipped along as d3-geo does at precision(0), its interpolation points joined by straight segments; any other value samples that edge every degree (§2.2).

project(proj, lon, lat)

@spec project(t(), number(), number()) :: {float(), float()} | nil

Projects a geographic point (longitude, latitude) to pixel coordinates (x, y).

rotate(proj, lambda, phi, gamma \\ 0)

@spec rotate(t(), number(), number(), number()) :: t()

Sets the rotation (lambda, phi, gamma), in degrees: d3-geo's projection.rotate at [-lambda, phi, gamma] (spec/07 §1.4).

  • lambda: the central meridian — the longitude turned to the centre (d3's λ with the opposite sign)
  • phi: d3's φ, a tilt toward or away from the viewer — -20 brings 20° N to the centre of an azimuthal view
  • gamma: d3's γ, a roll about the viewing axis

scale(proj, s)

@spec scale(t(), number()) :: t()

Sets the scale factor

sphere(proj)

@spec sphere(t()) :: [{float(), float()}]

The projection's outline as a closed list of {x, y} pixel points (spec/07 §1.6): the sphere of d3-geo's {type: "Sphere"}.

With a clip_angle it is the small circle at that angular distance from the centre, taken in the rotated and centred frame so rotate and center turn the globe under it, at 360 bearings and projected without the clip test; without one it is the map's edge — the antimeridian on either side and the two poles, sampled every degree, at latitude ±85 for the Mercators and ±90 otherwise. A point the raw projection cannot place is dropped.

translate(proj, x, y)

@spec translate(t(), number(), number()) :: t()

Sets the translation offset