内容提要
本文介绍了一个名为Squaria的大陆,它由一个SQL查询定义,具有高度不稳定的地理特征。文章讨论了河流和河湖的模拟,以及生成高度图和边界的方法。通过使用递归公共表达式(CTE)和空间函数,可以生成具有山脉、河流和湖泊的地形。最后,文章还讨论了河流的合流和分流问题,并提供了最终的脚本。
延伸解读
递归CTE的迭代本质与输出处理
文章指出,PostgreSQL中的递归CTE实际上是迭代执行:基础项先求值放入工作表,递归项反复执行直到工作表为空。输出包含工作表的所有历史记录,因此每个河流会有多行记录。最终查询通过自连接只保留每个河流的最后一步,这提醒读者在使用递归CTE时需注意结果集包含中间状态,必须显式过滤。
湖泊形成机制与局部最小值处理
河流可能流入被更高邻居包围的局部最小值区域。文章通过模拟湖泊蓄水来提升当前单元格的有效高度,使河流有机会流出。每次迭代高度增加2,最多尝试5次,可克服最多8个高度差。若仍无法流出,河流终止于内流湖。这一机制解决了内流盆地问题,但也引入了河流交叉的潜在悖论。
河流合流与分叉的修剪逻辑
当两条河流汇合后,若继续共享路径会导致重叠。文章通过修剪步骤解决:首先移除所有非最终记录,然后检测不同河流间共享的质心,并确定合流点。对于每条河流,在合流点处截断,确保支流只是支流,不会延续下游。这保证了河流网络的拓扑正确性,避免同一空间被多条河流占用。
Q&A
Squaria大陆的边界是如何定义的?
Squaria的边界由100单位包络内的Voronoi图定义,类似于Paul Ramsey的随机多边形生成方法。
如何生成Squaria的高度图?
高度图通过计算每个Voronoi多边形到山脉的距离,结合x坐标和随机噪声来生成高度值。
河流的源头是如何选择的?
河流源头从高度低于90且不接触边界的多边形中随机选择30个,也可以使用网格来更均匀地分布源头。
递归CTE在河流生成中是如何工作的?
递归CTE通过迭代方式工作:基础项初始化河流,递归项检查邻接多边形,选择较低且未访问过的邻居,并处理湖泊形成以克服局部最小值。
河流合流时如何处理重叠问题?
通过修剪操作,检测并移除与其他河流共享质心的河流部分,确保支流在合流点终止,避免重叠。
湖泊在河流模拟中起什么作用?
湖泊通过增加当前单元的有效高度,使河流能够克服局部最小值并继续流动,每个湖泊单元最多增加5次,每次增加2个高度单位。