his_location.h 7.8 KB

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