his_location.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. :m_cardid(id)
  18. ,m_type(type)
  19. ,m_objid(objid)
  20. {
  21. init();
  22. }
  23. uint32_t m_cardid;//卡id
  24. uint16_t m_type;//卡类型
  25. uint32_t m_objid;
  26. double m_arg;//运动方向角度值
  27. int m_areaid;//区域
  28. int m_mapid;//地图
  29. uint64_t m_timestamp;//入库后的时间
  30. point m_p;//入库后的点
  31. int m_direct_index;
  32. struct mini_data
  33. {
  34. mini_data(const point &p,uint64_t t)
  35. :p(p)
  36. ,time(t)
  37. {}
  38. point p;
  39. uint64_t time;
  40. };
  41. std::queue<mini_data> m_d;
  42. void init()
  43. {
  44. m_areaid=-1;
  45. m_mapid=-1;
  46. m_timestamp=0;
  47. m_p.set(0,0);
  48. std::queue<mini_data> tmp;
  49. m_d.swap(tmp);
  50. m_direct_index=0;
  51. }
  52. void init_att(const point &pt,uint64_t time)
  53. {
  54. std::queue<mini_data> tmp;
  55. m_d.swap(tmp);
  56. m_d.emplace(pt,time);
  57. }
  58. void set_invalid()
  59. {
  60. m_arg=0x12345678;
  61. }
  62. bool is_valid()
  63. {
  64. return m_arg!=0x12345678;
  65. }
  66. double make_arg(const point &pt,const point &p)
  67. {
  68. 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);
  69. return std::arg(std::complex<double>(pt.x,pt.y)-std::complex<double>(p.x,p.y));
  70. }
  71. void set(const point &pt,uint64_t time)
  72. {
  73. m_timestamp=time;
  74. m_p.set(pt);
  75. init_att(pt,time);
  76. }
  77. bool line_changed(const point &pt,int &df)
  78. {
  79. if(!is_valid())
  80. return false;
  81. point p;
  82. if(m_d.empty())p=m_p; else p=m_d.back().p;
  83. if(point::eq(p.x,pt.x,0.2) && point::eq(p.y,pt.y,0.2)) return false;
  84. double dis1=m_p.dist(pt);
  85. if(dis1<2)return false;
  86. double dis = p.dist(pt);
  87. double arg = make_arg(pt,p);
  88. //查看路径方向是否改变
  89. bool change_flag=(arg-m_arg > -1e-10 && arg-m_arg<1e-10);
  90. //change_flag为true,标识没有发生变化
  91. if(change_flag)m_direct_index=0;
  92. 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);
  93. //if(dis<0.5 && fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
  94. //判断5次反向才做下一步动作
  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. }
  104. bool is_speed_changed(const point& pt,uint64_t time)
  105. {
  106. bool flag = false;
  107. double v=0.0;
  108. if(m_d.size()>=4)
  109. {
  110. mini_data d1 = m_d.front();
  111. double dist = d1.p.dist(pt);
  112. double t = time-d1.time;
  113. v = dist/t*1000;
  114. m_d.pop();
  115. }
  116. m_d.emplace(pt,time);
  117. if(v<=0.1)
  118. return flag;
  119. double dist = m_p.dist(pt);
  120. double t = time - m_timestamp;
  121. double avge_speed= dist/t*1000;
  122. 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);
  123. if(v<(1-0.3)*avge_speed && v>(1+0.3)*avge_speed)
  124. flag=true;
  125. return flag;
  126. }
  127. bool time_out(const point &p,uint64_t time)
  128. {
  129. if(time-m_timestamp>=30*1000 && m_p.dist(p)>0.1)
  130. return true;
  131. return false;
  132. }
  133. bool is_area_changed(int new_areaid)
  134. {
  135. bool flag =false;
  136. if(m_areaid != new_areaid)
  137. {
  138. m_areaid = new_areaid;
  139. flag=true;
  140. }
  141. return flag;
  142. }
  143. bool is_map_changed(int new_mapid)
  144. {
  145. bool flag =false;
  146. if(m_mapid != new_mapid)
  147. {
  148. m_mapid = new_mapid;
  149. flag=true;
  150. }
  151. return flag;
  152. }
  153. void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid)
  154. {
  155. if(m_p.empty() || m_timestamp==0||m_areaid<0||m_mapid<0)
  156. {
  157. set(p,timestamp);
  158. m_areaid=areaid;m_mapid=mapid;
  159. m_d.emplace(p,timestamp);
  160. return;
  161. }
  162. if(!is_valid())
  163. {
  164. //if(p==m_p)
  165. if(point::eq(p.x,m_p.x,0.2) && point::eq(p.y,m_p.y,0.2))
  166. {
  167. set(p,timestamp);
  168. return ;
  169. }
  170. auto v=find_path(m_p,p);
  171. if(v.empty())
  172. m_arg=make_arg(p,m_p);
  173. else
  174. {
  175. log_info("his_location:more_abnormal_point....%d,(%.2f,%.2f)---(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y);
  176. handle_path(v,timestamp,true);
  177. set_invalid();
  178. return;
  179. }
  180. log_info("his_location:%d arg:%f",m_cardid,m_arg);
  181. insert();
  182. return;
  183. }
  184. bool flag=false;
  185. int iflag=0;
  186. //判断是否路径发生了变化
  187. flag=handle_message(p,timestamp);
  188. if(time_out(p,timestamp))
  189. if(!flag)iflag=2;
  190. if(is_speed_changed(p,timestamp))
  191. if(!flag)iflag=1;
  192. if(is_area_changed(areaid))
  193. if(!flag)iflag=1;
  194. if(is_map_changed(mapid))
  195. if(!flag)iflag=1;
  196. if(iflag)
  197. {
  198. update(p,timestamp);
  199. //set_invalid();
  200. if(iflag==1){
  201. set(p,timestamp);
  202. insert();
  203. }
  204. }
  205. }
  206. void insert()
  207. {
  208. //std::string tabName=getTabName();
  209. char nsql[512]={0};
  210. const char * sql = "replace into his_location (obj_id,card_type_id,ident,begin_time,map_id,area_id,begin_pt,direction)"
  211. "values(%d,%d,%d,'%s',%d,%d,'%.2f,%.2f',%f);";
  212. 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);
  213. log_info("his_location[%d,%lu]:%s",m_cardid,m_timestamp,nsql);
  214. sDBConnPool.PushAsync(nsql);
  215. }
  216. void update(const point &p,uint64_t timestamp)
  217. {
  218. //std::string tabName=getTabName();
  219. char nsql[512]={0};
  220. const char * sql = "update his_location set last_time='%s',speed=%.2f where obj_id=%d and begin_time='%s' and last_time is null;";
  221. double dist = m_p.dist(p);
  222. double t = (timestamp - m_timestamp)/1000;
  223. double avge_speed= dist/t;
  224. if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0;
  225. 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());
  226. log_info("his_location[%d]:%s[%lu,%lu]",m_cardid,nsql,timestamp,m_timestamp);
  227. sDBConnPool.PushAsync(nsql);
  228. }
  229. std::vector<point> find_path(const point &p1,const point &p2)
  230. {
  231. std::vector<point> rc=card_path::inst().find_path(point(p1.x,-p1.y),point(p2.x,-p2.y));
  232. return std::move(rc);
  233. }
  234. //virtual bool handle_message(const point &p,uint64_t timestamp)=0;
  235. bool handle_message(const point &p,uint64_t timestamp)
  236. {
  237. bool flag = false;
  238. int df=0;
  239. if(line_changed(p,df))
  240. {
  241. flag = true;
  242. std::vector<point> rc=find_path(m_d.back().p,p);
  243. if(rc.empty())
  244. {
  245. log_info("his_location:line_changed rc.empty() %d",m_cardid);
  246. update(m_d.back().p,m_d.back().time);
  247. set(m_d.back().p,m_d.back().time);
  248. }
  249. else
  250. {
  251. if(handle_path(rc,timestamp,false))
  252. return true;
  253. }
  254. //置m_arg非法
  255. set_invalid();
  256. }
  257. if(df==1)flag=true;
  258. return flag;
  259. }
  260. bool handle_path(std::vector<point> &rc,uint64_t timestamp,bool flag)
  261. {
  262. double dis=0;point _p=m_p;
  263. std::for_each(rc.begin(),rc.end(),[&dis,&_p](point &pt){
  264. pt.y=-pt.y;dis+=_p.dist(pt);_p=pt;
  265. });
  266. uint64_t t=timestamp/1000 - m_timestamp/1000;
  267. if(t==0||dis<0.1)return true;
  268. double avge_speed= dis/t;
  269. for(const point & pp:rc)
  270. {
  271. if(flag){
  272. m_arg=make_arg(pp,m_p);insert();
  273. }
  274. log_info("his_location:line_changed_x %d point(%.2f,%.2f)--circle point(%.2f,%.2f),speed:%.2f",m_cardid,m_p.x,m_p.y,pp.x,pp.y,avge_speed);
  275. double dist=m_p.dist(pp);uint64_t tt=dist/avge_speed*1000;
  276. uint64_t etime=m_timestamp+tt;
  277. update(pp,etime);set(pp,etime);
  278. flag=true;
  279. }
  280. return false;
  281. }
  282. };
  283. #if 0
  284. struct location_staff:location_card
  285. {
  286. location_staff(uint32_t id,uint64_t type,uint32_t objid)
  287. :location_card(id,type,objid)
  288. {}
  289. virtual std::string getTabName(){return std::string{"his_location_staff_"};}
  290. //人员如果运行方向发生变化的话,需要求的拐点。如果有拐点,入拐点。时间大与120s则不做处理。没有拐点,则不求
  291. virtual bool handle_message(const point &p,uint64_t timestamp)
  292. {
  293. bool flag = false;
  294. if(line_changed(p))
  295. {
  296. log_info("his_location:line_changed %d",m_cardid);
  297. flag=true;
  298. if(timestamp-m_timestamp>120*1000)
  299. {
  300. log_info("his_location:line_changed_timeout %d",m_cardid);
  301. update(m_d.back().p,m_d.back().time);
  302. set(p,timestamp);
  303. }
  304. else
  305. {
  306. 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);
  307. if(rc.empty())
  308. {
  309. log_info("his_location:line_changed rc.empty() %d",m_cardid);
  310. update(m_d.back().p,m_d.back().time);
  311. set(m_d.back().p,m_d.back().time);
  312. }
  313. else
  314. {
  315. for(uint32_t i=0;i<rc.size();i++)
  316. log_info("his_location:find_path..x=%.3lf,y=%.3lf\n",rc[i].x,rc[i].y);
  317. if(rc.size()==1)
  318. {
  319. log_info("his_location:line_changed %d circle point(%.2f,%.2f)",m_cardid,rc[0].x,rc[0].y);
  320. point tmp(rc[0].x,-rc[0].y);
  321. update(tmp,m_d.back().time);
  322. set(tmp,m_d.back().time);
  323. }
  324. else if(rc.size()==2)
  325. {
  326. point tmp(rc[0].x,-rc[0].y);
  327. update(tmp,m_d.back().time);
  328. set(tmp,m_d.back().time);
  329. //
  330. tmp.set(rc[1].x,-rc[1].y);
  331. m_arg=make_arg(tmp,m_p);
  332. insert();
  333. //
  334. update(tmp,timestamp);
  335. set(tmp,timestamp);
  336. }
  337. else//更多的拐点
  338. {
  339. point tmp(rc[0].x,-rc[0].y);
  340. update(tmp,m_d.back().time);
  341. tmp.set(rc.back().x,-rc.back().y);
  342. set(tmp,timestamp);
  343. }
  344. }
  345. }
  346. init_att();
  347. }
  348. return flag;
  349. }
  350. };
  351. struct location_vehicle:location_card
  352. {
  353. location_vehicle(uint32_t id,uint64_t type,uint32_t objid)
  354. :location_card(id,type,objid)
  355. {}
  356. virtual std::string getTabName(){return std::string{"his_location_vehicle_"};}
  357. //车辆是有推送拐点的,所以不需要求拐点。如果运行方向发生变化的话,直接更新数据库即可,使用上一个点的时间。同时生成这一次的历史。
  358. virtual bool handle_message(const point &p,uint64_t timestamp)
  359. {
  360. bool flag =false;
  361. if(line_changed(p))
  362. {
  363. flag=true;
  364. //如果有拐点,说明是丢失信号后,飞跃得过程
  365. // 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));
  366. log_info("his_location:line_changed %d ",m_cardid);
  367. update(m_d.back().p,m_d.back().time);
  368. set(m_d.back().p,m_d.back().time);init_att();
  369. }
  370. return flag;
  371. }
  372. };
  373. #endif
  374. #endif