美文网首页
【笔记】配网项目工程量自动统计

【笔记】配网项目工程量自动统计

作者: W__hisky | 来源:发表于2019-10-11 11:24 被阅读0次

    前言

    本人最近参与了某地区的农网升级改造项目,项目前期,我们的设计人员到现场进行了实地勘测,并在Google卫星图影像上绘制出了配网线路的设计图,如图1所示为配网线路设计图示例。

    图1.配网线路设计图

    根据需求现在需要对整个项目的工程量做一个估计,为了得到这个估计我们就需要知道400V/220V线路上各有多少转角杆、直线杆以及沿墙等。由于整个项目包含的台区数量较多,如果靠人工手动地对各个类型的电杆进行统计速度较慢、效率低且工作量庞大。针对这一问题,我专门设计了一个算法分别对400V/220V线路上的转角杆、直线杆以及沿墙进行自动统计,利用Python语言对其进行了实现。

    400V/220V线路转角杆数量统计

    from pykml import parser
    import math
    
    # 文件打开
    KML_FILE = 'data.kml'
    with open(KML_FILE, 'r', encoding="utf-8") as f:
        kml = parser.parse(f).getroot()
    
    # 线上的“转角”、“非沿墙”点个数统计
    color = 'ffff0000'
    k_total = 0
    for each in kml.Document.Folder.Placemark: # 遍历所有的Placemark
        if each.name == '':   # 选择线
            if each.Style.LineStyle.color == color:   # 选择线颜色,ffff0000蓝色,ff00ff00绿色,ff0000ff红色
                k1 = 0   # 起始点、终止点统计
                k = 0    # 中间的统计
                # 将字符串坐标转换为列表
                coo = str(each.LineString.coordinates)   # 线坐标
                coo = coo.split(' ')
                # 去除列表空元素
                coo = [x for x in coo if x != '']
                # 将列表中的字符串元素更改为列表,即双重列表
                coo_new = []
                for i in coo:
                    i = i.split(',')
                    i = [ float(x) for x in i ]
                    coo_new.append(i)
                print(coo_new)
    
                # 判断起始点、终止点是否为“非沿墙”
                num = len(coo_new)
                for each2 in kml.Document.Folder.Placemark: # 遍历所有的Placemark
                    if each2.name != '':   # 选择点
                        if '沿墙' not in str(each2.name):
                            coo_point = str(each2.Point.coordinates).split(',')   # 将“点”的字符串坐标抓换为列表坐标
                            coo_point = [ float(x) for x in coo_point ]  # 将列表中的字符串元素更改为数字
                            # 统计线上“点”个数
                            if coo_new[0][0] - 0.00002 < coo_point[0] < coo_new[0][0] + 0.00002:
                                if coo_new[0][1] - 0.00002 < coo_point[1] < coo_new[0][1] + 0.00002:
                                    k1 = k1 + 1
                            if coo_new[num-1][0] - 0.00002 < coo_point[0] < coo_new[num-1][0] + 0.00002:
                                if coo_new[num-1][1] - 0.00002 < coo_point[1] < coo_new[num-1][1] + 0.00002:
                                    k1 = k1 + 1
    
                # 判断中间点是否为“转角”、“非沿墙”
                # 计算夹角
                for i in range(1,num-1):
                    x1 = coo_new[i-1][0]
                    y1 = coo_new[i-1][1]
                    x2 = coo_new[i][0]
                    y2 = coo_new[i][1]
                    x3 = coo_new[i+1][0]
                    y3 = coo_new[i+1][1]
                    dx1 = x1 - x2
                    dy1 = y1 - y2
                    dx2 = x3 - x2
                    dy2 = y3 - y2
                    x_max = x2 + 0.00002
                    x_min = x2 - 0.00002
                    y_max = y2 + 0.00002
                    y_min = y2 - 0.00002
                    angle1 = math.atan2(dy1, dx1)
                    angle1 = int(angle1 * 180/math.pi)
                    angle2 = math.atan2(dy2, dx2)
                    angle2 = int(angle2 * 180/math.pi)
                    if angle1*angle2 >= 0:
                        included_angle = abs(angle1-angle2)
                    else:
                        included_angle = abs(angle1) + abs(angle2)
                        if included_angle > 180:
                            included_angle = 360 - included_angle
                    # 夹角判断,若夹角小于175°,则该点为转角杆
                    if included_angle <= 175:
                        # 判断该中间点是否为“非沿墙”
                        for each1 in kml.Document.Folder.Placemark: # 遍历所有的Placemark
                            if each1.name != '':   # 选择点
                                if '沿墙' not in str(each1.name):
                                    coo_point = str(each1.Point.coordinates).split(',')   # 将“点”的字符串坐标抓换为列表坐标
                                    coo_point = [ float(x) for x in coo_point ]  # 将列表中的字符串元素更改为数字
                                    # 统计线上“点”个数
                                    if x_min < coo_point[0] < x_max:
                                        if y_min < coo_point[1] < y_max:
                                            k = k + 1
                k = k + k1   # 中间点统计结果加上起始点、终止点统计结果
                k_total = k_total + k
                print(k)
    print('总点数 %s' %k_total)   # 每种颜色线上的总的“点”个数
    

    在本项目中,所有的400V四线线路均用蓝色线表示,220V两线线路均用绿色线表示,在如上程序中,若将color赋值为蓝色‘ffff0000’,即统计的是400V线路转角杆数量,若将color赋值为绿色‘ff00ff00’,即统计的是220V线路转角杆数量。

    图2.400V线路转角杆数量统计结果 图3.220V线路转角杆数量统计结果

    400V/220V线路直线杆数量统计

    # 线上的“直线”、“非沿墙”点个数统计
    color = 'ffff0000'
    k_total = 0
    for each in kml.Document.Folder.Placemark: # 遍历所有的Placemark
        if each.name == '':   # 选择线
            if each.Style.LineStyle.color == 'ffff0000':   # 选择线颜色,ffff0000蓝色,ff00ff00绿色,ff0000ff红色
                k = 0    # 中间的统计
                # 将字符串坐标转换为列表
                coo = str(each.LineString.coordinates)   # 线坐标
                coo = coo.split(' ')
                # 去除列表空元素
                coo = [x for x in coo if x != '']
                # 将列表中的字符串元素更改为列表,即双重列表
                coo_new = []
                for i in coo:
                    i = i.split(',')
                    i = [ float(x) for x in i ]
                    coo_new.append(i)
                print(coo_new)
    
                # 判断中间点是否为“直线”、“非沿墙”
                # 计算夹角
                num = len(coo_new)
                for i in range(1,num-1):
                    x1 = coo_new[i-1][0]
                    y1 = coo_new[i-1][1]
                    x2 = coo_new[i][0]
                    y2 = coo_new[i][1]
                    x3 = coo_new[i+1][0]
                    y3 = coo_new[i+1][1]
                    dx1 = x1 - x2
                    dy1 = y1 - y2
                    dx2 = x3 - x2
                    dy2 = y3 - y2
                    x_max = x2 + 0.00002
                    x_min = x2 - 0.00002
                    y_max = y2 + 0.00002
                    y_min = y2 - 0.00002
                    angle1 = math.atan2(dy1, dx1)
                    angle1 = int(angle1 * 180/math.pi)
                    angle2 = math.atan2(dy2, dx2)
                    angle2 = int(angle2 * 180/math.pi)
                    if angle1*angle2 >= 0:
                        included_angle = abs(angle1-angle2)
                    else:
                        included_angle = abs(angle1) + abs(angle2)
                        if included_angle > 180:
                            included_angle = 360 - included_angle
                    # 夹角判断,若夹角大于175°,则该点为直线杆
                    if included_angle > 175:
                        # 判断该中间点是否为“非沿墙”
                        for each1 in kml.Document.Folder.Placemark: # 遍历所有的Placemark
                            if each1.name != '':   # 选择点
                                if '沿墙' not in str(each1.name):
                                    coo_point = str(each1.Point.coordinates).split(',')   # 将“点”的字符串坐标抓换为列表坐标
                                    coo_point = [ float(x) for x in coo_point ]  # 将列表中的字符串元素更改为数字
                                    # 统计线上“点”个数
                                    if x_min < coo_point[0] < x_max:
                                        if y_min < coo_point[1] < y_max:
                                            k = k + 1
                k_total = k_total + k
                print(k)
    print('总点数 %s' %k_total)   # 每种颜色线上的总的“点”个数
    

    在如上程序中,若将color赋值为蓝色‘ffff0000’,即统计的是400V线路直线杆数量,若将color赋值为绿色‘ff00ff00’,即统计的是220V线路直线杆数量。

    图4.400V线路直线杆数量统计结果 图5.220V线路直线杆数量统计结果

    400V/220V线路沿墙数量统计

    # 线上的“沿墙”点个数统计
    k_total = 0
    for each in kml.Document.Folder.Placemark: # 遍历所有的Placemark
        if each.name == '':   # 选择线
            if each.Style.LineStyle.color == 'ffff0000':   # 选择线颜色,ffff0000蓝色,ff00ff00绿色,ff0000ff红色
                k = 0    # 中间的统计
                # 将字符串坐标转换为列表
                coo = str(each.LineString.coordinates)   # 线坐标
                coo = coo.split(' ')
                # 去除列表空元素
                coo = [x for x in coo if x != '']
                # 将列表中的字符串元素更改为列表,即双重列表
                coo_new = []
                for i in coo:
                    i = i.split(',')
                    i = [ float(x) for x in i ]
                    coo_new.append(i)
                print(coo_new)
    
                # 判断点是否为“沿墙”
                num = len(coo_new)
                for i in range(num):
                    for each1 in kml.Document.Folder.Placemark: # 遍历所有的Placemark
                        if each1.name != '':   # 选择点
                            if '沿墙' in str(each1.name):
                                coo_point = str(each1.Point.coordinates).split(',')   # 将“点”的字符串坐标抓换为列表坐标
                                coo_point = [ float(x) for x in coo_point ]  # 将列表中的字符串元素更改为数字
                                # 统计线上“点”个数
                                if (coo_new[i][0] - 0.00002) < coo_point[0] < (coo_new[i][0] + 0.00002):
                                    if (coo_new[i][1]- 0.00002) < coo_point[1] < (coo_new[i][1] + 0.00002):
                                        k = k + 1
                k_total = k_total + k
                print(k)
    print('总点数 %s' %k_total)   # 每种颜色线上的总的“点”个数
    

    在如上程序中,若将color赋值为蓝色‘ffff0000’,即统计的是400V线路上沿墙点数量,若将color赋值为绿色‘ff00ff00’,即统计的是220V线路上沿墙点数量。

    图6.400V线路上沿墙点数量统计结果 图7.220V线路上沿墙点数量统计结果

    相关文章

      网友评论

          本文标题:【笔记】配网项目工程量自动统计

          本文链接:https://www.haomeiwen.com/subject/rltmuctx.html