Skip to content

Centroid transform ^0.6.2

Plot offers two transforms that derive centroids from GeoJSON geometries: centroid and geoCentroid. These transforms can be used by any mark that accepts x and y channels. Below, a text mark labels the U.S. states.

Fork
js
Plot.plot({
  projection: "albers-usa",
  marks: [
    Plot.geo(statemesh),
    Plot.text(states, Plot.centroid({text: (d) => d.properties.name, fill: "currentColor", stroke: "white"}))
  ]
})

For fun, we can pass county centroids to the voronoi mark.

Fork
js
Plot.voronoi(counties, Plot.centroid()).plot({projection: "albers"})

While the centroid transform computes the centroid of a geometry after projection, the geoCentroid transform computes it before projection, then projects the resulting coordinates. This difference has a few implications, as follows.

As an initializer, the centroid transform operates after the geometries have been projected to screen coordinates. The resulting x and y channels reference the pixel coordinates of the planar centroid of the projected shapes. No assumption is made about the geometries: they can be in any coordinate system, and the returned value is in the frame — as long as the projected geometry returns at least one visible point.

Fork
js
Plot.dot(counties, Plot.centroid()).plot({projection: "albers-usa"})

The geoCentroid transform is more specialized as the x and y channels it derives represent the longitudes and latitudes of the centroids of the given GeoJSON geometries, before projection. It expects the geometries to be specified in spherical coordinates. It is more correct, in a geospatial sense — for example, the spherical centroid always represents the center of mass of the original shape, and it will be rotated exactly in line with the projection’s rotate argument. However, this also means that it might land outside the frame if only a part of the land mass is visible, and might be clipped by the projection. In practice, the difference is generally imperceptible.

Fork
js
Plot.dot(counties, Plot.geoCentroid()).plot({projection: "albers-usa"})

The geoCentroid transform is slightly faster than the centroid initializer — which might be useful if you have tens of thousands of features and want to show their density on a hexbin map:

Fork
js
Plot.dot(counties, Plot.hexbin({r:"count"}, Plot.geoCentroid())).plot({projection: "albers"})

Combined with the pointer transform, the centroid transform can add interactive tips on a map:

Fork
js
Plot.plot({
  projection: "albers-usa",
  marks: [
    Plot.geo(statemesh, {strokeOpacity: 0.2}),
    Plot.geo(nation),
    Plot.dot(states, Plot.centroid({fill: "red", stroke: "white"})),
    Plot.tip(states, Plot.pointer(Plot.centroid({title: (d) => d.properties.name})))
  ]
})

centroid(options)

js
Plot.centroid({geometry: Plot.identity})

The centroid initializer derives x and y channels representing the planar (projected) centroids for the given GeoJSON geometry. If the geometry option is not specified, the mark’s data is assumed to be GeoJSON objects.

geoCentroid(options)

js
Plot.geoCentroid({geometry: Plot.identity})

The geoCentroid transform derives x and y channels representing the spherical centroids for the given GeoJSON geometry. If the geometry option is not specified, the mark’s data is assumed to be GeoJSON objects.