Drawing a Polygon with a fill.

Hey guys,

I’ve done a google search but haven’t found anything. I’m not sure whether or not I have completely skipped something here. In the API section and docs they have display.newRect(), I just want to know if there’s a way you can define each corner with x and y values.

Hope I made sense,

Thanks [import]uid: 35662 topic_id: 10110 reply_id: 310110[/import]

Here’s a simple polygon fill method that I found and tweaked a bit for Corona use… (credit for the fill function goes to eyece for his forum post Here)

This function finds all the points on a pixel by pixel basis that can be connected with a line, not sure if it works for complex polys, but seems to work fine for simple ones for sure.

Basically I took this and tweaked the following:

  • can pass in the color to be set for the fill

  • can pass in an xoffset and a yoffset so you can re-use poly definitions (IE see the star)

This may work for what you are talking about…allthough it’s probably better performance to just use an image for this purpose I had to look this up once you posed the question on how to fill LOL

Here’s the code with a rectangle example as well…

[code]
function paintPoly(poly, xoffset, yoffset, rgba)

n = #poly

miny = poly[1].y
maxy = poly[1].y

for i = 2, n do
miny = math.min(miny, poly[i].y)
maxy = math.max(maxy, poly[i].y)
end

for y = miny, maxy do

ints = {}
int = 0
last = n

for i = 1, n do

y1 = poly[last].y
y2 = poly[i].y
if y1 < y2 then
x1 = poly[last].x
x2 = poly[i].x
if (y >= y1) and (y < y2) then
int = int + 1
ints[int] = math.floor((y-y1) * (x2-x1) / (y2-y1) + x1)
end
elseif y1 > y2 then
x1 = poly[last].x
x2 = poly[i].x
if (y >= y2) and (y < y1) then
int = int + 1
ints[int] = math.floor((y-y2) * (x1-x2) / (y1-y2) + x2)
end
end
last = i
end

—[[
i = 1
while i < int do
line = display.newLine(ints[i] + xoffset, y + yoffset, ints[i+1] + xoffset, y + yoffset)
line:setColor( rgba[1], rgba[2], rgba[3], rgba[4] )
i = i + 2
end
–]]

end

end

colors = { {128,255,255,255}, {255,128,255,255}, {255,255,255,255}}

myStar = {
{x=0,y=-110},
{x=27,y=-35},
{x=105,y=-35},
{x=43,y=16},
{x=65,y=90},
{x=0,y=45},
{x=-65,y=90},
{x=-43,y=15},
{x=-105,y=-35},
{x=-27,y=-35},
{x=0,y=-110},
}

myRectangle = {
{x=40,y=100},
{x=180,y=100},
{x=180,y=50},
{x=40,y=50},
}
paintPoly(myStar, 160, 240, colors[1])
paintPoly(myStar, 180, 260, colors[2])
paintPoly(myRectangle, 0, 0, colors[3])

[/code] [import]uid: 48203 topic_id: 10110 reply_id: 36892[/import]

Thanks heaps croisened! Going to try it out now :slight_smile: [import]uid: 35662 topic_id: 10110 reply_id: 37224[/import]

Thanks for the useful snippet!

I modified it a little, as it uses only globals, which is absolutely horrible, but otherwise code is perfectly fine. So I just redeclared variables with ‘local’, localized Corona functions that are called inside a loop for faster access and added a group to put lines into, so that you can just delete the group and lines will be removed automatically as well.

[lua]local function paintPoly(poly, xoffset, yoffset, rgba)

local newLine = display.newLine
local math_floor = math.floor
local math_min = math.min
local math_max = math.max
local polyGroup = display.newGroup()

local n = #poly

local minY = poly[1].y
local maxY = poly[1].y

for i = 2, n do
minY = math_min(minY, poly[i].y)
maxY = math_max(maxY, poly[i].y)
end

for y = minY, maxY do

local ints = {}
local int = 0
local last = n

for i = 1, n do
local y1 = poly[last].y
local y2 = poly[i].y
if y1 < y2 then
local x1 = poly[last].x
local x2 = poly[i].x
if (y >= y1) and (y < y2) then
int = int + 1
ints[int] = math_floor((y - y1) * (x2 - x1) / (y2 - y1) + x1)
end
elseif y1 > y2 then
local x1 = poly[last].x
local x2 = poly[i].x
if (y >= y2) and (y < y1) then
int = int + 1
ints[int] = math_floor((y - y2) * (x1 - x2) / (y1 - y2) + x2)
end
end
last = i
end

local i = 1
while i < int do
local line = newLine(ints[i] + xoffset, y + yoffset, ints[i + 1] + xoffset, y + yoffset)
polyGroup:insert(line)
line:setColor(rgba[1], rgba[2], rgba[3], rgba[4])
i = i + 2
end
end

return polyGroup
end[/lua] [import]uid: 52103 topic_id: 10110 reply_id: 65638[/import]

nice workaround! thanx for sharing!

a star is not a simple polygon, because it’s not a convex one

if it works for a star, it might as well work for all closed polygons

i tried this hourglass looking shape:

hg={{x=100,y=100},{x=200,y=100},{x=100,y=200},{x=200,y=200}}

no problems
[import]uid: 6459 topic_id: 10110 reply_id: 65705[/import]

Thanks for the code. Very interesting and useful.

I worry about the efficiency of creating dozens or hundreds of line objects in order to achieve the fill, however. Would animating the filled poly (rotating the polygon group, for example) be efficient, or slow? (I’ll give it a try when I get a moment.)

I wonder if Ansca is considering building in polygon fill functionality. I was surprised when I first realized it didn’t have this functionality built-in.

-d [import]uid: 40450 topic_id: 10110 reply_id: 99186[/import]

I just answered my own question to a degree:

Rotation (for example) of the Polygon group returned by paintPoly() seems to work well performance-wise.

However, when rotating the whole object, these horizontal fill lines become diagonal with the associated aliasing (steps), which results in a “sparkling” effect due to holes where adjacent diagonal fill lines don’t line up perfectly.

It sure would be nice to have a Corona library version of this that creates a single, more efficient object (hint hint).

-d [import]uid: 40450 topic_id: 10110 reply_id: 99187[/import]