parent
d6cd29f2fc
commit
e8b8114014
@ -1 +1 @@
|
|||||||
((nil . ((projectile-project-install-cmd . "mvn -B clean compile assembly:single && java -jar target/*.jar"))))
|
((nil . ((projectile-project-compilation-cmd . "mvn -B clean compile assembly:single && java -jar target/*.jar"))))
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
package edu.thi.phga.aparapi_test;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
|
||||||
|
import com.aparapi.Range;
|
||||||
|
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.geometry.Rectangle2D;
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.image.PixelFormat;
|
||||||
|
import javafx.scene.image.PixelReader;
|
||||||
|
import javafx.scene.image.PixelWriter;
|
||||||
|
import javafx.scene.image.WritableImage;
|
||||||
|
import javafx.scene.image.WritablePixelFormat;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.stage.Screen;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class Mandelbrot extends Application{
|
||||||
|
private static Rectangle2D bounds = Screen.getPrimary().getBounds();
|
||||||
|
private static final int BREITE = (int) (bounds.getWidth() * 0.8);
|
||||||
|
private static final int HOEHE = BREITE * 9 / 16;
|
||||||
|
|
||||||
|
private double[] farbe = new double[BREITE * HOEHE];
|
||||||
|
private double[] saturation = new double[BREITE * HOEHE];
|
||||||
|
|
||||||
|
private MandelbrotKernel k = new MandelbrotKernel(farbe, saturation);
|
||||||
|
private Range r;
|
||||||
|
|
||||||
|
// (x1, y1) = links oben, (x2, y2) = rechts unten
|
||||||
|
private double x1 = -3.0;
|
||||||
|
private double x2 = 1.8;
|
||||||
|
private double y1 = (x2 - x1) * HOEHE / BREITE / 2;
|
||||||
|
private double y2 = -y1;
|
||||||
|
|
||||||
|
// Wie scharf ist das Bild (Ab wann sagen wir |Z_n| <= 2 für alle Z_n)
|
||||||
|
private int maxIter = 200;
|
||||||
|
private int exponent = 0;
|
||||||
|
|
||||||
|
private WritableImage image = new WritableImage(BREITE, HOEHE);
|
||||||
|
private WritablePixelFormat<java.nio.ByteBuffer> format = PixelFormat.getByteBgraPreInstance();
|
||||||
|
|
||||||
|
private PixelWriter pw = image.getPixelWriter();
|
||||||
|
private PixelReader pr = image.getPixelReader();
|
||||||
|
|
||||||
|
private Deque<byte[]> imageStack = new ArrayDeque<>();
|
||||||
|
private Deque<double[]> frameStack = new ArrayDeque<>();
|
||||||
|
|
||||||
|
private Stage stage;
|
||||||
|
|
||||||
|
private void zeichne() {
|
||||||
|
stage.setTitle("KAO: Computing...");
|
||||||
|
|
||||||
|
k.setParameters(x1, y1, x2, y2, maxIter);
|
||||||
|
k.execute(r);
|
||||||
|
|
||||||
|
for (int i = 0; i < farbe.length; i++) {
|
||||||
|
Color c = Color.hsb(farbe[i], saturation[i], 0.5);
|
||||||
|
pw.setColor(i % BREITE, i / BREITE, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTitle() {
|
||||||
|
stage.setTitle(String.format("KAO: Mandelbrot (Zoom: %d^%d, n = %d)",
|
||||||
|
App.multiParam, exponent, maxIter));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zoomIn(MouseEvent e) {
|
||||||
|
byte[] buffer = new byte[4 * BREITE * HOEHE];
|
||||||
|
pr.getPixels(0, 0, BREITE, HOEHE, format, buffer, 0, 4 * BREITE);
|
||||||
|
imageStack.push(buffer);
|
||||||
|
frameStack.push(new double[] { x1, y1, x2, y2 });
|
||||||
|
|
||||||
|
double x = x1 + (x2 - x1) * e.getX() / BREITE;
|
||||||
|
double y = y1 + (y2 - y1) * e.getY() / HOEHE;
|
||||||
|
|
||||||
|
double dx = (x2 - x1) / App.multiParam / 2;
|
||||||
|
double dy = (y2 - y1) / App.multiParam / 2;
|
||||||
|
|
||||||
|
x1 = x - dx;
|
||||||
|
x2 = x + dx;
|
||||||
|
y1 = y - dy;
|
||||||
|
y2 = y + dy;
|
||||||
|
|
||||||
|
maxIter *= 2;
|
||||||
|
exponent++;
|
||||||
|
|
||||||
|
zeichne();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zoomOut(KeyEvent e) {
|
||||||
|
String key = e.getText();
|
||||||
|
System.out.println("Key: " + key);
|
||||||
|
if (key.equals("q") && !imageStack.isEmpty()) {
|
||||||
|
double[] frame = frameStack.pop();
|
||||||
|
x1 = frame[0];
|
||||||
|
y1 = frame[1];
|
||||||
|
x2 = frame[2];
|
||||||
|
y2 = frame[3];
|
||||||
|
|
||||||
|
maxIter /= 2;
|
||||||
|
|
||||||
|
pw.setPixels(0, 0, BREITE, HOEHE, format, imageStack.pop(), 0, 4 * BREITE);
|
||||||
|
|
||||||
|
setTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage stage) {
|
||||||
|
// Set range
|
||||||
|
int maxWGSize = 16;
|
||||||
|
System.out.println("Using WGSize: " + maxWGSize);
|
||||||
|
|
||||||
|
r = Range.create2D(App.device, BREITE, HOEHE, maxWGSize, maxWGSize);
|
||||||
|
|
||||||
|
this.stage = stage;
|
||||||
|
ImageView view = new ImageView(image);
|
||||||
|
view.setFocusTraversable(true);
|
||||||
|
view.setOnMousePressed(this::zoomIn);
|
||||||
|
view.setOnKeyPressed(this::zoomOut);
|
||||||
|
|
||||||
|
zeichne();
|
||||||
|
|
||||||
|
stage.setScene(new Scene(new Group(view)));
|
||||||
|
stage.setResizable(false);
|
||||||
|
stage.sizeToScene();
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
package edu.thi.phga.aparapi_test;
|
||||||
|
|
||||||
|
import com.aparapi.Kernel;
|
||||||
|
|
||||||
|
public class MandelbrotKernel extends Kernel {
|
||||||
|
private double[] farbe;
|
||||||
|
private double[] saturation;
|
||||||
|
private double x1, x2, y1, y2;
|
||||||
|
private int maxIter;
|
||||||
|
|
||||||
|
public MandelbrotKernel(double[] farbe, double[] saturation) {
|
||||||
|
this.farbe = farbe;
|
||||||
|
this.saturation = saturation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameters(double x1, double y1, double x2, double y2, int maxIter) {
|
||||||
|
this.x1 = x1;
|
||||||
|
this.y1 = y1;
|
||||||
|
|
||||||
|
this.x2 = x2;
|
||||||
|
this.y2 = y2;
|
||||||
|
|
||||||
|
this.maxIter = maxIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formel:
|
||||||
|
// z_n = { 0, n=0
|
||||||
|
// z_(n-1)^2 + c, n>0
|
||||||
|
// c element von C (Complex)
|
||||||
|
// Bei uns ist c dann ein Pixel den wir einfärben
|
||||||
|
// bzw. der Punkt(x, y) (offset) für eine bestimmte Zahl der Mandelbrot Menge
|
||||||
|
// Schwarz == ist Teil der Menge (|z_k| <= 2)
|
||||||
|
// Farbe == sonst (|z_k| > 2) (Frühzeitiger Schleifenabbruch)
|
||||||
|
// Alle z_n beginnen bei 0
|
||||||
|
// Iter 1: z = 0^2 + c
|
||||||
|
// Iter 2: z = c^2 + c
|
||||||
|
// Iter 3: z = (c^2 + c)^2 + c
|
||||||
|
// ...
|
||||||
|
// Abbruch: |z| > 2 || Iter == maxIter (200)
|
||||||
|
|
||||||
|
// @Override public void run() {
|
||||||
|
// int b = getGlobalId(0); // horizontaler Index
|
||||||
|
// int h = getGlobalId(1); // vertikaler Index
|
||||||
|
|
||||||
|
// double cx = x1 + (x2 - x1) * b / getGlobalSize(0);
|
||||||
|
// double cy = y1 + (y2 - y1) * h / getGlobalSize(1);
|
||||||
|
|
||||||
|
// double x = cx , y = cy;
|
||||||
|
// double xx = x * x, yy = y * y;
|
||||||
|
|
||||||
|
// int i;
|
||||||
|
|
||||||
|
// for (i = 1; xx + yy < 4 && i <= maxIter; i++) {
|
||||||
|
// y = 2 * x * y + cy;
|
||||||
|
// x = xx - yy + cx;
|
||||||
|
// yy = y * y;
|
||||||
|
// xx = x * x;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int idx = h * getGlobalSize(0) + b;
|
||||||
|
// farbe[idx] = log(i) * 360;
|
||||||
|
// helligkeit[idx] = i < maxIter ? 1 : 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int x = getGlobalId(0);
|
||||||
|
int y = getGlobalId(1);
|
||||||
|
|
||||||
|
int sizeX = getGlobalSize(0);
|
||||||
|
int sizeY = getGlobalSize(1);
|
||||||
|
double imageSizeX = x2 - x1;
|
||||||
|
double imageSizeY = y2 - y1;
|
||||||
|
|
||||||
|
// Skalierung
|
||||||
|
double cR = x1 + imageSizeX * x / sizeX;
|
||||||
|
double cI = y1 + imageSizeY * y / sizeY;
|
||||||
|
|
||||||
|
double zR = cR;
|
||||||
|
double zI = cI;
|
||||||
|
double zRQ = zR * zR;
|
||||||
|
double zIQ = zI * zI;
|
||||||
|
double zAbs = zIQ + zRQ;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 1; i <= maxIter && zAbs < 4; i++) {
|
||||||
|
// WICHTIG REIHENFOLGE!!! zR wird überschrieben...
|
||||||
|
zI = 2 * zR * zI + cI; // 2 * xyi + c_imag
|
||||||
|
zR = zRQ - zIQ + cR; // x^2 - y^2 + c_real
|
||||||
|
|
||||||
|
zIQ = zI * zI;
|
||||||
|
zRQ = zR * zR;
|
||||||
|
zAbs = zIQ + zRQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = y * sizeX + x;
|
||||||
|
if (i < maxIter) {
|
||||||
|
saturation[index] = min(i * log(i) / maxIter + 0.2, 1);
|
||||||
|
farbe[index] = log(i) * 360;
|
||||||
|
} else {
|
||||||
|
saturation[index] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// z = z*z + c
|
||||||
|
// z^2 = (z_r + z_i*i) * (z_r + z_i*i)
|
||||||
|
// = (z_r * z_r) + (z_r * z_i*i + z_r * z_i * i) - (z_i * z_i) <- [i^2 = -1]
|
||||||
|
// = z_r^2 + 2*z_r*z_i*i - z_i^2
|
||||||
|
// = z_r^2 - z_i^2 + 2*i*z_r*z_i
|
||||||
|
// = x^2 - y^2 + 2xyi
|
||||||
|
// real + imag
|
||||||
|
|
||||||
|
// Nette Entdeckung :) #LaserShow WUBWUBWUBWUB
|
||||||
|
// @Override
|
||||||
|
// public void run() {
|
||||||
|
// int sizeX = getGlobalSize(0);
|
||||||
|
// int sizeY = getGlobalSize(1);
|
||||||
|
// double imageSizeX = (x2 - x1);
|
||||||
|
// double imageSizeY = (y2 - y1);
|
||||||
|
// int x = getGlobalId(0);
|
||||||
|
// int y = getGlobalId(1);
|
||||||
|
// double c_r = x + imageSizeX / sizeX;
|
||||||
|
// double c_i = y + imageSizeY / sizeY;
|
||||||
|
// double z_r = 0; // komplexe zahl
|
||||||
|
// double z_i = 0;
|
||||||
|
// double zb = 0;
|
||||||
|
|
||||||
|
// for (int i = 0; i < 200 && zb <= 4; i++) {
|
||||||
|
// // z = z*z + c
|
||||||
|
// // z^2
|
||||||
|
// z_r = z_r * z_r - z_i * z_i;
|
||||||
|
// z_i = z_r * z_i + z_r * z_i;
|
||||||
|
|
||||||
|
// // z + c;
|
||||||
|
// z_r += c_r;
|
||||||
|
// z_i += c_i;
|
||||||
|
|
||||||
|
// // sqrt(z_r^2 + z_i^2)
|
||||||
|
// zb = sqrt(z_r * z_r + z_i * z_i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (zb <= 4) {
|
||||||
|
// helligkeit[x + x * y] = 0;
|
||||||
|
// } else {
|
||||||
|
// helligkeit[x + x * y] = 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package edu.thi.phga.aparapi_test;
|
||||||
|
|
||||||
|
import com.aparapi.Kernel;
|
||||||
|
|
||||||
|
public class RauschfilterKernel extends Kernel {
|
||||||
|
private float[] noisy;
|
||||||
|
private float[] clean;
|
||||||
|
private int len;
|
||||||
|
RauschfilterKernel(float[] noisy, float[] clean, int len) {
|
||||||
|
this.noisy = noisy;
|
||||||
|
this.clean = clean;
|
||||||
|
this.len = len;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// y_i = 1/N(x_-N/2 + x_-N/2+1 + ... + x_-1 + x_0 + x_1 + ... + x_N/2-1 + x_N/2)
|
||||||
|
int i = getGlobalId();
|
||||||
|
float sum = 0;
|
||||||
|
|
||||||
|
for (int n = 1; n <= len; n++) {
|
||||||
|
// To the right of x
|
||||||
|
if (i + n < noisy.length) {
|
||||||
|
sum += noisy[i + n];
|
||||||
|
}
|
||||||
|
// To the left of x
|
||||||
|
if (i - n >= 0) {
|
||||||
|
sum += noisy[i - n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write into clean
|
||||||
|
clean[i] = (sum + noisy[i]) / len;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
open module edu.thi.phga.aparapi_test {
|
|
||||||
requires javafx.controls;
|
|
||||||
requires aparapi;
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
// open module edu.thi.phga.aparapi_test {
|
||||||
|
// requires aparapi;
|
||||||
|
// requires javafx.controls;
|
||||||
|
// }
|
Loading…
Reference in new issue