Files
TJWaterServer/api/s32_virtual_district.py
2023-03-31 09:55:06 +08:00

66 lines
2.9 KiB
Python

from .database import *
def generate_virtual_district(name: str, centers: list[str]):
i = 0
node_index: dict[str, int] = {}
rows = read_all(name, 'select id from _node')
for row in rows:
i += 1
node_index[str(row['id'])] = i
write(name, 'drop table if exists vd_graph')
write(name, 'create table vd_graph (id serial, source integer, target integer, cost numeric)')
pipes = read_all(name, 'select node1, node2, length from pipes')
for pipe in pipes:
source = node_index[str(pipe['node1'])]
target = node_index[str(pipe['node2'])]
cost = float(pipe['length'])
write(name, f"insert into vd_graph (source, target, cost) values ({source}, {target}, {cost})")
pumps = read_all(name, 'select node1, node2 from pumps')
for pump in pumps:
source = node_index[str(pump['node1'])]
target = node_index[str(pump['node2'])]
write(name, f"insert into vd_graph (source, target, cost) values ({source}, {target}, 0.0)")
valves = read_all(name, 'select node1, node2 from valves')
for valve in valves:
source = node_index[str(valve['node1'])]
target = node_index[str(valve['node2'])]
write(name, f"insert into vd_graph (source, target, cost) values ({source}, {target}, 0.0)")
node_distance: dict[str, dict[str, Any]] = {}
for center in centers:
for node, index in node_index.items():
if node == center:
continue
# TODO: check none
distance = float(read(name, f"select max(agg_cost) as distance from pgr_dijkstraCost('select id, source, target, cost from vd_graph', {index}, {node_index[center]}, false)")['distance'])
if node not in node_distance:
node_distance[node] = { 'center': center, 'distance' : distance }
elif distance < node_distance[node]['distance']:
node_distance[node] = { 'center': center, 'distance' : distance }
write(name, 'drop table vd_graph')
center_node: dict[str, list[str]] = {}
for node, value in node_distance.items():
if value['center'] not in center_node:
center_node[value['center']] = []
center_node[value['center']].append(node)
write(name, 'delete from virtual_district')
for center, value in center_node.items():
write(name, f'drop table if exists vd_{center}')
write(name, f'create table vd_{center} (node varchar(32) primary key references _node(id))')
for node in value:
write(name, f"insert into vd_{center} values ('{node}')")
# TODO: check none
boundary = read(name, f'select st_astext(st_convexhull(st_collect(array(select coord from coordinates where node in (select * from vd_{center}))))) as boundary' )['boundary']
write(name, f"insert into virtual_district (id, center, boundary) values ('vd_{center}', '{center}', st_geomfromtext('{boundary}'))")
write(name, f'drop table vd_{center}')