this repo has no description
at main 3.6 kB view raw
1//! By convention, root.zig is the root source file when making a library. 2const std = @import("std"); 3 4const PI: comptime_float = std.math.pi; 5const sqrt_3: comptime_float = std.math.sqrt(3.0); 6 7pub const Point = struct { x: f32, y: f32 }; 8 9// Axial coordinates: q + r + s = 0 constraint 10// s = -q-r 11pub const Axial = struct { 12 q: i32, 13 r: i32, 14 s: i32, 15 16 pub fn init(q: i32, r: i32) Axial { 17 return .{ .q = q, .r = r, .s = -q - r }; 18 } 19 20 pub fn add(self: Axial, other: Axial) Axial { 21 return .{ .q = self.q + other.q, .r = self.r + other.r, .s = self.s + other.s }; 22 } 23 24 pub fn sub(self: Axial, other: Axial) Axial { 25 return .{ .q = self.q - other.q, .r = self.r - other.r, .s = self.s - other.s }; 26 } 27 28 pub fn neighbor(self: Axial, dir: Direction) Axial { 29 return self.add(direction_vectors[@intFromEnum(dir)]); 30 } 31 32 pub fn toPixel(self: Axial, size: f32) Point { 33 const q: f32 = @floatFromInt(self.q); 34 const r: f32 = @floatFromInt(self.r); 35 return .{ 36 .x = size * (1.5 * q), 37 .y = size * (sqrt_3 * (r + q / 2.0)), 38 }; 39 } 40 41 // flat-top odd-q 42 pub fn toOffset(self: Axial) Offset { 43 const col = self.q; 44 const row = self.r + @divFloor(self.q - (self.q & 1), 2); 45 return .{ .col = col, .row = row }; 46 } 47}; 48 49pub const Offset = struct { 50 col: i32, 51 row: i32, 52 53 // flat-top odd-q 54 pub fn toAxial(self: Offset) Axial { 55 const q = self.col; 56 const r = self.row - @divFloor(self.col - (self.col & 1), 2); 57 return Axial.init(q, r); 58 } 59}; 60 61const direction_vectors = [6]Axial{ 62 .{ .q = 0, .r = -1, .s = 1 }, // top_left 63 .{ .q = 1, .r = -1, .s = 0 }, // top 64 .{ .q = 1, .r = 0, .s = -1 }, // top_right 65 .{ .q = 0, .r = 1, .s = -1 }, // bottom_right 66 .{ .q = -1, .r = 1, .s = 0 }, // bottom 67 .{ .q = -1, .r = 0, .s = 1 }, // bottom_left 68}; 69 70pub const HexCell = struct { inner_radius: f32, outer_radius: f32, height: f32, width: f32, center: Point, cubic: Axial }; 71pub const Cell = HexCell; 72 73pub const HexDirections = enum { top_left, top, top_right, bottom_right, bottom, bottom_left }; 74pub const Direction = HexDirections; 75 76fn calculate_outer_radius(inner_radius: f32) f32 { 77 return 2.0 * inner_radius / sqrt_3; 78} 79fn calculate_inner_radius(outer_radius: f32) f32 { 80 return outer_radius / 2.0 * sqrt_3; 81} 82 83pub fn calculate_hex_corners(center: Point, size: f32, _i: usize) Point { 84 const i: f32 = @floatFromInt(_i); 85 const angle_deg = 60.0 * i; 86 const angle_rad = std.math.degreesToRadians(angle_deg); 87 88 const x_offset: f32 = size * std.math.cos(angle_rad); 89 const y_offset: f32 = size * std.math.sin(angle_rad); 90 91 return Point{ .x = center.x + x_offset, .y = center.y + y_offset }; 92} 93 94pub fn new_hex(outer_radius: f32, cubic: Axial) HexCell { 95 const size = outer_radius; 96 const inner = calculate_inner_radius(size); 97 const center = cubic.toPixel(size); 98 return HexCell{ .inner_radius = inner, .outer_radius = size, .height = sqrt_3 * size, .width = 2 * size, .center = center, .cubic = cubic }; 99} 100 101pub fn new_hex_at(outer_radius: f32, center: Point) HexCell { 102 const size = outer_radius; 103 const inner = calculate_inner_radius(size); 104 return HexCell{ .inner_radius = inner, .outer_radius = size, .height = sqrt_3 * size, .width = 2 * size, .center = center, .cubic = Axial.init(0, 0) }; 105} 106 107pub fn add_hex(base: HexCell, direction: HexDirections) HexCell { 108 const new_cubic = base.cubic.neighbor(direction); 109 return new_hex(base.outer_radius, new_cubic); 110}