Marching squares: Difference between revisions
Content added Content deleted
m (→{{header|Julia}}: add plotting) |
|||
Line 37: | Line 37: | ||
<pre> |
<pre> |
||
points = [(3, 4), (4, 3), (4, 2), (4, 1), (3, 0), (2, 1), (2, 1), (1, 2), (1, 3), (2, 4), (3, 4)] |
points = [(3, 4), (4, 3), (4, 2), (4, 1), (3, 0), (2, 1), (2, 1), (1, 2), (1, 3), (2, 4), (3, 4)] |
||
</pre> |
|||
=={{header|Lua}}== |
|||
Based on the Phix and Wren solutions. |
|||
<lang Lua>-- positive directions: right, down, clockwise |
|||
local Directions = { -- clockwise from North |
|||
N = {x= 0, y=-1}, |
|||
E = {x= 1, y= 0}, |
|||
S = {x= 0, y= 1}, |
|||
W = {x=-1, y= 0}, |
|||
} |
|||
local dxdybList = { |
|||
{0,0,1}, -- same position |
|||
{1,0,2}, -- right |
|||
{0,1,4}, -- down |
|||
{1,1,8}, -- right and down |
|||
} |
|||
local cases = { |
|||
"W", "N", "W", "S", |
|||
"S", nil, "S", "E", |
|||
nil, "N", "W", "E", |
|||
"E", "N", |
|||
} |
|||
local function identifyPerimeter(iLayer, startingX, startingY, data) |
|||
local resultDirections = {} |
|||
local resultPositions = {} |
|||
local currentX, currentY = startingX, startingY |
|||
local direction, prevDirection |
|||
while true do |
|||
local mask = 0 |
|||
for _, d in ipairs (dxdybList) do |
|||
local dx, dy, b = d[1], d[2], d[3] |
|||
local mx, my = currentX+dx, currentY+dy |
|||
if mx>1 and my>1 |
|||
and data[my-1] and data[my-1][mx-1] |
|||
and data[my-1][mx-1] == iLayer then |
|||
mask = mask + b |
|||
end |
|||
end |
|||
direction = cases[mask] |
|||
if not direction then |
|||
if mask == 6 then |
|||
direction = (prevDirection == "E") and "N" or "S" |
|||
elseif mask == 9 then |
|||
direction = (prevDirection == "S") and "E" or "W" |
|||
else |
|||
error ('no mask: '.. mask..' by x:'..currentX..' y:'..currentY, 1) |
|||
end |
|||
end |
|||
table.insert (resultDirections, direction) |
|||
table.insert (resultPositions, currentX) |
|||
table.insert (resultPositions, currentY) |
|||
local vDir = Directions[direction] |
|||
currentX, currentY = currentX+vDir.x, currentY+vDir.y |
|||
prevDirection = direction |
|||
if startingX == currentX and startingY == currentY then |
|||
return resultDirections, resultPositions |
|||
end |
|||
end |
|||
end |
|||
local function findFirstOnLayer (iLayer, data) |
|||
for y = 1, #data do -- from 1 to hight |
|||
for x = 1, #data[1] do -- from 1 to width |
|||
local value = data[y][x] |
|||
if value == iLayer then |
|||
return x, y -- only one contour |
|||
end |
|||
end |
|||
end |
|||
end |
|||
local function msMain (iLayer, data) |
|||
local rootX, rootY = findFirstOnLayer (iLayer, data) |
|||
print ("root: x="..rootX..' y='..rootY) |
|||
local directions, positions = identifyPerimeter(iLayer, rootX, rootY, data) |
|||
print ('directions amount: '..#directions) |
|||
print ('directions: '.. table.concat (directions, ',')) |
|||
local strPositions = "" |
|||
for i = 1, #positions-1, 2 do |
|||
strPositions = strPositions..positions[i]..','..positions[i+1]..', ' |
|||
end |
|||
print ('positions: {' .. strPositions..'}') |
|||
end |
|||
local example = { |
|||
{0, 0, 0, 0, 0, 0}, |
|||
{1, 0, 0, 0, 0, 1}, |
|||
{0, 1, 1, 0, 1, 0}, |
|||
{0, 1, 1, 1, 1, 0}, |
|||
{0, 1, 0, 1, 1, 0}, |
|||
{1, 0, 0, 0, 0, 1}, |
|||
} |
|||
msMain (1, example) |
|||
</lang>{{out}} |
|||
<pre> |
|||
root: x=1 y=2 |
|||
directions amount: 34 |
|||
directions: E,S,E,E,S,E,N,E,N,E,S,W,S,S,S,E,S,W,N,W,W,N,W,S,W,S,W,N,E,N,N,N,W,N |
|||
positions: {1,2, 2,2, 2,3, 3,3, 4,3, 4,4, 5,4, 5,3, 6,3, 6,2, 7,2, 7,3, 6,3, 6,4, 6,5, 6,6, 7,6, 7,7, 6,7, 6,6, 5,6, 4,6, 4,5, 3,5, 3,6, 2,6, 2,7, 1,7, 1,6, 2,6, 2,5, 2,4, 2,3, 1,3, } |
|||
</pre> |
</pre> |
||