X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=code%2Fnetwork-generator%2Fmodel%2Fpython%2Fhexagon.py;h=e2681875929b6194d0c9c66aa0ea7c5460f29605;hb=refs%2Fchanges%2F55%2F11955%2F1;hp=e75f1d0233f6804cfcd9a1eca95acc57bf8ef70b;hpb=9ea4e241e3ec0c9dffd3db7fd7ab5a2cf3d13e7d;p=oam.git diff --git a/code/network-generator/model/python/hexagon.py b/code/network-generator/model/python/hexagon.py index e75f1d0..e268187 100644 --- a/code/network-generator/model/python/hexagon.py +++ b/code/network-generator/model/python/hexagon.py @@ -20,38 +20,45 @@ from __future__ import division from __future__ import print_function import collections import math +from typing import NamedTuple -Point = collections.namedtuple("Point", ["x", "y"]) +from model.python.point import Point +from model.python.geo_location import GeoLocation -_Hex = collections.namedtuple("Hex", ["q", "r", "s"]) +class Hex: + def __init__(self, q: int, r: int, s: int): + if round(q + r + s) != 0: + raise ValueError("The sum of q, r, and s must be 0.") + self.q = q + self.r = r + self.s = s -def Hex(q, r, s): - assert not (round(q + r + s) != 0), "q + r + s must be 0" - return _Hex(q, r, s) + def __str__(self) -> str: + return f"q: {self.q}, r: {self.r}, s: {self.s}" -def hex_add(a, b): +def hex_add(a: Hex, b: Hex) -> Hex: return Hex(a.q + b.q, a.r + b.r, a.s + b.s) -def hex_subtract(a, b): +def hex_subtract(a: Hex, b: Hex) -> Hex: return Hex(a.q - b.q, a.r - b.r, a.s - b.s) -def hex_scale(a, k): +def hex_scale(a: Hex, k: int) -> Hex: return Hex(a.q * k, a.r * k, a.s * k) -def hex_rotate_left(a): +def hex_rotate_left(a) -> Hex: return Hex(-a.s, -a.q, -a.r) -def hex_rotate_right(a): +def hex_rotate_right(a) -> Hex: return Hex(-a.r, -a.s, -a.q) -hex_directions = [ +hex_directions: list[Hex] = [ Hex(1, 0, -1), Hex(1, -1, 0), Hex(0, -1, 1), @@ -61,15 +68,15 @@ hex_directions = [ ] -def hex_direction(direction): +def hex_direction(direction: int) -> Hex: return hex_directions[direction] -def hex_neighbor(hex, direction): +def hex_neighbor(hex: Hex, direction: int) -> Hex: return hex_add(hex, hex_direction(direction)) -hex_diagonals = [ +hex_diagonals: list[Hex] = [ Hex(2, -1, -1), Hex(1, -2, 1), Hex(-1, -1, 2), @@ -79,25 +86,25 @@ hex_diagonals = [ ] -def hex_diagonal_neighbor(hex, direction): +def hex_diagonal_neighbor(hex: Hex, direction: int) -> Hex: return hex_add(hex, hex_diagonals[direction]) -def hex_length(hex): +def hex_length(hex: Hex) -> int: return (abs(hex.q) + abs(hex.r) + abs(hex.s)) // 2 -def hex_distance(a, b): +def hex_distance(a: Hex, b: Hex) -> int: return hex_length(hex_subtract(a, b)) -def hex_round(h): - qi = int(round(h.q)) - ri = int(round(h.r)) - si = int(round(h.s)) - q_diff = abs(qi - h.q) - r_diff = abs(ri - h.r) - s_diff = abs(si - h.s) +def hex_round(hex: Hex) -> Hex: + qi = int(round(hex.q)) + ri = int(round(hex.r)) + si = int(round(hex.s)) + q_diff = abs(qi - hex.q) + r_diff = abs(ri - hex.r) + s_diff = abs(si - hex.s) if q_diff > r_diff and q_diff > s_diff: qi = -ri - si else: @@ -108,17 +115,17 @@ def hex_round(h): return Hex(qi, ri, si) -def hex_lerp(a, b, t): +def hex_lerp(a: Hex, b: Hex, t: int) -> Hex: # linearly interpolation return Hex( a.q * (1.0 - t) + b.q * t, a.r * (1.0 - t) + b.r * t, a.s * (1.0 - t) + b.s * t ) -def hex_linedraw(a, b): +def hex_linedraw(a: Hex, b: Hex) -> list[hex]: N = hex_distance(a, b) a_nudge = Hex(a.q + 1e-06, a.r + 1e-06, a.s - 2e-06) b_nudge = Hex(b.q + 1e-06, b.r + 1e-06, b.s - 2e-06) - results = [] + results: list[hex] = [] step = 1.0 / max(N, 1) for i in range(0, N + 1): results.append(hex_round(hex_lerp(a_nudge, b_nudge, step * i))) @@ -127,38 +134,38 @@ def hex_linedraw(a, b): OffsetCoord = collections.namedtuple("OffsetCoord", ["col", "row"]) -EVEN = 1 -ODD = -1 +EVEN: int = 1 +ODD: int = -1 -def qoffset_from_cube(offset, h): - col = h.q - row = h.r + (h.q + offset * (h.q & 1)) // 2 +def qoffset_from_cube(offset: int, hex: Hex) -> OffsetCoord: + col = hex.q + row = hex.r + (hex.q + offset * (hex.q & 1)) // 2 if offset != EVEN and offset != ODD: raise ValueError("offset must be EVEN (+1) or ODD (-1)") return OffsetCoord(col, row) -def qoffset_to_cube(offset, h): - q = h.col - r = h.row - (h.col + offset * (h.col & 1)) // 2 +def qoffset_to_cube(offset: int, hex: Hex) -> Hex: + q = hex.col + r = hex.row - (hex.col + offset * (hex.col & 1)) // 2 s = -q - r if offset != EVEN and offset != ODD: raise ValueError("offset must be EVEN (+1) or ODD (-1)") return Hex(q, r, s) -def roffset_from_cube(offset, h): - col = h.q + (h.r + offset * (h.r & 1)) // 2 - row = h.r +def roffset_from_cube(offset: int, hex: Hex) -> OffsetCoord: + col = hex.q + (hex.r + offset * (hex.r & 1)) // 2 + row = hex.r if offset != EVEN and offset != ODD: raise ValueError("offset must be EVEN (+1) or ODD (-1)") return OffsetCoord(col, row) -def roffset_to_cube(offset, h): - q = h.col - (h.row + offset * (h.row & 1)) // 2 - r = h.row +def roffset_to_cube(offset: int, hex: Hex) -> Hex: + q = hex.col - (hex.row + offset * (hex.row & 1)) // 2 + r = hex.row s = -q - r if offset != EVEN and offset != ODD: raise ValueError("offset must be EVEN (+1) or ODD (-1)") @@ -168,28 +175,28 @@ def roffset_to_cube(offset, h): DoubledCoord = collections.namedtuple("DoubledCoord", ["col", "row"]) -def qdoubled_from_cube(h): - col = h.q - row = 2 * h.r + h.q +def qdoubled_from_cube(hex: Hex): + col = hex.q + row = 2 * hex.r + hex.q return DoubledCoord(col, row) -def qdoubled_to_cube(h): - q = h.col - r = (h.row - h.col) // 2 +def qdoubled_to_cube(hex: Hex) -> Hex: + q = hex.col + r = (hex.row - hex.col) // 2 s = -q - r return Hex(q, r, s) -def rdoubled_from_cube(h): - col = 2 * h.q + h.r - row = h.r +def rdoubled_from_cube(hex: Hex) -> DoubledCoord: + col = 2 * hex.q + hex.r + row = hex.r return DoubledCoord(col, row) -def rdoubled_to_cube(h): - q = (h.col - h.row) // 2 - r = h.row +def rdoubled_to_cube(hex: Hex): + q = (hex.col - hex.row) // 2 + r = hex.row s = -q - r return Hex(q, r, s) @@ -199,9 +206,14 @@ Orientation = collections.namedtuple( ) -Layout = collections.namedtuple("Layout", ["orientation", "size", "origin"]) +# Layout = collections.namedtuple("Layout", ["orientation", "size", "origin"]) +class Layout(NamedTuple): + orientation: Orientation + size: Point + origin: Point -layout_pointy = Orientation( + +layout_pointy: Orientation = Orientation( math.sqrt(3.0), math.sqrt(3.0) / 2.0, 0.0, @@ -212,7 +224,7 @@ layout_pointy = Orientation( 2.0 / 3.0, 0.5, ) -layout_flat = Orientation( +layout_flat: Orientation = Orientation( 3.0 / 2.0, 0.0, math.sqrt(3.0) / 2.0, @@ -225,16 +237,16 @@ layout_flat = Orientation( ) -def hex_to_pixel(layout, h): +def hex_to_pixel(layout: Layout, hex: Hex) -> Point: M = layout.orientation size = layout.size origin = layout.origin - x = (M.f0 * h.q + M.f1 * h.r) * size.x - y = (M.f2 * h.q + M.f3 * h.r) * size.y + x = (M.f0 * hex.q + M.f1 * hex.r) * size.x + y = (M.f2 * hex.q + M.f3 * hex.r) * size.y return Point(x + origin.x, y + origin.y) -def pixel_to_hex(layout, p): +def pixel_to_hex(layout: Layout, p: Point) -> Hex: M = layout.orientation size = layout.size origin = layout.origin @@ -244,22 +256,29 @@ def pixel_to_hex(layout, p): return Hex(q, r, -q - r) -def hex_corner_offset(layout, corner): +def hex_corner_offset(layout: Layout, corner: int) -> Point: M = layout.orientation size = layout.size angle = 2.0 * math.pi * (M.start_angle - corner) / 6.0 return Point(size.x * math.cos(angle), size.y * math.sin(angle)) -def polygon_corners(layout, h): - corners = [] - center = hex_to_pixel(layout, h) +def polygon_corners(layout: Layout, hex: Hex) -> list[Point]: + corners: list[Point] = [] + center = hex_to_pixel(layout, hex) for i in range(0, 6): offset = hex_corner_offset(layout, i) corners.append(Point(center.x + offset.x, center.y + offset.y)) return corners +def hex_to_geo_location( + layout: Layout, hex: Hex, reference: GeoLocation +) -> GeoLocation: + hexPoint: Point = hex_to_pixel(layout, hex) + return GeoLocation(reference).point_to_geo_location(hexPoint) + + # Tests @@ -497,6 +516,7 @@ def test_all(): test_doubled_roundtrip() test_doubled_from_cube() test_doubled_to_cube() + print("test finished") if __name__ == "__main__":