##The Ditch
The Yukon Ditch was a ditch, flume, and pipeline aqueduct system that brought water from what is now Tombstone Territorial Park to the gold fields of the Klondike. Construction commenced in 1906 and was completed in 1910.
It carried water by gravity alone over the course of over 110 km. This presented a number of challenges and explains the circuitous route. Perhaps the greatest challenge was crossing the Klondike River valley. To cross the valley a pipeline was required, one of several along the route. According to T.A. Rickard, writing in 1909, the intake of the intake of the pipeline across the valley was at 2440 feet above sea level, the lowest point of the pipeline was at 1282 feet, with the discharge point at 2240 feet. With a hydraulic head of over 1000 feet, the pressure at the bottom of the pipe would be about 500 psi.
The pipeline served to aid hydraulic mining in the gold fields. It also provided power for the dredges through a powerhouse located near the intakes. The transmission lines are represented through the dashed line.
The ditch was in operation until 1933, a few more indepth articles on it can be found here, (in addition to the work by T.A. Rickard, referenced above): *The Yukon Ditch was an engineering marvel, Yukon News, 2010 *The Yukon Ditch, Association of Professional Engineers of Yukon
There is a second ditch on the map, that is the one ending above Dawson in a reservoir. This is the Acklen ditch, and was used presumably for drinking water, at least when the Yukon ditch was first constructed.
The railway shown is the narrow gauge Klondike Mines Railway, which operated briefly between Dawson City and Sulphur Springs. It ran from 1905 to 1913 and was about 50 km long.
This type of structure was not unique to Dawson. Fairbanks had the Davidson Ditch, while Nome had the Miocene Ditch
##Code This map uses d3.js v4.
The original purpose in creating this map was to try and show an aqueduct style symbology, but it just felt plain without the other content. I have a bl.ock on both rail symbology and the scale bar with those two elements by themselves.
The aqueduct symbology is rather simple, compared to the rail and should be pretty clear.
xxxxxxxxxx
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<svg width="960" height="960"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script>
d3.select(self.frameElement).style("height", "960px");
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var projection = d3.geoKavrayskiy7()
.scale(75000)
.rotate([139.10, 0])
.center([0,64.18])
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geoPath()
.projection(projection);
// Add a few groups for proper layering
var g = svg.append("g");
var g2 = svg.append("g");
var g3 = svg.append("g");
var g4 = svg.append("g");
////////////////////////////////////////////////////////////
// Add the contour map
d3.json("topo.json", function(error, contours) {
var paths = g.selectAll(".contour")
.data(topojson.feature(contours, contours.objects.contours).features)
.enter().append("path")
.attr("d", path)
.attr("class", function(d,i) { return "contour c" + d.properties.gridcode; });
});
////////////////////////////////////////////////////////////
// Add water and streams to the map
d3.json("water.json", function(error, water) {
var paths = g2.selectAll(".water")
.data(topojson.feature(water, water.objects.water).features)
.enter().append("path")
.attr("d", path)
.attr("class", "water");
});
d3.json("streams.json", function(error, water) {
var paths = g2.selectAll(".streams")
.data(topojson.feature(water, water.objects.water).features)
.enter().append("path")
.attr("d", path)
.attr("class", "streams");
});
////////////////////////////////////////////////////////////
// Add the Yukon Ditch and Acklen ditch
d3.json("aqueducts.json", function(error, aqueduct) {
var paths = g3.selectAll(".aqueduct")
.data(topojson.feature(aqueduct, aqueduct.objects.aqueduct).features)
.enter().append("path")
.attr("d", path)
.attr("class", "aqueduct")
.attr("id",function(d,i) { return "aqueduct" + i });
// Add circles along the aqueduct paths
paths.each(function(d,i) {
var currentPath = d3.select("#aqueduct" + i).node();
var totalLength = currentPath.getTotalLength();
var numberOfSymbols = Math.round(totalLength/25);
var spacingOfSymbols = totalLength/numberOfSymbols;
var intialSpacng = spacingOfSymbols/2;
var j = 0;
while (j < numberOfSymbols) {
var p = currentPath.getPointAtLength( (spacingOfSymbols/2) + (spacingOfSymbols * j) );
var point = g3.append("circle")
.attr("cx", p.x)
.attr("cy", p.y)
.attr("r", 3)
.attr("class","aqueduct-symbol");
j++;
}
});
});
////////////////////////////////////////////////////////////
// Add transmission lines
d3.json("power.json", function(error, power) {
var paths = g3.selectAll(".power")
.data(topojson.feature(power, power.objects.power).features)
.enter().append("path")
.attr("d", path)
.attr("class", "power");
});
////////////////////////////////////////////////////////////
// Add the railroad
d3.json("railroad.json", function(error, railroad) {
var paths = g3.selectAll(".railroad")
.data(topojson.feature(railroad, railroad.objects.railroad).features)
.enter().append("path")
.attr("d", path)
.attr("class", "rail")
.attr("id",function(d,i) { return "r" + i });
// Figure out how many cross hatches are needed for each track section
paths.each(function(d,i) {
var currentPath = d3.select("#r" + i).node();
var totalLength = currentPath.getTotalLength();
var numberOfSymbols = Math.round(totalLength/6);
var spacingOfSymbols = totalLength/numberOfSymbols;
var intialSpacng = spacingOfSymbols/2;
var j = 0;
// Add each cross hatch at the right angle
while (j < numberOfSymbols) {
var p1 = currentPath.getPointAtLength( (spacingOfSymbols/2 - 5) + (spacingOfSymbols * j) );
var p2 = currentPath.getPointAtLength( (spacingOfSymbols/2 + 5) + (spacingOfSymbols * j) );
var p3 = currentPath.getPointAtLength( (spacingOfSymbols/2) + (spacingOfSymbols * j) );
var r = 3; // length of cross hatch from line
var m = (p2.y - p1.y) / (p1.x - p2.x);
m = 1/m;
var k = r / Math.sqrt( 1 + (m*m) );
if (m == Infinity) {
p1.x = p3.x;
p1.y = p3.y + r;
p2.y = p3.y - r;
p2.x = p3.x;
}
else {
p1.x = p3.x + k;
p1.y = p3.y + (m * k);
p2.x = p3.x - k;
p2.y = p3.y - (m * k);
}
var line = g3.append("line")
.attr("x1",p1.x)
.attr("x2",p2.x)
.attr("y1",p1.y)
.attr("y2",p2.y)
.attr("class", "rail")
.attr("stroke-width",1);
j++;
}
});
});
////////////////////////////////////////////////////////////
// Add some labels
d3.csv("points.csv", function ( error, data ) {
var points = g4.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return projection([d.lon,d.lat])[0]; })
.attr("cy", function(d) { return projection([d.lon,d.lat])[1]; })
.attr("r",5)
.attr("class","point")
.attr("stroke", function(d) { return d.color });
var text = g4.selectAll(".label")
.data(data)
.enter()
.append("text")
.attr("x", function(d) { return projection([d.lon,d.lat])[0] - d.offset; })
.attr("y", function(d) { return projection([d.lon,d.lat])[1] - 2; })
.attr("text-anchor", function(d) { return d.anchor })
.text(function(d) { return " " + d.name })
.attr("class","text")
.attr("font-size",12);
});
////////////////////////////////////////////////////////////
// Regional Labels
g4.append("text")
.attr("x", projection([-139.228,63.97])[0] )
.attr("y", projection([-139.228,63.97])[1] )
.attr("text-anchor","middle")
.attr("class","region-label text")
.text("The Gold Fields");
g4.append("text")
.attr("x", projection([-138.799,64.3966])[0] )
.attr("y", projection([-138.799,64.3966])[1] )
.attr("text-anchor","middle")
.attr("class","region-label text")
.text("Tombstone Range");
////////////////////////////////////////////////////////////
// Add a title
g4.append("text")
.attr("x", 200 )
.attr("y", 100 )
.attr("class","text")
.attr("font-size",24)
.attr("text-decoration","underline")
.text("The Yukon Ditch");
////////////////////////////////////////////////////////////
// Add a scale
var baseWidth = width / 4;
var p1 = projection.invert([width/2 - baseWidth/2, height / 2]);
var p2 = projection.invert([width/2 + baseWidth/2, height / 2]);
var distance = getDistance(p1,p2);
var unit = "m";
var multiply = 1;
var bestFit = 1;
var increment = 0.1;
var scaleDistance = 0;
var scaleWidth = 0;
if ( distance > 1000 ) {
unit = "km"; multiply = 0.001;
}
// Adjust distance to a round(er) number
var i = 0;
while (i < 400) {
var temp = getDistance( projection.invert([ width/2 - (baseWidth / 2) + (increment * i), height / 2 ]), projection.invert([ width/2 + baseWidth/2 - (increment * i), height / 2 ]));
var ratio = temp / temp.toPrecision(1);
// If the second distance is moving away from a cleaner number, reverse direction.
if (i == 1) {
if (Math.abs(1 - ratio) > bestFit) { increment = - increment; }
}
// If we are moving away from a best fit after that, break
else if (i > 2) {
if (Math.abs(1 - ratio) > bestFit) { break }
}
// See if the current distance is the cleanest number
if (Math.abs(1-ratio) < bestFit) {
bestFit = Math.abs(1 - ratio);
scaleDistance = temp;
scaleWidth = (baseWidth) - (2 * increment * i);
}
i++;
}
// Now to build the scale
var margin = {
left: 600, // scale is this far from the left
bottom:200 // scale is this far off the bottom
}
var bars = [];
var smallBars = 10;
var bigBars = 4;
var odd = true;
var label = false;
// Populate an array to represent the bars on the scale
for (i = 0; i < smallBars; i++) {
if (smallBars - 1 > i ) { label = false; } else { label = true; }
bars.push( {width: 1 / (smallBars * (bigBars + 1)), offset: i / (smallBars * (bigBars + 1)), label: label, odd: odd } );
odd = !odd;
}
for (i = 0; i < bigBars; i++) {
bars.push( {width: 1 / (bigBars + 1), offset: (i + 1) / (bigBars + 1), label: true, odd: odd } );
odd = !odd;
}
// Append the scale
g.selectAll(".scaleBar")
.data(bars).enter()
.append("rect")
.attr("x", function(d) { return d.offset * scaleWidth + margin.left })
.attr("y", height - margin.bottom)
.attr("width", function(d) { return d.width * scaleWidth})
.attr("height", 10)
.attr("fill", function (d) { if (d.odd) { return "#ccc"; } else { return "#222"; } });
g.selectAll(".scaleText")
.data(bars).enter()
.filter( function (d) { return d.label == true })
.append("text")
.attr("class","scaleText")
.attr("x",0)
.attr("y",0)
.style("text-anchor","start")
.text(function(d) { return d3.format(",")(((d.offset + d.width) * scaleDistance).toPrecision(2) * multiply); })
.attr("transform", function(d) { return "translate("+ ((d.offset + d.width) * scaleWidth + margin.left )+","+ (height - margin.bottom -5) +") rotate(-45)" });
g.append("text")
.attr("x", scaleWidth/2 + margin.left)
.attr("y", height - margin.bottom + 25)
.text( function() { if(unit == "km") { return "kilometers"; } else { return "metres";} })
.style("text-anchor","middle")
.attr("class","scaleText");
// End Scale -----------------------------------------
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Latitude/longitude spherical geodesy tools (c) Chris Veness 2002-2016 */
/* MIT Licence */
/* www.movable-type.co.uk/scripts/latlong.html */
/* www.movable-type.co.uk/scripts/geodesy/docs/module-latlon-spherical.html */
function getDistance(p1,p2) {
var lat1 = p1[1];
var lat2 = p2[1];
var lon1 = p1[0];
var lon2 = p2[0];
var R = 6371e3; // metres
var φ1 = lat1* Math.PI / 180;
var φ2 = lat2* Math.PI / 180;
var Δφ = (lat2-lat1)* Math.PI / 180;
var Δλ = (lon2-lon1)* Math.PI / 180;
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var distance = R * c;
return distance;
}
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-geo-projection.v1.min.js
https://d3js.org/topojson.v1.min.js