发布时间:2026/8/29 16:57:34
【天体运行模拟|02】HarmonyOS ArkTS 引力参数实战:校验质量、距离与速度输入边界 轨道页面最危险的参数往往不是用户明显输错的字符而是“看起来合法、进入计算后却把系统推向极端”的数值质量接近零会让对象失去预期影响质量过大会让近距离加速度骤增半径过大会导致刚放置就碰撞初速度过高会让天体一帧飞出画布距离接近零则可能让平方反比公式产生数值爆炸。“天体运行模拟”没有开放自由文本输入而是使用 ArkUISlider约束质量、半径、初速度、方向和轨道倾角。这个选择已经挡住了大量非法输入但仅靠控件范围还不够参数还会经过状态数组、天体创建、引力计算、碰撞判定和结果展示。任何一层都可能成为新的调用入口。因此可靠的参数链需要三道边界UI 负责给出可操作范围模型入口负责归一化引力计算负责防御近距离奇点。本文基于真实源码ExperimentSimPage.ets与FormulaPage.ets逐项复核当前边界并给出不夸大现有能力的增强方案。应用包名为com.jiaweikan.one13面向 HarmonyOS 5.0 及以上的 phone、tablet 和 2in1。唯一复核标记GRAVITY-ONE13-PARAM-BOUNDARY-20260726控件限制可选范围模型入口归一化参数物理内核防御零距离。一、先区分公式知识与模拟单位应用的“引力速查”页展示了万有引力、圆轨道速度、逃逸速度、动能、引力势能与质心等公式State formulas: FormulaItem[] [ { name: 万有引力, formula: F GMm / r², description: 两个天体之间的吸引力随质量增大而增大随距离平方减小。, category: 引力 }, { name: 圆轨道速度, formula: v √(GM / r), description: 速度过低会坠落速度过高会形成椭圆或逃逸。, category: 轨道 }, { name: 逃逸速度, formula: vₑ √(2GM / r), description: 达到该速度后天体可离开中心天体引力束缚。, category: 轨道 } ]这些公式承担知识解释模拟页面则采用归一化单位质量单位显示为M速度显示为v半径和位置使用 Canvas 像素引力常量在代码中取0.028。二者的关系是“概念对应”不是直接把 SI 单位代入。页面概念模拟中的表示不应作出的承诺质量204000 M不是千克或太阳质量半径432 px不是天体真实半径初速度04 v不是 km/s距离Canvas 坐标差不是 AU 或 km引力常量g 0.028不是物理常数 G 的原值先明确单位边界参数校验才不会变成“拿真实天文范围限制屏幕演示”。这是一套教学模拟参数而不是星历输入表。二、当前参数定义已经形成第一道约束页面使用ExperimentParam[]描述五个可调参数State paramDefs: ExperimentParam[] [ { name: 质量, unit: M, min: 20, max: 4000, defaultValue: 420, step: 10 }, { name: 半径, unit: px, min: 4, max: 32, defaultValue: 13, step: 1 }, { name: 初速度, unit: v, min: 0, max: 4, defaultValue: 1.4, step: 0.05 }, { name: 方向, unit: °, min: 0, max: 360, defaultValue: 0, step: 5 }, { name: 轨道倾角, unit: °, min: -60, max: 60, defaultValue: 0, step: 5 } ]这组元数据同时驱动标签、数值显示和 Slider 范围避免界面写一套范围、业务逻辑再维护另一套文案。当前默认值也位于各自区间内State paramValues: number[] [420, 13, 1.4, 0, 0]从工程维护角度看仍有一个潜在错位点默认值同时存在于paramDefs.defaultValue和paramValues。如果以后只修改其中一处首次显示和回退值可能不一致。更稳的初始化方式是从定义生成状态private initialParamValues(): number[] { return this.paramDefs.map( (param: ExperimentParam) param.defaultValue ) }这段是建议的增强写法当前源码尚未这样初始化。文章把“现有约束”和“可演进方案”分开避免把计划当成已实现能力。三、Slider 限制的是交互路径不是所有数据入口ArkUISlider直接使用参数定义中的min、max与stepSlider({ value: this.paramValues[index], min: param.min, max: param.max, step: param.step, style: SliderStyle.OutSet }) .onChange((value: number) { this.paramValues[index] Math.round(value * 100) / 100 this.paramValues [...this.paramValues] })用户沿正常界面操作时Slider 会把值限制在定义范围内步长也能阻止大部分无意义的小数。Math.round(value * 100) / 100又把浮点显示控制到两位特别适合步长为0.05的初速度。但 Slider 不是模型校验器。以下场景仍可能绕过它将来增加文本输入、导入配置或恢复历史场景。测试代码直接写入paramValues。数组索引与paramDefs顺序发生错位。路由参数或持久化数据被用于初始化参数。undefined、NaN或无穷值进入状态。因此第一道边界可以放在控件第二道边界必须靠近addSelectedBody()。越靠近天体创建入口越能覆盖未来新增的数据来源。四、质量边界为什么是 204000 M质量直接进入引力加速度计算。源码先根据两个天体间距离计算方向和反比项再乘以另一个天体的质量const dx b.x - a.x const dy b.y - a.y const distSq Math.max(dx * dx dy * dy, 90) const dist Math.sqrt(distSq) const force g / distSq ax[i] force * b.mass * dx / dist ay[i] force * b.mass * dy / dist ax[j] - force * a.mass * dx / dist ay[j] - force * a.mass * dy / dist当b.mass增大时a的加速度线性增大。质量若没有上限即使距离有软化单步速度变化仍可能过大。当前上限 4000 M 与页面预置黑洞的 2600 M 处于同一量级给用户保留更强引力体验同时没有开放任意大数。质量下限 20 M 也不是装饰。若允许零质量其他天体不会受到它的引力影响但它仍可能被引力拉动、参与碰撞与显示教学语义会变得混乱。若允许负质量方向甚至会出现与界面概念不符的行为。Slider 目前避免了这些值。创建天体时源码使用空值合并作为最后回退this.paramValues[0] ?? 200需要注意??只处理null和undefined不会拦截NaN、Infinity、负数或超大值。因此如果未来参数来源不再只有 Slider应增加数值归一化。五、半径既影响视觉也影响碰撞时机半径范围为 432 px。它不仅决定圆的大小还参与碰撞阈值if (dist (a.radius b.radius) * 0.78) { this.mergeBodies(i, j) }这意味着半径校验不能只按“是否画得下”判断。半径越大两个天体越早合并若半径大于生成距离的一半新天体可能在第一轮计算中立刻与中心天体碰撞。当前生成半径为const spawnRadius 92 (this.nextBodyId % 4) * 18也就是约 92146 px。用户可选半径最大为 32 px与常见中心天体半径相加后仍明显小于出生距离给第一帧保留了活动空间。这说明参数上限与场景几何不是孤立设计的。合并后视觉半径按面积近似累加并限制为 34primary.radius Math.min( 34, Math.sqrt( primary.radius * primary.radius other.radius * other.radius ) )即使质量持续累积圆形也不会无限变大遮住整个画布。这里是“输入边界”和“运行边界”配合的典型例子。六、初速度范围决定坠落、椭圆与逃逸的观察窗口初速度 Slider 的范围是 04 v步长为 0.05。创建天体时速度被转换为切向分量const angle (this.paramValues[3] ?? 0) * Math.PI / 180 const speed this.paramValues[2] ?? 0 const vx -Math.sin(angle) * speed const vy Math.cos(angle) * speed当角度为 0° 时天体位于中心右侧初速度沿正 Y 方向角度变化时位置和速度一起旋转。由于速度方向与半径方向垂直用户更容易观察低速坠落、中速绕行和高速逃逸。速度上限的价值体现在越界清理条件if ( body.x -200 || body.x this.canvasCenterX() * 2 200 || body.y -200 || body.y this.canvasCenterY() * 2 200 ) { body.alive false }高速度对象可以离开画布但不会永远保留在数组中继续参与O(n²)的两两计算。输入上限控制一帧位移越界规则控制长期成本两者缺一不可。七、方向需要归一化360° 与 0° 应是同一状态当前 Slider 给出 0360°步长为 5°。三角函数天然会把 360° 映射回接近 0° 的方向但浮点结果可能存在极小误差。正常界面中这不会造成明显问题若以后支持输入任意角度建议先归一化private normalizeAngle(value: number): number { const wrapped value % 360 return wrapped 0 ? wrapped 360 : wrapped }归一化后-10°会变成350°725°会变成5°。它比简单截断到 0360 更符合“方向是周期量”的语义。当前direction的 UI 范围已经安全但模型层若接收历史记录或外部配置周期归一化仍然值得保留。八、轨道倾角在当前实现中是二维压缩系数源码把倾角限制在 -60°60°const tilt (this.paramValues[4] ?? 0) * Math.PI / 180 const y cy Math.sin(angle) * spawnRadius * Math.cos(tilt)倾角只作用于出生位置的 Y 方向缩放没有 Z 坐标也没有改变速度矢量。因此它表达的是二维画布上的轨道压缩效果不是三维轨道平面旋转。为什么不开放到 ±90°当接近 90° 时cos(tilt)接近零纵向出生偏移会被压扁多个角度可能落在接近同一水平线上增加重叠与立即碰撞概率。限制到 ±60°至少保留cos(60°)0.5的纵向尺度。这是产品参数边界应有的思路不是数学函数能接受什么就把什么全部开放给用户而是选择能稳定表达教学现象的区间。九、距离不能由用户直接输入但仍必须在物理层防御当前页面没有“距离”Slider。距离由画布中心、方向和spawnRadius间接决定也会在天体运动中不断变化。因为它是运行时派生量不能靠 UI 控件保证永远大于零。源码在物理内核中设置了距离平方下限const distSq Math.max( dx * dx dy * dy, 90 ) const dist Math.sqrt(distSq)即使两个中心坐标相同后续除法也不会除以零。这个90对应最小有效距离约9.49像素。它是一种数值软化并不代表真实天体半径或物理常数。防御零距离必须放在物理层因为碰撞判断发生在计算引力之后。如果只依赖“相交就合并”在进入合并逻辑前已经可能产生无穷大或NaN。十、建立统一归一化函数避免数组值直接进入模型现有 Slider 路径是受控的但为未来扩展准备时可以先定义一个小而明确的数值函数private clampFinite( value: number | undefined, min: number, max: number, fallback: number ): number { if (value undefined || !Number.isFinite(value)) { return fallback } return Math.max(min, Math.min(max, value)) }再在添加天体时逐项归一化private normalizedBodyParams(): number[] { const mass this.clampFinite( this.paramValues[0], 20, 4000, 420 ) const radius this.clampFinite( this.paramValues[1], 4, 32, 13 ) const speed this.clampFinite( this.paramValues[2], 0, 4, 1.4 ) const direction this.normalizeAngle( this.clampFinite( this.paramValues[3], 0, 360, 0 ) ) const tilt this.clampFinite( this.paramValues[4], -60, 60, 0 ) return [mass, radius, speed, direction, tilt] }这两段是建议方案不是当前工程已经存在的函数。它们解决四个具体风险拦截非有限数值。将范围规则集中到模型入口。为未来文本输入、导入和持久化恢复提供共同边界。让createBody()接收到的始终是可计算数值。更进一步可以用具名接口替代number[]消除索引错位interface BodyInput { mass: number radius: number speed: number directionDeg: number tiltDeg: number }这同样属于演进方向。当前源码使用数组是为了让ForEach与参数定义快速对应当参数来源变多时具名模型的收益才会明显超过简洁性。十一、步长校验与范围校验是两件事范围校验只保证值处于[min,max]步长校验则决定值是否落在可复现的离散点上。初速度步长是0.05质量步长是10方向步长是5。如果未来从文本恢复1.43 v它虽然在范围内却不是 Slider 能直接产生的值。可以按定义吸附到最近步长private snapToStep( value: number, min: number, step: number ): number { const ticks Math.round((value - min) / step) return min ticks * step }执行顺序建议是检查是否为有限数。截断到最小值与最大值。按步长吸附。根据步长小数位做最终舍入。如果先吸附再截断边界附近可能得到超范围点如果只用toFixed只能改变显示不能保证数值真正落到合法步长。十二、参数之间也存在组合约束单个字段都合法并不保证组合合理。例如最大质量 最小出生距离 最大时间倍率容易产生大步长加速。最大半径 接近中心的出生位置可能立即合并。最大速度 最大倍率可能在很少帧内越界。多个黑洞连续放置会快速扩大两两计算和合并频率。因此可以在“放置天体”前计算风险级别而不是把每个 Slider 独立看待private isHighRiskCombination(input: BodyInput): boolean { return ( input.mass 3000 input.speed 3.5 this.speed 2.5 ) }对教学应用更合适的响应通常不是禁止操作而是给出明确提示例如“高质量、高初速和高倍率组合可能快速逃逸”。当前页面没有这条组合提示不能声称已经实现但这是比任意收紧单个范围更友好的增强方向。十三、状态更新要保证 ArkUI 观察到数组变化Slider 回调先修改数组元素再创建新数组引用this.paramValues[index] Math.round(value * 100) / 100 this.paramValues [...this.paramValues]在 ArkUI 状态管理中只修改数组内部元素有时不足以让依赖它的 UI 明确更新。重新赋值让State观察到引用变化参数数值文本能够及时刷新。显示精度则依据步长决定Text( (this.paramValues[index] ?? param.defaultValue) .toFixed(param.step 1 ? 2 : 0) )质量、半径和角度显示整数初速度显示两位小数。这是显示层格式化不应反过来作为计算层校验。模型仍然应保存数值而不是从格式化字符串重新解析。十四、公式速查页的分类过滤保持纯函数边界FormulaPage通过选中分类过滤公式private filteredFormulas(): FormulaItem[] { const cat this.categories[this.selectedCategory] if (cat 全部) { return this.formulas } return this.formulas.filter( (formula: FormulaItem) formula.category cat ) }它只根据状态返回列表不修改公式内容。这个纯函数边界适合保留知识页负责解释概念模拟页负责约束交互参数二者不要共享一套未经转换的“真实单位”数值。若以后从公式页跳转到模拟页可以传递场景意图例如“观察逃逸速度”而不是直接传公式中的物理数值。模拟页再根据自己的单位体系生成安全默认参数。十五、面向 phone、tablet 与 2in1 的参数控件检查参数页本身使用纵向Scroll每个 Slider 宽度为100%适合不同窗口宽度。但多设备验证不应只看是否能显示还要检查可操作性phone 竖屏滑块是否容易精细选择0.05的速度步长。phone 横屏或小窗口参数标题和当前值是否仍在同一行可读。tablet滑轨变宽后步长感知是否过于稀疏。2in1鼠标点击轨道与拖动行为是否一致键盘焦点是否清晰。大字体单位、当前值和 Slider 是否发生遮挡。当前源码的标题行使用Blank()分隔名称与数值Slider 使用全宽布局具备基础伸缩能力。真正发布前仍要在目标窗口尺寸下操作而不是只看静态截图。十六、最小验证矩阵检查值、状态与运行结果质量测试值预期20可放置显示 20 M4000可放置运行仍可暂停小于 20非 Slider 来源应被截断或回退NaN模型入口拒绝或使用默认值半径测试值预期4可见且可参与碰撞32不应一放置就因错误坐标重叠0非 Slider 来源不得进入绘制极大值不得遮盖整个 Canvas初速度测试值预期0天体受引力后坠落或移动1.4默认场景可观察绕行4可快速逃逸越界后被清理Infinity不得进入速度分量距离让两个对象中心尽可能接近。确认计算不产生NaN或无穷值。确认碰撞后对象数量减少。确认剩余对象质量为两者之和。十七、常见问题与排查方法现象根因线索处理Slider 显示合法创建后却异常数组索引错位用具名输入模型或集中映射速度显示 1.40内部却有长小数只格式化了文本在状态写入时按步长舍入导入数据后出现NaN??没有拦截非有限数使用Number.isFinite两个天体重合后全屏消失距离平方接近零在物理层保留软化下限最大半径天体立即合并出生距离与碰撞阈值冲突联合校验半径和生成距离高质量高倍率下轨迹发散单步速度增量过大限制组合或采用子步360° 与 0° 结果略有差异浮点三角误差将方向归一到[0,360)公式页数值无法直接套用单位体系不同明确公式用于概念解释平板上速度难以精调轨道过长、步长感知弱增加步进按钮或数值提示排查时先打印或观察“归一化后的参数”再检查物理结果。若入口值已经错误继续调引力常量只会掩盖真正的问题。十八、上线前边界清单参数定义中的默认值全部位于最小值和最大值之间。paramValues与paramDefs数量、顺序一致。Slider 的步长能被显示精度准确表达。模型入口能防御undefined、NaN与无穷值。质量不允许零、负数或无限大。半径上限与出生距离、碰撞阈值协调。初速度上限与时间倍率共同验证。方向按周期量归一化。倾角文案明确是二维视觉参数。距离平方在物理内核中有非零下限。越界天体会被清理不再参与后续计算。公式知识页与模拟单位说明一致不误导为真实天文计算。phone、tablet、2in1 都完成实际拖动与边界操作。十九、总结输入合法只是起点进入物理内核前还要可计算这套参数链的核心不是多写几个if而是把责任分层。ArkUI Slider 负责让正常用户选择落在安全范围内状态写入负责步长与精度天体创建入口负责把未来可能出现的导入、路由或持久化值归一化物理内核则必须独立防御零距离和极端组合。当前“天体运行模拟”已经通过 Slider 范围、固定步长、距离平方下限、碰撞合并与越界清理建立了基础边界。若后续增加文本输入、场景分享或历史配置恢复应优先补上具名输入模型与统一归一化函数而不是把校验散落在每个按钮回调中。这样质量、距离和速度才不仅“能输入”而是始终保持可解释、可绘制、可计算。

