程序生成的行星表面上的不规则瓷砖

在这里,我们将考虑一种用不规则的瓷砖划分程序生成的行星的球面的方法,并因此将海洋和大洲划分为单独的部分(扇区)。 我们假设已经使用一些GIS设置了地球表面的陆地结构,并且可以将矢量数据导出到ESRI shapefile或直接导出到具有PostGIS扩展名的PostgreSQL数据库。 创建扇区的过程是使用PostGIS进行的。

请参阅文章底部的带有SQL代码的脚本链接,此处的解释将更加实际。 该说明提供了脚本的基本功能,并且还假设可从伪造地图网站(comgedmaps.com)获取程序生成的行星的大陆和河流的数据可用性。

不规则瓷砖的选择使我们能够精确地细分行星的表面
划分为多个部分,通常不会在任何地方混合海洋和陆地。 湖泊和内陆海洋
我们认为它是土地的一部分。 我们还将看到如何将河流用作部门的自然边界。 扇区本身将基于球体的基本多边形划分而构建。

在划分平坦区域时,通常使用Voronoi图获得不规则的瓷砖。 同样使用Lloyd算法 ,我们可以得到大小上差别不大的凸多边形的视觉吸引形式(Centroidal Voronoi细分)。 劳埃德算法的本质是在每次后续迭代中都重复Voronoi图的构造,以在先前迭代中获得的多边形的中心为生成点。

我们将对球面的多边形基本划分施加某些要求:
球形多边形的凸度及其与给定平均尺寸的偏差不是很大。

由于图块通常具有基本含义,例如,用作战略游戏的图块卡的单元部分或某个表面的单元部分, 因此使用名称扇区来代替图块 。 该部门内部有一个内部结构:浮雕和各种地理对象。 反过来,扇区也可以用作基本的图块:建立扇区之间可能的过渡图可达到此目的。

球体和海洋部分的基本划分。


PostGIS具有一个ST_VoronoiPolygons的函数,该函数在正方形区域中构建Voronoi图。 让我们看看如何将其用于我们的目的。

如果您尝试使用简单的方法会怎样? 行星的矩形投影可以通过坐标转换为正方形,在其中构建多边形并执行坐标的逆变换。 但是,以这种方式构造的矩形将在一个方向上拉伸,这是不希望的。 而且,如果您尝试应用劳埃德算法,那么靠近球体两极的矩形的面积(在球体上)将比靠近赤道的面积小得多。

让我们尝试通过消除缺点来适应这种方法。 选择Voronoi图的随机起点,以便它们在球体上均匀分布。 在墨卡托投影中,这意味着在极点处,它们出现的频率应减少,且概率与纬度余弦成比例。 我们正在“世界”多边形中构建Voronoi图-这要么是行星的整个矩形投影,要么只是其中的一部分。 ST_VoronoiPolygons函数本身将矩形完成为正方形,我们只需要根据“世界”多边形裁剪结果图。

我们看一下以自适应方式获得的Voronoi多边形的图片。 这是测试行星地图的一部分,从上边缘的赤道到下边缘的南纬73度。 (这里的土地已经被填埋场砍掉了。)

图片

在墨卡托投影上可以看到,多边形在接近极点时通常较大,但按面积大小,它们将大致均匀地分布在球体上。 这就是我们所需要的。 但是,还可以看到,多边形的面积分布非常大,并且整体外观并不美观。

让我们尝试应用Lloyd算法的多次迭代。 作为新点
对于Voronoi图的后续迭代,我们将选择已修剪的中心
“世界”多边形Voronoi多边形。 为了防止极点附近的多边形面积减少太多,我们仅进行少量迭代(大约3次)。

为了获得海段,将土地占用面积从获得的垃圾填埋场中排除。 结果,可以形成小的多边形,希望将其附着到相邻的多边形上。 同样,小多边形可能靠近“世界”多边形的边界。 我们以选择“最近”的邻居而不破坏全局的方式连接多边形。

应用了这种改进的算法后,我们获得以下图片,这可能已经可以接受了。 图中的红色部分表示所需的多边形合并。

图片

可以以不同的方式选择用于合并的多边形。 在上述脚本中,实现了两种方法:在最长的边界上和在最近的中心上。 下图显示了第二种方式的合并结果。

图片

总的来说,我们已经实现了海洋部门可以期望的目标。 它们的面积(在球体上)大致相同,并且是凸的或与凸的偏差很小。

产生海洋部门的主要功能:

 map.makeOceanSectors( world Geometry, avg_vp_areaKM Double Precision, merging_ratio Double Precision, merging_method Int ) RETURNS Void 

world - «世界»垃圾填埋场服务于世界的边界。
avg_vp_areaKM形成海洋扇区的多边形的平均面积(km 2 )。
merging_ratio - merging_ratio份额,这样,如果扇区面积小于它,则它将附加到相邻的扇区。
merging_method合并方法(“ 1”或“ 2”)。

