polygon_path_finder.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. #include "polygon_path_finder.h"
  2. #include "geometry.h"
  3. bool PolygonPathFinder::_is_point_inside(const Vector2& p_point) const {
  4. int crosses=0;
  5. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  6. const Edge& e=E->get();
  7. Vector2 a = points[e.points[0]].pos;
  8. Vector2 b = points[e.points[1]].pos;
  9. if (Geometry::segment_intersects_segment_2d(a,b,p_point,outside_point,NULL)) {
  10. crosses++;
  11. }
  12. }
  13. return crosses&1;
  14. }
  15. void PolygonPathFinder::setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections) {
  16. ERR_FAIL_COND(p_connections.size()&1);
  17. points.clear();
  18. edges.clear();
  19. //insert points
  20. int point_count=p_points.size();
  21. points.resize(point_count+2);
  22. bounds=Rect2();
  23. for(int i=0;i<p_points.size();i++) {
  24. points[i].pos=p_points[i];
  25. points[i].penalty=0;
  26. outside_point.x = i==0?p_points[0].x:(MAX( p_points[i].x, outside_point.x ));
  27. outside_point.y = i==0?p_points[0].y:(MAX( p_points[i].y, outside_point.y ));
  28. if (i==0) {
  29. bounds.pos=points[i].pos;
  30. } else {
  31. bounds.expand_to(points[i].pos);
  32. }
  33. }
  34. outside_point.x+=20.451+Math::randf()*10.2039;
  35. outside_point.y+=21.193+Math::randf()*12.5412;
  36. //insert edges (which are also connetions)
  37. for(int i=0;i<p_connections.size();i+=2) {
  38. Edge e(p_connections[i],p_connections[i+1]);
  39. ERR_FAIL_INDEX(e.points[0],point_count);
  40. ERR_FAIL_INDEX(e.points[1],point_count);
  41. points[p_connections[i]].connections.insert(p_connections[i+1]);
  42. points[p_connections[i+1]].connections.insert(p_connections[i]);
  43. edges.insert(e);
  44. }
  45. //fill the remaining connections based on visibility
  46. for(int i=0;i<point_count;i++) {
  47. for(int j=i+1;j<point_count;j++) {
  48. if (edges.has(Edge(i,j)))
  49. continue; //if in edge ignore
  50. Vector2 from=points[i].pos;
  51. Vector2 to=points[j].pos;
  52. if (!_is_point_inside(from*0.5+to*0.5)) //connection between points in inside space
  53. continue;
  54. bool valid=true;
  55. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  56. const Edge& e=E->get();
  57. if (e.points[0]==i || e.points[1]==i || e.points[0]==j || e.points[1]==j )
  58. continue;
  59. Vector2 a = points[e.points[0]].pos;
  60. Vector2 b = points[e.points[1]].pos;
  61. if (Geometry::segment_intersects_segment_2d(a,b,from,to,NULL)) {
  62. valid=false;
  63. break;
  64. }
  65. }
  66. if (valid) {
  67. points[i].connections.insert(j);
  68. points[j].connections.insert(i);
  69. }
  70. }
  71. }
  72. }
  73. Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector2& p_to) {
  74. Vector<Vector2> path;
  75. Vector2 from=p_from;
  76. Vector2 to=p_to;
  77. Edge ignore_from_edge(-1,-1);
  78. Edge ignore_to_edge(-1,-1);
  79. if (!_is_point_inside(from)) {
  80. float closest_dist=1e20;
  81. Vector2 closest_point;
  82. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  83. const Edge& e=E->get();
  84. Vector2 seg[2]={
  85. points[e.points[0]].pos,
  86. points[e.points[1]].pos
  87. };
  88. Vector2 closest = Geometry::get_closest_point_to_segment_2d(from,seg);
  89. float d = from.distance_squared_to(closest);
  90. if (d<closest_dist) {
  91. ignore_from_edge=E->get();
  92. closest_dist=d;
  93. closest_point=closest;
  94. }
  95. }
  96. from=closest_point;
  97. };
  98. if (!_is_point_inside(to)) {
  99. float closest_dist=1e20;
  100. Vector2 closest_point;
  101. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  102. const Edge& e=E->get();
  103. Vector2 seg[2]={
  104. points[e.points[0]].pos,
  105. points[e.points[1]].pos
  106. };
  107. Vector2 closest = Geometry::get_closest_point_to_segment_2d(to,seg);
  108. float d = to.distance_squared_to(closest);
  109. if (d<closest_dist) {
  110. ignore_to_edge=E->get();
  111. closest_dist=d;
  112. closest_point=closest;
  113. }
  114. }
  115. to=closest_point;
  116. };
  117. //test direct connection
  118. {
  119. bool can_see_eachother=true;
  120. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  121. const Edge& e=E->get();
  122. if (e.points[0]==ignore_from_edge.points[0] && e.points[1]==ignore_from_edge.points[1])
  123. continue;
  124. if (e.points[0]==ignore_to_edge.points[0] && e.points[1]==ignore_to_edge.points[1])
  125. continue;
  126. Vector2 a = points[e.points[0]].pos;
  127. Vector2 b = points[e.points[1]].pos;
  128. if (Geometry::segment_intersects_segment_2d(a,b,from,to,NULL)) {
  129. can_see_eachother=false;
  130. break;
  131. }
  132. }
  133. if (can_see_eachother) {
  134. path.push_back(from);
  135. path.push_back(to);
  136. return path;
  137. }
  138. }
  139. //add to graph
  140. int aidx = points.size()-2;
  141. int bidx = points.size()-1;
  142. points[aidx].pos=from;
  143. points[bidx].pos=to;
  144. points[aidx].distance=0;
  145. points[bidx].distance=0;
  146. points[aidx].prev=-1;
  147. points[bidx].prev=-1;
  148. points[aidx].penalty=0;
  149. points[bidx].penalty=0;
  150. for(int i=0;i<points.size()-2;i++) {
  151. bool valid_a=true;
  152. bool valid_b=true;
  153. points[i].prev=-1;
  154. points[i].distance=0;
  155. if (!_is_point_inside(from*0.5+points[i].pos*0.5)) {
  156. valid_a=false;
  157. }
  158. if (!_is_point_inside(to*0.5+points[i].pos*0.5)) {
  159. valid_b=false;
  160. }
  161. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  162. const Edge& e=E->get();
  163. if (e.points[0]==i || e.points[1]==i)
  164. continue;
  165. Vector2 a = points[e.points[0]].pos;
  166. Vector2 b = points[e.points[1]].pos;
  167. if (valid_a) {
  168. if (e.points[0]!=ignore_from_edge.points[1] &&
  169. e.points[1]!=ignore_from_edge.points[1] &&
  170. e.points[0]!=ignore_from_edge.points[0] &&
  171. e.points[1]!=ignore_from_edge.points[0]) {
  172. if (Geometry::segment_intersects_segment_2d(a,b,from,points[i].pos,NULL)) {
  173. valid_a=false;
  174. }
  175. }
  176. }
  177. if (valid_b) {
  178. if (e.points[0]!=ignore_to_edge.points[1] &&
  179. e.points[1]!=ignore_to_edge.points[1] &&
  180. e.points[0]!=ignore_to_edge.points[0] &&
  181. e.points[1]!=ignore_to_edge.points[0]) {
  182. if (Geometry::segment_intersects_segment_2d(a,b,to,points[i].pos,NULL)) {
  183. valid_b=false;
  184. }
  185. }
  186. }
  187. if (!valid_a && !valid_b)
  188. break;
  189. }
  190. if (valid_a) {
  191. points[i].connections.insert(aidx);
  192. points[aidx].connections.insert(i);
  193. }
  194. if (valid_b) {
  195. points[i].connections.insert(bidx);
  196. points[bidx].connections.insert(i);
  197. }
  198. }
  199. //solve graph
  200. Set<int> open_list;
  201. points[aidx].distance=0;
  202. points[aidx].prev=aidx;
  203. for(Set<int>::Element *E=points[aidx].connections.front();E;E=E->next()) {
  204. open_list.insert(E->get());
  205. points[E->get()].distance=from.distance_to(points[E->get()].pos);
  206. points[E->get()].prev=aidx;
  207. }
  208. bool found_route=false;
  209. while(true) {
  210. if (open_list.size()==0) {
  211. printf("open list empty\n");
  212. break;
  213. }
  214. //check open list
  215. int least_cost_point=-1;
  216. float least_cost=1e30;
  217. //this could be faster (cache previous results)
  218. for (Set<int>::Element *E=open_list.front();E;E=E->next()) {
  219. const Point& p =points[E->get()];
  220. float cost = p.distance;
  221. cost+=p.pos.distance_to(to);
  222. cost+=p.penalty;
  223. if (cost<least_cost) {
  224. least_cost_point=E->get();
  225. least_cost=cost;
  226. }
  227. }
  228. Point &np = points[least_cost_point];
  229. //open the neighbours for search
  230. for(Set<int>::Element *E=np.connections.front();E;E=E->next()) {
  231. Point& p =points[E->get()];
  232. float distance = np.pos.distance_to(p.pos) + np.distance;
  233. if (p.prev!=-1) {
  234. //oh this was visited already, can we win the cost?
  235. if (p.distance>distance) {
  236. p.prev=least_cost_point; //reasign previous
  237. p.distance=distance;
  238. }
  239. } else {
  240. //add to open neighbours
  241. p.prev=least_cost_point;
  242. p.distance=distance;
  243. open_list.insert(E->get());
  244. if (E->get()==bidx) {
  245. //oh my reached end! stop algorithm
  246. found_route=true;
  247. break;
  248. }
  249. }
  250. }
  251. if (found_route)
  252. break;
  253. open_list.erase(least_cost_point);
  254. }
  255. if (found_route) {
  256. int at = bidx;
  257. path.push_back(points[at].pos);
  258. do {
  259. at=points[at].prev;
  260. path.push_back(points[at].pos);
  261. } while (at!=aidx);
  262. path.invert();;
  263. }
  264. for(int i=0;i<points.size()-2;i++) {
  265. points[i].connections.erase(aidx);
  266. points[i].connections.erase(bidx);
  267. points[i].prev=-1;
  268. points[i].distance=0;
  269. }
  270. points[aidx].connections.clear();
  271. points[aidx].prev=-1;
  272. points[aidx].distance=0;
  273. points[bidx].connections.clear();
  274. points[bidx].prev=-1;
  275. points[bidx].distance=0;
  276. return path;
  277. }
  278. void PolygonPathFinder::_set_data(const Dictionary& p_data) {
  279. ERR_FAIL_COND(!p_data.has("points"));
  280. ERR_FAIL_COND(!p_data.has("connections"));
  281. ERR_FAIL_COND(!p_data.has("segments"));
  282. ERR_FAIL_COND(!p_data.has("bounds"));
  283. DVector<Vector2> p=p_data["points"];
  284. Array c=p_data["connections"];
  285. ERR_FAIL_COND(c.size()!=p.size());
  286. if (c.size())
  287. return;
  288. int pc = p.size();
  289. points.resize(pc+2);
  290. DVector<Vector2>::Read pr=p.read();
  291. for(int i=0;i<pc;i++) {
  292. points[i].pos=pr[i];
  293. DVector<int> con=c[i];
  294. DVector<int>::Read cr=con.read();
  295. int cc=con.size();
  296. for(int j=0;j<cc;j++) {
  297. points[i].connections.insert(cr[j]);
  298. }
  299. }
  300. if (p_data.has("penalties")) {
  301. DVector<float> penalties=p_data["penalties"];
  302. if (penalties.size()==pc) {
  303. DVector<float>::Read pr = penalties.read();
  304. for(int i=0;i<pc;i++) {
  305. points[i].penalty=pr[i];
  306. }
  307. }
  308. }
  309. DVector<int> segs=p_data["segments"];
  310. int sc=segs.size();
  311. ERR_FAIL_COND(sc&1);
  312. DVector<int>::Read sr = segs.read();
  313. for(int i=0;i<sc;i+=2) {
  314. Edge e(sr[i],sr[i+1]);
  315. edges.insert(e);
  316. }
  317. bounds=p_data["bounds"];
  318. }
  319. Dictionary PolygonPathFinder::_get_data() const{
  320. Dictionary d;
  321. DVector<Vector2> p;
  322. DVector<int> ind;
  323. Array connections;
  324. p.resize(points.size()-2);
  325. connections.resize(points.size()-2);
  326. ind.resize(edges.size()*2);
  327. DVector<float> penalties;
  328. penalties.resize(points.size()-2);
  329. {
  330. DVector<Vector2>::Write wp=p.write();
  331. DVector<float>::Write pw=penalties.write();
  332. for(int i=0;i<points.size()-2;i++) {
  333. wp[i]=points[i].pos;
  334. pw[i]=points[i].penalty;
  335. DVector<int> c;
  336. c.resize(points[i].connections.size());
  337. {
  338. DVector<int>::Write cw=c.write();
  339. int idx=0;
  340. for (Set<int>::Element *E=points[i].connections.front();E;E=E->next()) {
  341. cw[idx++]=E->get();
  342. }
  343. }
  344. connections[i]=c;
  345. }
  346. }
  347. {
  348. DVector<int>::Write iw=ind.write();
  349. int idx=0;
  350. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  351. iw[idx++]=E->get().points[0];
  352. iw[idx++]=E->get().points[1];
  353. }
  354. }
  355. d["bounds"]=bounds;
  356. d["points"]=p;
  357. d["penalties"]=penalties;
  358. d["connections"]=connections;
  359. d["segments"]=ind;
  360. return d;
  361. }
  362. bool PolygonPathFinder::is_point_inside(const Vector2& p_point) const {
  363. return _is_point_inside(p_point);
  364. }
  365. Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const {
  366. float closest_dist=1e20;
  367. Vector2 closest_point;
  368. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  369. const Edge& e=E->get();
  370. Vector2 seg[2]={
  371. points[e.points[0]].pos,
  372. points[e.points[1]].pos
  373. };
  374. Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point,seg);
  375. float d = p_point.distance_squared_to(closest);
  376. if (d<closest_dist) {
  377. closest_dist=d;
  378. closest_point=closest;
  379. }
  380. }
  381. ERR_FAIL_COND_V(closest_dist==1e20,Vector2());
  382. return closest_point;
  383. }
  384. Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2& p_from, const Vector2& p_to) const {
  385. Vector<Vector2> inters;
  386. for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
  387. Vector2 a = points[E->get().points[0]].pos;
  388. Vector2 b = points[E->get().points[1]].pos;
  389. Vector2 res;
  390. if (Geometry::segment_intersects_segment_2d(a,b,p_from,p_to,&res)) {
  391. inters.push_back(res);
  392. }
  393. }
  394. return inters;
  395. }
  396. Rect2 PolygonPathFinder::get_bounds() const {
  397. return bounds;
  398. }
  399. void PolygonPathFinder::set_point_penalty(int p_point,float p_penalty) {
  400. ERR_FAIL_INDEX(p_point,points.size()-2);
  401. points[p_point].penalty=p_penalty;
  402. }
  403. float PolygonPathFinder::get_point_penalty(int p_point) const {
  404. ERR_FAIL_INDEX_V(p_point,points.size()-2,0);
  405. return points[p_point].penalty;
  406. }
  407. void PolygonPathFinder::_bind_methods() {
  408. ObjectTypeDB::bind_method(_MD("setup","points","connections"),&PolygonPathFinder::setup);
  409. ObjectTypeDB::bind_method(_MD("find_path","from","to"),&PolygonPathFinder::find_path);
  410. ObjectTypeDB::bind_method(_MD("get_intersections","from","to"),&PolygonPathFinder::get_intersections);
  411. ObjectTypeDB::bind_method(_MD("get_closest_point","point"),&PolygonPathFinder::get_closest_point);
  412. ObjectTypeDB::bind_method(_MD("is_point_inside","point"),&PolygonPathFinder::is_point_inside);
  413. ObjectTypeDB::bind_method(_MD("set_point_penalty","idx","penalty"),&PolygonPathFinder::set_point_penalty);
  414. ObjectTypeDB::bind_method(_MD("get_point_penalty","idx"),&PolygonPathFinder::get_point_penalty);
  415. ObjectTypeDB::bind_method(_MD("get_bounds"),&PolygonPathFinder::get_bounds);
  416. ObjectTypeDB::bind_method(_MD("_set_data"),&PolygonPathFinder::_set_data);
  417. ObjectTypeDB::bind_method(_MD("_get_data"),&PolygonPathFinder::_get_data);
  418. ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
  419. }
  420. PolygonPathFinder::PolygonPathFinder()
  421. {
  422. }