Skip to content

Instantly share code, notes, and snippets.

@md5
Forked from mbostock/.block
Last active January 6, 2016 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save md5/359b305b7f6996fbf2e0 to your computer and use it in GitHub Desktop.
Save md5/359b305b7f6996fbf2e0 to your computer and use it in GitHub Desktop.
Loxodrome

Loxodrome/rhumb lines

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #fcfcfa;
}
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill {
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: 1px;
stroke-opacity: .5;
}
.loxodrome {
fill: none;
stroke: #0A0;
stroke-width: 2px;
stroke-opacity: .5;
}
.land {
fill: #222;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="loxodrome.js"></script>
<script>
var width = 960,
height = 960;
var projection = d3.geo.orthographic()
.scale(475)
.translate([width / 2, height / 2])
.clipAngle(90)
.precision(.1);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule()
.minorExtent([[-180, -90 + 1e-6], [180, 90 - 1e-6]])
.majorStep([90,0])
.minorStep([30,0]);
var λ = d3.scale.linear()
.domain([0, width])
.range([-180, 180]);
var φ = d3.scale.linear()
.domain([0, height])
.range([90, -90]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
var loxodrome = d3.geo.loxodrome([-180,90], [1940,-90]);
svg.append("path")
.datum(loxodrome)
.attr("class", "loxodrome")
.attr("d", path);
svg.on("ontouchstart" in document ? "touchmove" : "mousemove", function() {
var p = d3.mouse(this);
projection.rotate([λ(p[0]), φ(p[1])]);
svg.selectAll("path").attr("d", path);
});
d3.select(self.frameElement).style("height", height + "px");
</script>
d3.geo.loxodrome = function(p0, p1) {
var ε = 1e-6,
abs = Math.abs,
x0 = p0[0],
y0 = p0[1],
x1 = p1[0],
y1 = p1[1];
function loxodrome() {
return { type: "LineString", coordinates: coordinates() };
}
function coordinates() {
if (abs(x0 - x1) < ε) {
return [p0, p1];
} else if (x1 < x0) {
x1 += 360;
}
var m = (y1 - y0) / (x1 - x0);
return d3.range(x0, x1, .1).concat(x1).map(function (x) { return [x, m * (x - x1) + y1]; });
}
return loxodrome;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment