bd1 / utils /click.py
hoangrimo's picture
Upload folder using huggingface_hub
92a8b49 verified
Raw
History Blame Contribute Delete
2.46 kB
# utils/click.py — Click detection: nearest leg, nearest city, coordinate extraction
import math
from typing import Optional, Tuple
import gradio as gr
from config import get_style, DEFAULT_STYLE
from core.geometry import control_point, sample_curve
from models.city import DB
def _extract_xy(evt: gr.SelectData) -> Tuple[Optional[float], Optional[float], Optional[any]]:
"""Extract (x, y, size) in base image pixels from Gradio click event."""
if evt is None:
return None, None, None
x = getattr(evt, "x", None)
y = getattr(evt, "y", None)
size = getattr(evt, "size", None)
if x is not None and y is not None:
return float(x), float(y), size
idx = getattr(evt, "index", None)
if isinstance(idx, (list, tuple)) and len(idx) >= 2:
return float(idx[0]), float(idx[1]), size
val = getattr(evt, "value", None)
if isinstance(val, dict) and ("x" in val) and ("y" in val):
w = val.get("width")
h = val.get("height")
if (w is None or h is None) and isinstance(val.get("image"), dict):
w = val["image"].get("width")
h = val["image"].get("height")
return float(val["x"]), float(val["y"]), (w, h)
return None, None, None
def _nearest_leg_on_click(x, y, legs, to_xy, bulge_overrides=None, n=220):
best = None
_default_bulge = get_style(DEFAULT_STYLE).curve_bulge
for idx, e in enumerate(legs or []):
a, b = e.get("a"), e.get("b")
if a not in DB.by_name or b not in DB.by_name:
continue
bulge = float((bulge_overrides or {}).get((a, b), _default_bulge))
p0 = to_xy(a)
p2 = to_xy(b)
pc = control_point(p0, p2, bulge)
pts = sample_curve(p0, pc, p2, n=n)
best_d = 1e18
best_i = 0
for i, (xx, yy) in enumerate(pts):
d = (xx - x) ** 2 + (yy - y) ** 2
if d < best_d:
best_d = d
best_i = i
d_px = math.sqrt(best_d)
t = best_i / (n - 1)
if (best is None) or (d_px < best[0]):
best = (d_px, idx, t)
return best
def _nearest_city_on_click(x, y, to_xy, city_names):
best_nm, best_d = None, 1e18
for nm in city_names:
cx, cy = to_xy(nm)
d = math.hypot(x - cx, y - cy)
if d < best_d:
best_d, best_nm = d, nm
return best_nm, best_d