CoolFace
Apppublic

michalis13/ship-tracker

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
routing.py98 linesDownload Raw Back to root
1"""Voyage routing: πεδίο κόστους θάλασσας + A* -> βέλτιστη (μπλε) πορεία.2Η στεριά (NaN στα marine δεδομένα) γίνεται αυτόματα αδιάβατη."""3import heapq4import numpy as np5 6IMPASSABLE = 1e67 8 9def make_grid(bbox, n):10    """bbox = (lat_min, lon_min, lat_max, lon_max). Σειρά 0 = βορράς (πάνω)."""11    lat_min, lon_min, lat_max, lon_max = bbox12    lats = np.linspace(lat_max, lat_min, n)13    lons = np.linspace(lon_min, lon_max, n)14    return lats, lons15 16 17def ll_to_idx(lat, lon, lats, lons):18    return int(np.argmin(np.abs(lats - lat))), int(np.argmin(np.abs(lons - lon)))19 20 21def idx_to_ll(path, lats, lons):22    return [[float(lons[c]), float(lats[r])] for r, c in path]  # [lon, lat] για pydeck23 24 25def _norm(a):26    a = np.array(a, float)27    finite = a[np.isfinite(a)]28    if finite.size == 0:29        return np.zeros_like(a)30    lo, hi = finite.min(), finite.max()31    if hi - lo < 1e-9:32        return np.zeros_like(a)33    return (a - lo) / (hi - lo)34 35 36def build_cost_grid(wave, current, w_wave=1.0, w_curr=0.5):37    """Συνδυάζει κύμα + ρεύμα σε κόστος ανά κελί. NaN (στεριά) -> αδιάβατο."""38    wave = np.array(wave, float)39    current = np.array(current, float)40    land = ~np.isfinite(wave) | ~np.isfinite(current)41    cost = 1.0 + w_wave * np.nan_to_num(_norm(wave)) + w_curr * np.nan_to_num(_norm(current))42    cost[land] = IMPASSABLE43    return cost44 45 46def astar(cost, start, goal):47    """8-κατευθύνσεων A*. Αποφεύγει αδιάβατα κελιά. Επιστρέφει (path, total_cost)."""48    H, W = cost.shape49    cmin = max(cost[cost < IMPASSABLE].min(), 1e-6)50    gr, gc = goal51 52    def h(r, c):53        return np.hypot(r - gr, c - gc) * cmin54 55    open_h = [(h(*start), 0.0, start)]56    came, gscore, seen = {}, {start: 0.0}, set()57    nbrs = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]58 59    while open_h:60        _, g, cur = heapq.heappop(open_h)61        if cur in seen:62            continue63        seen.add(cur)64        if cur == goal:65            path = [cur]66            while cur in came:67                cur = came[cur]; path.append(cur)68            return path[::-1], g69        r, c = cur70        for dr, dc in nbrs:71            nr, nc = r + dr, c + dc72            if not (0 <= nr < H and 0 <= nc < W):73                continue74            if cost[nr, nc] >= IMPASSABLE:75                continue76            ng = g + cost[nr, nc] * np.hypot(dr, dc)77            if ng < gscore.get((nr, nc), 1e18):78                gscore[(nr, nc)] = ng79                came[(nr, nc)] = cur80                heapq.heappush(open_h, (ng + h(nr, nc), ng, (nr, nc)))81    return None, float("inf")82 83 84def path_cost(cost, path):85    total = 0.086    for (r0, c0), (r1, c1) in zip(path[:-1], path[1:]):87        cell = cost[r1, c1]88        if cell >= IMPASSABLE:89            cell = 50  # ποινή αν η πραγματική πορεία ακούμπησε "στεριά"/άκυρο90        total += cell * np.hypot(r1 - r0, c1 - c0)91    return total92 93 94def straight_idx(start, goal, n=160):95    rs = np.linspace(start[0], goal[0], n).round().astype(int)96    cs = np.linspace(start[1], goal[1], n).round().astype(int)97    return list(dict.fromkeys(zip(rs.tolist(), cs.tolist())))98