The square grid of points is still reasonably far away from the shape of the US. Let’s change that. Thanks to D3’s own d3.polygonContains() method, this is rather simple. The method takes screen coordinates of a polygon and a point, and for each point returns true if the point is in the polygon and false if it isn’t. It couldn’t be more helpful.
To get the polygon of our US map, we write a small function called getPolygonPoints() and use it as a next step in our ready() function, which so far looks like this:
function ready(error, us) {
var us = prepData(us);
drawGeo(us);
var points = getPointGrid(160);
var polygonPoints = getPolygonPoints(us);
}
The only argument we pass in is the array of GeoJSON objects for our map called us. For simplicity reasons, we decided to only look at the mainland US. So, the first thing we need to do is focus our data on the US mainland:
function getPolygonPoints(data) {
var features = data.features[0].geometry.coordinates[7][0];
var polygonPoints = []
features.forEach(function(el) {
polygonPoints.push(projection(el));
});
return polygonPoints;
}
data.features[0].geometry.coordinates holds 11 arrays of polygon point pairs, describing mainland US as well as Alaska, Hawaii, and further offshore areas. We want to focus on mainland US, whose outline is represented by the first element in the seventh array. Note that this might be different if your data comes from a different source or is being assembled differently.
Then, we will loop through all polygonPoints, which are in longitude and latitude, and convert them into x and y coordinates for further use.
Now, we have both the polygon boundaries of the US and our grid points in pixel coordinates. All we need to do now is to identify the grid points that lie within mainland US:
var usPoints = keepPointsInPolygon(points, polygonPoints);
We pass the two arrays to a function we boldly name keepPointsInPolygon():
function keepPointsInPolygon(points, polygon) {
var pointsInPolygon = [];
points.forEach(function(el) {
var inPolygon = d3.polygonContains(polygon, [el.x, el.y]);
if (inPolygon) pointsInPolygon.push(el);
});
return pointsInPolygon;
}
In here, we create an empty array called pointsInPolygon, which will hold our US-exclusive points. We then loop through our grid points and check for each whether it’s within the US polygon or not. If it is, we wave it through into pointsInPolygon.
If we were to draw these points, we would see a pointy US:
