123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- /*!
- * \file segmen2d.c
- *
- * \author H. Mitasova, I. Kosinovsky, D. Gerdes
- *
- * \copyright
- * (C) 1993 by Helena Mitasova and the GRASS Development Team
- *
- * \copyright
- * This program is free software under the
- * GNU General Public License (>=v2).
- * Read the file COPYING that comes with GRASS
- * for details.
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <omp.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #include <grass/interpf.h>
- #include <grass/gmath.h>
- static int cut_tree(struct multtree *, struct multtree **, int *);
- /*!
- * See documentation for IL_interp_segments_2d.
- * This is a parallel processing implementation.
- */
- int IL_interp_segments_2d_parallel(struct interp_params *params, struct tree_info *info, /*!< info for the quad tree */
- struct multtree *tree, /*!< current leaf of the quad tree */
- struct BM *bitmask, /*!< bitmask */
- double zmin, double zmax, /*!< min and max input z-values */
- double *zminac, double *zmaxac, /*!< min and max interp. z-values */
- double *gmin, double *gmax, /*!< min and max inperp. slope val. */
- double *c1min, double *c1max, /*!< min and max interp. curv. val. */
- double *c2min, double *c2max, /*!< min and max interp. curv. val. */
- double *ertot, /*!< total interplating func. error */
- int totsegm, /*!< total number of segments */
- off_t offset1, /*!< offset for temp file writing */
- double dnorm, int threads)
- {
- int some_thread_failed = 0;
- int tid;
- int i = 0;
- int j = 0;
- int i_cnt;
- int cursegm = 0;
- double smseg;
- double ***matrix = NULL;
- int **indx = NULL;
- double **b = NULL;
- double **A = NULL;
- struct quaddata **data_local;
- struct multtree **all_leafs;
- all_leafs =
- (struct multtree **)G_malloc(sizeof(struct multtree *) * totsegm);
- data_local =
- (struct quaddata **)G_malloc(sizeof(struct quaddata *) * threads);
- matrix = (double ***)G_malloc(sizeof(double **) * threads);
- indx = (int **)G_malloc(sizeof(int *) * threads);
- b = (double **)G_malloc(sizeof(double *) * threads);
- A = (double **)G_malloc(sizeof(double *) * threads);
- for (i_cnt = 0; i_cnt < threads; i_cnt++) {
- if (!
- (matrix[i_cnt] =
- G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- }
- for (i_cnt = 0; i_cnt < threads; i_cnt++) {
- if (!(indx[i_cnt] = G_alloc_ivector(params->KMAX2 + 1))) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- }
- for (i_cnt = 0; i_cnt < threads; i_cnt++) {
- if (!(b[i_cnt] = G_alloc_vector(params->KMAX2 + 3))) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- }
- for (i_cnt = 0; i_cnt < threads; i_cnt++) {
- if (!
- (A[i_cnt] =
- G_alloc_vector((params->KMAX2 + 2) * (params->KMAX2 + 2) + 1))) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- }
- smseg = smallest_segment(tree, 4);
- cut_tree(tree, all_leafs, &i);
- G_message(_("Starting parallel work"));
- #pragma omp parallel firstprivate(tid, i, j, zmin, zmax, tree, totsegm, offset1, dnorm, smseg, ertot, params, info, all_leafs, bitmask, b, indx, matrix, data_local, A) shared(cursegm, threads, some_thread_failed, zminac, zmaxac, gmin, gmax, c1min, c1max, c2min, c2max) default(none)
- {
- #pragma omp for schedule(dynamic)
- for (i_cnt = 0; i_cnt < totsegm; i_cnt++) {
- /* Obtain thread id */
- #if defined(_OPENMP)
- tid = omp_get_thread_num();
- #endif
- double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1,
- temp2;
- int npt, nptprev, MAXENC;
- double ew_res, ns_res;
- int MINPTS;
- double pr;
- struct triple *point;
- struct triple skip_point;
- int m_skip, skip_index, k, segtest;
- double xx, yy, zz;
- //struct quaddata *data_local;
- ns_res = (((struct quaddata *)(tree->data))->ymax -
- ((struct quaddata *)(tree->data))->y_orig) /
- params->nsizr;
- ew_res =
- (((struct quaddata *)(tree->data))->xmax -
- ((struct quaddata *)(tree->data))->x_orig) / params->nsizc;
- if (all_leafs[i_cnt] == NULL) {
- some_thread_failed = -1;
- continue;
- }
- if (all_leafs[i_cnt]->data == NULL) {
- some_thread_failed = -1;
- continue;
- }
- if (((struct quaddata *)(all_leafs[i_cnt]->data))->points == NULL) {
- continue;
- }
- else {
- distx =
- (((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols *
- ew_res) * 0.1;
- disty =
- (((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows *
- ns_res) * 0.1;
- distxp = 0;
- distyp = 0;
- xmn = ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig;
- xmx = ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax;
- ymn = ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig;
- ymx = ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax;
- i = 0;
- MAXENC = 0;
- /* data is a window with zero points; some fields don't make sence in this case
- so they are zero (like resolution,dimentions */
- /* CHANGE */
- /* Calcutaing kmin for surrent segment (depends on the size) */
- /*****if (smseg <= 0.00001) MINPTS=params->kmin; else {} ***/
- pr = pow(2., (xmx - xmn) / smseg - 1.);
- MINPTS =
- params->kmin * (pr /
- (1 + params->kmin * pr / params->KMAX2));
- /* fprintf(stderr,"MINPTS=%d, KMIN=%d, KMAX=%d, pr=%lf, smseg=%lf, DX=%lf \n", MINPTS,params->kmin,params->KMAX2,pr,smseg,xmx-xmn); */
- data_local[tid] =
- (struct quaddata *)quad_data_new(xmn - distx, ymn - disty,
- xmx + distx, ymx + disty,
- 0, 0, 0, params->KMAX2);
- npt =
- MT_region_data(info, tree, data_local[tid], params->KMAX2,
- 4);
- while ((npt < MINPTS) || (npt > params->KMAX2)) {
- if (i >= 70) {
- G_warning(_("Taking too long to find points for interpolation - "
- "please change the region to area where your points are. "
- "Continuing calculations..."));
- break;
- }
- i++;
- if (npt > params->KMAX2)
- /* decrease window */
- {
- MAXENC = 1;
- nptprev = npt;
- temp1 = distxp;
- distxp = distx;
- distx = distxp - fabs(distx - temp1) * 0.5;
- temp2 = distyp;
- distyp = disty;
- disty = distyp - fabs(disty - temp2) * 0.5;
- /* decrease by 50% of a previous change in window */
- }
- else {
- nptprev = npt;
- temp1 = distyp;
- distyp = disty;
- temp2 = distxp;
- distxp = distx;
- if (MAXENC) {
- disty = fabs(disty - temp1) * 0.5 + distyp;
- distx = fabs(distx - temp2) * 0.5 + distxp;
- }
- else {
- distx += distx;
- disty += disty;
- }
- /* decrease by 50% of extra distance */
- }
- data_local[tid]->x_orig = xmn - distx; /* update window */
- data_local[tid]->y_orig = ymn - disty;
- data_local[tid]->xmax = xmx + distx;
- data_local[tid]->ymax = ymx + disty;
- data_local[tid]->n_points = 0;
- npt =
- MT_region_data(info, tree, data_local[tid],
- params->KMAX2, 4);
- }
- if (totsegm != 0 && tid == 0) {
- G_percent(cursegm, totsegm, 1);
- }
- data_local[tid]->n_rows =
- ((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows;
- data_local[tid]->n_cols =
- ((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols;
- /* for printing out overlapping segments */
- ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig =
- xmn - distx;
- ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig =
- ymn - disty;
- ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax =
- xmx + distx;
- ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax =
- ymx + disty;
- data_local[tid]->x_orig = xmn;
- data_local[tid]->y_orig = ymn;
- data_local[tid]->xmax = xmx;
- data_local[tid]->ymax = ymx;
- /* allocate memory for CV points only if cv is performed */
- if (params->cv) {
- if (!
- (point =
- (struct triple *)G_malloc(sizeof(struct triple) *
- data_local[tid]->
- n_points))) {
- G_warning(_("Out of memory"));
- some_thread_failed = -1;
- continue;
- }
- }
- /*normalize the data so that the side of average segment is about 1m */
- /* put data_points into point only if CV is performed */
- for (i = 0; i < data_local[tid]->n_points; i++) {
- data_local[tid]->points[i].x =
- (data_local[tid]->points[i].x -
- data_local[tid]->x_orig) / dnorm;
- data_local[tid]->points[i].y =
- (data_local[tid]->points[i].y -
- data_local[tid]->y_orig) / dnorm;
- if (params->cv) {
- point[i].x = data_local[tid]->points[i].x; /*cv stuff */
- point[i].y = data_local[tid]->points[i].y; /*cv stuff */
- point[i].z = data_local[tid]->points[i].z; /*cv stuff */
- }
- /* commented out by Helena january 1997 as this is not necessary
- although it may be useful to put normalization of z back?
- data->points[i].z = data->points[i].z / dnorm;
- this made smoothing self-adjusting based on dnorm
- if (params->rsm < 0.) data->points[i].sm = data->points[i].sm / dnorm;
- */
- }
- /* cv stuff */
- if (params->cv) {
- m_skip = data_local[tid]->n_points;
- }
- else {
- m_skip = 1;
- }
- /* remove after cleanup - this is just for testing */
- skip_point.x = 0.;
- skip_point.y = 0.;
- skip_point.z = 0.;
- for (skip_index = 0; skip_index < m_skip; skip_index++) {
- if (params->cv) {
- segtest = 0;
- j = 0;
- xx = point[skip_index].x * dnorm +
- data_local[tid]->x_orig + params->x_orig;
- yy = point[skip_index].y * dnorm +
- data_local[tid]->y_orig + params->y_orig;
- zz = point[skip_index].z;
- if (xx >= data_local[tid]->x_orig + params->x_orig &&
- xx <= data_local[tid]->xmax + params->x_orig &&
- yy >= data_local[tid]->y_orig + params->y_orig &&
- yy <= data_local[tid]->ymax + params->y_orig) {
- segtest = 1;
- skip_point.x = point[skip_index].x;
- skip_point.y = point[skip_index].y;
- skip_point.z = point[skip_index].z;
- for (k = 0; k < m_skip; k++) {
- if (k != skip_index && params->cv) {
- data_local[tid]->points[j].x = point[k].x;
- data_local[tid]->points[j].y = point[k].y;
- data_local[tid]->points[j].z = point[k].z;
- j++;
- }
- }
- } /* segment area test */
- }
- if (!params->cv) {
- if ( /* params */
- IL_matrix_create_alloc(params,
- data_local[tid]->points,
- data_local[tid]->
- n_points, matrix[tid],
- indx[tid],
- A[tid]) < 0) {
- some_thread_failed = -1;
- continue;
- }
- }
- else if (segtest == 1) {
- if ( /* params */
- IL_matrix_create_alloc(params,
- data_local[tid]->points,
- data_local[tid]->
- n_points - 1,
- matrix[tid], indx[tid],
- A[tid]) < 0) {
- some_thread_failed = -1;
- continue;
- }
- }
- if (!params->cv) {
- for (i = 0; i < data_local[tid]->n_points; i++) {
- b[tid][i + 1] = data_local[tid]->points[i].z;
- }
- b[tid][0] = 0.;
- G_lubksb(matrix[tid], data_local[tid]->n_points + 1,
- indx[tid], b[tid]);
- /* put here condition to skip error if not needed */
- params->check_points(params, data_local[tid], b[tid],
- ertot, zmin, dnorm, skip_point);
- }
- else if (segtest == 1) {
- for (i = 0; i < data_local[tid]->n_points - 1; i++) {
- b[tid][i + 1] = data_local[tid]->points[i].z;
- }
- b[tid][0] = 0.;
- G_lubksb(matrix[tid], data_local[tid]->n_points,
- indx[tid], b[tid]);
- params->check_points(params, data_local[tid], b[tid],
- ertot, zmin, dnorm, skip_point);
- }
- } /*end of cv loop */
- if (!params->cv) {
- if ((params->Tmp_fd_z != NULL) ||
- (params->Tmp_fd_dx != NULL) ||
- (params->Tmp_fd_dy != NULL) ||
- (params->Tmp_fd_xx != NULL) ||
- (params->Tmp_fd_yy != NULL) ||
- (params->Tmp_fd_xy != NULL)) {
- #pragma omp critical
- {
- if (params->grid_calc
- (params, data_local[tid], bitmask, zmin, zmax,
- zminac, zmaxac, gmin, gmax, c1min, c1max,
- c2min, c2max, ertot, b[tid], offset1,
- dnorm) < 0) {
- some_thread_failed = -1;
- }
- }
- }
- }
- /* show after to catch 100% */
- #pragma omp atomic
- cursegm++;
- if (totsegm < cursegm) {
- G_debug(1, "%d %d", totsegm, cursegm);
- }
- if (totsegm != 0 && tid == 0) {
- G_percent(cursegm, totsegm, 1);
- }
- /*
- G_free_matrix(matrix);
- G_free_ivector(indx);
- G_free_vector(b);
- */
- G_free(data_local[tid]->points);
- G_free(data_local[tid]);
- }
- }
- } /* All threads join master thread and terminate */
- for (i_cnt = 0; i_cnt < threads; i_cnt++) {
- G_free(matrix[i_cnt]);
- G_free(indx[i_cnt]);
- G_free(b[i_cnt]);
- G_free(A[i_cnt]);
- }
- G_free(all_leafs);
- G_free(data_local);
- G_free(matrix);
- G_free(indx);
- G_free(b);
- G_free(A);
- if (some_thread_failed != 0) {
- return -1;
- }
- return 1;
- }
- /* cut given tree into separate leafs */
- int cut_tree(struct multtree *tree, /* tree we want to cut */
- struct multtree **cut_leafs, /* array of leafs */
- int *where_to_add /* index of leaf which will be next */ )
- {
- if (tree == NULL)
- return -1;
- if (tree->data == NULL)
- return -1;
- if (((struct quaddata *)(tree->data))->points == NULL) {
- int i;
- for (i = 0; i < 4; i++) {
- cut_tree(tree->leafs[i], cut_leafs, where_to_add);
- }
- return 1;
- }
- else {
- cut_leafs[*where_to_add] = tree;
- (*where_to_add)++;
- return 1;
- }
- }
|