一、准备工作

由于传统的二维地下管线难以准确、直观地显示管线的空间位置关系。在一些城市的市政项目中,三维管线作为反映管线空间关系的一种新方式,弥补了二维管线在直观性、可视性方面的不足,成为管线生成的首选方式。

目前生成三维管线的软件很多,比如UG、CAD等。现在,我们尝试用FME生成三维管线。给出的数据如下:

管线线属性表1-1 (Excel)

三维管线python 三维管线检查_碰撞检测

            管线点属性表1-2 (Excel)

三维管线python 三维管线检查_数据_02

 

截取部分效果图(至于如何生成三维管线,稍后再说):

图1-1

三维管线python 三维管线检查_碰撞检测_03

图1-1的黑框显示了两种类型管线的相交部分。对于少量的数据,从生成的管线当中,我们可以很容易辨别出哪些管线是相交的。但是,当你面对一个县或一个市区的数据时,这恐怕就变成了一个令人头疼的问题。

当然,FME提供了获取三维实体相交部分的转换器Clipper、CSGBuilder。如果你想偷一下懒,你可以尝试将所有的三维实体作为输入,运行转换器模板。结果一定会让你印象深刻——可能一两天内,你的模板都无法运行出结果。这促使我们寻找能够优化数据的方法。

最直接的想法就是将三维的管线降成二维来做。在做二维相交之前,先给出管线相交的一些规则(规则1):

    1、两管线在管点处相交。也就是两管线共用一个管井,不作为管线相交部分。

    2、两管线在非管井处相交,将相交部分的实体取出,作为管线相交位置。

 

即下列两种情况:

                                        

三维管线python 三维管线检查_碰撞检测_04

不相交                 

三维管线python 三维管线检查_数据_05

相交

 

咳咳……,貌似有点跑题了。这一部分的工作主要是为了后面三维管线相交作相关的说明。下面,我们正式进入相交检查部分。

二、二维相交处理

对于给定如表1-1、表1-2的条件下,依据点表跟线表的属性挂接,可以很容易获取管线起点、终点的x、y、z坐标。

先贴一个二维管线线图:

 

图2-1

三维管线python 三维管线检查_数据_06

 

     从图2-1看到,二维线是纵横交错的。可能有人会说,既然已知二维线,为何不直接用二维线判断管线之间的相交关系?如果直接利用二维线,会漏掉下面的相交类型(图2-2):

                                            

三维管线python 三维管线检查_碰撞检测_07

 图2-2右边是三维管线实体在二维上的投影。当然,我们这里所说的相交是“疑似相交”,它只是二维上的相交,在三维空间上,可能会不相交。

如此,在二维平面上,我们考虑对二维线作缓冲,由于各个管线的角度、管直径(或宽、高)的不同,真实的三维管线投影在端点处是有所区别的——不同的椭圆和长方形。如果你想获得真实的缓冲区(不考虑误差的情况下),可能你需要对端点处的缓冲作一些处理。

 

如果一开始模板制作,就要考虑角度,进行计算,未免有点让人沮丧。我们不妨贪心一点,不管角度如何,都按照最大的缓冲面积来计算。缓冲区生成(图2-3):

图2-3

三维管线python 三维管线检查_碰撞检测_08

 

按照上述步骤生成缓冲区之后,利用面之间的压盖关系就可以获得相交的管线信息了。

如果模板做到这里你会发现,相交的数据也是不少的。或许你觉得只在xOy平面作投影完全不够,你可以在yOz平面、xOz平面也作相同的投影,如果在三个面的投影都相交,则当做相交的面处理。这样可能会减少相交的数据量。但是,作三个面的投影,势必会增加数据的存储量和处理数量,判断在三个坐标平面上的投影都相交也会增加时间和计算量。如果你有兴趣,可以尝试着做一下。

面之间进行压盖运算之后,按照(规则1)的要求,我们需要把在管点(管井)处相交的这部分数据去掉。这需要将相交的管线数据跟原始的管线数据(类似于图2-1)作比较,从中剔除掉不符合规则的部分。

 

图2-4

三维管线python 三维管线检查_二维_09

  

接下来,我们讨论在三维层面的管线相交情况。

三、三维管线处理

前面我们已经在二维上将“疑似相交”的管线找出,二维上的筛选已经去掉了一部分的数据,而且我们还将相交的管线以分组的形式表示出来。但是,对于大量的Excel数据来说,这显然是不够的。我们还需要在三维上作一些过滤。对于多面体的相交检测,现在主要运用碰撞检测进行计算。