相关新闻

2026/8/29 16:57:34

本地LLM基准测试全流程:量化选型与性能指标实战

很多教程会告诉你:本地部署一个 7B 模型,用 GGUF 量化到 q4_K_M,在笔记本上就能跑起来。这话没错,但真正上手时会发现,问题远不止“能不能跑”这么简单。同一个模型,用不同量化精度、不同上下文长度、不同推…

2026/8/29 16:57:34

AMD收购Taalas:把模型刻进芯片,AI推理进入专用化时代

这次我们不聊一个能直接下载的一键包,也不聊某个开源模型的实测跑分,而是聊一笔已经发生的芯片收购:AMD 收购了 AI 推理专用芯片公司 Taalas。消息出来之后,很多讨论都停在“AMD 又在扩建芯片版图”的层面。但如果只看资本动作&am…

2026/8/29 16:57:34

【2026】使用Ollama部署本地大模型最新教程

前言 之前部署过一次,但是时间太长就会有点忘记了;于是本次打算记录一下如何使用Ollama部署本地大模型,并实现局域网内远程调用。 正文 下载Ollama 这是其官网地址:https://ollama.com/页面比较简洁。进去就有下载&#xff0…

2026/8/29 17:07:34

华为前端面试高频题与备考策略:从JS原理到框架源码全解析

