-- lua script for drawing spirals
-- some basic constants
local w_mid = width / 2
local h_mid = height / 2
local screen_radius = math.sqrt((w_mid * w_mid) + (h_mid * h_mid))
local r2d =  180 / 3.14159265
local r, g, b

-- allow the user to change the settings. 
-- Note the sliders have range is 0 .. 1.0 for reading but have range 1..100 for setting
--@TBCONFIG SLIDER: X Axis, 50
--@TBCONFIG SLIDER: Y Axis, 50
--@TBCONFIG SLIDER: Radius, 60
--@TBCONFIG SLIDER: Sides, 80
--@TBCONFIG SLIDER: Coils, 14
--@TBCONFIG SLIDER: Rotation, 0
--@TBCONFIG FLAG: Paint, false

local ucenterX = math.floor(sliderVal1 * width)
local ucenterY = math.floor(sliderVal2 * height)
local uradius = math.floor(sliderVal3 * screen_radius)
local usides = math.floor(sliderVal4 * 1000)
local ucoils = math.floor(sliderVal5 * 100)
local urotation  = sliderVal6  * math.pi * 2 
local uPaint = flagVal1


-- ------------------------------
-- note: functions must be defined BEFORE the calling logic calls them
-- ------------------------------
function plot(pointx,pointy)
     if (pointx > 0) and (pointy > 0) and (pointx < width) and (pointy < height) then  
    	set_rgba(pointx, pointy, r, g, b, 1)
    end 
end

function round(x)
    local xf = math.floor(x)
    if (x - xf) <= 0.5 then 
        return xf
    else
        return math.ceil(x)
    end 
end

-- Line Clipping Algorithm -- Liang-Barsky
function Liang_Barsky_clipTest(p, q, u1, u2)
local r
   if (p < 0) then 
        r = q / p
        if (r > u2) then 
            return 0, u1, u2
        elseif (r > u1) then 
            return 1, r, u2
        end
   elseif (p > 0) then 
      r = q / p
      if (r < u1) then 
         return 0, u1, u2
      elseif (r < u2) then 
            return 1, u1, r
      end
   elseif (q < 0) then 
      return 0, u1, u2
   end
   return 1, u1, u2
end

function Liang_Barsky_clipping(x0, y0, x1, y1)
local XS_MIN = 0
local XS_MAX = width
local YS_MIN = 0
local YS_MAX = height
local dx = x1 - x0
local dy = y1 - y0
local u1 = 0
local u2 = 1
local t1, t2, t3, t4 

t1, u1, u2 = Liang_Barsky_clipTest(-dx, x0-XS_MIN, u1, u2)
t2, u1, u2 = Liang_Barsky_clipTest( dx, XS_MAX-x0, u1, u2)
t3, u1, u2 = Liang_Barsky_clipTest(-dy, y0-YS_MIN, u1, u2)
t4, u1, u2 = Liang_Barsky_clipTest( dy, YS_MAX-y0, u1, u2)
    
   if (t1 == 1) and (t2 == 1) and (t3 == 1) and (t4 == 1)  then 
        if (u2 < 1) then 
            x1 = x0 + round(u2 * dx)
            y1 = y0 + round(u2 * dy)
        end
        if (u1 > 0) then 
            x0 = x0 + round(u1 * dx)
            y0 = y0 + round(u1 * dy)
        end
    end
    return x0, y0, x1, y1
end

-- Line Generating Algorithm using Bresenham's technique
function line_bres(x0, y0, x1, y1)
   x0, y0, x1, y1 = Liang_Barsky_clipping(x0, y0, x1, y1)
    local steep, t
    if (math.abs(y1 - y0) > math.abs(x1 - x0)) then 
        steep = 1 
    else 
        steep = 0 
    end 

    if steep == 1 then
        t = x0; x0 = y0; y0 = t
        t = x1; x1 = y1; y1 = t
    end
    if x0 > x1 then
        t = x0; x0 = x1; x1 = t
        t = y0; y0 = y1; y1 = t
    end 

    local deltax = x1 - x0
    local deltay = math.abs(y1 - y0)
    local error = round(deltax / 2)
    local ystep
    local y = y0
    if y0 < y1 then ystep = 1 else ystep = -1 end
    
    for x = x0, x1 do
         if (steep == 1) then plot(y,x) else plot(x,y) end 
         error = error - deltay
         if error < 0 then
             y = y + ystep
             error = error + deltax
         end
    end
end

--  centerX-- X origin of the spiral.
--  centerY-- Y origin of the spiral.
--  radius--- Distance from origin to outer arm.
--  sides---- Number of points or sides along the spiral's arm.
--  coils---- Number of coils or full rotations. (Positive numbers spin clockwise, negative numbers spin counter-clockwise)
--  rotation- Overall rotation of the spiral. ('0'=no rotation, '1'=360 degrees, '180/360'=180 degrees)
-- 
function logSpiral(centerX, centerY, radius, sides, coils, rotation)
		local current_x = centerX
		local current_y = centerY
		local away, around, new_x, new_y, i, aroundStep, aroundRadians

		--  How far to rotate around center for each side.
		aroundStep = coils/sides  --  0 to 1 based.
		--  Convert aroundStep to radians.
		aroundRadians = aroundStep * 2 * math.pi
		
		--  For every side, step around and away from center.

		for  i = 1, sides do 
			--  How far away from center
			away = math.pow(radius, i/sides)
			--  How far around the center.
			around = i * aroundRadians + rotation
			--  Convert 'around' and 'away' to X and Y.
			new_x = centerX + math.cos(around) * away
			new_y = centerY + math.sin(around) * away
			
			if uPaint == false then
				line_bres(current_x, current_y, new_x, new_y)
			else
				paint_line(current_x, current_y, new_x, new_y)
			end 
			
			current_x = new_x
			current_y = new_y
		end
end

r, g, b = get_color1()


paint_open(1)
 logSpiral(  ucenterX, ucenterY, uradius, usides, ucoils, urotation)
paint_close()




