专题显示区改为一组圆(后端与查询层)

把专题的「一个圆」换成「一组圆」(areas jsonb 数组):落在任一圆内即算在
区域内(SQL 里的 OR)。这一批只动后端与查询层,前台渲染与后台地图编辑器
分别跟进;后台表单暂时沿用原来的三个坐标输入框,保存时合成一个圆写进
areas,所以现有交互不受影响。

- topics.areas JSONB + 存量回填:老的单圆搬进去,之后 areas 是唯一权威。
  废弃的 center_lat/center_lon/radius_km 保留(写入时镜像第一个圆),
  一是回滚旧二进制时还能退化显示成第一个圆,二是回填的输入。
- Topic.AreaList() 归一:Areas 为空时退回老的三列,未回填的老行与直接构造
  Topic 的调用方都继续工作。
- topicAreaCond 改成 N 个圆的 OR;每个圆占 3 个占位符,编号纪律照旧
  (写错就是「专题内容全变 0」那种难查的事故)。
- fitParams 改用所有圆的并集外接矩形:多圆之后「圆心+半径」表达不了,
  统一走 fitBBox;单圆时外接矩形就是这个圆的外接正方形,与原路径等价。
- 坐标系:编辑器提交的圆心若是 WGS-84 底图上点的,存前换算成 GCJ-02
  (地点过滤要拿它跟 places 的 GCJ-02 坐标比距离)。

测试:
- 表单解析(两个入口同一套校验)、wgs84 换算、半径为 0/空 = 不限区域、
  坏 JSON/越界必须报错、上限 20 个。
- 占位符纪律:本段引用的 $n 必须恰好是 [prefix+1, len(args)] 连续区间,
  最大值必须等于参数个数。
- 多圆并集语义(DB 门控):两圆专题的地点集合必须恰好等于两个单圆专题的
  并集 —— 定义性不变量,变异验证过(只认第一个圆 ⇒ 两个用例同时红)。
This commit is contained in:
tamakyi
2026-10-12 16:29:46 +08:00
parent cc37c9d1c9
commit 1bb35dbbc9
5 changed files with 725 additions and 39 deletions
+17 -1
View File
@@ -383,7 +383,7 @@ BEGIN
END $$;
-- 专题:把某段时间内、某个区域里的足迹(地点 + 迷雾)打包成一个可对外展示的页面。
-- 区域用「中心点 + 半径」,半径为 0 表示不限区域(时间范围内的地点画到哪算哪)。
-- 「区域」是**一组圆**(areas,见下),空数组表示不限区域(时间范围内的地点画到哪算哪)。
--
-- ⚠️ dataset_id **故意不带外键**(早期版本带 ON DELETE CASCADE)。
-- 专题是「一段时间 + 一块区域」的**定义**,不是备份里的数据:换数据集之后它照旧成立
@@ -409,6 +409,22 @@ CREATE TABLE IF NOT EXISTS topics (
);
CREATE INDEX IF NOT EXISTS idx_topics_user ON topics(user_id, sort_order, id);
-- 专题的显示区:**一组圆**,jsonb 数组,元素形如 {"lat":..,"lon":..,"radiusKm":..}。
-- 坐标是 GCJ-02(与 places 同系);前台由 rond-map.js 的 project() 换算到底图坐标系。
-- 落在**任一**圆内就算在区域内(并集)——地点过滤是 SQL 里的 OR,迷雾裁剪是 clip-path: path()
-- 的多段子路径(同绕向 ⇒ nonzero 填充规则下自然取并集)。
--
-- 为什么用 jsonb 而不是单开一张表:这些圆是专题定义的组成部分、跟专题一起读写、没有独立
-- 生命周期,也就免了「能不能从备份重导」那道归属口径(topics 本来就只归人、不挂数据集)。
--
-- ⚠️ center_lat / center_lon / radius_km 三列**已废弃**(早期只支持一个圆),保留只为两件事:
-- 一是回滚旧二进制时还能退化显示成「第一个圆」,二是下面这段存量回填的输入。
-- 新代码一律只读 areas;写入时把第一个圆镜像进这三列。
ALTER TABLE topics ADD COLUMN IF NOT EXISTS areas JSONB NOT NULL DEFAULT '[]'::jsonb;
UPDATE topics SET areas = jsonb_build_array(
jsonb_build_object('lat', center_lat, 'lon', center_lon, 'radiusKm', radius_km))
WHERE radius_km > 0 AND areas = '[]'::jsonb;
-- fog of world 快照里「非已探索层」的原始瓦片文件(Model/~ 与 Model/#)。
-- 站点只用已探索层渲染,但导出必须原样写回这两层,否则重导出的快照会丢掉约 55% 的内容。