Public
Edited
Jun 16, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
/**
* traceSrcToDst
*
* Trace from the src to the dst point.
* The input is srcWalmartIdx,
* and when the distance is back to zero,
* it means arriving at the dstWalmartPoint.
*
* It also keeps the trace inside the polygonUS.
**/

traceSrcToDst = {
// The insideTraceFlag prevents the path from repeating
distanceMap.map((d) => (d.insideTraceFlag = false));

const trace = [distanceMap[srcWalmartIdx]];

var idx, pnt, candidates;

for (let _ = 0; _ < distanceMap.length; ++_) {
trace[trace.length - 1].insideTraceFlag = true;

if (trace[trace.length - 1].distance === 0) break;

idx = trace[trace.length - 1].rawIdx;

// The candidates should be not inside the trace already,
// and its middle point should be inside the polygonUS
candidates = [...delaunay.neighbors(idx)]
.filter((j) => !distanceMap[j].insideTraceFlag)
.filter((j) =>
d3.polygonContains(
polygonUS,
d3
.scaleLinear()
.domain([0, 1])
.range([
[distanceMap[j].longitude, distanceMap[j].latitude],
[distanceMap[idx].longitude, distanceMap[idx].latitude]
])(0.5)
)
);
candidates.sort(
(a, b) => distanceMap[a].distance - distanceMap[b].distance
);

if (candidates.length === 0) break;
trace.push(distanceMap[candidates.shift()]);
}

if (trace[trace.length - 1].distance !== 0)
console.warn("The trace is not finished");

return trace;
}
Insert cell
distanceMap
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
/**
* distanceMap
*
* Mark the points inside canNotReachRect,
* and compute the distance map.
**/

distanceMap = {
Data.walmarts.map((d) => (d.canNotReachFlag = canNotReachRect.insideMe(d)));
return computeDistanceMap(Data.walmarts, dstWalmartIdx, delaunay);
}
Insert cell
/**
* delaunay
*
*
* The delaunay is used to determine the neighborhood of the points
**/

delaunay = d3.Delaunay.from(
Data.walmarts.map(({ longitude, latitude }) => [longitude, latitude])
)
Insert cell
Insert cell
/**
* canNotReachRect
*
* The rect of can-not-reach.
* it marks the can-not-reached points
**/

canNotReachRect = {
var tmp,
{ minLongitude, maxLongitude, minLatitude, maxLatitude } =
canNotReachRectSetup;

if (minLatitude > maxLatitude) {
tmp = maxLatitude;
maxLatitude = minLatitude;
minLatitude = tmp;
}

if (minLongitude > maxLongitude) {
tmp = maxLongitude;
maxLongitude = minLongitude;
minLongitude = tmp;
}

const polygon = [
[minLongitude, maxLatitude],
[maxLongitude, maxLatitude],
[maxLongitude, minLatitude],
[minLongitude, minLatitude],
[minLongitude, maxLatitude]
],
canNotReachGeometry = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "MultiPolygon",
coordinates: [[polygon]]
}
}
]
};

canNotReachGeometry.insideMe = (pnt) => {
return d3.polygonContains(polygon, [pnt.longitude, pnt.latitude]);
};

return canNotReachGeometry;
}
Insert cell
Data = {
const walmarts = await FileAttachment("walmarts.tsv").tsv({ typed: true }),
elections = await FileAttachment("us-presidential-election-2020.csv").csv();

walmarts.sort((a, b) => a.longitude - b.longitude);

return { walmarts, elections };
}
Insert cell
Insert cell
polygonUS = Geography.nation.features[0].geometry.coordinates[0][0]
Insert cell
Geography = {
const us = await FileAttachment("us-counties-10m.json").json();

const nation = topojson.feature(us, us.objects.nation),
states = topojson.feature(us, us.objects.states),
counties = topojson.feature(us, us.objects.counties),
statemesh = topojson.mesh(us, us.objects.states, (a, b) => a !== b),
countrymesh = topojson.mesh(us, us.objects.counties, (a, b) => a !== b);

return { us, nation, states, counties, statemesh, countrymesh };
}
Insert cell
/**
* Compute the distance between point a and b
**/
function computeDistance(a, b) {
var x = a.longitude - b.longitude,
y = a.latitude - b.latitude;
return Math.sqrt(x * x + y * y);
}
Insert cell
d3 = require("d3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more