It looks like you're new here. If you want to get involved, click one of these buttons!
Hi, I wrote this program to teach my children about fractions. In some fractions, e.g. 1/13 or 1/15 the slices don't quite fill the pie. Can someone suggest how to improve the arc calculation to fix this, please? Thank you.
Main class
-- Fractions
function setup()
Pick = 1
Slices = 4
parameter.integer("Pick", 1, 20, Pick, pick)
parameter.integer("Slices", 1, 20, Slices, slice)
end
function draw()
background(40, 40, 50)
for _,p in pairs(pies) do
p:draw()
end
if #pies > 1 then
fontSize(40)
fill(255, 255, 255, 255)
text(Pick.."/"..Slices, WIDTH/2, HEIGHT-50)
end
end
function slice(n)
pick(Pick)
end
function pick(n)
local reqPies = math.ceil(n / Slices)
local cols = math.ceil(math.sqrt(reqPies))
local rows = math.ceil(reqPies / cols)
local radius = HEIGHT / cols / 4
pies = {}
for i = 1,reqPies do
local col = (i - 1) % cols + 1
local row = math.ceil(i / cols)
local x = radius * col * 3 - radius
local y = radius * row * 3 - radius
local thisPick = Slices
if i == reqPies then
thisPick = Pick % Slices
if thisPick == 0 then
thisPick = Slices
end
end
table.insert(pies, Pie(x, y, radius, Slices, thisPick))
end
end
Arc class
Arc = class()
local delta = math.pi / 36
-- If the Arc is closed, radius will be drawn
function Arc:init(startAngle, endAngle, radius, closed)
self.startAngle = startAngle
self.endAngle = endAngle
self.radius = radius
if closed ~= nil then
self.closed = closed
else
self.closed = false
end
self.points = {vec2(0, 0)}
for angle = startAngle, endAngle, delta do
local b = math.cos(angle) * radius
local h = math.sin(angle) * radius
table.insert(self.points, vec2(b, h))
end
end
function Arc:draw()
local n = #self.points
local startPoint = 1
local endPoint = n-2
if self.closed then
startPoint = 0
endPoint = n-1
end
for i = startPoint, endPoint do
local p1 = self.points[i%n + 1]
local p2 = self.points[(i+1)%n + 1]
line(p1.x, p1.y, p2.x, p2.y)
end
end
Slice class
Slice = class()
function Slice:init(x, y, startAngle, endAngle, radius, colour)
self.x = x
self.y = y
self.arc = Arc(startAngle, endAngle, radius, true)
local vertices = {}
local colours = {}
for i = 2, (#self.arc.points-1) do
table.insert(vertices, vec2(0, 0))
table.insert(vertices, self.arc.points[i])
table.insert(vertices, self.arc.points[i+1])
table.insert(colours, colour)
table.insert(colours, colour)
table.insert(colours, colour)
end
self.mesh = mesh()
self.mesh.vertices = vertices
self.mesh.colors = colours
end
function Slice:draw()
pushMatrix()
translate(self.x, self.y)
self.mesh:draw()
popMatrix()
strokeWidth(5)
stroke(0, 0, 0, 255)
self.arc:draw()
end
Pie class
Pie = class()
function Pie:init(x, y, radius, sliceCount, selected)
self.x = x
self.y = y
self.radius = radius
self.sliceCount = sliceCount
self.selected = selected
self.label = self.selected.."/"..self.sliceCount
local delta = 2 * math.pi / self.sliceCount
self.slices = {}
local colour
for i = 1,self.sliceCount do
if i <= selected then
colour = color(87, 64, 168, 255)
else
colour = color(127, 127, 127, 255)
end
table.insert(self.slices, Slice(0, 0, delta*(i-1), delta*i, radius, colour))
end
end
function Pie:draw()
pushMatrix()
translate(self.x, self.y)
for i,slice in ipairs(self.slices) do
slice:draw()
end
fontSize(self.radius / 4)
self.labelW, self.labelH = textSize(self.label)
fill(255, 255, 255, 255)
text(self.label, 0, self.radius + self.labelH)
popMatrix()
end
Comments
@LightDye Here's how I would do slices.
EDIT: Changed color and size of lines.
Thanks @dave1707, that works well when all slices are of the same colour, but I need to draw parts of the circle with different colour and that's why I'm using mesh to build slices out of narrow triangles.
I can improve the fit of slices by drawing narrower triangles in the mesh just by reducing the delta variable in the Arc class:
But then I start noticing how the drawing slows down.
OK, I didn't think about different colors for different slices.
@LightDye Is this better.
EDIT: Changed the code to make the lines thicker.
Thanks @dave1707, that certainly looks better. Cheers!
If you replace the 'text()' line in @Dave1707's code with this:
It will reduce the fractions nicely (good for the kiddos!)
@Monkeyman32123 You're doing extra divisions in the % line of code
can be changed to
Ah, yes, I see that now, how silly of me >_<
Thank you for pointing that out (didn't really go over it very well, just whipped it up)
Edited in the code above.
Nice addition to the code @Monkeyman32123, thank you!
You're welcome, any time!
Codea Fractions
Turns out that what makes my code slow is the drawing of line segments that form each slice border. After adapting @dave1707's code to my code and adding an FPS class this became obvious. I'm sharing the improved code here for future reference.
Main class
FPS class
Fraction class
Arc class
Slice class
Pie class
There are better ways to draw an arc than as a sequence of lines. Here's my arc code. It's long because it is flexible. It uses a mesh to draw the arc. There's an
arc
function and anArc
class depending on how one wants to invoke it.There's also an
arc
shader in Codea; I don't think it is all that fast.