geom.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include "local_proto.h"
  2. /* static double dirs[8] = { 0.7854, 0., 5.4978, 4.7124, 3.9270, 3.1416, 2.3562, 1.5708 };*/ /* radians */
  3. static double sins[8] = { 0.7071067812, 0, -0.7071067812, -1, -0.7071067812, 0, 0.7071067812, 1 }; /* sinus */
  4. static double coss[8] = { 0.7071067812, 1, 0.7071067812, 0, -0.7071067812, -1, -0.7071067812, 0 }; /* cosinus */
  5. /* DIRS in DEGREES from NORTH: 45,0,315,270,225,180,135,90 */
  6. unsigned int ternary_rotate(unsigned int value)
  7. {
  8. /* this function returns rotated and mirrored
  9. * ternary code from any number
  10. * function is used to create lookup table with original
  11. * terrain patterns (6561) and its rotated and mirrored counterparts (498)*/
  12. unsigned char pattern[8];
  13. unsigned char rev_pattern[8];
  14. unsigned char tmp_pattern[8];
  15. unsigned char tmp_rev_pattern[8];
  16. unsigned int code = 10000, tmp_code, rev_code = 10000, tmp_rev_code;
  17. int power = 1;
  18. int i, j, k;
  19. for (i = 0; i < 8; i++) {
  20. pattern[i] = value % 3;
  21. rev_pattern[7 - i] = value % 3;
  22. value /= 3;
  23. }
  24. for (j = 0; j < 8; j++) {
  25. power = 1;
  26. tmp_code = 0;
  27. tmp_rev_code = 0;
  28. for (i = 0; i < 8; i++) {
  29. k = (i - j) < 0 ? j - 8 : j;
  30. tmp_pattern[i] = pattern[i - k];
  31. tmp_rev_pattern[i] = rev_pattern[i - k];
  32. tmp_code += tmp_pattern[i] * power;
  33. tmp_rev_code += tmp_rev_pattern[i] * power;
  34. power *= 3;
  35. }
  36. code = tmp_code < code ? tmp_code : code;
  37. rev_code = tmp_rev_code < rev_code ? tmp_rev_code : rev_code;
  38. }
  39. return code < rev_code ? code : rev_code;
  40. }
  41. int determine_form(int num_minus, int num_plus)
  42. {
  43. /* determine form according number of positives and negatives
  44. * simple approach to determine form pattern */
  45. const FORMS forms[9][9] = {
  46. /* minus ------------- plus ---------------- */
  47. /* 0 1 2 3 4 5 6 7 8 */
  48. /* 0 */ {FL, FL, FL, FS, FS, VL, VL, VL, PT},
  49. /* 1 */ {FL, FL, FS, FS, FS, VL, VL, VL, __},
  50. /* 2 */ {FL, SH, SL, SL, CN, CN, VL, __, __},
  51. /* 3 */ {SH, SH, SL, SL, SL, CN, __, __, __},
  52. /* 4 */ {SH, SH, CV, SL, SL, __, __, __, __},
  53. /* 5 */ {RI, RI, CV, CV, __, __, __, __, __},
  54. /* 6 */ {RI, RI, RI, __, __, __, __, __, __},
  55. /* 7 */ {RI, RI, __, __, __, __, __, __, __},
  56. /* 8 */ {PK, __, __, __, __, __, __, __, __},
  57. };
  58. /* legend:
  59. FL, flat
  60. PK, peak, summit
  61. RI, ridge
  62. SH, shoulder
  63. CV, convex
  64. SL, slope
  65. CN, concave
  66. FS, footslope
  67. VL, valley
  68. PT, pit, depression
  69. __ error, impossible
  70. */
  71. return forms[num_minus][num_plus];
  72. }
  73. int determine_binary(int *pattern, int sign)
  74. {
  75. /* extract binary pattern for zenith (+) or nadir (-) from unrotated ternary pattern */
  76. int n, i;
  77. unsigned char binary = 0, result = 255, test = 0;
  78. for (i = 0, n = 1; i < 8; i++, n *= 2)
  79. binary += (pattern[i] == sign) ? n : 0;
  80. /* rotate */
  81. for (i = 0; i < 8; ++i) {
  82. if ((i &= 7) == 0)
  83. test = binary;
  84. else
  85. test = (binary << i) | (binary >> (8 - i));
  86. result = (result < test) ? result : test;
  87. }
  88. return (int)result;
  89. }
  90. int rotate(unsigned char binary)
  91. {
  92. int i;
  93. unsigned char result = 255, test = 0;
  94. /* rotate */
  95. for (i = 0; i < 8; ++i) {
  96. if ((i &= 7) == 0)
  97. test = binary;
  98. else
  99. test = (binary << i) | (binary >> (8 - i));
  100. result = (result < test) ? result : test;
  101. }
  102. return (int)result;
  103. }
  104. int determine_ternary(int *pattern)
  105. {
  106. /* extract rotated and mirrored ternary pattern form unrotated ternary pattern */
  107. unsigned ternary_code = 0;
  108. int power, i;
  109. for (i = 0, power = 1; i < 8; ++i, power *= 3)
  110. ternary_code += (pattern[i] + 1) * power;
  111. return global_ternary_codes[ternary_code];
  112. }
  113. float intensity(float *elevation, int pattern_size)
  114. {
  115. /* calculate relative elevation of the central cell against its visibility surround */
  116. float sum_elevation = 0.;
  117. int i;
  118. for (i = 0; i < 8; i++)
  119. sum_elevation -= elevation[i];
  120. return sum_elevation / (float)pattern_size;
  121. }
  122. float exposition(float *elevation)
  123. {
  124. /* calculate relative elevation of the central cell against its visibility */
  125. float max = 0.;
  126. int i;
  127. for (i = 0; i < 8; i++)
  128. max = fabs(elevation[i]) > fabs(max) ? elevation[i] : max;
  129. return -max;
  130. }
  131. float range(float *elevation)
  132. {
  133. /* calculate relative difference in visible range of central cell */
  134. float max = -90000000000., min = 9000000000000.; /* should be enough */
  135. int i;
  136. for (i = 0; i < 8; i++) {
  137. max = elevation[i] > max ? elevation[i] : max;
  138. min = elevation[i] < min ? elevation[i] : min;
  139. }
  140. return max - min;
  141. }
  142. float variance(float *elevation, int pattern_size)
  143. {
  144. /* calculate relative variation of the visible neighbourhood of the cell */
  145. float sum_elevation = 0;
  146. float variance = 0;
  147. int i;
  148. for (i = 0; i < 8; i++)
  149. sum_elevation += elevation[i];
  150. sum_elevation /= (float)pattern_size;
  151. for (i = 0; i < 8; i++)
  152. variance +=
  153. ((sum_elevation - elevation[i]) * (sum_elevation - elevation[i]));
  154. return variance / (float)pattern_size;
  155. }
  156. int radial2cartesian(PATTERN * pattern)
  157. {
  158. /* this function converts radial coordinates of geomorphon
  159. * (assuming center as 0,0) to cartezian coordinates
  160. * with the beginning in the central cell of geomorphon */
  161. int i;
  162. for (i = 0; i < 8; ++i)
  163. if (pattern->distance > 0) {
  164. pattern->x[i] = pattern->distance[i] * sins[i];
  165. pattern->y[i] = pattern->distance[i] * coss[i];
  166. }
  167. else {
  168. pattern->x[i] = 0;
  169. pattern->y[i] = 0;
  170. }
  171. return 0;
  172. }
  173. float extends(PATTERN * pattern, int pattern_size)
  174. {
  175. int i, j;
  176. float area = 0;
  177. for (i = 0, j = 1; i < 8; ++i, ++j) {
  178. j = j < 8 ? j : 0;
  179. area +=
  180. (pattern->x[i] * pattern->y[j] - pattern->x[j] * pattern->y[i]);
  181. }
  182. return fabs(area) / 2.;
  183. }
  184. int shape(PATTERN * pattern, int pattern_size, float *azimuth,
  185. float *elongation, float *width)
  186. {
  187. /* calculates azimuth, elongation and width of geomorphon's polygon */
  188. int i;
  189. double avg_x = 0, avg_y = 0;
  190. double avg_x_y = 0;
  191. double avg_x_square;
  192. double rx, ry;
  193. double sine, cosine;
  194. double result;
  195. double rxmin, rxmax, rymin, rymax;
  196. for (i = 0; i < 8; ++i) {
  197. avg_y += pattern->y[i];
  198. avg_x += pattern->x[i];
  199. avg_x_square += pattern->x[i] * pattern->x[i];
  200. avg_x_y += pattern->x[i] * pattern->y[i];
  201. }
  202. avg_y /= (float)pattern_size;
  203. avg_x /= (float)pattern_size;
  204. avg_x_y /= (float)pattern_size;
  205. avg_x_square /= (float)pattern_size;
  206. result = (avg_x_y - avg_x * avg_y) / (avg_x_square - avg_x * avg_x);
  207. result = atan(result);
  208. *azimuth = (float)RAD2DEGREE(PI2 - result);
  209. /* rotation */
  210. sine = sin(result);
  211. cosine = cos(result);
  212. for (i = 0; i < 8; ++i) {
  213. rx = pattern->x[i] * cosine - pattern->y[i] * sine;
  214. ry = pattern->x[i] * sine + pattern->y[i] * cosine;
  215. rxmin = rx < rxmin ? rx : rxmin;
  216. rxmax = rx > rxmax ? rx : rxmax;
  217. rymin = ry < rymin ? ry : rymin;
  218. rymax = ry > rymax ? ry : rymax;
  219. }
  220. rx = (rxmax - rxmin);
  221. ry = (rymax - rymin);
  222. *elongation = rx > ry ? (float)rx / ry : (float)ry / rx;
  223. *width = rx > ry ? ry : rx;
  224. return 0;
  225. }