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

前言

本人最近参与了某地区的农网升级改造项目,项目前期,我们的设计人员到现场进行了实地勘测,并在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线路上沿墙点数量统计结果

你可能感兴趣的:(【笔记】配网项目工程量自动统计)