MarcoXL commited on
Commit
5407eb3
·
1 Parent(s): d5769e5

parallel street-view fetch; thread-local ro connections

Browse files
Files changed (1) hide show
  1. app.py +36 -13
app.py CHANGED
@@ -262,28 +262,51 @@ def render(scene_id: str, show_road_path: bool) -> Tuple[Optional[Image.Image],
262
 
263
 
264
  def node_gallery(scene_id: str) -> List[Tuple[str, str]]:
 
 
 
 
 
265
  det = load_scene(scene_id)
266
  if det is None:
267
  return []
268
- out = []
269
  city = det["scene"]["city"]
270
  folder = PACKAGE / "ground" / city
271
- for n in det["nodes"]:
 
272
  cap = (f"{n['label']} · {n['corridor_name'] or '无走廊'}"
273
  + (" · 孤儿" if n["is_orphan"] else ""))
274
- # 街景文件名带朝向,本地包直接 glob;数据集模式下朝向未知,
275
- # 逐个试常见朝向取第一张命中的
276
  if folder.is_dir():
277
- hits = sorted(folder.glob(f"{city},{n['panoid']},*.webp"))
278
  if hits:
279
- out.append((str(hits[0]), cap))
280
- continue
281
  rel = ground_rel(n)
282
- if rel:
283
- p = asset(rel)
284
- if p:
285
- out.append((str(p), cap))
286
- return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
 
289
  def ground_rel(node: Dict[str, Any]) -> Optional[str]:
@@ -292,7 +315,7 @@ def ground_rel(node: Dict[str, Any]) -> Optional[str]:
292
  打包时写了一张 pano -> 文件名 的索引,因为文件名里有 alt/year/heading
293
  三个字段是数据库里没有的,猜不出来。
294
  """
295
- row = con().execute(
296
  "SELECT rel FROM ground_index WHERE panoid = ? LIMIT 1",
297
  (node["panoid"],)).fetchone()
298
  return row[0] if row else None
 
262
 
263
 
264
  def node_gallery(scene_id: str) -> List[Tuple[str, str]]:
265
+ """取本场景每个节点的一张街景。
266
+
267
+ 数据集模式下每张图都要走一次 CDN,串行拉 38 张要等半分钟。
268
+ 并行拉——单张仍是那个延迟,但总时长压到接近单张。
269
+ """
270
  det = load_scene(scene_id)
271
  if det is None:
272
  return []
 
273
  city = det["scene"]["city"]
274
  folder = PACKAGE / "ground" / city
275
+
276
+ def fetch(n: Dict[str, Any]) -> Optional[Tuple[str, str]]:
277
  cap = (f"{n['label']} · {n['corridor_name'] or '无走廊'}"
278
  + (" · 孤儿" if n["is_orphan"] else ""))
 
 
279
  if folder.is_dir():
280
+ hits = sorted(folder.rglob(f"{city},{n['panoid']},*.webp"))
281
  if hits:
282
+ return (str(hits[0]), cap)
 
283
  rel = ground_rel(n)
284
+ if not rel:
285
+ return None
286
+ p = asset(rel)
287
+ return (str(p), cap) if p else None
288
+
289
+ from concurrent.futures import ThreadPoolExecutor
290
+ with ThreadPoolExecutor(max_workers=12) as ex:
291
+ got = list(ex.map(fetch, det["nodes"]))
292
+ return [g for g in got if g]
293
+
294
+
295
+ _TLS = __import__("threading").local()
296
+
297
+
298
+ def ro_con() -> sqlite3.Connection:
299
+ """每个线程一个只读连接。
300
+
301
+ sqlite3 的连接默认不允许跨线程用,而街景是并行拉的——共用一个连接
302
+ 会抛 ProgrammingError。
303
+ """
304
+ c = getattr(_TLS, "con", None)
305
+ if c is None:
306
+ c = sqlite3.connect(f"file:{DB}?mode=ro", uri=True)
307
+ c.row_factory = sqlite3.Row
308
+ _TLS.con = c
309
+ return c
310
 
311
 
312
  def ground_rel(node: Dict[str, Any]) -> Optional[str]:
 
315
  打包时写了一张 pano -> 文件名 的索引,因为文件名里有 alt/year/heading
316
  三个字段是数据库里没有的,猜不出来。
317
  """
318
+ row = ro_con().execute(
319
  "SELECT rel FROM ground_index WHERE panoid = ? LIMIT 1",
320
  (node["panoid"],)).fetchone()
321
  return row[0] if row else None