Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Шарафиева #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions Fractal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
let Fractal = 'newtonPool';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Переменные и функции в JS называются маленькой буквы (camelCase). Исключение функции-конструкторы.

let Coloring = 'classic';
let Scale = 2;
let Field = {
left: -2,
top: -2,
right: 2,
bottom: 2
};

var resetScale = () => {
Scale = 2;
};

function updateCoordinates(left, top, right, bottom) {
Field.left = left;
Field.right = right;
Field.top = top;
Field.bottom = bottom;
}

function changeZoomLevel(canvas, e) {
var mouseCoords = canvas.relMouseCoords(e);
var x = mouseCoords.x * (Field.right - Field.left) / (canvas.width - 1) + Field.left;
var y = mouseCoords.y * (Field.bottom - Field.top) / (canvas.height - 1) + Field.top;
if (e.button === 0) {
Scale /= 1.5;
}
if (e.button === 2) {
Scale *= 1.5;
}
run(x, y, Fractal);
}

function mousePress() {
canvas.addEventListener("mousedown",
function (e) {
changeZoomLevel(canvas, e);
},
false);
}

function run(centerX, centerY, fractalType) {
if (fractalType === undefined)
fractalType = Fractal;
Fractal = fractalType;
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var left = centerX - Scale;
var top = centerY - Scale;
var right = centerX + Scale;
var bottom = centerY + Scale;
var n = parseInt(document.getElementById('n').value);
drawFractal(left, top, right, bottom, fractalType, n);
}

function putColor(x, y, color, width, imageData) {
var index = (x + y * width) * 4;
imageData.data[index + 0] = color[0];
imageData.data[index + 1] = color[1];
imageData.data[index + 2] = color[2];
imageData.data[index + 3] = color[3];
}

function drawFractal(left, top, right, bottom, fractalType, n) {
updateCoordinates(left, top, right, bottom);
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var width = canvas.width;
var height = canvas.height;

for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
var i = x * (right - left) / (width - 1) + left;
var j = y * (bottom - top) / (height - 1) + top;
var pointData = choseFractal(i, j, n, fractalType);
var color = choseColor(pointData, n);
putColor(x, y, color, width, imageData);
}
}
context.putImageData(imageData, 0, 0);
}

function choseFractal(x, y, n, fractalType) {
switch (fractalType) {
case 'newtonPool':
return getNewtonAttr(x, y, n, 0);
case 'mandelbrotSet':
return getMandelbrotAttr(x, y, n);
case 'juliaSet':
var re = parseFloat(document.getElementById('re').value);
var im = parseFloat(document.getElementById('im').value);
return getJuliaAttr(x, y, re, im, n);
}
}

function getNewtonAttr(x, y, n, itter) {
var cos = Math.cos(Math.PI / 3);
var sin = Math.sin(Math.PI / 3);

if (n === 0)
return {
attractor: 0,
itterations: itter
};
if (checkLimits(x, y, 1, 0))
return {
attractor: 1,
itterations: itter
};
if (checkLimits(x, y, -cos, sin))
return {
attractor: 2,
itterations: itter
};
if (checkLimits(x, y, -cos, -sin))
return {
attractor: 3,
itterations: itter
};
var x2 = x * x;
var y2 = y * y;
var x1 = 2 / 3 * x + (x2 - y2) / (3 * (x2 + y2) * (x2 + y2));
var y1 = 2 / 3 * y * (1 - x / ((x2 + y2) * (x2 + y2)));
return getNewtonAttr(x1, y1, n - 1, itter + 1);
}

function checkLimits(x1, y1, x2, y2) {
return Math.abs(x2 - x1) <= 0.0001 && Math.abs(y2 - y1) <= 0.0001;
}

function getMandelbrotAttr(x, y, n) {
var x0 = 0;
var y0 = 0;
var x1 = 0;
var y1 = 0;
var k = 0;
while (k < n) {
x1 = x0 * x0 - y0 * y0 + x;
y1 = 2 * x0 * y0 + y;
if (x1 * x1 + y1 * y1 > 4)
return {
itterations: k
};
x0 = x1;
y0 = y1;
k++;
}
return {
itterations: 0
};
}

function getJuliaAttr(x, y, re, im, n) {
var x0 = x;
var y0 = y;
var x1 = 0;
var y1 = 0;
var k = 0;
while (k < n) {
if (x0 * x0 + y0 * y0 > 4)
return {
itterations: k
};
x1 = x0 * x0 - y0 * y0 + re;
y1 = 2 * x0 * y0 + im;
x0 = x1;
y0 = y1;
k++;
}
return {
itterations: 0
};
}

function paintClassic(point, fractalType) {
if (fractalType === "newtonPool") {
switch (point.attractor) {
case 0:
return [0, 0, 0, 0];
case 1:
return [255, 0, 0, 255];
case 2:
return [0, 255, 0, 255];
case 3:
return [0, 0, 255, 255];
}
} else return point.itterations === 0 ? [0, 0, 0, 255] : [255, 255, 255, 255];
}

function paintLevels(n, itter) {
var brightness = n > 1 ? 255 * itter * 4 / (n - 1) : 255;
return [brightness, brightness, brightness, 255];
}

function paintZebra(itter) {
var color;
itter % 2 === 0 ? color = [0, 0, 0, 255] : color = [255, 255, 255, 255];
return color;
}

