Skip to content

Instantly share code, notes, and snippets.

@christophermanning
Last active October 27, 2019 20:02
Show Gist options
  • Save christophermanning/5562420 to your computer and use it in GitHub Desktop.
Save christophermanning/5562420 to your computer and use it in GitHub Desktop.
Spherical Random Walk
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Spherical Random Walk</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<!--<script src="/js/d3.v3.min.js"></script>-->
<!--<script src="/js/dat-gui/build/dat.gui.js"></script> -->
<style type="text/css">
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
var config = { "projection": "Orthographic", "clip": false, "theta": 140, "steps" : 10000, "velocityX": .01, "velocityY": .005 };
var gui = new dat.GUI();
var thetaChanger = gui.add(config, "theta", 1, 360).step(1)
thetaChanger.onChange(function(value) {
config.redraw()
});
gui.add(config, "steps", 1, 50000).step(1);
var projections = {
"Albers": d3.geo.albers(),
"Azimuthal Equal Area": d3.geo.azimuthalEqualArea(),
"Azimuthal Eqidistant": d3.geo.azimuthalEquidistant(),
"Conic Conformal": d3.geo.conicConformal(),
"Conic Equal Area": d3.geo.conicEqualArea(),
"Conic Equidistant": d3.geo.conicEquidistant(),
"Eqirectangular": d3.geo.equirectangular(),
"Gnomonic": d3.geo.gnomonic(),
"Mercator": d3.geo.mercator(),
"Orthographic": d3.geo.orthographic(),
"Stereographic": d3.geo.stereographic(),
"Transverse Mercator": d3.geo.transverseMercator(),
};
Object.keys(projections).forEach(function(o) {
projections[o].rotate([0, 0]).center([0, 0]);
});
var projectionChanger = gui.add(config, "projection", Object.keys(projections));
projectionChanger.onChange(function(value) {
projection = projections[value]
.scale(height/2)
.translate([(width/2)-125, height/2])
.clipAngle(config["clip"] ? 90 : null)
path.projection(projections[value])
});
var clipChanger = gui.add(config, "clip")
clipChanger.onChange(function(value) {
projection.clipAngle(value ? 90 : null)
});
gui.add(config, "velocityX", 0, .1).step(.001).listen()
gui.add(config, "velocityY", 0, .1).step(.001).listen()
config.random = function(){
gui.__controllers.forEach(function(c){
if(typeof(c.__select) != 'undefined') {
c.setValue(c.__select[Math.floor(Math.random()*(c.__select.length-1))].value)
} else {
if(["redraw", "random", "velocityX", "velocityY"].indexOf(c.property) === -1){
c.setValue(Math.floor(Math.random() * c.__max) + c.__min)
}
}
})
}
gui.add(config, "random")
config.redraw = function(){
vertices = [[0,0]]
}
gui.add(config, "redraw")
var width = window.innerWidth,
height = window.innerHeight -5
vertices = [[0,0]]
origin = [0, 0],
t0 = Date.now(),
vertices = [[0, 0]],
rotate = true
var projection = projections[config["projection"]]
.scale(height/2)
.translate([(width/2)-125, height/2])
.clipAngle(config["clip"] ? 90 : null)
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height)
.on("click", function() { rotate = !rotate })
.call(d3.behavior.drag()
.origin(function() { var r = projection.rotate(); return {x: 2 * r[0], y: -2 * r[1]}; })
.on("drag", function() { var r = [d3.event.x / 2, -d3.event.y / 2, projection.rotate()[2]]; t0 = Date.now(); origin = r; projection.rotate(r); }))
var context = canvas.node().getContext("2d");
var path = d3.geo.path()
.projection(projection)
.context(context)
d3.timer(function(t){
if(vertices.length < config["steps"]) {
for(var i=0;i<1000;i++){
var last = vertices[vertices.length-1]
var xo = last[0]
var yo = last[1]
var r = Math.floor(Math.random()*(360/config["theta"]))
var theta = Math.PI * ((r * config["theta"] % 360)/180)
xo += Math.cos(theta)
yo += Math.sin(theta)
vertices.push([xo, yo])
}
} else if(vertices.length > config["steps"]) {
vertices.length = config["steps"]
}
if(rotate){
var t = Date.now() - t0,
o = [origin[0] + t * config["velocityX"], origin[1] + t * config["velocityY"]];
projection.rotate(o)
}
context.clearRect(0, 0, width, height);
context.lineWidth = 1
context.beginPath()
path({"type":"Feature","geometry":{"type":"LineString","coordinates":vertices}})
context.stroke();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment