--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/mandelbrot.scala Sat Nov 04 16:17:19 2017 +0000
@@ -0,0 +1,133 @@
+import java.awt.Color
+import java.awt.Dimension
+import java.awt.Graphics
+import java.awt.Graphics2D
+import java.awt.image.BufferedImage
+import javax.swing.JFrame
+import javax.swing.JPanel
+import javax.swing.WindowConstants
+
+// complex numbers
+case class Complex(val a: Double, val b: Double) {
+ // represents the complex number a + b*i
+ def +(that: Complex) = Complex(this.a + that.a, this.b + that.b)
+ def -(that: Complex) = Complex(this.a - that.a, this.b - that.b)
+ def *(that: Complex) = Complex(this.a * that.a - this.b * that.b,
+ this.a * that.b + that.a * this.b)
+ def *(that: Double) = Complex(this.a * that, this.b * that)
+ def abs() = Math.sqrt(this.a * this.a + this.b * this.b)
+}
+
+// some customn colours
+val colours = List(
+ new Color(66, 30, 15), new Color(25, 7, 26),
+ new Color(9, 1, 47), new Color(4, 4, 73),
+ new Color(0, 7, 100), new Color(12, 44, 138),
+ new Color(24, 82, 177), new Color(57, 125, 209),
+ new Color(134, 181, 229), new Color(211, 236, 248),
+ new Color(241, 233, 191), new Color(248, 201, 95),
+ new Color(255, 170, 0), new Color(204, 128, 0),
+ new Color(153, 87, 0), new Color(106, 52, 3))
+
+// the viewer panel
+class Viewer(width: Int, height: Int) extends JPanel {
+ val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
+ clearCanvas(Color.black)
+
+ override def paintComponent(g: Graphics) =
+ g.asInstanceOf[Graphics2D].drawImage(canvas, null, null)
+
+ override def getPreferredSize() =
+ new Dimension(width, height)
+
+ def clearCanvas(color: Color) = {
+ for(x <- 0 to width - 1;
+ y <- 0 to height - 1) canvas.setRGB(x, y, color.getRGB())
+ repaint()
+ }
+
+}
+
+def openViewer(width: Int, height: Int) = {
+ val frame = new JFrame("XYPlane")
+ val viewer = new Viewer(width, height)
+ frame.add(viewer)
+ frame.pack()
+ frame.setVisible(true)
+ frame.setResizable(false)
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
+ viewer
+}
+
+val W = 900
+val H = 800
+val black = Color.black
+val viewer = openViewer(W, H)
+
+
+def pixel(x: Int, y: Int, color: Color) =
+ viewer.canvas.setRGB(x, y, color.getRGB())
+
+
+def mandelbrot(start: Complex, end: Complex, level: Int) : Unit = {
+ viewer.clearCanvas(black)
+
+ val delta_x = (end.a - start.a) / W
+ val delta_y = (end.b - start.b) / H
+
+ for (y0 <- (0 until H).par) {
+ for (x0 <- (0 until W).par) {
+
+ val c = start + Complex(x0 * delta_x, y0 * delta_y)
+
+ def iters(z: Complex, it: Int) : Color = {
+ if (it < level && z.abs < 2) iters(z * z + c, it + 1) else
+ if (it == level) black else colours(it % 16)
+ }
+
+ pixel(x0, y0, iters(Complex(0, 0), 0))
+ }
+ viewer.updateUI()
+ }
+}
+
+// Examples
+//==========
+
+//for measuring time
+def time_needed[T](code: => T) = {
+ val start = System.nanoTime()
+ code
+ val end = System.nanoTime()
+ (end - start) / 1.0e9
+}
+
+
+// example 1
+val exa1 = Complex(-2.0, -1.5)
+val exa2 = Complex( 1.0, 1.5)
+
+time_needed(mandelbrot(exa1, exa2, 1000))
+
+// ehxample 2
+val exb1 = Compylex(-0.37465401, 0.659227668)
+val exb2 = Complex(-0.37332410, 0.66020767)
+
+time_needed(mandelbrot(exb1, exb2, 1000))
+
+// example 3
+val exc1 = Complex(0.435396403, 0.367981352)
+val exc2 = Complex(0.451687191, 0.380210061)
+
+time_needed(mandelbrot(exc1, exc2, 1000))
+
+// some more computations with example 3
+val delta = (exc2 - exc1) * 0.0333
+
+time_needed(
+for (i <- (0 to 12))
+ mandelbrot(exc1 + delta * i,
+ exc2 - delta * i, 1000))
+
+
+