Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Mandelbrot Fractal with Glimmer DSL for SWT(Implemented Mandelbrot Set Fractal, Parallelized with all CPU cores, and then rendered with Glimmer DSL for SWT)
Mandelbrot Fractal with Glimmer DSL for SWT [message #1838391] |
Wed, 24 February 2021 02:46 |
Andy Maleh Messages: 75 Registered: March 2020 Location: Montreal, Quebec, Canada |
Member |
|
|
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), 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.
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
Learn more at this blog post:
https://andymaleh.blogspot.com/2021/02/glimmer-dsl-for-swt-mandelbrot-fractal.html
Enjoy!
EclipseCon / EclipseWorld / Agile Conference Speaker
Open-Source Software Author of Glimmer DSL for SWT
[Updated on: Wed, 24 February 2021 03:23] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Fri Apr 26 11:19:15 GMT 2024
Powered by FUDForum. Page generated in 0.03547 seconds
|