Paproć Barnsleya: Różnice pomiędzy wersjami

[wersja nieprzejrzana][wersja przejrzana]
Usunięta treść Dodana treść
Dodałem kod źródłowy programu napisanego w P5.js. Program napisany prze ze mnie, jednakże wzorowany na istniejących kodach tutaj. Źródło mojego kodu: https://openprocessing.org/sketch/1162828
PG (dyskusja | edycje)
te wszystkie programy to sztuka dla sztuki, nic nie wnoszą do artykułu; są w internecie inne serwisy, gdzie można umieszczać tego typu twórczość
 
Linia 1:
[[Plik:Bransleys fern.png|thumb|150px|Paproć Barnsley’aBarnsleya]]
[[Plik:Fractal fern1.png|thumb|150px|Paproć Barnsley’aBarnsleya]]
[[Plik:Fractal fern explained.png|thumb|150px|Przekształcenia [[IFS (geometria fraktalna)|IFS]]]]
 
Linia 13:
 
== Algorytm ==
[[Algorytm]] generowania tego fraktala polega na procesie [[iteracja|iteracji]] (wielokrotnego przekształcania) współrzędnych rysowanego punktu. Początkowo losowo wybieramywybiera się współrzędne punktu, a następnie również losowo wybieramywybiera się jedno z przekształceń afinicznych z odpowiednim [[prawdopodobieństwo|prawdopodobieństwem]]. Po obliczeniu nowych współrzędnych punktu, proces powtarzamypowtarza się określoną ilośćliczbę razy.
 
== PrzykładowePrzykładowy programy (Matlab) ==
[[Plik:Fractal fern-Barnsley animation.gif|thumb|300px|Animacja przedstawiająca paproć Barnsley’aBarnsleya dla różnej liczby powtórzeń algorytmu IFS.]]
 
=== Matlab ===
Program napisany w [[Matlab]]ie generujący paproć widoczną na animacji obok:
 
Linia 46 ⟶ 45:
pause(0.5)
end
</syntaxhighlight>
 
=== Python ===
Program napisany w [[Python|Pythonie]]:
 
<syntaxhighlight lang="python">
 
import random
import matplotlib.pyplot as plt
 
X = [0]
Y = [0]
for n in range(100000):
r = random.uniform(0, 100)
if r < 1.0:
x = 0
y = 0.16*Y[n-1]
elif r < 86.0:
x = 0.85*X[n-1] + 0.04*Y[n-1]
y = -0.04*X[n-1] + 0.85*Y[n-1]+1.6
elif r < 93.0:
x = 0.2*X[n-1] - 0.26*Y[n-1]
y = 0.23*X[n-1] + 0.22*Y[n-1] + 1.6
else:
x = -0.15*X[n-1] + 0.28*Y[n-1]
y = 0.26*X[n-1] + 0.24*Y[n-1] + 0.44
X.append(x);Y.append(y)
 
'''Tworzenie wykresu'''
plt.figure(figsize = [15,15])
plt.scatter(X,Y,color = 'g',marker = '.')
plt.show()
</syntaxhighlight>
 
=== JavaScript (HTML5) ===
Program napisany w [[JavaScript]] (HTML5):
 
<syntaxhighlight lang="html5">
<canvas id="canvas" height="700" width="700">
</canvas>
 
<script>
let canvas;
let canvasContext;
 
let move;
 
let fps = 250;
 
let pointColor = "green";
let backgroundColor = "black";
let pointRadius = 1;
 
let x = 0;
let y = 0;
 
window.onload = function () {
canvas = document.getElementById("canvas");
canvasContext = canvas.getContext('2d');
 
canvasContext.fillStyle = backgroundColor;
canvasContext.fillRect(0, 0, canvas.width, canvas.height);
 
move = setInterval(doIt, 1000/fps);
};
 
let doIt = function () {
for (let i = 0; i < 20; i++)
moveAll()
};
 
function moveAll() {
 
let nextX, nextY;
let r = Math.random();
if (r < 0.01) {
nextX = 0;
nextY = 0.16 * y;
} else if (r < 0.86) {
nextX = 0.85 * x + 0.04 * y;
nextY = -0.04 * x + 0.85 * y + 1.6;
} else if (r < 0.93) {
nextX = 0.20 * x - 0.26 * y;
nextY = 0.23 * x + 0.22 * y + 1.6;
} else {
nextX = -0.15 * x + 0.28 * y;
nextY = 0.26 * x + 0.24 * y + 0.44;
}
 
// Skalowanie i pozycjonowanie
let plotX = canvas.width * (x + 3) / 6;
let plotY = canvas.height - canvas.height * ((y + 2) / 14);
 
drawFilledCircle(plotX, plotY, pointRadius, pointColor);
 
x = nextX;
y = nextY;
 
}
const drawFilledCircle = (centerX, centerY, radius, color) => {
canvasContext.beginPath();
canvasContext.fillStyle = color;
canvasContext.arc(centerX, centerY, radius, 0, 2 * Math.PI, true);
canvasContext.fill();
};
</script>
</syntaxhighlight>
 
=== QBasic ===
Programy napisany w [[QBasic]]:
 
<syntaxhighlight lang="qbasic">
SCREEN 12
WINDOW (-5, 0)-(5, 10)
RANDOMIZE TIMER
COLOR 10
DO
SELECT CASE RND
CASE IS < .01
nextX = 0
nextY = .16 * y
CASE .01 TO .08
nextX = .2 * x - .26 * y
nextY = .23 * x + .22 * y + 1.6
CASE .08 TO .15
nextX = -.15 * x + .28 * y
nextY = -.26 * x + .24 * y + .44
CASE ELSE
nextX = .85 * x + .04 * y
nextY = -.04 * x + .85 * y + 1.6
END SELECT
x = nextX
y = nextY
PSET (x, y)
LOOP UNTIL INKEY$ = CHR$(27)
</syntaxhighlight>
 
