Page 1 of 2

### Hey, so here's a couple functions!

Posted: Sat Dec 10, 2016 2:53 am
I take no credit for creating the concepts or the formulas, I only wrote the code , obviously xD I'm not a genius, but I did the tedious work of putting the functions together. I don't think there is any practical use for them, but I still found them interesting to play with

This is a Super Ellipse function, not much to explain here haha
Pretty basic, xOff and yOff are the positions of the center of the Ellipse, a, b, and n are variables to play with at your leisure(A and B are w and h, n is the gud stuff, detail is line segments

Code: Select all

``````function love.graphics.superEllipse(xOff, yOff, a, b, n, detail)
local function sgn(x) --Function for stuff :3
return x > 0 and 1 or x < 0 and -1 or 0
end
xOff, yOff, a, b, n, na, detail = xOff or 0, yOff or 0, a or 100, b or 100, n or 2, n/2, detail or 0.1
local PointTable = {}
for i=0, math.pi*2, (math.pi*2) / detail or 0.1 do
table.insert(PointTable, {x=math.pow(math.abs(math.cos(i)), na) * a * sgn(math.cos(i)),y=math.pow(math.abs(math.sin(i)), na) * b * sgn(math.sin(i))})
end
for k,v in pairs(PointTable) do
local thisVec = v
local nextVec = PointTable[k+1] or PointTable[1]
love.graphics.line(v.x + xOff, v.y + yOff, nextVec.x + xOff, nextVec.y + yOff)
end
end
``````
Now here comes the fun stuff! SuperShapes Mwahahhahahaa, if you have no idea what it is, or what you can go do with it, go check out this page http://paulbourke.net/geometry/supershape/. It even goes over some variables you can input to have various different shapes. I'm not gonna go into super detail cuz it's allot haha. But it's cool nonetheless
Once again, xOff and yOff are positions, n1, n2, n3, m, a, and b are your children.. Don't abuse them... Naw, jk do what you want fam, it's just a letter. Detail is segments, and radius is.. well radius

Code: Select all

``````function love.graphics.superShape(xOff, yOff, n1, n2, n3, m, a, b, detail, radius)
--[[ Default values ]]--
n1, n2, n3, m, a, b, detail, radius, xOff, yOff = n1 or 1, n2 or 1, n3 or 1, m or 0, a or 1, b or 1, detail or 500, radius or 100, xOff or 0, yOff or 0
--[[ Function for stuff :3 ]]--
local function spshpe(theta)
local formula = math.pow((math.pow(math.abs((1 / a) * math.cos(theta * m / 4)), n2)) + (math.pow(math.abs((1 / b) * math.sin(theta * m / 4)), n3)), 1 / n1)

return formula == 0 and 0 or 1 / formula
end

local PointTable = {}
for i=0, math.pi * 2, (math.pi*2) / detail do
end
for k,v in pairs(PointTable) do
local thisVec = v
local nextVec = PointTable[k+1] or PointTable[1]
love.graphics.line(v.x + xOff, v.y + yOff, nextVec.x + xOff, nextVec.y + yOff)
end
end
``````
Have fun guys, It's fun to tinker with

EDIT:
Here's the more optimized and ability to use outside of LOVE2D with credit from the all mighty Positive07
Positive07 wrote:Okey I had a go with the first function, trying to optimize and making it nicre, Also with lot's of comments so you can understand why I changed what I changed

Code: Select all

``````--Declare variables that are gonna be used EVERY time the function is called outside of it
--This is so that Lua doesn't calculate them every single time
local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
-- I used tables here because I'm actually cheating later
local offset = { x or 0, y or 0 }
local v = { a or 100, b or 100 }
--It didn't look like you needed n after all
local na = (n or 2)/2
--I declared all variables in different lines because it's easier to know which one gets which value
local detail = detail or 0.1

--ranamed for consistency
local points = {}

for i=0, tau, tau / detail do
--x and y are calculated the same so we can do it in a loop
for j=1, 2 do
--This are only used here so they must be locals
--we don't want to pollute the global scope
local f = func[j](i)
local abs = math.abs(f)
--I removed the sign function and used this which ivan suggested
local sgn = math.floor(f/abs + 0.5)

--We apply the offset directly to the points
local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
--All points are in a single list, odd enrties are x values, even are y values
--table.insert is slow in common Lua (Not that it matters with LuaJIT though)
points[#points + 1] = result
end
end

--Return the list of points
return points
end

--LÖVE specific function, the other is just math
function superEllipseDraw (...)
--love.graphics.polygon has a line mode which do the same job as your second loop
love.graphics.polygon("line", supperEllipse(...))
end
``````

Code: Select all

``````local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
local offset = { x or 0, y or 0 }
local v = { a or 100, b or 100 }
local na = (n or 2)/2
local detail = detail or 0.1

local points = {}

for i=0, tau, tau / detail do
for j=1, 2 do
local f = func[j](i)
local abs = math.abs(f)
local sgn = math.floor(f/abs + 0.5)

local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
points[#points + 1] = result
end
end

return points
end

function superEllipseDraw (...)
love.graphics.polygon("line", supperEllipse(...))
end
``````

### Re: Hey, so here's a couple functions!

Posted: Sat Dec 10, 2016 7:47 am
The first function (math.sgn) can be replaced with a much more compact version:

Code: Select all

``````function math.sgn(x)
return x > 0 and 1 or x < 0 and -1 or 0
end``````
And the if formula/return lines could be replaced too...

Code: Select all

``return formula == 0 and 0 or 1 / formula``
Sorry, I've just been obsessed with this trick lately. Probably an unhealthy obsession. No idea if they'd even make things faster or slower. Just more compact and neat looking. (As long as you understand what they do)

### Re: Hey, so here's a couple functions!

Posted: Sat Dec 10, 2016 7:56 am
In this case, since you already know the absolute value you can simply write:

Code: Select all

``````local absValue = math.abs(value) -- already known
assert(absValue > 0)
local sign = value/absValue``````
Also, make sure to store intermediate stuff in locals since Lua is a dynamic language (and cannot optimize 'constant' operations):

Code: Select all

``````    local a = a or 100
local b = b or 100
local n = n or 2
local na = n/2
local co = math.cos(i)
local si = math.sin(i)
local aco = math.abs(co)
local asi = math.abs(si)
local x = math.pow(aco, na) * a * co/aco
local y = math.pow(asi, na) * b * si/asi
table.insert(PointTable, Vector(x, y))``````
Note: You'll need an extra check if aco==0 or asi==0 to avoid a division by 0
or better yet, if your math code is robust enough, that shouldn't happen at all.

PS. and move "local a = a or 100" outside of the loop, you don't need that check in every iteration.

### Re: Hey, so here's a couple functions!

Posted: Sun Dec 11, 2016 5:06 am
ivan wrote:
Jasoco wrote:
Credit to you two , I worked stuff out and just did some general changes, so there ya go
Also I can't get over that trick either Jasoco haha, I love it but don't use it for when I'm lettin others see the code cuz well.. It's kind of a hard concept for new people to understand but ye

### Re: Hey, so here's a couple functions!

Posted: Sun Dec 11, 2016 6:37 am
Haha, yeah. It can be confusing to newbies, but when you get used to it, it saves a lot of code typing.

### Re: Hey, so here's a couple functions!

Posted: Mon Dec 12, 2016 1:10 am
Okey I had a go with the first function, trying to optimize and making it nicre, Also with lot's of comments so you can understand why I changed what I changed

Code: Select all

``````--Declare variables that are gonna be used EVERY time the function is called outside of it
--This is so that Lua doesn't calculate them every single time
local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
-- I used tables here because I'm actually cheating later
local offset = { x or 0, y or 0 }
local v = { a or 100, b or 100 }
--It didn't look like you needed n after all
local na = (n or 2)/2
--I declared all variables in different lines because it's easier to know which one gets which value
local detail = detail or 0.1

--ranamed for consistency
local points = {}

for i=0, tau, tau / detail do
--x and y are calculated the same so we can do it in a loop
for j=1, 2 do
--This are only used here so they must be locals
--we don't want to pollute the global scope
local f = func[j](i)
local abs = math.abs(f)
--I removed the sign function and used this which ivan suggested
local sgn = math.floor(f/abs + 0.5)

--We apply the offset directly to the points
local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
--All points are in a single list, odd enrties are x values, even are y values
--table.insert is slow in common Lua (Not that it matters with LuaJIT though)
points[#points + 1] = result
end
end

--Return the list of points
return points
end

--LÖVE specific function, the other is just math
function superEllipseDraw (...)
--love.graphics.polygon has a line mode which do the same job as your second loop
love.graphics.polygon("line", supperEllipse(...))
end
``````

Code: Select all

``````local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
local offset = { x or 0, y or 0 }
local v = { a or 100, b or 100 }
local na = (n or 2)/2
local detail = detail or 0.1

local points = {}

for i=0, tau, tau / detail do
for j=1, 2 do
local f = func[j](i)
local abs = math.abs(f)
local sgn = math.floor(f/abs + 0.5)

local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
points[#points + 1] = result
end
end

return points
end

function superEllipseDraw (...)
love.graphics.polygon("line", supperEllipse(...))
end
``````

### Re: Hey, so here's a couple functions!

Posted: Mon Dec 12, 2016 4:41 am
Just to nitpick a bit, 2pi is commonly called "tau".

### Re: Hey, so here's a couple functions!

Posted: Mon Dec 12, 2016 6:51 am
Good job, Positive, your revisions look much cleaner than the original.
Of course, I would even remove "table.insert" and "love.graphics" too
so the code would be pure Lua math (each function could return a list of points).

### Re: Hey, so here's a couple functions!

Posted: Mon Dec 12, 2016 4:57 pm
For those just curious what super ellipses look like, see attached Love.
Definitely not an example of great code - just wanted to see what this was all about.
Key control for 'm' and 'n' parameters.
love.math.triangulate definitely doesn't like certain parameter combinations.
Have fun.

### Re: Hey, so here's a couple functions!

Posted: Mon Dec 12, 2016 10:43 pm
ivan wrote:Good job, Positive, your revisions look much cleaner than the original.
Of course, I would even remove "table.insert" and "love.graphics" too
so the code would be pure Lua math (each function could return a list of points).
Okay I fixed this things, [manual]table.insert[/manual] is not slower than points[#points + 1] in LuaJIT though, because LuaJIT optimizes it
I added a superEllipseDraw function which is LÖVE specific but the supperEllipse one is just math
zorg wrote:Just to nitpick a bit, 2pi is commonly called "tau".
I fixed this too because there was actually a bug and instead of writing "pi2", I wrote "p12"... so "tau" is better