管网系统设备分块
## 前置条件
1. 项目下的模型文件已上传；
2. 所有管网已正确连接；
3. 相邻层立管开放端口坐标位置相等（距离差值不能超过0.01）
4. （非强制）通过模型检查：连接件检查、系统类型名称检查、管网及相关设备检查、管段检查

## 处理方式

1. 获取所有当前项目project_id下的的有模型文件models； 表：revit.model_folder、revit.model_floor、revit.model_file
2. 遍历models，获取model层的系统图systemGraphs；
    1. 获取model下且domain、systemName符合条件的connector,connectors，表：revit.connector
    2. 获取model下所有的设备、部件、其它、风管、水管，表：revit.equipment、revit.component、revit.other、revit.pipe、revit.duct
    3. 获取model层的系统图数据，存在systemGraphs中。
3. 获取systemGraphs中所有的开放立管，按开放立管对连接的系统图systemGraphs进行合并；
4. 删除本项目下project_id、指定系统类型systemName,指定域domain，所有数据，表revit_calc.connected_block
4. 将合并后的数据存入数据库，表：revit_calc.connected_block。


# 函数
```
create or replace function public.sys_block(project_id character varying,building_id character varying,system_name character varying,domain character varying) returns boolean
as
$$
from relations.src.system_relation import systemutils, graph_model

def get_models(project_id,building_id):
  sql ="select " \
		"id,name,local_id,local_name,sequence_id,model_id,building_id,project_id " \
		"from floor " \
		"where project_id=$1 " \
		"and ($2 is null or building_id=$2) " \
		"order by sequence_id desc"
  join_plan=plpy.prepare(sql,["text","text"])
  data=join_plan.execute([project_id,building_id])
  models=systemutils.sqldata2objlist(data)
  return models

def get_connectors(model_id, system_name, domain):
  sql = "SELECT * FROM revit.connector where model_id=$1 and mep_system_type=$2 and domain=$3"
  join_plan=plpy.prepare(sql,["text","text","text"])
  data=join_plan.execute([model_id, system_name, domain])
  floor_connectors=systemutils.sqldata2objlist(data)
  return floor_connectors
def get_elements(model_id):
  floor_elements=[]
  sql="select * from revit.equipment where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))

  sql="select * from revit.component where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))

  sql="select * from revit.other where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))

  sql="select * from revit.join_object where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))

  sql="select * from revit.pipe where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))

  sql="select * from revit.duct where model_id=$1"
  join_plan=plpy.prepare(sql,["text"])
  data=join_plan.execute([model_id])
  floor_elements.extend(systemutils.sqldata2objlist(data))
  return floor_elements
def delete_block_data(project_id,building_id,system_name,domain):
  sql="delete from revit_calc.connected_block " \
		  "where project_id=$1"\
		  "and mep_system_type=$2" \
		  "and domain=$3" \
		  "and ($4 is null or building_id=$4)"
  join_plan=plpy.prepare(sql,["text","text","text","text"])
  join_plan.execute([project_id,system_name,domain,building_id])
def save_edge_data(edge,block_id,system_name,domain,building_id):
  vertex1=edge.start_vertex
  vertex2=edge.end_vertex
  c1=vertex1.system_data
  c2=vertex2.system_data
  floor1 = vertex1.get_parent_floor()
  floor2 = vertex2.get_parent_floor()
  model1= floor1.model
  model2 = floor2.model
  sql="insert into revit_calc.connected_block" \
    "(id1,type1,model_id1,id2,type2,model_id2,block_id,project_id,mep_system_type,domain,building_id) values " \
    "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)"
  join_plan=plpy.prepare(sql,["text","text","text","text","text","text","text","text","text","text","text"])
  join_plan.execute([c1.id,c1.type,model1.model_id,c2.id,c2.type,model2.model_id,block_id,model1.project_id,floor1.system_name,floor1.domain,building_id])

try:
  # 将下面对数据库的操作作为一个事务, 出异常则自动rollback
  with plpy.subtransaction():
    models=get_models(project_id,building_id)
    floorgraphs=[]
    for model in models:
      floor_connectors=get_connectors(model.model_id, system_name, domain)
      floor_elements=get_elements(model.model_id)
      g= graph_model.FloorGraph(model, system_name, domain,floor_connectors,floor_elements)
      g.get_floor_graphs()
      floorgraphs.append(g)
    projectgraph= graph_model.combine_systemgraph(project_id,floorgraphs)

    delete_block_data(project_id,building_id, system_name, domain)
    block_id=0
    for g in projectgraph.groupedsystemgraphs:
      for s in g.systemgraphs:
        for e in s.system_edges:
          save_edge_data(e, block_id,system_name,domain,building_id)
      for e in g.connectedges:
        save_edge_data(e,block_id,system_name,domain,building_id)
      block_id+=1
except Exception as e:
    plpy.warning(e)
    return False
else:
    return True
$$
LANGUAGE 'plpython3u' VOLATILE;

select public.sys_block('Pj1101010015','Bd11010100153c05821ed8fd11e9b8f2d79d0a5b4bf6','冷冻水供水管','DomainPiping')
```

## 输入
    1. 项目id
    2. 需要计算的building_id，如果没有提供时请传入null，不能传""
    3. 需要计算的系统名称
    4. 需要计算的管道系统类型，枚举（水管或风管）：DomainPiping，DomainHvac
## 返回结果
    True    成功
    False   失败
    
## 结果展示
![原模型图](img/1.png)
![抽象后的图](img/2.png)
![确定完流向的图](img/3.png)
