Graphics_altitude.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* Graphics_altitude.cpp
  2. *
  3. * Copyright (C) 1992-2011,2015,2016,2017 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "Graphics.h"
  19. static int empty (double **data, int **right, int **below, integer row1, integer col1, double height, int row, int col, int ori) {
  20. if (ori == 3) { row ++; ori = 1; } else if (ori == 2) { col ++; ori = 4; }
  21. if (ori == 1)
  22. return (data [row] [col] < height) != (data [row] [col + 1] < height) &&
  23. ! right [row - row1] [col - col1];
  24. else /* ori == 4 */
  25. return (data [row] [col] < height) != (data [row + 1] [col] < height) &&
  26. ! below [row - row1] [col - col1];
  27. }
  28. #define MAXALTSIDE 50
  29. #define MAXALTPATH (2 * MAXALTSIDE * (MAXALTSIDE - 1) + 2)
  30. static integer numberOfPoints;
  31. static integer row1, row2, col1, col2;
  32. static int **right, **below;
  33. static double *x, *y;
  34. static int closed;
  35. static double dx, dy, xoff, yoff;
  36. static int note (double **z, double height, int row, int col, int ori, int pleaseForget) {
  37. ++ numberOfPoints;
  38. Melder_assert (numberOfPoints <= MAXALTPATH);
  39. if (ori == 3) { row ++; ori = 1; } else if (ori == 2) { col ++; ori = 4; }
  40. if (ori == 1) {
  41. if (pleaseForget) right [row - row1] [col - col1] = 1;
  42. x [numberOfPoints] = xoff +
  43. (col + (height - z [row] [col]) / (z [row] [col + 1] - z [row] [col])) * dx;
  44. y [numberOfPoints] = yoff + row * dy;
  45. } else { /* ori == 4 */
  46. if (pleaseForget) below [row - row1] [col - col1] = 1;
  47. x [numberOfPoints] = xoff + col * dx;
  48. y [numberOfPoints] = yoff +
  49. (row + (height - z [row] [col]) / (z [row + 1] [col] - z [row] [col])) * dy;
  50. }
  51. return 1;
  52. }
  53. static void makeContour (Graphics graphics, double **z, double height, int row0, int col0, int ori0) {
  54. int row, col, ori, clockwise = 0, edge = 0;
  55. numberOfPoints = 0;
  56. row = row0; col = col0; ori = ori0;
  57. note (z, height, row0, col0, ori0, 0);
  58. do {
  59. clockwise = ! (ori & 1);
  60. do { /* Preference for contours perpendicular to x == y. */
  61. ori = (clockwise ? ori : ori + 2) % 4 + 1;
  62. } while (! empty (z, right, below, row1, col1, height, row, col, ori));
  63. if (! closed) switch (ori) {
  64. case 1: edge = row == row1; break;
  65. case 2: edge = col == col2 - 1; break;
  66. case 3: edge = row == row2 - 1; break;
  67. case 4: edge = col == col1; break;
  68. }
  69. if (! edge) {
  70. switch (ori) {
  71. case 1: row --; break;
  72. case 2: col ++; break;
  73. case 3: row ++; break;
  74. case 4: col --; break;
  75. }
  76. ori = (ori + 1) % 4 + 1;
  77. }
  78. if (! note (z, height, row, col, ori, 1)) return;
  79. }
  80. while (edge == 0 && (row != row0 || col != col0 || ori != ori0));
  81. if (closed) note (z, height, row0, col0, ori0, 1); /* Close the contour. */
  82. Graphics_polyline (graphics, numberOfPoints, & x [1], & y [1]);
  83. }
  84. static void smallAlt (Graphics graphics, double **z, double height) {
  85. int row, col;
  86. for (row = 0; row < MAXALTSIDE; row ++) for (col = 0; col < MAXALTSIDE; col ++)
  87. right [row] [col] = below [row] [col] = 0;
  88. /* Find all the edge contours of this border value. */
  89. closed = 0;
  90. for (col = col1; col < col2; col ++)
  91. if (empty (z, right, below, row1, col1, height, row1, col, 1))
  92. makeContour (graphics, z, height, row1, col, 1);
  93. for (row = row1; row < row2; row ++)
  94. if (empty (z, right, below, row1, col1, height, row, col2 - 1, 2))
  95. makeContour (graphics, z, height, row, col2 - 1, 2);
  96. for (col = col2 - 1; col >= col1; col --)
  97. if (empty (z, right, below, row1, col1, height, row2 - 1, col, 3))
  98. makeContour (graphics, z, height, row2 - 1, col, 3);
  99. for (row = row2 - 1; row >= row1; row --)
  100. if (empty (z, right, below, row1, col1, height, row, col1, 4))
  101. makeContour (graphics, z, height, row, col1, 4);
  102. /* Find all the closed contours of this border value. */
  103. closed = 1;
  104. for (row = row1 + 1; row < row2; row ++)
  105. for (col = col1; col < col2; col ++)
  106. if (empty (z, right, below, row1, col1, height, row, col, 1))
  107. makeContour (graphics, z, height, row, col, 1);
  108. for (col = col1 + 1; col < col2; col ++)
  109. for (row = row1; row < row2; row ++)
  110. if (empty (z, right, below, row1, col1, height, row, col, 4))
  111. makeContour (graphics, z, height, row, col, 4);
  112. }
  113. void Graphics_contour (Graphics me, double **z,
  114. integer ix1, integer ix2, double x1WC, double x2WC,
  115. integer iy1, integer iy2, double y1WC, double y2WC,
  116. double height)
  117. {
  118. if (ix2 <= ix1 || iy2 <= iy1) return;
  119. dx = (x2WC - x1WC) / (ix2 - ix1);
  120. dy = (y2WC - y1WC) / (iy2 - iy1);
  121. xoff = x1WC - ix1 * dx;
  122. yoff = y1WC - iy1 * dy;
  123. if (! right) { // static!
  124. right = NUMmatrix <int> (0, MAXALTSIDE - 1, 0, MAXALTSIDE - 1);
  125. below = NUMmatrix <int> (0, MAXALTSIDE - 1, 0, MAXALTSIDE - 1);
  126. x = NUMvector <double> (1, MAXALTPATH);
  127. y = NUMvector <double> (1, MAXALTPATH);
  128. }
  129. for (row1 = iy1; row1 < iy2; row1 += MAXALTSIDE - 1) {
  130. for (col1 = ix1; col1 < ix2; col1 += MAXALTSIDE - 1) {
  131. if ((row2 = row1 + (MAXALTSIDE - 1)) > iy2) row2 = iy2;
  132. if ((col2 = col1 + (MAXALTSIDE - 1)) > ix2) col2 = ix2;
  133. smallAlt (me, z, height);
  134. }
  135. }
  136. }
  137. void Graphics_altitude (Graphics me, double **z,
  138. integer ix1, integer ix2, double x1WC, double x2WC,
  139. integer iy1, integer iy2, double y1WC, double y2WC,
  140. int numberOfBorders, double borders [])
  141. {
  142. int iborder;
  143. if (ix2 <= ix1 || iy2 <= iy1) return;
  144. dx = (x2WC - x1WC) / (ix2 - ix1);
  145. dy = (y2WC - y1WC) / (iy2 - iy1);
  146. xoff = x1WC - ix1 * dx;
  147. yoff = y1WC - iy1 * dy;
  148. if (! right) { // static!
  149. right = NUMmatrix <int> (0, MAXALTSIDE - 1, 0, MAXALTSIDE - 1);
  150. below = NUMmatrix <int> (0, MAXALTSIDE - 1, 0, MAXALTSIDE - 1);
  151. x = NUMvector <double> (1, MAXALTPATH);
  152. y = NUMvector <double> (1, MAXALTPATH);
  153. }
  154. for (row1 = iy1; row1 < iy2; row1 += MAXALTSIDE - 1) {
  155. for (col1 = ix1; col1 < ix2; col1 += MAXALTSIDE - 1) {
  156. if ((row2 = row1 + (MAXALTSIDE - 1)) > iy2) row2 = iy2;
  157. if ((col2 = col1 + (MAXALTSIDE - 1)) > ix2) col2 = ix2;
  158. for (iborder = 1; iborder <= numberOfBorders; iborder ++) {
  159. smallAlt (me, z, borders [iborder]);
  160. }
  161. }
  162. }
  163. }
  164. /* End of file Graphics_altitude.cpp */