diff --git a/src/channel.js b/src/channel.js
index 4fb46c3448..888d3fd00e 100644
--- a/src/channel.js
+++ b/src/channel.js
@@ -5,15 +5,19 @@ import {registry} from "./scales/index.js";
import {isSymbol, maybeSymbol} from "./symbol.js";
import {maybeReduce} from "./transforms/group.js";
-export function createChannel(data, {scale, type, value, filter, hint, label = labelof(value)}, name) {
- if (hint === undefined && typeof value?.transform === "function") hint = value.hint;
+export function createChannel(data, {scale, type, value, filter, hint, source, label = labelof(value)}, name) {
+ if (typeof value?.transform === "function") {
+ if (hint === undefined) hint = value.hint;
+ if (source === undefined) source = value.source;
+ }
return inferChannelScale(name, {
scale,
type,
value: valueof(data, value),
label,
filter,
- hint
+ hint,
+ source
});
}
diff --git a/src/marks/geo.js b/src/marks/geo.js
index e986539377..5623b2e6d2 100644
--- a/src/marks/geo.js
+++ b/src/marks/geo.js
@@ -23,6 +23,8 @@ export class Geo extends Mark {
data,
{
geometry: {value: options.geometry, scale: "projection"},
+ x: {value: options.x, scale: "x", optional: true},
+ y: {value: options.y, scale: "y", optional: true},
r: {value: vr, scale: "r", filter: positive, optional: true}
},
withDefaultSort(options),
diff --git a/src/transforms/centroid.js b/src/transforms/centroid.js
index b832775164..86cda092b4 100644
--- a/src/transforms/centroid.js
+++ b/src/transforms/centroid.js
@@ -16,17 +16,22 @@ export function centroid({geometry = identity, ...options} = {}) {
facets,
channels: {
x: {value: X, scale: projection == null ? "x" : null, source: null},
- y: {value: Y, scale: projection == null ? "y" : null, source: null}
+ y: {value: Y, scale: projection == null ? "y" : null, source: null},
+ geometry: {value: G}
}
};
});
}
-export function geoCentroid({geometry = identity, ...options} = {}) {
+export function geoCentroid(options = {}) {
let C;
+ const {geometry = identity} = options;
return {
...options,
- x: {transform: (data) => Float64Array.from((C = valueof(valueof(data, geometry), GeoCentroid)), ([x]) => x)},
- y: {transform: () => Float64Array.from(C, ([, y]) => y)}
+ x: {
+ transform: (data) => Float64Array.from((C = valueof(valueof(data, geometry), GeoCentroid)), ([x]) => x),
+ source: null
+ },
+ y: {transform: () => Float64Array.from(C, ([, y]) => y), source: null}
};
}
diff --git a/test/data/README.md b/test/data/README.md
index 303710c6dc..91eb29abbe 100644
--- a/test/data/README.md
+++ b/test/data/README.md
@@ -115,6 +115,14 @@ CBO
https://www.cbo.gov/topics/budget/accuracy-projections
https://observablehq.com/@tophtucker/examples-of-bitemporal-charts
+## london.json
+giCentre, City University of London
+https://github.com/gicentre/data
+
+## london-car-access.csv
+Derived by Jo Wood from UK Census data
+https://github.com/observablehq/plot/pull/2086
+
## metros.csv
The New York Times
https://www.nytimes.com/2019/12/02/upshot/wealth-poverty-divide-american-cities.html
diff --git a/test/data/london-car-access.csv b/test/data/london-car-access.csv
new file mode 100644
index 0000000000..3abc79f002
--- /dev/null
+++ b/test/data/london-car-access.csv
@@ -0,0 +1,34 @@
+borough,y2001,y2011,y2021
+City of London,0.380,0.306,0.228
+Barking and Dagenham,0.621,0.604,0.652
+Barnet,0.733,0.713,0.701
+Bexley,0.763,0.763,0.776
+Brent,0.627,0.570,0.559
+Bromley,0.770,0.765,0.771
+Camden,0.444,0.389,0.364
+Croydon,0.702,0.665,0.664
+Ealing,0.683,0.647,0.632
+Enfield,0.715,0.675,0.690
+Greenwich,0.592,0.580,0.569
+Hammersmith and Fulham,0.514,0.448,0.425
+Haringey,0.535,0.482,0.473
+Harrow,0.773,0.765,0.753
+Havering,0.767,0.770,0.785
+Hillingdon,0.783,0.773,0.777
+Hounslow,0.714,0.684,0.672
+Islington,0.424,0.353,0.331
+Kensington and Chelsea,0.496,0.440,0.417
+Kingston upon Thames,0.762,0.749,0.743
+Lambeth,0.491,0.422,0.420
+Lewisham,0.572,0.519,0.523
+Merton,0.699,0.674,0.670
+Newham,0.511,0.479,0.483
+Redbridge,0.738,0.721,0.725
+Richmond upon Thames,0.763,0.753,0.746
+Southwark,0.481,0.416,0.397
+Sutton,0.767,0.766,0.772
+Tower Hamlets,0.432,0.370,0.336
+Waltham Forest,0.610,0.581,0.579
+Wandsworth,0.593,0.547,0.521
+Westminster,0.436,0.371,0.338
+Hackney,0.440,0.354,0.351
diff --git a/test/data/london.json b/test/data/london.json
new file mode 100644
index 0000000000..6baf16f55d
--- /dev/null
+++ b/test/data/london.json
@@ -0,0 +1,1478 @@
+{
+ "type": "Topology",
+ "bbox": [
+ -0.5103750689005356,
+ 51.28676016315083,
+ 0.3340155643740317,
+ 51.69187411690989
+ ],
+ "transform": {
+ "scale": [0.00008444750807826456, 0.00004051544692059764],
+ "translate": [-0.5103750689005356, 51.28676016315083]
+ },
+ "objects": {
+ "boroughs": {
+ "type": "GeometryCollection",
+ "geometries": [
+ {
+ "type": "Polygon",
+ "arcs": [[0, 1, 2, 3, 4]],
+ "id": "Kingston upon Thames",
+ "properties": { "GSSCode": "E09000021" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[5, 6, 7, 8, 9]],
+ "id": "Croydon",
+ "properties": { "GSSCode": "E09000008" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-9, 10, 11, 12, 13, 14, 15]],
+ "id": "Bromley",
+ "properties": { "GSSCode": "E09000006" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[16, 17, 18, 19, 20, 21]],
+ "id": "Hounslow",
+ "properties": { "GSSCode": "E09000018" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[22, 23, 24, -21, 25]],
+ "id": "Ealing",
+ "properties": { "GSSCode": "E09000009" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[26, 27, 28]],
+ "id": "Havering",
+ "properties": { "GSSCode": "E09000016" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[29, -26, -20, 30]],
+ "id": "Hillingdon",
+ "properties": { "GSSCode": "E09000017" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[31, 32, 33, -23, -30]],
+ "id": "Harrow",
+ "properties": { "GSSCode": "E09000015" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[34, 35, -24, -34, 36, 37, 38]],
+ "id": "Brent",
+ "properties": { "GSSCode": "E09000005" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[39, 40, 41, -37, -33, 42]],
+ "id": "Barnet",
+ "properties": { "GSSCode": "E09000003" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[43, 44, -11, -8, 45, 46]],
+ "id": "Lambeth",
+ "properties": { "GSSCode": "E09000022" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[47, 48, -12, -45]],
+ "id": "Southwark",
+ "properties": { "GSSCode": "E09000028" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[49, 50, 51, 52, -13, -49]],
+ "id": "Lewisham",
+ "properties": { "GSSCode": "E09000023" }
+ },
+ {
+ "type": "MultiPolygon",
+ "arcs": [[[53, -51]], [[54, -14, -53, 55]]],
+ "id": "Greenwich",
+ "properties": { "GSSCode": "E09000011" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[56, -15, -55]],
+ "id": "Bexley",
+ "properties": { "GSSCode": "E09000004" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[57, 58, 59, 60, -40, 61]],
+ "id": "Enfield",
+ "properties": { "GSSCode": "E09000010" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[62, 63, 64, -58, 65, 66]],
+ "id": "Waltham Forest",
+ "properties": { "GSSCode": "E09000031" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[67, 68, -67, 69, -28, 70, 71]],
+ "id": "Redbridge",
+ "properties": { "GSSCode": "E09000026" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[72, -4, 73, -6]],
+ "id": "Sutton",
+ "properties": { "GSSCode": "E09000029" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[74, 75, -1, 76, -18]],
+ "id": "Richmond upon Thames",
+ "properties": { "GSSCode": "E09000027" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-74, -3, 77, -46, -7]],
+ "id": "Merton",
+ "properties": { "GSSCode": "E09000024" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[78, -47, -78, -2, -76]],
+ "id": "Wandsworth",
+ "properties": { "GSSCode": "E09000032" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-22, -25, -36, 79, 80]],
+ "id": "Hammersmith and Fulham",
+ "properties": { "GSSCode": "E09000013" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-80, -35, 81, 82]],
+ "id": "Kensington and Chelsea",
+ "properties": { "GSSCode": "E09000020" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-82, -39, 83, 84, 85]],
+ "id": "Westminster",
+ "properties": { "GSSCode": "E09000033" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[86, 87, -84, -38, -42, 88]],
+ "id": "Camden",
+ "properties": { "GSSCode": "E09000007" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[89, 90, 91, 92, 93, 94]],
+ "id": "Tower Hamlets",
+ "properties": { "GSSCode": "E09000030" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[95, 96, 97, -87]],
+ "id": "Islington",
+ "properties": { "GSSCode": "E09000019" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-64, 98, -93, 99, -97, 100]],
+ "id": "Hackney",
+ "properties": { "GSSCode": "E09000012" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-96, -89, -41, -61, 59, -59, -65, -101]],
+ "id": "Haringey",
+ "properties": { "GSSCode": "E09000014" }
+ },
+ {
+ "type": "MultiPolygon",
+ "arcs": [[[101, 102]], [[-94, -99, -63, -69, 103, 104]]],
+ "id": "Newham",
+ "properties": { "GSSCode": "E09000025" }
+ },
+ {
+ "type": "MultiPolygon",
+ "arcs": [[[-104, -68, 105, -103, 106]], [[-71, -27, 107]]],
+ "id": "Barking and Dagenham",
+ "properties": { "GSSCode": "E09000002" }
+ },
+ {
+ "type": "Polygon",
+ "arcs": [[-85, -88, -98, -100, -92, 90, -90, 108]],
+ "id": "City of London",
+ "properties": { "GSSCode": "E09000001" }
+ }
+ ]
+ }
+ },
+ "arcs": [
+ [
+ [2281, 2639],
+ [96, 156],
+ [14, 361],
+ [29, 169],
+ [-30, 91],
+ [-70, 76],
+ [45, 98],
+ [50, -51],
+ [58, 10],
+ [96, -100],
+ [33, 62],
+ [48, -218],
+ [73, 41],
+ [112, 190],
+ [200, 191]
+ ],
+ [[3035, 3715], [35, -116]],
+ [
+ [3070, 3599],
+ [-37, -83],
+ [22, -72],
+ [30, -242],
+ [61, -299],
+ [-32, -168],
+ [68, -91],
+ [23, -113]
+ ],
+ [[3205, 2531], [12, -79], [-75, -150]],
+ [
+ [3142, 2302],
+ [-101, -31],
+ [-88, 20],
+ [-44, -98],
+ [-86, -74],
+ [-193, -260],
+ [38, -21],
+ [-72, -115],
+ [-19, -96],
+ [-87, -128],
+ [-47, -110],
+ [-19, -188],
+ [-161, -188],
+ [-107, -33],
+ [-29, 61],
+ [31, 373],
+ [-28, 108],
+ [29, 92],
+ [69, 100],
+ [47, 180],
+ [3, 168],
+ [43, 107],
+ [67, 20],
+ [14, 88],
+ [-40, 177],
+ [-81, 185]
+ ],
+ [
+ [4190, 858],
+ [130, 49],
+ [13, 73],
+ [-58, 57],
+ [63, 47],
+ [-42, 200],
+ [35, 82],
+ [202, 132],
+ [9, -64],
+ [117, 22],
+ [-58, 329],
+ [6, 140],
+ [-80, 389],
+ [-17, 165],
+ [-58, 91]
+ ],
+ [[4452, 2570], [117, 161], [-79, 163], [-15, 108], [56, 97]],
+ [
+ [4531, 3099],
+ [33, 24],
+ [65, 141],
+ [80, 105],
+ [223, -11],
+ [88, -87],
+ [94, 14]
+ ],
+ [
+ [5114, 3285],
+ [-23, -106],
+ [91, -71],
+ [-8, -76],
+ [78, -169],
+ [88, -86],
+ [76, 54],
+ [28, -47],
+ [-33, -108],
+ [132, -145],
+ [68, -21],
+ [-16, -129],
+ [11, -153],
+ [80, 5],
+ [40, 53],
+ [38, -177],
+ [6, -128],
+ [88, -201],
+ [86, -80],
+ [38, -80],
+ [89, -574]
+ ],
+ [
+ [6071, 1046],
+ [-131, 118],
+ [-66, -102],
+ [-74, 182],
+ [-64, 35],
+ [-81, -28],
+ [-60, 31],
+ [-49, -121],
+ [-98, -29],
+ [29, -182],
+ [-41, -69],
+ [-152, -94],
+ [-70, 6],
+ [-12, 58],
+ [-93, -36],
+ [-70, -97],
+ [34, -128],
+ [-81, -85],
+ [-28, -142],
+ [-38, -52],
+ [-198, -175],
+ [-42, 4],
+ [-37, -132],
+ [-77, -8],
+ [-69, 144],
+ [-12, 71],
+ [-74, 131],
+ [-39, -30],
+ [-174, 42],
+ [-28, 82],
+ [40, 142],
+ [-90, 229],
+ [64, 47]
+ ],
+ [[5114, 3285], [2, 19]],
+ [[5116, 3304], [52, 136]],
+ [
+ [5168, 3440],
+ [131, -22],
+ [72, -56],
+ [155, -2],
+ [74, 52],
+ [86, 17],
+ [110, -117],
+ [-19, -84],
+ [54, -61],
+ [88, -38],
+ [115, 58],
+ [30, 66],
+ [46, -3],
+ [29, 114],
+ [72, 77],
+ [82, 16],
+ [52, 53],
+ [127, -163],
+ [30, 56],
+ [-12, 215],
+ [-47, -41],
+ [-99, 99],
+ [-7, 63],
+ [48, 13],
+ [6, 72]
+ ],
+ [[6391, 3824], [12, 65], [111, -82], [224, -405], [56, -8], [142, 191]],
+ [
+ [6936, 3585],
+ [86, -44],
+ [88, -170],
+ [201, -224],
+ [77, -29],
+ [184, 45],
+ [235, -159]
+ ],
+ [
+ [7807, 3004],
+ [64, -87],
+ [56, -228],
+ [39, -79],
+ [-173, 7],
+ [25, -47],
+ [1, -269],
+ [39, -48],
+ [-24, -145],
+ [-73, -230],
+ [10, -114],
+ [-39, -185],
+ [-67, -162],
+ [-140, 42],
+ [-77, -41],
+ [-23, -68],
+ [58, -190],
+ [-87, -157],
+ [-112, -1],
+ [-126, -174],
+ [-108, -106],
+ [-26, -256],
+ [42, -136],
+ [57, -81],
+ [-70, -97],
+ [-317, -88],
+ [-29, 75],
+ [-65, 39],
+ [-97, -32],
+ [23, 146],
+ [-22, 77],
+ [-113, 143],
+ [-98, -139],
+ [-65, -251],
+ [-49, 2],
+ [-78, 470],
+ [23, 131],
+ [-45, -12],
+ [-50, 333]
+ ],
+ [
+ [3148, 4984],
+ [-45, -44],
+ [-35, -106],
+ [0, -108],
+ [-36, -124],
+ [-69, -47],
+ [-108, 57],
+ [-77, 206],
+ [-69, 106],
+ [-132, 30],
+ [-79, -61],
+ [-16, -78],
+ [-73, -138],
+ [-163, -127],
+ [-12, -141]
+ ],
+ [
+ [2234, 4409],
+ [-59, -90],
+ [13, -93],
+ [-69, -17],
+ [-66, -66],
+ [-37, 114],
+ [-93, -60],
+ [-100, 40],
+ [-197, -23],
+ [-127, -197],
+ [-47, -2],
+ [18, -67],
+ [99, -106],
+ [79, 21],
+ [52, -40],
+ [-131, -120],
+ [21, -31],
+ [-85, -84],
+ [-57, -105],
+ [47, -128],
+ [-16, -48],
+ [-70, 39]
+ ],
+ [
+ [1409, 3346],
+ [-98, 30],
+ [-68, -26],
+ [-100, 187],
+ [-87, 52],
+ [-99, -83],
+ [-124, 45],
+ [3, 98],
+ [-94, 10],
+ [17, 123],
+ [-121, -46],
+ [-14, 274],
+ [-45, -6],
+ [33, 181]
+ ],
+ [
+ [612, 4185],
+ [174, -75],
+ [30, 87],
+ [57, 22],
+ [36, 100],
+ [133, 117],
+ [133, 84],
+ [-56, 102],
+ [-11, 169],
+ [50, 191],
+ [20, 227],
+ [47, 47]
+ ],
+ [
+ [1225, 5256],
+ [235, -124],
+ [109, 47],
+ [71, -151],
+ [103, 133],
+ [148, 80],
+ [101, -76],
+ [144, -23],
+ [78, 20],
+ [50, -41],
+ [40, 40],
+ [46, -96],
+ [77, 63],
+ [-5, 41],
+ [98, -32],
+ [-37, 110],
+ [79, 55],
+ [98, -20],
+ [59, 51],
+ [119, -207],
+ [181, 12],
+ [28, 160]
+ ],
+ [[3047, 5298], [45, -110], [57, 24], [-1, -228]],
+ [
+ [1570, 6620],
+ [23, -47],
+ [158, 73],
+ [1, 31],
+ [176, 59],
+ [59, -54],
+ [83, -22]
+ ],
+ [
+ [2070, 6660],
+ [90, -32],
+ [180, -148],
+ [66, -100],
+ [10, -282],
+ [43, -45],
+ [82, 82],
+ [83, 19],
+ [75, 64],
+ [47, -82],
+ [-9, -57],
+ [-57, 11],
+ [-63, -45],
+ [104, -79],
+ [166, 50],
+ [104, 119],
+ [136, -63]
+ ],
+ [
+ [3127, 6072],
+ [-74, -190],
+ [44, -281],
+ [26, -60],
+ [11, -164],
+ [-111, -8],
+ [24, -71]
+ ],
+ [
+ [1225, 5256],
+ [38, 84],
+ [126, 106],
+ [34, 156],
+ [90, 104],
+ [79, 192],
+ [-3, 76],
+ [-441, 144],
+ [-73, 100],
+ [168, 93],
+ [120, 2],
+ [-41, 132],
+ [159, 81],
+ [89, 94]
+ ],
+ [
+ [7923, 5564],
+ [80, 401],
+ [63, 103],
+ [50, 145],
+ [50, 45],
+ [10, 85],
+ [68, 86],
+ [52, 134],
+ [-69, 123],
+ [-11, 172],
+ [-119, 12],
+ [-136, -86],
+ [-144, 199],
+ [-27, 274],
+ [41, 73],
+ [2, 289],
+ [-35, 87]
+ ],
+ [[7798, 7706], [16, 97], [-25, 237], [-109, 272]],
+ [
+ [7680, 8312],
+ [202, -4],
+ [161, -48],
+ [137, 75],
+ [170, 31],
+ [65, -19],
+ [125, 44],
+ [136, 87],
+ [21, 37],
+ [182, -213],
+ [151, -132],
+ [66, -91],
+ [77, -154],
+ [-74, -33],
+ [-33, -130],
+ [173, -41],
+ [-6, -101],
+ [32, -191],
+ [119, -227],
+ [97, -352],
+ [269, 38],
+ [26, -196],
+ [85, -127],
+ [33, 8],
+ [74, -176],
+ [31, -134],
+ [-148, 0],
+ [-247, -43],
+ [-35, -85],
+ [-303, -52],
+ [-80, -26],
+ [0, -180],
+ [-20, -173],
+ [-117, 1],
+ [-35, 269],
+ [-95, -109],
+ [-25, -78],
+ [38, -71],
+ [-80, 24],
+ [47, -138],
+ [9, -142],
+ [-180, -33],
+ [39, -179],
+ [-55, -45],
+ [-115, -23],
+ [-72, -170],
+ [-170, -43],
+ [-90, -2],
+ [-34, 68],
+ [-27, 217],
+ [-46, 144],
+ [-176, 163],
+ [-59, 7]
+ ],
+ [
+ [1259, 8057],
+ [23, -156],
+ [-3, -122],
+ [69, -166],
+ [12, -124],
+ [40, -42],
+ [7, -171],
+ [163, -656]
+ ],
+ [
+ [612, 4185],
+ [-177, 57],
+ [-37, 65],
+ [-122, 4],
+ [-81, 32],
+ [-89, 115],
+ [-105, 3],
+ [60, 163],
+ [20, 158],
+ [57, 140],
+ [1, 74],
+ [118, 168],
+ [-13, 74],
+ [43, 48],
+ [35, 155],
+ [-77, 104],
+ [-32, 140],
+ [20, 240],
+ [20, 59],
+ [-77, 225],
+ [105, 289],
+ [110, 129],
+ [-2, 124],
+ [-44, 17],
+ [-42, 146],
+ [9, 196],
+ [-49, 41],
+ [-17, 130],
+ [-60, 68],
+ [-58, 187],
+ [-16, 198],
+ [54, 61],
+ [-34, 160],
+ [45, 246],
+ [-57, 78],
+ [31, 111],
+ [-32, 50],
+ [47, 75],
+ [57, -24],
+ [35, -89],
+ [141, -130],
+ [89, -125],
+ [139, -111],
+ [98, 70],
+ [43, 111],
+ [88, 5],
+ [133, -69],
+ [125, -18],
+ [59, -62],
+ [86, -16]
+ ],
+ [
+ [1259, 8057],
+ [203, 59],
+ [240, 130],
+ [82, 109],
+ [124, 40],
+ [111, 95],
+ [19, -31],
+ [88, 133],
+ [139, 91],
+ [28, 49],
+ [145, -104]
+ ],
+ [[2438, 8628], [6, -120], [436, -767]],
+ [
+ [2880, 7741],
+ [-111, -96],
+ [-164, -72],
+ [76, -83],
+ [18, -128],
+ [-244, 55],
+ [-119, -74],
+ [-84, -95],
+ [-77, -41],
+ [54, -225],
+ [-90, -63],
+ [18, -113],
+ [-87, -146]
+ ],
+ [[3486, 5952], [-148, 60]],
+ [[3338, 6012], [-70, 57], [-108, -21], [-33, 24]],
+ [
+ [2880, 7741],
+ [224, -396],
+ [-73, -70],
+ [36, -206],
+ [-21, -16],
+ [73, -96],
+ [3, 70],
+ [62, 31],
+ [95, -18],
+ [136, -223],
+ [100, -192]
+ ],
+ [[3515, 6625], [261, -466]],
+ [[3776, 6159], [-60, -213], [-76, 129], [-145, -37], [-9, -86]],
+ [
+ [3887, 9425],
+ [-45, -143],
+ [369, -180],
+ [36, -251],
+ [45, -81],
+ [33, 14],
+ [44, -103],
+ [145, -153],
+ [-74, -261],
+ [-108, -153],
+ [68, -131]
+ ],
+ [
+ [4400, 7983],
+ [-55, -33],
+ [16, -137],
+ [-28, -79],
+ [-82, -66],
+ [-23, 129],
+ [-41, 56],
+ [-58, -179],
+ [50, -274],
+ [-98, -83],
+ [-66, -266]
+ ],
+ [
+ [4015, 7051],
+ [-37, -79],
+ [-43, 30],
+ [-140, -136],
+ [-10, -77],
+ [-92, -76],
+ [-20, -63],
+ [-67, -22],
+ [-49, 36],
+ [-42, -39]
+ ],
+ [
+ [2438, 8628],
+ [99, -22],
+ [260, 86],
+ [15, 78],
+ [114, 68],
+ [70, -74],
+ [75, 188],
+ [14, 127],
+ [137, 90],
+ [111, 43],
+ [29, -70],
+ [73, 82],
+ [147, 59],
+ [-39, 101],
+ [38, -9],
+ [54, 87],
+ [101, -45],
+ [-21, -69],
+ [66, -40],
+ [39, 99],
+ [67, 18]
+ ],
+ [[4523, 4894], [49, 67], [37, 177], [21, 220], [41, 87], [83, 27]],
+ [
+ [4754, 5472],
+ [35, -159],
+ [-58, -163],
+ [71, -47],
+ [20, -58],
+ [-63, -131],
+ [53, -122],
+ [-50, -16],
+ [98, -84],
+ [-8, -64],
+ [55, -108],
+ [35, 52],
+ [35, -143],
+ [-7, -72],
+ [-61, -145],
+ [-61, -80],
+ [2, -94],
+ [56, -89],
+ [65, -254],
+ [32, -182],
+ [113, -209]
+ ],
+ [[4531, 3099], [-75, -33], [-102, 58], [-64, -11], [91, 157]],
+ [
+ [4381, 3270],
+ [30, 46],
+ [-6, 233],
+ [37, -5],
+ [-52, 123],
+ [44, 165],
+ [-91, -4],
+ [-23, 87],
+ [38, 139],
+ [-64, 33],
+ [-36, 264],
+ [2, 113],
+ [177, 126],
+ [86, 304]
+ ],
+ [
+ [4754, 5472],
+ [158, -3],
+ [172, -60],
+ [204, -128],
+ [77, 3],
+ [81, 54],
+ [72, 96],
+ [104, -1],
+ [38, -66],
+ [0, -275]
+ ],
+ [
+ [5660, 5092],
+ [-97, -7],
+ [-23, -63],
+ [-112, -27],
+ [-28, -260],
+ [20, -15],
+ [16, -262],
+ [59, -73],
+ [2, -184],
+ [54, -49],
+ [-54, -126],
+ [-92, -29],
+ [-43, 40],
+ [-73, -143],
+ [2, -174],
+ [-29, -76],
+ [-72, -47],
+ [-36, -91],
+ [14, -66]
+ ],
+ [[5660, 5092], [89, -186]],
+ [[5749, 4906], [-18, -99], [39, -47], [71, 20]],
+ [[5841, 4780], [-67, -125]],
+ [
+ [5774, 4655],
+ [43, -134],
+ [71, -25],
+ [-24, 70],
+ [83, 25],
+ [97, -23],
+ [177, 31],
+ [16, -101],
+ [-86, -77],
+ [29, -229],
+ [71, -38],
+ [52, -151],
+ [-5, -153],
+ [93, -26]
+ ],
+ [[5749, 4906], [72, -50], [20, -76]],
+ [
+ [7467, 5546],
+ [12, -497],
+ [12, -234],
+ [23, -124],
+ [-68, 52],
+ [-76, -144],
+ [-45, 75],
+ [-73, -41],
+ [-45, 25],
+ [-159, -167],
+ [-30, -51],
+ [7, -168],
+ [-50, -14],
+ [83, -65],
+ [27, -248],
+ [-7, -83],
+ [-77, -70],
+ [-65, -207]
+ ],
+ [
+ [5774, 4655],
+ [91, 155],
+ [-32, 40],
+ [125, 13],
+ [87, 76],
+ [30, 122],
+ [-35, 85],
+ [-12, 200],
+ [77, 23],
+ [116, -199],
+ [105, -56],
+ [194, 37],
+ [263, -24],
+ [168, 44],
+ [68, 67],
+ [114, 247],
+ [176, 10],
+ [158, 51]
+ ],
+ [
+ [7467, 5546],
+ [57, 39],
+ [86, -18],
+ [147, -120],
+ [183, -46],
+ [78, -55],
+ [63, -169],
+ [6, -191],
+ [65, -130],
+ [73, -65],
+ [119, -39],
+ [211, 82],
+ [66, -54],
+ [-17, -75],
+ [-59, -52],
+ [-37, -109],
+ [34, -59],
+ [-8, -144],
+ [-93, -107],
+ [4, -107],
+ [-116, -56],
+ [-64, -74],
+ [-39, -100],
+ [-99, -65],
+ [-38, 25],
+ [-72, -197],
+ [-32, -151],
+ [-96, 48],
+ [-28, -185],
+ [-28, -73],
+ [-23, -197],
+ [54, -29],
+ [-57, -69]
+ ],
+ [
+ [5898, 8872],
+ [-37, -270],
+ [-117, -319],
+ [-88, -149],
+ [-34, -106],
+ [19, -64],
+ [-88, -94]
+ ],
+ [[5553, 7870], [-168, 81], [-136, 1]],
+ [[5249, 7952], [0, 0]],
+ [
+ [5249, 7952],
+ [-222, -12],
+ [-115, 20],
+ [-135, -24],
+ [-196, 10],
+ [-136, 62],
+ [-45, -25]
+ ],
+ [
+ [3887, 9425],
+ [76, 112],
+ [38, -2],
+ [105, 230],
+ [1, 141],
+ [162, -64],
+ [180, 81],
+ [153, -6],
+ [112, 61],
+ [96, 19],
+ [111, -42],
+ [106, 2],
+ [81, -31],
+ [150, -125],
+ [63, -24],
+ [113, 17],
+ [282, -33],
+ [196, -34],
+ [9, -110],
+ [-14, -308],
+ [31, -91],
+ [-35, -189],
+ [-5, -157]
+ ],
+ [
+ [6285, 6652],
+ [-41, -76],
+ [-28, 44],
+ [-60, -92],
+ [-76, 21],
+ [-139, -54],
+ [-23, 67],
+ [-78, -26]
+ ],
+ [
+ [5840, 6536],
+ [-15, 89],
+ [-129, 152],
+ [-47, -18],
+ [-166, 54],
+ [7, 41],
+ [-136, 194],
+ [-35, 135]
+ ],
+ [[5319, 7183], [-13, 43], [120, 209], [-16, 47], [34, 164], [109, 224]],
+ [
+ [5898, 8872],
+ [58, -1],
+ [-11, -62],
+ [93, -3],
+ [16, -43],
+ [204, -38],
+ [54, 21],
+ [35, -155],
+ [-45, -148]
+ ],
+ [
+ [6302, 8443],
+ [-35, -138],
+ [-52, -107],
+ [-69, 4],
+ [90, -55],
+ [61, -141],
+ [-100, -298],
+ [-10, -170],
+ [15, -207],
+ [48, -156],
+ [-13, -112],
+ [32, -146],
+ [-54, -35],
+ [-3, -105],
+ [73, -125]
+ ],
+ [[6865, 6352], [-12, 7]],
+ [
+ [6853, 6359],
+ [-6, 214],
+ [-50, 105],
+ [-41, -22],
+ [-68, 80],
+ [-48, 107],
+ [-100, -63],
+ [50, -163],
+ [-132, 9],
+ [-114, -28],
+ [-59, 54]
+ ],
+ [
+ [6302, 8443],
+ [86, -92],
+ [140, -233],
+ [146, 68],
+ [-53, -119],
+ [168, -165],
+ [117, -55],
+ [71, 57],
+ [98, -62],
+ [65, 42],
+ [26, 113],
+ [-30, 69],
+ [69, 46],
+ [25, -67],
+ [112, 31],
+ [84, 73],
+ [22, -38],
+ [66, 52],
+ [59, 98],
+ [107, 51]
+ ],
+ [
+ [7798, 7706],
+ [-19, 11],
+ [-201, -231],
+ [17, -63],
+ [-55, -19],
+ [17, -126],
+ [56, -8],
+ [-40, -123],
+ [29, -111],
+ [-27, -132],
+ [-122, -84],
+ [-22, -153],
+ [-72, -108],
+ [-208, -164],
+ [-15, 68],
+ [-166, -107],
+ [-101, -5]
+ ],
+ [[6869, 6351], [-4, 1]],
+ [
+ [4190, 858],
+ [-91, 112],
+ [13, 104],
+ [-116, -6],
+ [-15, 79],
+ [-157, 184],
+ [-117, 72],
+ [-67, -93],
+ [-119, -106],
+ [-13, -128],
+ [-81, -12],
+ [-105, 164],
+ [149, 170],
+ [-56, 201],
+ [-18, 170],
+ [-40, 103],
+ [-121, 106],
+ [-99, -1],
+ [11, 89],
+ [-6, 236]
+ ],
+ [
+ [3205, 2531],
+ [60, 30],
+ [11, -73],
+ [71, -89],
+ [114, -94],
+ [98, 200],
+ [110, -83],
+ [78, 74],
+ [66, -61],
+ [113, 116],
+ [47, 82],
+ [100, -92],
+ [13, -43],
+ [248, 67],
+ [29, -33],
+ [89, 38]
+ ],
+ [
+ [2234, 4409],
+ [85, -133],
+ [94, -82],
+ [33, -87],
+ [-65, -116],
+ [-106, -50],
+ [-101, -16],
+ [-58, -164],
+ [64, -184],
+ [-47, 235],
+ [96, 100],
+ [100, 26],
+ [94, 62],
+ [35, 61],
+ [-21, 118],
+ [-174, 199],
+ [7, 148],
+ [130, 107],
+ [120, 220],
+ [83, 71],
+ [68, -4],
+ [93, -126],
+ [44, -156],
+ [64, -85],
+ [90, -23],
+ [63, 30],
+ [59, 102],
+ [19, 205],
+ [86, 109],
+ [122, -19],
+ [32, -61],
+ [21, -239],
+ [34, -97]
+ ],
+ [
+ [3398, 4560],
+ [-114, 15],
+ [-3, -201],
+ [-115, 30],
+ [-117, 1],
+ [-61, -122],
+ [-13, -132],
+ [140, -142],
+ [67, -149],
+ [-147, -145]
+ ],
+ [
+ [2281, 2639],
+ [-118, -47],
+ [-160, 286],
+ [-31, 15],
+ [-189, 199],
+ [-79, -22],
+ [-79, -63],
+ [-75, -19],
+ [-51, 57],
+ [-70, 14],
+ [-7, 90],
+ [49, -2],
+ [-18, 125],
+ [-44, 74]
+ ],
+ [
+ [3070, 3599],
+ [234, 137],
+ [84, 18],
+ [101, -27],
+ [122, 25],
+ [182, 66],
+ [-12, -207],
+ [63, 3],
+ [14, -137],
+ [31, -72],
+ [241, -120],
+ [20, 69],
+ [183, -121],
+ [48, 37]
+ ],
+ [
+ [3398, 4560],
+ [119, -140],
+ [159, -76],
+ [136, 24],
+ [53, 41],
+ [65, 133],
+ [45, 190],
+ [81, 64],
+ [220, 64],
+ [141, -23],
+ [106, 57]
+ ],
+ [
+ [3338, 6012],
+ [21, -206],
+ [-19, -22],
+ [68, -135],
+ [39, -150],
+ [48, -47],
+ [-33, -37],
+ [46, -133],
+ [132, -184],
+ [60, -135],
+ [41, -33],
+ [125, -224]
+ ],
+ [
+ [3866, 4706],
+ [53, 5],
+ [-40, -199],
+ [-42, -77],
+ [-87, -40],
+ [-103, 12],
+ [-160, 94],
+ [-72, 117],
+ [-29, 237],
+ [-58, 138],
+ [-45, 31],
+ [-135, -40]
+ ],
+ [
+ [3486, 5952],
+ [112, -45],
+ [70, -131],
+ [-37, -3],
+ [54, -151],
+ [49, 12],
+ [34, -127],
+ [50, 7],
+ [44, -207],
+ [46, -8],
+ [9, -91],
+ [167, 23],
+ [83, 88],
+ [43, -254],
+ [-12, -58],
+ [69, -102]
+ ],
+ [[4267, 4905], [-305, -95], [-42, -90], [-54, -14]],
+ [
+ [3776, 6159],
+ [32, -44],
+ [102, 125],
+ [126, -24],
+ [54, -70],
+ [145, 43],
+ [66, -308],
+ [51, -28],
+ [69, -124],
+ [73, -44],
+ [39, -110],
+ [55, 62],
+ [134, 5]
+ ],
+ [[4722, 5642], [0, -113]],
+ [
+ [4722, 5529],
+ [-99, -49],
+ [-30, -74],
+ [-33, -345],
+ [-75, -141],
+ [-98, -32],
+ [-120, 17]
+ ],
+ [
+ [4357, 6969],
+ [16, -212],
+ [46, -127],
+ [71, -92],
+ [51, -115],
+ [51, -231],
+ [0, -170],
+ [78, -22],
+ [43, -152],
+ [63, -37],
+ [20, -90]
+ ],
+ [[4796, 5721], [-100, -7], [26, -72]],
+ [[4015, 7051], [47, 13], [201, -34], [94, -61]],
+ [[5104, 5457], [7, 24]],
+ [[5111, 5481], [0, 0]],
+ [[5111, 5481], [71, 36], [-14, 103], [-65, 108], [11, 66]],
+ [
+ [5114, 5794],
+ [28, 16],
+ [-13, 127],
+ [36, 70],
+ [93, 27],
+ [79, 71],
+ [116, 57],
+ [62, -13],
+ [139, 216],
+ [46, -58],
+ [147, 26]
+ ],
+ [[5847, 6333], [-55, -153], [52, -148], [70, -43], [41, -79], [-4, -79]],
+ [
+ [5951, 5831],
+ [-16, -78],
+ [58, -85],
+ [19, 34],
+ [75, -80],
+ [-27, -87],
+ [87, -91],
+ [-60, 26],
+ [-64, -24],
+ [-57, -84],
+ [-15, -79],
+ [54, -214],
+ [-5, -78],
+ [-58, -60],
+ [-93, -10],
+ [-59, 33],
+ [-76, 170],
+ [0, 264],
+ [-26, 59],
+ [-127, 59],
+ [-84, -29],
+ [-100, -121],
+ [-77, -16],
+ [-196, 117]
+ ],
+ [[4357, 6969], [112, 98], [159, 60], [53, -122], [127, -143]],
+ [
+ [4808, 6862],
+ [68, -97],
+ [82, -15],
+ [15, -150],
+ [127, -58],
+ [34, -141],
+ [-83, 12],
+ [-33, -230],
+ [-123, -106],
+ [19, -93],
+ [123, -74],
+ [-2, -145]
+ ],
+ [[5035, 5765], [-151, 63], [3, -53], [-91, -54]],
+ [[5840, 6536], [-21, -27], [28, -176]],
+ [[5114, 5794], [-79, -29]],
+ [[4808, 6862], [98, 145], [-20, 73], [200, 49], [55, -16], [178, 70]],
+ [[6938, 5999], [-1, 1]],
+ [[6937, 6000], [1, -1]],
+ [[6853, 6359], [-14, -125], [71, -246]],
+ [
+ [6910, 5988],
+ [63, -13],
+ [80, -80],
+ [80, 1],
+ [46, -252],
+ [-66, -18],
+ [-82, -78],
+ [-115, -275],
+ [-158, -50],
+ [-192, 39],
+ [-210, -33],
+ [-102, 48],
+ [-133, 238],
+ [9, 102],
+ [-115, 95],
+ [-29, -30],
+ [-44, 76],
+ [9, 73]
+ ],
+ [[6865, 6352], [-9, -83], [82, -270]],
+ [[6937, 6000], [-27, -12]],
+ [
+ [7923, 5564],
+ [-74, 10],
+ [-105, 63],
+ [-90, 84],
+ [-105, 22],
+ [-94, -32],
+ [-148, -104],
+ [-87, 22],
+ [-45, 53],
+ [-1, 88],
+ [-44, 153],
+ [-73, -16],
+ [-107, 92],
+ [-90, 300],
+ [9, 52]
+ ],
+ [[5104, 5457], [-241, 72], [-141, 0]]
+ ]
+}
diff --git a/test/output/londonCarAccess.svg b/test/output/londonCarAccess.svg
new file mode 100644
index 0000000000..1bbaa91313
--- /dev/null
+++ b/test/output/londonCarAccess.svg
@@ -0,0 +1,142 @@
+
\ No newline at end of file
diff --git a/test/output/londonCarAccessGeoCentroid.svg b/test/output/londonCarAccessGeoCentroid.svg
new file mode 100644
index 0000000000..1bbaa91313
--- /dev/null
+++ b/test/output/londonCarAccessGeoCentroid.svg
@@ -0,0 +1,142 @@
+
\ No newline at end of file
diff --git a/test/output/londonMap.svg b/test/output/londonMap.svg
new file mode 100644
index 0000000000..bb2ecf855a
--- /dev/null
+++ b/test/output/londonMap.svg
@@ -0,0 +1,86 @@
+
\ No newline at end of file
diff --git a/test/plots/index.ts b/test/plots/index.ts
index 907109e590..6937ddfba0 100644
--- a/test/plots/index.ts
+++ b/test/plots/index.ts
@@ -153,6 +153,7 @@ export * from "./linear-regression-mtcars.js";
export * from "./linear-regression-penguins.js";
export * from "./log-degenerate.js";
export * from "./log-tick-format.js";
+export * from "./london-maps.js";
export * from "./long-labels.js";
export * from "./markers.js";
export * from "./markov-chain.js";
diff --git a/test/plots/london-maps.ts b/test/plots/london-maps.ts
new file mode 100644
index 0000000000..9037430517
--- /dev/null
+++ b/test/plots/london-maps.ts
@@ -0,0 +1,72 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+import {feature} from "topojson-client";
+
+export async function londonMap() {
+ const london = feature(await d3.json("data/london.json"), "boroughs");
+ return Plot.plot({
+ projection: {type: "transverse-mercator", rotate: [2, 0, 0], domain: london},
+ marks: [
+ Plot.geo(london),
+ Plot.text(london.features, Plot.centroid({text: "id", stroke: "var(--plot-background)", fill: "currentColor"}))
+ ]
+ });
+}
+
+export async function londonCarAccess() {
+ const london = feature(await d3.json("data/london.json"), "boroughs");
+ const wide = await d3.csv("data/london-car-access.csv", d3.autoType);
+ const access = wide.flatMap(({borough, y2001, y2011, y2021}) => [
+ {borough, year: "2001", access: y2001},
+ {borough, year: "2011", access: y2011},
+ {borough, year: "2021", access: y2021}
+ ]);
+ const boroughs = new Map(london.features.map((d) => [d.id, d]));
+ return Plot.plot({
+ width: 900,
+ projection: {type: "transverse-mercator", rotate: [2, 0, 0], domain: london},
+ color: {scheme: "RdYlBu", pivot: 0.5},
+ marks: [
+ Plot.geo(
+ access,
+ Plot.centroid({
+ fx: "year",
+ geometry: (d) => boroughs.get(d.borough),
+ fill: "access",
+ stroke: "var(--plot-background)",
+ strokeWidth: 0.75,
+ tip: true
+ })
+ )
+ ]
+ });
+}
+
+export async function londonCarAccessGeoCentroid() {
+ const london = feature(await d3.json("data/london.json"), "boroughs");
+ const wide = await d3.csv("data/london-car-access.csv", d3.autoType);
+ const access = wide.flatMap(({borough, y2001, y2011, y2021}) => [
+ {borough, year: "2001", access: y2001},
+ {borough, year: "2011", access: y2011},
+ {borough, year: "2021", access: y2021}
+ ]);
+ const boroughs = new Map(london.features.map((d) => [d.id, d]));
+ return Plot.plot({
+ width: 900,
+ projection: {type: "transverse-mercator", rotate: [2, 0, 0], domain: london},
+ color: {scheme: "RdYlBu", pivot: 0.5},
+ marks: [
+ Plot.geo(
+ access,
+ Plot.geoCentroid({
+ fx: "year",
+ geometry: (d) => boroughs.get(d.borough),
+ fill: "access",
+ stroke: "var(--plot-background)",
+ strokeWidth: 0.75,
+ tip: true
+ })
+ )
+ ]
+ });
+}