2016年9月4日日曜日

開発環境

Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の6章(幾何図形とフラクタルを描画)、6.4(プログラミングチャレンジ)、問題6-3(エノンの関数を調べる(Hénon map、Michel Hénon))をJavaScript(とarray.js)で取り組んでみる。

問題6-3(エノンの関数を調べる(Hénon map、Michel Hénon))

コード(Emacs)

HTML5

<div id="graph0"></div>
<label for="nums0">
  点の個数:
</label>
<input id="nums0" type="number" min="1" step="1" value="10000">
<progress id="progress0"></progress>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>

<script src="array.js"></script>
<script src="sample3.js"></script>

JavaScript

(function () {
    'use strict';
    var width = 600,
        height = 600,
        padding = 50,
        xscale,
        yscale,
        xaxis,
        yaxis,
        timeoutIDs = [], 

        div_graph = document.querySelector('#graph0'),
        svg,
        input_nums = document.querySelector('#nums0'),
        progress = document.querySelector('#progress0'),

        clearTimeoutIDs,
        transform,
        getPoints,
        drawCircles,
        draw;

    clearTimeoutIDs = function () {
        timeoutIDs.forEach(function (id) {
            clearTimeout(id);
        });
    };
    transform = function (point) {
        var x = point[0],
            y = point[1];
        
        return [y + 1 - 1.4 * Math.pow(x, 2), 0.3 * x];
    };

    getPoints = function (n) {
        var point = [1, 1],
            points = [point];

        range(n).forEach(function () {
            point = transform(point);
            points.push(point);
        });
        return points;
    };
    drawCircles = function (points, i, n) {
        var circles = svg.selectAll('circle')
            .data(points.slice(0, i + 1));

        // enter
        circles.enter()
            .append('circle')
            .attr('cx', xscale(points[i][0]))
            .attr('cy', yscale(points[i][1]))
            .attr('r', 1)
            .attr('fill', 'green');
        // update
        circles.transition()
            .attr('cx', function (d) {
                return xscale(d[0]);
            })
            .attr('cy', function (d) {
                return yscale(d[1]);
            })
            .attr('r', 2)
            .attr('fill', 'green');
        i += 1;
        progress.value = i;
        if (i !== n) {
            timeoutIDs.push(
                setTimeout(function () {
                    drawCircles(points, i, n);
                }, 10));
        }
    };
    draw = function () {
        var n = parseInt(input_nums.value, 10),        
            points = getPoints(n),
            xs = points.map(function (point) { return point[0]; }),
            ys = points.map(function (point) { return point[1]; }),
            xmin = d3.min(xs),
            xmax = d3.max(xs),
            ymin = d3.min(ys),
            ymax = d3.max(ys),
            i = 0;

        clearTimeoutIDs();
        progress.value = 0;
        progress.max = n;    
        
        xscale = d3.scaleLinear()
            .domain([xmin, xmax])
            .range([padding, width - padding]);
        yscale = d3.scaleLinear()
            .domain([ymin, ymax])
            .range([height - padding, padding]);
        xaxis = d3.axisBottom().scale(xscale);
        yaxis = d3.axisLeft().scale(yscale);

        div_graph.innerHTML = '';
        svg = d3.select('#graph0')
            .append('svg')
            .attr('width', width)
            .attr('height', height);
        
        svg.append('g')
            .attr('transform', 'translate(0, ' + (height - padding) + ')')
            .call(xaxis);
        svg.append('g')
            .attr('transform', 'translate(' + padding + ', 0)')
            .call(yaxis);

        drawCircles(points, i, n);
    };

    input_nums.onchange = draw;
    draw();
}());

0 コメント:

コメントを投稿