There doesn’t seem to be a fill routine in Codea that can fill vector drawn polygons, so I built one. Essentially, it fills your shape by creating an image (just once), which can then be drawn as many times as you like. You initialise it by passing an array of vectors and a color, and then just call its draw routine when you want to, so it’s pretty easy to use.
I’m sure the code can be improved, comments welcome. Note it can be easily adapted to fill any hollow shape/image.
--# Main
-- Fill
function setup()
--set up an array of vectors which make up our shape
v={vec2(0,0),vec2(100,0),vec2(150,75),vec2(80,200),vec2(40,50)}
c=color(255,0,0,255) --fill color
f=FillShape(v,c) --create filled object
end
function draw()
background(128)
f:draw(100,400) --draw filled object
f:draw(400,600)
end
--# FillShape
FillShape = class()
--parameters are
--1. an array of 2D vectors making up the shape, the last one will be joined to the first automatically
--2. the fill color
--the result is an image that is only created once and can be drawn as many times as you like
function FillShape:init(v,c)
self.maxx,self.maxy=0,0 --to store size of object
--calculate x,y bounds
self.n = #v
for i=1,self.n do
if v[i].x>self.maxx then self.maxx=v[i].x end
if v[i].y>self.maxy then self.maxy=v[i].y end
end
--create image
self.img=image(self.maxx,self.maxy)
--tell Codea to draw onto our image instead of the screen
setContext(self.img)
--draw the shape on our image, and return a starting x,y point within the image
local x,y=self:DrawShape(v,c)
--fill the image
self:DoFill(x,y,c)
--let Codea draw onthe screen again
setContext()
end
--this function draws the shape
--you can change it any way you want as long as it draws a closed object
--and returns a starting x,y position within the object
function FillShape:DrawShape(v,c)
pushStyle()
stroke(c)
strokeWidth(1)
local x,y=0,0
for i=1,self.n-1 do
line(v[i].x,v[i].y,v[i+1].x,v[i+1].y)
x=x+v[i].x --we'll return a starting x,y position of the average of all x and y values
y=y+v[i].y
end
line(v[self.n].x,v[self.n].y,v[1].x,v[1].y) --join the last point to the first point
popStyle()
return x/self.n,y/self.n --return the average x and y position
end
function FillShape:draw(x,y)
sprite(self.img,x,y)
end
--this is a recursive function.
--Starting with the initial x,y position, it looks at all its neighbours, colouring any blanks, and
--running itself again for each neighbour that is blank
function FillShape:DoFill(x,y,c)
if x<1 or x>self.maxx or y<1 or y>self.maxy then return end --stop if out of bounds
local r,g,b,a=self.img:get(x,y)
if r+g+b==0 then --fill in blank cells
self.img:set(x,y,c)
self:DoFill(x-1,y,c) --run for all neighbours
self:DoFill(x+1,y,c)
self:DoFill(x,y-1,c)
self:DoFill(x,y+1,c)
end
end