Only create one alias metatable
[oweals/minetest.git] / builtin / voxelarea.lua
1 VoxelArea = {
2         MinEdge = {x=1, y=1, z=1},
3         MaxEdge = {x=0, y=0, z=0},
4         ystride = 0,
5         zstride = 0,
6 }
7
8 function VoxelArea:new(o)
9         o = o or {}
10         setmetatable(o, self)
11         self.__index = self
12
13         local e = o:getExtent()
14         o.ystride = e.x
15         o.zstride = e.x * e.y
16
17         return o
18 end
19
20 function VoxelArea:getExtent()
21         return {
22                 x = self.MaxEdge.x - self.MinEdge.x + 1,
23                 y = self.MaxEdge.y - self.MinEdge.y + 1,
24                 z = self.MaxEdge.z - self.MinEdge.z + 1,
25         }
26 end
27
28 function VoxelArea:getVolume()
29         local e = self:getExtent()
30         return e.x * e.y * e.z
31 end
32
33 function VoxelArea:index(x, y, z)
34         local i = (z - self.MinEdge.z) * self.zstride +
35                           (y - self.MinEdge.y) * self.ystride +
36                           (x - self.MinEdge.x) + 1
37         return math.floor(i)
38 end
39
40 function VoxelArea:indexp(p)
41         local i = (p.z - self.MinEdge.z) * self.zstride +
42                           (p.y - self.MinEdge.y) * self.ystride +
43                           (p.x - self.MinEdge.x) + 1
44         return math.floor(i)
45 end
46
47 function VoxelArea:position(i)
48         local p = {}
49  
50         i = i - 1
51
52         p.z = math.floor(i / self.zstride) + self.MinEdge.z
53         i = i % self.zstride
54
55         p.y = math.floor(i / self.ystride) + self.MinEdge.y
56         i = i % self.ystride
57
58         p.x = math.floor(i) + self.MinEdge.x
59
60         return p
61 end
62
63 function VoxelArea:contains(x, y, z)
64         return (x >= self.MinEdge.x) and (x <= self.MaxEdge.x) and
65                    (y >= self.MinEdge.y) and (y <= self.MaxEdge.y) and
66                    (z >= self.MinEdge.z) and (z <= self.MaxEdge.z)
67 end
68
69 function VoxelArea:containsp(p)
70         return (p.x >= self.MinEdge.x) and (p.x <= self.MaxEdge.x) and
71                    (p.y >= self.MinEdge.y) and (p.y <= self.MaxEdge.y) and
72                    (p.z >= self.MinEdge.z) and (p.z <= self.MaxEdge.z)
73 end
74
75 function VoxelArea:containsi(i)
76         return (i >= 1) and (i <= self:getVolume())
77 end
78
79 function VoxelArea:iter(minx, miny, minz, maxx, maxy, maxz)
80         local i = self:index(minx, miny, minz) - 1
81         local last = self:index(maxx, maxy, maxz)
82         local ystride = self.ystride
83         local zstride = self.zstride
84         local yoff = (last+1) % ystride
85         local zoff = (last+1) % zstride
86         local ystridediff = (i - last) % ystride
87         local zstridediff = (i - last) % zstride
88         return function()
89                 i = i + 1
90                 if i % zstride == zoff then
91                         i = i + zstridediff
92                 elseif i % ystride == yoff then
93                         i = i + ystridediff
94                 end
95                 if i <= last then
96                         return i
97                 end
98         end
99 end
100
101 function VoxelArea:iterp(minp, maxp)
102         return self:iter(minp.x, minp.y, minp.z, maxp.x, maxp.y, maxp.z)
103 end