Комментарии 16
Класс. Еще интересные фракталы получаются при вероятностном выборе афинных преобразований. Самый известный лист Папоротника. https://www.kv.by/archive/index2002491201.htm
В целом же фракталы интересны тем, что с их помощью можно обьяснять теорему о неполноте Геделя, и проблему остановки Тьюринга. Ну и как пример математического Платонизма тоже.
В целом же фракталы интересны тем, что с их помощью можно обьяснять теорему о неполноте Геделя, и проблему остановки Тьюринга. Ну и как пример математического Платонизма тоже.
фракталы интересны тем, что с их помощью можно обьяснять теорему о неполноте Геделя
Интересно! А как?
Чтобы не писать долго, отошлю к Пенроузу, он достаточно подробно это рассмотрел. Граница рекурсивно нумеруемых множеств. Там немного читать.
http://www.rulit.me/books/novyj-um-korolya-o-kompyuterah-myshlenii-i-zakonah-fiziki-read-362086-80.html
http://www.rulit.me/books/novyj-um-korolya-o-kompyuterah-myshlenii-i-zakonah-fiziki-read-362086-80.html
Было время, баловался с таким, но это было до того, как я наткнулся на генетические алгоритмы — где-то в 2006м. С тех пор успел запустить собственные :)
Разбавьте текстурками и фантазией: fractal-orgy-is-the-first-ever-raw-fractal-to-be-banned + youtube
Вот за что я люблю математичку! (с)
большой проект эволюционирующих фракталов, где пользователь является фактором естественного отбора — Electric Sheep.
Если поискать, у них очень занятные генеалогические деревья есть.
Если поискать, у них очень занятные генеалогические деревья есть.
Вот ещё предложение по улучшению трёхмерной визуализации: сглаженные пиксели и интенсивность, зависящая от глубины.
<script></script>
<script>
var canvas;
var canvasData;
var context;
var massiv;
var angls=[[45,180],[-45,90],[-45,90],[45,180]];
function createRequestObject() {
if (typeof XMLHttpRequest === 'undefined') {
XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch(e) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}
return new XMLHttpRequest();
}
function selecter(num){
req = new XMLHttpRequest();
if (req) {
req.open("POST", '/geom3d/', true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.onreadystatechange = processReqChange;
var postmyplease="num="+num;
req.send(postmyplease);
}
}
function processReqChange(){
try {
if (req.readyState == 4) {
if (req.status == 200) {
var ang=JSON.parse(req.responseText);
angls=ang.response;
massiv=sfera(angls);
droveLines(canvas, 0, 0, massiv);
var logger=document.getElementById('logger');
logger.innerHTML=" <br />";
var link="";
for (i=0, len=angls.length; i<len; i++) {
//logger.innerHTML += "("+angls[i][0]+", "+angls[i][1]+") <br />";
link+=angls[i][0]+"/"+angls[i][1]+"/";
}
logger.innerHTML="<a href=\"http://fractal.xcont.com/geom3d/"+link+"\">"+link+"</a>";
} else {
alert("Не удалось получить данные:\n" + req.statusText);
}
}
}
catch( e ) {}
}
function rotate(v, p, cos, sin, mcos){
var x=v[0], y=v[1], z=v[2]; // вектор, вокруг которого вращаем
var xp=p[0], yp=p[1], zp=p[2]; // точка, которую вращаем
var a11=(mcos*x*x+cos), a12=(mcos*x*y-sin*z), a13=(mcos*x*z+sin*y); // матрица поворота вокруг вектора
var a21=(mcos*x*y+sin*z), a22=(mcos*y*y+cos), a23=(mcos*z*y-sin*x);
var a31=(mcos*x*z-sin*y), a32=(mcos*z*y+sin*x), a33=(mcos*z*z+cos);
var xx=xp*a11+yp*a12+zp*a13; // умножаем точку на матрицу
var yy=xp*a21+yp*a22+zp*a23;
var zz=xp*a31+yp*a32+zp*a33;
return [xx, yy, zz];
}
function find_point(a, b, c, angls){
var alfa=angls[0]*Math.PI/180, betta=angls[1]*Math.PI/180;
var x1=a[0], y1=a[1], z1=a[2]; //A
var x2=b[0], y2=b[1]; z2=b[2]; //B - ось вращения AB
var x3=c[0], y3=c[1], z3=c[2]; //C - третья точка нужна для задания плоскости
var xa=x2-x1, ya=y2-y1, za=z2-z1; // вектор AB
var xc=x3-x1, yc=y3-y1, zc=z3-z1; // вектор AC
var xv=(ya*zc-za*yc), yv=-(xa*zc-za*xc), zv=(xa*yc-ya*xc); // векторное произведение векторов AB и AC (получаем вектор-перпиндикуляр к плоскости)
var cosa=Math.cos(alfa); // всю тригонометрию из матрицы поворота считаем заранее (оптимизация)
var sina=Math.sin(alfa);
var mcosa=1-Math.cos(alfa);
var cosb=Math.cos(betta);
var sinb=Math.sin(betta);
var mcosb=1-Math.cos(betta);
var r=Math.sqrt(Math.pow(xv,2)+Math.pow(yv,2)+Math.pow(zv,2)); // длина вектора-перпиндикуляра
var vector=[xv/r, yv/r, zv/r]; // нормированный вектор
var point=[xa, ya, za]; // вокруг вектора-перпендикуляра делаем поворот точки A на угол alfa
var d=rotate(vector, point, cosa, sina, mcosa); // точка после поворота
r=Math.sqrt(Math.pow(xa,2)+Math.pow(ya,2)+Math.pow(za,2)); // длина вектора AB
vector=[xa/r, ya/r, za/r]; // нормированный вектор
point=[d[0]*Math.cos(alfa),d[1]*Math.cos(alfa),d[2]*Math.cos(alfa)]; // угол ADC=90°
d=rotate(vector, point, cosb, sinb, mcosb); // вращаем точку D вокруг AB
d=[d[0]+x1, d[1]+y1, d[2]+z1]; // сдвигаем точку D
return d;
}
function recurs(array, n, a, b, d, angls){
if (n==0){
return array;
}else{
if (!array[0][n]) array[0][n]=0;
var d=find_point(a, b, d, angls[array[0][n]]);
array[1].push(d);
array[0][n]++;
if (array[0][n]==angls.length) array[0][n]=0;
recurs(array, n-1, a, d, b, angls);
recurs(array, n-1, d, b, a, angls);
return array;
}
}
function sfera(angls){
var massiv=new Array();
var x1=0; y1=10; z1=0;
var x2=0; y2=-10; z2=0;
var x3=0; y3=0; z3=-10;
massiv[0]=[x1, y1, z1];
massiv[1]=[x2, y2, z2];
massiv[2]=[x3, y3, z3];
var d=find_point(massiv[0], massiv[1], massiv[2], [angls[0][0], 0]);
massiv[2]=d;
var m1=new Array();
var m2=new Array();
var array=[m1,m2];
d=recurs(array, 15, massiv[0], massiv[1], massiv[2], angls);
massiv = massiv.concat(d[1]);
return massiv;
}
window.onload=function(){
canvas=document.getElementById('myCanvas');
context=canvas.getContext('2d');
canvas.width=600;
canvas.height=600;
canvasData=context.getImageData(0, 0, canvas.width, canvas.height);
massiv=sfera(angls);
droveLines(canvas, 0, 0, massiv);
canvas.addEventListener('mousemove', function(evt){
var mousePos=getMousePos(canvas, evt);
droveLines(canvas, mousePos.x, mousePos.y, massiv);
}, false);
function getMousePos(canvas, evt){
var obj=canvas;
var top=0;
var left=0;
while (obj && obj.tagName != 'BODY') {
top+=obj.offsetTop;
left+=obj.offsetLeft;
obj=obj.offsetParent;
}
var mouseX=evt.clientX-left+window.pageXOffset;
var mouseY=evt.clientY-top+window.pageYOffset;
return {
x: mouseX,
y: mouseY
};
}
}
function droveLines(canvas, xMouse, yMouse, massiv){
clearCanvas();
var xCenter=canvas.width/2;
var yCenter=canvas.height/2;
var focus=800;
var i, x, y, z, xx, yy, zz;
var arr=new Array();
var arr2=new Array();
var alfa=yMouse*Math.PI/180;
var betta=xMouse*Math.PI/180;
var cosa=Math.cos(alfa);
var cosb=Math.cos(betta);
var sina=Math.sin(alfa);
var sinb=Math.sin(betta);
for (i=0, len=massiv.length; i<len; i++) {
x=massiv[i][0];
y=massiv[i][1];
z=massiv[i][2];
yy=y*cosa-z*sina;
zz=z*cosa+y*sina;
z=zz;
xx=x*cosb+z*sinb;
zz=z*cosb-x*sinb;
y=yy; x=xx; z=zz;
z+=64;
xx=focus*x/z+xCenter;
yy=focus*y/z+yCenter;
var fade = Math.max(Math.min(0.8 - z / 100.0, 1.0), 0.0);
fade = (fade * fade + fade) * 0.5;
drawPixel(xx, yy, 450 * fade, 370 * fade, 150 * fade);
}
updateCanvas();
}
function drawPixel(x, y, r, g, b) {
var ix = Math.floor(x);
var iy = Math.floor(y);
var dx = x - ix;
var dy = y - iy;
var v00 = (1.0 - dx) * (1.0 - dy);
var v10 = dx * (1.0 - dy);
var v01 = (1.0 - dx) * dy;
var v11 = dx * dy;
var index = (ix + iy * canvas.width) * 4;
var d = canvasData.data;
index = Math.max(Math.min(index, d.length - canvas.width * 4 - 4), 0);
d[index + 0] = Math.min(d[index + 0] + r * v00, 255);
d[index + 1] = Math.min(d[index + 1] + g * v00, 255);
d[index + 2] = Math.min(d[index + 2] + b * v00, 255);
d[index + 3] = 255;
d[index + 4] = Math.min(d[index + 4] + r * v10, 255);
d[index + 5] = Math.min(d[index + 5] + g * v10, 255);
d[index + 6] = Math.min(d[index + 6] + b * v10, 255);
d[index + 7] = 255;
index += canvas.width * 4;
d[index + 0] = Math.min(d[index + 0] + r * v01, 255);
d[index + 1] = Math.min(d[index + 1] + g * v01, 255);
d[index + 2] = Math.min(d[index + 2] + b * v01, 255);
d[index + 3] = 255;
d[index + 4] = Math.min(d[index + 4] + r * v11, 255);
d[index + 5] = Math.min(d[index + 5] + g * v11, 255);
d[index + 6] = Math.min(d[index + 6] + b * v11, 255);
d[index + 7] = 255;
}
function updateCanvas() {
context.putImageData(canvasData, 0, 0);
}
function clearCanvas() {
for (var i=0; i<canvasData.data.length; i+=4){
canvasData.data[i]=0;
canvasData.data[i+1]=0;
canvasData.data[i+2]=0;
canvasData.data[i+3]=255;
}
context.putImageData(canvasData, 0, 0);
}
</script>
Увидел от имбриона до саламандра
Чтобы устранить из алгоритма человека можно в качестве fitness использовать какую-нибудь картинку. Того же дракона, например. Тогда можно реально картинки превращать во фракталы.
Хорошая работа. Очень круто. Согласен, 3D всегда лучше. Будут еще аналогичные статьи?
Тоже в универе рисовал фракталы, только с использованием систем итерированных функций (СИФ). Написал программу, позволяющую пользователю интерактивно менять параметры СИФ и сразу видеть полученный фрактал
Очень интересная статья!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Эволюция фрактальных монстров