ressegm2d.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*-
  2. * Written by H. Mitasova, I. Kosinovsky, D. Gerdes Summer 1993
  3. * University of Illinois
  4. * US Army Construction Engineering Research Lab
  5. * Copyright 1993, H. Mitasova (University of Illinois),
  6. * I. Kosinovsky, (USA-CERL), and D.Gerdes (USA-CERL)
  7. *
  8. * modified by McCauley in August 1995
  9. * modified by Mitasova in August 1995
  10. *
  11. * bug fixes by Jaro Hofierka in February 1999:
  12. * line: 175,348 (*dnorm)
  13. * 177,350 (points[m1].sm)
  14. * 457,461 (})
  15. *
  16. * modified by Mitasova November 1999 (option for dnorm ind. tension)
  17. *
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <math.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/interpf.h>
  25. #include <grass/gmath.h>
  26. static int input_data(struct interp_params *,
  27. int, int, struct fcell_triple *, int, int, int, int,
  28. double, double, double);
  29. static int write_zeros(struct interp_params *, struct quaddata *, off_t);
  30. int IL_resample_interp_segments_2d(struct interp_params *params, struct BM *bitmask, /* bitmask */
  31. double zmin, double zmax, /* min and max input z-values */
  32. double *zminac, double *zmaxac, /* min and max interp. z-values */
  33. double *gmin, double *gmax, /* min and max inperp. slope val. */
  34. double *c1min, double *c1max, double *c2min, double *c2max, /* min and max interp. curv. val. */
  35. double *ertot, /* total interplating func. error */
  36. off_t offset1, /* offset for temp file writing */
  37. double *dnorm,
  38. int overlap,
  39. int inp_rows,
  40. int inp_cols,
  41. int fdsmooth,
  42. int fdinp,
  43. double ns_res,
  44. double ew_res,
  45. double inp_ns_res,
  46. double inp_ew_res, int dtens)
  47. {
  48. int i, j, k, l, m, m1, i1; /* loop coounters */
  49. int cursegm = 0;
  50. int new_comp = 0;
  51. int n_rows, n_cols, inp_r, inp_c;
  52. double x_or, y_or, xm, ym;
  53. static int first = 1, new_first = 1;
  54. double **matrix = NULL, **new_matrix = NULL, *b = NULL;
  55. int *indx = NULL, *new_indx = NULL;
  56. static struct fcell_triple *in_points = NULL; /* input points */
  57. int inp_check_rows, inp_check_cols, /* total input rows/cols */
  58. out_check_rows, out_check_cols; /* total output rows/cols */
  59. int first_row, last_row; /* first and last input row of segment */
  60. int first_col, last_col; /* first and last input col of segment */
  61. int num, prev;
  62. int div; /* number of divides */
  63. int rem_out_row, rem_out_col; /* output rows/cols remainders */
  64. int inp_seg_r, inp_seg_c, /* # of input rows/cols in segment */
  65. out_seg_r, out_seg_c; /* # of output rows/cols in segment */
  66. int ngstc, nszc /* first and last output col of the
  67. * segment */
  68. , ngstr, nszr; /* first and last output row of the
  69. * segment */
  70. int index; /* index for input data */
  71. int c, r;
  72. int overlap1;
  73. int p_size;
  74. struct quaddata *data;
  75. double xmax, xmin, ymax, ymin;
  76. int totsegm; /* total number of segments */
  77. int total_points = 0;
  78. struct triple triple; /* contains garbage */
  79. xmin = params->x_orig;
  80. ymin = params->y_orig;
  81. xmax = xmin + ew_res * params->nsizc;
  82. ymax = ymin + ns_res * params->nsizr;
  83. prev = inp_rows * inp_cols;
  84. if (prev <= params->kmax)
  85. div = 1; /* no segmentation */
  86. else { /* find the number of divides */
  87. for (i = 2;; i++) {
  88. c = inp_cols / i;
  89. r = inp_rows / i;
  90. num = c * r;
  91. if (num < params->kmin) {
  92. if (((params->kmin - num) > (prev + 1 - params->kmax)) &&
  93. (prev + 1 < params->KMAX2)) {
  94. div = i - 1;
  95. break;
  96. }
  97. else {
  98. div = i;
  99. break;
  100. }
  101. }
  102. if ((num > params->kmin) && (num + 1 < params->kmax)) {
  103. div = i;
  104. break;
  105. }
  106. prev = num;
  107. }
  108. }
  109. out_seg_r = params->nsizr / div; /* output rows per segment */
  110. out_seg_c = params->nsizc / div; /* output cols per segment */
  111. inp_seg_r = inp_rows / div; /* input rows per segment */
  112. inp_seg_c = inp_cols / div; /* input rows per segment */
  113. rem_out_col = params->nsizc % div;
  114. rem_out_row = params->nsizr % div;
  115. overlap1 = min1(overlap, inp_seg_c - 1);
  116. overlap1 = min1(overlap1, inp_seg_r - 1);
  117. out_check_rows = 0;
  118. out_check_cols = 0;
  119. inp_check_rows = 0;
  120. inp_check_cols = 0;
  121. if (div == 1) {
  122. p_size = inp_seg_c * inp_seg_r;
  123. }
  124. else {
  125. p_size = (overlap1 * 2 + inp_seg_c) * (overlap1 * 2 + inp_seg_r);
  126. }
  127. if (!in_points) {
  128. if (!
  129. (in_points =
  130. (struct fcell_triple *)G_malloc(sizeof(struct fcell_triple) *
  131. p_size * div))) {
  132. fprintf(stderr, "Cannot allocate memory for in_points\n");
  133. return -1;
  134. }
  135. }
  136. *dnorm =
  137. sqrt(((xmax - xmin) * (ymax -
  138. ymin) * p_size) / (inp_rows * inp_cols));
  139. if (dtens) {
  140. params->fi = params->fi * (*dnorm) / 1000.;
  141. fprintf(stderr, "dnorm = %f, rescaled tension = %f\n", *dnorm,
  142. params->fi);
  143. }
  144. if (div == 1) { /* no segmentation */
  145. totsegm = 1;
  146. cursegm = 1;
  147. input_data(params, 1, inp_rows, in_points, fdsmooth, fdinp, inp_rows,
  148. inp_cols, zmin, inp_ns_res, inp_ew_res);
  149. x_or = 0.;
  150. y_or = 0.;
  151. xm = params->nsizc * ew_res;
  152. ym = params->nsizr * ns_res;
  153. data = (struct quaddata *)quad_data_new(x_or, y_or, xm, ym,
  154. params->nsizr, params->nsizc,
  155. 0, params->KMAX2);
  156. m1 = 0;
  157. for (k = 1; k <= p_size; k++) {
  158. if (!Rast_is_f_null_value(&(in_points[k - 1].z))) {
  159. data->points[m1].x = in_points[k - 1].x / (*dnorm);
  160. data->points[m1].y = in_points[k - 1].y / (*dnorm);
  161. /* data->points[m1].z = (double) (in_points[k - 1].z) / (*dnorm); */
  162. data->points[m1].z = (double)(in_points[k - 1].z);
  163. data->points[m1].sm = in_points[k - 1].smooth;
  164. m1++;
  165. }
  166. }
  167. data->n_points = m1;
  168. total_points = m1;
  169. if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
  170. fprintf(stderr, "Cannot allocate memory for indx\n");
  171. return -1;
  172. }
  173. if (!(matrix = G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
  174. fprintf(stderr, "Cannot allocate memory for matrix\n");
  175. return -1;
  176. }
  177. if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
  178. fprintf(stderr, "Cannot allocate memory for b\n");
  179. return -1;
  180. }
  181. if (params->matrix_create(params, data->points, m1, matrix, indx) < 0)
  182. return -1;
  183. for (i = 0; i < m1; i++) {
  184. b[i + 1] = data->points[i].z;
  185. }
  186. b[0] = 0.;
  187. G_lubksb(matrix, m1 + 1, indx, b);
  188. params->check_points(params, data, b, ertot, zmin, *dnorm, triple);
  189. if (params->grid_calc(params, data, bitmask,
  190. zmin, zmax, zminac, zmaxac, gmin, gmax,
  191. c1min, c1max, c2min, c2max, ertot, b, offset1,
  192. *dnorm) < 0) {
  193. fprintf(stderr, "interpolation failed\n");
  194. return -1;
  195. }
  196. else {
  197. if (totsegm != 0) {
  198. G_percent(cursegm, totsegm, 1);
  199. }
  200. /*
  201. * if (b) G_free_vector(b); if (matrix) G_free_matrix(matrix); if
  202. * (indx) G_free_ivector(indx);
  203. */
  204. fprintf(stderr, "dnorm in ressegm after grid before out= %f \n",
  205. *dnorm);
  206. return total_points;
  207. }
  208. }
  209. out_seg_r = params->nsizr / div; /* output rows per segment */
  210. out_seg_c = params->nsizc / div; /* output cols per segment */
  211. inp_seg_r = inp_rows / div; /* input rows per segment */
  212. inp_seg_c = inp_cols / div; /* input rows per segment */
  213. rem_out_col = params->nsizc % div;
  214. rem_out_row = params->nsizr % div;
  215. overlap1 = min1(overlap, inp_seg_c - 1);
  216. overlap1 = min1(overlap1, inp_seg_r - 1);
  217. out_check_rows = 0;
  218. out_check_cols = 0;
  219. inp_check_rows = 0;
  220. inp_check_cols = 0;
  221. totsegm = div * div;
  222. /* set up a segment */
  223. for (i = 1; i <= div; i++) { /* input and output rows */
  224. if (i <= div - rem_out_row)
  225. n_rows = out_seg_r;
  226. else
  227. n_rows = out_seg_r + 1;
  228. inp_r = inp_seg_r;
  229. out_check_cols = 0;
  230. inp_check_cols = 0;
  231. ngstr = out_check_rows + 1; /* first output row of the segment */
  232. nszr = ngstr + n_rows - 1; /* last output row of the segment */
  233. y_or = (ngstr - 1) * ns_res; /* y origin of the segment */
  234. /*
  235. * Calculating input starting and ending rows and columns of this
  236. * segment
  237. */
  238. first_row = (int)(y_or / inp_ns_res) + 1;
  239. if (first_row > overlap1) {
  240. first_row -= overlap1; /* middle */
  241. last_row = first_row + inp_seg_r + overlap1 * 2 - 1;
  242. if (last_row > inp_rows) {
  243. first_row -= (last_row - inp_rows); /* bottom */
  244. last_row = inp_rows;
  245. }
  246. }
  247. else {
  248. first_row = 1; /* top */
  249. last_row = first_row + inp_seg_r + overlap1 * 2 - 1;
  250. }
  251. if ((last_row > inp_rows) || (first_row < 1)) {
  252. fprintf(stderr, "Row overlap too large!\n");
  253. return -1;
  254. }
  255. input_data(params, first_row, last_row, in_points, fdsmooth, fdinp,
  256. inp_rows, inp_cols, zmin, inp_ns_res, inp_ew_res);
  257. for (j = 1; j <= div; j++) { /* input and output cols */
  258. if (j <= div - rem_out_col)
  259. n_cols = out_seg_c;
  260. else
  261. n_cols = out_seg_c + 1;
  262. inp_c = inp_seg_c;
  263. ngstc = out_check_cols + 1; /* first output col of the segment */
  264. nszc = ngstc + n_cols - 1; /* last output col of the segment */
  265. x_or = (ngstc - 1) * ew_res; /* x origin of the segment */
  266. first_col = (int)(x_or / inp_ew_res) + 1;
  267. if (first_col > overlap1) {
  268. first_col -= overlap1; /* middle */
  269. last_col = first_col + inp_seg_c + overlap1 * 2 - 1;
  270. if (last_col > inp_cols) {
  271. first_col -= (last_col - inp_cols); /* right */
  272. last_col = inp_cols;
  273. }
  274. }
  275. else {
  276. first_col = 1; /* left */
  277. last_col = first_col + inp_seg_c + overlap1 * 2 - 1;
  278. }
  279. if ((last_col > inp_cols) || (first_col < 1)) {
  280. fprintf(stderr, "Column overlap too large!\n");
  281. return -1;
  282. }
  283. m = 0;
  284. /* Getting points for interpolation (translated) */
  285. xm = nszc * ew_res;
  286. ym = nszr * ns_res;
  287. data = (struct quaddata *)quad_data_new(x_or, y_or, xm, ym,
  288. nszr - ngstr + 1,
  289. nszc - ngstc + 1, 0,
  290. params->KMAX2);
  291. new_comp = 0;
  292. for (k = 0; k <= last_row - first_row; k++) {
  293. for (l = first_col - 1; l < last_col; l++) {
  294. index = k * inp_cols + l;
  295. if (!Rast_is_f_null_value(&(in_points[index].z))) {
  296. /* if the point is inside the segment (not overlapping) */
  297. if ((in_points[index].x - x_or >= 0) &&
  298. (in_points[index].y - y_or >= 0) &&
  299. ((nszc - 1) * ew_res - in_points[index].x >= 0) &&
  300. ((nszr - 1) * ns_res - in_points[index].y >= 0))
  301. total_points += 1;
  302. data->points[m].x =
  303. (in_points[index].x - x_or) / (*dnorm);
  304. data->points[m].y =
  305. (in_points[index].y - y_or) / (*dnorm);
  306. /* data->points[m].z = (double) (in_points[index].z) / (*dnorm); */
  307. data->points[m].z = (double)(in_points[index].z);
  308. data->points[m].sm = in_points[index].smooth;
  309. m++;
  310. }
  311. else
  312. new_comp = 1;
  313. /* fprintf(stderr,"%f,%f,%f
  314. zmin=%f\n",in_points[index].x,in_points[index].y,in_points[index].z,zmin);
  315. */
  316. }
  317. }
  318. /* fprintf (stdout,"m,index:%di,%d\n",m,index); */
  319. if (m <= params->KMAX2)
  320. data->n_points = m;
  321. else
  322. data->n_points = params->KMAX2;
  323. out_check_cols += n_cols;
  324. inp_check_cols += inp_c;
  325. cursegm = (i - 1) * div + j - 1;
  326. /* show before to catch 0% */
  327. if (totsegm != 0) {
  328. G_percent(cursegm, totsegm, 1);
  329. }
  330. if (m == 0) {
  331. /*
  332. * fprintf(stderr,"Warning: segment with zero points encountered,
  333. * insrease overlap\n");
  334. */
  335. write_zeros(params, data, offset1);
  336. }
  337. else {
  338. if (new_comp) {
  339. if (new_first) {
  340. new_first = 0;
  341. if (!b) {
  342. if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
  343. fprintf(stderr,
  344. "Cannot allocate memory for b\n");
  345. return -1;
  346. }
  347. }
  348. if (!(new_indx = G_alloc_ivector(params->KMAX2 + 1))) {
  349. fprintf(stderr,
  350. "Cannot allocate memory for new_indx\n");
  351. return -1;
  352. }
  353. if (!
  354. (new_matrix =
  355. G_alloc_matrix(params->KMAX2 + 1,
  356. params->KMAX2 + 1))) {
  357. fprintf(stderr,
  358. "Cannot allocate memory for new_matrix\n");
  359. return -1;
  360. }
  361. } /*new_first */
  362. if (params->
  363. matrix_create(params, data->points, data->n_points,
  364. new_matrix, new_indx) < 0)
  365. return -1;
  366. for (i1 = 0; i1 < m; i1++) {
  367. b[i1 + 1] = data->points[i1].z;
  368. }
  369. b[0] = 0.;
  370. G_lubksb(new_matrix, data->n_points + 1, new_indx, b);
  371. params->check_points(params, data, b, ertot, zmin,
  372. *dnorm, triple);
  373. if (params->grid_calc(params, data, bitmask,
  374. zmin, zmax, zminac, zmaxac, gmin,
  375. gmax, c1min, c1max, c2min, c2max,
  376. ertot, b, offset1, *dnorm) < 0) {
  377. fprintf(stderr, "interpolate() failed\n");
  378. return -1;
  379. }
  380. } /*new_comp */
  381. else {
  382. if (first) {
  383. first = 0;
  384. if (!b) {
  385. if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
  386. fprintf(stderr,
  387. "Cannot allocate memory for b\n");
  388. return -1;
  389. }
  390. }
  391. if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
  392. fprintf(stderr,
  393. "Cannot allocate memory for indx\n");
  394. return -1;
  395. }
  396. if (!
  397. (matrix =
  398. G_alloc_matrix(params->KMAX2 + 1,
  399. params->KMAX2 + 1))) {
  400. fprintf(stderr,
  401. "Cannot allocate memory for matrix\n");
  402. return -1;
  403. }
  404. } /* first */
  405. if (params->
  406. matrix_create(params, data->points, data->n_points,
  407. matrix, indx) < 0)
  408. return -1;
  409. /* } here it was bug */
  410. for (i1 = 0; i1 < m; i1++)
  411. b[i1 + 1] = data->points[i1].z;
  412. b[0] = 0.;
  413. G_lubksb(matrix, data->n_points + 1, indx, b);
  414. params->check_points(params, data, b, ertot, zmin,
  415. *dnorm, triple);
  416. if (params->grid_calc(params, data, bitmask,
  417. zmin, zmax, zminac, zmaxac, gmin,
  418. gmax, c1min, c1max, c2min, c2max,
  419. ertot, b, offset1, *dnorm) < 0) {
  420. fprintf(stderr, "interpolate() failed\n");
  421. return -1;
  422. }
  423. }
  424. }
  425. if (data) {
  426. G_free(data->points);
  427. G_free(data);
  428. }
  429. /*
  430. * cursegm++;
  431. */
  432. }
  433. inp_check_rows += inp_r;
  434. out_check_rows += n_rows;
  435. }
  436. /* run one last time after the loop is done to catch 100% */
  437. if (totsegm != 0)
  438. G_percent(1, 1, 1); /* cursegm doesn't get to totsegm so we force 100% */
  439. /*
  440. * if (b) G_free_vector(b); if (indx) G_free_ivector(indx); if (matrix)
  441. * G_free_matrix(matrix);
  442. */
  443. fprintf(stderr, "dnorm in ressegm after grid before out2= %f \n", *dnorm);
  444. return total_points;
  445. }
  446. /* input of data for interpolation and smoothing parameters */
  447. static int input_data(struct interp_params *params,
  448. int first_row, int last_row,
  449. struct fcell_triple *points,
  450. int fdsmooth, int fdinp,
  451. int inp_rows, int inp_cols,
  452. double zmin, double inp_ns_res, double inp_ew_res)
  453. {
  454. double x, y, sm; /* input data and smoothing */
  455. int m1, m2; /* loop counters */
  456. static FCELL *cellinp = NULL; /* cell buffer for input data */
  457. static FCELL *cellsmooth = NULL; /* cell buffer for smoothing */
  458. if (!cellinp)
  459. cellinp = Rast_allocate_f_buf();
  460. if (!cellsmooth)
  461. cellsmooth = Rast_allocate_f_buf();
  462. for (m1 = 0; m1 <= last_row - first_row; m1++) {
  463. Rast_get_f_row(fdinp, cellinp, inp_rows - m1 - first_row);
  464. if (fdsmooth >= 0)
  465. Rast_get_f_row(fdsmooth, cellsmooth, inp_rows - m1 - first_row);
  466. y = params->y_orig + (m1 + first_row - 1 + 0.5) * inp_ns_res;
  467. for (m2 = 0; m2 < inp_cols; m2++) {
  468. x = params->x_orig + (m2 + 0.5) * inp_ew_res;
  469. /*
  470. * z = cellinp[m2]*params->zmult;
  471. */
  472. if (fdsmooth >= 0)
  473. sm = (double)cellsmooth[m2];
  474. else
  475. sm = 0.01;
  476. points[m1 * inp_cols + m2].x = x - params->x_orig;
  477. points[m1 * inp_cols + m2].y = y - params->y_orig;
  478. if (!Rast_is_f_null_value(cellinp + m2)) {
  479. points[m1 * inp_cols + m2].z =
  480. cellinp[m2] * params->zmult - zmin;
  481. }
  482. else {
  483. Rast_set_f_null_value(&(points[m1 * inp_cols + m2].z), 1);
  484. }
  485. /* fprintf (stdout,"sm: %f\n",sm); */
  486. points[m1 * inp_cols + m2].smooth = sm;
  487. }
  488. }
  489. return 1;
  490. }
  491. static int write_zeros(struct interp_params *params,
  492. struct quaddata *data, /* given segment */
  493. off_t offset1 /* offset for temp file writing */
  494. )
  495. {
  496. /*
  497. * C C INTERPOLATION BY FUNCTIONAL METHOD : TPS + complete regul.
  498. * c
  499. */
  500. double x_or = data->x_orig;
  501. double y_or = data->y_orig;
  502. int n_rows = data->n_rows;
  503. int n_cols = data->n_cols;
  504. int cond1, cond2;
  505. int k, l;
  506. int ngstc, nszc, ngstr, nszr;
  507. off_t offset, offset2;
  508. double ns_res, ew_res;
  509. ns_res = (((struct quaddata *)(data))->ymax -
  510. ((struct quaddata *)(data))->y_orig) / data->n_rows;
  511. ew_res = (((struct quaddata *)(data))->xmax -
  512. ((struct quaddata *)(data))->x_orig) / data->n_cols;
  513. cond2 = ((params->adxx != NULL) || (params->adyy != NULL) ||
  514. (params->adxy != NULL));
  515. cond1 = ((params->adx != NULL) || (params->ady != NULL) || cond2);
  516. ngstc = (int)(x_or / ew_res + 0.5) + 1;
  517. nszc = ngstc + n_cols - 1;
  518. ngstr = (int)(y_or / ns_res + 0.5) + 1;
  519. nszr = ngstr + n_rows - 1;
  520. for (k = ngstr; k <= nszr; k++) {
  521. offset = offset1 * (k - 1); /* rows offset */
  522. for (l = ngstc; l <= nszc; l++) {
  523. /*
  524. * params->az[l] = 0.;
  525. */
  526. Rast_set_d_null_value(params->az + l, 1);
  527. if (cond1) {
  528. /*
  529. * params->adx[l] = (FCELL)0.; params->ady[l] = (FCELL)0.;
  530. */
  531. Rast_set_d_null_value(params->adx + l, 1);
  532. Rast_set_d_null_value(params->ady + l, 1);
  533. if (cond2) {
  534. Rast_set_d_null_value(params->adxx + l, 1);
  535. Rast_set_d_null_value(params->adyy + l, 1);
  536. Rast_set_d_null_value(params->adxy + l, 1);
  537. /*
  538. * params->adxx[l] = (FCELL)0.; params->adyy[l] = (FCELL)0.;
  539. * params->adxy[l] = (FCELL)0.;
  540. */
  541. }
  542. }
  543. }
  544. offset2 = (offset + ngstc - 1) * sizeof(FCELL);
  545. if (params->wr_temp(params, ngstc, nszc, offset2) < 0)
  546. return -1;
  547. }
  548. return 1;
  549. }