pole_in_poly.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include <grass/gis.h>
  2. /**********************************************************
  3. * G_pole_in_polygon(x, y, n)
  4. * double *x, *y, n;
  5. *
  6. * For lat-lon coordinates, this routine determines if the polygon
  7. * defined by the n verticies x,y contain one of the poles
  8. *
  9. * returns
  10. * -1 if it contains the south pole,
  11. * 1 if it contains the north pole,
  12. * 0 no pole
  13. *
  14. * Note: don't use this routine if the projection isn't PROJECTION_LL
  15. * no check is made by this routine for valid projection
  16. ***********************************************************/
  17. static void mystats(double, double, double, double, double *, double *);
  18. /*!
  19. * \brief pole in polygon
  20. *
  21. * For latitude-longitude coordinates, this routine determines if the polygon
  22. * defined by the <b>n</b> coordinate vertices <b>x,y</b> contains one of the
  23. * poles.
  24. * Returns -1 if it contains the south pole; 1 if it contains the north pole; 0
  25. * if it contains neither pole.
  26. * <b>Note.</b> Use this routine only if the projection is PROJECTION_LL.
  27. *
  28. * \param x
  29. * \param y
  30. * \param n
  31. * \return int
  32. */
  33. int G_pole_in_polygon(const double *x, const double *y, int n)
  34. {
  35. int i;
  36. double len, area, total_len, total_area;
  37. if (n <= 1)
  38. return 0;
  39. mystats(x[n - 1], y[n - 1], x[0], y[0], &total_len, &total_area);
  40. for (i = 1; i < n; i++) {
  41. mystats(x[i - 1], y[i - 1], x[i], y[i], &len, &area);
  42. total_len += len;
  43. total_area += area;
  44. }
  45. /* if polygon contains a pole then the x-coordinate length of
  46. * the perimeter should compute to 0, otherwise it should be about 360
  47. * (or -360, depending on the direction of perimeter traversal)
  48. *
  49. * instead of checking for exactly 0, check from -1 to 1 to avoid
  50. * roundoff error.
  51. */
  52. if (total_len < 1.0 && total_len > -1.0)
  53. return 0;
  54. return total_area >= 0.0 ? 1 : -1;
  55. }
  56. static void mystats(double x0, double y0, double x1, double y1, double *len,
  57. double *area)
  58. {
  59. if (x1 > x0)
  60. while (x1 - x0 > 180)
  61. x0 += 360;
  62. else if (x0 > x1)
  63. while (x0 - x1 > 180)
  64. x0 -= 360;
  65. *len = x0 - x1;
  66. if (x0 > x1)
  67. *area = (x0 - x1) * (y0 + y1) / 2.0;
  68. else
  69. *area = (x1 - x0) * (y1 + y0) / 2.0;
  70. }