Skip to content

Instantly share code, notes, and snippets.

@socantre
Last active September 30, 2017 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save socantre/14f5790f0d95781b3ad025a1f7147188 to your computer and use it in GitHub Desktop.
Save socantre/14f5790f0d95781b3ad025a1f7147188 to your computer and use it in GitHub Desktop.
regions.lua composing bitmaps
local module = {}
function module.circle(cx, cy, radius)
return function(x, y) return (x - cx)^2 + (y - cy)^2 < radius^2 end
end
function module.halfspace(rise, run, x0, y0)
return function(x, y) return run*(y - y0) < rise*(x - x0) end
end
function module.complement(r)
return function(x, y) return not r(x, y) end
end
function module.union(...)
local region = {...};
return function(x, y)
local result = false;
for i, r in ipairs(region) do
result = result or r(x, y)
end
return result
end
end
function module.intersection(...)
local region = {...};
return function(x, y)
if #region == 0 then return false end
local result = true;
for i, r in ipairs(region) do
result = result and r(x, y)
end
return result
end
end
function module.difference(r1, r2)
return function(x, y) return r1(x, y) and not r2(x, y) end
end
function module.xor(r1, r2)
return function(x, y) return r1(x, y) ~= r2(x, y) end
end
function module.translate(r, tx, ty)
return function(x, y)
return r(x - tx, y - ty)
end
end
function module.scale(r, s)
return function(x, y)
return r(x/s, y/s)
end
end
function module.rotate(r, radians, cx, cy)
cx = cx or 0
cy = cy or 0
return function(x, y)
return r(
(x - cx)*math.cos(-radians) - (y - cy)*math.sin(-radians) + cx,
(y - cy)*math.cos(-radians) + (x - cx)*math.sin(-radians) + cy
)
end
end
function module.plot(r, output_width, output_height, x0, y0, x1, y1)
x0, y0, x1, y1 = x0 or 0, y0 or 0, x1 or 1, y1 or 1
local x, y
io.write('P7\nWIDTH ', output_width, '\nHEIGHT ', output_height, '\nDEPTH 1\nMAXVAL 1\nTUPLTYPE BLACKANDWHITE_ALPHA\nENDHDR\n')
-- io.write('P1\n', output_width, ' ', output_height, '\n')
for i = 0, output_height - 1 do
y = y1 - (y1 - y0)/output_height * i
for j = 0, output_width - 1 do
x = (x1 - x0)/output_width * j + x0
if r(x, y) then
io.write('\x00\x00')
else
io.write('\x00\x01')
end
end
end
end
return module
-- main.lua
--[[
local regions = require 'regions'
local xor = regions.xor
local intersection = regions.intersection
local circle = regions.circle
local complement = regions.complement
local halfspace = regions.halfspace
local scale = regions.scale
local rotate = regions.rotate
local plot = regions.plot
local r =
xor(
intersection(
circle(0, 0, 9/16),
complement(circle(0, 1/3, 1/16)),
complement(circle(0, -1/3, 1/16))
),
intersection(
halfspace(2, 1, 0, 0),
circle(0, 0, 1/2)
)
)
--r = scale(r, 2)
--r = rotate(r, math.atan2(1, 2))
local width = arg[1] or 200
local height = arg[2] or 200
local subsamples = arg[3] or 4
plot(r, width, height)
]]
-- main2.lua
--[[
local regions = require "regions"
function square(x0, y0, x1, y1)
return function(x, y) return x0 < x and x < x1 and y0 < y and y < y1 end
end
local linewidth = 2/81
local s = square(0 + linewidth/2, 0 + linewidth/2, 1/3 - linewidth/2, 1/3 - linewidth/2)
gliders = {
regions.union(s,
regions.translate(s, 1/3, 0/3),
regions.translate(s, 1/3, 1/3),
regions.translate(s, 2/3, 1/3),
regions.translate(s, 0/3, 2/3)),
regions.union(s,
regions.translate(s, 1/3, 0/3),
regions.translate(s, 2/3, 0/3),
regions.translate(s, 1/3, 2/3),
regions.translate(s, 2/3, 1/3)),
regions.union(regions.translate(s, 1/3, -1/3),
regions.translate(s, 1/3, 0/3),
regions.translate(s, 2/3, 0/3),
regions.translate(s, 0/3, 1/3),
regions.translate(s, 2/3, 1/3)),
regions.union(regions.translate(s, 1/3, -1/3),
regions.translate(s, 2/3, -1/3),
regions.translate(s, 2/3, 0/3),
regions.translate(s, 0/3, 0/3),
regions.translate(s, 2/3, 1/3)),
}
local framewidth = 1 + 2/3
for i, glider in ipairs(gliders) do
gliders[i] = regions.translate(glider, (i-1)*framewidth, 0)
end
local r = regions.union(unpack(gliders))
local pixels_high = 108
local image_height = 1 + 1/3
local x0, y0 = 0 + 1/(2*pixels_high), - 1/3 - 1/(2*pixels_high) -- offset by half a pixel to avoid boundary issues
local aspect_ratio = 18/4
regions.plot(r, math.floor(pixels_high*aspect_ratio), pixels_high, x0, y0, x0+(image_height*aspect_ratio), y0+image_height)
]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment