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