his_location.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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)
  17. :m_cardid(id)
  18. ,m_type(type)
  19. {
  20. init();
  21. }
  22. uint32_t m_cardid;//卡id
  23. uint16_t m_type;//卡类型
  24. double m_arg;//运动方向角度值
  25. int m_areaid;//区域
  26. int m_mapid;//地图
  27. uint64_t m_timestamp;//入库后的时间
  28. point m_p;//入库后的点
  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. init_att();
  46. }
  47. void init_att()
  48. {
  49. m_arg=0x12345678;
  50. std::queue<mini_data> tmp;
  51. m_d.swap(tmp);
  52. }
  53. void set_invalid()
  54. {
  55. m_arg=0x12345678;
  56. }
  57. bool is_valid()
  58. {
  59. return m_arg!=0x12345678;
  60. }
  61. double make_arg(const point &pt,const point &p)
  62. {
  63. 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);
  64. return std::arg(std::complex<double>(pt.x,pt.y)-std::complex<double>(p.x,p.y));
  65. }
  66. void set(const point &pt,uint64_t time)
  67. {
  68. m_timestamp=time;
  69. m_p.set(pt);
  70. }
  71. bool line_changed(const point &pt)
  72. {
  73. if(!is_valid())
  74. return false;
  75. point p=m_d.back().p;
  76. //if(p==pt)return false;
  77. if(point::eq(p.x,pt.x,0.05) && point::eq(p.y,pt.y,0.05)) return false;
  78. double arg = make_arg(pt,p);
  79. 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);
  80. return !point::eq(arg,m_arg,1e-10);
  81. }
  82. bool is_speed_changed(const point& pt,uint64_t time)
  83. {
  84. bool flag = false;
  85. double v=0.0;
  86. if(m_d.size()>=4)
  87. {
  88. mini_data d1 = m_d.front();
  89. double dist = d1.p.dist(pt);
  90. double t = time-d1.time;
  91. v = dist/t*1000;
  92. m_d.pop();
  93. }
  94. m_d.emplace(pt,time);
  95. if(v==0.0)
  96. return flag;
  97. double dist = m_p.dist(pt);
  98. double t = time - m_timestamp;
  99. double avge_speed= dist/t*1000;
  100. 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);
  101. if(v<(1-0.2)*avge_speed && v>(1+0.2)*avge_speed)
  102. flag=true;
  103. return flag;
  104. }
  105. bool time_out(const point &p,uint64_t time)
  106. {
  107. if(time-m_timestamp>=60*1000 && !(p == m_p))
  108. return true;
  109. return false;
  110. }
  111. bool is_area_changed(int new_areaid)
  112. {
  113. bool flag =false;
  114. if(m_areaid != new_areaid)
  115. {
  116. m_areaid = new_areaid;
  117. flag=true;
  118. }
  119. return flag;
  120. }
  121. bool is_map_changed(int new_mapid)
  122. {
  123. bool flag =false;
  124. if(m_mapid != new_mapid)
  125. {
  126. m_mapid = new_mapid;
  127. flag=true;
  128. }
  129. return flag;
  130. }
  131. void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid)
  132. {
  133. if(m_p.empty() || m_timestamp==0||m_areaid<=0||m_mapid<=0)
  134. {
  135. set(p,timestamp);
  136. m_areaid=areaid;m_mapid=mapid;
  137. m_d.emplace(p,timestamp);
  138. return;
  139. }
  140. if(!is_valid())
  141. {
  142. if(p==m_p)
  143. {
  144. init_att();set(p,timestamp);
  145. m_d.emplace(p,timestamp);
  146. return ;
  147. }
  148. m_arg=make_arg(p,m_p);
  149. log_info("his_location:%d arg:%f",m_cardid,m_arg);
  150. insert();
  151. }
  152. bool flag=false;
  153. bool iflag=false;
  154. flag=handle_message(p,timestamp);
  155. if(time_out(p,timestamp))
  156. if(!flag)iflag=true;
  157. if(is_speed_changed(p,timestamp))
  158. if(!flag)iflag=true;
  159. if(is_area_changed(areaid))
  160. if(!flag)iflag=true;
  161. if(is_map_changed(mapid))
  162. if(!flag)iflag=true;
  163. if(iflag)
  164. {
  165. update(p,timestamp);
  166. //set_invalid();
  167. set(p,timestamp);
  168. insert();
  169. }
  170. }
  171. virtual std::string getTabName()=0;
  172. void insert()
  173. {
  174. std::string tabName=getTabName();
  175. char nsql[512]={0};
  176. const char * sql = "replace into %s (card_id,begin_time,map_id,area_id,begin_pt,direction)values(%03d%010d,'%s',%d,%d,'%.2f,%.2f',%f);";
  177. snprintf(nsql,512,sql,tabName.c_str(),m_type,m_cardid,tool_time::to_str_ex(m_timestamp).c_str(),m_mapid,m_areaid,m_p.x,m_p.y,m_arg);
  178. log_info("his_location[%d]:%s",m_cardid,nsql);
  179. sDBConnPool.PushAsync(nsql);
  180. }
  181. void update(const point &p,uint64_t timestamp)
  182. {
  183. std::string tabName=getTabName();
  184. char nsql[512]={0};
  185. const char * sql = "update %s set last_time='%s',speed=%.2f where card_id=%03d%010d and begin_time='%s';";
  186. double dist = m_p.dist(p);
  187. double t = timestamp - m_timestamp;
  188. double avge_speed= dist/t*1000;
  189. if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0;
  190. snprintf(nsql,512,sql,tabName.c_str(),tool_time::to_str_ex(timestamp).c_str(),avge_speed,m_type,m_cardid,tool_time::to_str_ex(m_timestamp).c_str());
  191. log_info("his_location[%d]:%s",m_cardid,nsql);
  192. sDBConnPool.PushAsync(nsql);
  193. }
  194. virtual bool handle_message(const point &p,uint64_t timestamp)=0;
  195. };
  196. struct location_staff:location_card
  197. {
  198. location_staff(uint32_t id,uint16_t type)
  199. :location_card(id,type)
  200. {}
  201. virtual std::string getTabName(){return std::string{"his_location_staff_"};}
  202. //人员如果运行方向发生变化的话,需要求的拐点。如果有拐点,入拐点。时间大与120s则不做处理。没有拐点,则不求
  203. virtual bool handle_message(const point &p,uint64_t timestamp)
  204. {
  205. bool flag = false;
  206. if(line_changed(p))
  207. {
  208. log_info("his_location:line_changed %d",m_cardid);
  209. flag=true;
  210. if(timestamp-m_timestamp>120*1000)
  211. {
  212. log_info("his_location:line_changed_timeout %d",m_cardid);
  213. update(m_d.back().p,m_d.back().time);
  214. set(p,timestamp);
  215. }
  216. else
  217. {
  218. 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);
  219. 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));
  220. if(rc.empty())
  221. {
  222. log_info("his_location:line_changed rc.empty() %d",m_cardid);
  223. update(m_d.back().p,m_d.back().time);
  224. set(m_d.back().p,m_d.back().time);
  225. }
  226. else
  227. {
  228. for(uint32_t i=0;i<rc.size();i++)
  229. log_info("his_location:find_path..x=%.3lf,y=%.3lf\n",rc[i].x,rc[i].y);
  230. if(rc.size()==1)
  231. {
  232. log_info("his_location:line_changed %d circle point(%.2f,%.2f)",m_cardid,rc[0].x,rc[0].y);
  233. point tmp(rc[0].x,-rc[0].y);
  234. update(tmp,m_d.back().time);
  235. set(tmp,m_d.back().time);
  236. }
  237. else if(rc.size()==2)
  238. {
  239. point tmp(rc[0].x,-rc[0].y);
  240. update(tmp,m_d.back().time);
  241. set(tmp,m_d.back().time);
  242. //
  243. tmp.set(rc[1].x,-rc[1].y);
  244. m_arg=make_arg(tmp,m_p);
  245. insert();
  246. //
  247. update(tmp,timestamp);
  248. set(tmp,timestamp);
  249. }
  250. else//更多的拐点
  251. {
  252. point tmp(rc[0].x,-rc[0].y);
  253. update(tmp,m_d.back().time);
  254. tmp.set(rc.back().x,-rc.back().y);
  255. set(tmp,timestamp);
  256. }
  257. }
  258. }
  259. init_att();
  260. }
  261. return flag;
  262. }
  263. };
  264. struct location_vehicle:location_card
  265. {
  266. location_vehicle(uint32_t id,uint16_t type)
  267. :location_card(id,type)
  268. {}
  269. virtual std::string getTabName(){return std::string{"his_location_vehicle_"};}
  270. //车辆是有推送拐点的,所以不需要求拐点。如果运行方向发生变化的话,直接更新数据库即可,使用上一个点的时间。同时生成这一次的历史。
  271. virtual bool handle_message(const point &p,uint64_t timestamp)
  272. {
  273. bool flag =false;
  274. if(line_changed(p))
  275. {
  276. log_info("his_location:line_changed %d ",m_cardid);
  277. flag=true;
  278. update(m_d.back().p,m_d.back().time);
  279. set(m_d.back().p,m_d.back().time);init_att();
  280. }
  281. return flag;
  282. }
  283. };
  284. #endif