DEV Community

Andy Maleh
Andy Maleh

Posted on • Edited on

1 2

Glimmer DSL for SWT Mandelbrot Fractal

For the hardcore Computer Scientists out there who have strong interest in graphical algorithms, the Mandelbrot Set is a very well known Computer Science/Math algorithm that renders a fractal at various zoom levels, demonstrating the repetitive nature of fractals. During my bachelor of Computer Science at McGill University (Montreal, QC, Canada) over two decades ago, I remember spending very long and tiring nights at the computer lab to implement an Assembly language renderer of the Mandelbrot Fractal. Much has changed since then. We have multi-core processors today, let alone the wonderful Ruby programming language, so I wrote this with Glimmer DSL for SWT by taking advantage of the multi-threaded JRuby and saturating all CPU cores to finish calculating Mandelbrot points in less than 10 seconds on 4 CPU cores. The sample supports unlimited zooming, pre-calculated in the background with the window title bar notifying you once higher zooms are available. It also allows panning with scrollbars or mouse dragging.

Glimmer DSL for SWT Mandelbrot Fractal

The initial version's Glimmer GUI DSL (domain specific language) code was so simple, this was all of it:

  body {
    shell {
      text 'Mandelbrot Fractal'
      minimum_size @width, @height + 12
      image @image

      canvas {
        image(@image, 0, 0)
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

Below is the multi-threaded model code and Glimmer GUI DSL code of the Mandelbrot Fractal initial version (without zooming or menus). The Glimmer DSL for SWT GUI simply paints an image as a form of image buffering (to avoid Mandelbrot pixel repaints on GUI repaints) and then puts it inside a canvas to display.

require 'glimmer-dsl-swt'
require 'complex'
require 'concurrent-ruby'

class Mandelbrot
  attr_accessor :max_iterations

  def initialize(max_iterations)
    @max_iterations = max_iterations
  end

  def calculate_all(x_array, y_array)
    thread_pool = Concurrent::FixedThreadPool.new(Concurrent.processor_count)
    width = x_array.size
    height = y_array.size
    pixel_rows_array = Concurrent::Array.new(height)
    height.times do |y|
      pixel_rows_array[y] ||= Concurrent::Array.new(width)
      width.times do |x|
        thread_pool.post do
          pixel_rows_array[y][x] = calculate(x_array[x], y_array[y]).last
        end
      end
    end
    thread_pool.shutdown
    thread_pool.wait_for_termination
    pixel_rows_array
  end

  # Mandelbrot point calculation implementation
  # Courtesy of open-source code at:
  # https://github.com/gotbadger/ruby-mandelbrot
  def calculate(x,y)
    base_case = [Complex(x,y), 0]
    Array.new(max_iterations, base_case).inject(base_case) do |prev ,base|
      z, itr = prev
      c, _ = base
      val = z*z + c
      itr += 1 unless val.abs < 2
      [val, itr]
    end
  end
end

class MandelbrotFractal
  include Glimmer::UI::CustomShell

  before_body {
    @colors = [[0, 0, 0]] + 40.times.map { |i| [255 - i*5, 255 - i*5, 55 + i*5] }
    @colors = @colors.map {|color_data| rgb(*color_data).swt_color}
    mandelbrot = Mandelbrot.new(@colors.size - 1)
    @y_array = (1.0).step(-1,-0.0030).to_a
    @x_array = (-2.0).step(0.5,0.0030).to_a
    @height = @y_array.size
    @width = @x_array.size
    @pixel_rows_array = mandelbrot.calculate_all(@x_array, @y_array)
    @image = Image.new(display.swt_display, @width, @height)
    image_gc = org.eclipse.swt.graphics.GC.new(@image)
    @height.times { |y|
      @width.times { |x|
        new_foreground = @colors[@pixel_rows_array[y][x]]
        image_gc.foreground = @current_foreground = new_foreground unless new_foreground == @current_foreground
        image_gc.draw_point x, y
      }
    }
  }

  body {
    shell {
      text 'Mandelbrot Fractal'
      minimum_size @width, @height + 12
      image @image

      canvas {
        image(@image, 0, 0)
      }
    }
  }
end

MandelbrotFractal.launch
Enter fullscreen mode Exit fullscreen mode

Learn more at this blog post:
https://andymaleh.blogspot.com/2021/02/glimmer-dsl-for-swt-mandelbrot-fractal.html

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more