classdef Hex
properties (SetAccess = immutable)
q
r
s
address
end
properties (Constant)
directions = {Hex(1,0,-1);Hex(1,-1,0);Hex(0,-1,1);Hex(-1,0,1);Hex(-1,1,0);Hex(0,1,-1)};
diagonals = {Hex(2,-1,-1);Hex(1,-2,1);Hex(-1,-1,2);Hex(-2,1,1);Hex(-1,2,-1);Hex(1,1,-2)};
end
methods
function obj = Hex(q,r,s)
assert(q + r + s == 0,"Invalid hex coordinates.");
obj.q = q;
obj.r = r;
obj.s = s;
obj.address = char(string(obj.q)+"."+string(obj.r)+"."+string(obj.s));
end
function e = eq(obj1,obj2)
if(length(obj1) > 1 || length(obj2) > 1)
msg = "Cannot currently compare two lists of hexes.";
assert((length(obj1) == 1 || length(obj2) == 1),msg);
if(length(obj1) > 1)
temp = obj2;
obj2 = obj1;
obj1 = temp;
end
for i = 1:length(obj2)
if(obj1 == obj2(i))
e(i) = true;
else
e(i) = false;
end
end
else
if(obj1.q == obj2.q && obj1.r == obj2.r && obj1.s == obj2.s)
e = true;
else
e = false;
end
end
end
function e = ne(obj1,obj2)
if(obj1.q == obj2.q && obj1.r == obj2.r && obj1.s == obj2.s)
e = true;
else
e = false;
end
end
function hex = hex_add(A,B)
hex = Hex(A.q+B.q,A.r+B.r,A.s+B.s);
end
function hex = hex_subtract(A,B)
hex = Hex(A.q-B.q,A.r-B.r,A.s-B.s);
end
function hex = hex_multiply(A,k)
hex = Hex(A.q*k,A.r*k,A.s*k);
end
function ln = hex_length(A)
ln = max([abs(A.q),abs(A.r),abs(A.s)]);
end
function d = hex_distance(A,B)
d = hex_length(hex_subtract(A,B));
end
function neighbour = hex_neighbour(hex,direction)
neighbour = hex_add(hex,hex.hex_direction(direction));
end
function neighbour = hex_diagonal_neighbour(hex,direction)
neighbour = hex_add(hex,Hex.diagonals{direction});
end
function point = to_pixel(hex,layout)
M = layout.orientation;
x = (M.f1 * hex.q + M.f2 * hex.r) * layout.size.x;
y = (M.f3 * hex.q + M.f4 * hex.r) * layout.size.y;
point = Point(x + layout.origin.x,y + layout.origin.y);
end
function corners = polygon_corners(hex, layout)
center = hex.to_pixel(layout);
corners(1:6) = Point(0,0);
for i = 0:6
offset = Hex.corner_offset(layout,i);
corners(i+1) = (Point(center.x + offset.x, center.y + offset.y));
end
end
function fracHex = hex_linearly_interpolate(A, B, t)
fracHex = FractionalHex(Hex.linearly_interpolate(A.q,B.q,t),Hex.linearly_interpolate(A.r,B.r,t),Hex.linearly_interpolate(A.s,B.s,t));
end
function hexList = linedraw(A,B)
N = A.hex_distance(B);
hexList = Hex(0,0,0);
step = 1 / max(N,1);
for i = 0:N
hexList(i+1) = hex_round(hex_linearly_interpolate(A,B,step * i));
end
end
function offsetCoord = cube_to_oddr(hex)
col = hex.q + (hex.r -(mod(hex.r,2))) / 2;
row = hex.r;
offsetCoord = [col,row];
end
function hex = hex_scale(hex,factor)
hex = Hex(hex.q * factor, hex.r * factor, hex.s * factor);
end
end
methods (Static)
function direction = hex_direction(dir)
dir = mod(dir,6) + 1;
direction = Hex.directions{dir};
end
function fracHex = pixel_to_hex(layout, point)
M = layout.orientation;
pt = Point((point.x - layout.origin.x) / layout.size.x, (point.y - layout.origin.y) / layout.size.y);
q = M.b1 * pt.x + M.b2 * pt.y;
r = M.b3 * pt.x + M.b4 * pt.y;
s = 0 - q - r;
fracHex = FractionalHex(q,r,s);
end
function point = corner_offset(layout, corner)
size = layout.size;
angle = 2 * pi * (layout.orientation.startAngle + corner) / 6;
point = Point(size.x * cos(angle), size.y * sin(angle));
end
function c = linearly_interpolate(a, b, t)
c = a * (1 - t) + b * t;
end
function hex = oddr_to_cube(col,row)
q = col - (row - (mod(row,2))) / 2;
r = row;
s = 0 - q - r;
hex = Hex(q,r,s);
end
end
end