From a15d410449d96b91121768acc3a491ab68fda761 Mon Sep 17 00:00:00 2001 From: Sebastian Rieger Date: Wed, 8 Nov 2017 00:16:53 +0100 Subject: [PATCH] Initial RMI Version of Mandelbrot App --- .../mandelbrot/rmi/MGuiRMI.java | 285 ++++++++++++++++++ .../RMIMandelbrotCalculationsInterface.java | 14 + .../rmi/RMIMandelbrotCalculationsServer.java | 130 ++++++++ 3 files changed, 429 insertions(+) create mode 100644 VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/MGuiRMI.java create mode 100644 VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsInterface.java create mode 100644 VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsServer.java diff --git a/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/MGuiRMI.java b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/MGuiRMI.java new file mode 100644 index 0000000..03df54c --- /dev/null +++ b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/MGuiRMI.java @@ -0,0 +1,285 @@ +package verteiltesysteme.mandelbrot.rmi; + +//Mandelbot Example A. Gepperth + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import java.awt.image.BufferedImage; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +class MyJLabel extends JLabel { + + /** + * + */ + private static final long serialVersionUID = -7750935382747799343L; + + int boxULx, boxULy, boxW, boxH; + + MyJLabel() { + super(); + } + + MyJLabel(String s) { + super(s); + } + + void setBox(int boxULx, int boxULy, int boxW, int boxH) { + this.boxULx = boxULx; + this.boxULy = boxULy; + this.boxW = boxW; + this.boxH = boxH; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(Color.black); + g.drawRect(this.boxULx, this.boxULy, this.boxW, this.boxH); + } + +} + +public class MGuiRMI implements ActionListener, ChangeListener, MouseListener, MouseMotionListener { + + // GUI elements + JFrame frame; + JPanel panel; + JButton endButton; + JButton backButton; + JButton calcButton; + JSlider maxIterations; + MyJLabel view; + int nrIterations; + + // box management + int boxULx, boxULy, boxW, boxH; + boolean dragging = false; + + // this one does all the calculating work + RMIMandelbrotCalculationsInterface remoteCalcObj; + + // how many points in the image? + // change if you want a higher resolution + public static final int RESX = 600; + public static final int RESY = 600; + + MGuiRMI() { + // set up GUI + this.frame = new JFrame("Mandelbrotmenge"); + this.panel = new JPanel(); + this.endButton = new JButton("Ende"); + this.panel.add(this.endButton); + this.backButton = new JButton("Zurueck"); + this.panel.add(this.backButton); + this.calcButton = new JButton("Rechnen"); + this.panel.add(this.calcButton); + this.frame.add(this.panel); + this.frame.setSize(500, 500); + this.frame.setVisible(true); + this.view = new MyJLabel("Platzhalter"); + this.maxIterations = new JSlider(0, 50, 30); + this.panel.add(this.maxIterations); + this.panel.add(this.view); + + this.endButton.addActionListener(this); + this.backButton.addActionListener(this); + this.calcButton.addActionListener(this); + this.maxIterations.addChangeListener(this); + + this.maxIterations.setMajorTickSpacing(10); + this.maxIterations.setPaintTicks(true); + this.maxIterations.setPaintLabels(true); + + this.view.addMouseListener(this); + this.view.addMouseMotionListener(this); + + this.boxULx = 0; + this.boxULy = 0; + this.boxW = MGuiRMI.RESX; + this.boxH = MGuiRMI.RESY; + + // Non-Gui stuff + String host = ""; + try { + Registry registry = LocateRegistry.getRegistry(host); + this.remoteCalcObj = (RMIMandelbrotCalculationsInterface) registry.lookup("RMIEchoInterface"); + } catch (RemoteException | NotBoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + this.nrIterations = 1000; + } + + // visualization related stuff, do not touch! + int[] generateLookupTable(int nrHues) { + int[] tmp = new int[nrHues + 1]; + int cycle = 2048; + for (int i = 0; i < nrHues; i++) { + float hue = 1 * ((float) (i % cycle)) / cycle/* ((float)nrHues) */ ; + tmp[i] = Color.HSBtoRGB(hue, 0.8f, 1.0f); + } + tmp[0] = Color.HSBtoRGB(0f, 1.0f, 0.0f); + return tmp; + } + + // visualization + static void applyLookupTable(int[] data, int[] dest, int[] lookupTable) { + for (int i = 0; i < data.length; i++) { + dest[i] = lookupTable[data[i]]; + } + } + + // here we check what the buttons do + public void actionPerformed(ActionEvent ae) { + if (ae.getSource() == this.endButton) { + System.out.println("Ende"); + System.exit(0); + } else + + if (ae.getSource() == this.backButton) { + System.out.println("Zurueck"); + double ULx = -0.16099999999999995; + double ULy = -0.9365333333333333; + double LRx = -0.03533333333333327; + double LRy = -0.8108666666666666; + this.boxULx = 0; + this.boxULy = 0; + this.boxW = MGuiRMI.RESX; + this.boxH = MGuiRMI.RESY; + this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH); + this.view.repaint(); + try { + this.remoteCalcObj.setView(ULx, ULy, LRx, LRy); + } catch (RemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else + + if (ae.getSource() == this.calcButton) { + System.out.println("Rechnen"); + long timestampStart = System.currentTimeMillis(); + + double ULx = 0; + double ULy = 0; + double LRx = 0; + double LRy = 0; + try { + ULx = this.remoteCalcObj.getULx(); + ULy = this.remoteCalcObj.getULy(); + LRx = this.remoteCalcObj.getLRx(); + LRy = this.remoteCalcObj.getLRy(); + } catch (RemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + double w = LRx - ULx; + double h = LRy - ULy; + ULx = ULx + w * this.boxULx / (double) MGuiRMI.RESX; + ULy = ULy + h * this.boxULy / (double) MGuiRMI.RESY; + w *= this.boxW / (double) (RESX); + h *= this.boxH / (double) (RESX); + LRx = ULx + w; + LRy = ULy + h; + System.out.println(ULx + "/" + ULy + "/" + LRx + "/" + LRy); + this.boxULx = 0; + this.boxULy = 0; + this.boxW = MGuiRMI.RESX; + this.boxH = MGuiRMI.RESY; + int[] colors = null; + try { + this.remoteCalcObj.setView(ULx, ULy, LRx, LRy); + this.remoteCalcObj.iterateAllPoints(this.maxIterations.getValue() * 1000, MGuiRMI.RESX, MGuiRMI.RESY); + int[] lookupTable = generateLookupTable(this.maxIterations.getValue() * 1000); + colors = new int[MGuiRMI.RESX * MGuiRMI.RESY]; + MGuiRMI.applyLookupTable(remoteCalcObj.getResult(), colors, lookupTable); + } catch (RemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + BufferedImage colorImage = new BufferedImage(MGuiRMI.RESX, MGuiRMI.RESY, BufferedImage.TYPE_INT_ARGB); + colorImage.setRGB(0, 0, MGuiRMI.RESX, MGuiRMI.RESY, colors, 0, MGuiRMI.RESX); + this.view.setIcon(new ImageIcon(colorImage)); + + this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH); + this.view.repaint(); + + long timestampEnd = System.currentTimeMillis(); + + String timeElapsed = "Zeit: " + ((timestampEnd - timestampStart) / 1000.0) + " sec"; + System.out.println(timeElapsed); + this.view.setText(timeElapsed); + } + } + + public void mousePressed(MouseEvent e) { + this.boxULx = e.getX(); + this.boxULy = e.getY(); + this.boxW = 1; + this.boxH = 1; + this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH); + } + + public void mouseDragged(MouseEvent e) { + this.boxW = e.getX() - this.boxULx + 1; + this.boxH = e.getY() - this.boxULy + 1; + int m = Math.min(boxW, boxH); + this.boxW = m; + this.boxH = m; + this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH); + this.view.repaint(); + } + + public void mouseReleased(MouseEvent e) { + + if (e.getButton() == MouseEvent.BUTTON1) { + this.view.repaint(); + } + } + + public void mouseMoved(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseClicked(MouseEvent e) { + } + + // process a new slider value + public void stateChanged(ChangeEvent ce) { + if (ce.getSource() == this.maxIterations) { + //System.out.println("Neuer Wert"); + this.nrIterations = this.maxIterations.getValue() * 1000; + } + } + + // main, just instantiate an MGui object, gives control to the Gui + public static void main(String[] args) { + @SuppressWarnings("unused") + MGuiRMI gui = new MGuiRMI(); + } +} diff --git a/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsInterface.java b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsInterface.java new file mode 100644 index 0000000..7b91dc4 --- /dev/null +++ b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsInterface.java @@ -0,0 +1,14 @@ +package verteiltesysteme.mandelbrot.rmi; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface RMIMandelbrotCalculationsInterface extends Remote { + void iterateAllPoints(int maxIterations, double nrPointsX, double nrPointsY) throws RemoteException; + public int[] getResult() throws RemoteException; + public double getULx() throws RemoteException; + public double getLRx() throws RemoteException; + public double getULy() throws RemoteException; + public double getLRy() throws RemoteException; + public void setView(double ULx, double ULy, double LRx, double LRy) throws RemoteException; +} \ No newline at end of file diff --git a/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsServer.java b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsServer.java new file mode 100644 index 0000000..846d3ce --- /dev/null +++ b/VerteilteSysteme-Examples/src/verteiltesysteme/mandelbrot/rmi/RMIMandelbrotCalculationsServer.java @@ -0,0 +1,130 @@ +package verteiltesysteme.mandelbrot.rmi; + +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +class Complex { + double r; + double i; + + Complex() { + r = 0.0; + i = 0.0; + } + + Complex(double r, double i) { + this.r = r; + this.i = i; + } + + void mulBy(Complex other) { + double rTmp = this.r * other.r - this.i * other.i; + this.i = this.r * other.i + this.i * other.r; + this.r = rTmp; + } + + void add(Complex other) { + this.r += other.r; + this.i += other.i; + } + + void sub(Complex other) { + this.r -= other.r; + this.i -= other.i; + } + + double absValue() { + return Math.sqrt(this.r * this.r + this.i * this.i); + } +} + +public class RMIMandelbrotCalculationsServer implements RMIMandelbrotCalculationsInterface { + public RMIMandelbrotCalculationsServer() {} + + public static void main(String args[]) { + + try { + RMIMandelbrotCalculationsServer obj = new RMIMandelbrotCalculationsServer(); + RMIMandelbrotCalculationsInterface stub = (RMIMandelbrotCalculationsInterface) UnicastRemoteObject.exportObject(obj, 0); + + // Bind the remote object's stub in the registry + Registry registry = LocateRegistry.getRegistry(); + registry.bind("RMIEchoInterface", stub); + + System.err.println("Server ready"); + } catch (Exception e) { + System.err.println("Server exception: " + e.toString()); + e.printStackTrace(); + } + } + + // hier wird das Ergebnis von iterateAll() gespeichert + protected int[] result = null; + + // der augenblicklich gewaehlte Ausschnitt + //double ULx = -2, ULy = -2, LRx = 2, LRy = 2; + double ULx = -0.16099999999999995, ULy = -0.9365333333333333, LRx = -0.03533333333333327, LRy = -0.8108666666666666; + + int iterateOnePoint(Complex c, int maxIterations, double maxModulus) { + Complex z = new Complex(0., 0.); + + for (int i = 0; i < maxIterations; i++) { + z.mulBy(z); + z.add(c); + double m = z.absValue(); + if (m > maxModulus) { + return i; + } + } + return maxIterations; + } + + public void iterateAllPoints(int maxIterations, double nrPointsX, double nrPointsY) { + + this.result = new int[(int) (nrPointsX * nrPointsY)]; + + int counter = 0; + double stepX = (this.LRx - this.ULx) / nrPointsX; + double stepY = (this.LRy - this.ULy) / nrPointsY; + double i = this.ULy; + for (int cy = 0; cy < nrPointsY; cy++) { + double r = this.ULx; + for (int cx = 0; cx < nrPointsX; cx++) { + Complex c = new Complex(r, i); + this.result[counter] = maxIterations - this.iterateOnePoint(c, maxIterations, 2.0); + counter += 1; + r += stepX; + } + i += stepY; + } + } + + public int[] getResult() { + return this.result; + } + + public double getULx() { + return this.ULx; + } + + public double getLRx() { + return this.LRx; + } + + public double getULy() { + return this.ULy; + } + + public double getLRy() { + return this.LRy; + } + + public void setView(double ULx, double ULy, double LRx, double LRy) { + this.ULx = ULx; + this.ULy = ULy; + this.LRx = LRx; + this.LRy = LRy; + } + +} \ No newline at end of file