这次的周报又多拖了两个星期。其实按照实际进度来说项目已经接近完成了。不过我会吧进度同步到这份周报该发布的时间。

项目进度

Filter and Collection

完成 filter 部分,将原始请求的 osm bbox 数据进行筛选,分为 public transport 和 highway 等 collection。

考虑到编辑器主要服务于公共交通,所以不需要过多关注建筑物等信息的编辑。主要关注 highway 和 public transport.在参考了 OSM wiki 之后编写了 filter, 利用 tag 信息来过滤数据,进行分类。

对于筛选后需要展示和编辑的数据,建立了 feature tree 的树形结构,维护 OSM 数据的树形关系,便于展示和编辑。

在地图的右侧新增了 sidebar, 包括 outline view 和 property editor。

在 outline view 中,使用树形 list 展示数据,并且允许选择数据。

在 property editor 中 展示现有 OSM feature 的 property, 并且允许编辑其中的 tag. 成员的顺序更改引入的 dnd-kit 来拖拽变化顺序。同时允许将一些选中的 feature 插入其中作为成员。

Fix

relation 的 member 也可以是 relation, 之前的 type 定义中忘记了。

移除了一些 console.log 调试语句。

其他一些小的 bug 修正。

更新计划

下阶段的更新将会进行一些收尾性质的功能,主要包括未完成的功能,需要优化的逻辑,UI 上的问题等等。

具体的 TODO 已经更新在项目仓库。

很遗憾这个周报欠了两个星期,所以这次会连着发两份周报(下一份也在写了)。

项目进度

截止本周报应该发布的时间,我已经完成了项目的 React 重构,并且初步确定了 UI 编辑模块的组成。

重构

在项目开始一个月,已经写了一半的情况下面重构,的确不是一个很容易做出的确定,但是原先的技术选型确实不能支持这个项目的继续开发了——倒不说说技术上不可行,但是需要更多的时间,而且复杂度会超出掌控。

原先的技术选型受到了 Rapid 项目的影响,这个项目采用了原生 ESM 来进行开发,而不是使用流行的前端框架。因为我这个项目也使用 PIXI.js 来进行地图的渲染,很多实现和设计都参考了 Rapid ,所以一开始也很自然的学起了它的技术选型。

但是在准备 UI 模块的时候,面对需要拓展的状态管理相关的逻辑,这个项目的复杂度开始了指数增长,我需要保证 PIXI.js 的组件和 DOM 的 UI 都去跟踪同一份数据的变更来进行渲染和重绘,这样的逻辑会很复杂,需要我对状态管理的逻辑进行拓展,因为还需要 undo 和 redo 功能。原先的 Action List 的模型还是不足以撑起这么复杂的需求,如果要拓展到能用的程度就会需要很大的工作量——Rapid 项目,或者 iD 项目,在实现编辑系统和相关部分的时候应该写了上千行代码,而且只是一个框架。而如果我打算这么写的话,后续的开发进度就很难保证。

这时候我开始向导师求助,导师代询问了几位活跃在一线的前端开发者,并且得到了一些状态管理方面的建议。另外,不止一人对不用框架硬写表示怀疑,建议引入现代前端框架,比如 React 或者 Vue,“我觉得想清楚是自己想要造轮子,还是想用轮子实现一个应用,最好只二选一”。

在综合了各方建议之后,我决定引入 React 框架,使用 zustand 作为全局状态管理,同时 PIXI.js 有一个官方的 React 绑定,这也方便了我的迁移工作。

迁移的过程还算顺利,毕竟我其实也更熟悉用框架来开发,当初选取原生 JS 纯粹是抱着试试看的心态。显然这次尝试不是很成功。

