Skip to content

Instantly share code, notes, and snippets.

@jgbos
Last active December 15, 2015 15:38
Show Gist options
  • Save jgbos/5283008 to your computer and use it in GitHub Desktop.
Save jgbos/5283008 to your computer and use it in GitHub Desktop.
Simple Ellipsoid Gravity
(function() {
// From http://bl.ocks.org/mbostock/3057239
var φ = 1.618033988749895,
ρ = 180 / Math.PI;
var vertices = [
[1,φ,0], [-1,φ,0], [1,-φ,0], [-1,-φ,0],
[0,1,φ], [0,-1,φ], [0,1,-φ], [0,-1,-φ],
[φ,0,1], [-φ,0,1], [φ,0,-1], [-φ,0,-1]
];
var triangles = [
[0,1,4], [1,9,4], [4,9,5], [5,9,3], [2,3,7],
[3,2,5], [7,10,2], [0,8,10], [0,4,8], [8,2,10],
[8,4,5], [8,5,2], [1,0,6], [11,1,6], [3,9,11],
[6,10,7], [3,11,7], [11,6,7], [6,0,10], [9,1,11]
].map(function(triangle) {
return triangle.map(function(i) {
return vertices[i];
});
});
d3.geodesic = {
multipolygon: function(n) {
return {
type: "MultiPolygon",
coordinates: geodesic(~~n).map(function(triangle) {
triangle = triangle.map(project);
triangle.push(triangle[0]);
return [triangle];
})
};
},
polygons: function(n) {
return geodesic(~~n).map(function(triangle) {
triangle = triangle.map(project);
triangle.push(triangle[0]);
return {type: "Polygon", coordinates: [triangle]};
});
}
};
function geodesic(n) {
return d3.merge(triangles.map(function(triangle) {
var i01 = interpolate(triangle[0], triangle[1]),
i02 = interpolate(triangle[0], triangle[2]),
triangles = [];
triangles.push([
triangle[0],
i01(1 / n),
i02(1 / n)
]);
for (var i = 1; i < n; ++i) {
var i1 = interpolate(i01(i / n), i02(i / n)),
i2 = interpolate(i01((i + 1) / n), i02((i + 1) / n));
for (var j = 0; j <= i; ++j) {
triangles.push([
i1(j / i),
i2(j / (i + 1)),
i2((j + 1) / (i + 1))
]);
}
for (var j = 0; j < i; ++j) {
triangles.push([
i1(j / i),
i1((j + 1) / i),
i2((j + 1) / (i + 1))
]);
}
}
return triangles;
}));
}
function interpolate(p0, p1) {
var x0 = p0[0],
y0 = p0[1],
z0 = p0[2],
x1 = p1[0] - x0,
y1 = p1[1] - y0,
z1 = p1[2] - z0;
return function(t) {
return [
x0 + t * x1,
y0 + t * y1,
z0 + t * z1
];
};
}
function project(p) {
var x = p[0],
y = p[1],
z = p[2];
return [
Math.atan2(y, x) * ρ,
Math.acos(z / Math.sqrt(x * x + y * y + z * z)) * ρ - 90
];
}
})();
<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
stroke: #000;
stroke-width: .5px;
}
circle {
fill: none;
stroke: #000;
stroke-width: 2px;
}
</style>
<body>
<script src="http://d3js.org/d3.v2.min.js?2.9.6"></script>
<script src="geodesic.js"></script>
<script>
var width = 960,
height = 500;
var origin = [0, 0],
velocity = [.010, .005],
t0 = Date.now();
var projection = d3.geo.azimuthal()
.mode("orthographic")
.origin(origin)
.scale(240);
var path = d3.geo.path()
.projection(projection);
var arc = d3.geo.greatArc()
.source(origin)
.target(function(d) { return d; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("path")
.data(d3.geodesic.polygons(8))
.enter().append("path")
.style("fill", function(d) { return d3.hsl(d.coordinates[0][0][0], .7, .5); });
svg.append("circle")
.attr("transform", "translate(" + projection(origin) + ")")
.attr("r", 240);
d3.timer(function() {
var t = Date.now() - t0,
o = [origin[0] + t * velocity[0], origin[1] + t * velocity[1]];
projection.origin(o);
arc.source(o);
svg.selectAll("path").attr("d", function(d) { return visible(d) ? path(d) : null; });
});
function visible(d) {
return d.coordinates[0].some(function(p) {
return arc.distance(p) < Math.PI / 2;
});
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment