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