mapfix-spatial / app.py
Arun0808's picture
Add deterministic coordinate Space demo
6f1f64c
Raw
History Blame Contribute Delete
3.39 kB
"""CPU-safe Gradio Space for MapFix-Spatial coordinate correction.
The public Space exposes the deterministic correction path so the demo remains
available without API keys or browser-only map services.
"""
from __future__ import annotations
import math
import gradio as gr
def correct(coords: str, projection: str):
lat, lon = _parse_lat_lon(coords)
corrected_lat = lat + 0.00018 * math.cos(math.radians(lat))
corrected_lon = lon - 0.00022 * math.cos(math.radians(lon))
delta_m = (
((corrected_lat - lat) * 111_000) ** 2
+ ((corrected_lon - lon) * 85_000) ** 2
) ** 0.5
lines = [
"MapFix-Spatial CPU-safe correction demo",
f"input lat/lon: ({lat:.7f}, {lon:.7f})",
f"corrected lat/lon: ({corrected_lat:.7f}, {corrected_lon:.7f})",
f"estimated shift: {delta_m:.2f} m",
f"target projection: {projection}",
]
if projection in {"EPSG:3857", "Web Mercator"}:
x, y = _to_web_mercator(corrected_lat, corrected_lon)
lines.append(f"web mercator: x={x:.2f}, y={y:.2f}")
elif projection == "Local UTM":
zone = int((corrected_lon + 180) / 6) + 1
lines.append(f"local UTM proxy: zone={zone}, easting/northing computed in browser demo")
stats = (
"engine=deterministic CPU fallback\n"
"api_keys_required=false\n"
"full_demo=https://arunshar.github.io/mapfix-spatial/\n"
"correction_model=lat/lon harmonic bias proxy"
)
return "\n".join(lines), stats
def _parse_lat_lon(coords: str) -> tuple[float, float]:
cleaned = coords
for char in "[](){}":
cleaned = cleaned.replace(char, "")
parts = [part.strip() for part in cleaned.replace(";", ",").split(",") if part.strip()]
if len(parts) < 2:
raise gr.Error("Enter coordinates as 'lat,lon'.")
try:
lat = float(parts[0])
lon = float(parts[1])
except ValueError as exc:
raise gr.Error("Latitude and longitude must be numeric.") from exc
if not (-90 <= lat <= 90 and -180 <= lon <= 180):
raise gr.Error("Latitude must be in [-90, 90] and longitude in [-180, 180].")
return lat, lon
def _to_web_mercator(lat: float, lon: float) -> tuple[float, float]:
clipped_lat = max(min(lat, 85.05112878), -85.05112878)
x = lon * 20037508.34 / 180
y = math.log(math.tan((90 + clipped_lat) * math.pi / 360)) / (math.pi / 180)
y = y * 20037508.34 / 180
return x, y
def build_ui():
with gr.Blocks(title="MapFix-Spatial") as demo:
gr.Markdown(
"# MapFix-Spatial\n"
"CPU-safe deterministic geospatial correction demo. The full interactive browser workflow is "
"available at arunshar.github.io/mapfix-spatial."
)
with gr.Row():
coords = gr.Textbox(label="Coordinates ('lat,lon' or list)", value="44.97,-93.27")
proj = gr.Dropdown(["EPSG:4326", "EPSG:3857", "Web Mercator", "Local UTM"], label="Target projection", value="EPSG:4326")
run = gr.Button("Correct", variant="primary")
with gr.Row():
out = gr.Textbox(label="Corrected coordinates", lines=8)
stats = gr.Textbox(label="Run stats", lines=3)
run.click(correct, [coords, proj], [out, stats])
return demo
if __name__ == "__main__":
build_ui().launch(server_name="0.0.0.0")