Support more region utils, such as convex hull

This commit is contained in:
WQY\qiong
2023-04-29 19:15:34 +08:00
parent 538284f502
commit 04a3d0057e
7 changed files with 126 additions and 29 deletions

View File

@@ -132,6 +132,8 @@ 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 .clean_api import clean_scada_element
from .s32_region_util import get_nodes_in_boundary, get_nodes_in_region, calculate_convex_hull
from .s33_region import get_region_schema, get_region, set_region, add_region, delete_region
from .s37_virtual_district import calculate_virtual_district

View File

@@ -1,3 +1,4 @@
from .database import read, read_all, write
def from_postgis_polygon(polygon: str) -> list[tuple[float, float]]:
boundary = polygon.lower().removeprefix('polygon((').removesuffix('))').split(',')
@@ -13,3 +14,36 @@ def to_postgis_polygon(boundary: list[tuple[float, float]]) -> str:
for pt in boundary:
polygon += f'{pt[0]} {pt[1]},'
return f'polygon(({polygon[:-1]}))'
def get_nodes_in_boundary(name: str, boundary: list[tuple[float, float]]) -> list[str]:
api = 'get_nodes_in_boundary'
write(name, f"delete from temp_region where id = '{api}'")
write(name, f"insert into temp_region (id, boundary) values ('{api}', '{to_postgis_polygon(boundary)}')")
nodes: list[str] = []
for row in read_all(name, f"select c.node from coordinates as c, temp_region as r where ST_Intersects(c.coord, r.boundary) and r.id = '{api}'"):
nodes.append(row['node'])
write(name, f"delete from temp_region where id = '{api}'")
return nodes
def get_nodes_in_region(name: str, id: str) -> list[str]:
nodes: list[str] = []
for row in read_all(name, f"select c.node from coordinates as c, region as r where ST_Intersects(c.coord, r.boundary) and r.id = '{id}'"):
nodes.append(row['node'])
return nodes
def calculate_convex_hull(name: str, nodes: list[str]) -> list[tuple[float, float]]:
write(name, f'delete from temp_node')
for node in nodes:
write(name, f"insert into temp_node values ('{node}')")
# TODO: check none
polygon = read(name, f'select st_astext(st_convexhull(st_collect(array(select coord from coordinates where node in (select * from temp_node))))) as boundary' )['boundary']
write(name, f'delete from temp_node')
return from_postgis_polygon(polygon)

View File

@@ -1,19 +1,10 @@
from .database import *
from .s0_base import get_node_links
def _polygon_to_nodes(polygon: str) -> list[tuple[float, float]]:
boundary = polygon.removeprefix('POLYGON((').removesuffix('))').split(',')
xys = []
for pt in boundary:
xy = pt.split(' ')
xys.append((float(xy[0]), float(xy[1])))
return xys
from .s32_region_util import calculate_convex_hull
def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
write(name, 'drop table if exists vd_graph')
write(name, 'create table vd_graph (id serial, source integer, target integer, cost numeric)')
write(name, 'delete from temp_vd_topology')
# map node name to index
i = 0
@@ -33,17 +24,17 @@ def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
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})")
write(name, f"insert into temp_vd_topology (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)")
write(name, f"insert into temp_vd_topology (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)")
write(name, f"insert into temp_vd_topology (source, target, cost) values ({source}, {target}, 0.0)")
# dijkstra distance
node_distance: dict[str, dict[str, Any]] = {}
@@ -52,14 +43,13 @@ def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
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'])
distance = float(read(name, f"select max(agg_cost) as distance from pgr_dijkstraCost('select id, source, target, cost from temp_vd_topology', {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 }
# destroy topology graph
write(name, 'drop table vd_graph')
write(name, 'delete from temp_vd_topology')
# reorganize the distance result
center_node: dict[str, list[str]] = {}
@@ -71,17 +61,7 @@ def calculate_virtual_district(name: str, centers: list[str]) -> dict[str, Any]:
vds: list[dict[str, Any]] = []
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']
xys = _polygon_to_nodes(boundary)
xys = calculate_convex_hull(name, value)
vds.append({ 'center': center, 'nodes': value, 'boundary': xys })
write(name, f'drop table vd_{center}')
return { 'virtual_districts': vds, 'isolated_nodes': isolated_nodes }