hull.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include <grass/glocale.h>
  2. #include "hull.h"
  3. int rightTurn(struct Point *P, int i, int j, int k)
  4. {
  5. double a, b, c, d;
  6. a = P[i].x - P[j].x;
  7. b = P[i].y - P[j].y;
  8. c = P[k].x - P[j].x;
  9. d = P[k].y - P[j].y;
  10. return a * d - b * c < 0;
  11. }
  12. int cmpPoints(const void *v1, const void *v2)
  13. {
  14. struct Point *p1, *p2;
  15. p1 = (struct Point *)v1;
  16. p2 = (struct Point *)v2;
  17. if (p1->x > p2->x)
  18. return 1;
  19. else if (p1->x < p2->x)
  20. return -1;
  21. else
  22. return 0;
  23. }
  24. int convexHull(struct Point *P, int numPoints, int **hull)
  25. {
  26. int pointIdx, upPoints, loPoints;
  27. int *upHull, *loHull;
  28. /* sort points in ascending x order */
  29. qsort(P, numPoints, sizeof(struct Point), cmpPoints);
  30. *hull = (int *)G_malloc(numPoints * 2 * sizeof(int));
  31. /* compute upper hull */
  32. upHull = *hull;
  33. upHull[0] = 0;
  34. upHull[1] = 1;
  35. upPoints = 1;
  36. for (pointIdx = 2; pointIdx < numPoints; pointIdx++) {
  37. upPoints++;
  38. upHull[upPoints] = pointIdx;
  39. while (upPoints > 1 &&
  40. !rightTurn(P, upHull[upPoints], upHull[upPoints - 1],
  41. upHull[upPoints - 2])
  42. ) {
  43. upHull[upPoints - 1] = upHull[upPoints];
  44. upPoints--;
  45. }
  46. }
  47. /* compute lower hull, overwrite last point of upper hull */
  48. loHull = &(upHull[upPoints]);
  49. loHull[0] = numPoints - 1;
  50. loHull[1] = numPoints - 2;
  51. loPoints = 1;
  52. for (pointIdx = numPoints - 3; pointIdx >= 0; pointIdx--) {
  53. loPoints++;
  54. loHull[loPoints] = pointIdx;
  55. while (loPoints > 1 &&
  56. !rightTurn(P, loHull[loPoints], loHull[loPoints - 1],
  57. loHull[loPoints - 2])
  58. ) {
  59. loHull[loPoints - 1] = loHull[loPoints];
  60. loPoints--;
  61. }
  62. }
  63. G_debug(3, "numPoints:%d loPoints:%d upPoints:%d",
  64. numPoints, loPoints, upPoints);
  65. /* reclaim uneeded memory */
  66. *hull = (int *)G_realloc(*hull, (loPoints + upPoints) * sizeof(int));
  67. return loPoints + upPoints;
  68. }
  69. void convexHull3d(struct Point *P, const int numPoints, struct Map_info *Map)
  70. {
  71. int error;
  72. int i;
  73. double *px;
  74. double *py;
  75. double *pz;
  76. px = G_malloc(sizeof(double) * numPoints);
  77. py = G_malloc(sizeof(double) * numPoints);
  78. pz = G_malloc(sizeof(double) * numPoints);
  79. for (i = 0; i < numPoints; i++) {
  80. px[i] = (P)[i].x;
  81. py[i] = (P)[i].y;
  82. pz[i] = (P)[i].z;
  83. }
  84. /* make 3D hull */
  85. error = make3DHull(px, py, pz, numPoints, Map);
  86. if (error < 0) {
  87. G_fatal_error(_("Simple planar hulls not implemented yet"));
  88. }
  89. G_free(px);
  90. G_free(py);
  91. G_free(pz);
  92. }