# 限位与既有相机契约的合成 + 进出状态机 Type: grilling Status: resolved Labels: wayfinder:grilling Blocked by: 01,02 ## 进度:100% 已收口(2026-09-18 维护者确认)。Q1–Q5 与 R2-1…R2-6 全部裁定并落 `## Answer`;ADR 0009 已按 R2-6 创建、ADR 0008 已补指向行;map Decisions-so-far 已同步。**03 取代 02 的 `range_max` 锚点(2,542 m → 12,000 m)**,平行图 `cockpit-point-locate-and-device-link/issues/03` 已记跨图提示。 ## Question 区域限位要落在**既有**相机契约的哪一层,进/出主场景区的**状态机**如何与视图模式、票 30 的 home 预设共存? 现状(`domain/camera.js` + `domain/viewModes.js`): - `RANGE_LIMITS = { min: 120, max: 30000000 }` —— **全局常数**,上限覆盖全球视角。 - `PITCH_LIMITS` 按**视图模式**分:`ground {min:−85,max:−5}` / `pipeline {min:−85,max:+5}`。 - 管线视图把 range 压到 400–6,000 m、pitch 放宽到允许平视。 - 票 30 的 home 预设 `pitch −55, range 12000`,已验收("12 km 是县域级")。 - ADR 0008 锁死三键分工与阻尼,且"管线视图不重置旋转中心、不新增第二套鼠标绑定"。 ## Answer ### 已确认决策:第 1 轮(Q1–Q5) 维护者答复:`Q1=d; Q2=a(含闲置回初始态); Q3=a; Q4=c(软回弹,软区 5%); Q5=a+b`。编号为本票访谈编号。 1. **限位锚点(Q1=d)**:**最远视野 = 归位默认视角** —— `range_max = home.range = 12,000 m`(pitch 沿用 home 的 −55,不单独收紧)。home 预设**不改**。02 的 `range_max = 1651 / (2·tan(fovY/2))`(≈2,542 m)与"15% 垂直覆盖预算"**被本票取代**,不再作为限位基准(该预算的数值不再约束相机;雾的"遮缝半径"另由 07 以本票口径重新对齐)。 2. **进出状态机(Q2=a)**:显式模式锁 —— 点「进入系统」/「归位」进区并锁定;**只有「返回全球」能解除**。判定与相机位置无关,不随跨界自动切换(避免贴边抖动)。**全球态闲置 5 秒未操作 → 回到程序初始态**:地球自转恢复 + 屏幕中央闪烁「点击进入系统」。 3. **与管线视图合成(Q3=a)**:取交集。区内管线视图 `range ∈ [400, min(6000, range_max)] = [400, 6,000]` —— 因 `range_max = 12,000 > 6,000`,**区内管线视图与现状完全一致,无额外收紧**;pitch 上下限沿用视图模式(区域不收紧 pitch,02 已定)。 4. **边界行为(Q4=c 软回弹)**:拖拽时 `target.pivot` 允许越出 `primaryArea.bounds` 最多一个**软区(框短边的 5%,≈550 m,可微调)**;越界部分在**松手时按既有阻尼弹回**框内(不是拖拽中持续回弹)。`shown` 始终由阻尼跟随 `target`。断言口径:`shown.pivot` 最终回到框内;越界只出现在拖拽过程。 5. **返回全球语义(Q5=a+b)**:解除限位 + 阻尼飞到**程序初始态的全景**(heading 0 / pitch −60 / range 20,000,000,即引导页开始时的星球视角)+ 之后完全自由;**全球态闲置 5 秒 → 重新回到引导页**(星球自转 + 「点击进入系统」),**不重置一级模式/筛选**;顶栏按钮在区外自动变回「归位/进入」。 ### 已确认决策:第 2 轮(R2-1…R2-6) 维护者答复:`R2-1=推荐; R2-2=推荐(软区 5%); R2-3=推荐; R2-4=推荐; R2-5=推荐; R2-6=推荐`。 6. **`range_max` 最终数值(R2-1)**:`range_max = 12,000 m`,精确等于 `home.range` —— 归位即最远视野,再往外滚轮即夹。`isAtHome` 的 2% 相对容差(240 m)足够识别"已归位"。 7. **软回弹参数(R2-2)**:软区 = 框短边(N-S 11,008 m)的 **5% ≈ 550 m**,可微调;松手回弹,不持续回弹。 8. **返回全球目标(R2-3)**:程序初始态全景(heading 0 / pitch −60 / range 20,000,000)。 9. **状态与计时器落点(R2-4)**:`areaState: 'locked' | 'global'` 进 **`filterStore`**(与 `viewMode` 同层——全局视图条件,切一级模式不重置);`mapService` 负责状态转移(进入/返回/归位);`cameraControl` 按状态换 limits(新增 `setRangeLimits` 一类,与既有 `setPitchLimits` 对称);**5 秒闲置计时器与引导页显隐归 `CockpitShell`**(组件内或 `uiStore`),只在 `global` 态计时、任何交互即重置、**不重置** `mode`/筛选。`map.intro.enabled=false`(其它票走查自隔离)时按 `global` 自由视角启动、不弹引导页。 10. **顶栏按钮(R2-5)**:区内显示「归位」+「返回全球」两个 chip(归位沿用现有);区外只显示一个「归位/进入」chip。 11. **ADR 归属(R2-6)**:新建 **ADR 0009「主场景区的相机限位与进出状态机」**,记录第 1–2 轮结论;ADR 0008 补一行指向 ADR 0009。 ### 防入地(继承 02,机制落本票) - 相机离地高度 `h = range·sin|pitch|`;每次输入(滚轮/轨道)时取相机正下方地形(`globe.getHeight`),若 `h < 地形 + 10 m` 则**夹 range**(不夹 pitch、不动 pivot);瓦片未加载时退回固定 10 m 绝对下限。 - 与区域限位的合成:输入时 `range` 同时被 `[120, range_max]`、管线视图 `[400, 6000]`、防入地下限三处夹取,最终生效 = 三者交集(防入地是下限侧,与 120/400 取 max;range_max 是上限侧)。 ### 边界(本票不裁决) - 雾的曲线、配色、门控 —— 归 07(以本票的 `areaState` 与 `range_max` 为输入契约)。 - 低精度→高精度过渡手段 —— 归 08(以本票的进出状态机为输入契约)。 - 中心点 `height` 口径、`setFocus`(选中只换中心)—— 既有票 03/04/30 已锁,本票不重复。 - 平行图 `cockpit-point-locate-and-device-link` 的镜头定位 —— 其上限受 `range_max = 12,000` 约束;其票 03 的 fact-check 引用 02 的 `1651/(2·tan(fovY/2))` 公式,**需以本票取代**(落盘时在该图相关票面记一行)。 ## Comments ### 2026-09-18 第 1 轮:fact-check 与 frontier 发出 事实核实(只读复核,均在本仓或同 effort 票面内): 1. `domain/camera.js`:`RANGE_LIMITS = { min: 120, max: 30000000 }` 是唯一全局常量;域层只有 `{heading, pitch, range}`,无「相机离地高度 h」这个量(`h ≈ range·sin|pitch|`,pivot 已由票 30 地形感知)。 2. clamp 只在输入时生效(`zoomByWheel` / `setHpr` / `applyViewPreset`),无逐帧主动回拉 —— 因此若进区后 range 仍为 12000,第一次滚轮内滚会从 12000 一次夹到 ~2542(4.7× 突跳),这是 Q1 冲突的具体危害。 3. 管线视图 `PIPELINE_CAMERA`:pitch −18、range 压到 35% 并夹 [400, 6,000];`viewHprFor` 只动 pitch 与 range,heading 与中心原样带走。 4. 进入/归位同走 `mapService.goHome()` → `cameraControl.applyViewPreset()`;引导 `CockpitIntro` `@enter="enterSystem"` → 停自转 + `goHome`。无「返回全球」现有按钮。 5. `filterStore` 已持 `viewMode`(ground/pipeline)作"全局视图条件"先例;`uiStore` 只管 mode/面板。 6. 平行图 `cockpit-point-locate-and-device-link` 的 03(镜头定位)claimed,fact-check 引用本 effort 02 的 `1651/(2·tan(fovY/2))`;其 Notes 明确"镜头定位必须与 .scratch/cockpit-primary-area-guardrails 的限位数值契约(02 resolved)与其进出状态机(03 open)合成"。 7. `CONTEXT.md` 已收录「主场景区」词条(未提交)。 第 1 轮五问已发维护者:Q1 home 预设冲突 / Q2 进出判定与状态机 / Q3 管线合成 / Q4 边界行为 / Q5 返回全球语义。 ### 2026-09-18 第 2 轮:Q1–Q5 落盘,R2-1…R2-6 发出 维护者答复:`Q1=d(以归位默认视角为参考); Q2=a(且全球态闲置 5 秒回初始态); Q3=a; Q4=c(软回弹); Q5=a+b(先飞出,闲置 5 秒回引导页,不重置模式/筛选,顶栏区外变回归位/进入)`。已写入 `## Answer` 第 1 轮。 Q1=d 连锁:`range_max` 锚点从 02 的 `1651/(2·tan(fovY/2))`(≈2,542 m)改为 **home.range = 12,000 m**;02 的"15% 垂直覆盖预算"不再作为限位基准;Q3 的管线合成冲突因 `min(6000, 12000)=6000` 自动消解。 第 2 轮六问已发:R2-1 数值 / R2-2 软区参数 / R2-3 返回全球目标 / R2-4 状态落点 / R2-5 顶栏形态 / R2-6 ADR。 ### 2026-09-18 第 3 轮:R2 全部落盘 维护者答复:`R2-1=推荐; R2-2=推荐(软区 5%); R2-3=推荐; R2-4=推荐; R2-5=推荐; R2-6=推荐`。已写入 `## Answer` 第 2 轮;软区定为框短边 5%(≈550 m)。 剩余动作:等维护者确认最终 Answer 全文与 ADR 0009 内容后收口 resolved;同步 map Decisions-so-far;向平行图 `cockpit-point-locate-and-device-link` 相关票面记"以 03 为准,02 的 range_max 锚点已取代";随后提醒 `/to-spec`。