I'm struggling to align a topojson of Canada and a PNG DEM.
I've done a lot of hunting and cobbled together a few tests based largely on https://gist.github.com/ThomasThoren/5e676d0de41bac8a0e96. My understanding is that the PNG must be preprojected and is simply scaled + translated to the appropriate spot on the page, while the topojson is either fed in as lat/long and reprojected with d3 tools or preprojected and drawn using d3.geoIdentity (as per https://medium.com/p/e9ccc6c0bba3/responses/show). I just cannot get the two datasets aligned despite knowing they are aligned in projected coordinate space (at least when preprojecting the topojson and using d3.geoIdentity), which leads me to believe I'm missing something in the d3 code. Any ideas? I have no problem manipulating the topojson or source raster in other tools if that's the solution, but I have yet to find a recipe that works for this alignment. Here is an example where the topojson is preprojected. In any case, whether I preproject or project in d3 using geoConicConformal, I get the same result.
Here's the PNG file:
And here's my TopoJSON file.
This is the code I'm using to display the topojson and png:
<html>
<head>
<meta charset="utf-8">
<title>D3 Canada</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js"></script>
<script src="test-canada-topojson-canlam.js"></script>
<style>
body {
padding: 0;
margin: 0;
background: whitesmoke;
display: flex;
flex-direction: column;
align-items: center;
}
.province {
fill: white;
fill-opacity: 10%;
transition: fill 0.25s ease-in-out;
}
.province:hover {
fill: aliceblue;
fill-opacity: 90%;
transition: fill 0.25s ease-in-out;
}
</style>
</head>
<body>
<div class="home"></div>
<script>
var width = window.innerWidth,
height = window.innerHeight;
const container = d3.select(".home");
var svg = container.append("svg");
svg.attr("width", width)
.attr("height", height);
var provinces = topojson.feature(canada,canada.objects.canada).features;
var projection = d3.geoIdentity().reflectY(true).fitSize([width,height],topojson.feature(canada, canada.objects.canada));
var path = d3.geoPath(projection);
var bounds = path.bounds(topojson.feature(canada, canada.objects.canada));
var scale = 1 / Math.max((bounds[1][0] - bounds[0][0]) / width,(bounds[1][1] - bounds[0][1]) / height);
var raster_width = (bounds[1][0] - bounds[0][0]) * scale;
var raster_height = (bounds[1][1] - bounds[0][1]) * scale;
var rtranslate_x = (width - raster_width) / 2;
var rtranslate_y = (height - raster_height) / 2;
const g = svg.append("g");
g.append("image")
.attr("xlink:href", "canada-dem-conic.png")
.attr("class", "raster")
.attr("width", raster_width)
.attr("height", raster_height)
.attr("transform",
"translate(" + rtranslate_x + ", " + rtranslate_y + ")");
g.append("g")
.selectAll("path")
.data(provinces)
.enter()
.append("path")
.attr("d", path)
.attr("stroke", "lightslategrey")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin","round")
.attr("class", "province")
</script>
</body>
</html>