最近帮不少准备华为前端岗位的朋友做过面试复盘,发现一个挺有意思的现象:很多人不是能力不行,而是努力方向偏了。有人抱着 LeetCode 狂刷三个月,结果被问一句"浏览器从输入 URL 到页面渲染发生了什么"就卡了壳&#xff…

2026/8/29 17:07:34

基于Obsidian管理UTAU翻唱项目:搭建可检索的知识库工作区

开头先说清楚这篇文章要解决什么问题。Obsidian 是一款基于本地 Markdown 文件的个人知识管理软件,它的核心卖点是双向链接、知识图谱和高度可扩展的插件体系。把一个标题为“UTAUCOVER”的翻唱项目交给 Obsidian 管理时,很多人第一反应是“这不就是个本…

2026/8/29 17:07:34

基于SpringBoot的多人共享记账管理系统毕业设计项目源码

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/29 17:07:34

PID控制器原理与实战:从参数整定到代码实现避坑指南

1. 从“失控”到“驯服”:PID控制器的核心使命 如果你曾经尝试过让一个电机精确地停在某个位置,或者让一个烤箱的温度稳定在200度,又或者让一架无人机悬停在半空中,那你大概率已经和“失控”打过交道了。电机要么冲过头&#xff0…

2026/8/29 17:02:34

