#include "his_location.h" #include "log.h" #include "tool_time.h" #include "card_path.h" #include "db_api/CDBSingletonDefine.h" #include extern config_file config; uint32_t location_card::m_difftime=0; int location_card::m_distance=-1; location_card::location_card(uint32_t id,uint64_t type,uint32_t objid) :m_cardid(id) ,m_type(type) ,m_objid(objid) { init(); if(location_card::m_distance==-1) { location_card::m_difftime=config.get("service.difftime",300); location_card::m_distance=config.get("service.distance",30); log_info("his_location_init:%u,%d",m_difftime,m_distance); } } void location_card::init() { m_areaid=-1; m_mapid=-1; m_siteid = -1; m_timestamp=0; m_p.set(0,0); std::queue tmp; m_d.swap(tmp); m_direct_index=0; last_timestamp=0; set_invalid(); } void location_card::init_att(const point &pt,uint64_t time) { std::queue tmp; m_d.swap(tmp); m_d.emplace(pt,time); } void location_card::set_invalid() { m_arg=0x12345678; } bool location_card::is_valid() { return m_arg!=0x12345678; } double location_card::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 location_card::set(const point &pt,uint64_t time) { m_timestamp=time; m_p.set(pt); init_att(pt,time); } bool location_card::line_changed(const point &pt)//,int &df) { if(!is_valid()) return false; point p; if(m_d.empty()) p=m_p; else p=m_d.back().p; if(point::eq(p.x,pt.x,0.2) && point::eq(p.y,pt.y,0.2)) return false; double dis1=m_p.dist(pt); if(dis1<2)return false; //double dis = p.dist(pt); double dis = m_p.dist(pt); double arg = make_arg(pt,m_p); //查看路径方向是否改变 bool change_flag=(arg-m_arg > -1e-10 && arg-m_arg<1e-10); //change_flag为true,标识没有发生变化 // if(change_flag)m_direct_index=0; log_info("his_location:line_changed:%d,%f,m_arg:%f,%s,%f,%f",m_cardid,arg,m_arg, change_flag?"same":"not same",m_arg-arg,dis); return !change_flag; } bool location_card::is_speed_changed(const point& pt,uint64_t time) { bool flag = false; double v=0.0; point ps=m_d.back().p; if(ps.dist(pt)<0.1)return flag; 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.1) 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.7*avge_speed,1.3*avge_speed); if(v<(1-0.3)*avge_speed || v>(1+0.3)*avge_speed) flag=true; return flag; } bool location_card::time_out(const point &p,uint64_t time) { uint64_t t=last_timestamp==0?m_timestamp:last_timestamp; if(time-t>=30*1000 && m_p.dist(p)>0.1) return true; return false; } //区域是否发生变化 bool location_card::is_area_changed(int new_areaid) { bool flag =false; if(m_areaid != new_areaid) { m_areaid = new_areaid; flag=true; } return flag; } //地图是否发生变化 bool location_card::is_map_changed(int new_mapid) { bool flag =false; if(m_mapid != new_mapid) { m_mapid = new_mapid; flag=true; } return flag; } void location_card::push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid,int32_t siteid,bool bclose/* = false*/) { //log_info("his_location: 1111111111111111111; timestamp=%d, p.x=%.2f, p.y=%.2f", timestamp, p.x, p.y); if (bclose) //卡移除后直接更新his_location { update(p,timestamp); init(); return; } //log_info("his_location: m_p.empty()=%d, m_timestamp=%d, m_areaid=%d, m_mapid=%d, m_siteid=%d", m_p.empty(), m_timestamp, m_areaid, m_mapid, m_siteid); if(m_p.empty() || m_timestamp==0||m_areaid<0||m_mapid<0 || m_siteid < 0) { set(p,timestamp); m_areaid = areaid; m_mapid = mapid; m_siteid = siteid; m_d.emplace(p,timestamp); return ; } if(!is_valid()) { if(point::eq(p.x,m_p.x,0.2) && point::eq(p.y,m_p.y,0.2)) { set(p,timestamp); log_info("his_location:%d New Point Too close.Point[%.2f,%.2f]",m_cardid,p.x,p.y); return ; } auto v=find_path(m_p,p); if(v.empty()) m_arg=make_arg(p,m_p); else { log_info("his_location:more_abnormal_point....%d,(%.2f,%.2f)---(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y); handle_path(v,timestamp,true); set_invalid(); return; } log_info("his_location:%d arg:%f",m_cardid,m_arg); insert(); return; } bool flag=false; int iflag=0; //判断是否路径发生了变化 //这里现在又判断,如果反向了也会返回true.但是不运作,依然走下面的逻辑就会有问题 //比如速度 flag=handle_message(p,timestamp); if(time_out(p,timestamp)) if(!flag)iflag=1; if(is_speed_changed(p,timestamp)) if(!flag)iflag=2; if(is_area_changed(areaid)) if(!flag)iflag=3; if(is_map_changed(mapid)) if(!flag)iflag=4; log_info("his_location cardid:%d:%d",m_cardid,iflag); if(iflag) { update(p,timestamp,iflag); //set_invalid(); if(iflag>1){ m_siteid = siteid; set(p,timestamp); insert(); } } } void location_card::insert(uint64_t timestamp, const point & p, int32_t areaid, int32_t mapid, int32_t siteid, double scale) { double speed = 0.0; double dist = 0.0; if(m_timestamp != 0){ dist = m_p.dist(p)*scale; if(fabs(dist) < 1){ return; } double t = (timestamp - m_timestamp)/1000; speed = dist/t; if(std::isnan(speed)|| std::isinf(speed)) speed=0; } m_timestamp = timestamp; m_p = p; char sql[512] = {0}; snprintf(sql, 512, "replace into his_location_simplify(obj_id, card_type_id, ident, loc_time, map_id, area_id, begin_pt, reader_id, speed) values (%d, %d, %d, '%s', %d, %d, '%.2f,%.2f', %d, %.2f);", m_objid, m_type, m_cardid, tool_time::to_str(timestamp/1000).c_str(), mapid, areaid, p.x, p.y, siteid, speed); logn_info(2, "his_location_simplify: %d-%lu: %s", m_cardid, timestamp, sql); sDBConnPool.PushAsync(sql); } void location_card::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,reader_id)" "values(%d,%d,%d,'%s',%d,%d,'%.2f,%.2f',%f,%d);"; 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,m_siteid); logn_info(2, "his_location[%d,%lu]:%s", m_cardid, m_timestamp, nsql); sDBConnPool.PushAsync(nsql); } void location_card::update(const point &p,uint64_t timestamp,int flag/*=0*/,int dflag/*=0*/) { //std::string tabName=getTabName(); if(timestamp <= 0){ return; } char nsql[512]={0}; const char * sql = "update his_location set last_time='%s',speed=%.3f,direction=%f,location_flag=%d where obj_id=%d and begin_time='%s' and last_time is null;"; double dist = m_p.dist(p); double t = (timestamp - m_timestamp)/1000; double avge_speed = dist/t; if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0; logn_info(2, "his_location_time[%d]:%d[%lu,%lu,%lu]", m_cardid, flag, last_timestamp, timestamp, m_timestamp); if(last_timestamp != 0) { const char * ss = "update his_location set last_time='%s',speed=%.3f,direction=%f,location_flag=%d where obj_id=%d and begin_time='%s' and last_time = '%s';"; snprintf(nsql,512,ss,tool_time::to_str(timestamp/1000).c_str(),avge_speed,m_arg,dflag,m_objid,tool_time::to_str(m_timestamp/1000).c_str(),tool_time::to_str(last_timestamp/1000).c_str()); } else snprintf(nsql,512,sql,tool_time::to_str(timestamp/1000).c_str(),avge_speed,m_arg,dflag,m_objid,tool_time::to_str(m_timestamp/1000).c_str()); if(flag==1) last_timestamp=timestamp; else last_timestamp=0; logn_info(2, "his_location[%d]:%s[%lu,%lu]", m_cardid, nsql, timestamp, m_timestamp); sDBConnPool.PushAsync(nsql); } std::vector location_card::find_path(const point &p1,const point &p2) { std::vector rc=card_path::inst().find_path(point(p1.x,-p1.y),point(p2.x,-p2.y)); return std::move(rc); } bool location_card::handle_message(const point &p,uint64_t timestamp) { bool flag = false; if(line_changed(p)) { flag = true; std::vector rc=find_path(m_p,p); 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 { if(handle_path(rc,timestamp,false)) return true; } //置m_arg非法 set_invalid(); }else{ log_info("his_location: line not change"); } return flag; } bool location_card::handle_path(std::vector &rc,uint64_t timestamp,bool flag) { double dis=0; point _p=m_p; std::for_each(rc.begin(),rc.end(),[&dis,&_p](point &pt){ pt.y = pt.y; dis+=_p.dist(pt); _p=pt; }); uint64_t t=timestamp/1000 - m_timestamp/1000; if(t==0||dis<0.1){ log_info("his_location: card_id=%d, t=%d, dist=%.2f, rc.size=%d", m_cardid, t, dis, rc.size()); return true; } double avge_speed= dis/t; //有拐点 盲区时间差 距离 uint64_t difftime = t; int dflag = 0; if(!m_d.empty()) difftime = timestamp/1000-(m_d.back().time)/1000; if(difftime >= location_card::m_difftime && dis>location_card::m_distance) { log_info("his_location[%d]:abnormal_line difftime:%lu,ltime:%u,dis:%.2f,limit_dis:%d",m_cardid,difftime,location_card::m_difftime,dis,location_card::m_distance); dflag=1; } for(const point & pp:rc) { m_arg=make_arg(pp,m_p); if(flag)insert(); log_info("his_location[%d]:line_changed_x point(%.2f,%.2f)--circle point(%.2f,%.2f),speed:%.2f",m_cardid,m_p.x,m_p.y,pp.x,pp.y,avge_speed); double dist=m_p.dist(pp);uint64_t tt=dist/avge_speed*1000; uint64_t etime=m_timestamp+tt; update(pp,etime,0,dflag); set(pp,etime); flag=true; } return false; }