=== R ===
Program napisany w języku [[R (język programowania)|R]]:
 
<syntaxhighlight lang="R">
# Paproć Barnsley'a
 
# Utworzenie funkcji z rachunkiem prawdopodobieństwa i obecnym punktem
fractal_fern2 <- function(x, p){
if (p <= 0.01) {
m <- matrix(c(0, 0, 0, .16), 2, 2)
f <- c(0, 0)
} else if (p <= 0.86) {
m <- matrix(c(.85, -.04, .04, .85), 2, 2)
f <- c(0, 1.6)
} else if (p <= 0.93) {
m <- matrix(c(.2, .23, -.26, .22), 2, 2)
f <- c(0, 1.6)
} else {
m <- matrix(c(-.15, .26, .28, .24), 2, 2)
f <- c(0, .44)
}
m %*% x + f
}
 
# liczba powtórzeń; im większa, tym bardziej dokładny efekt końcowy
reps <- 10000
 
# stworzenie wektora z wartościami prawdopodobieństwa oraz macierzy do przechowywania współrzędnych
p <- runif(reps)
 
# zainicjalizowanie punktu początkowego w początku układu współrzędnych
coords <- c(0, 0)
 
# obliczanie współrzędnych fraktalu
m <- Reduce(fractal_fern2, p, accumulate = T, init = coords)
m <- t(do.call(cbind, m))
 
# stworzenie wykresu
plot(m, type = "p", cex = 0.1, col = "darkgreen",
xlim = c(-3, 3), ylim = c(0, 10),
xlab = NA, ylab = NA, axes = FALSE)
</syntaxhighlight>
 
=== Processing ===
Program napisany w [[Processing]] (wersja 3.4):
 
<syntaxhighlight lang="java">
 
// deklarowanie zmiennych x i y
float x, y;
 
// stworzenie planszy
void setup() {
size(600, 600);
background(255);
}
 
/* ustawianie wyglądu punktów, mapowanie planszy i następnie rysowanie punktów */
void drawPoint() {
stroke(34, 139, 34);
strokeWeight(1);
float px = map(x, -2.1820, 2.6558, 0, width);
float py = map(y, 0, 9.9983, height, 0);
point(px, py);
}
 
/* algorytm na obliczanie (n+1)ego
wyrazu x i y bazujący na przekształceniu macierzy */
void nextPoint() {
float nextX, nextY;
float r = random(1);
if (r < 0.01) {
nextX = 0;
nextY = 0.16 * y;
} else if (r < 0.86) {
nextX = 0.85 * x + 0.04 * y;
nextY = -0.04 * x + 0.85 * y + 1.6;
} else if (r < 0.93) {
nextX = 0.20 * x - 0.26 * y;
nextY = 0.23 * x + 0.22 * y + 1.6;
} else {
nextX = -0.15 * x + 0.28 * y;
nextY = 0.26 * x + 0.24 * y + 0.44;
}
x = nextX;
y = nextY;
}
 
/* iteracja w pętli funkcji obliczających i rysujących */
void draw() {
for (int i = 0; i < 100; i++) {
drawPoint();
nextPoint();
}
}
</syntaxhighlight>
 
=== SmallBasic ===
Program napisany w języku SmallBasic<syntaxhighlight lang="s" start="1">
x = 1
y = 1
skala = 40 'skala rysunku
zeroxdo = 300 'przesunięcie początku układu współrzędnych
zeroydo = 200
For n = 1 to 100000
r = Math.GetRandomNumber(100001)/100000
If r <= 0.01 Then
xn = 0
yn = 0.16*y
Elseif r <= 0.08 then
xn = 0.2*x - 0.26*y
yn= 0.23*x + 0.22*y + 1.6
Elseif r <= 0.15 then
xn = -0.15*x + 0.28*y
yn = 0.26*x + 0.24*y + 0.44
Else
xn = 0.85*x + 0.04*y
yn= -0.04*x + 0.85*y + 1.6
EndIf
xe = x*skala+zeroxdo 'punkt na ekranie
ye = y*skala+zeroydo 'punkt na ekranie
GraphicsWindow.SetPixel(xe,630-ye,"red")
x = xn
y = yn
EndFor
</syntaxhighlight>'''P5.js'''
 
Program napisany w języku P5.js<syntaxhighlight line="1">
function setup() {
createCanvas(windowWidth, windowHeight);
background(255);
}
 
let x = '', y = '', px = '', py = '';
 
 
function drawPoint()
{
stroke(34,139,34);
strokeWeight(1);
px = map(x, -2.182, 2.6558, 0, width);
py = map(y, 0, 9.983, height, 0);
point(px, py);
}
 
function nextPoint()
{
let nextX, nextY, r = random(1);
if (r < 0.01) {
nextX = 0;
nextY = 0.16 * y;
} else if (r < 0.86) {
nextX = 0.85 * x + 0.04 * y;
nextY = -0.04 * x + 0.85 * y + 1.6;
} else if (r < 0.93) {
nextX = 0.20 * x - 0.26 * y;
nextY = 0.23 * x + 0.22 * y + 1.6;
} else {
nextX = -0.15 * x + 0.28 * y;
nextY = 0.26 * x + 0.24 * y + 0.44;
}
x = nextX;
y = nextY;
}
 
function draw()
{
drawPoint();
nextPoint();
loop(100);
}
</syntaxhighlight>