重构之后,原来的 Action 抽象被彻底废弃,转入用 zustand 实现的 model 模块,原先所需的功能变成了 zustand 的 store 中的函数。这些以 Action 为名字结尾的函数应该是这个模块最后的痕迹了。 PIXI 模块使用了 React 绑定,现在看上去就像普通的 React JSX 了。原先的 stateMachine 被保留了下来,除了已经废弃的 ActionList 的接口和被大改的 PIXI 模块的接口部分做了一点改动。其他的代码没有太多大改,只是被我接着重构的机会迁移到了 Typescript, 相比 JSDoc 纯粹在注释上的类型标注自然是更加严格而且便捷了。

UI 部分

在重构之后,我开始了 UI 模块的开发工作。对于原先计划的 Outline 和 Property 页面大致写下了一些简单的静态组件来进行占位。目前测试良好,能够获取全局状态并且展示。这部分的开发可能会更加偏向传统前端项目。所以应该会比较平稳。

更新计划

这次的更新计划,由于没有太多功能上的推进,会继续在上一份双周报中提到的目标的基础上继续推进。

需要补充的是接下来会在大纲视图中对当前的元素分类,并且会写出 filter 来筛选数据,因为这个编辑器中可能目前只需要展示 highway=* 和 public transport v2 的数据,所以接下来的编辑界面应该会清爽很多。

距离上一个周报已经过去两个多星期了,我也应该要同步当前的进度了。

项目进度

目前项目的核心模块已经基本固定下来,可以进入后半阶段的开发,接下来的工作基本上是在现有框架内添加新的功能。

首先是调通了渲染部分,不过还是有些细节缺少打磨,比如样式以及控制渲染的元素,这些会和之后的功能同步进行,确保样式和编辑逻辑贴和。

其次我写了个 OSM API 模块,用 Promise 打包了一些 OSM 的接口,将返回的 XML 解析成 JS Object , 方便在程序中调用。

接下来是编辑模块。主要包括操作逻辑部分和全局数据管理部分

对于地图编辑中的操作逻辑,引入了状态机,在代码中称为 state machine,管理当前的编辑器状态,通过监听鼠标和键盘事件,再根据状态图中提供的函数和状态关系,进行状态转移和相关数据维护。根据当前状态判断事件应当触发的行为和新状态。state machine 提供了一些 hook, 用于在其他地方挂载,追踪事件,比如 pixi 中的鼠标事件。编辑操作就在状态转移的时候进行。

一般来说,在状态机本身转移的过程中会产生一系列对全局数据的变更。为了维护这些变更,提供了一个双向链表来进行管理这些变更,在代码中称为 action list。这个链表对外提供 undo, redo 和 do 接口。其中 do 接口接受一个 action 并且执行它,再将其加入链表尾部。为了避免多个重复 action,还会对有些 action 进行 merge 操作。

一个 action 提供 do, undo, redo 接口,有些还会提供 merge。action 应当在被执行,撤销,重做时对全局数据进行维护,同时还要维护其他相关变更,比如被影响的元素的 UI,各个图层的数据等等。这样确保所有的变更集中到一起,尽可能减少引入撤销重做时对于相关变更维护的心智富而俺。

全局数据是一个对象,它的引用存在每个 action 中,由 action list 保证每个 action 在撤销和重做时的顺序是正确的,比如确保撤销 action 时一定是该 action 被执行之后的状态,即后续 action 都已经被撤销。

由于目前实际的编辑操作尚未完成,暂时不考虑 undo 和 redo 操作,因为他们会依赖未完成的部分代码。

更新计划

目前项目已经开发了一个月了,考虑到九月底就要结项,时间还是比较紧的。所以我会尽量优先完成核心功能,将一些非核心的外围功能排在后面完成,确保顺利结项(OSPP 的一万二不能丢啊,好多钱呢,剩下功能大不了国庆继续开发)。

以下是大致需要的功能:

UI 方面

大纲(Outline)视图:可以显示当前所有元素,可以在这里选择元素,管理元素的基础状态

属性(Property)视图:管理各种属性,包括全局设置属性,当前选中元素元信息等。