function changeColor(color) {
resetScale();
Coloring = color;
run(0, 0, Fractal);
}

function choseColor(pointData, n) {
switch (Coloring) {
case 'classic':
return paintClassic(pointData, Fractal);
case 'levels':
return paintLevels(n, pointData.itterations);
case 'zebra':
return paintZebra(pointData.itterations);
}
}
141 changes: 62 additions & 79 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,80 +1,63 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Cache-Control" content="no-cache"/>

<script>
HTMLCanvasElement.prototype.relMouseCoords = function (event) {
var totalOffsetX = 0;
var totalOffsetY = 0;
var canvasX = 0;
var canvasY = 0;
var currentElement = this;

do {
totalOffsetX += currentElement.offsetLeft;
totalOffsetY += currentElement.offsetTop;
}
while (currentElement = currentElement.offsetParent)

canvasX = event.pageX - totalOffsetX;
canvasY = event.pageY - totalOffsetY;

// Fix for variable canvas width
canvasX = Math.round( canvasX * (this.width / this.offsetWidth) );
canvasY = Math.round( canvasY * (this.height / this.offsetHeight) );

return {x:canvasX, y:canvasY}
}

//пример рисования произвольного множества точек
function example(canvas) {
var canvasHeight = parseInt(canvas.getAttribute("height"));
var canvasWidth = parseInt(canvas.getAttribute("width"));

//создаем 2d context
var context = canvas.getContext('2d');

//создаем "буфер" imageData, в который будем класть новую информацию о цветах
var imageData = context.createImageData(canvasWidth, canvasHeight);
for (var i = 0; i < canvasWidth; i++) {
for (var j = 0; j < canvasHeight; j++) {
var red = 0;
var green = 0;
var blue = (i + j) % 255;
if (i % 20 == 0)
red = 150;
if (j % 20 == 0)
green = 150;
var opacity = 255;

imageData.data[4*(i + canvasWidth*j) + 0] = red;
imageData.data[4*(i + canvasWidth*j) + 1] = green;
imageData.data[4*(i + canvasWidth*j) + 2] = blue;
imageData.data[4*(i + canvasWidth*j) + 3] = opacity;
}
}
//заполненный "буфер" imageData передаем в context для вывода на экран
context.putImageData(imageData, 0, 0);
}

function mouseDownHandler(canvas, e) {
var coords = canvas.relMouseCoords(e);
alert("x=" + coords.x + " " + "y=" + coords.y);
}

//вызывается после загрузки body
function run () {
var canvas = document.getElementById("canvas");
canvas.addEventListener("mousedown",
function(e) { mouseDownHandler(canvas, e); },
false);
example(canvas);
}
</script>

<body onload="run()">
<canvas height='200' width='200' id='canvas'></canvas>
</body>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="Fractal.js" type="text/javascript" charset="utf-8"></script>
<script>
HTMLCanvasElement.prototype.relMouseCoords = function (event) {
var moveX = 0;
var moveY = 0;
var canvasX = 0;
var canvasY = 0;
var currentElement = this;
do {
moveX += currentElement.offsetLeft;
moveY += currentElement.offsetTop;
}
while (currentElement = currentElement.offsetParent)
canvasX = event.pageX - moveX;
canvasY = event.pageY - moveY;
canvasX = Math.round(canvasX * (this.width / this.offsetWidth));
canvasY = Math.round(canvasY * (this.height / this.offsetHeight));
return {
x: canvasX,
y: canvasY
}
}
</script>
</head>
<body onload="mousePress(); run(0, 0, 'newtonPool');">
<canvas oncontextmenu="return false;" height='500' width='500' id='canvas'></canvas>
<table>
<tr>
<td colspan = "3">Тип фрактала:</td>
</tr>
<tr>
<td><button type="button" id = 'newtonPool' onclick="resetScale(); run(0, 0, 'newtonPool')">Бассейн Ньютона</button></td>
<td><button type="button" id = 'mandelbrotSet' onclick="resetScale(); resetScale(); run(0, 0, 'mandelbrotSet')">Множество Мандельброта</button></td>
<td><button type="button" id = 'juliaSet' onclick="resetScale(); run(0, 0, 'juliaSet')">Множество Жюлиа</button></td>
</tr>
<tr>
<td colspan = "3">Тип расскраски:</td>
</tr>
<tr>
<td><button type="button" id = 'classicPaint' onclick="changeColor('classic')">Классический</button></td>
<td><button type="button" id = 'levelPaint' onclick="changeColor('levels')">Уровни</button></td>
<td><button type="button" id = 'zebraPaint' onclick="changeColor('zebra')">Зебра</button></td>
</tr>
<tr>
<td colspan = "3">Характеристики множества Жюлиа:</td>
</tr>
<tr>
<td>Re: <input type ="number" id = "re" name = "re" value = "-0.12"></td>
<td>Im: <input type ="number" id = "im" name = "im" value = "0.74"></td>
</tr>
<tr>
<td colspan = "2">Максимальная итерация <input type ="number" id = "n" name = "n" value = "200"></td>
</tr>
<tr>
<td><button type="button" onclick="resetScale(); run(0, 0)">Нарисовать</button></td>
</tr>
</table>
</body>
</html>