news 2026/9/13 20:33:45

Pascal 3D 编辑器垂直模型(Vertical Model)架构详解:层级堆叠、墙体顶面夹持与板面支撑规则

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pascal 3D 编辑器垂直模型(Vertical Model)架构详解:层级堆叠、墙体顶面夹持与板面支撑规则

Pascal 3D 编辑器垂直模型(Vertical Model)架构详解:层级堆叠、墙体顶面夹持与板面支撑规则

【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor

本文以 wiki/architecture/vertical-model.md 为骨架,深入 Pascal 3D 编辑器的垂直几何模型:层级高度如何存储与堆叠、普通墙体顶面如何被夹持到层高平面、板面如何通过厚度向下生长、支撑宿主(support host)如何被持久化,以及一套"夹持而非询问"(clamp, never ask)的规则如何让整栋建筑在编辑时始终保持拓扑一致。读完本文,你将掌握这套模型的全部存储字段、解析辅助函数、加载迁移逻辑与落地陷阱,并能对照源码逐行验证。

该模型适用于一切读写垂直几何的构件:层级(level)、墙体(wall)、板面(slab)、天花板(ceiling)、楼梯(stair)、围栏(fence)、落地放置的家具物品(floor-placed items)。其核心源码集中在:

  • packages/core/src/services/storey.ts —— 层级堆叠、墙顶平面、天花板夹持边界
  • packages/core/src/systems/wall/wall-top.ts —— 墙体顶面解析与最小墙高
  • packages/core/src/systems/slab/slab-support.ts —— 板面支撑选举与墙体基座夹持
  • packages/core/src/systems/stair/stair-rise.ts —— 楼梯总升高解析与直线段收敛
  • packages/core/src/utils/vertical-scene-migration.ts —— 加载时的垂直模型迁移

一句话不变量

普通受平面约束(plane-bound)的墙体顶面被钉在层级平面上。绘制在地形或其它抬升支撑上的墙体,则通过保留"幽灵体高度"(ghost body height)的方式维持其高度:先物化该高度,再从选举出的基座向上平移整面墙。可选的地形填充只向下延伸墙体底部,永远不改变墙体作者设定的高度与顶面。

这套不变量的核心是:墙体顶面由"所在层高平面"决定,而不是由墙体自己的高度字段决定——只要墙没有被显式写入height,它的顶面就永远等于层高平面(或被上层板面底面截短),因此无论板面如何抬升墙体基座,墙只会变矮、不会变高,层顶永远不会出现缝隙。

存储事实(Stored truth):每个字段的语义

垂直模型的全部状态都是显式存储在场景节点字段中的。下表是这套模型的数据契约,理解它就能理解后续所有解析逻辑:

字段含义缺省(Absent)时意味着
level.height层高(米),层间楼板到楼板(floor-to-floor)。层的世界 Y 由getLevelElevationslevel序号累加解析未迁移的遗留数据(加载后不会出现,迁移会写入);消费方回退到DEFAULT_LEVEL_HEIGHT(2.5)
level.baseElevation相对计算堆叠位置的附加偏移。它同时平移本层与同一建筑中所有更高层;允许负值0(schema 默认值)
wall.height显式墙身高度(矮墙、女儿墙、或需要保持幽灵高度的抬升支撑草绘)。落地承载的墙总是解析为顶 = 选举基座 + height(含基准面以下);其它遗留下沉支撑保持其绝对顶面约束受平面约束(普通基准面放置的默认形态):顶面跟随getWallPlaneTop—— 即min(层高, 跨段上最低覆盖板面底面)
ceiling.height显式自定义高度,写入时被夹持到边界内跟随层高:实时解析为getCeilingClampBound=min(层高, 覆盖底面) − 0.01
slab.elevation行走面(顶面),层局部坐标默认 0.05
slab.thickness向下生长:实体占据[elevation − thickness, elevation]默认 0.05
slab.recessed下沉意图:开放壳体,底面为elevation,边缘为recessedRimElevation。被排除在"覆盖"查询与墙面贴附之外实心板
slab.recessedRimElevation抬升/下沉凹池的可选边缘锚点。相对预设保持此锚点不变而改变深度层平面(0),保持遗留水池
slab.fillToTerrain在实心板固定底面之下添加跟随地形的周界基础。行走面与作者设定的结构厚度保持水平无地形基础
supportSlabId墙体与所有落地放置种类的持久化支撑宿主。仅当重叠支撑在标高上不一致时在提交时写入;'ground'哨兵值把平台下的裸地钉住。结构块总是钉住其放置时的宿主,防止上方生成的房间板面反过来抬升平台支撑按查询即时选举(墙用覆盖选举,物品用足迹最大值)
wall.supportOffset可选层局部增量,相对选举出的支撑。地形墙链用它让每一段保持在首点的构造平面上,只存一个数字,不存地形采样零偏移:墙直接位于其选举的板面或雕刻地形源上
fence.supportOffset可选层局部增量,相对围栏的板面宿主或层平面。平移整条围栏而保持高度零偏移:围栏直接位于宿主或层平面上
wall.fillToTerrain从作者设定的基座向下延伸到地形,左右面独立采样。墙身高度与顶面保持不变固定基座,无地形填充
stair.deckSlabId目标平台板:升高实时跟随deck.elevation − 楼梯自身选举基座;附着期间禁用开洞同步目标是一个层
stair.totalRise显式自定义总升高(优先于一切)跟随:由平台板或所在层推导;syncStairRises将直梯段收敛到解析出的升高