亲测4款降AI工具:4.8元vs8元千字,价格差一倍效果差多少?

亲测4款降AI工具:4.8元vs8元千字,价格差一倍效果差多少? 写完论文被打回来的感觉不好受。知网AIGC检测39%,学校要求15%以下,交稿还有三天。 去搜降AI工具测评,价格从4.8元到8元每千字不等,差距…

2026/8/28 16:16:17

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/28 16:16:21

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/28 16:16:22

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/29 0:01:10

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

一、设置环境变量etc目录下的profile.d文件目录 /etc/profile.d1、编写 vi test.sh文件内容# jdk变量 export ZHK_HOME/root export PATH$PATH:$ZHK_HOME/test # 可以取出来ZHK_HOME变量给ZZZ_HOME赋值 export ZZZ_HOME${ZHK_HOME}/test2、刷新 执行source /etc/profile 命令使…

2026/8/29 0:01:10

【JavaScript】内存管理-垃圾回收机制-内存泄露

内存管理 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()和free()。 而 JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。 整…

2026/8/29 0:01:10

Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP 的目标是把 MCP(Model Context Protocol)能力延伸到真实嵌入式硬件实验室:AI Agent 通过一个标准化的 MCP Server,就能查看目标板状态、控制上电断电、复位开发板、读取串口日志,甚至执行镜像刷写。对于经…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…