|         |      1 import java.awt.Color | 
|         |      2 import java.awt.Dimension | 
|         |      3 import java.awt.Graphics | 
|         |      4 import java.awt.Graphics2D | 
|         |      5 import java.awt.image.BufferedImage | 
|         |      6 import javax.swing.JFrame | 
|         |      7 import javax.swing.JPanel | 
|         |      8 import javax.swing.WindowConstants | 
|         |      9  | 
|         |     10 // complex numbers | 
|         |     11 case class Complex(val a: Double, val b: Double) {  | 
|         |     12     // represents the complex number a + b*i | 
|         |     13     def +(that: Complex) = Complex(this.a + that.a, this.b + that.b) | 
|         |     14     def -(that: Complex) = Complex(this.a - that.a, this.b - that.b) | 
|         |     15     def *(that: Complex) = Complex(this.a * that.a - this.b * that.b, | 
|         |     16                                    this.a * that.b + that.a * this.b) | 
|         |     17     def *(that: Double) = Complex(this.a * that, this.b * that) | 
|         |     18     def abs() = Math.sqrt(this.a * this.a + this.b * this.b) | 
|         |     19 } | 
|         |     20  | 
|         |     21 // some customn colours | 
|         |     22 val colours = List( | 
|         |     23     new Color(66, 30, 15),    new Color(25, 7, 26), | 
|         |     24     new Color(9, 1, 47),      new Color(4, 4, 73), | 
|         |     25     new Color(0, 7, 100),     new Color(12, 44, 138), | 
|         |     26     new Color(24, 82, 177),   new Color(57, 125, 209), | 
|         |     27     new Color(134, 181, 229), new Color(211, 236, 248), | 
|         |     28     new Color(241, 233, 191), new Color(248, 201, 95), | 
|         |     29     new Color(255, 170, 0),   new Color(204, 128, 0), | 
|         |     30     new Color(153, 87, 0),    new Color(106, 52, 3)) | 
|         |     31  | 
|         |     32 // the viewer panel | 
|         |     33 class Viewer(width: Int, height: Int) extends JPanel { | 
|         |     34     val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) | 
|         |     35     clearCanvas(Color.black) | 
|         |     36  | 
|         |     37     override def paintComponent(g: Graphics) =  | 
|         |     38       g.asInstanceOf[Graphics2D].drawImage(canvas, null, null) | 
|         |     39  | 
|         |     40     override def getPreferredSize() =  | 
|         |     41        new Dimension(width, height) | 
|         |     42  | 
|         |     43     def clearCanvas(color: Color) = { | 
|         |     44       for(x <- 0 to width - 1; | 
|         |     45           y <- 0 to height - 1) canvas.setRGB(x, y, color.getRGB()) | 
|         |     46       repaint() | 
|         |     47     }   | 
|         |     48  | 
|         |     49 } | 
|         |     50  | 
|         |     51 def openViewer(width: Int, height: Int) = { | 
|         |     52     val frame = new JFrame("XYPlane") | 
|         |     53     val viewer = new Viewer(width, height) | 
|         |     54     frame.add(viewer) | 
|         |     55     frame.pack() | 
|         |     56     frame.setVisible(true) | 
|         |     57     frame.setResizable(false) | 
|         |     58     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) | 
|         |     59     viewer | 
|         |     60 } | 
|         |     61  | 
|         |     62 val W = 900 | 
|         |     63 val H = 800  | 
|         |     64 val black = Color.black | 
|         |     65 val viewer = openViewer(W, H) | 
|         |     66  | 
|         |     67  | 
|         |     68 def pixel(x: Int, y: Int, color: Color) =  | 
|         |     69   viewer.canvas.setRGB(x, y, color.getRGB()) | 
|         |     70    | 
|         |     71  | 
|         |     72 def mandelbrot(start: Complex, end: Complex, level: Int) : Unit = { | 
|         |     73   viewer.clearCanvas(black) | 
|         |     74     | 
|         |     75   val delta_x = (end.a - start.a) / W | 
|         |     76   val delta_y = (end.b - start.b) / H | 
|         |     77     | 
|         |     78   for (y0 <- (0 until H).par) { | 
|         |     79     for (x0 <- (0 until W).par) { | 
|         |     80      | 
|         |     81      val c = start + Complex(x0 * delta_x, y0 * delta_y) | 
|         |     82  | 
|         |     83      def iters(z: Complex, it: Int) : Color = { | 
|         |     84        if (it < level && z.abs < 2) iters(z * z + c, it + 1) else  | 
|         |     85         if (it == level) black else colours(it % 16)  | 
|         |     86      } | 
|         |     87  | 
|         |     88      pixel(x0, y0, iters(Complex(0, 0), 0)) | 
|         |     89    } | 
|         |     90    viewer.updateUI() | 
|         |     91  } | 
|         |     92 } | 
|         |     93  | 
|         |     94 // Examples | 
|         |     95 //========== | 
|         |     96  | 
|         |     97 //for measuring time | 
|         |     98 def time_needed[T](code: => T) = { | 
|         |     99   val start = System.nanoTime() | 
|         |    100   code | 
|         |    101   val end = System.nanoTime() | 
|         |    102   (end - start) / 1.0e9 | 
|         |    103 } | 
|         |    104  | 
|         |    105  | 
|         |    106 // example 1 | 
|         |    107 val exa1 = Complex(-2.0, -1.5) | 
|         |    108 val exa2 = Complex( 1.0,  1.5) | 
|         |    109  | 
|         |    110 time_needed(mandelbrot(exa1, exa2, 1000)) | 
|         |    111  | 
|         |    112 // ehxample 2 | 
|         |    113 val exb1 = Compylex(-0.37465401, 0.659227668) | 
|         |    114 val exb2 = Complex(-0.37332410, 0.66020767) | 
|         |    115  | 
|         |    116 time_needed(mandelbrot(exb1, exb2, 1000)) | 
|         |    117  | 
|         |    118 // example 3 | 
|         |    119 val exc1 = Complex(0.435396403, 0.367981352) | 
|         |    120 val exc2 = Complex(0.451687191, 0.380210061) | 
|         |    121  | 
|         |    122 time_needed(mandelbrot(exc1, exc2, 1000)) | 
|         |    123  | 
|         |    124 // some more computations with example 3 | 
|         |    125 val delta = (exc2 - exc1) * 0.0333 | 
|         |    126  | 
|         |    127 time_needed( | 
|         |    128 for (i <- (0 to 12))  | 
|         |    129   mandelbrot(exc1 + delta * i,  | 
|         |    130              exc2 - delta * i, 1000)) | 
|         |    131  | 
|         |    132  | 
|         |    133  |