在三维空间中,基本的图形要素就是点、线、面。其中,面要素是相对比较复杂的。现有的碰撞检测主要跟多面体的面、棱有关。因为圆柱体和立方体的面比较多,情况比较复杂,我们可以先根据两者中心线的距离来进行判断。

圆柱体之间距离遵循下列规则(规则2)时,作为“疑似相交”:

1、如果两圆柱之间的距离小于两者的半径之和,则两圆柱体相交。

给定的数据中既有立方体,也有圆柱体,我们把立方体当做圆柱体来做,圆柱要完全包含立方体。经过这部分的筛选,“疑似相交”的管线组会减少很多。又计算两线段之间的距离比较好实现,在碰撞检测之前做这样的筛选是很有必要的。

接下来,我们说一说碰撞检测。

三维物体碰撞检测的实现一直是一个难点,特别是对于比较复杂的三维实体。由于管线数据只有两类模型:圆柱体和立方体。实际上我们需要讨论的只有圆柱体之间的碰撞检测,立方体之间的碰撞检测,以及圆柱体和立方体之间的碰撞检测。

立方体之间的碰撞检测是很好实现的。现有的OBB方向包围盒算法就可以实现此碰撞检测。只是在实现过程中,需要考虑立方体的旋转角度、每个表面的法向以及顶点坐标等。三维OBB方向包围盒的算法实现如下,

参考资料:http://www.2cto.com/kf/201410/339595.html

圆柱体之间的碰撞,因为时间的关系,没有在模板中实现。具体算法文献如下,

参考资料:http://www.realtimerendering.com/intersections.html

或者你可以将圆柱以它的包围盒来进行计算。这样简化的效果如何?我想还是跟圆柱体的管径、圆柱之间的距离以及方向包围盒的三个法向的方向等相关。

圆柱体与立方体之间的碰撞检测暂时未找到参考文献。可以将立方体的六个表面,分别作面与圆柱体的碰撞检测。可以查看上面链接的相关资料。如果你有兴趣,可以尝试将上面三种类型的碰撞检测都实现一下。相交处理部分(图3-1):

 

图3-1

三维管线python 三维管线检查_三维管线python_10

 

在实际碰撞检测的计算过程中,可能由于误差或者其他因素,不一定能够将所有的相交管线都找出来。但是,经过一层层的检测筛选,“疑似相交”的管线数量已经减少了很大一部分。此时,我们就可以利用FME自带的3D转换器进行最后的相交位置提取(图3-2)。

 

图3-2

三维管线python 三维管线检查_二维_11

三维管线相交部分就暂时讨论到这里。前面的讨论只是提供了一种实现相交位置提取的方式。不一定是最优、最简的方式。莎士比亚说:“一千个读者,就有一千个哈姆雷特”。无论你在阅读过程中,是感觉眼前一亮还是平淡无奇,只要能够引起你的思考,于我而言,也是倍感荣幸的。

后面部分我们来谈谈前面搁置的问题——如何生成三维管线。

三、三维管线生成

三维管线主要分为两个类型:圆柱或立方体。我们已知管线的中心线(或端点的x、y、z坐标),以此构造三维管线。

首先在坐标原点将圆柱或立方体底面,也就是横截面构面;然后,对底面进行z轴方向的拉伸,生成圆柱或立方体;接着,对拉伸后的圆柱或立方体进行旋转,旋转后的轴线方向与初始管线的方向一致,然后对三维实体进行坐标平移。具体的方法如下图(网上截图,图4-1):

图4-1

三维管线python 三维管线检查_碰撞检测_12

 在立方体的生成过程中,由于立方体旋转会导致底面的旋转,在立方体旋转之前,应事先对立方体底面作相应的旋转处理。

还有一点需要注意的是,对于中心轴与z轴平行的立方体,究竟底面是否旋转;如果旋转,宽和高的方向是否跟此立方体同管点的管线有关,也需要根据具体的情况来分析。生成三维管线(图4-2)。

图4-2

三维管线python 三维管线检查_三维管线python_13

OK,三维管线的这部分讨论到此就告一段落了。在三维管线的可视化方面,仍然有不完整的地方——没有涉及管线接口处弯头、三通、四通的处理。FME模板生成弯头、三通、四通会比较复杂。如果同管井的管线中心线不在一个平面上,弯头、三通、四通会变得更复杂。所以,也只有留点遗憾在这里了。