还有一些独立的小组件,比如新建结点,连接线段等等

功能方面

作为公共交通编辑器,就应该有公共交通编辑功能。在 OSM XML 中,公共交通关系是一个 relation 元素,这个 relation 拥有一个 route, 以及一系列 tag 表示该元素的具体信息。

对于元信息的编辑,可以使用前面提到的属性视图来直接编辑。

对于具体的点的位置,使用地图模块完成编辑。可以考虑添加一定的 style 来实现高亮方便明确当前编辑的路线。

对于路线对于点和路径的包含关系,需要将地图的选择功能和属性视图结合。

可能还需要一定的线路新建功能,包括新建点,新建线路,对线路属性再进行编辑。

完成根据站点关系的线路计算功能,可以考虑调用现有 API 来实现

演示效果

原谅我没有时间来打磨,现在他们全部共享一个 style 确实很难看。

不过再加几行代码就可以吧建筑物的渲染取消掉,那样就会好很多。之后会慢慢调整style 的,也许从 iD 编辑器那边把颜色吸过来?😂

关于编辑功能就不演示了,反正只有拖动点和拖动地图以及调整缩放比例。

img

很快开发就经过了两个星期,是时候写一篇双周报了。

项目进度

项目还在早期开发阶段,目前还没有可用的原型,不过已经可以渲染一些测试数据了。

目前基本上确定了渲染部分的实现,经过测试可以渲染点和路径。

不过由于其他模块的接口还没有完全确定,有部分功能没有实现。比如分线段高亮路径,而不是 iD 编辑器中默认选中整条路径的逻辑。还有多面体的渲染目前也没有实现,因为需要编辑模块的接口。

更新计划

接下来的两个星期将会进行编辑模块的开发,写出一个功能良好的原型进行打磨,在稳定之后就可以和符合 OSM 标准的 API 进行通信并提交结果了。希望不会因为写出恶性 bug 被拉黑,😂。

现在正在编写状态管理模块,希望能够为编辑提供稳定的支持。

演示效果

目前我们的代码还不能进行任何编辑操作,也无法直接渲染从 OSM 网站获取的 XML 或 JSON, 因此我手动构造了几个点作为非常简陋的渲染测试。同时也测试了背景瓷砖的功能,目前运行良好。

请原谅糟糕的配色,我会在后期进行打磨的。因为选取的经纬度刚好没有道路(这一点也不奇怪,地球上 71% 的地方都是海洋,陆地上大部分也是无人区,而我不幸随便打了个经纬度),OSM 的瓦片没有任何可辨识的内容,但是确实可以正常请求瓦片并渲染,可以看见开发者工具中的图片请求。

img

在这次 OSPP 当中我将会完成一个基于现代前端技术栈的 OpenStreeMap 公共交通关系编辑器。希望能为 OSM 社区做一些贡献。

项目目标

本项目的目标是使用现代前端技术栈开发一个跨平台的编辑器,该编辑器操作简便,交互直观。项目过程中将与 OSM 中国社区合作,确保在交互设计和功能实现上达到较高的标准。

项目实现

项目基本框架

项目可以大致分为地图渲染模块,路线编辑模块,以及 OSM API 模块

地图渲染

根据当前经纬度位置和需要的渲染范围,利用 OSM API 模块提供的抽象,向 OSM 主站请求地图数据,并根据所得的地图,通过渲染模块提供的 Feature 抽象,将元数据数据解析成点,线或多边形的图形对象(如 PIXI.Graphics 或 PIXI.Sprite ),通过 Pixi.js 使用 WebGL 渲染。

同时,需要通过用户的交互来更新地图。通过监听用户鼠标和键盘事件,移动时动态地向服务器请求数据并更新,在放大缩小时控制地图的渲染粒度。当用户选择某些元素时,对元素进行高亮。这部分逻辑需要和路线编辑模块相互结合。

