БлогNot. Javascript: рисуем множество Жюлиа

Javascript: рисуем множество Жюлиа

Если мы что и знаем о множествах Жюлиа, обычно это лишь то, что "они красивые", ну, вот такие примерно:

множество Жюлиа, картинка
множество Жюлиа, картинка

Ниже приложен небольшой сервис, позволяющий изобразить точки из окрестности множества примерно так, как это делается в "Вики".

Похоже чем-то на мандельбротщину, но не в Маткаде, а прямо онлайн и цветное.

Способ извлечения параметров и код - самые примитивные, после любого нового выбора из списка старая канва удаляется и заменяется новой. Ну а выбор всех настроек из списков сделан, чтобы не соблазнять юзера ничего вводить.

Большинство этих конфигураций будут "мёртвые", но вы можете попытаться найти и "живые" :) Если получится что-то красивее, чем картинка по умолчанию - отпишитесь с цифрами настроек, для этого в скрипте есть кнопка "Записать", выводящая нужную строку текста, например

Итераций: 1000, Размер канвы: 800, Коэффициенты: -0.7, 0.7, -0.8, 0.8, 0.285, 0.01

Кнопка "Сброс" возвращает настройки по умолчанию.

 Приложение в работе (текущее окно/вкладка)

 JuliaSet.html, файл приложения (скачать правой кнопкой мыши) (9 Кб)

Полный исходник, большая часть которого - просто форма HTML, предполагается, что файл .html будет сохранён в Юникоде (UTF-8):

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>Julia Set</title>
 </head>
<body>
<div align="center">

<form name="juliaForm">
Итераций: <select size="1" name="maxIterations" id="maxIterations" onchange="init()">
 <option value="100">100
 <option value="200">200
 <option value="300">300
 <option value="400">400
 <option value="450" selected>450
 <option value="500">500
 <option value="600">600
 <option value="700">700
 <option value="800">800
 <option value="900">900
 <option value="1000">1000
</select>
Размер канвы: <select size="1" name="canvasSize" id="canvasSize" onchange="init()">
 <option value="400">400
 <option value="600" selected>600
 <option value="800">800
 <option value="1000">1000
</select>
Коэффициенты:
<select size="1" name="minX" id="minX" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5" selected>-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="0">0
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5">0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (minX), 
<select size="1" name="maxX" id="maxX" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5">-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="0">0
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5" selected>0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (maxX), 
<select size="1" name="minY" id="minY" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5" selected>-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="0">0
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5">0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (minY), 
<select size="1" name="maxY" id="maxY" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5">-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="0">0
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5" selected>0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (maxY),
<select size="1" name="jsX" id="jsX" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5">-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="0">0
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.25">0.25
 <option value="0.275">0.275
 <option value="0.28">0.28
 <option value="0.285" selected>0.285
 <option value="0.29">0.29
 <option value="0.295">0.295
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5">0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (dX), 
<select size="1" name="jsY" id="jsY" onchange="init()">
 <option value="-1">-1
 <option value="-0.9">-0.9
 <option value="-0.8">-0.8
 <option value="-0.7">-0.7
 <option value="-0.6">-0.6
 <option value="-0.5">-0.5
 <option value="-0.4">-0.4
 <option value="-0.3">-0.3
 <option value="-0.2">-0.2
 <option value="-0.1">-0.1
 <option value="-0.09">-0.09
 <option value="-0.08">-0.08
 <option value="-0.07">-0.07
 <option value="-0.06">-0.06
 <option value="-0.05">-0.05
 <option value="-0.04">-0.04
 <option value="-0.03">-0.03
 <option value="-0.02">-0.02
 <option value="-0.01">-0.01
 <option value="0">0
 <option value="0.01" selected>0.01
 <option value="0.02">0.02
 <option value="0.03">0.03
 <option value="0.04">0.04
 <option value="0.05">0.05
 <option value="0.06">0.06
 <option value="0.07">0.07
 <option value="0.08">0.08
 <option value="0.09">0.09
 <option value="0.1">0.1
 <option value="0.2">0.2
 <option value="0.3">0.3
 <option value="0.4">0.4
 <option value="0.5">0.5
 <option value="0.6">0.6
 <option value="0.7">0.7
 <option value="0.8">0.8
 <option value="0.9">0.9
 <option value="1">1
</select> (dY) 
<input type="button" value="сброс" onclick="reloadMe()">
<input type="button" value="записать" onclick="writeMe()">
</form>
<div id="juliaResults"></div>

<script type="text/javascript">
var maxIterations; //количество итераций
var width, height, context; //размеры канвы и контекст
var minX,maxX,minY,maxY,jsX,jsY; //коэффициенты
                          //0.01
function getMapCoeffs (x, t1, t2, s1, s2) {
 var f = (x - t1) / (t2 - t1);
 var g = f * (s2 - s1) + s1;
 return g;
}

