1
0

his_location.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #ifndef __INCLUDE_HIS_LOCATION_HPP
  2. #define __INCLUDE_HIS_LOCATION_HPP
  3. #include <complex>
  4. #include <queue>
  5. #include "point.h"
  6. #include "log.h"
  7. #include "tool_time.h"
  8. #include "card_path.h"
  9. #include "db_api/CDBSingletonDefine.h"
  10. //速度
  11. //区域 地图变换
  12. //运动方向
  13. //路径变换
  14. struct location_card
  15. {
  16. location_card(uint32_t id,uint64_t type,uint32_t objid);
  17. uint32_t m_cardid;//卡id
  18. uint16_t m_type;//卡类型
  19. uint32_t m_objid;
  20. double m_arg;//运动方向角度值
  21. int m_areaid;//区域
  22. int m_mapid;//地图
  23. uint64_t m_timestamp;//入库后的时间
  24. point m_p;//入库后的点
  25. int m_direct_index;
  26. uint64_t last_timestamp;
  27. static uint32_t m_difftime;//进入盲区得时长限制 时长
  28. static int m_distance;//进入盲区后,第一个点与之前得距离 像素距离
  29. struct mini_data
  30. {
  31. mini_data(const point &p,uint64_t t)
  32. :p(p)
  33. ,time(t)
  34. {}
  35. point p;
  36. uint64_t time;
  37. };
  38. std::queue<mini_data> m_d;
  39. void init()
  40. {
  41. m_areaid=-1;
  42. m_mapid=-1;
  43. m_timestamp=0;
  44. m_p.set(0,0);
  45. std::queue<mini_data> tmp;
  46. m_d.swap(tmp);
  47. m_direct_index=0;
  48. last_timestamp=0;
  49. }
  50. void init_att(const point &pt,uint64_t time)
  51. {
  52. std::queue<mini_data> tmp;
  53. m_d.swap(tmp);
  54. m_d.emplace(pt,time);
  55. }
  56. void set_invalid()
  57. {
  58. m_arg=0x12345678;
  59. }
  60. bool is_valid()
  61. {
  62. return m_arg!=0x12345678;
  63. }
  64. double make_arg(const point &pt,const point &p)
  65. {
  66. 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);
  67. return std::arg(std::complex<double>(pt.x,pt.y)-std::complex<double>(p.x,p.y));
  68. }
  69. void set(const point &pt,uint64_t time)
  70. {
  71. m_timestamp=time;
  72. m_p.set(pt);
  73. init_att(pt,time);
  74. }
  75. bool line_changed(const point &pt)//,int &df)
  76. {
  77. if(!is_valid())
  78. return false;
  79. point p;
  80. if(m_d.empty())p=m_p; else p=m_d.back().p;
  81. if(point::eq(p.x,pt.x,0.2) && point::eq(p.y,pt.y,0.2)) return false;
  82. double dis1=m_p.dist(pt);
  83. if(dis1<2)return false;
  84. //double dis = p.dist(pt);
  85. double dis = m_p.dist(pt);
  86. double arg = make_arg(pt,m_p);
  87. //查看路径方向是否改变
  88. bool change_flag=(arg-m_arg > -1e-10 && arg-m_arg<1e-10);
  89. //change_flag为true,标识没有发生变化
  90. // if(change_flag)m_direct_index=0;
  91. 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);
  92. //if(dis<0.5 && fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
  93. // return false;
  94. //判断10次反向才做下一步动作
  95. // if(fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
  96. // {
  97. // if(++m_direct_index<=10)
  98. // {
  99. // df=1;return false;
  100. // }
  101. // }
  102. //return !point::eq(arg,m_arg,1e-10);
  103. return !change_flag;
  104. }
  105. bool is_speed_changed(const point& pt,uint64_t time)
  106. {
  107. bool flag = false;
  108. double v=0.0;
  109. point ps=m_d.back().p;
  110. if(ps.dist(pt)<0.1)return flag;
  111. if(m_d.size()>=4)
  112. {
  113. mini_data d1 = m_d.front();
  114. double dist = d1.p.dist(pt);
  115. double t = time-d1.time;
  116. v = dist/t*1000;
  117. m_d.pop();
  118. }
  119. m_d.emplace(pt,time);
  120. if(v<=0.1)
  121. return flag;
  122. double dist = m_p.dist(pt);
  123. double t = time - m_timestamp;
  124. double avge_speed= dist/t*1000;
  125. 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);
  126. if(v<(1-0.3)*avge_speed || v>(1+0.3)*avge_speed)
  127. flag=true;
  128. return flag;
  129. }
  130. bool time_out(const point &p,uint64_t time)
  131. {
  132. uint64_t t=last_timestamp==0?m_timestamp:last_timestamp;
  133. if(time-t>=30*1000 && m_p.dist(p)>0.1)
  134. return true;
  135. return false;
  136. }
  137. bool is_area_changed(int new_areaid)
  138. {
  139. bool flag =false;
  140. if(m_areaid != new_areaid)
  141. {
  142. m_areaid = new_areaid;
  143. flag=true;
  144. }
  145. return flag;
  146. }
  147. bool is_map_changed(int new_mapid)
  148. {
  149. bool flag =false;
  150. if(m_mapid != new_mapid)
  151. {
  152. m_mapid = new_mapid;
  153. flag=true;
  154. }
  155. return flag;
  156. }
  157. void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid)
  158. {
  159. if(m_p.empty() || m_timestamp==0||m_areaid<0||m_mapid<0)
  160. {
  161. set(p,timestamp);
  162. m_areaid=areaid;m_mapid=mapid;
  163. m_d.emplace(p,timestamp);
  164. return;
  165. }
  166. if(!is_valid())
  167. {
  168. //if(p==m_p)
  169. if(point::eq(p.x,m_p.x,0.2) && point::eq(p.y,m_p.y,0.2))
  170. {
  171. set(p,timestamp);
  172. return ;
  173. }
  174. auto v=find_path(m_p,p);
  175. if(v.empty())
  176. m_arg=make_arg(p,m_p);
  177. else
  178. {
  179. log_info("his_location:more_abnormal_point....%d,(%.2f,%.2f)---(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y);
  180. handle_path(v,timestamp,true);
  181. set_invalid();
  182. return;
  183. }
  184. log_info("his_location:%d arg:%f",m_cardid,m_arg);
  185. insert();
  186. return;
  187. }
  188. bool flag=false;
  189. int iflag=0;
  190. //判断是否路径发生了变化
  191. //这里现在又判断,如果反向了也会返回true.但是不运作,依然走下面的逻辑就会有问题
  192. //比如速度
  193. flag=handle_message(p,timestamp);
  194. if(time_out(p,timestamp))
  195. if(!flag)iflag=1;
  196. if(is_speed_changed(p,timestamp))
  197. if(!flag)iflag=2;
  198. if(is_area_changed(areaid))
  199. if(!flag)iflag=3;
  200. if(is_map_changed(mapid))
  201. if(!flag)iflag=4;
  202. log_info("his_location cardid:%d:%d",m_cardid,iflag);
  203. if(iflag)
  204. {
  205. update(p,timestamp,iflag);
  206. //set_invalid();
  207. if(iflag>1){
  208. set(p,timestamp);
  209. insert();
  210. }
  211. }
  212. }
  213. void insert()
  214. {
  215. //std::string tabName=getTabName();
  216. char nsql[512]={0};
  217. const char * sql = "replace into his_location (obj_id,card_type_id,ident,begin_time,map_id,area_id,begin_pt,direction)"
  218. "values(%d,%d,%d,'%s',%d,%d,'%.2f,%.2f',%f);";
  219. 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);
  220. log_info("his_location[%d,%lu]:%s",m_cardid,m_timestamp,nsql);
  221. sDBConnPool.PushAsync(nsql);
  222. }
  223. void update(const point &p,uint64_t timestamp,int flag=0,int dflag=0)
  224. {
  225. //std::string tabName=getTabName();
  226. char nsql[512]={0};
  227. 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;";
  228. double dist = m_p.dist(p);
  229. double t = (timestamp - m_timestamp)/1000;
  230. double avge_speed= dist/t;
  231. if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0;
  232. log_info("his_location_time[%d]:%d[%lu,%lu,%lu]",m_cardid,flag,last_timestamp,timestamp,m_timestamp);
  233. if(last_timestamp != 0)
  234. {
  235. 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';";
  236. 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());
  237. }
  238. else
  239. 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());
  240. if(flag==1) last_timestamp=timestamp;
  241. else last_timestamp=0;
  242. log_info("his_location[%d]:%s[%lu,%lu]",m_cardid,nsql,timestamp,m_timestamp);
  243. sDBConnPool.PushAsync(nsql);
  244. }
  245. std::vector<point> find_path(const point &p1,const point &p2)
  246. {
  247. std::vector<point> rc=card_path::inst().find_path(point(p1.x,-p1.y),point(p2.x,-p2.y));
  248. return std::move(rc);
  249. }
  250. //virtual bool handle_message(const point &p,uint64_t timestamp)=0;
  251. bool handle_message(const point &p,uint64_t timestamp)
  252. {
  253. bool flag = false;
  254. //int df=0;
  255. if(line_changed(p))//,df))
  256. {
  257. flag = true;
  258. //std::vector<point> rc=find_path(m_d.back().p,p);
  259. std::vector<point> rc=find_path(m_p,p);
  260. if(rc.empty())
  261. {
  262. log_info("his_location:line_changed rc.empty() %d",m_cardid);
  263. update(m_d.back().p,m_d.back().time);
  264. set(m_d.back().p,m_d.back().time);
  265. }
  266. else
  267. {
  268. if(handle_path(rc,timestamp,false))
  269. return true;
  270. }
  271. //置m_arg非法
  272. set_invalid();
  273. }
  274. //if(df==1)flag=true;
  275. return flag;
  276. }
  277. bool handle_path(std::vector<point> &rc,uint64_t timestamp,bool flag)
  278. {
  279. double dis=0;point _p=m_p;
  280. std::for_each(rc.begin(),rc.end(),[&dis,&_p](point &pt){
  281. pt.y=-pt.y;dis+=_p.dist(pt);_p=pt;
  282. });
  283. uint64_t t=timestamp/1000 - m_timestamp/1000;
  284. if(t==0||dis<0.1)return true;
  285. double avge_speed= dis/t;
  286. //有拐点 盲区时间差 距离
  287. uint64_t difftime=t;int dflag=0;
  288. if(!m_d.empty()) difftime=timestamp/1000-(m_d.back().time)/1000;
  289. if(difftime>=location_card::m_difftime && dis>location_card::m_distance)
  290. {
  291. 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);
  292. dflag=1;
  293. }
  294. for(const point & pp:rc)
  295. {
  296. m_arg=make_arg(pp,m_p);
  297. if(flag)insert();
  298. 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);
  299. double dist=m_p.dist(pp);uint64_t tt=dist/avge_speed*1000;
  300. uint64_t etime=m_timestamp+tt;
  301. update(pp,etime,0,dflag);set(pp,etime);
  302. flag=true;
  303. }
  304. return false;
  305. }
  306. };
  307. #endif