123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- #ifndef __INCLUDE_HIS_LOCATION_HPP
- #define __INCLUDE_HIS_LOCATION_HPP
- #include <complex>
- #include <queue>
- #include "point.h"
- #include "log.h"
- #include "tool_time.h"
- #include "card_path.h"
- #include "db_api/CDBSingletonDefine.h"
- //速度
- //区域 地图变换
- //运动方向
- //路径变换
- struct location_card
- {
- location_card(uint32_t id,uint64_t type,uint32_t objid)
- :m_cardid(id)
- ,m_type(type)
- ,m_objid(objid)
- {
- init();
- }
- uint32_t m_cardid;//卡id
- uint16_t m_type;//卡类型
- uint32_t m_objid;
- 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)return false;
- if(point::eq(p.x,pt.x,0.05) && point::eq(p.y,pt.y,0.05)) return false;
- double arg = make_arg(pt,p);
- log_info("his_location:line_changed:%d,%f,m_arg:%f,%s,%f",m_cardid,arg,m_arg, (arg-m_arg > -1e-10 && arg-m_arg<1e-10)?"same":"not same",m_arg-arg);
- return !point::eq(arg,m_arg,1e-10);
- }
- 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(const point &p,uint64_t time)
- {
- if(time-m_timestamp>=60*1000 && !(p == m_p))
- 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(p,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);
- insert();
- }
- }
- virtual std::string getTabName()=0;
- void insert()
- {
- std::string tabName=getTabName();
- char nsql[512]={0};
- const char * sql = "replace into his_location (obj_id,card_type_id,ident,begin_time,map_id,area_id,begin_pt,direction)"
- "values(%d,%d,%d,'%s',%d,%d,'%.2f,%.2f',%f);";
- snprintf(nsql,512,sql,m_objid,m_type,m_cardid,tool_time::to_str(m_timestamp/1000).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 his_location set last_time='%s',speed=%.2f where obj_id=%d and begin_time='%s';";
- double dist = m_p.dist(p);
- double t = timestamp - m_timestamp;
- double avge_speed= dist/t*1000;
- if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0;
- snprintf(nsql,512,sql,tool_time::to_str(timestamp/1000).c_str(),avge_speed,m_objid,tool_time::to_str(m_timestamp/1000).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,uint64_t type,uint32_t objid)
- :location_card(id,type,objid)
- {}
- 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)
- {
- log_info("his_location:line_changed_timeout %d",m_cardid);
- update(m_d.back().p,m_d.back().time);
- set(p,timestamp);
- }
- else
- {
- log_info("his_location:line_changed_find_path %d,(%.2f,%.2f)-->(%.2f,%.2f)-->(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,m_d.back().p.x,m_d.back().p.y,p.x,p.y);
- std::vector<point> rc=card_path::inst().find_path(point(m_d.back().p.x,-m_d.back().p.y),point(p.x,-p.y));
- if(rc.empty())
- {
- log_info("his_location:line_changed rc.empty() %d",m_cardid);
- update(m_d.back().p,m_d.back().time);
- set(m_d.back().p,m_d.back().time);
- }
- else
- {
- for(uint32_t i=0;i<rc.size();i++)
- log_info("his_location:find_path..x=%.3lf,y=%.3lf\n",rc[i].x,rc[i].y);
- if(rc.size()==1)
- {
- log_info("his_location:line_changed %d circle point(%.2f,%.2f)",m_cardid,rc[0].x,rc[0].y);
- point tmp(rc[0].x,-rc[0].y);
- update(tmp,m_d.back().time);
- set(tmp,m_d.back().time);
- }
- else if(rc.size()==2)
- {
- point tmp(rc[0].x,-rc[0].y);
- update(tmp,m_d.back().time);
- set(tmp,m_d.back().time);
- //
- tmp.set(rc[1].x,-rc[1].y);
- m_arg=make_arg(tmp,m_p);
- insert();
- //
- update(tmp,timestamp);
- set(tmp,timestamp);
- }
- else//更多的拐点
- {
- point tmp(rc[0].x,-rc[0].y);
- update(tmp,m_d.back().time);
- tmp.set(rc.back().x,-rc.back().y);
- set(tmp,timestamp);
- }
- }
- }
- init_att();
- }
- return flag;
- }
- };
- struct location_vehicle:location_card
- {
- location_vehicle(uint32_t id,uint64_t type,uint32_t objid)
- :location_card(id,type,objid)
- {}
- 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
|