function getColor (c) {
 var r, g, b, p = c / 32,
  l = ~~( p * 6 ), o = p * 6 - l, //~~ - это двойное побитовое "не"
  q = 1 - o;
  switch( l % 6 ) {
   case 0: r = 1; g = o; b = 0; break;
   case 1: r = q; g = 1; b = 0; break;
   case 2: r = 0; g = 1; b = o; break;
   case 3: r = 0; g = q; b = 1; break;
   case 4: r = o; g = 0; b = 1; break;
   case 5: r = 1; g = 0; b = q; break;
  }
  var c = "#" + ( "00" + ( ~~( r * 255 ) ).toString( 16 ) ).slice( -2 ) + 
                ( "00" + ( ~~( g * 255 ) ).toString( 16 ) ).slice( -2 ) + 
                ( "00" + ( ~~( b * 255 ) ).toString( 16 ) ).slice( -2 );
  return (c);
}

function drawFractal() {
 var a, as, za, b, bs, zb, count, clr;
 for (var j = 0; j < height; j++) {
  for (var i = 0; i < width; i++ ) {
   a = getMapCoeffs (i, 0, width, minX, maxX);
   b = getMapCoeffs (j, 0, height, minY, maxY);
   count = 0;
   while (++count < maxIterations) {
    za = a * a; zb = b * b;
    if (za + zb > 4) break;
    as = za - zb; bs = 2 * a * b;
    a = as + jsX; b = bs + jsY;
   }
   if (count < maxIterations) {
    context.fillStyle = getColor (count);
   }
   context.fillRect (i, j, 1, 1); //рисуем точку
  }
 }
}

function init() {
 maxIterations = parseInt(document.juliaForm.maxIterations.value);
 if (maxIterations === 'undefined') maxIterations=450;
 canvasSize = parseInt(document.juliaForm.canvasSize.value);
 if (canvasSize === 'undefined') canvasSize=600;
 minX = parseFloat(document.juliaForm.minX.value);
 if (minX === 'undefined') minX=-0.5;
 maxX = parseFloat(document.juliaForm.maxX.value);
 if (maxX === 'undefined') maxX=0.5;
 minY = parseFloat(document.juliaForm.minY.value);
 if (minY === 'undefined') minY=-0.5;
 maxY = parseFloat(document.juliaForm.maxY.value);
 if (maxY === 'undefined') maxY=0.5;
 jsX = parseFloat(document.juliaForm.jsX.value);
 if (jsX === 'undefined') jsX=0.285;
 jsY = parseFloat(document.juliaForm.jsY.value);
 if (jsY === 'undefined') jsY=0.01;

 if (document.getElementById("juliaCanvas")) {
  document.body.removeChild (document.getElementById("juliaCanvas"));
 }

 var canvas = document.createElement("canvas");
 canvas.setAttribute("id", "juliaCanvas");
 width = height = canvasSize;
 canvas.width = width; canvas.height = height;
 context = canvas.getContext("2d");
 context.fillStyle = "black"; context.fillRect (0, 0, width, height);
 document.body.appendChild( canvas );
 drawFractal();
 if (document.getElementById("juliaResults").innerHTML!='') writeMe();
}

function reloadMe() {
 document.juliaForm.maxIterations.value = 450;
 document.juliaForm.canvasSize.value = 600;
 document.juliaForm.minX.value = -0.5;
 document.juliaForm.maxX.value = 0.5;
 document.juliaForm.minY.value = -0.5;
 document.juliaForm.maxY.value = 0.5;
 document.juliaForm.jsX.value = 0.285;
 document.juliaForm.jsY.value = 0.01;
 document.getElementById("juliaResults").innerHTML = '';
 init();
 return false;
}

function writeMe() {
 document.getElementById("juliaResults").innerHTML = 
  'Итераций: ' + document.juliaForm.maxIterations.value + ', ' +
  'Размер канвы: ' + document.juliaForm.canvasSize.value + ', ' +
  'Коэффициенты: ' + document.juliaForm.minX.value + ', ' +
                     document.juliaForm.maxX.value + ', ' +
                     document.juliaForm.minY.value + ', ' +
                     document.juliaForm.maxY.value + ', ' +
                     document.juliaForm.jsX.value + ', ' +
                     document.juliaForm.jsY.value;
}

init();
</script>
<noscript>Извините, требуется включённый Javascript для работы приложения!</noscript>

</div></body></html>

Место для сохранения интересных конфигураций:

Итераций: 450, Размер канвы: 600, Коэффициенты: -0.9, 0.3, -0.7, 0.9, -0.6, -0.6
Итераций: 800, Размер канвы: 800, Коэффициенты: 0.2, 0.8, -0.7, -0.5, 0.25, -0.5
Итераций: 800, Размер канвы: 800, Коэффициенты: 0.2, 0.8, 0.2, 0.8, 0.28, 0.01

12.10.2017, 14:28 [4160 просмотров]


теги: javascript графика числа математика

К этой статье пока нет комментариев, Ваш будет первым