drop function if exists processStationPoint();
create function processStationPoint()
returns text as
$$
declare
v_stationId integer;
v_stationGeom geometry;
v_startPoint geometry;
v_stationSource integer;
v_stationTarget integer;
v_stationLine geometry;
v_stationLineId integer;
v_stationSrcPulloutable boolean;
v_stationDstPulloutable boolean;
v_searchNode geometry;
v_searchNodeId integer;
v_searchLine geometry;
v_searchLineMerged geometry;
v_searchLineId integer;
v_searchLineOneway varchar;
v_searchLineSrc integer;
v_searchLineDst integer;
v_searchLineSrcIn integer;
v_searchLineSrcOut integer;
v_searchLineDstIn integer;
v_searchLineDstOut integer;
v_srcsegline geometry;
v_dstsegline geometry;
v_curs cursor
for select gid, geom from station order by gid asc;
begin
v_stationSrcPulloutable := false;
v_stationDstPulloutable := false;
v_searchNodeId := -1;
drop table if exists stationNear;
CREATE TABLE stationNear
(
stationId integer,
geom geometry(Point),
CONSTRAINT "stationNear_pkey" PRIMARY KEY (stationid)
);
open v_curs;
loop
fetch v_curs into v_stationId, v_stationGeom;
--raise notice 'fetch v_curs into %, %', v_stationId, v_stationGeom;
if not found then exit;end if;
/*
v_searchNode := null;
select id, the_geom into v_searchNodeId, v_searchNode from changsharoad_connected_vertices_pgr where
ST_Distance(the_geom, v_stationGeom) < 0.000001;
if (v_searchNode != null) then
update station set isNode = true where gid = v_stationId;
update station set nodeId = v_searchNodeId where gid = v_stationId;
end if;*/
v_searchLine := null;
select gid, geom, oneway, source, target into
v_searchLineId, v_searchLine, v_searchLineOneway, v_searchLineSrc, v_searchLineDst from changsharoad_connected
where
ST_DWithin(geom::geography, v_stationGeom::geography, 1000, true) order by ST_Distance(geom, v_stationGeom) limit 1;
if (v_searchLine is null) then
--raise notice '%, v_searchLine is null', v_stationId;
else
v_startPoint := ST_ClosestPoint(v_searchLine, v_stationGeom);
INSERT INTO stationNear(stationid, geom)
VALUES(v_stationId, v_startPoint)
ON conflict(stationid)
DO update set
stationid = v_stationId,
geom = v_startPoint;
raise notice 'ST_ClosestPoint is on v_searchLine: %', ST_DistanceSphere(v_searchLine, v_stationGeom) < 0.1;
select ein, eout into v_searchLineSrcIn, v_searchLineSrcOut from changsharoad_connected_vertices_pgr where id = v_searchLineSrc;
select ein, eout into v_searchLineDstIn, v_searchLineDstOut from changsharoad_connected_vertices_pgr where id = v_searchLineDst;
if (v_searchLineOneway != 'T' and v_searchLineDstOut > 0) then
v_stationDstPulloutable := true;
--raise notice '%, v_stationPulloutable is true', v_stationId;
else
--raise notice '%, v_stationPulloutable is false', v_stationId;
end if;
if (v_searchLineOneway != 'F' and v_searchLineSrcOut > 0) then
v_stationSrcPulloutable := true;
--raise notice '%, v_stationPulloutable is true', v_stationId;
else
--raise notice '%, v_stationPulloutable is false', v_stationId;
end if;
v_searchLineMerged := ST_LineMerge(v_searchLine);
declare
v_lineFraction float;
v_isNode boolean;
v_nodeId integer;
begin
v_nodeId := -1;
v_lineFraction := ST_LineLocatePoint(v_searchLineMerged, v_startPoint);
if (v_lineFraction < 0.0001) then
v_srcsegline = null;
v_isNode := true;
v_nodeId := v_searchLineSrc;
v_lineFraction := 0;
--raise notice '坐标跟起点相同';
else
v_srcsegline := st_reverse(st_linesubstring(v_searchLineMerged, 0, v_lineFraction));
end if;
if ((1.0 - v_lineFraction) < 0.0001) then
v_dstsegline = null;
v_isNode := true;
v_nodeId := v_searchLineDst;
v_lineFraction := 1;
--raise notice '坐标跟终点相同';
else
v_dstsegline := st_linesubstring(v_searchLineMerged, v_lineFraction, 1);
end if;
update station set lineId = v_searchLineId,
startPoint = v_startPoint,
isnode = v_isNode,
nodeid = v_nodeId,
source = v_searchLineSrc,
lineFraction = v_lineFraction,
target = v_searchLineDst,
srcPulloutable = v_stationSrcPulloutable,
dstPulloutable = v_stationDstPulloutable,
srcsegline = v_srcsegline,
dstsegline = v_dstsegline
where gid = v_stationId;
--raise notice 'line geometry: %, %', st_astext(v_srcsegline), st_astext(v_dstsegline);
--raise notice '%, update station.... ok!', v_stationId;
end;
end if;
end loop;
close v_curs;
return 'ok';
end;
$$ language plpgsql;