PL/pgSQL检索移动轨迹停留区域

create or replace function findregion(sqltablename varchar,simid varchar,mininterval double precision,maxdistance double precision) 
returns setof resulttable as 
$body$
declare 
	id bigint;		--车辆记录的id号
	row0 record;
	typerow record;

	r resulttable%rowtype;	--resulttable的记录(行)结构
	--vehiclesimid varchar:='806584018900';

	vehiclesimid varchar:=simid;
	tablename varchar:='resulttable';	--计算结果的表名
	sqltable varchar:=sqltablename;	--轨迹所在的表名
	sqlcount  varchar;	--表中记录数
 	sqlinsert varchar;	--插入记录
	sqltruncate varchar; 	--清空表
	sqlresult varchar;
	sqltype varchar;	--创建新数据类型
	sqlresulttable varchar;	--最终的结果表

	segNumber integer;	--分割数目(整个轨迹被停留点所分割)或称为停留次数
	i  integer;		--循环计数器
	result integer;		--判断结果表是否存在

	total integer;		--车辆轨迹总数
	flag integer;		--短距离停留次数标记

	stoptime timestamp without time zone;	--离开停留区的时刻
	tmptime timestamp without time zone;	--中间变量
	starttime timestamp without time zone;	--进入停留区的时刻

	stopid bigint;		--离开停留区的最后一个记录的id号
	tmpid bigint;		--中间变量
	startid bigint;		--进入停留区的开始记录的id号
	isstart integer; 	--是否进入停留区

	d double precision;	--两点间的距离
	d0 double precision;	--最小时间间隔和最大距离间隔推演出来的基准距离
	x0 double precision;    --t0时刻的经度
	y0 double precision;    --t0时刻的纬度
	
	sampledistance double precision;	--采样点间的距离
	maxdistance0 double precision;		--最大判断距离
	sampleinterval double precision;	--采样时间间隔
	lasttime bigint;			--上一时刻点
	currenttime bigint;			--当前时刻点
	mininterval0 double precision;		--最小时间间隔
	ratio double precision;			--最小时间间隔与采样时间间隔的比率

	startx double precision;    --进入停留区该时刻的经度
	starty double precision;    --进入停留区该时刻的纬度
	tmpx double precision;
	tmpy double precision;
	midx double precision;
	midy double precision;
	pt point ;		    --停留区的中心点
        stopx double precision;	    --离开停留区该时刻的经度
	stopy double precision;     --离开停留区该时刻的纬度

	xi double precision;	--ti时刻的经度
	yi double precision;    --ti时刻的纬度
	xj double precision;    --tj时刻的经度
	yj double precision;    --tj时刻的纬度
	--cur cursor for select * from gps_table2;--初始化游标
	cur refcursor;

begin
	sqlcount:='select count(*) from '||quote_ident(sqltable)||' where vehiclesimid=$1';
	EXECUTE sqlcount INTO total USING vehiclesimid;	--获取总记录数
	--RAISE NOTICE '该车辆全天总记录数%',total;
	
	--判断自定义数据类型是否存在
	select * into typerow from pg_type where typname='timepoint';	
	if not found then
		create type timepoint as(
		x double precision,	--tij时刻的经度
		y double precision,	--tij时刻的纬度
		xytime timestamp without time zone --tij时刻
		);
	
	end if;

	--判断数据库中,结果表是否存在
	sqlresult:='select count(*) from pg_class where relname=$1';
	EXECUTE sqlresult INTO result USING tablename;	

	sqlresulttable:='create table resulttable (id bigint,pointin timepoint,pointmid point,pointout timepoint)';	--结果表,用来存储计算结果
	
	sqltruncate:='truncate table '||quote_ident(tablename);
	--sqltruncate:='truncate table resulttable';
	if result=0 then	--如果结果表不存在
	EXECUTE sqlresulttable;	--创建一个新表
	else
	EXECUTE sqltruncate;	--存在,清空表
	end if;
	
	--变量初始化
	i:=1;
	flag:=0;
	segNumber:=0;
	isstart:=1;
	--mininterval0:=10;	--10秒
	--maxdistance0:=0.00012;	--10秒对应15米
	mininterval0:=mininterval;	--10秒
	maxdistance0:=maxdistance/100000;	--10秒对应15米

	--open cur ;	--打开游标
	OPEN cur FOR EXECUTE 'select * from '||quote_ident(sqltable);
	fetch cur into row0;	--使用游标,取得第一行记录
	x0:=row0.gpslongitude;
	y0:=row0.gpslatitude;
	--RAISE NOTICE 'gpstime2:%',row0.gpstime2;
	--RAISE NOTICE '经纬度:%,%',x0,y0;

	while i<total loop	--遍历整辆车的全天GPS记录
	  
	   tmptime:=row0.gpstimestamp;
	   tmpid:=row0.id;
	   tmpx:=row0.gpslongitude;
	   tmpy:=row0.gpslatitude;
           lasttime:=row0.gpstime2;

	   fetch cur into row0;  ----使用游标,取得下一行记录
	 --  RAISE NOTICE 'id:%',row0.id;
	   i:=i+1;

	   xi:=row0.gpslongitude;
	   yi:=row0.gpslatitude;
	   currenttime:=row0.gpstime2;
	   sampleinterval:=currenttime-lasttime;
	   ratio:=sampleinterval/mininterval0;
	   d0:=ratio*maxdistance0;
	   d:=sqrt((xi-x0)*(xi-x0)+(yi-y0)*(yi-y0));
	   x0:=xi;
	   y0:=yi;
	--RAISE NOTICE 'ratio*maxdistance0:%,d:%',d0,d;
	-- if d<0.0005 then  --0.001为经验距离d,单位是度,约为100米
	  if d<d0 then

	   flag:=flag+1;

	   if isstart>0 then
	  	 starttime:=tmptime;
		 startid:=tmpid;
		 startx:=tmpx;
		 starty:=tmpy;
	   end if;
	   
	   isstart:=-1;	--进入停留区后,关闭开关

	   if flag>0 then	--停留15次以上,车辆id被记录
		stopid:=row0.id;
		stoptime:=row0.gpstimestamp;
		stopx:=row0.gpslongitude;
		stopy:=row0.gpslatitude;
	   end if;

       
	else
           isstart:=1;--离开停留区后,开关打开
	   
	   if flag>0 then
            segNumber:=segNumber+1;	--聚集划分数目
	    midx:=(startx+stopx)/2;	--计算停留区域中心点经度
	    midx:=round(cast(midx as numeric),6);
	    midy:=(starty+stopy)/2;	--计算停留区域中心点纬度
	    midy:=round(cast(midy as numeric),6);
	    pt:=(midx,midy);		--停留区域中心点

	    sqlinsert:='insert into resulttable values($1,row($2,$3,$4),$5,row($6,$7,$8))';
	    EXECUTE sqlinsert USING segNumber,startx,starty,starttime,pt,stopx,stopy,stoptime;
	   end if;

	   flag:=0;	--循环窗口清零
	   
	end if;
		

	end loop;

	--读出结果表中的数据
	for r in select * from resulttable where resulttable.id>0
	    loop
		return next r;
	    end loop;
	
	return;


end;
$body$ 
language plpgsql;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值