-
-
Save Andrew-Reid/fb091eca1ad507e155fd3544c73453d1 to your computer and use it in GitHub Desktop.
GeoEllipse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/topojson.v1.min.js"></script> | |
<script> | |
var width = 800; | |
var height = 800; | |
var svg = d3.select("body").append("svg") | |
.attr("width",width) | |
.attr("height",height); | |
var projection = d3.geoOrthographic(); | |
var path = d3.geoPath().projection(projection); | |
d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, world) { | |
if (error) throw error; | |
svg.insert("path", ".graticule") | |
.datum(topojson.feature(world, world.objects.land)) | |
.attr("class", "land") | |
.attr("d", path); | |
var ellipses = [[1000000,500000,50,70,45],[100000,500000,-50,70],[1000000,3000000],[3000000,1000000,-100,-20],[1000000,3000000,100,-20,15]] | |
var geojson = ellipses.map(function(d) { | |
return createEllipse(...d); | |
}) | |
svg.selectAll() | |
.data(geojson) | |
.enter() | |
.append("path") | |
.attr("d",path) | |
.attr("fill","orange"); | |
var speed = 0.5e-2; | |
var start = Date.now(); | |
d3.timer(function() { | |
projection.rotate([speed * (Date.now() - start), -15]); | |
d3.selectAll("path").attr("d",path); | |
}); | |
}) | |
function createEllipse(a,b,x,y,rotation) { | |
if(typeof rotation == 'undefined') { rotation = 0; } | |
if(typeof x == 'undefined') { x = 0; } | |
if(typeof y == 'undefined') { y = 0; } | |
var k = Math.ceil(36 * (Math.max(a/b,b/a))); // sample angles | |
var coords = []; | |
for (var i = 0; i <= k; i++) { | |
// get the current angle | |
var angle = Math.PI*2 / k * i + rotation | |
// get the radius at that angle | |
var r = a * b / Math.sqrt(a*a*Math.sin(angle)*Math.sin(angle) + b*b*Math.cos(angle)*Math.cos(angle)); | |
coords.push(getLatLong([x,y],angle,r)); | |
} | |
return { "type":"Polygon", "coordinates":[coords] }; | |
} | |
function getLatLong(center,angle,radius) { | |
var rEarth = 6371000; // meters | |
x0 = center[0] * Math.PI / 180; // convert to radians. | |
y0 = center[1] * Math.PI / 180; | |
var y1 = Math.asin( Math.sin(y0)*Math.cos(radius/rEarth) + Math.cos(y0)*Math.sin(radius/rEarth)*Math.cos(angle) ); | |
var x1 = x0 + Math.atan2(Math.sin(angle)*Math.sin(radius/rEarth)*Math.cos(y0), Math.cos(radius/rEarth)-Math.sin(y0)*Math.sin(y1)); | |
y1 = y1 * 180 / Math.PI; | |
x1 = x1 * 180 / Math.PI; | |
return [x1,y1]; | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment