Warum ist jedes 4-Wörter-Adress-Dekodierungsergebnis in meiner Flask-App die Ost-Antarktis, ATA?Python

Python-Programme
Anonymous
 Warum ist jedes 4-Wörter-Adress-Dekodierungsergebnis in meiner Flask-App die Ost-Antarktis, ATA?

Post by Anonymous »

Ich arbeite an einem flaskbasierten Geolocation-Tool, das (LAT, LON) in vier Wörter koordiniert, wobei ein benutzerdefiniertes Netzsystem über Land und Wasser verwendet wird. Hier ist eine vereinfachte Version des Code: < /p>

Code: Select all

import math
import csv
from typing import List, Tuple, Dict

import geopandas as gpd
from shapely.geometry import Point
from flask import Flask, request, render_template
from geopy.geocoders import ArcGIS

# ------------------------------------------------------------------------------
# FLASK APP INIT
# ------------------------------------------------------------------------------

app = Flask(__name__)
geolocator = ArcGIS()

# ------------------------------------------------------------------------------
# CONSTANTS
# ------------------------------------------------------------------------------

GRID_SIZE_LAND = 5     # metres
GRID_SIZE_WATER = 10   # metres

NUM_LAT_CELLS_LAND = int(180_000_000 / GRID_SIZE_LAND)
NUM_LON_CELLS_LAND = int(360_000_000 / GRID_SIZE_LAND)

NUM_LAT_CELLS_WATER = int(180_000_000 / GRID_SIZE_WATER)
NUM_LON_CELLS_WATER = int(360_000_000 / GRID_SIZE_WATER)

TOTAL_LAND_CELLS = NUM_LAT_CELLS_LAND * NUM_LON_CELLS_LAND
LEGACY_SPLIT = 10 ** 12  # old 4-digit prefix boundary

# ------------------------------------------------------------------------------
# WORD LIST
# ------------------------------------------------------------------------------

def load_words_from_csv(filename: str) -> Tuple[List[str], Dict[str, int]]:
"""Return a de-duplicated word list and lookup table."""
words: List[str] = []
lookup: Dict[str, int] = {}

with open(filename, newline="") as fh:
for row in csv.DictReader(fh):
w = row["word"].strip().lower()
if w and w not in lookup:  # drop blanks & duplicates
lookup[w] = len(words)
words.append(w)

return words, lookup

WORDS, WORD_TO_INDEX = load_words_from_csv("data/fourwords_wordlist.csv")
BASE = len(WORDS)

# ------------------------------------------------------------------------------
# LAND / WATER TEST
# ------------------------------------------------------------------------------

land_union = gpd.read_file("data/ne_50m_land.shp").unary_union

def is_land(lat: float, lon: float) -> bool:
return land_union.covers(Point(lon, lat))

# ------------------------------------------------------------------------------
# ENCODING
# ------------------------------------------------------------------------------

def latlon_to_cell(lat: float, lon: float) -> int:
"""Current contiguous ID scheme (land first, then water)."""
grid = GRID_SIZE_LAND if is_land(lat, lon) else GRID_SIZE_WATER

