Skip to content

Instantly share code, notes, and snippets.

@telic
Last active July 16, 2023 19:57
Show Gist options
  • Select an option

  • Save telic/9376360 to your computer and use it in GitHub Desktop.

Select an option

Save telic/9376360 to your computer and use it in GitHub Desktop.
Smoothed random number generator

Synopsis

An attempt at a "smoothed" random generator. Each consecutive generated number is constrained to be within an envelope near the previous number. The width of the envelope is controlled by the inverse of the smoothing factor; thus higher factors will produce output that varies less from number to number.

Usage

var r = SmoothRandom(2);
var d = [];
while (d.length < 100) {
    d.push(r());
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Smoothed random line</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="SmoothRandom.js"></script>
<style>
path {
stroke: black;
stroke-width: 1px;
fill: none;
}
</style>
</head>
<body>
<div id="canvas"></div>
<form>
<label>Smoothing factor: <input id="smooth" type="range" value="5" min="1" max="20" step="0.1"/></label>
</form>
<script>
var samples = 100;
var size = { y:200, x:500 };
var margin = 10;
var xScale = d3.scale.linear().domain([0,samples-1]).range([0,size.x]);
var yScale = d3.scale.linear().domain([0,1]).range([0,size.y]);
var line = d3.svg.line().x(function (d,i) { return xScale(i); }).y(function (d) { return yScale(d); });
var svg = d3.select("#canvas").append("svg").attr({ width:size.x+margin*2, height:size.y+margin*2 });
svg.append("clipPath").attr("id", "clip")
.append("rect").attr({ x:0, y:0, height:size.y, width:size.x });
var r = SmoothRandom(d3.select("#smooth").node().value);
function setSmoothing() {
r = SmoothRandom(d3.select("#smooth").node().value, r());
}
d3.select("form").on("change", setSmoothing);
var data = [];
for (var i=0; i<samples+1; i++) { data.push(r()); }
var p = svg.append("g").attr({
"transform": "translate("+margin+","+margin+")",
"clip-path": "url(#clip)"
}).append("path").datum(data);
function update() {
data.push(r());
d3.select("path")
.attr("d", line)
.attr("transform", null)
.transition().duration(100).ease("linear")
.attr("transform", "translate("+xScale(-1)+",0)")
.each("end", update);
data.shift();
}
update();
</script>
</body>
</html>
function SmoothRandom(factor, start) {
var last = (start!==undefined)?start:Math.random();
var halfEnvelope = (1/factor)/2;
return function() {
// clamp output range to [0,1] as Math.random()
var max = Math.min(1, last + halfEnvelope);
var min = Math.max(0, last - halfEnvelope);
// return a number within halfRange of the last returned value
return last = Math.random()*(max-min)+min;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment