eventlist.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /****************************************************************************
  2. *
  3. * MODULE: r.viewshed
  4. *
  5. * AUTHOR(S): Laura Toma, Bowdoin College - ltoma@bowdoin.edu
  6. * Yi Zhuang - yzhuang@bowdoin.edu
  7. * Ported to GRASS by William Richard -
  8. * wkrichar@bowdoin.edu or willster3021@gmail.com
  9. * Markus Metz: surface interpolation
  10. *
  11. * Date: april 2011
  12. *
  13. * PURPOSE: To calculate the viewshed (the visible cells in the
  14. * raster) for the given viewpoint (observer) location. The
  15. * visibility model is the following: Two points in the raster are
  16. * considered visible to each other if the cells where they belong are
  17. * visible to each other. Two cells are visible to each other if the
  18. * line-of-sight that connects their centers does not intersect the
  19. * terrain. The terrain is NOT viewed as a tesselation of flat cells,
  20. * i.e. if the line-of-sight does not pass through the cell center,
  21. * elevation is determined using bilinear interpolation.
  22. * The viewshed algorithm is efficient both in
  23. * terms of CPU operations and I/O operations. It has worst-case
  24. * complexity O(n lg n) in the RAM model and O(sort(n)) in the
  25. * I/O-model. For the algorithm and all the other details see the
  26. * paper: "Computing Visibility on * Terrains in External Memory" by
  27. * Herman Haverkort, Laura Toma and Yi Zhuang.
  28. *
  29. * COPYRIGHT: (C) 2008 by the GRASS Development Team
  30. *
  31. * This program is free software under the GNU General Public License
  32. * (>=v2). Read the file COPYING that comes with GRASS for details.
  33. *
  34. *****************************************************************************/
  35. #include <math.h>
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <assert.h>
  39. extern "C"
  40. {
  41. #include <grass/gis.h>
  42. }
  43. #include "eventlist.h"
  44. /* forced to use this because DistanceCompare::compare has troubles if
  45. i put it inside the class */
  46. Viewpoint globalVP;
  47. /* ------------------------------------------------------------
  48. compute the gradient of the CENTER of this event wrt viewpoint. For
  49. efficiency it does not compute the gradient, but the square of the
  50. arctan of the gradient. Assuming all gradients are computed the same
  51. way, this is correct. */
  52. double calculate_center_gradient(AEvent * e, Viewpoint * vp)
  53. {
  54. assert(e && vp);
  55. double gradient, sqdist;
  56. /*square of the distance from the center of this event to vp */
  57. sqdist = (e->row - vp->row) * (e->row - vp->row) +
  58. (e->col - vp->col) * (e->col - vp->col);
  59. gradient = (e->elev[1] - vp->elev) * (e->elev[1] - vp->elev) / sqdist;
  60. /*maintain sign */
  61. if (e->elev[1] < vp->elev)
  62. gradient = -gradient;
  63. return gradient;
  64. }
  65. /* ------------------------------------------------------------
  66. //calculate the angle at which the event is. Return value is the angle.
  67. angle quadrants:
  68. 2 1
  69. 3 4
  70. ----->x
  71. |
  72. |
  73. |
  74. V y
  75. */
  76. /*/////////////////////////////////////////////////////////////////////
  77. //return the angle from this event wrt viewpoint; the type of the
  78. //event is taken into position to compute a different amngle for each
  79. //event associated with a cell */
  80. double calculate_event_angle(AEvent * e, Viewpoint * vp)
  81. {
  82. assert(e && vp);
  83. double ex, ey;
  84. calculate_event_position(*e, vp->row, vp->col, &ey, &ex);
  85. return calculate_angle(ex, ey, vp->col, vp->row);
  86. }
  87. /*/////////////////////////////////////////////////////////////////////
  88. //calculate the exit angle corresponding to this cell */
  89. double
  90. calculate_exit_angle(dimensionType row, dimensionType col, Viewpoint * vp)
  91. {
  92. AEvent e;
  93. double x, y;
  94. e.eventType = EXITING_EVENT;
  95. e.angle = 0;
  96. e.elev[0] = e.elev[1] = e.elev[2] = 0;
  97. e.row = row;
  98. e.col = col;
  99. calculate_event_position(e, vp->row, vp->col, &y, &x);
  100. return calculate_angle(x, y, vp->col, vp->row);
  101. }
  102. /*/////////////////////////////////////////////////////////////////////
  103. //calculate the enter angle corresponding to this cell */
  104. double
  105. calculate_enter_angle(dimensionType row, dimensionType col, Viewpoint * vp)
  106. {
  107. AEvent e;
  108. double x, y;
  109. e.eventType = ENTERING_EVENT;
  110. e.angle = 0;
  111. e.elev[0] = e.elev[1] = e.elev[2] = 0;
  112. e.row = row;
  113. e.col = col;
  114. calculate_event_position(e, vp->row, vp->col, &y, &x);
  115. return calculate_angle(x, y, vp->col, vp->row);
  116. }
  117. /*///////////////////////////////////////////////////////////////////// */
  118. double
  119. calculate_angle(double eventX, double eventY,
  120. double viewpointX, double viewpointY)
  121. {
  122. double angle = atan(fabs(eventY - viewpointY) / fabs(eventX - viewpointX));
  123. /*M_PI is defined in math.h to represent 3.14159... */
  124. if (viewpointY == eventY && eventX > viewpointX) {
  125. return 0; /*between 1st and 4th quadrant */
  126. }
  127. else if (eventX > viewpointX && eventY < viewpointY) {
  128. /*first quadrant */
  129. return angle;
  130. }
  131. else if (viewpointX == eventX && viewpointY > eventY) {
  132. /*between 1st and 2nd quadrant */
  133. return (M_PI) / 2;
  134. }
  135. else if (eventX < viewpointX && eventY < viewpointY) {
  136. /*second quadrant */
  137. return (M_PI - angle);
  138. }
  139. else if (viewpointY == eventY && eventX < viewpointX) {
  140. /*between 1st and 3rd quadrant */
  141. return M_PI;
  142. }
  143. else if (eventY > viewpointY && eventX < viewpointX) {
  144. /*3rd quadrant */
  145. return (M_PI + angle);
  146. }
  147. else if (viewpointX == eventX && viewpointY < eventY) {
  148. /*between 3rd and 4th quadrant */
  149. return (M_PI * 3.0 / 2.0);
  150. }
  151. else if (eventX > viewpointX && eventY > viewpointY) {
  152. /*4th quadrant */
  153. return (M_PI * 2.0 - angle);
  154. }
  155. assert(eventX == viewpointX && eventY == viewpointY);
  156. return 0;
  157. }
  158. /* ------------------------------------------------------------ */
  159. /* calculate the exact position of the given event, and store them in x
  160. and y.
  161. quadrants: 1 2
  162. 3 4
  163. ----->x
  164. |
  165. |
  166. |
  167. V y
  168. */
  169. void
  170. calculate_event_position(AEvent e, dimensionType viewpointRow,
  171. dimensionType viewpointCol, double *y, double *x)
  172. {
  173. assert(x && y);
  174. *x = 0;
  175. *y = 0;
  176. if (e.eventType == CENTER_EVENT) {
  177. /*FOR CENTER_EVENTS */
  178. *y = e.row;
  179. *x = e.col;
  180. return;
  181. }
  182. if (e.row < viewpointRow && e.col < viewpointCol) {
  183. /*first quadrant */
  184. if (e.eventType == ENTERING_EVENT) {
  185. /*if it is ENTERING_EVENT */
  186. *y = e.row - 0.5;
  187. *x = e.col + 0.5;
  188. }
  189. else {
  190. /*otherwise it is EXITING_EVENT */
  191. *y = e.row + 0.5;
  192. *x = e.col - 0.5;
  193. }
  194. }
  195. else if (e.col == viewpointCol && e.row < viewpointRow) {
  196. /*between the first and second quadrant */
  197. if (e.eventType == ENTERING_EVENT) {
  198. /*if it is ENTERING_EVENT */
  199. *y = e.row + 0.5;
  200. *x = e.col + 0.5;
  201. }
  202. else {
  203. /*otherwise it is EXITING_EVENT */
  204. *y = e.row + 0.5;
  205. *x = e.col - 0.5;
  206. }
  207. }
  208. else if (e.col > viewpointCol && e.row < viewpointRow) {
  209. /*second quadrant */
  210. if (e.eventType == ENTERING_EVENT) {
  211. /*if it is ENTERING_EVENT */
  212. *y = e.row + 0.5;
  213. *x = e.col + 0.5;
  214. }
  215. else { /*otherwise it is EXITING_EVENT */
  216. *y = e.row - 0.5;
  217. *x = e.col - 0.5;
  218. }
  219. }
  220. else if (e.row == viewpointRow && e.col > viewpointCol) {
  221. /*between the second and the fourth quadrant */
  222. if (e.eventType == ENTERING_EVENT) {
  223. /*if it is ENTERING_EVENT */
  224. *y = e.row + 0.5;
  225. *x = e.col - 0.5;
  226. }
  227. else {
  228. /*otherwise it is EXITING_EVENT */
  229. *y = e.row - 0.5;
  230. *x = e.col - 0.5;
  231. }
  232. }
  233. else if (e.col > viewpointCol && e.row > viewpointRow) {
  234. /*fourth quadrant */
  235. if (e.eventType == ENTERING_EVENT) {
  236. /*if it is ENTERING_EVENT */
  237. *y = e.row + 0.5;
  238. *x = e.col - 0.5;
  239. }
  240. else {
  241. /*otherwise it is EXITING_EVENT */
  242. *y = e.row - 0.5;
  243. *x = e.col + 0.5;
  244. }
  245. }
  246. else if (e.col == viewpointCol && e.row > viewpointRow) {
  247. /*between the third and fourth quadrant */
  248. if (e.eventType == ENTERING_EVENT) {
  249. /*if it is ENTERING_EVENT */
  250. *y = e.row - 0.5;
  251. *x = e.col - 0.5;
  252. }
  253. else {
  254. /*otherwise it is EXITING_EVENT */
  255. *y = e.row - 0.5;
  256. *x = e.col + 0.5;
  257. }
  258. }
  259. else if (e.col < viewpointCol && e.row > viewpointRow) {
  260. /*third quadrant */
  261. if (e.eventType == ENTERING_EVENT) {
  262. /*if it is ENTERING_EVENT */
  263. *y = e.row - 0.5;
  264. *x = e.col - 0.5;
  265. }
  266. else {
  267. /*otherwise it is EXITING_EVENT */
  268. *y = e.row + 0.5;
  269. *x = e.col + 0.5;
  270. }
  271. }
  272. else if (e.row == viewpointRow && e.col < viewpointCol) {
  273. /*between first and third quadrant */
  274. if (e.eventType == ENTERING_EVENT) { /*if it is ENTERING_EVENT */
  275. *y = e.row - 0.5;
  276. *x = e.col + 0.5;
  277. }
  278. else {
  279. /*otherwise it is EXITING_EVENT */
  280. *y = e.row + 0.5;
  281. *x = e.col + 0.5;
  282. }
  283. }
  284. else {
  285. /*must be the viewpoint cell itself */
  286. assert(e.row == viewpointRow && e.col == viewpointCol);
  287. *x = e.col;
  288. *y = e.row;
  289. }
  290. assert(fabs(*x - e.col) < 1 && fabs(*y - e.row) < 1);
  291. /*
  292. if ((fabs(*x -e.col) >=1) || (fabs(*y -e.row) >=1)) {
  293. G_warning("x-e.col=%f, y-e.row=%f ", fabs(*x -e.col), fabs(*y -e.row));
  294. print_event(e, 0);
  295. G_warning("vp=(%d, %d), x=%.3f, y=%.3f", viewpointRow, viewpointCol, *x, *y);
  296. exit(1);
  297. }
  298. */
  299. return;
  300. }
  301. void
  302. calculate_event_row_col(AEvent e, dimensionType viewpointRow,
  303. dimensionType viewpointCol, int *y, int *x)
  304. {
  305. assert(x && y);
  306. *x = 0;
  307. *y = 0;
  308. if (e.eventType == CENTER_EVENT) {
  309. G_fatal_error("calculate_event_row_col() must not be called for CENTER events");
  310. }
  311. if (e.row < viewpointRow && e.col < viewpointCol) {
  312. /*first quadrant */
  313. if (e.eventType == ENTERING_EVENT) {
  314. /*if it is ENTERING_EVENT */
  315. *y = e.row - 1;
  316. *x = e.col + 1;
  317. }
  318. else {
  319. /*otherwise it is EXITING_EVENT */
  320. *y = e.row + 1;
  321. *x = e.col - 1;
  322. }
  323. }
  324. else if (e.col == viewpointCol && e.row < viewpointRow) {
  325. /*between the first and second quadrant */
  326. if (e.eventType == ENTERING_EVENT) {
  327. /*if it is ENTERING_EVENT */
  328. *y = e.row + 1;
  329. *x = e.col + 1;
  330. }
  331. else {
  332. /*otherwise it is EXITING_EVENT */
  333. *y = e.row + 1;
  334. *x = e.col - 1;
  335. }
  336. }
  337. else if (e.col > viewpointCol && e.row < viewpointRow) {
  338. /*second quadrant */
  339. if (e.eventType == ENTERING_EVENT) {
  340. /*if it is ENTERING_EVENT */
  341. *y = e.row + 1;
  342. *x = e.col + 1;
  343. }
  344. else { /*otherwise it is EXITING_EVENT */
  345. *y = e.row - 1;
  346. *x = e.col - 1;
  347. }
  348. }
  349. else if (e.row == viewpointRow && e.col > viewpointCol) {
  350. /*between the second and the fourth quadrant */
  351. if (e.eventType == ENTERING_EVENT) {
  352. /*if it is ENTERING_EVENT */
  353. *y = e.row + 1;
  354. *x = e.col - 1;
  355. }
  356. else {
  357. /*otherwise it is EXITING_EVENT */
  358. *y = e.row - 1;
  359. *x = e.col - 1;
  360. }
  361. }
  362. else if (e.col > viewpointCol && e.row > viewpointRow) {
  363. /*fourth quadrant */
  364. if (e.eventType == ENTERING_EVENT) {
  365. /*if it is ENTERING_EVENT */
  366. *y = e.row + 1;
  367. *x = e.col - 1;
  368. }
  369. else {
  370. /*otherwise it is EXITING_EVENT */
  371. *y = e.row - 1;
  372. *x = e.col + 1;
  373. }
  374. }
  375. else if (e.col == viewpointCol && e.row > viewpointRow) {
  376. /*between the third and fourth quadrant */
  377. if (e.eventType == ENTERING_EVENT) {
  378. /*if it is ENTERING_EVENT */
  379. *y = e.row - 1;
  380. *x = e.col - 1;
  381. }
  382. else {
  383. /*otherwise it is EXITING_EVENT */
  384. *y = e.row - 1;
  385. *x = e.col + 1;
  386. }
  387. }
  388. else if (e.col < viewpointCol && e.row > viewpointRow) {
  389. /*third quadrant */
  390. if (e.eventType == ENTERING_EVENT) {
  391. /*if it is ENTERING_EVENT */
  392. *y = e.row - 1;
  393. *x = e.col - 1;
  394. }
  395. else {
  396. /*otherwise it is EXITING_EVENT */
  397. *y = e.row + 1;
  398. *x = e.col + 1;
  399. }
  400. }
  401. else if (e.row == viewpointRow && e.col < viewpointCol) {
  402. /*between first and third quadrant */
  403. if (e.eventType == ENTERING_EVENT) { /*if it is ENTERING_EVENT */
  404. *y = e.row - 1;
  405. *x = e.col + 1;
  406. }
  407. else {
  408. /*otherwise it is EXITING_EVENT */
  409. *y = e.row + 1;
  410. *x = e.col + 1;
  411. }
  412. }
  413. else {
  414. /*must be the viewpoint cell itself */
  415. G_debug(1, "calculate_event_row_col() called for viewpoint cell itself");
  416. assert(e.row == viewpointRow && e.col == viewpointCol);
  417. *x = e.col;
  418. *y = e.row;
  419. }
  420. /* assert(fabs(*x - e.col) <= 1 && fabs(*y - e.row) <= 1); */
  421. if ((abs(*x - e.col) > 1) || (abs(*y - e.row) > 1)) {
  422. G_warning("calculate_event_row_col() :");
  423. G_warning("x-e.col=%d, y-e.row=%d", abs(*x - e.col), abs(*y - e.row));
  424. print_event(e, 0);
  425. G_warning("vp=(%d, %d), x=%d, y=%d", viewpointRow, viewpointCol, *x, *y);
  426. exit(1);
  427. }
  428. return;
  429. }
  430. /* ------------------------------------------------------------ */
  431. void print_event(AEvent a, int debug_level)
  432. {
  433. char c = '0';
  434. if (a.eventType == ENTERING_EVENT)
  435. c = 'E';
  436. if (a.eventType == EXITING_EVENT)
  437. c = 'X';
  438. if (a.eventType == CENTER_EVENT)
  439. c = 'Q';
  440. if (debug_level < 1)
  441. G_warning("ev=[(%3d, %3d), e=%8.1f a=%4.2f t=%c] ",
  442. a.row, a.col, a.elev[1], a.angle, c);
  443. else
  444. G_debug(debug_level, "ev=[(%3d, %3d), e=%8.1f a=%4.2f t=%c] ",
  445. a.row, a.col, a.elev[1], a.angle, c);
  446. return;
  447. }
  448. /* ------------------------------------------------------------ */
  449. /*computes the distance from the event to the viewpoint. Note: all 3
  450. //events associate to a cell are considered at the same distance, from
  451. //the center of the cell to the viewpoint */
  452. double
  453. get_square_distance_from_viewpoint(const AEvent & a, const Viewpoint & vp)
  454. {
  455. double eventy, eventx, dist;
  456. calculate_event_position(a, vp.row, vp.col, &eventy, &eventx);
  457. if (G_projection() == PROJECTION_LL) {
  458. struct Cell_head window;
  459. Rast_get_window(&window);
  460. dist = G_distance(Rast_col_to_easting(vp.col + 0.5, &window),
  461. Rast_row_to_northing(vp.row + 0.5, &window),
  462. Rast_col_to_easting(eventx + 0.5, &window),
  463. Rast_row_to_northing(eventy + 0.5, &window));
  464. dist = dist * dist;
  465. }
  466. else {
  467. /*don't take sqrt, it is expensive; suffices for comparison */
  468. dist = (eventx - vp.col) * (eventx - vp.col) +
  469. (eventy - vp.row) * (eventy - vp.row);
  470. }
  471. return dist;
  472. }
  473. /* ------------------------------------------------------------ */
  474. /* a duplicate of get_square_distance_from_viewpoint() needed for debug */
  475. double
  476. get_square_distance_from_viewpoint_with_print(const AEvent & a,
  477. const Viewpoint & vp)
  478. {
  479. double eventy, eventx, dist;
  480. calculate_event_position(a, vp.row, vp.col, &eventy, &eventx);
  481. if (G_projection() == PROJECTION_LL) {
  482. struct Cell_head window;
  483. Rast_get_window(&window);
  484. dist = G_distance(Rast_col_to_easting(vp.col + 0.5, &window),
  485. Rast_row_to_northing(vp.row + 0.5, &window),
  486. Rast_col_to_easting(eventx + 0.5, &window),
  487. Rast_row_to_northing(eventy + 0.5, &window));
  488. dist = dist * dist;
  489. }
  490. else {
  491. /*don't take sqrt, it is expensive; suffices for comparison */
  492. dist = (eventx - vp.col) * (eventx - vp.col) +
  493. (eventy - vp.row) * (eventy - vp.row);
  494. }
  495. print_event(a, 2);
  496. G_debug(2, " pos= (%.3f. %.3f) sqdist=%.3f", eventx, eventy, dist);
  497. return dist;
  498. }
  499. /* ------------------------------------------------------------ */
  500. /*determines if the point at row,col is outside the maximum distance
  501. limit. Return 1 if the point is outside limit, 0 if point is inside
  502. limit. */
  503. int is_point_outside_max_dist(Viewpoint vp, GridHeader hd,
  504. dimensionType row, dimensionType col,
  505. float maxDist)
  506. {
  507. /* it is not too smart to compare floats */
  508. if ((int)maxDist == INFINITY_DISTANCE)
  509. return 0;
  510. if (maxDist < G_distance(Rast_col_to_easting(vp.col + 0.5, &hd.window),
  511. Rast_row_to_northing(vp.row + 0.5, &hd.window),
  512. Rast_col_to_easting(col + 0.5, &hd.window),
  513. Rast_row_to_northing(row + 0.5, &hd.window))) {
  514. return 1;
  515. }
  516. return 0;
  517. }
  518. /* ------------------------------------------------------------
  519. //note: this is expensive because distance is not stored in the event
  520. //and must be computed on the fly */
  521. int DistanceCompare::compare(const AEvent & a, const AEvent & b)
  522. {
  523. /*calculate distance from viewpoint
  524. //don't take sqrt, it is expensive; suffices for comparison */
  525. double da, db;
  526. /*da = get_square_distance_from_viewpoint(a, globalVP);
  527. //db = get_square_distance_from_viewpoint(b, globalVP); */
  528. /*in the event these are not inlined */
  529. double eventy, eventx;
  530. calculate_event_position(a, globalVP.row, globalVP.col, &eventy, &eventx);
  531. if (G_projection() == PROJECTION_LL) {
  532. struct Cell_head window;
  533. Rast_get_window(&window);
  534. da = G_distance(Rast_col_to_easting(globalVP.col + 0.5, &window),
  535. Rast_row_to_northing(globalVP.row + 0.5, &window),
  536. Rast_col_to_easting(eventx + 0.5, &window),
  537. Rast_row_to_northing(eventy + 0.5, &window));
  538. da = da * da;
  539. }
  540. else {
  541. /*don't take sqrt, it is expensive; suffices for comparison */
  542. da = (eventx - globalVP.col) * (eventx - globalVP.col) +
  543. (eventy - globalVP.row) * (eventy - globalVP.row);
  544. }
  545. calculate_event_position(b, globalVP.row, globalVP.col, &eventy, &eventx);
  546. if (G_projection() == PROJECTION_LL) {
  547. struct Cell_head window;
  548. Rast_get_window(&window);
  549. db = G_distance(Rast_col_to_easting(globalVP.col + 0.5, &window),
  550. Rast_row_to_northing(globalVP.row + 0.5, &window),
  551. Rast_col_to_easting(eventx + 0.5, &window),
  552. Rast_row_to_northing(eventy + 0.5, &window));
  553. db = db * db;
  554. }
  555. else {
  556. /*don't take sqrt, it is expensive; suffices for comparison */
  557. db = (eventx - globalVP.col) * (eventx - globalVP.col) +
  558. (eventy - globalVP.row) * (eventy - globalVP.row);
  559. }
  560. if (da > db) {
  561. return 1;
  562. }
  563. else if (da < db) {
  564. return -1;
  565. }
  566. else {
  567. return 0;
  568. }
  569. return 0;
  570. }
  571. /* ------------------------------------------------------------ */
  572. int RadialCompare::compare(const AEvent & a, const AEvent & b)
  573. {
  574. if (a.row == b.row && a.col == b.col && a.eventType == b.eventType)
  575. return 0;
  576. assert(a.angle >= 0 && b.angle >= 0);
  577. if (a.angle > b.angle) {
  578. return 1;
  579. }
  580. else if (a.angle < b.angle) {
  581. return -1;
  582. }
  583. else {
  584. /*a.angle == b.angle */
  585. if (a.eventType == EXITING_EVENT)
  586. return -1;
  587. if (b.eventType == EXITING_EVENT)
  588. return 1;
  589. if (a.eventType == ENTERING_EVENT)
  590. return 1;
  591. if (b.eventType == ENTERING_EVENT)
  592. return -1;
  593. return 0;
  594. }
  595. }
  596. /* ------------------------------------------------------------ */
  597. /* a copy of the function above is needed by qsort, when the
  598. computation runs in memory */
  599. int radial_compare_events(const void *x, const void *y)
  600. {
  601. AEvent *a, *b;
  602. a = (AEvent *) x;
  603. b = (AEvent *) y;
  604. if (a->row == b->row && a->col == b->col && a->eventType == b->eventType)
  605. return 0;
  606. assert(a->angle >= 0 && b->angle >= 0);
  607. if (a->angle > b->angle) {
  608. return 1;
  609. }
  610. else if (a->angle < b->angle) {
  611. return -1;
  612. }
  613. else {
  614. /*a->angle == b->angle */
  615. if (a->eventType == EXITING_EVENT)
  616. return -1;
  617. else if (a->eventType == ENTERING_EVENT)
  618. return 1;
  619. return 0;
  620. }
  621. }
  622. /* ------------------------------------------------------------ */
  623. /*sort the event list in radial order */
  624. void sort_event_list(AMI_STREAM < AEvent > **eventList)
  625. {
  626. /*printf("sorting events.."); fflush(stdout); */
  627. assert(*eventList);
  628. AMI_STREAM < AEvent > *sortedStr;
  629. RadialCompare cmpObj;
  630. AMI_err ae;
  631. ae = AMI_sort(*eventList, &sortedStr, &cmpObj, 1);
  632. assert(ae == AMI_ERROR_NO_ERROR);
  633. *eventList = sortedStr;
  634. /*printf("..done.\n"); fflush(stdout); */
  635. return;
  636. }
  637. /* ------------------------------------------------------------ */
  638. /*sort the event list in distance order */
  639. void
  640. sort_event_list_by_distance(AMI_STREAM < AEvent > **eventList, Viewpoint vp)
  641. {
  642. /*printf("sorting events by distance from viewpoint.."); fflush(stdout); */
  643. assert(*eventList);
  644. AMI_STREAM < AEvent > *sortedStr;
  645. DistanceCompare cmpObj;
  646. globalVP.row = vp.row;
  647. globalVP.col = vp.col;
  648. /*printViewpoint(globalVP); */
  649. AMI_err ae;
  650. ae = AMI_sort(*eventList, &sortedStr, &cmpObj, 1);
  651. assert(ae == AMI_ERROR_NO_ERROR);
  652. *eventList = sortedStr;
  653. /*printf("..sorting done.\n"); fflush(stdout); */
  654. return;
  655. }