if grid == GRID_SIZE_LAND:
lat_i = int((lat + 90) * 1e6 // GRID_SIZE_LAND)
lon_i = int((lon + 180) * 1e6 // GRID_SIZE_LAND)
return lat_i * NUM_LON_CELLS_LAND + lon_i
else:  # water
lat_i = int((lat + 90) * 1e6 // GRID_SIZE_WATER)
lon_i = int((lon + 180) * 1e6 // GRID_SIZE_WATER)
return TOTAL_LAND_CELLS + lat_i * NUM_LON_CELLS_WATER + lon_i

def encode(lat: float, lon: float) -> List[str]:
cell_id = latlon_to_cell(lat, lon)
digits = [(cell_id // BASE ** i) % BASE for i in range(3, -1, -1)]  # MSB→LSB
return [WORDS[d] for d in digits]

# ------------------------------------------------------------------------------
# DECODING
# ------------------------------------------------------------------------------

def _decode_current(cell_id: int) -> Tuple[float, float]:
"""Decode using the current contiguous ID scheme."""
if cell_id < TOTAL_LAND_CELLS:
grid = GRID_SIZE_LAND
lon_cells = NUM_LON_CELLS_LAND
core_id = cell_id
else:
grid = GRID_SIZE_WATER
lon_cells = NUM_LON_CELLS_WATER
core_id = cell_id - TOTAL_LAND_CELLS

lat_i = core_id // lon_cells
lon_i = core_id % lon_cells

lat = (lat_i * grid) / 1e6 - 90 + grid / (2 * 1e6)
lon = (lon_i * grid) / 1e6 - 180 + grid / (2 * 1e6)
return lat, lon

def _decode_legacy(cell_id: int) ->  Tuple[float, float]:
"""Decode a legacy ID using the 10¹² prefix trick."""
prefix = cell_id // LEGACY_SPLIT
core_id = cell_id % LEGACY_SPLIT

if prefix not in (0, 1):
raise ValueError

grid = GRID_SIZE_LAND if prefix == 0 else GRID_SIZE_WATER
lon_cells = NUM_LON_CELLS_LAND if prefix == 0 else NUM_LON_CELLS_WATER

lat_i = core_id // lon_cells
lon_i = core_id % lon_cells

lat = (lat_i * grid) / 1e6 - 90 + grid / (2 * 1e6)
lon = (lon_i * grid) / 1e6 - 180 + grid / (2 * 1e6)
return lat, lon

def decode(words: List[str]) -> Tuple[float, float]:
"""Decode four words to (lat, lon)."""
try:
digits = [WORD_TO_INDEX[w] for w in words]
except KeyError as e:
raise ValueError(f"Unknown word in code: {e.args[0]}") from None

cell_id = 0
for d in digits:
cell_id = cell_id * BASE + d

lat, lon = _decode_current(cell_id)

if lat < -89.82:  # likely bogus, near South Pole
try:
lat, lon = _decode_legacy(cell_id)
except ValueError:
pass

return lat, lon

# ------------------------------------------------------------------------------
# UTILITIES
# ------------------------------------------------------------------------------

def format_words(words: List[str]) -> str:
return ".".join(words)

def parse_words(code: str) -> List[str]:
return code.lower().strip().split(".")

def resolve_input(query: str):
query = query.strip()

if "." in query and len(query.split(".")) == 4:
return "decode", query.lower().split(".")

try:
lat, lon = map(float, query.split(","))
return "encode", (lat, lon)
except:
pass

location = geolocator.geocode(query)
if location:
return "encode", (location.latitude, location.longitude)

raise ValueError("Input could not be recognized.")`
Die Ausgabe
Die Funktion codode () gibt eine Liste von vier Wörtern zurück, basierend auf einem berechneten cell_id . Wenn ich diese vier Wörter jedoch mit Decode () dekodieren, unterscheiden sich die resultierenden (lat, lon) Koordinaten oft signifikant von den ursprünglichen -, manchmal um mehrere Kilometer oder mehr. /> Ich wende die Wortliste ein und erstelle ein sauberes Wort → Index Mapping. /> [*] testete sowohl das Legacy- als auch die aktuelle Dekodierungslogik: < /strong>
für IDs behandle ich sie als aktuelles Format; Andere greifen auf die Legacy Decodes Logic zurück. Noch kein Erfolg. /> Off-by-One-Fehler in der Gittermathematik < /li>
Basisumwandlung Fehlausrichtung (MSB /LSB-Bestellung, Überlauf) < /li>
Word-Index-Order-Ausgabe < /li>
< /ul>
< /li>
< /li>
< /ul>
Fragen < /h3>

Gibt es offensichtlich etwas nicht, wie ich cell_id < /code> → Wörter und zurück-Rücken umwandeln kann. Land/Wasser aufgeteilt, ohne die cell_id math?
Ist Decode () stillschweigend fehlschlagen und eine "Fallback" -Koordinate ohne Werfen? PrettyPrint-Override ">

Code: Select all

lat, lon = 48.8584, 2.2945
words = encode(lat, lon)
decoded = decode(words)
print(f"Original: {lat}, {lon} → Encoded: {format_words(words)} → Decoded: {decoded}")
Wenn der dekodierte Ort nicht nur wenige Meter vom Original entfernt ist, bricht etwas zusammen.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post