一个例子。 我们正在给定的“世界”垃圾填埋场中建设部门,平均基本垃圾填埋场面积为1,000,000 km 2 。 面积小于此大小一半的扇区将合并在一起。 使用第二种合并方法-在最近的中心。

 SELECT * FROM map.makeOceanSectors( ST_GeomFromText( 'POLYGON((-75 -85, 75 -85, 75 85, -75 85, -75 -85))', 4326 ), 1000000, 0.5, 2 ); 

各大洲的部分。


在大陆上,您可以根据一方面较小的基准范围的总数,另一方面基于河流和分水岭等自然物体,来输入更有趣的分区。 这样获得的结构与其中的州和省的地图非常相似。 也就是说,这是从程序上产生世界政治地图的过程

与海段不同,凸起完全是可选的。

forgedmaps.com尚无分水岭,但已经有河流。 在脚本中使用河流需要在MultiLineString中表示它们。 他们在riversz shapefile中有这个想法。 导入数据库时​​,您可以在此过程中立即消除多余的z坐标。 其他必需的数据(即陆地区域的边界)位于land shapefile中。 每个陆地区域都有一个aid (区域ID)标识符,并且可以由大陆和最近的岛屿组成,或者仅由附近的小岛屿组成。

在我们的例子中,我们选择部门在40000 平方公里的平均尺寸和5000 平方公里的基础多边形的平均大小 这是一个相当大的尺寸,选择它只是为了说明。 也可以使用较小的大小(最大为m 2 ),但是要跟踪计算时间并使用适当的数据库配置。

在此图片中,示例了基本多边形在陆地区域内部的外观。

图片

下一步是将基础多边形合并为扇区。 为此,请从基础多边形中随机选择要创建的扇区,然后逐渐将相邻多边形附加到累积扇区上。

图片

现在是时候考虑河流问题了。 我们使用它们将部门划分为
通过ST_Split函数分离零件。 可以根据某些条件进行这种划分:最终河流流量或分离部分的面积。

现在我们可以看到沿河的边界如何。

图片

我们将一小部分部门连接到大部门。 但是我们必须尝试
请勿将零件连接到其被切断的同一扇区。

图片

我们管理着大片土地,但仍然是小岛。 我们将那些具有接近该部门平均面积的区域作为一次性部门。 但是对于那些面积比平均行业小得多的企业,我们正在做两件事。

1.如果这些岛屿与现有地区的距离相对较远,那么我们将它们划分为单独的地区。 这里的“稀疏度”取决于给定的部门平均面积:该区域越小,该岛成为独立部门的可能性就越大。

2.如果该岛靠近已经创建的其他扇区,则将其与其中之一合并。 即,使用ST_Buffer从该岛获得的某个多边形中具有最大面积的区域。

图片

在这里,四个岛屿分为两个不同的部分。 如果增加设置的平均扇区面积,迟早所有岛屿将落入一个扇区。

在陆地上产生部门的主要功能:

 map.makeLandSectors( aid BigInt, avg_vp_areaKM Double Precision, avg_sector_areaKM Double Precision, max_sector_cut_area_ratio Float, pref_min_island_area_ratio Float, min_streamflow Int ) RETURNS Void 

aid地块的标识符。
avg_vp_areaKM的平均面积(km 2 )。
avg_sector_areaKM平均面积(km 2 )。
max_sector_cut_area_ratio - max_sector_cut_area_ratio的份额,该份额确定河流可以截断的最大面积。
pref_min_island_area_ratio - pref_min_island_area_ratio的份额,该份额确定了最小面积,岛屿立即拥有该最小面积成为单独的扇区。
streamflow -如果河流的最终流量至少为该值,则它参与切割部分。

在以下示例中,使用该函数将在辅助= 5的土地上创建扇区。 所述基本多边形与5000公里2的平均面积被用来与的40000公里2的平均面积创建扇区 同时,河流切断的最大领土为0.125 * 40,000 km 2 ,而0.25 * 40,000 km 2是岛屿立即成为扇形的最小面积。 为了按河段切割,使用最终径流量最小为2的河。

 SELECT * FROM map.makeLandSectors(5, 5000, 40000, 0.125, 0.25, 2); 

参考文献


可用SQL脚本代码完成所有工作,包括创建扇区和在相邻扇区之间建立过渡图。 来自程序生成的行星的GIS数据可以从伪造的maps.com获取 。 您可以使用GIS Earth数据 ,使它们形成类似的结构。 您还可以使用任何现代GIS从头开始手动制作数据,或通过转换从任何其他来源接收的数据来获取新数据。 可以在手册中找到有关脚本的更完整说明。

Source: https://habr.com/ru/post/zh-CN414699/


All Articles