一个值得注意的细节:supportSlabId只在重叠支撑标高不一致时才持久化写入——如果所有候选支撑高度一致,就无需记录,查询时会自然得到相同结果。而'ground'哨兵值的语义是"由层基座(地面)承载",在 packages/core/src/hooks/spatial-grid/support-host-id.ts 中定义。

两条保护语义的 schema 规则

  • 含义承载字段不加 Zod 默认值。level.heightwall.heightceiling.heightstair.totalRise均为.optional()没有.default()——缺失本身就是数据。创建处显式写入值;migrateNodes的输出是类型断言(cast)而非解析(parse),所以即便定义了默认值,也不会在遗留数据加载时物化。
  • store 会删除显式undefined的键。updateNode(id, { height: undefined })会移除该键(见node-actions.ts中的mergeNodeUpdate)。遗留受平面约束的墙可能仍然省略height;墙体面板在启用地形填充前会解析并物化其当前墙身高。天花板与楼梯的跟随模式继续由字段存在性推导——没有持久化的模式枚举

这条规则的直接好处:跟随模式(follows mode)不需要一个mode: 'follow'字段,只要height键不存在,天花板/楼梯就处于"跟随层高"的活语义;一旦写入height,就变为显式覆盖。迁移与编辑器逻辑共享同一套判据。

解析辅助函数(Resolution helpers):永远不要手写?? 2.5

仓库提供了成套的解析函数,所有消费方都应调用它们,而不是各自回退到魔法常量。下表是权威清单:

辅助函数所在文件解析内容
getStoredLevelHeightgetLevelElevationsgetLevelAbove/Belowservices/storey.ts层高、感知偏移的逐建筑堆叠、相邻层
getWallPlaneTopservices/storey.ts受平面约束墙的顶面:层高被覆盖板面底面夹持,跨段采样且边界包含的带重叠
resolveWallTopresolveWallEffectiveHeightMIN_WALL_HEIGHTsystems/wall/wall-top.ts给定平面 + 选举基座后的墙顶 / 有效高度
getWallBaseElevationForNodesgetWallEffectiveHeightForNodesspatial-grid manager带地形/支撑偏移的选举基座与墙身高(供 UI 叠加层使用)
getCeilingClampBoundgetCoveringSlabUndersideAtservices/storey.ts天花板夹持边界;跨层覆盖查询(上一层、非下沉板)
resolveCeilingHeightservices/level-height.ts天花板有效高度(显式或跟随)
resolveStairTotalRisesyncStairRisessystems/stair/stair-rise.ts楼梯升高优先级 + 直梯段收敛
computeWallSlabSupportgetSlabSupportForItemgetSupportCandidatesForFootprintsystems/slab/slab-support.ts + spatial-grid manager支撑选举(渲染多边形、宿主优先、可选maxElevation上限)
resolveSlabPlacementElevationsystems/slab/slab-placement.ts把实心板的作者顶/厚区间平移到捕获的基底平面上;下沉板保持层相对
getSlabBaseElevationapplySlabBaseElevationChangeapplySlabThicknessChangenodes/slab/elevation-limit.ts分离整体底面放置与固定基座的厚度编辑
resolveFenceLiftElevationnodes/fence/lift.ts围栏板面宿主标高 + 可选手动支撑偏移
clampSlabElevationForWallsslab-support + nodes/slab/elevation-limit.ts受平面约束墙体下的板顶夹持

