Skip to content

Instantly share code, notes, and snippets.

Created October 24, 2016 22:10
Show Gist options
  • Save anonymous/621f1a070cd884af3ccc8bcb5c9801c4 to your computer and use it in GitHub Desktop.
Save anonymous/621f1a070cd884af3ccc8bcb5c9801c4 to your computer and use it in GitHub Desktop.
Geodesic Random
license: mit
!function(){function n(n){return d3.merge(e.map(function(t){var o=r(t[0],t[1]),u=r(t[0],t[2]),i=[];i.push([t[0],o(1/n),u(1/n)]);for(var a=1;n>a;++a){for(var e=r(o(a/n),u(a/n)),c=r(o((a+1)/n),u((a+1)/n)),f=0;a>=f;++f)i.push([e(f/a),c(f/(a+1)),c((f+1)/(a+1))]);for(var f=0;a>f;++f)i.push([e(f/a),c((f+1)/(a+1)),e((f+1)/a)])}return i}))}function t(t){function r(n,t){var r;(n[0]<t[0]||n[0]==t[0]&&(n[1]<t[1]||n[1]==t[1]&&n[2]<t[2]))&&(r=n,n=t,t=r),u[n.map(o)+" "+t.map(o)]=[n,t]}function o(n){return d3.round(n,4)}var u={};return n(t).forEach(function(n){r(n[0],n[1]),r(n[1],n[2]),r(n[2],n[0])}),d3.values(u)}function r(n,t){var r=n[0],o=n[1],u=n[2],i=t[0]-r,a=t[1]-o,e=t[2]-u;return function(n){return[r+n*i,o+n*a,u+n*e]}}function o(n){var t=n[0],r=n[1],o=n[2];return[Math.atan2(r,t)*i,Math.acos(o/Math.sqrt(t*t+r*r+o*o))*i-90]}var u=1.618033988749895,i=180/Math.PI,a=[[1,u,0],[-1,u,0],[1,-u,0],[-1,-u,0],[0,1,u],[0,-1,u],[0,1,-u],[0,-1,-u],[u,0,1],[-u,0,1],[u,0,-1],[-u,0,-1]],e=[[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(n){return n.map(function(n){return a[n]})});d3.geodesic={multipolygon:function(t){return{type:"MultiPolygon",coordinates:n(~~t).map(function(n){return n=n.map(o),n.push(n[0]),n=[n]})}},polygons:function(n){return d3.geodesic.multipolygon(~~n).coordinates.map(function(n){return{type:"Polygon",coordinates:n}})},multilinestring:function(n){return{type:"MultiLineString",coordinates:t(~~n).map(function(n){return n.map(o)})}}}}();
<!DOCTYPE html>
<meta charset="utf-8">
<style>
#subdivision {
position: absolute;
top: 20px;
left: 20px;
}
#subdivision input {
width: 200px;
}
</style>
<div id="subdivision">
<input type="range" min="1" max="12" value="8">
<output name="subdivision"></output>
</div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.geodesic.min.js"></script>
<script>
var width = 960,
height = 500;
var velocity = [.010, .0025],
t0 = Date.now();
var projection = d3.geo.orthographic()
.scale(height / -0.9472 - 43);
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
context.strokeStyle = "#cccccc";
context.lineWidth = .25;
var faces;
var output = d3.select("output");
var input = d3.select("input")
.on("input", function() { geodesic(+this.value); })
.on("change", function() { geodesic(+this.value); })
.each(function() { geodesic(+this.value); });
d3.timer(function() {
var time = Date.now() - t0;
projection.rotate([time * velocity[0], time * velocity[1]]);
redraw();
});
function redraw() {
context.clearRect(0, 0, width, height);
faces.forEach(function(d) {
d.polygon[0] = projection(d[0]);
d.polygon[1] = projection(d[1]);
d.polygon[2] = projection(d[2]);
if (d.visible = d.polygon.area() > 0) {
context.fillStyle = 'white';
context.beginPath();
drawTriangle(d.polygon);
context.fill();
}
});
context.beginPath();
faces.forEach(function(d) {
if (d.visible) {
drawTriangle(d.polygon);
}
});
context.stroke();
}
function drawTriangle(triangle) {
context.moveTo(triangle[0][0], triangle[0][1]);
context.lineTo(triangle[1][0], triangle[1][1]);
context.lineTo(triangle[2][0], triangle[2][1]);
context.closePath();
}
function geodesic(subdivision) {
output.text(subdivision);
faces = d3.geodesic.polygons(subdivision).map(function(d) {
d = d.coordinates[0];
d.pop(); // use an open polygon
d.fill = d3.hsl(d[0][0], 1, .5) + "";
d.polygon = d3.geom.polygon(d.map(projection));
return d;
});
redraw();
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment