find_normal.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /****************************************************************/
  2. /* find_normal() - Function to find the set of normal equations */
  3. /* that allow a quadratic trend surface to be */
  4. /* fitted through N points using least squares */
  5. /* V.1.0, Jo Wood, 27th November, 1994. */
  6. /****************************************************************/
  7. #include "param.h"
  8. void find_normal(double **normal, /* Matrix of cross-products. */
  9. double *w)
  10. { /* Weights matrix. */
  11. int edge = EDGE; /* Store (wsize-1)/2 to save */
  12. /* on computation */
  13. double x, y, /* Local coordinates of window. */
  14. x1 = 0, y1 = 0, /* coefficients of X-products. */
  15. x2 = 0, y2 = 0,
  16. x3 = 0, y3 = 0,
  17. x4 = 0, y4 = 0,
  18. xy2 = 0, x2y = 0, xy3 = 0, x3y = 0, x2y2 = 0, xy = 0, N = 0;
  19. int row, col; /* Pass through local window. */
  20. /* Initialise sums-of-squares and cross products matrix */
  21. for (row = 0; row < 6; row++)
  22. for (col = 0; col < 6; col++)
  23. normal[row][col] = 0.0;
  24. /* Calculate matrix of sums of squares and cross products */
  25. for (row = 0; row < wsize; row++)
  26. for (col = 0; col < wsize; col++) {
  27. x = resoln * (col - edge);
  28. y = resoln * (row - edge);
  29. x4 += x * x * x * x * *(w + row * wsize + col);
  30. x2y2 += x * x * y * y * *(w + row * wsize + col);
  31. x3y += x * x * x * y * *(w + row * wsize + col);
  32. x3 += x * x * x * *(w + row * wsize + col);
  33. x2y += x * x * y * *(w + row * wsize + col);
  34. x2 += x * x * *(w + row * wsize + col);
  35. y4 += y * y * y * y * *(w + row * wsize + col);
  36. xy3 += x * y * y * y * *(w + row * wsize + col);
  37. xy2 += x * y * y * *(w + row * wsize + col);
  38. y3 += y * y * y * *(w + row * wsize + col);
  39. y2 += y * y * *(w + row * wsize + col);
  40. xy += x * y * *(w + row * wsize + col);
  41. x1 += x * *(w + row * wsize + col);
  42. y1 += y * *(w + row * wsize + col);
  43. N += *(w + row * wsize + col);
  44. }
  45. /* --- Store cross-product matrix elements. --- */
  46. normal[0][0] = x4;
  47. normal[0][1] = normal[1][0] = x2y2;
  48. normal[0][2] = normal[2][0] = x3y;
  49. normal[0][3] = normal[3][0] = x3;
  50. normal[0][4] = normal[4][0] = x2y;
  51. normal[0][5] = normal[5][0] = x2;
  52. normal[1][1] = y4;
  53. normal[1][2] = normal[2][1] = xy3;
  54. normal[1][3] = normal[3][1] = xy2;
  55. normal[1][4] = normal[4][1] = y3;
  56. normal[1][5] = normal[5][1] = y2;
  57. normal[2][2] = x2y2;
  58. normal[2][3] = normal[3][2] = x2y;
  59. normal[2][4] = normal[4][2] = xy2;
  60. normal[2][5] = normal[5][2] = xy;
  61. normal[3][3] = x2;
  62. normal[3][4] = normal[4][3] = xy;
  63. normal[3][5] = normal[5][3] = x1;
  64. normal[4][4] = y2;
  65. normal[4][5] = normal[5][4] = y1;
  66. normal[5][5] = N;
  67. }
  68. /****************************************************************/
  69. /* find_obs() - Function to find the observed vector as part of */
  70. /* the set of normal equations for least squares. */
  71. /* V.1.0, Jo Wood, 11th December, 1994. */
  72. /****************************************************************/
  73. void find_obs(DCELL * z, /* Local window of elevs. */
  74. double *obs, /* Observed column vector. */
  75. double *w)
  76. { /* Weighting matrix. */
  77. int row, col, /* Counts through local window. */
  78. edge = EDGE, /* EDGE = (wsize-1)/2. */
  79. offset; /* Array offset for weights & z */
  80. double x, y; /* Local window coordinates. */
  81. for (row = 0; row < 6; row++) /* Initialise column vector. */
  82. obs[row] = 0.0;
  83. for (row = 0; row < wsize; row++)
  84. for (col = 0; col < wsize; col++) {
  85. x = resoln * (col - edge);
  86. y = resoln * (row - edge);
  87. offset = row * wsize + col;
  88. obs[0] += *(w + offset) * *(z + offset) * x * x;
  89. obs[1] += *(w + offset) * *(z + offset) * y * y;
  90. obs[2] += *(w + offset) * *(z + offset) * x * y;
  91. obs[3] += *(w + offset) * *(z + offset) * x;
  92. obs[4] += *(w + offset) * *(z + offset) * y;
  93. if (!constrained) /* If constrained, should remain 0.0 */
  94. obs[5] += *(w + offset) * *(z + offset);
  95. }
  96. }
  97. /****************************************************************/
  98. /* find_weight() Function to find the weightings matrix for the */
  99. /* observed cell values. */
  100. /* Uses an inverse distance function that can be */
  101. /* calibrated with an exponent (0= no decay, */
  102. /* 1=linear decay, 2=squared distance decay etc.) */
  103. /* V.1.1, Jo Wood, 11th May, 1995. */
  104. /****************************************************************/
  105. void find_weight(double *weight_ptr)
  106. {
  107. int edge = EDGE; /* EDGE = (wsize-1)/2. */
  108. int row, col; /* Counts through the rows and */
  109. /* columns of weights matrix. */
  110. double dist; /* Distance to centre of kernel. */
  111. /* --- Find inverse distance of all cells to centre. --- */
  112. for (row = 0; row < wsize; row++)
  113. for (col = 0; col < wsize; col++) {
  114. dist = 1.0 /
  115. pow(sqrt
  116. ((edge - col) * (edge - col) +
  117. (edge - row) * (edge - row)) + 1.0, exponent);
  118. *(weight_ptr + row * wsize + col) = dist;
  119. }
  120. }