// Mandelbrot pictures//=====================//// see https://en.wikipedia.org/wiki/Mandelbrot_set// // under scala 2.13.1 needs to be called with// // scala -cp scala-parallel-collections_2.13-0.2.0.jar mandelbrot.scalaimport java.awt.Colorimport java.awt.Dimensionimport java.awt.Graphicsimport java.awt.Graphics2Dimport java.awt.image.BufferedImageimport javax.swing.JFrameimport javax.swing.JPanelimport javax.swing.WindowConstantsimport scala.language.implicitConversions import scala.collection.parallel.CollectionConverters._// complex numberscase class Complex(val re: Double, val im: Double) { // represents the complex number re + im * i def +(that: Complex) = Complex(this.re + that.re, this.im + that.im) def -(that: Complex) = Complex(this.re - that.re, this.im - that.im) def *(that: Complex) = Complex(this.re * that.re - this.im * that.im, this.re * that.im + that.re * this.im) def *(that: Double) = Complex(this.re * that, this.im * that) def abs() = Math.sqrt(this.re * this.re + this.im * this.im)}// to allow the notation n + m * iobject i extends Complex(0, 1)implicit def double2complex(re: Double) = Complex(re, 0)// some customn colours for the "sliding effect"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 with an image canvasclass Viewer(width: Int, height: Int) extends JPanel { val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) 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() } }// initialising the viewer paneldef openViewer(width: Int, height: Int) : Viewer = { 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}// some hardcoded parametersval W = 900 // widthval H = 800 // heightval black = Color.blackval viewer = openViewer(W, H)// draw a pixel on the canvasdef pixel(x: Int, y: Int, color: Color) = viewer.canvas.setRGB(x, y, color.getRGB())// calculates the number of iterations using lazy lists (streams)// the iteration goes on for a maximum of max steps,// but might leave early when the pred is satisfieddef iterations(c: Complex, max: Int) : Int = { def next(z: Complex) = z * z + c def pred(z: Complex) = z.abs() < 2 // exit condition LazyList.iterate(0.0 * i, max)(next).takeWhile(pred).size}// main function // start and end are the upper-left and lower-right corners, // max is the number of maximum iterationsdef mandelbrot(start: Complex, end: Complex, max: Int) : Unit = { viewer.clearCanvas(black) // deltas for each grid step val d_x = (end.re - start.re) / W val d_y = (end.im - start.im) / H for (y <- (0 until H)) { for (x <- (0 until W)) { val c = start + (x * d_x + y * d_y * i) val iters = iterations(c, max) val col = if (iters == max) black else colours(iters % 16) pixel(x, y, col) } viewer.updateUI() } }// Examples//==========//for measuring timedef time_needed[T](code: => T) = { val start = System.nanoTime() code val end = System.nanoTime() (end - start) / 1.0e9}// example 1val exa1 = -2.0 + -1.5 * ival exa2 = 1.0 + 1.5 * iprintln(s"${time_needed(mandelbrot(exa1, exa2, 1000))} secs")// example 2val exb1 = -0.37465401 + 0.659227668 * ival exb2 = -0.37332410 + 0.66020767 * i//time_needed(mandelbrot(exb1, exb2, 1000))// example 3val exc1 = 0.435396403 + 0.367981352 * ival exc2 = 0.451687191 + 0.380210061 * i//time_needed(mandelbrot(exc1, exc2, 1000))// some more computations with example 3val delta = (exc2 - exc1) * 0.0333//println(s"${time_needed(// for (n <- (0 to 12)) // mandelbrot(exc1 + delta * n, // exc2 - delta * n, 100))} secs") // Larry Paulson's exampleval exl1 = -0.74364990 + 0.13188170 * ival exl2 = -0.74291189 + 0.13261971 * i//println(s"${time_needed(mandelbrot(exl1, exl2, 1000))} secs")// example by Jorgen Villadsenval exj1 = 0.10284 - 0.63275 * ival exj2 = 0.11084 - 0.64075 * i//time_needed(mandelbrot(exj1, exj2, 1000))// another exampleval exA = 0.3439274 + 0.6516478 * ival exB = 0.3654477 + 0.6301795 * i//time_needed(mandelbrot(exA, exB, 1000))