#ifndef __INCLUDE_HIS_LOCATION_HPP #define __INCLUDE_HIS_LOCATION_HPP #include #include #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 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 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(pt.x,pt.y)-std::complex(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 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