spec_syn.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Updated by Michel Wurtz 12/99 */
  2. /*****************************************************************************/
  3. /*** ***/
  4. /*** spec_syn() ***/
  5. /*** Creates a fractal surface using spectral synthesis. ***/
  6. /*** Algorithm adapted from Peitgen and Sauper (1988), p.108. ***/
  7. /*** Jo Wood, V1.0, 19th October, 1994 ***/
  8. /*** Modified to allow multiple realisations of same surface, ***/
  9. /*** Jo Wood, V1.1 15th October, 1995. ***/
  10. /*** ***/
  11. /*****************************************************************************/
  12. #include <unistd.h>
  13. #include <math.h>
  14. #include <grass/gis.h>
  15. #include <grass/glocale.h>
  16. #include "frac.h"
  17. #include <grass/gmath.h>
  18. int specsyn(double *data[2], /* Array holding complex data to transform. */
  19. int nn /* Size of array in one dimension. */
  20. )
  21. {
  22. /* ---------------------------------------------------------------- */
  23. /* --- Initialise --- */
  24. /* ---------------------------------------------------------------- */
  25. int row, col, /* Counts through half the data array. */
  26. row0, col0, /* 'other half' of the array. */
  27. coeff, /* No. of Fourier coeffficents to calc. */
  28. seed; /* Random number seed. */
  29. double phase, rad, /* polar coordinates of Fourier coeff. */
  30. *temp[2];
  31. seed = -1 * getpid();
  32. G_math_rand(seed); /* Reset random number generator. */
  33. temp[0] = (double *)G_malloc(nn * nn * sizeof(double));
  34. temp[1] = (double *)G_malloc(nn * nn * sizeof(double));
  35. /* ---------------------------------------------------------------- */
  36. /* --- Create fractal surface --- */
  37. /* ---------------------------------------------------------------- */
  38. /* Calculate all the preliminary random coefficients. */
  39. /* ================================================== */
  40. G_message(_("Preliminary surface calculations..."));
  41. data_reset(data, nn);
  42. for (row = 0; row <= nn / 2; row++)
  43. for (col = 0; col <= nn / 2; col++) {
  44. /* Generate random Fourier coefficients. */
  45. phase = TWOPI * G_math_rand(0);
  46. if ((row != 0) || (col != 0))
  47. rad =
  48. pow(row * row + col * col,
  49. -(H + 1) / 2.0) * G_math_rand_gauss(0, 1.);
  50. else
  51. rad = 0.0;
  52. /* Fill half the array with coefficients. */
  53. *(data[0] + row * nn + col) = rad * cos(phase);
  54. *(data[1] + row * nn + col) = rad * sin(phase);
  55. /* Fill other half of array with coefficients. */
  56. if (row == 0)
  57. row0 = 0;
  58. else
  59. row0 = nn - row;
  60. if (col == 0)
  61. col0 = 0;
  62. else
  63. col0 = nn - col;
  64. *(data[0] + row0 * nn + col0) = rad * cos(phase);
  65. *(data[1] + row0 * nn + col0) = -rad * sin(phase);
  66. }
  67. *(temp[1] + nn / 2) = 0.0;
  68. *(temp[1] + nn * nn / 2) = 0.0;
  69. *(temp[1] + nn * nn / 2 + nn / 2) = 0.0;
  70. for (row = 1; row < nn / 2; row++)
  71. for (col = 1; col < nn / 2; col++) {
  72. phase = TWOPI * G_math_rand(0);
  73. rad =
  74. pow(row * row + col * col,
  75. -(H + 1) / 2.0) * G_math_rand_gauss(0, 1.);
  76. *(data[0] + row * nn + nn - col) = rad * cos(phase);
  77. *(data[1] + row * nn + nn - col) = rad * sin(phase);
  78. *(data[0] + (nn - row) * nn + col) = rad * cos(phase);
  79. *(data[1] + (nn - row) * nn + col) = -rad * sin(phase);
  80. }
  81. /* Transfer random coeffients to array before ifft transform */
  82. /* ========================================================= */
  83. for (coeff = 0; coeff < Steps; coeff++) {
  84. G_message(_("Calculating surface %d (of %d)..."), coeff + 1, Steps);
  85. data_reset(temp, nn);
  86. for (row = 0; row <= (coeff + 1) * nn / (Steps * 2); row++)
  87. for (col = 0; col <= (coeff + 1) * nn / (Steps * 2); col++) {
  88. if (row == 0)
  89. row0 = 0;
  90. else
  91. row0 = nn - row;
  92. if (col == 0)
  93. col0 = 0;
  94. else
  95. col0 = nn - col;
  96. *(temp[0] + row * nn + col) = *(data[0] + row * nn + col);
  97. *(temp[1] + row * nn + col) = *(data[1] + row * nn + col);
  98. *(temp[0] + row0 * nn + col0) = *(data[0] + row0 * nn + col0);
  99. *(temp[1] + row0 * nn + col0) = *(data[1] + row0 * nn + col0);
  100. }
  101. for (row = 1; row < (coeff + 1) * nn / (Steps * 2); row++)
  102. for (col = 1; col < (coeff + 1) * nn / (Steps * 2); col++) {
  103. *(temp[0] + row * nn + nn - col) =
  104. *(data[0] + row * nn + nn - col);
  105. *(temp[1] + row * nn + nn - col) =
  106. *(data[1] + row * nn + nn - col);
  107. *(temp[0] + (nn - row) * nn + col) =
  108. *(data[0] + (nn - row) * nn + col);
  109. *(temp[1] + (nn - row) * nn + col) =
  110. *(data[1] + (nn - row) * nn + col);
  111. }
  112. fft(1, temp, nn * nn, nn, nn); /* Perform inverse FFT and */
  113. write_rast(temp, nn, coeff + 1); /* write out raster. */
  114. }
  115. /* Free memory. */
  116. /* ============ */
  117. G_free(temp[0]);
  118. G_free(temp[1]);
  119. return 0;
  120. }