progs/mandelbrot.scala
changeset 266 ca48ac1d3c3e
parent 265 59779ce322a6
child 309 b192bc772613
equal deleted inserted replaced
265:59779ce322a6 266:ca48ac1d3c3e
     1 // Mandelbrot pictures
     1 // Mandelbrot pictures
       
     2 //
     2 //   see https://en.wikipedia.org/wiki/Mandelbrot_set
     3 //   see https://en.wikipedia.org/wiki/Mandelbrot_set
       
     4 // 
       
     5 // under scala 2.13 needs to be called with 
       
     6 // scala -cp `coursier fetch -p org.scala-lang.modules:scala-parallel-collections_2.13:0.2.0` mandelbrot.scala
     3 
     7 
     4 import java.awt.Color
     8 import java.awt.Color
     5 import java.awt.Dimension
     9 import java.awt.Dimension
     6 import java.awt.Graphics
    10 import java.awt.Graphics
     7 import java.awt.Graphics2D
    11 import java.awt.Graphics2D
     8 import java.awt.image.BufferedImage
    12 import java.awt.image.BufferedImage
     9 import javax.swing.JFrame
    13 import javax.swing.JFrame
    10 import javax.swing.JPanel
    14 import javax.swing.JPanel
    11 import javax.swing.WindowConstants
    15 import javax.swing.WindowConstants
    12 import scala.language.implicitConversions    
    16 import scala.language.implicitConversions    
    13 
    17 import scala.collection.parallel.CollectionConverters._
    14 
    18 
    15 // complex numbers
    19 // complex numbers
    16 case class Complex(val re: Double, val im: Double) { 
    20 case class Complex(val re: Double, val im: Double) { 
    17   // represents the complex number re + im * i
    21   // represents the complex number re + im * i
    18   def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
    22   def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
    37   new Color(134, 181, 229), new Color(211, 236, 248),
    41   new Color(134, 181, 229), new Color(211, 236, 248),
    38   new Color(241, 233, 191), new Color(248, 201, 95),
    42   new Color(241, 233, 191), new Color(248, 201, 95),
    39   new Color(255, 170, 0),   new Color(204, 128, 0),
    43   new Color(255, 170, 0),   new Color(204, 128, 0),
    40   new Color(153, 87, 0),    new Color(106, 52, 3))
    44   new Color(153, 87, 0),    new Color(106, 52, 3))
    41 
    45 
    42 // the viewer panel with a canvas
    46 // the viewer panel with an image canvas
    43 class Viewer(width: Int, height: Int) extends JPanel {
    47 class Viewer(width: Int, height: Int) extends JPanel {
    44   val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
    48   val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
    45   
    49   
    46   override def paintComponent(g: Graphics) = 
    50   override def paintComponent(g: Graphics) = 
    47     g.asInstanceOf[Graphics2D].drawImage(canvas, null, null)
    51     g.asInstanceOf[Graphics2D].drawImage(canvas, null, null)
    54       canvas.setRGB(x, y, color.getRGB())
    58       canvas.setRGB(x, y, color.getRGB())
    55     repaint()
    59     repaint()
    56   }  
    60   }  
    57 }
    61 }
    58 
    62 
    59 // initialising the viewer
    63 // initialising the viewer panel
    60 def openViewer(width: Int, height: Int) : Viewer = {
    64 def openViewer(width: Int, height: Int) : Viewer = {
    61   val frame = new JFrame("XYPlane")
    65   val frame = new JFrame("XYPlane")
    62   val viewer = new Viewer(width, height)
    66   val viewer = new Viewer(width, height)
    63   frame.add(viewer)
    67   frame.add(viewer)
    64   frame.pack()
    68   frame.pack()
    66   frame.setResizable(false)
    70   frame.setResizable(false)
    67   frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    71   frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    68   viewer
    72   viewer
    69 }
    73 }
    70 
    74 
    71 // some hardcoded data
    75 // some hardcoded parameters
    72 val W = 900   // width
    76 val W = 900   // width
    73 val H = 800   // height
    77 val H = 800   // height
    74 val black = Color.black
    78 val black = Color.black
    75 val viewer = openViewer(W, H)
    79 val viewer = openViewer(W, H)
    76 
    80 
    77 // drawing a pixel on the canvas
    81 // draw a pixel on the canvas
    78 def pixel(x: Int, y: Int, color: Color) = 
    82 def pixel(x: Int, y: Int, color: Color) = 
    79   viewer.canvas.setRGB(x, y, color.getRGB())
    83   viewer.canvas.setRGB(x, y, color.getRGB())
    80 
    84 
    81 
    85 
    82 // calculating the number of iterations using lazy streams
    86 // calculates the number of iterations using lazy lists (streams)
    83 //   the iteration goes on for a maximum of max steps,
    87 //   the iteration goes on for a maximum of max steps,
    84 //   but might leave early when the pred is satisfied
    88 //   but might leave early when the pred is satisfied
    85 def iterations(c: Complex, max: Int) : Int = {
    89 def iterations(c: Complex, max: Int) : Int = {
    86   def next(z: Complex) = z * z + c    
    90   def next(z: Complex) = z * z + c    
    87   def pred(z: Complex) = z.abs < 2    // exit condition
    91   def pred(z: Complex) = z.abs < 2    // exit condition
    88   Stream.iterate(0.0 * i, max)(next).takeWhile(pred).size
    92   LazyList.iterate(0.0 * i, max)(next).takeWhile(pred).size
    89 }
    93 }
    90 
    94 
    91 // main function 
    95 // main function 
    92 //    start and end are the upper-left and lower right corners 
    96 //    start and end are the upper-left and lower-right corners, 
    93 //    max is the number of maximum iterations
    97 //    max is the number of maximum iterations
    94 def mandelbrot(start: Complex, end: Complex, max: Int) : Unit = {
    98 def mandelbrot(start: Complex, end: Complex, max: Int) : Unit = {
    95   viewer.clearCanvas(black)
    99   viewer.clearCanvas(black)
    96   
   100   
    97   // deltas for each grid step 
   101   // deltas for each grid step 
   143 val exc1 = 0.435396403 + 0.367981352 * i
   147 val exc1 = 0.435396403 + 0.367981352 * i
   144 val exc2 = 0.451687191 + 0.380210061 * i
   148 val exc2 = 0.451687191 + 0.380210061 * i
   145 
   149 
   146 //time_needed(mandelbrot(exc1, exc2, 1000))
   150 //time_needed(mandelbrot(exc1, exc2, 1000))
   147 
   151 
       
   152 
       
   153 
   148 // some more computations with example 3
   154 // some more computations with example 3
   149 
   155 
   150 val delta = (exc2 - exc1) * 0.0333
   156 val delta = (exc2 - exc1) * 0.0333
   151 
   157 
   152 /*
   158 /*
   153 time_needed(
   159 time_needed(
   154   for (n <- (0 to 12)) 
   160   for (n <- (0 to 12)) 
   155      mandelbrot(exc1 + delta * n, 
   161      mandelbrot(exc1 + delta * n, 
   156                 exc2 - delta * n, 100)) 
   162                 exc2 - delta * n, 100)) 
   157 */
   163 */
       
   164 
   158 /*
   165 /*
   159 time_needed(
   166 time_needed(
   160   for (n <- (0 to 12)) 
   167   for (n <- (0 to 12)) 
   161      mandelbrot(exc1 + delta * n, 
   168      mandelbrot(exc1 + delta * n, 
   162                 exc2 - delta * n, 1000))
   169                 exc2 - delta * n, 1000))