2016年9月5日月曜日

開発環境

Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の6章(幾何図形とフラクタルを描画)、6.4(プログラミングチャレンジ)、問題6-4(マンデルブロを集合を描く(Mandelbrot set))をJavaScript(とarray.js)で取り組んでみる。

問題6-4(マンデルブロを集合を描く(Mandelbrot set))

コード(Emacs)

HTML5

<div id="graph0"></div>
<label for="nums0">
  座標軸の区切りの個数:
</label>
<input id="nums0" type="number" min="1" step="1" value="200">
<label for="iteration0">
  反復最大回数: 
</label>
<input id="iteration0" type="number" min="1" step="1" value="100">

<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="number.js"></script>
<script src="sample4.js"></script>

JavaScript

(function () {
    'use strict';
    var X_MIN = -2.5,
        X_MAX = 1.0,
        Y_MIN = -1.0,
        Y_MAX = 1.0,
        ratio = (Y_MAX - Y_MIN) / (X_MAX - X_MIN),
        width = 600,
        height = width * ratio,
        x_padding  = 50,
        y_padding = x_padding * ratio,
        xscale,
        yscale,
        xaxis,
        yaxis,
        timeoutIDs = [],
        color = 'blue',

        div_graph = document.querySelector('#graph0'),
        svg,
        input_nums = document.querySelector('#nums0'),
        input_iteration = document.querySelector('#iteration0'),
        inputs = [input_nums, input_iteration],

        getPoints,
        drawMandelbrotSet;

    xscale = d3.scaleLinear()
        .domain([X_MIN, X_MAX])
        .range([x_padding, width - x_padding]);
    yscale = d3.scaleLinear()
        .domain([Y_MIN, Y_MAX])
        .range([height - y_padding, y_padding]);
    xaxis = d3.axisBottom().scale(xscale);
    yaxis = d3.axisLeft().scale(yscale);

    getPoints = function (n) {
        var points = [],
            step_x = (X_MAX - X_MIN) / n,
            step_y = (Y_MAX - Y_MIN) / n;

        range(X_MIN, X_MAX, step_x).forEach(function (x) {
            range(Y_MIN, Y_MAX, step_y).forEach(function (y) {
                points.push([x, y]);
            });
        });
        return points;
    };
    drawMandelbrotSet = function () {
        var n = parseInt(input_nums.value, 10),
            max_iteration = parseInt(input_iteration.value, 10),
            points = getPoints(n);

        div_graph.innerHTML = '';
        svg = d3.select('#graph0')
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        svg.selectAll('circle')
            .data(points)
            .enter()
            .append('circle')
            .attr('cx', function (d) {
                return xscale(d[0]);
            })
            .attr('cy', function (d) {
                return yscale(d[1]);
            })
            .attr('r', 1)
            .attr('fill', function (d) {
                var iteration = 0,
                    z = 0,
                    c = new Complex(d[0], d[1]),
                    t = 0;

                for (;t < 2 && iteration < max_iteration ;) {
                    z = z.mul(z).add(c);
                    iteration += 1;
                    t = z.magnitude(z);
                }
                return t < 2 ? 'white' : 'black';
            });
        svg.append('g')
            .attr('transform', 'translate(0, ' + (height - y_padding) + ')')
            .call(xaxis);
        svg.append('g')
            .attr('transform', 'translate(' + x_padding + ', 0)')
            .call(yaxis);
    };

    inputs.forEach(function (input) {
        input.onchange = drawMandelbrotSet;
    });

    drawMandelbrotSet();
}());

0 コメント:

コメントを投稿