GIS多边形分割裁剪
多边形分割是常用的数据编辑形式之一,turf.js 实现了对线的分割与共边面的合并,通过turf能够实现对面的分割,但是在实现的过程中,我们不得不对各种问题进行解决,才能实现对面分割的效果。
3D模型在线预览提供多种低代码平台3D模型在线预览解决方案,实现了将多种3D模型格式无缝集成到低代码业务表单中。这意味着用户可以在不离开低代码平台的情况下,直接查看和操作3D模型,极大地提升了数据可视化的效果和用户交互体验。
说明
当前实现的分割只是基础版本,有以下限制:
- 仅支持操作规则多边形,不支持环形多边形
- 仅支持将一条分割线将面分割成两个面,不支持一刀多切
以上所说的缺陷可以在后续有实际需求时实现。
分割逻辑
- 面转线获得pLine
- 获取pLine与splitLine的交点
- 用交点分别对两条线进行分割
- 获取分割线
- 获取被分割的pLine
- 将被分割的pLine合并成两条线
- 将两条pLine与分割合并成面,即被分割的两个面
- 增加检测判断
步骤详解
1
将面转成线直接使用turf.polygonToLine便能达到效果,再使用turf.lineIntersect获得两者的初步交点。
2
在步骤1时获取到交点,当交点数量为2时,便符合分割线的一般逻辑,然后获取分割线和被分割的面
最初,我获取上述两者使用的是turf.lineSplit,但是发现这个方法在一些情况下有问题,于是自己重写了lineSplit(仅能使用点分割),之后便获得了被两个点分割的三条线,判断这三条线哪一条是真正的分割线(起点与终点都在线上)。 用同样的方式又获得面被分割的三条线,这时候将三条线拼成两条线,便成功获取到两条面的被分割线。
3
我们拿到分割线与面的两条线,接下来需要将他们拼成面,一开始我使用的是turf.polygonize,但因为精度问题,导致无法顺利的拼接成面,于是便写了一个方法,将原本相连的两条线段合并成一条线段,这样便形成一个闭环的线段,最后生成面即可。
4
在实现分割的基础逻辑后,需要对各种分割线情况进行判断并作出处理,以下是我所做的处理:
- 检测分割线是否符合逻辑,必须要保证只有两个交点,如果交点少,或者没有交点,便反馈为不正确分割线。
- 在步骤1中,我将用turf.lineIntersect所获取的交点称为初步交点,这是因为这里获取的交点,如果直接使用,由于turf分割有精度省略的问题,导致分割不成功,不过后面换成了自己写的分割,这一步检测可以省去。
- 如果分割线本身的起点和终点在面的线上,获取的初步交点有可能是缺失的,需要对这类情况进行补点。
- 对获取的初步交点进行校正,通过turf.nearestPointOnLine重新获取交点,对交点进行校正。
Q&A
turf分割中最大的问题
- 实现分割的主要依托为turf,但turf本身很多方法有精度问题,使是同一个点,点在线上的情况没有判断出来,导致结果出现问题。目前已知有精度问题的有:lineIntersect、polygonize、lineSplit。
获取分割线
- 一条线被两个点分割成三条线,已知两个点的坐标,用这两个点与三条线的始末两点进行比较,符合条件的是分割线。
获取需要合并两条线
- 面转线后,它同样被两个点分割成三条线,我们需要把其中两条合成一条,同获取分割线,用同样的方式能获取到需要合并的两条线。
合并线的思路
- 合并有公共点的两条线,关键在于找到线的顺序,所以需要拿两条线的始末点分别进行比较,找到他们的公共点的位置,根据比较结果将坐标数组反转,去除一个共同点,最后将数组合并。
用点分割
- 由于turf的精度问题,于是重新实现了用点分割线,实现逻辑比较简单,循环获取线上每一个线段,在获取分割点到线上最近的点的位置(nearestPointOnLine),比较分割点与最近点是否是同一个点,如果是则记录一下当前线段的序列,按当前序列将线的坐标数组分割成两个(slice),这样便实现了用点分割线。
引入精度
- 如上文所说,很多问题都是以为turf的精度问题所造成的,所以改分割类添加了一个参数——精度,可以在不同的场景下,传入不同精度,例如,默认精度是6,也就是经纬度小数位到六位,在判断点是否是同一个点时,只要小数位六位(包括六位)之前的是一样的,便确保是同一个点。添加这样一个参数,便可以将很多不可控的问题便为可控。
总结
当前实现的分割比较基础,但好在增加了很多判断,让程序出错或判断错误的情况降低,如果业务需要,也可以在此基础上实现“一刀多切”的分割、及环形多边形的分割以及多边形挖洞这些功能。
与裁剪相对的功能——合并,虽然turf的合并同样有一些问题,不过问题并不像分割这么多,稍作简单判断就能使用,后面业务有实际需求时,可以再考虑重写合并。