源码级关键点一:层级堆叠如何解析

getLevelElevations是整套模型的基石。它的实现(storey.ts 第 65-102 行)要点:

  1. 逐建筑堆叠:先解析每个层所属建筑(显式parentId优先,其次才是建筑children数组中的成员关系);
  2. 按序号升序排序,用累积变量cumulativeYByBuilding逐层累加:baseY = 上一层的 (baseY + height) + 本层的 baseElevation。因此baseElevation偏移会顺带抬升同建筑内所有更高层;
  3. 身份键 WeakMap 记忆化nodes是不可变 store 切片,引用相同即场景未变。这是针对热调用路径的优化——注释明确记录了一个真实案例:WallCutout每帧每墙调用一次,曾导致每帧重建 1000+ 次的相同 Map。

源码级关键点二:墙体顶面三态解析

wall-top.ts 的resolveWallTop是整个"垂直模型反转"的核心,三种情况:

export function resolveWallTop(wall, storeyHeight, electedBase): number { if (wall.height == null) return storeyHeight // ① 受平面约束:顶 = 层高平面 if (wall.supportSlabId === 'ground') return electedBase + wall.height // ② 地面承载:顶 = 基座 + 高度(含基准面以下) return electedBase > 0 ? electedBase + wall.height : wall.height // ③ 遗留抬升承载:基座 > 0 才跟随,否则保持绝对顶 }
  • ① 无height→ 顶面钉在层高平面,板面抬升基座只会让墙变矮;
  • 'ground'哨兵(地形承载)→ 高度始终是墙身高度,即使基准面以下也成立,因此雕刻地形不会拉伸墙体;
  • ③ 显式height但非地面承载(遗留下沉板场景)→ 只有基座抬升(>0)时才跟随,保持遗留的"绝对顶面"约束。

MIN_WALL_HEIGHT = 0.5(米)同时约束墙高箭头的最低拖拽边界与板面标高夹持(见下文夹持规则)。

夹持规则(Clamp, never ask)

垂直模型把"一致性"实现为写入时夹持而非"写入后询问/修复"。四条核心规则:

  1. 受平面约束墙体下的板面:板面标高夹持到层高 − MIN_WALL_HEIGHT(0.5)。否则墙身挤出(平面减基座)会塌缩到最小值以下,到平面时甚至为零。实现见 slab-support.ts 的clampSlabElevationForWalls:它把候选板面标高代入选举集合后再跑选举,因此"只有在提出标高时才赢得选举"的板面也会被夹持,而被兄弟板面挤出选举的不会。getSlabElevationUpperBound更进一步:先用"把该板抬到所有兄弟之上"的探测标高试探,若任何受平面约束墙会选举它,拖拽上限就是层高 − 0.5,否则无上界。
  2. 天花板夹持:写入时(以及通过空间检测响应式向下)夹持到min(层顶, 覆盖板面底面) − 0.010.01是 storey.ts 中的CEILING_CLAMP_MARGIN常量,目的是让天花板表面永不与其上方实体重合。
  3. 受平面约束墙顶夹持到覆盖板面底面——厚板或与层齐平的上层板会缩短其下的墙体(Revit 的 attach-to-floor-bottom 自动行为);显式高度的墙豁免。实现上,getWallPlaneTop用墙的厚度带(中心线 + 双面线、感知弧线)通过wallOverlapsSlabFootprint对每块覆盖板面的存储多边形(扣除孔洞)做裁剪——刻意不做点采样,因为自动板面多边形由墙中心线推导,周界墙正好落在多边形边界上,射线投射的点在多边形判定会随边方向翻转(一面墙被夹持而邻居没有)。边界接触在任何一侧都算覆盖。
  4. 实心板控制器的非重叠契约
    • 立方体拖拽平移占据区间而保持thickness
    • chevron 与面板厚度控件固定底面、通过同时写thicknesselevation移动行走面;
    • 面板标高平移整体而保持厚度;
    • 下沉凹池单独存储边缘锚点,使地面/边缘/深度控件与预设始终相对同一锚点。

配套规则还有:结构标高跟踪器移动参考基座而非构件尺寸——板跟踪器移动底面并保持thickness;墙跟踪器写supportOffset并物化当前墙身高;围栏跟踪器写supportOffset并保持height。而下沉板保留独立的边缘/深度控件。

getRenderableSlabPolygon中的墙面贴附(wall-face adoption)只适用于接地板(elevation − thickness ≤ 0.01且非下沉)——悬浮平台保留其手绘多边形,并被跳过作为接缝候选。

指针决定的放置(Pointer-decided placement)

堆叠表面决策必须来自真实相机射线而非平面命中,因为网格事件相交的平面骑在幽灵体的标高上。getPointedSupportSurface返回最近的合格表面加上交点,而支撑选举上限(maxElevation)与光标 XZ 都来自这一次计算:

  • 指向平台板下方→ 选举地面;指向平台顶面→ 选举平台。
  • 朝上的块体几何是板、围栏、柱、楼梯、物品与注册表驱动地面对象的共享放置表面;墙体草绘还可额外包含朝上的墙、可堆叠物品与柱几何。
  • 这些节点顶命中会为本次放置冻结一个标量构造平面(throw 期有效),它们不是持久化承载边,不跟随后续宿主编辑。
  • 命中后的持久化方式分三类:板存为elevation,墙与围栏存为supportOffset,落地放置位置节点存为其规范 Y 偏移。三者还会钉住块体下方的板或地面,防止稍后生成的板面反馈抬升已放置对象。
  • 普通板/地面命中会持久化其选举的支撑源,保持正常的阶梯式基座行为。
  • 2D 平面图放置没有相机射线,保持最大选举(max-election)。

板面草绘的平面冻结

墙与板草绘共享水平构造平面解析器(slab-placement.ts 的resolveSlabPlacementElevation):

  • 板冻结第一个吸附顶点的平面,后续顶点都保持在该平面,提交时把作者的垂直区间平移到捕获的基座;
  • 绝不把厚度或单个顶点铺盖(drape)到地形上。可选的地形跟随是与固定底面分离的独立周界基础,绝不改变板区间;
  • 下沉板保留显式边缘锚点;
  • 被锁定的构造平面打上fixed-plane标签,这样世界 Y=0 的平面在后续指针移动时不会与地形查询平面混淆。

自动房间表面的垂直派生

自动房间表面从包围墙体派生垂直位置(storey.ts 相关逻辑):

  • 每面边界墙的基座通过渲染器所用的同一套选举解析——包括其下的地面,因此画在裸地上的房间也能获得地形输入,即使没有墙携带显式supportSlabId
  • 地面取最高的墙基座,并保持其既定的 0.05 m 行走面偏移;天花板取最低的墙顶,并落在其下 0.01 m。两面都保持水平:混合标高的围合不再退回到备用放置,选择最高基座是因为较低墙本来就向下延伸入地面,不会在任何墙下开启天光;
  • 现有autoFromWalls表面会与后续墙体支撑偏移变化以及雕刻协调——层的结构签名对每面墙解析后的层基座做哈希,因此在已完成的房间下移动地面会重新派生其地面与天花板(每笔刷一次,在该笔刷自己的撤销步骤内)。手动表面永不重写
  • 自动板被排除在这套墙基座选举之外,防止派生地面递归抬升自己的墙、再抬升自己。

继承地形(Inheriting terrain):通用接缝

levelBaseElevationAt(nodes, levelId, x, z)是"当节点下方没有任何建造物时,它停靠的表面是什么"的唯一答案——雕刻地形处返回地形高度,其它地方返回0。它的实现(terrain-support.ts)通过terrainSupportLift(...) ?? 0组合而成:terrainSupportLift回答"这里有没有地形"(可空,调用方可分支),levelBaseElevationAt回答"这里的世界地面有多高"(总量,调用方无需知道地形是否存在)。

关键历史背景:地形曾经是按种类(per-kind)选择加入的,因为每个场地都手写terrainSupportLift(…) ?? 0,而每个忘记询问的消费方都默默假设平面y = 0。通过本函数解析基座,任何种类都能跟随地面,无需注册任何东西。需要区分"平地"与"与层基座齐平的建造表面"的调用方,仍需terrainSupportLift的 null——两者在此都读0,只有前者会铺盖山坡。

三种让种类 Y 触达地面的方式(按推荐优先级):

  1. capabilities.floorPlaced—— 解析器(getFloorPlacedElevation,见 floor-placed-elevation.ts)在每个足迹上于重叠板与层基座之间选举,FloorElevationSystem每帧把结果写入注册网格。适用于一切站在表面上的东西。实现细节:层级基座在节点自身 XZ采样一次(不是每足迹、也不是足迹平均)——这保证一排柱子各自在坡上正确,而复合节点(柜体组合、L 形桌)保持刚性不剪切。'ground'哨兵在这里直接返回groundLift()
  2. def.geometry构建器中的ctx.levelBaseAt(x, z)—— 适用于把垂直原点烘进网格的种类(如围栏的内部抬升组)。调用它同时登记该种类参与地形失效:noteLevelBaseConsumer在首次构建时记录类型,markTerrainSupportDependents在每次地形变化时弄脏这些节点以便原点重建。询问即注册——刻意如此:声明式标志只会成为又一种每种类选择加入,而过度近似为"每个有构建器的种类"会在每次笔刷涂抹时重建整个底层地板。def.floorplan缺此能力(平面视图不绘制标高),共享构建器必须将其视为可选,而不能假设 2D 中地面是平的。
  3. 直接调用levelBaseElevationAt—— 适用于渲染路径之外、已持有节点记录的解析器(支撑选举、吸附引导、手柄放置)。采样必须与渲染器相同的 XZ,否则叠加层与网格会不一致。

集体渲染器(一个组件绘制多个节点,如实例化网格)三者皆不适用:FloorElevationSystem写入节点注册的对象,而这些种类的注册对象是选择代理而非实例。此类渲染器必须自行通过getFloorStackedPosition解析每个实例的 Y。

加载迁移(Load migration):常驻加载路径

垂直模型迁移在migrateVerticalSceneNodes(vertical-scene-migration.ts)中实现,无限期驻留。原因是社区自动保存只在首次加载后编辑时才持久化,迁移必须留在加载路径上。它纯净且服务器安全——编辑器加载器与托管场景权威都会调用它,使协作比较或持久化操作前双方规范出相同字段。

五步迁移:

  1. 写入每个遗留层的精确派生高度(默认遗留楼层存 2.55 = 0.05 板 + 2.5 墙),绝不吸附到预设。派生逻辑见 level-height.ts 的deriveLegacyLevelHeight:取子构件中天花板显式高度与墙解析顶的最大值(墙顶通过computeWallSlabSupport(...).elevation选举基座后由resolveWallTop解析)。
  2. 按建筑压缩level序号,以零为锚(非负 → 0,1,2…;负 → −1,−2…——地下室保持地下室)。每次加载都运行,幂等。
  3. 对墙顶对照派生平面分类|plane − top| < 0.20严格小于→ 受平面约束(移除height键);否则显式(缺失高度的矮墙物化 2.5)。ε 由生产普查校准:存在刻意的 0.20 短墙,不能吸附
  4. **天花板在 ε 内贴近边界(以及所有autoFromWalls天花板)**丢弃height→ 跟随模式;楼梯丢弃遗留的盲目totalRise: 2.5。两者都受"场景是遗留的"(某层缺height)门控。
  5. 板面thickness := elevation(字节级相同的占据区间,含退化零);负标高水池变为recessed: trueelevation不变。

此外迁移还修复一个特殊场景:地形雕刻时代在平面场景 3D 草绘的墙被印上supportSlabId: 'ground',该钉会短路板选举,使墙脚埋在板内 z-fighting。迁移仅在"埋入"状态修复此钉(板区间严格跨越钉住的基座,容差 1e-3);有雕刻地形的场景整体跳过——那里地面宿主是承重的,且实时地形场对此纯通道不可见。

陷阱清单(Gotchas)

  • 序号是语义的。level < 0渲染为"Basement N";level === 0是地面层查询。永远不要脱离零锚点重新编号
  • 边界几何。自动板多边形由墙中心线派生,墙/顶夹持采样恰好落在多边形边缘上——始终使用边界包含的带重叠辅助函数wallOverlapsSlabFootprintslabCoversPoint),这些路径上绝不要用原始射线投射的点在多边形判定(其答案会随边方向翻转)。
  • 直梯从存储的段高构建,而非解析出的升高——任何升高变化都必须走syncStairRises(由StairOpeningSystem应用,历史暂停,在 store 更新后一个微任务执行,等空间网格安定)。曲线/螺旋楼梯直接读取解析升高,无需同步。
  • 响应性是显式的。level.height变化弄脏该层的墙/楼梯/天花板/围栏;板变化弄脏同层重叠支撑、下层墙/天花板与附着平台的楼梯。每次实时地形笔刷弄脏地面承载结构、fillToTerrain墙/板、每个在平地的floorPlaced节点,以及每个构建器询问过ctx.levelBaseAt的种类——通过 spatial-grid-sync.ts 中的瞬态useLiveTerrain订阅;场景图与撤销历史仅在笔刷提交时写一次。
  • 自动房间重派生按笔刷而非按笔刷内涂抹(per stroke, not per dab)。实时涂抹只发布到useLiveTerrain,从不触碰场景 store,因此重派生房间地面/天花板的结构签名差异在松手时只运行一次。拖拽中地面承载墙跟随笔刷而地面等待松手——刻意设计:按涂抹重派生意味着每笔都写场景、地面在光标下抖动。
  • 宿主生命周期。删除板会在同一撤销提交中从幸存者剥离supportSlabId/deckSlabId;仅被重塑掉的宿主静默回退,板返回后自动恢复。
  • 克隆路径不同。clone-scene-graph.ts 重映射supportSlabId/deckSlabId;编辑器剪贴板(scene-clipboard.ts故意不重映射(它重新选举);房间放置重映射二者。新增克隆/实例化路径时,两个字段都必须重映射。

源码对照速查

验证本文论断的最短路径:

  1. 层级堆叠与墙顶平面:读 packages/core/src/services/storey.ts 的getLevelElevationsgetWallPlaneTopgetCeilingClampBound
  2. 墙顶三态与最小墙高:读 packages/core/src/systems/wall/wall-top.ts 的resolveWallTopMIN_WALL_HEIGHT
  3. 支撑选举与夹持:读 packages/core/src/systems/slab/slab-support.ts 的computeWallSlabSupportclampSlabElevationForWalls,以及 packages/nodes/src/slab/elevation-limit.ts 的底板/厚度/顶面/预设控制器;
  4. 楼梯升高:读 packages/core/src/systems/stair/stair-rise.ts 的resolveStairTotalRisesyncStairRises
  5. 地形接缝:读 packages/core/src/lib/terrain-support.ts 的levelBaseElevationAtnoteLevelBaseConsumer,以及 packages/nodes/src/fence/lift.ts 的resolveFenceLiftElevation
  6. 加载迁移:读 packages/core/src/utils/vertical-scene-migration.ts 的migrateVerticalSceneNodes

延迟决策(Deferred by decision)

持续的房间身份(Persistent Room identity)、部分楼层导航、板参考面枚举、悬挂天花板、以及坡地场地基准(site datum for sloped terrain)在plans/中都有命名的门控(gates),均不阻塞本模型。平台板(deck)以目录房间/预设形式交付;一步式夹层/阳台工具已被移除(代码保留在 editor 的e30042db提交)。换句话说:垂直模型是一套已稳定落地、被所有垂直几何构件共享的底层契约,未来扩展只需遵循同一套字段、辅助函数与夹持规则。

【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 20:31:15

家用充电桩3C认证新规:选购安装避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 20:30:41

CogVideoX 文生视频完全拆解:5 步跑通 + 显存优化清单

CogVideoX 文生视频完全拆解&#xff1a;5 步跑通 显存优化清单 【免费下载链接】CogVideo text and image to video generation: CogVideoX (2024) and CogVideo (ICLR 2023) 项目地址: https://gitcode.com/GitHub_Trending/co/CogVideo CogVideoX 是智谱开源的视频生…

作者头像 李华
网站建设 2026/9/13 20:29:34

QMap遍历原理与性能优化:红黑树、隐式共享与线程安全

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 20:27:31

基于STM32的ATT7022电能计量驱动:SPI通信、相位校正与温度补偿

简介&#xff1a;面向STM32开发者的ATT7022电能计量芯片驱动代码包&#xff0c;专注解决电压、电流、功率等参数的实时采集与精度校正问题&#xff0c;适合正在做智能电表、电力监控或电源管理项目的嵌入式工程师&#xff0c;尤其对需要快速上手计量驱动的新手非常友好。资源全…

作者头像 李华
网站建设 2026/9/13 20:27:20

模糊图片OCR乱码原因与修复实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华