Support to calculate virtual district
This commit is contained in:
@@ -132,4 +132,4 @@ from .s31_scada_element import SCADA_ELEMENT_STATUS_OFFLINE, SCADA_ELEMENT_STATU
|
|||||||
from .s31_scada_element import get_scada_element_schema, get_scada_elements, get_scada_element, set_scada_element, add_scada_element, delete_scada_element
|
from .s31_scada_element import get_scada_element_schema, get_scada_elements, get_scada_element, set_scada_element, add_scada_element, delete_scada_element
|
||||||
from .del_cmd import clean_scada_element
|
from .del_cmd import clean_scada_element
|
||||||
|
|
||||||
from .s32_virtual_district import generate_virtual_district
|
from .s32_virtual_district import calculate_virtual_district
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
from .database import *
|
from .database import *
|
||||||
|
from .s0_base import get_node_links
|
||||||
|
|
||||||
|
def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
|
||||||
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, 'drop table if exists vd_graph')
|
||||||
write(name, 'create table vd_graph (id serial, source integer, target integer, cost numeric)')
|
write(name, 'create table vd_graph (id serial, source integer, target integer, cost numeric)')
|
||||||
|
|
||||||
|
# map node name to index
|
||||||
|
i = 0
|
||||||
|
isolated_nodes = []
|
||||||
|
node_index: dict[str, int] = {}
|
||||||
|
for row in read_all(name, 'select id from _node'):
|
||||||
|
node = str(row['id'])
|
||||||
|
if get_node_links(name, node) == []:
|
||||||
|
isolated_nodes.append(node)
|
||||||
|
continue
|
||||||
|
i += 1
|
||||||
|
node_index[node] = i
|
||||||
|
|
||||||
|
# build topology graph
|
||||||
pipes = read_all(name, 'select node1, node2, length from pipes')
|
pipes = read_all(name, 'select node1, node2, length from pipes')
|
||||||
for pipe in pipes:
|
for pipe in pipes:
|
||||||
source = node_index[str(pipe['node1'])]
|
source = node_index[str(pipe['node1'])]
|
||||||
@@ -29,6 +35,7 @@ def generate_virtual_district(name: str, centers: list[str]):
|
|||||||
target = node_index[str(valve['node2'])]
|
target = node_index[str(valve['node2'])]
|
||||||
write(name, f"insert into vd_graph (source, target, cost) values ({source}, {target}, 0.0)")
|
write(name, f"insert into vd_graph (source, target, cost) values ({source}, {target}, 0.0)")
|
||||||
|
|
||||||
|
# dijkstra distance
|
||||||
node_distance: dict[str, dict[str, Any]] = {}
|
node_distance: dict[str, dict[str, Any]] = {}
|
||||||
for center in centers:
|
for center in centers:
|
||||||
for node, index in node_index.items():
|
for node, index in node_index.items():
|
||||||
@@ -41,15 +48,18 @@ def generate_virtual_district(name: str, centers: list[str]):
|
|||||||
elif distance < node_distance[node]['distance']:
|
elif distance < node_distance[node]['distance']:
|
||||||
node_distance[node] = { 'center': center, 'distance' : distance }
|
node_distance[node] = { 'center': center, 'distance' : distance }
|
||||||
|
|
||||||
|
# destroy topology graph
|
||||||
write(name, 'drop table vd_graph')
|
write(name, 'drop table vd_graph')
|
||||||
|
|
||||||
|
# reorganize the distance result
|
||||||
center_node: dict[str, list[str]] = {}
|
center_node: dict[str, list[str]] = {}
|
||||||
for node, value in node_distance.items():
|
for node, value in node_distance.items():
|
||||||
if value['center'] not in center_node:
|
if value['center'] not in center_node:
|
||||||
center_node[value['center']] = []
|
center_node[value['center']] = []
|
||||||
center_node[value['center']].append(node)
|
center_node[value['center']].append(node)
|
||||||
|
|
||||||
write(name, 'delete from virtual_district')
|
# write(name, 'delete from virtual_district')
|
||||||
|
vds: list[dict[str, Any]] = []
|
||||||
|
|
||||||
for center, value in center_node.items():
|
for center, value in center_node.items():
|
||||||
write(name, f'drop table if exists vd_{center}')
|
write(name, f'drop table if exists vd_{center}')
|
||||||
@@ -60,6 +70,17 @@ def generate_virtual_district(name: str, centers: list[str]):
|
|||||||
|
|
||||||
# TODO: check none
|
# 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']
|
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"insert into virtual_district (id, center, boundary) values ('vd_{center}', '{center}', st_geomfromtext('{boundary}'))")
|
||||||
|
|
||||||
|
outlines = str(boundary).removeprefix('POLYGON((').removesuffix('))').split(',')
|
||||||
|
outline_tuples = []
|
||||||
|
for pt in outlines:
|
||||||
|
xy = pt.split(' ')
|
||||||
|
outline_tuples.append((float(xy[0]), float(xy[1])))
|
||||||
|
|
||||||
|
vd = { 'center': center, 'nodes': value, 'boundary': outline_tuples }
|
||||||
|
vds.append(vd)
|
||||||
|
|
||||||
write(name, f'drop table vd_{center}')
|
write(name, f'drop table vd_{center}')
|
||||||
|
|
||||||
|
return { 'virtual_districts': vds, 'isolated_nodes': isolated_nodes }
|
||||||
|
|||||||
@@ -939,5 +939,5 @@ def clean_scada_element(name: str) -> ChangeSet:
|
|||||||
# virtual_district 32
|
# virtual_district 32
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
def generate_virtual_district(name: str, centers: list[str]):
|
def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
|
||||||
return api.generate_virtual_district(name, centers)
|
return api.calculate_virtual_district(name, centers)
|
||||||
|
|||||||
Reference in New Issue
Block a user