1. 业务空间有所属楼层关系
2. 设备有所属楼层关系
3. 业务空间有轮廓数据(outline信息点)
4. 设备有坐标信息(bimLocation信息点)
Eq2Fl, Sp2Fl
1. 取出项目内的所有业务空间和设备, 将在同一楼层内的设备和业务空间分成一组
2. 在一组内, 判断设备的bim_location是否在业务空间的outline内, 即做点在多边形内的判断, 点在多边形内则认为有关系
源码
CREATE OR REPLACE FUNCTION "public"."rel_eq2sp"("tables" text, "out_tables" text, "project_id" varchar, "sign1" int4, "sign2" int4)
RETURNS "pg_catalog"."bool" AS $BODY$
from matplotlib.path import Path
import json
def is_in_meta_polygon(point, single_poly, radius):
poly_len = len(single_poly)
poly = []
for i in range(poly_len):
pair = single_poly[i]
poly.append((pair["X"], pair["Y"]))
p = Path(poly)
return p.contains_points([point], None, radius)
def is_in_polygon(point, polygons):
polygons_length = len(polygons)
if polygons_length == 0:
return False
for j in range(polygons_length):
polygon = polygons[j]
if j == 0:
if not is_in_meta_polygon(point, polygon, -0.001):
return False
else:
if is_in_meta_polygon(point, polygon, 0.001):
return False
return True
def is_point_in_polygon(x, y, json_poly):
try:
polygon_list = json.loads(json_poly)
total_len = len(polygon_list)
point_pair = (float(x), float(y))
for index in range(total_len):
if is_in_polygon(point_pair, polygon_list[index]):
return True
return False
except Exception as e:
plpy.info(e)
return False
# 将下面对数据库的操作作为一个事务, 出异常则自动rollback
input_table_list = tables.split(',')
output_table_list = out_tables.split(',')
with plpy.subtransaction():
for i in range(0, len(input_table_list)):
in_table_name = input_table_list[i]
out_table_name = output_table_list[i]
# 删除原来关系表中的数据
plan1 = plpy.prepare("delete from {0} where project_id = $1 and (sign = $2 or sign = $3)".format(out_table_name.strip()), ["text", "integer", "integer"])
plan1.execute([project_id, sign1, sign2])
# 计算关系
plan_floor = plpy.prepare("select id from floor where project_id = $1", ["text"])
floors = plan_floor.execute([project_id])
# 按楼层计算
for floor in floors:
floor_id = floor['id']
# 获取楼层下的设备
plan_equip = plpy.prepare("select id, bim_location from equipment where project_id = $1 and bim_location is not null and floor_id = $2", ["text", "text"])
equips = plan_equip.execute([project_id, floor_id])
if len(equips) == 0:
continue
# 获取楼层下的业务空间
space_plan = plpy.prepare("select sp.id, sp.outline, sp.object_type from public.r_sp_in_fl rel inner join {0} sp on rel.space_id = sp.id where outline is not null and rel.floor_id = $1".format(in_table_name), ["text"])
spaces = space_plan.execute([floor_id])
if len(spaces) == 0:
continue
# 判断设备的bim_location是否在业务空间的outline内
for equip in equips:
for space in spaces:
try:
location = equip['bim_location'].split(',')
if is_point_in_polygon(location[0], location[1], space['outline']):
# 设备在业务空间内, 添加关系
insert_plan = plpy.prepare("insert into {0}(eq_id, sp_id, project_id, sign, type, zone_type) values($1, $2, $3, 2, 'eq2sp_in', $4)".format(out_table_name.strip()), ["text", "text", "text", "text"])
insert_plan.execute([equip['id'], space['id'], project_id, space['object_type']])
except Exception as ex:
plpy.warning(ex)
continue
return True
$BODY$
LANGUAGE plpython3u VOLATILE
COST 100
例子:
select public.rel_eq2sp('zone_general,zone_lighting', 'r_eq_in_sp_zone_general,r_eq_in_sp_zone_lighting', 'Pj1101010015', 2, 2);
1. 参与计算的业务空间表的全名称, 带schema名, 以英文逗号隔开
2. 关系计算结果存储的表, 跟第一个参数一一对应, 带schema名, 以英文逗号隔开
3. 项目id
4. 要被删除的sign, 只能是int型, 值为1或2 (1表示手动维护的关系, 2表示自动计算的关系)
5. 第二个要被删除的sign, 只能是int型, 值为1或2 (1表示手动维护的关系, 2表示自动计算的关系)
true 成功
false 失败