|
@@ -0,0 +1,272 @@
|
|
|
+#ifndef __INCLUDE_HIS_LOCATION_HPP
|
|
|
+#define __INCLUDE_HIS_LOCATION_HPP
|
|
|
+#include <complex>
|
|
|
+#include <queue>
|
|
|
+#include "point.h"
|
|
|
+#include "log.h"
|
|
|
+#include "db_api/CDBConnPool.h"
|
|
|
+//速度
|
|
|
+//区域 地图变换
|
|
|
+//运动方向
|
|
|
+//路径变换
|
|
|
+struct location_card
|
|
|
+{
|
|
|
+ location_card(uint32_t id,uint64_t type)
|
|
|
+ :m_cardid(id)
|
|
|
+ ,m_type(type)
|
|
|
+ {
|
|
|
+ init();
|
|
|
+ }
|
|
|
+ uint32_t m_cardid;//卡id
|
|
|
+ uint16_t m_type;//卡类型
|
|
|
+ double m_arg;//运动方向角度值
|
|
|
+ int m_areaid;//区域
|
|
|
+ int m_mapid;//地图
|
|
|
+ uint64_t m_timestamp;//入库后的时间
|
|
|
+ point m_p;//入库后的点
|
|
|
+ struct mini_data
|
|
|
+ {
|
|
|
+ mini_data(const point &p,uint64_t t)
|
|
|
+ :p(p)
|
|
|
+ ,time(t)
|
|
|
+ {}
|
|
|
+ point p;
|
|
|
+ uint64_t time;
|
|
|
+ };
|
|
|
+ std::queue<mini_data> m_d;
|
|
|
+ void init()
|
|
|
+ {
|
|
|
+ m_areaid=-1;
|
|
|
+ m_mapid=-1;
|
|
|
+ m_timestamp=0;
|
|
|
+ m_p.set(0,0);
|
|
|
+ init_att();
|
|
|
+ }
|
|
|
+ void init_att()
|
|
|
+ {
|
|
|
+ m_arg=0x12345678;
|
|
|
+ std::queue<mini_data> tmp;
|
|
|
+ m_d.swap(tmp);
|
|
|
+ }
|
|
|
+ void set_invalid()
|
|
|
+ {
|
|
|
+ m_arg=0x12345678;
|
|
|
+ }
|
|
|
+ bool is_valid()
|
|
|
+ {
|
|
|
+ return m_arg!=0x12345678;
|
|
|
+ }
|
|
|
+ double make_arg(const point &pt,const point &p)
|
|
|
+ {
|
|
|
+ log_info("his_location arg[%d],(%.2f,%.2f)--->(%.2f,%.2f)---->(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y,pt.x,pt.y);
|
|
|
+ return std::arg(std::complex<double>(pt.x,pt.y)-std::complex<double>(p.x,p.y));
|
|
|
+ }
|
|
|
+ void set(const point &pt,uint64_t time)
|
|
|
+ {
|
|
|
+ m_timestamp=time;
|
|
|
+ m_p.set(pt);
|
|
|
+ }
|
|
|
+ bool line_changed(const point &pt)
|
|
|
+ {
|
|
|
+ if(!is_valid())
|
|
|
+ return false;
|
|
|
+ point p=m_d.back().p;
|
|
|
+ if(p==pt)p=m_p;
|
|
|
+ double arg = make_arg(pt,p);
|
|
|
+ log_info("his_location:line_changed:%d,%.2f,m_arg:%.2f",m_cardid,arg,m_arg);
|
|
|
+ return arg != m_arg;
|
|
|
+ }
|
|
|
+ bool is_speed_changed(const point& pt,uint64_t time)
|
|
|
+ {
|
|
|
+ bool flag = false;
|
|
|
+ double v=0.0;
|
|
|
+ if(m_d.size()>=4)
|
|
|
+ {
|
|
|
+ mini_data d1 = m_d.front();
|
|
|
+ double dist = d1.p.dist(pt);
|
|
|
+ double t = time-d1.time;
|
|
|
+ v = dist/t*1000;
|
|
|
+ m_d.pop();
|
|
|
+ }
|
|
|
+ m_d.emplace(pt,time);
|
|
|
+ if(v==0.0)
|
|
|
+ return flag;
|
|
|
+ double dist = m_p.dist(pt);
|
|
|
+ double t = time - m_timestamp;
|
|
|
+ double avge_speed= dist/t*1000;
|
|
|
+ log_info("his_location cardid:%d:v:%.2f,avge_v:%.2f,(%.2f--%.2f)",m_cardid,v,avge_speed,0.8*avge_speed,1.2*avge_speed);
|
|
|
+ if(v<(1-0.2)*avge_speed && v>(1+0.2)*avge_speed)
|
|
|
+ flag=true;
|
|
|
+
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+ bool time_out(uint64_t time)
|
|
|
+ {
|
|
|
+ if(time-m_timestamp>=60*1000)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ bool is_area_changed(int new_areaid)
|
|
|
+ {
|
|
|
+ bool flag =false;
|
|
|
+ if(m_areaid != new_areaid)
|
|
|
+ {
|
|
|
+ m_areaid = new_areaid;
|
|
|
+ flag=true;
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+ bool is_map_changed(int new_mapid)
|
|
|
+ {
|
|
|
+ bool flag =false;
|
|
|
+ if(m_mapid != new_mapid)
|
|
|
+ {
|
|
|
+ m_mapid = new_mapid;
|
|
|
+ flag=true;
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+ void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid)
|
|
|
+ {
|
|
|
+ if(m_p.empty() || m_timestamp==0||m_areaid<=0||m_mapid<=0)
|
|
|
+ {
|
|
|
+ set(p,timestamp);
|
|
|
+ m_areaid=areaid;m_mapid=mapid;
|
|
|
+ m_d.emplace(p,timestamp);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!is_valid())
|
|
|
+ {
|
|
|
+ if(p==m_p)
|
|
|
+ {
|
|
|
+ init_att();set(p,timestamp);
|
|
|
+ m_d.emplace(p,timestamp);
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ m_arg=make_arg(p,m_p);
|
|
|
+ log_info("his_location:%d arg:%f",m_cardid,m_arg);
|
|
|
+ insert();
|
|
|
+ }
|
|
|
+ bool flag=false;
|
|
|
+ bool iflag=false;
|
|
|
+ flag=handle_message(p,timestamp);
|
|
|
+ if(time_out(timestamp))
|
|
|
+ if(!flag)iflag=true;
|
|
|
+ if(is_speed_changed(p,timestamp))
|
|
|
+ if(!flag)iflag=true;
|
|
|
+ if(is_area_changed(areaid))
|
|
|
+ if(!flag)iflag=true;
|
|
|
+ if(is_map_changed(mapid))
|
|
|
+ if(!flag)iflag=true;
|
|
|
+ if(iflag)
|
|
|
+ {
|
|
|
+ update(p,timestamp);
|
|
|
+ set_invalid();
|
|
|
+ set(p,timestamp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ virtual std::string getTabName()=0;
|
|
|
+ void insert()
|
|
|
+ {
|
|
|
+ std::string tabName=getTabName();
|
|
|
+ char nsql[512]={0};
|
|
|
+ const char * sql = "replace into %s (card_id,begin_time,map_id,area_id,begin_pt,direction)values(%03d%010d,'%s',%d,%d,'%.2f,%.2f',%f);";
|
|
|
+ snprintf(nsql,512,sql,tabName.c_str(),m_type,m_cardid,tool_time::to_str_ex(m_timestamp).c_str(),m_mapid,m_areaid,m_p.x,m_p.y,m_arg);
|
|
|
+ log_info("his_location[%d]:%s",m_cardid,nsql);
|
|
|
+ sDBConnPool.PushAsync(nsql);
|
|
|
+ }
|
|
|
+ void update(const point &p,uint64_t timestamp)
|
|
|
+ {
|
|
|
+ std::string tabName=getTabName();
|
|
|
+ char nsql[512]={0};
|
|
|
+ const char * sql = "update %s set last_time='%s',speed=%.2f where card_id=%03d%010d and begin_time='%s';";
|
|
|
+ double dist = m_p.dist(p);
|
|
|
+ double t = timestamp - m_timestamp;
|
|
|
+ double avge_speed= dist/t*1000;
|
|
|
+ snprintf(nsql,512,sql,tabName.c_str(),tool_time::to_str_ex(timestamp).c_str(),avge_speed,m_type,m_cardid,tool_time::to_str_ex(m_timestamp).c_str());
|
|
|
+ log_info("his_location[%d]:%s",m_cardid,nsql);
|
|
|
+ sDBConnPool.PushAsync(nsql);
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool handle_message(const point &p,uint64_t timestamp)=0;
|
|
|
+};
|
|
|
+struct location_staff:location_card
|
|
|
+{
|
|
|
+ location_staff(uint32_t id,uint16_t type)
|
|
|
+ :location_card(id,type)
|
|
|
+ {}
|
|
|
+ virtual std::string getTabName(){return std::string{"his_location_staff_"};}
|
|
|
+ //人员如果运行方向发生变化的话,需要求的拐点。如果有拐点,入拐点。时间大与120s则不做处理。没有拐点,则不求
|
|
|
+ virtual bool handle_message(const point &p,uint64_t timestamp)
|
|
|
+ {
|
|
|
+ bool flag = false;
|
|
|
+ if(line_changed(p))
|
|
|
+ {
|
|
|
+ log_info("his_location:line_changed %d",m_cardid);
|
|
|
+ flag=true;
|
|
|
+ if(timestamp-m_timestamp>120*1000)
|
|
|
+ {
|
|
|
+ update(m_d.back().p,m_d.back().time);
|
|
|
+ set(p,timestamp);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::vector<point> rc=card_path::inst().find_path(m_p,p);
|
|
|
+ if(rc.empty())
|
|
|
+ {
|
|
|
+ update(m_d.back().p,m_d.back().time);
|
|
|
+ set(m_d.back().p,m_d.back().time);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(rc.size()==1)
|
|
|
+ {
|
|
|
+ log_info("his_location:line_changed %d circle point(%.2f,%.2f)",m_cardid,rc[0].x,rc[0].y);
|
|
|
+ update(rc[0],m_d.back().time);
|
|
|
+ set(rc[0],m_d.back().time);
|
|
|
+ }
|
|
|
+ else if(rc.size()==2)
|
|
|
+ {
|
|
|
+ update(rc[0],m_d.back().time);
|
|
|
+ set(rc[0],m_d.back().time);
|
|
|
+ //
|
|
|
+ m_arg=make_arg(rc[1],m_p);
|
|
|
+ insert();
|
|
|
+ //
|
|
|
+ update(rc[1],timestamp);
|
|
|
+ set(rc[1],timestamp);
|
|
|
+ }
|
|
|
+ else//更多的拐点
|
|
|
+ {
|
|
|
+ update(rc[0],m_d.back().time);
|
|
|
+ set(rc[1],timestamp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ init_att();
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+};
|
|
|
+struct location_vehicle:location_card
|
|
|
+{
|
|
|
+ location_vehicle(uint32_t id,uint16_t type)
|
|
|
+ :location_card(id,type)
|
|
|
+ {}
|
|
|
+ virtual std::string getTabName(){return std::string{"his_location_vehicle_"};}
|
|
|
+ //车辆是有推送拐点的,所以不需要求拐点。如果运行方向发生变化的话,直接更新数据库即可,使用上一个点的时间。同时生成这一次的历史。
|
|
|
+ virtual bool handle_message(const point &p,uint64_t timestamp)
|
|
|
+ {
|
|
|
+ bool flag =false;
|
|
|
+ if(line_changed(p))
|
|
|
+ {
|
|
|
+ log_info("his_location:line_changed %d ",m_cardid);
|
|
|
+ flag=true;
|
|
|
+ update(m_d.back().p,m_d.back().time);
|
|
|
+ set(m_d.back().p,m_d.back().time);init_att();
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+};
|
|
|
+#endif
|