{
var yMax = 1,
yMin = 0,
iterations = 100,
rectSize = 5,
xMin = 1,
xMax = 4;
var data = generateData (xMin, xMax, iterations);
plotBifurcationChart (data);
d3.select("#xMin")
.on("input", function() {
xMin = (this.value < xMax) ? this.value : xMax*0.9999;
d3.select("#xMin-value").text(+xMin);
data = generateData (xMin, xMax, iterations);
plotBifurcationChart (data);
});
d3.select("#xMax")
.on("input", function() {
xMax = (this.value > xMin) ? this.value : xMin*1.0001;
d3.select("#xMax-value").text(+xMax);
data = generateData (xMin, xMax, iterations);
plotBifurcationChart (data);
});
function getDocumentWidth () {
// get document width , this is from the internet...
var width = document.width;
if (width === undefined) {
// if document width fails, e.g., this page http://jblevins.org/projects/markdown-mode/
// then find the biggest element available to grab width
var widthElt = (document.getElementsByTagName('html')[0] ||
document.getElementsByTagName('body')[0] ||
document.querySelector('*'));
// use widthElt’s width or worst-case fallback to the window
width = widthElt ? widthElt.offsetWidth : window.innerWidth;
}
return width;
}
//
// this funditon creates the chaotic data
//
function generateData (xMin, xMax, iterations) {
var myArray = [],
point = {},
lambda = xMin,
y=0.01;
do {
for (var i=0; i<iterations; i++) {
y = lambda * y * (1.0-y);
point = {"x": lambda, "y": y };
myArray.push (point);
}
lambda = lambda*1.0+(xMax-xMin)/iterations;
y=0.01;
} while (lambda < xMax)
return myArray;
}
//
// plot the Bifurkationsgraf
//
function plotBifurcationChart (data) {
var
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 0.85*getDocumentWidth()/2 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
d3.select("g").remove(); // remove old svg 'g' elements
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear()
.range([0, width])
.domain([xMin, xMax]);
var y = d3.scaleLinear()
// .domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0])
.domain([yMin, d3.max(data, function(d) { return d.y; }) ]);
/*
the axis
*/
var xAxis = g => g
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", width - margin.right)
.attr("y", -4)
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "end")
.text(data.x))
var yAxis = g => g
.attr("transform", `translate(0,0)`)
.call(d3.axisLeft(y))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("fill", "#000")
.attr("x", 5)
.attr("y", margin.top)
.attr("dy", "0.32em")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(data.y))
chart
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width)
.attr("y", 18)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("lambda");
chart
.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("y");
/*
the circes
*/
var bar = chart.selectAll("bar")
.data(data)
.enter();
var circle = bar.append("circle")
.attr("class", "crc")
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.attr("r", 3 );
/*
the mouse positiion
*/
var chart = d3.select(".chart");
chart.on("mouseout",
function () {
chart.selectAll(".redLine").remove();
})
chart.on("mousemove",
// drawRedLine
function () {
var mx = d3.mouse(this)[0],
my = d3.mouse(this)[1];
chart.selectAll(".redLine").remove();
d3.select("#xMouse-value").text(mx)
d3.select("#yMouse-value").text(my)
//console.log (d3.mouse(this));
chart
.append ("path")
.attr("class", "redLine")
.attr("stroke", "red")
.attr("d", "M "+mx+","+(height+margin.top)+",L "+mx+","+0+" Z");
chart
.append ("text")
.attr("class", "redLine")
.text( Math.round(10000*x.invert(mx-margin.left))/10000 )
.attr("x", mx+2)
.attr("y", 0)
.attr("dy", ".75em")
.attr("fill", "red")
.attr("text-anchor", "left")
.style("font", "12px sans-serif");
var histogram = new Histogram1D ( yMin, yMax, 100);
var tmpx = x.invert(mx-margin.left);
var tmpData = generateData (tmpx, tmpx, 2000);
for (var i = 0; i< tmpData.length; i++) {
//console.log ("filling: "+ tmpData[i].y );
histogram.fill (tmpData[i].y);
}
//histogram.plot();
plotHistogram ( histogram );
}
);
}
//
// plot a Histogram
//
function plotHistogram (histogram) {
//console.log ("in plotHistogram: " + histogram.bins[4]);
var
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 0.85*getDocumentWidth()/2 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
d3.select("#histogram g").remove(); // remove old svg 'g' elements
var histogramDiv = d3.select("#histogram")
//let histogramDiv = d3.select(DOM.svg(width + margin.left + margin.right, height + margin.top + margin.bottom))
//.attr("id", "histogram")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear()
.range([0, width])
.domain([histogram.xMin, histogram.xMax]);
var y = d3.scaleLinear()
// .domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0])
.domain([0, d3.max(histogram.bins) ]);
/*
the axis
*/
var xAxis = g => g
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", width - margin.right)
.attr("y", -4)
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "end")
.text(data.x))
var yAxis = g => g
.attr("transform", `translate(0,0)`)
.call(d3.axisLeft(y))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("fill", "#000")
.attr("x", 5)
.attr("y", margin.top)
.attr("dy", "0.32em")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(data.y))
histogramDiv
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width)
.attr("y", 18)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("distribution of y");;
histogramDiv
.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("y");
var lineFunction = d3.line()
.x(function (d,i) { return x(i/histogram.nBins); })
.y(function (d,i) { return y(d)});
histogramDiv.append("path")
.attr("d", lineFunction(histogram.bins) )
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
// textbox stats
histogramDiv.append("text")
// .attr("class", "axis")
.attr("y", 10)
.attr("x", 10)
.append("tspan")
.text("N: " + histogram.nEntries)
.append("tspan")
.text("underflow: " + histogram.underflow)
.attr("x", 10)
.attr("dy", 10)
.append("tspan")
.text("overflow: " + histogram.overflow)
.attr("x", 10)
.attr("dy", 10)
.append("tspan")
.text("average: " + Math.round (histogram.average*100)/100)
.attr("x", 10)
.attr("dy", 10);
}
}