d3-geo projection methods
Geographic projection methods: projection.invert (unproject point from plane to sphere), projection.stream (wrap stream to project geometry), projection.preclip (set spherical clipping), projection.postclip (set cartesian clipping), projection.clipAngle (set clip circle radius), projection.clipExtent (set viewport extent), projection.scale (set scale factor), projection.translate (set translation offset), projection.center (set center point), projection.angle (set post-projection rotation), projection.reflectX (reflect x-dimension), projection.reflectY (reflect y-dimension), projection.rotate (set three-axis spherical rotation), projection.precision (set precision threshold), projection.fitExtent, projection.fitSize, projection.fitWidth, projection.fitHeight (fit to GeoJSON).
Mercator projection implementation example
A basic spherical Mercator projection takes longitude (lambda) and latitude (phi) in radians and returns an [x, y] position on the plane. The implementation is: function mercator(lambda, phi) { const x = lambda; const y = Math.log(Math.tan(Math.PI / 4 + phi / 2)); return [x, y]; }
Why discrete geometry needs special handling in projections
Map projections must handle discrete geometry such as polygons and polylines specially. The edges of spherical polygons are geodesics (segments of great circles), not straight lines. Geodesics become curves in all map projections except gnomonic projections, so accurate projection requires interpolation along each arc. D3 uses adaptive sampling inspired by Visvalingam's line simplification method to balance accuracy and performance.
Antimeridian crossing in map projections
Some projections require cutting geometry that crosses the antimeridian when projecting polygons and polylines from the sphere to the plane.
Clipping geometry to a great circle
Some projections require clipping geometry to a great circle when projecting from the sphere to the plane.
D3 supports common and unusual map projections
D3 supports a wide variety of common and unusual map projections. Unusual projections are available in the d3-geo-projection package.
projection(point) - project a point
Calling a projection with a point projects it from spherical to planar coordinates. The input point must be a two-element array [longitude, latitude] in degrees. The output is a new array [x, y] typically in pixels representing the projected point. May return null if the point has no defined projected position, such as when outside the clipping bounds.
projection.invert(point) - inverse projection
Returns a new array [longitude, latitude] in degrees representing the unprojected point of the given projected point. The input point must be a two-element array [x, y] typically in pixels. May return null if the point is outside clipping bounds. This method is only defined on invertible projections.
projection.stream(stream) - get projection stream
Returns a projection stream for the specified output stream. Any input geometry is projected before being streamed to the output stream. A typical projection involves several geometry transformations: input geometry is converted to radians, rotated on three axes, clipped to the small circle or cut along the antimeridian, and lastly projected to the plane with adaptive resampling, scale and translation.
projection.preclip(preclip) - set spherical clipping
If preclip is specified, sets the projection's spherical clipping to the specified function and returns the projection. The preclip argument is a function that takes a projection stream and returns a clipped stream. If preclip is not specified, returns the current spherical clipping function. Preclipping is commonly used to cut along the antimeridian line or along a small circle.
projection.postclip(postclip) - set Cartesian clipping
If postclip is specified, sets the projection's Cartesian clipping to the specified function and returns the projection. The postclip argument is a function that takes a projection stream and returns a clipped stream. If postclip is not specified, returns the current Cartesian clipping function. Post-clipping occurs on the plane when a projection is bounded to a certain extent such as a rectangle.
projection.clipAngle(angle) - small-circle clipping radius
If angle is specified, sets the projection's clipping circle radius to the specified angle in degrees and returns the projection. If angle is null, switches to antimeridian cutting rather than small-circle clipping. If angle is not specified, returns the current clip angle which defaults to null. Small-circle clipping is independent of viewport clipping via projection.clipExtent.
projection.clipExtent(extent) - viewport clipping bounds
If extent is specified, sets the projection's viewport clip extent to the specified bounds in pixels and returns the projection. The extent bounds are specified as an array [[x₀, y₀], [x₁, y₁]], where x₀ is the left side, y₀ is the top, x₁ is the right and y₁ is the bottom. If extent is null, no viewport clipping is performed. If extent is not specified, returns the current viewport clip extent which defaults to null. Viewport clipping is independent of small-circle clipping via projection.clipAngle.
projection.scale(scale) - scale factor
If scale is specified, sets the projection's scale factor to the specified value and returns the projection. If scale is not specified, returns the current scale factor; the default scale is projection-specific. The scale factor corresponds linearly to the distance between projected points; however, absolute scale factors are not equivalent across projections.
projection.translate(translate) - translation offset
If translate is specified, sets the projection's translation offset to the specified two-element array [tx, ty] and returns the projection. If translate is not specified, returns the current translation offset which defaults to [480, 250]. The translation offset determines the pixel coordinates of the projection's center. The default translation offset places ⟨0°,0°⟩ at the center of a 960×500 area.
projection.center(center) - projection center
If center is specified, sets the projection's center to the specified center, a two-element array of [longitude, latitude] in degrees, and returns the projection. If center is not specified, returns the current center, which defaults to ⟨0°,0°⟩.
projection.angle(angle) - post-projection planar rotation
If angle is specified, sets the projection's post-projection planar rotation angle to the specified angle in degrees and returns the projection. If angle is not specified, returns the projection's current angle, which defaults to 0°. Note that it may be faster to rotate during rendering using context.rotate rather than during projection.
projection.reflectX(reflect) - x-dimension reflection
If reflect is specified, sets whether or not the x-dimension is reflected (negated) in the output. If reflect is not specified, returns true if x-reflection is enabled, which defaults to false. This can be useful to display sky and astronomical data with the orb seen from below: right ascension (eastern direction) will point to the left when North is pointing up.
projection.reflectY(reflect) - y-dimension reflection
If reflect is specified, sets whether or not the y-dimension is reflected (negated) in the output. If reflect is not specified, returns true if y-reflection is enabled, which defaults to false. This is especially useful for transforming from standard spatial reference systems, which treat positive y as pointing up, to display coordinate systems such as Canvas and SVG, which treat positive y as pointing down.
projection.rotate(angles) - three-axis spherical rotation
If angles is specified, sets the projection's three-axis spherical rotation to the specified value, which must be a two- or three-element array of numbers [lambda, phi, gamma] specifying the rotation angles in degrees about each spherical axis (corresponding to yaw, pitch and roll). If the rotation angle gamma is omitted, it defaults to 0. If angles is not specified, returns the current rotation which defaults to [0, 0, 0].
projection.precision(precision) - adaptive resampling threshold
If precision is specified, sets the threshold for the projection's adaptive resampling to the specified value in pixels and returns the projection. This value corresponds to the Douglas–Peucker distance. If precision is not specified, returns the projection's current resampling precision which defaults to √0.5 ≅ 0.70710…
projection.fitExtent(extent, object) - fit GeoJSON to extent
Sets the projection's scale and translate to fit the specified GeoJSON object in the center of the given extent. The extent is specified as an array [[x₀, y₀], [x₁, y₁]], where x₀ is the left side, y₀ is the top, x₁ is the right and y₁ is the bottom. Returns the projection. Any clip extent is ignored when determining the new scale and translate. The precision used to compute the bounding box is computed at an effective scale of 150.
projection.fitExtent(extent, object) example with New Jersey State Plane
Example showing how to fit a GeoJSON object to a bounding box with padding: var projection = d3.geoTransverseMercator().rotate([74 + 30 / 60, -38 - 50 / 60]).fitExtent([[20, 20], [940, 480]], nj);
projection.fitSize(size, object) - fit to size
A convenience method for projection.fitExtent where the top-left corner of the extent is [0, 0]. The following two statements are equivalent: projection.fitExtent([[0, 0], [width, height]], object); and projection.fitSize([width, height], object);
projection.fitHeight(height, object) - fit to height
A convenience method for projection.fitSize where the width is automatically chosen from the aspect ratio of object and the given constraint on height.
Raw projection - point transformation
Raw projections are point transformation functions used to implement custom projections; they are typically passed to geoProjection or geoProjectionMutator. Raw projections take spherical coordinates [lambda, phi] in radians (not degrees) and return a point [x, y], typically in the unit square centered around the origin.
project(lambda, phi) - raw projection function
Projects the specified point [lambda, phi] in radians, returning a new point [x, y] in unitless coordinates.
project.invert(x, y) - raw projection inverse
The inverse of the raw project function, converting unitless [x, y] coordinates back to [lambda, phi] in radians.
geoProjection(project) - construct projection from raw function
Constructs a new projection from the specified raw projection function. The project function takes longitude and latitude in radians (lambda and phi) and returns a two-element array [x, y] representing its unit projection. The project function does not need to scale, translate, or rotate the point, as these are applied automatically by projection.scale, projection.translate, projection.center, and projection.rotate. If the project function exposes an invert method, the returned projection will also expose projection.invert.
geoProjection(project) example - spherical Mercator
Example of implementing a spherical Mercator projection: var mercator = d3.geoProjection(function(x, y) { return [x, Math.log(Math.tan(Math.PI / 4 + y / 2))]; });
geoProjectionMutator(factory) - construct mutable projection
Constructs a new projection from the specified raw projection factory and returns a mutate function to call whenever the raw projection changes. The factory must return a raw projection. The returned mutate function returns the wrapped projection. This is useful for projections with configurable parameters, such as conic projections with two configurable parallels.
geoProjectionMutator(factory) example - conic projection
Example showing how to implement a mutable conic projection with configurable parallels: function conicFactory(phi0, phi1) { return function conicRaw(lambda, phi) { return [..., ...]; }; } function conicCustom() { var phi0 = 29.5, phi1 = 45.5, mutate = d3.geoProjectionMutator(conicFactory), projection = mutate(phi0, phi1); projection.parallels = function(_) { return arguments.length ? mutate(phi0 = +_[0], phi1 = +_[1]) : [phi0, phi1]; }; return projection; }
geoTransform(methods) - arbitrary geometric transform
Defines an arbitrary transform using the methods defined on the specified methods object. Any undefined methods will use pass-through methods that propagate inputs to the output stream. A transform is a generalized projection; it implements projection.stream and can be passed to path.projection, but implements only a subset of other projection methods and represent arbitrary geometric transformations rather than projections from spherical to planar coordinates.
geoTransform(methods) example - reflect y-dimension
Example showing how to reflect the y-dimension: const reflectY = d3.geoTransform({ point(x, y) { this.stream.point(x, -y); } });
geoTransform(methods) example - affine matrix transformation
Example showing how to define an affine matrix transformation: function matrix(a, b, c, d, tx, ty) { return d3.geoTransform({ point(x, y) { this.stream.point(a * x + b * y + tx, c * x + d * y + ty); } }); }
geoIdentity() - identity transform
The identity transform can be used to scale, translate and clip planar geometry. It implements projection.scale, projection.translate, projection.fitExtent, projection.fitSize, projection.fitWidth, projection.fitHeight, projection.clipExtent, projection.angle, projection.reflectX and projection.reflectY.
geoClipAntimeridian - antimeridian clipping function
A clipping function which transforms a stream such that geometries (lines or polygons) that cross the antimeridian line are cut in two, one on each side. Typically used for pre-clipping.
geoClipCircle(angle) - small circle clipping function
Generates a clipping function which transforms a stream such that geometries are bounded by a small circle of radius angle around the projection's center. Typically used for pre-clipping.
geoClipRectangle(x0, y0, x1, y1) - rectangle clipping function
Generates a clipping function which transforms a stream such that geometries are bounded by a rectangle of coordinates [[x0, y0], [x1, y1]]. Typically used for post-clipping.
Projection classes available in D3
D3 provides implementations of several classes of standard projections: azimuthal projections, conic projections, and cylindrical projections. For more projections, see d3-geo-projection and d3-geo-polygon. Custom projections can be implemented using geoProjection or geoProjectionMutator.