function Clamp(x,a,b)
    if x < a then return a end
    if x > b then return b end
    return x
end

 -----------------------------StepSmooth-------------------------------------- 
 --[[
                              StepSmooth
        ^
        |                               
     1  |                       *     *   
        |                *
        |            *
        |  *   *
     0  |--min------------------------max----- >   x

]]

function StepSmooth(x,min,max)
    if not min then min = 0 end
    if not max then max = 1 end
    x = Clamp(x,min,max)
    return  - 2*math.pow((x - min)/(max - min),3) + 3*math.pow((x - min)/(max - min),2)
end

 -----------------------------SmoothPit-------------------------------------- 

 --[[
                              SmoothPit
        ^
        |                               
     1  |                       *     *  
        |                *                *  
        |            *                          *
        |  *   *                                       *    *   
     0  |--min---------------------middle-------------------max----- >   x

]]

function PitSmooth(x,min,middle,max)
    return (1 - StepSmooth(x,min,middle) + StepSmooth(x,middle,max))
end


function StepSin(x)
    return math.sin(x * 3.1415926 / 2)
end


function StepLinear(x)
    return x
end


function NormalizeAngleTo360(angle)
    while angle < 0 do
        angle = angle + 360
    end
    while angle > 360 do
        angle = angle - 360
    end
    return angle
end


function CalcDirectionAndDistance(start_angle, end_angle)
    local dist, dir
    
    start_angle = NormalizeAngleTo360(start_angle)
    end_angle = NormalizeAngleTo360(end_angle)
                   
    if end_angle > start_angle then
        dist = end_angle - start_angle
    else
        dist = end_angle + 360 - start_angle
    end
    if dist > 180 then
        dist = 360 - dist
        dir = -1
    else
        dir = 1
    end
    
    return start_angle, end_angle, dist, dir
end


Set = 
function(element)
	local set = {}
	 -- return true if element was added
	function set.Add(this,element)
    
        if type(element)=="table" then
            for i=1,#element do
                this:Add(element[i])
            end
        end
    
		for i = 1,#this
		do
			if this[i] == element then return false end
		end
		this[#this + 1] = element
		return true
	end
	
	function set.Remove(this,element)
		for i = 1,#this
		do
			if this[i] == element then this[i] = this[#this] this[#this] = nil end
		end
	end
	
	function set.Contain(this,element)
		for i = 1,#this
		do
			if this[i] == element then return true end
		end
		return false
	end
	
	function set.Subtraction(this,otherSet)
		local outSet = Set()
		for i = 1,#this
		do
			if not otherSet:Contain(this[i]) then outSet:Add(this[i]) end
		end
		return outSet
	end
	
	function set.Copy(this)
		local set = Set()
		for i = 1,#this
		do
			set:Add(this[i])
		end
		return set
	end
    
    if element then set:Add(element) end

	return set

end


function Round(num, idp)
    local mult = 10 ^ (idp or 0)
    return math.floor(num * mult + 0.5) / mult
end

function atan2(x,y,centerX,centerY)

	if centerX==nil then centerX=0 end
	if centerY==nil then centerY=0 end
	local ret = math.atan2(x-centerX,y-centerY)
	if ret >=0  
	then 
		return ret/0.017453292519943
	end
	return (ret+2.0*math.pi)/0.017453292519943
end
