与要素数据模型重构指南)
前端图形学3D渲染【免费下载链接】Fantasy-Map-GeneratorWeb application generating interactive and highly customizable maps项目地址https://gitcode.com/gh_mirrors/fa/Fantasy-Map-Generator点击查看免费下载本文基于仓库内 features-overview.md 这一 PRD 文档结合src/下的实际实现系统讲解 Fantasy Map Generator 中岛屿、湖泊、海洋三大地理要素的统一管理方案从数据模型subtype分类与group渲染的职责划分、样式体系改造自定义湖组成为一等公民到「Geographical Features Overview」总览对话框的表格、筛选、双向高亮与编辑操作。读完本文你将掌握要素数据的组织方式、该总览工具的使用与入口工具栏按钮 / 命令 /Shift F热键以及每项设计在源码中的具体落点可直接用于排查与扩展相关功能。背景pack.features缺少统一视图数据模型已经漂移在 Fantasy Map Generator 中pack.features持有地图上的每一个岛屿、湖泊和海洋术语定义见 glossary 的 Feature Type / Subtype / Group 条目但此前项目里没有任何一个地方能以列表形式查看它们湖泊只能通过点击地图上的湖泊进入湖泊编辑器Lakes Editor查看岛屿没有任何编辑器——海岸线编辑器Coastline Editor早已演变为纯粹的海岸形状工具海洋在任何 UI 中都没有入口。与此同时要素数据模型本身出现了三处结构性问题这是本 PRD 要解决的核心矛盾。问题一subtype与group的语义错位理想分工应该是subtype子类型承载领域含义——生成器读取它做分类判断例如 population-generator.ts、goods-generator.ts、markers-generator.ts、provinces-generator.tsgroup分组只决定渲染——渲染器根据它把要素画进对应的 SVGg组。但有两个地方违反了这一约定lakes-editor.ts 的assignGroup用户挑选一个现成的渲染组时会静默改写subtype把领域分类与渲染参数搅在一起NON_NAVIGABLE_LAKE_GROUPS原定义在features.ts被 burgs-generator.ts 使用根据group判断港口可否通航——可导航性本应属于领域数据subtype却绑在了渲染参数上。问题二自定义湖组处于“半坏”状态湖泊编辑器会在#lakes下创建新的g元素但stylesSchema.lakes是一个只包含六个固定组的strictObject见下文样式改造因此自定义组的样式永远不会被持久化保存同时isLakeType把任何#lakes g都当成固定组处理导致自定义组无法被删除其组名还会泄漏进subtype。问题三海洋是“二等公民”features-generator.ts 的defineGroups直接跳过了海洋海洋没有subtype、没有group、没有#feature_N路径还被排除在MapEntities.collect(feature)之外——这直接导致海洋上不了笔记、进不了任何实体交互。另外data-model.md 中仍然写着“要素可以在海岸线编辑器中跨组移动”这与现状不符需要一并修正。目标与非目标目标Goals提供一个标准的总览对话框列出每一个要素——岛屿、湖泊、海洋包含名称、类型、子类型、分组、面积和笔记操作支持重命名任意要素修改子类型从固定集合中选择和分组仅限湖泊且必须是已存在的组双向高亮鼠标悬停列表行 → 地图上描出该要素轮廓鼠标悬停地图 → 对应行高亮让group在所有地方都纯粹作为渲染参数去掉湖泊编辑器中的 subtype 改写把可导航性判定移到subtype上让自定义湖组在样式存储中成为一等公民与路线组route groups采用同一套机制。非目标Non-goals不增删要素——那是高度图编辑器Heightmap Editor的职责总览对话框底部的画笔按钮正是跳转到它不支持用户自定义子类型——每个类型的子类型集合是固定的不编辑岛屿分组——sea_island/lake_island由地理形态推导得出不提供海洋轮廓与要素层级如海、海湾作为子级——海洋只获得按面积划分的子类型ocean | sea | gulf、一个名称和一条笔记没有自己的形状不在地图上渲染要素标签——要素名称只是数据供 tooltip、笔记、omnibar 使用。数据模型subtype 分类、group 渲染、name 与 coastline改造后的要素数据模型在 features-generator.ts 的Feature接口与defineGroups/defineSubtype中有完整实现四个字段的语义如下。固定子类型集合feature.subtype每个类型的子类型集合固定常量定义在 features-generator.ts类型固定子类型集合判定规则源码defineGroups岛屿continent \| island \| isle \| lake_island前一个要素是湖泊 →lake_islandcell 数 全网格 1/10 →continent 1/1000 →island否则isle湖泊freshwater \| salt \| dry \| sinkhole \| frozen \| lava温度 -3 →frozen高海拔小湖 →lava无进/出流且蒸发远超入流 →dry极小且无进/出流 →sinkhole无出流且蒸发大于入流 →salt否则freshwater海洋ocean \| sea \| gulf按 cell 数量 全网格 1/25 →ocean 1/1000 →sea否则gulf见getOceanSubtype用户在总览对话框中只能从这些集合中选择不能自创子类型。渲染分组feature.group湖泊可以是styles.lakes.groups中任意一个组的 id——固定组或自定义组均可岛屿只能是sea_island或lake_island由地理推导getDefaultGroup按subtype lake_island区分用户不可编辑海洋不设group海洋根本不绘制。名称feature.name每个要素都会生成名称defineNames仅在要素还没有名字时赋值已有名字视为用户数据、保持不变岛屿与湖泊以岸边文化的命名规则生成getName从 shoreline 或 firstCell 取文化经Names.getCulture生成另有 10% 概率直接取形容词海洋不属于任何文化——80% 概率取形容词如 “Azure”“Stormy”否则按要素中心相对地图中心的位置命名为 Western / Eastern / Northern / Southern。用户可以在总览中重命名或清空名称。清空后列表显示为Unnamed在笔记、搜索等场景下MapEntities.getName会回退为{subtype || type} {id}形式见 map-entities.ts。海岸线覆盖feature.coastline新增的可选字段要素自己的海岸线设置海岸线编辑器产物覆盖地图级设置。总览表格中每个岛屿/湖泊行都有海岸线编辑图标海洋该列为空占位点击打开对应要素的 Coastline Editor。修改 subtype 无级联与项目内其他编辑器一致修改子类型不触发级联重算——港口、货物、标记等都保持原样直到用户显式重新生成Update World、河流重算。重新生成时所有要素会像对待其他生成属性一样重新分类。样式体系改造自定义湖组成为一等公民styles.lakes从“六个固定组的strictObject”改为{ groups: Recordstring, LakeStyle }与routes、labels的样式组织方式对齐。styles.lakes结构变化schema 定义lakes: z.strictObject({ groups: z.record(z.string(), lake) }), // stock groups plus user-created ones配套改动styles-legacy.ts 的路径映射更新#freshwater→[lakes, groups, freshwater]六个固定组逐一映射旧样式收割逻辑对#lakes g的采集方式与#routes g一致styles-legacy.tsfixtures 同步更新isLakeType判定改为Object.keys(Styles.defaults.lakes.groups)见 lakes-editor.ts 的isStockGroup不再“只要在#lakes下就算固定组”。湖泊编辑器的组管理同步写回样式表湖泊编辑器创建 / 重命名 / 删除组时同时写入或删除styles.lakes.groups[name]新建组以freshwater为模板structuredClone克隆完全复刻 route-groups-editor 的模式lakes-editor.ts。这样做的直接收益自定义组的样式可以被持久化、被样式预设style presets寻址删除自定义组时组内湖泊统一并入freshwater组并同步删除styles.lakes.groups[group]lakes-editor.ts样式编辑器无需改动——它本来就读取 DOM 中的湖组。这条链路有测试覆盖styles-legacy.test.ts 验证自定义组可写入与删除后的寻址结果styles-legacy.dom.test.ts 验证自定义组从freshwater继承属性。总览对话框 UI 设计入口与挂载控制器为 features-overview.ts通过 controllers/index.ts 懒加载暴露为Controllers.FeaturesOverview对话框 id 为featuresOverview。它复用了initEditorTable/renderEditorHeader/applyLineHighlighting这套表格基础设施与 rivers-overview 同构。三个入口工具栏按钮Tools 标签页的overviewFeaturesButton“Features”见 tools-tab.ts命令“Open Geographical Features Overview”别名islands、lakes、oceans、landmasses、water bodies见 map-commands.ts热键Shift F见 hotkeys.ts。对话框标题为 “Geographical Features Overview”。表格列列内容可编辑性locate定位缩放到要素顶点包围盒highlightArea岛屿、湖泊name名称文本输入框清空显示Unnamed全部type类型类型 子类型合并展示湖泊显示{Subtype} lake其余为Subtype \|\| type并首字母大写以下拉框从固定子类型集合中选择岛屿lake_island除外以文本展示、湖泊、海洋group分组已存在的#lakes gid 下拉框仅湖泊岛屿显示为文本海洋为空area面积估算面积 单位被地图边界切开的要素feature.border按 地图面积 / (mapSize / 100) 外推前缀~tooltip 给出图上实际面积否coastline海岸线打开该要素的海岸线编辑器岛屿、湖泊note笔记Notes.getIcon→ 笔记编辑器{type:feature, id}全部edit编辑在湖泊的use上打开湖泊编辑器仅湖泊实现细节features-overview.tslocate、name、note为常驻列area列默认按面积降序排序。表格底部显示n of total当前筛选结果数 / 要素总数以及筛选集合的总面积估算面积之和。筛选与状态持久化类型下拉all | island | lake | ocean子类型下拉选项随所选类型变化类型为all时汇总所有子类型见updateSubtypeFilter搜索框匹配名称Unnamed也算在内、类型与子类型。筛选状态通过dialogState按对话框 id 持久化与其他总览overviews行为一致features-overview.ts。双向高亮行悬停 → 地图描边highlightOutline(#feature_N d)直接描出要素路径海洋没有路径则通过getVertexPath描出它覆盖的 cell 轮廓路径在每次对话框会话内缓存于oceanPathsMapfeatures-overview.ts地图悬停 → 行高亮applyLineHighlighting(dialogId, ({cellId}) pack.cells.f[cellId])对海洋同样生效features-overview.ts。编辑操作重命名直接写feature.name清空即写入空值显示Unnamed改子类型只写feature.subtype源码注释明确无级联生成器在下次运行时读取改分组湖泊写feature.group并把use元素移到新的g下或调用Layers.draw(lakes)重绘。行内编辑采用事件委托click/input/change三类事件各挂一个监听器按选择器分发到对应动作rowActions这也是该项目对话框的一致模式。CSV 导出导出列包含Id, Name, Type, Subtype, Group, Area (unit), Map area (unit), Cut by border——即比表格多出图上实际面积与是否被地图边界切开两个字段便于离线分析与核对features-overview.ts。关联改动与源码落点湖泊编辑器改造lakes-editor.ts 中“Type”下拉改名为“Group”其 tooltip 明确说明“不影响生成”Rendering groupassignGroup不再触碰subtype新增独立的“Subtype”下拉写feature.subtype时注释为“subtype 是领域数据渲染组不受影响”lakes-editor.ts组的新建 / 重命名 / 删除与styles.lakes.groups保持同步见上文样式改造。可导航湖泊判定迁移NON_NAVIGABLE_LAKE_GROUPS更名为NON_NAVIGABLE_LAKE_SUBTYPES改读subtypeexport const NON_NAVIGABLE_LAKE_SUBTYPES new Setstring([dry, frozen, lava]);features-generator.ts。这意味着“干涸 / 冻结 / 熔岩湖不可作为港口停靠”的规则从此由领域分类subtype驱动而不是由渲染组驱动湖泊编辑器中 subtype 下拉的 tooltip 也同步说明“生成器读取它burgs 不能在 dry、frozen、lava 湖上设港”。海洋纳入实体集合MapEntities的 feature 解析map-entities.ts支持feature_N与lake_N两种 id 形式并将要素纳入实体查找海洋从此可以携带笔记getEntityLabel提供的名称回退规则subtype || type id也正是总览“Unnamed”展示之外的数据侧兜底。总览的“edit”列在打开湖泊编辑器时通过use[data-fid]定位use元素避免依赖不存在的元素 id。文档更新data-model.md 的要素小节同步修正group仅为渲染参数、可在湖泊编辑器与要素总览中编辑subtype才是分类。术语层面glossary 的 Feature Type / Subtype / Group 三条目即对应此约定。测试与验收要点PRD 的验收标准可从实现侧归纳如下无级联修改 subtype 后 ports / goods / markers 保持原样直到下一次重新生成自定义湖组持久化创建、重命名、删除组的样式表同步有测试覆盖styles-legacy.test.ts、styles-legacy.dom.test.ts海洋笔记feature_{i}可被实体解析map-entities.ts笔记编辑器可对海洋打开{type:feature, id}CSV 导出导出行与当前筛选集合一致且包含图上面积与边界标志热键与命令Shift F、命令别名、工具栏按钮三个入口均指向同一FeaturesOverview.open()。开放问题PRD 末尾标注的 Open questions 为None——方案在数据模型、样式存储、UI 三方面均已收敛当前仓库中 features-overview.ts 的完整实现与 features-generator.ts 的数据层可直接对照本文逐步核对。赞分享前端图形学3D渲染【免费下载链接】Fantasy-Map-GeneratorWeb application generating interactive and highly customizable maps项目地址https://gitcode.com/gh_mirrors/fa/Fantasy-Map-Generator点击查看免费下载相关推荐Bokeh geo features 地理要素模块指南借助 Cartopy 在 Bokeh 中绘制地图Bokeh geo features 地理要素模块指南借助 Cartopy 在 Bokeh 中绘制地图 Bokeh 在 bokeh.plotting._geo数据可视化图表库SOLAR-10.7b-ko-Y24_v1.0-openmind vs 其他韩国语模型为什么它是2024年最佳选择SOLAR 10.7b ko Y24_v1.0 openmind vs 其他韩国语模型为什么它是2024年最佳选择 SOLAR 10.7b ko Y24_vturf/combine 详解将 Point、LineString、Polygon 要素集合合并为 Multi 类型要素的 Turf 地理工具turf/combine 详解将 Point、LineString、Polygon 要素集合合并为 Multi 类型要素的 Turf 地理工具 导读 tu数据分析上一篇掌握Magisk从Android Root入门到高级系统定制实战下一篇终极指南四步让老旧Mac焕发新生OpenCore Legacy Patcher完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考