路线编辑

支持多选地图中的路线结点和站点,支持点选,框选,刷选等方式进行元素选择。通过简洁的 UI 进行线路的新建和编辑操作。页面需要足够清晰,提供直观的工具,方便用户快速找到需要的功能。

通过调用其他开源路由 API (如 GraphHopper, OSRM, OpenTripPlanner 等)支持仅通过公交站点数据自动计算可能路径。

通过引入状态管理机制,支持操作历史可持久化,可以满足撤回重做等基本操作需求。同时可以引入版本控制的有关思想,确保历史记录的高效性和稳定性。

OSM API 模块

提供与 OSM API v0.6 的交互的抽象,包括登录鉴权,数据请求,编辑数据后的数据上传,并且遵循 OSM 接口的规范。

项目进度

项目进度会在后续文章更新

授权

This work is licensed under a
CC0
.

开始之前

去年暑假看 GOG 上面的巫师 3 打骨折了就花了 30 抄底。玩到 Velen 困在内啥洞里面砍石像,因为太菜卡关了就没有玩下去😂。加上之前对自己没有搞好百果园的那个任务,以及乱选给皇帝汇报的事情等等让我很不满意。所以这次我重新开了一个存档,决定痛改前非。

这回为了有个新气象,我打算稍稍微调一些 Geralt 的外观,心里想着导出到 Blender 里面改完导入回去很快的吧,结果就写了整整三天的 Mod。因为缺少文档,全靠看教程瞎猜,开虚拟机装了个 wcc_lite WolvenKit 种种工具,整来整去各种打包解包导入导出。模型早早做好了,就是导入进去之后没有材质,翻来覆去地倒腾。最后一次手动改 w2mesh 文件把材质路径往里面写,加进去之后游戏崩了。遂放弃。

看来我还是低估了游戏开发的难度(

游玩随记

之后就是很正常的流程。Velen 真不是啥好地方,主线我都是赶紧打的,以后除了凯拉的任务估计也不想回来了。野外的怪物各种精神污染,还天天下雨,氛围很压抑,对人心理影响挺大的。也怪不得 Baron 家里这么多破事。提前救了 Black Beauty 达成了只有 Baron 一家存活的结局,想想也差不多吧。我寻思都是乡村,和百果园怎么相差这么多,想必是森林太密的缘故。我家乡的地形就是丘陵,走山路的体验我在现实当中也有,但是想不到可以给人这么压抑的体验,看来制作者在这方面还是比较用心的,只是给玩家太多负担了。到了 Novigrad 之后算是有点正常起来了。

回过头来自己想想,这里的怪物可以说是有理有据的。像所有的传说一样,这些怪物的形象也是有它们在现实生活中的依据。人们把看不见的病具象成妖怪,把强大的野狼夸张成狼人,把一些无法解释的现象造成的恐惧或者损失全部交给那些神秘的生灵。通过那些形象反推,这些就是中世纪人们生活写照了。然而自然的折磨还不够,人主的暴政也在同时摧残人们本就艰难的生活。游戏最开始看到的 Hangd Mans Tree 就在暗示这一点。毕竟村子里面哪来的那么多要吊死的。<未完>

Novigrad 的塑造就是一副中世纪城镇的样子,里面的生活虽然不是很现代,但是也至少可以接受一点。我觉得接下来的游戏体验应该会比较平缓了。进去就见到烧女巫,可惜经过前面的洗练,这种场景已经没法在我内心掀起波澜了。不过想想这游戏里面的世界也够黑暗的,一边是险恶的自然环境,一边是各种魔怔壬的统治,作为平民要生存下去真的很不容易。后面应该有更加复杂的剧情,我这里就玩到两人分头找 Dandelion 的女友,想想作者拿这个剧情来引导玩家探索城市还是比较幽默的。

先放在这里,我等到后面找到 Ciri 之后再填坑。

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

中文测试

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×