设备所在楼层
1. 设备有ModelId信息点 (模型web服务的模型id)
2. 楼层有ModelId信息点 (模型web服务的楼层id)
3. 设备没有所在楼层关系
4. 设备有Location(非必要)
5. 楼层有Outline(非必要)
1. 如果楼层有Outline, 设备有Location, 做点(Location)在多边形(Outline)内的判断, 点在多边形内则认为有关系
2. 如果不满足条件1, 即楼层没有Outline, 设备没有Location, 则判断它们ModelId信息点的值, 相等则认为有关系
(此处的相等表示设备上的ModelId信息点在关系上从属于楼层上的ModelId信息点, 即模型web服务中的模型id属于楼层id)
1. 做点在多边形内的判断, 使用到了python的 shapely 库 中的 Path 类的contains_points 方法
源码
-- 设备所在楼层
CREATE OR REPLACE FUNCTION "public"."rel_eq2fl"("project_id" varchar)
RETURNS "pg_catalog"."bool" AS $BODY$
from matplotlib.path import Path
import json
def is_in_meta_polygon(x, y, json_poly):
try:
poly = []
polygon = json.loads(json_poly)
l = len(polygon)
points = (float(x), float(y))
for i in range(l):
pair = polygon[i]
poly.append((pair["X"], pair["Y"]))
p = Path(poly)
except Exception as e:
plpy.info(e)
return False
else:
return p.contains_points([points], None, -0.0001)
model_floor_map = dict()
def get_model_floor(model_id):
try:
if model_id in model_floor_map :
return model_floor_map[model_id]
model_floor_plan = plpy.prepare("select model_floor_id from revit.model_file where id = $1", ["text"])
model_floor_arr = model_floor_plan.execute([model_id])
if len(model_floor_arr) == 0:
return None
model_floor = model_floor_arr[0].get('model_floor_id')
model_floor_map[model_id] = model_floor
return model_floor
except Exception as e:
return None
try:
# 将下面对数据库的操作作为一个事务, 出异常则自动rollback
with plpy.subtransaction():
floor_plan = plpy.prepare("select id, outline, model_id from floor where project_id = $1 and model_id is not null", ["text"])
floors = floor_plan.execute([project_id])
equip_plan = plpy.prepare("select id, bim_location, model_id from equipment where project_id = $1 and model_id is not null", ["text"])
equips = equip_plan.execute([project_id])
for floor in floors:
for equip in equips:
outline = floor['outline']
location = equip['bim_location']
if outline == None or len(outline) == 0 or location == None or len(location) == 0:
model_floor_id = get_model_floor(equip['model_id'])
if model_floor_id is None:
continue
if floor['model_id'] == model_floor_id:
equip['floor_id'] = floor['id']
continue
location = location.split(',')
try:
if floor['model_id'] == model_floor_id:
if is_in_meta_polygon(location[0], location[1], outline):
equip['floor_id'] = floor['id']
except Exception as ex:
continue
for equip in equips:
if equip.__contains__('floor_id'):
try:
#plpy.info("equip id {0}, floor id {1}".format(equip['id'], equip['floor_id']))
plan = plpy.prepare("update equipment set floor_id = $1 where id = $2", ["text", "text"])
plan.execute([equip['floor_id'], equip['id']])
except Exception as ex:
continue
except Exception as e:
plpy.warning(e)
return False
else:
return True
$BODY$
LANGUAGE plpython3u VOLATILE
COST 100
select public.rel_eq2fl('Pj1101010015');
1. 项目id
true 成功
false 失败