Advertisement
CloneTrooper1019

Mandelbrot.lua

Jan 10th, 2019
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.87 KB | None | 0 0
  1. local Complex = {}
  2. Complex.__index = Complex
  3.  
  4. local argAssert = "'%s' must be a %s"
  5. local floor = math.floor
  6.  
  7. local function assertType(value, label, expectedType)
  8.     assert(type(value) == expectedType, argAssert:format(label, expectedType))
  9. end
  10.  
  11. local function assertComplex(complex)
  12.     if type(complex) == "number" then
  13.         complex = Complex.new(complex, 0)
  14.     end
  15.    
  16.     assertType(complex, "input", "table")
  17.     assert(getmetatable(complex) == Complex, argAssert:format("input", "Complex"))
  18.    
  19.     return complex
  20. end
  21.  
  22. function Complex.new(real, imaginary)
  23.     local real = real or 0
  24.     assertType(real, "real", "number")
  25.    
  26.     local imaginary = imaginary or 0
  27.     assertType(imaginary, "imaginary", "number")
  28.    
  29.     local complex = {}
  30.     complex.Real = real
  31.     complex.Imaginary = imaginary
  32.    
  33.     return setmetatable(complex, Complex)
  34. end
  35.  
  36. function Complex:__newindex(k,v)
  37.     error("Complex is read-only.", 0)
  38. end
  39.  
  40. function Complex:__tostring()
  41.     local real = self.Real
  42.     local imaginary = self.Imaginary
  43.    
  44.     if real == 0 then
  45.         return imaginary .. 'i'
  46.     elseif imaginary == 0 then
  47.         return real
  48.     end
  49.    
  50.     imaginary = imaginary .. 'i'
  51.    
  52.     if imaginary:sub(1, 1) == '-' then
  53.         imaginary = imaginary:gsub('-', " - ")
  54.     else
  55.         imaginary = " + " .. imaginary
  56.     end
  57.    
  58.     return real .. imaginary
  59. end
  60.  
  61. function Complex:__add(complex)
  62.     self = assertComplex(self)
  63.     complex = assertComplex(complex)
  64.     return Complex.new(self.Real + complex.Real, self.Imaginary + complex.Imaginary)
  65. end
  66.  
  67. function Complex:__sub(complex)
  68.     self = assertComplex(self)
  69.     complex = assertComplex(complex)
  70.     return Complex.new(self.Real - complex.Real, self.Imaginary - complex.Imaginary)
  71. end
  72.  
  73. function Complex:__mul(complex)
  74.     -- This computes the distributed multiplication of...
  75.     -- [   (a + bi)(c + di)   ] = [ ac + (ad)i + (bc)i + (bd)(i^2) ] =
  76.     -- [ ac + (ad + bc)i - bd ] = [     (ac - bd) + (ad + bc)i     ]
  77.    
  78.     self = assertComplex(self)
  79.     complex = assertComplex(complex)
  80.    
  81.     local a = self.Real
  82.     local b = self.Imaginary
  83.    
  84.     local c = complex.Real
  85.     local d = complex.Imaginary
  86.    
  87.     local ac = a * c
  88.     local ad = a * d
  89.    
  90.     local bc = b * c
  91.     local bd = b * d
  92.    
  93.     return Complex.new(ac - bd, ad + bc)
  94. end
  95.  
  96. function Complex:__eq(complex)
  97.     self = assertComplex(self)
  98.     complex = assertComplex(complex)
  99.    
  100.     return self.Real == complex.Real and
  101.            self.Imaginary == complex.Imaginary
  102. end
  103.  
  104. ---------------------------------------------------------------------------------------------------------------------
  105.  
  106. local Mandelbrot =
  107. {
  108.     CharacterSet = "      .,=;:%$@&# ";
  109.    
  110.     Iterations = 20;
  111.     Threshold  = 10e20;
  112.    
  113.     Horizontal =
  114.     {
  115.         Min = -1.5;
  116.         Max =  0.5;
  117.         Scale = 118;
  118.     };
  119.    
  120.     Vertical =
  121.     {
  122.         Min = -1.1;
  123.         Max = 1.1;
  124.         Scale = 80;
  125.     };
  126.    
  127.     Zoom = 1;
  128. }
  129.  
  130. function Mandelbrot:Sample(real, imaginary)
  131.     local c = Complex.new(real, imaginary)
  132.    
  133.     local z = c
  134.     local i = 0
  135.    
  136.     while i < self.Iterations and z.Real < self.Threshold do
  137.         z = (z * z) + c
  138.         i = i + 1
  139.     end
  140.    
  141.     local char = 1 + floor((#self.CharacterSet - 1) * (i / self.Iterations))
  142.     return self.CharacterSet:sub(char, char)
  143. end
  144.  
  145. function Mandelbrot:Render()
  146.     local h = self.Horizontal
  147.     local v = self.Vertical
  148.    
  149.     for imaginary = v.Min, v.Max, (v.Max - v.Min) / v.Scale do
  150.         local row = ""
  151.  
  152.         for real = h.Min, h.Max, (h.Max - h.Min) / h.Scale do
  153.             local sample = self:Sample(real, imaginary)
  154.             row = row .. sample
  155.         end
  156.        
  157.         print(row)
  158.        
  159.         if wait then
  160.             wait()
  161.         end
  162.     end
  163. end
  164.  
  165. Mandelbrot:Render()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement