int main(int argc, char *argv[]) { int npmin; int ii; double x_orig, y_orig, dnorm, deltx, delty, xm, ym; char dmaxchar[200]; char dminchar[200]; struct quaddata *data; struct multfunc *functions; struct multtree *tree; int open_check, with_z; char buf[1024]; struct GModule *module; struct { struct Option *input, *field, *zcol, *wheresql, *scol, *elev, *slope, *aspect, *pcurv, *tcurv, *mcurv, *treefile, *overfile, *maskmap, *dmin, *dmax, *zmult, *fi, *rsm, *segmax, *npmin, *cvdev, *devi, *theta, *scalex; } parm; struct { struct Flag *deriv, *cprght, *cv; } flag; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("surface")); G_add_keyword(_("interpolation")); G_add_keyword(_("3D")); module->label = _("Performs surface interpolation from vector points map by splines."); module->description = _("Spatial approximation and topographic analysis from given " "point or isoline data in vector format to floating point " "raster format using regularized spline with tension."); flag.cv = G_define_flag(); flag.cv->key = 'c'; flag.cv->description = _("Perform cross-validation procedure without raster approximation"); flag.cv->guisection = _("Parameters"); flag.cprght = G_define_flag(); flag.cprght->key = 't'; flag.cprght->description = _("Use scale dependent tension"); flag.cprght->guisection = _("Parameters"); flag.deriv = G_define_flag(); flag.deriv->key = 'd'; flag.deriv->description = _("Output partial derivatives instead of topographic parameters"); flag.deriv->guisection = _("Outputs"); parm.input = G_define_standard_option(G_OPT_V_INPUT); parm.field = G_define_standard_option(G_OPT_V_FIELD); parm.field->answer = "1"; parm.field->guisection = _("Selection"); parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN); parm.zcol->key = "zcolumn"; parm.zcol->required = NO; parm.zcol->label = _("Name of the attribute column with values to be used for approximation"); parm.zcol->description = _("If not given and input is 2D vector map then category values are used. " "If input is 3D vector map then z-coordinates are used."); parm.zcol->guisection = _("Parameters"); parm.wheresql = G_define_standard_option(G_OPT_DB_WHERE); parm.wheresql->guisection = _("Selection"); parm.elev = G_define_standard_option(G_OPT_R_OUTPUT); parm.elev->key = "elevation"; parm.elev->required = NO; parm.elev->description = _("Name for output surface elevation raster map"); parm.elev->guisection = _("Outputs"); parm.slope = G_define_standard_option(G_OPT_R_OUTPUT); parm.slope->key = "slope"; parm.slope->required = NO; parm.slope->description = _("Name for output slope raster map"); parm.slope->guisection = _("Outputs"); parm.aspect = G_define_standard_option(G_OPT_R_OUTPUT); parm.aspect->key = "aspect"; parm.aspect->required = NO; parm.aspect->description = _("Name for output aspect raster map"); parm.aspect->guisection = _("Outputs"); parm.pcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.pcurv->key = "pcurvature"; parm.pcurv->required = NO; parm.pcurv->description = _("Name for output profile curvature raster map"); parm.pcurv->guisection = _("Outputs"); parm.tcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.tcurv->key = "tcurvature"; parm.tcurv->required = NO; parm.tcurv->description = _("Name for output tangential curvature raster map"); parm.tcurv->guisection = _("Outputs"); parm.mcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.mcurv->key = "mcurvature"; parm.mcurv->required = NO; parm.mcurv->description = _("Name for output mean curvature raster map"); parm.mcurv->guisection = _("Outputs"); parm.devi = G_define_standard_option(G_OPT_V_OUTPUT); parm.devi->key = "deviations"; parm.devi->required = NO; parm.devi->description = _("Name for output deviations vector point map"); parm.devi->guisection = _("Outputs"); parm.cvdev = G_define_standard_option(G_OPT_V_OUTPUT); parm.cvdev->key = "cvdev"; parm.cvdev->required = NO; parm.cvdev->description = _("Name for output cross-validation errors vector point map"); parm.cvdev->guisection = _("Outputs"); parm.treefile = G_define_standard_option(G_OPT_V_OUTPUT); parm.treefile->key = "treeseg"; parm.treefile->required = NO; parm.treefile->description = _("Name for output vector map showing quadtree segmentation"); parm.treefile->guisection = _("Outputs"); parm.overfile = G_define_standard_option(G_OPT_V_OUTPUT); parm.overfile->key = "overwin"; parm.overfile->required = NO; parm.overfile->description = _("Name for output vector map showing overlapping windows"); parm.overfile->guisection = _("Outputs"); parm.maskmap = G_define_standard_option(G_OPT_R_INPUT); parm.maskmap->key = "mask"; parm.maskmap->required = NO; parm.maskmap->description = _("Name of raster map used as mask"); parm.maskmap->guisection = _("Parameters"); parm.fi = G_define_option(); parm.fi->key = "tension"; parm.fi->type = TYPE_DOUBLE; parm.fi->answer = TENSION; parm.fi->required = NO; parm.fi->description = _("Tension parameter"); parm.fi->guisection = _("Parameters"); parm.rsm = G_define_option(); parm.rsm->key = "smooth"; parm.rsm->type = TYPE_DOUBLE; parm.rsm->required = NO; parm.rsm->description = _("Smoothing parameter"); parm.rsm->guisection = _("Parameters"); parm.scol = G_define_option(); parm.scol->key = "smooth_column"; parm.scol->type = TYPE_STRING; parm.scol->required = NO; parm.scol->description = _("Name of the attribute column with smoothing parameters"); parm.scol->guisection = _("Parameters"); parm.segmax = G_define_option(); parm.segmax->key = "segmax"; parm.segmax->type = TYPE_INTEGER; parm.segmax->answer = MAXSEGM; parm.segmax->required = NO; parm.segmax->description = _("Maximum number of points in a segment"); parm.segmax->guisection = _("Parameters"); parm.npmin = G_define_option(); parm.npmin->key = "npmin"; parm.npmin->type = TYPE_INTEGER; parm.npmin->answer = MINPOINTS; parm.npmin->required = NO; parm.npmin->description = _("Minimum number of points for approximation in a segment (>segmax)"); parm.npmin->guisection = _("Parameters"); parm.dmin = G_define_option(); parm.dmin->key = "dmin"; parm.dmin->type = TYPE_DOUBLE; parm.dmin->required = NO; parm.dmin->description = _("Minimum distance between points (to remove almost identical points)"); parm.dmin->guisection = _("Parameters"); parm.dmax = G_define_option(); parm.dmax->key = "dmax"; parm.dmax->type = TYPE_DOUBLE; parm.dmax->required = NO; parm.dmax->description = _("Maximum distance between points on isoline (to insert additional points)"); parm.dmax->guisection = _("Parameters"); parm.zmult = G_define_option(); parm.zmult->key = "zscale"; parm.zmult->type = TYPE_DOUBLE; parm.zmult->answer = ZMULT; parm.zmult->required = NO; parm.zmult->description = _("Conversion factor for values used for approximation"); parm.zmult->guisection = _("Parameters"); parm.theta = G_define_option(); parm.theta->key = "theta"; parm.theta->type = TYPE_DOUBLE; parm.theta->required = NO; parm.theta->description = _("Anisotropy angle (in degrees counterclockwise from East)"); parm.theta->guisection = _("Parameters"); parm.scalex = G_define_option(); parm.scalex->key = "scalex"; parm.scalex->type = TYPE_DOUBLE; parm.scalex->required = NO; parm.scalex->description = _("Anisotropy scaling factor"); parm.scalex->guisection = _("Parameters"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_get_set_window(&cellhd); ew_res = cellhd.ew_res; ns_res = cellhd.ns_res; n_cols = cellhd.cols; n_rows = cellhd.rows; x_orig = cellhd.west; y_orig = cellhd.south; xm = cellhd.east; ym = cellhd.north; if (ew_res < ns_res) dmin = ew_res / 2; else dmin = ns_res / 2; disk = n_rows * n_cols * sizeof(int); sdisk = n_rows * n_cols * sizeof(short int); sprintf(dmaxchar, "%f", dmin * 5); sprintf(dminchar, "%f", dmin); if (!parm.dmin->answer) { parm.dmin->answer = G_store(dminchar); parm.dmin->answers = (char **) G_malloc(2 * sizeof(char *)); parm.dmin->answers[0] = G_store(dminchar); parm.dmin->answers[1] = NULL; } if (!parm.dmax->answer) { parm.dmax->answer = G_store(dmaxchar); parm.dmax->answers = (char **) G_malloc(2 * sizeof(char *)); parm.dmax->answers[0] = G_store(dmaxchar); parm.dmax->answers[1] = NULL; } input = parm.input->answer; zcol = parm.zcol->answer; scol = parm.scol->answer; wheresql = parm.wheresql->answer; maskmap = parm.maskmap->answer; elev = parm.elev->answer; devi = parm.devi->answer; cvdev = parm.cvdev->answer; slope = parm.slope->answer; aspect = parm.aspect->answer; pcurv = parm.pcurv->answer; tcurv = parm.tcurv->answer; mcurv = parm.mcurv->answer; treefile = parm.treefile->answer; overfile = parm.overfile->answer; if (devi) { if (Vect_legal_filename(devi) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), devi); } if (cvdev) { if (Vect_legal_filename(cvdev) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), cvdev); } if (treefile) { if (Vect_legal_filename(treefile) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), treefile); } if (overfile) { if (Vect_legal_filename(overfile) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), overfile); } /* if (treefile) Vect_check_input_output_name(input, treefile, G_FATAL_EXIT); if (overfile) Vect_check_input_output_name(input, overfile, G_FATAL_EXIT); */ if ((elev == NULL) && (pcurv == NULL) && (tcurv == NULL) && (mcurv == NULL) && (slope == NULL) && (aspect == NULL) && (devi == NULL) && (cvdev == NULL)) G_warning(_("You are not outputting any raster or vector maps")); cond2 = ((pcurv != NULL) || (tcurv != NULL) || (mcurv != NULL)); cond1 = ((slope != NULL) || (aspect != NULL) || cond2); deriv = flag.deriv->answer; dtens = flag.cprght->answer; cv = flag.cv->answer; if ((cv && cvdev == NULL) || (!(cv) && cvdev != NULL)) G_fatal_error(_("Both cross-validation options (-c flag and cvdev vector output) must be specified")); if ((elev != NULL || cond1 || cond2 || devi != NULL) && cv) G_fatal_error(_("The cross-validation cannot be computed simultaneously with output raster or devi file")); ertre = 0.1; sscanf(parm.dmax->answer, "%lf", &dmax); sscanf(parm.dmin->answer, "%lf", &dmin); sscanf(parm.fi->answer, "%lf", &fi); sscanf(parm.segmax->answer, "%d", &KMAX); sscanf(parm.npmin->answer, "%d", &npmin); sscanf(parm.zmult->answer, "%lf", &zmult); /* if (fi=0.000000) G_fatal_error("Tension must be > 0.000000") */ if (parm.theta->answer) sscanf(parm.theta->answer, "%lf", &theta); if (parm.scalex->answer) { sscanf(parm.scalex->answer, "%lf", &scalex); if (!parm.theta->answer) G_fatal_error(_("Using anisotropy - both theta and scalex have to be specified")); } if (parm.rsm->answer) { sscanf(parm.rsm->answer, "%lf", &rsm); if (rsm < 0.0) G_fatal_error("Smoothing must be a positive value"); if (scol != NULL) G_warning(_("Both smatt and smooth options specified - using constant")); } else { sscanf(SMOOTH, "%lf", &rsm); if (scol != NULL) rsm = -1; /* used in InterpLib to indicate variable smoothing */ } if (npmin > MAXPOINTS - 50) { G_warning(_("The computation will last too long - lower npmin is suggested")); KMAX2 = 2 * npmin; /* was: KMAX2 = npmin + 50; */ } else KMAX2 = 2 * npmin; /* was: KMAX2 = MAXPOINTS; fixed by JH in 12/01 */ /* handling of KMAX2 in GRASS4 v.surf.rst if (npmin > MAXPOINTS - 50) KMAX2 = npmin + 50; else KMAX2 = MAXPOINTS; */ dmin = dmin * dmin; KMIN = npmin; az = G_alloc_vector(n_cols + 1); if (!az) { G_fatal_error(_("Not enough memory for %s"), "az"); } if (cond1) { adx = G_alloc_vector(n_cols + 1); if (!adx) { G_fatal_error(_("Not enough memory for %s"), "adx"); } ady = G_alloc_vector(n_cols + 1); if (!ady) { G_fatal_error(_("Not enough memory for %s"), "ady"); } if (cond2) { adxx = G_alloc_vector(n_cols + 1); if (!adxx) { G_fatal_error(_("Not enough memory for %s"), "adxx"); } adyy = G_alloc_vector(n_cols + 1); if (!adyy) { G_fatal_error(_("Not enough memory for %s"), "adyy"); } adxy = G_alloc_vector(n_cols + 1); if (!adxy) { G_fatal_error(_("Not enough memory for %s"), "adxy"); } } } if ((data = quad_data_new(x_orig, y_orig, xm, ym, n_rows, n_cols, 0, KMAX)) == NULL) G_fatal_error(_("Unable to create %s"), "quaddata"); if ((functions = MT_functions_new(quad_compare, quad_divide_data, quad_add_data, quad_intersect, quad_division_check, quad_get_points)) == NULL) G_fatal_error(_("Unable to create %s"), "quadfunc"); if ((tree = MT_tree_new(data, NULL, NULL, 0)) == NULL) G_fatal_error(_("Unable to create %s"), "tree"); root = tree; if ((info = MT_tree_info_new(root, functions, dmin, KMAX)) == NULL) G_fatal_error(_("Unable to create %s"), "tree info"); open_check = Vect_open_old2(&Map, input, "", parm.field->answer); if (open_check < 1) G_fatal_error(_("Unable to open vector map <%s>"), input); /* if (open_check < 2) G_fatal_error(_("You first need to run v.build on vector map <%s>"), input); */ /* get value used for approximation */ with_z = !parm.zcol->answer && Vect_is_3d(&Map); field = Vect_get_field_number(&Map, parm.field->answer); if (!with_z && field < 1) G_fatal_error(_("Layer <%s> not found"), parm.field->answer); if (Vect_is_3d(&Map)) { if (!with_z) G_verbose_message(_("Input is 3D: using attribute values instead of z-coordinates for approximation")); else G_verbose_message(_("Input is 3D: using z-coordinates for approximation")); } else { /* 2D */ if (parm.zcol->answer) G_verbose_message(_("Input is 2D: using attribute values for approximation")); else G_verbose_message(_("Input is 2D: using category values for approximation")); } /* we can't read the input file's timestamp as they don't exist in */ /* the new vector format. Even so, a TimeStamp structure is needed */ /* for IL_init_params_2d(), so we set it to NULL. */ /* If anyone is ever motivated to add it, the Plus_head struct has */ /* 'long coor_mtime' and dig_head has 'char *date; char *source_date;' */ /* which could be read in. */ if (devi != NULL || cvdev != NULL) { Pnts = Vect_new_line_struct(); Cats2 = Vect_new_cats_struct(); db_init_string(&sql2); if (devi != NULL) { if (Vect_open_new(&Map2, devi, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), devi); } else { if (Vect_open_new(&Map2, cvdev, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), cvdev); } Vect_hist_command(&Map2); ff = Vect_default_field_info(&Map2, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map2, 1, NULL, ff->table, GV_KEY_COLUMN, ff->database, ff->driver); /* Create new table */ db_zero_string(&sql2); sprintf(buf, "create table %s ( ", ff->table); db_append_string(&sql2, buf); db_append_string(&sql2, "cat integer"); db_append_string(&sql2, ", flt1 double precision"); db_append_string(&sql2, ")"); G_debug(1, "%s", db_get_string(&sql2)); driver2 = db_start_driver_open_database(ff->driver, ff->database); if (driver2 == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), ff->database, ff->driver); db_set_error_handler_driver(driver2); if (db_execute_immediate(driver2, &sql2) != DB_OK) { G_fatal_error(_("Unable to create table '%s'"), db_get_string(&sql2)); } db_begin_transaction(driver2); count = 1; } ertot = 0.; create_temp_files(); IL_init_params_2d(¶ms, NULL, 1, 1, zmult, KMIN, KMAX, maskmap, n_rows, n_cols, az, adx, ady, adxx, adyy, adxy, fi, KMAX2, SCIK1, SCIK2, SCIK3, rsm, elev, slope, aspect, pcurv, tcurv, mcurv, dmin, x_orig, y_orig, deriv, theta, scalex, Tmp_fd_z, Tmp_fd_dx, Tmp_fd_dy, Tmp_fd_xx, Tmp_fd_yy, Tmp_fd_xy, devi, NULL, cv, parm.wheresql->answer); IL_init_func_2d(¶ms, IL_grid_calc_2d, IL_matrix_create, IL_check_at_points_2d, IL_secpar_loop_2d, IL_crst, IL_crstg, IL_write_temp_2d); totsegm = IL_vector_input_data_2d(¶ms, &Map, with_z ? 0 : field, zcol, scol, info, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax, &NPOINT, &dmax); if (totsegm <= 0) { clean(); G_fatal_error(_("Input failed")); } /*Vect_set_release_support(&Map); */ Vect_close(&Map); if (treefile != NULL) { if (0 > Vect_open_new(&TreeMap, treefile, 0)) { clean(); G_fatal_error(_("Unable to open vector map <%s>"), treefile); } Vect_hist_command(&TreeMap); /* sprintf (TreeMap.head.your_name, "grass"); sprintf (TreeMap.head.map_name, "Quad tree for %s", input); TreeMap.head.orig_scale = 100000; TreeMap.head.plani_zone = G_zone (); */ print_tree(root, x_orig, y_orig, &TreeMap); Vect_build(&TreeMap); Vect_close(&TreeMap); } disk = disk + totsegm * sizeof(int) * 4; sdisk = sdisk + totsegm * sizeof(int) * 4; if (elev != NULL) ddisk += disk; if (slope != NULL) sddisk += sdisk; if (aspect != NULL) sddisk += sdisk; if (pcurv != NULL) ddisk += disk; if (tcurv != NULL) ddisk += disk; if (mcurv != NULL) ddisk += disk; ddisk += sddisk; G_verbose_message(_("Processing all selected output files " "will require %d bytes of disk space for temp files"), ddisk); deltx = xmax - xmin; delty = ymax - ymin; dnorm = sqrt((deltx * delty * KMIN) / NPOINT); if (dtens) { params.fi = params.fi * dnorm / 1000.; G_verbose_message("dnorm = %f, rescaled tension = %f", dnorm, params.fi); } bitmask = IL_create_bitmask(¶ms); if (totsegm <= 0) { clean(); G_fatal_error(_("Input failed")); } ertot = 0.; G_message(_("Processing segments...")); if (IL_interp_segments_2d(¶ms, info, info->root, bitmask, zmin, zmax, &zminac, &zmaxac, &gmin, &gmax, &c1min, &c1max, &c2min, &c2max, &ertot, totsegm, n_cols, dnorm) < 0) { clean(); G_fatal_error(_("Interp_segmets failed")); } G_free_vector(az); if (cond1) { G_free_vector(adx); G_free_vector(ady); if (cond2) { G_free_vector(adxx); G_free_vector(adyy); G_free_vector(adxy); } } ii = IL_output_2d(¶ms, &cellhd, zmin, zmax, zminac, zmaxac, c1min, c1max, c2min, c2max, gmin, gmax, ertot, input, dnorm, dtens, 1, NPOINT); if (ii < 0) { clean(); G_fatal_error(_("Unable to write raster maps - try to increase resolution")); } G_free(zero_array_cell); if (elev != NULL) fclose(Tmp_fd_z); if (slope != NULL) fclose(Tmp_fd_dx); if (aspect != NULL) fclose(Tmp_fd_dy); if (pcurv != NULL) fclose(Tmp_fd_xx); if (tcurv != NULL) fclose(Tmp_fd_yy); if (mcurv != NULL) fclose(Tmp_fd_xy); if (overfile != NULL) { if (0 > Vect_open_new(&OverMap, overfile, 0)) { clean(); G_fatal_error(_("Unable to create vector map <%s>"), overfile); } Vect_hist_command(&OverMap); /* sprintf (OverMap.head.your_name, "grass"); sprintf (OverMap.head.map_name, "Overlap segments for %s", input); OverMap.head.orig_scale = 100000; OverMap.head.plani_zone = G_zone (); */ print_tree(root, x_orig, y_orig, &OverMap); Vect_build(&OverMap); Vect_close(&OverMap); } if (elev != NULL) unlink(Tmp_file_z); if (slope != NULL) unlink(Tmp_file_dx); if (aspect != NULL) unlink(Tmp_file_dy); if (pcurv != NULL) unlink(Tmp_file_xx); if (tcurv != NULL) unlink(Tmp_file_yy); if (mcurv != NULL) unlink(Tmp_file_xy); if (cvdev != NULL || devi != NULL) { db_commit_transaction(driver2); db_close_database_shutdown_driver(driver2); Vect_build(&Map2); Vect_close(&Map2); } G_done_msg(" "); exit(EXIT_SUCCESS); }
/* * * Recursively processes each segment in a tree by: * * a) finding points from neighbouring segments so that the total number of * points is between KMIN and KMAX2 by calling tree function MT_get_region(). * * b) creating and solving the system of linear equations using these points * and interp() by calling matrix_create() and G_ludcmp(). * * c) checking the interpolating function values at points by calling * check_points(). * * d) computing grid for this segment using points and interp() by calling * grid_calc(). * */ int IL_interp_segments_2d(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, 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) { double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1, temp2; int i, npt, nptprev, MAXENC; struct quaddata *data; static int cursegm = 0; static double *b = NULL; static int *indx = NULL; static double **matrix = NULL; double ew_res, ns_res; static int first_time = 1; static double smseg; int MINPTS; double pr; struct triple *point; struct triple skip_point; int m_skip, skip_index, j, k, segtest; double xx, yy, zz; /* find the size of the smallest segment once */ if (first_time) { smseg = smallest_segment(info->root, 4); first_time = 0; } ns_res = (((struct quaddata *)(info->root->data))->ymax - ((struct quaddata *)(info->root->data))->y_orig) / params->nsizr; ew_res = (((struct quaddata *)(info->root->data))->xmax - ((struct quaddata *)(info->root->data))->x_orig) / params->nsizc; if (tree == NULL) return -1; if (tree->data == NULL) return -1; if (((struct quaddata *)(tree->data))->points == NULL) { for (i = 0; i < 4; i++) { IL_interp_segments_2d(params, info, tree->leafs[i], bitmask, zmin, zmax, zminac, zmaxac, gmin, gmax, c1min, c1max, c2min, c2max, ertot, totsegm, offset1, dnorm); } return 1; } else { distx = (((struct quaddata *)(tree->data))->n_cols * ew_res) * 0.1; disty = (((struct quaddata *)(tree->data))->n_rows * ns_res) * 0.1; distxp = 0; distyp = 0; xmn = ((struct quaddata *)(tree->data))->x_orig; xmx = ((struct quaddata *)(tree->data))->xmax; ymn = ((struct quaddata *)(tree->data))->y_orig; ymx = ((struct quaddata *)(tree->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 = (struct quaddata *)quad_data_new(xmn - distx, ymn - disty, xmx + distx, ymx + disty, 0, 0, 0, params->KMAX2); npt = MT_region_data(info, info->root, data, 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->x_orig = xmn - distx; /* update window */ data->y_orig = ymn - disty; data->xmax = xmx + distx; data->ymax = ymx + disty; data->n_points = 0; npt = MT_region_data(info, info->root, data, params->KMAX2, 4); } if (totsegm != 0) { G_percent(cursegm, totsegm, 1); } data->n_rows = ((struct quaddata *)(tree->data))->n_rows; data->n_cols = ((struct quaddata *)(tree->data))->n_cols; /* for printing out overlapping segments */ ((struct quaddata *)(tree->data))->x_orig = xmn - distx; ((struct quaddata *)(tree->data))->y_orig = ymn - disty; ((struct quaddata *)(tree->data))->xmax = xmx + distx; ((struct quaddata *)(tree->data))->ymax = ymx + disty; data->x_orig = xmn; data->y_orig = ymn; data->xmax = xmx; data->ymax = ymx; if (!matrix) { if (! (matrix = G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) { G_warning(_("Out of memory")); return -1; } } if (!indx) { if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) { G_warning(_("Out of memory")); return -1; } } if (!b) { if (!(b = G_alloc_vector(params->KMAX2 + 3))) { G_warning(_("Out of memory")); return -1; } } /* allocate memory for CV points only if cv is performed */ if (params->cv) { if (! (point = (struct triple *)G_malloc(sizeof(struct triple) * data->n_points))) { G_warning(_("Out of memory")); return -1; } } /*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->n_points; i++) { data->points[i].x = (data->points[i].x - data->x_orig) / dnorm; data->points[i].y = (data->points[i].y - data->y_orig) / dnorm; if (params->cv) { point[i].x = data->points[i].x; /*cv stuff */ point[i].y = data->points[i].y; /*cv stuff */ point[i].z = data->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->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.; /*** TODO: parallelize this loop instead of the LU solver! ***/ for (skip_index = 0; skip_index < m_skip; skip_index++) { if (params->cv) { segtest = 0; j = 0; xx = point[skip_index].x * dnorm + data->x_orig + params->x_orig; yy = point[skip_index].y * dnorm + data->y_orig + params->y_orig; zz = point[skip_index].z; if (xx >= data->x_orig + params->x_orig && xx <= data->xmax + params->x_orig && yy >= data->y_orig + params->y_orig && yy <= data->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->points[j].x = point[k].x; data->points[j].y = point[k].y; data->points[j].z = point[k].z; j++; } } } /* segment area test */ } if (!params->cv) { if (params-> matrix_create(params, data->points, data->n_points, matrix, indx) < 0) return -1; } else if (segtest == 1) { if (params-> matrix_create(params, data->points, data->n_points - 1, matrix, indx) < 0) return -1; } if (!params->cv) { for (i = 0; i < data->n_points; i++) b[i + 1] = data->points[i].z; b[0] = 0.; G_lubksb(matrix, data->n_points + 1, indx, b); /* put here condition to skip error if not needed */ params->check_points(params, data, b, ertot, zmin, dnorm, skip_point); } else if (segtest == 1) { for (i = 0; i < data->n_points - 1; i++) b[i + 1] = data->points[i].z; b[0] = 0.; G_lubksb(matrix, data->n_points, indx, b); params->check_points(params, data, b, 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)) { if (params->grid_calc(params, data, bitmask, zmin, zmax, zminac, zmaxac, gmin, gmax, c1min, c1max, c2min, c2max, ertot, b, offset1, dnorm) < 0) return -1; } /* show after to catch 100% */ cursegm++; if (totsegm < cursegm) G_debug(1, "%d %d", totsegm, cursegm); if (totsegm != 0) { G_percent(cursegm, totsegm, 1); } /* G_free_matrix(matrix); G_free_ivector(indx); G_free_vector(b); */ G_free(data->points); G_free(data); } return 1; }