03-camera-contract-composition-and-entry-state.md 8.7 KB

限位与既有相机契约的合成 + 进出状态机

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=推荐。

  1. range_max 最终数值(R2-1):range_max = 12,000 m,精确等于 home.range —— 归位即最远视野,再往外滚轮即夹。isAtHome 的 2% 相对容差(240 m)足够识别"已归位"。
  2. 软回弹参数(R2-2):软区 = 框短边(N-S 11,008 m)的 5% ≈ 550 m,可微调;松手回弹,不持续回弹。
  3. 返回全球目标(R2-3):程序初始态全景(heading 0 / pitch −60 / range 20,000,000)。
  4. 状态与计时器落点(R2-4):areaState: 'locked' | 'global' 进 filterStore(与 viewMode 同层——全局视图条件,切一级模式不重置);mapService 负责状态转移(进入/返回/归位);cameraControl 按状态换 limits(新增 setRangeLimits 一类,与既有 setPitchLimits 对称);5 秒闲置计时器与引导页显隐归 CockpitShell(组件内或 uiStore),只在 global 态计时、任何交互即重置、不重置 mode/筛选。map.intro.enabled=false(其它票走查自隔离)时按 global 自由视角启动、不弹引导页。
  5. 顶栏按钮(R2-5):区内显示「归位」+「返回全球」两个 chip(归位沿用现有);区外只显示一个「归位/进入」chip。
  6. 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。