예제 #1
0
파일: main.c 프로젝트: rashadkm/grass_cmake
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(&params, 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(&params, 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(&params, &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(&params);
    
    if (totsegm <= 0) {
	clean();
	G_fatal_error(_("Input failed"));
    }

    ertot = 0.;
    G_message(_("Processing segments..."));    
    if (IL_interp_segments_2d(&params, 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(&params, &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);
}
예제 #2
0
int IL_resample_interp_segments_2d(struct interp_params *params, 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 */
				   off_t offset1,	/* offset for temp file writing */
				   double *dnorm,
				   int overlap,
				   int inp_rows,
				   int inp_cols,
				   int fdsmooth,
				   int fdinp,
				   double ns_res,
				   double ew_res,
				   double inp_ns_res,
				   double inp_ew_res, int dtens)
{

    int i, j, k, l, m, m1, i1;	/* loop coounters */
    int cursegm = 0;
    int new_comp = 0;
    int n_rows, n_cols, inp_r, inp_c;
    double x_or, y_or, xm, ym;
    static int first = 1, new_first = 1;
    double **matrix = NULL, **new_matrix = NULL, *b = NULL;
    int *indx = NULL, *new_indx = NULL;
    static struct fcell_triple *in_points = NULL;	/* input points */
    int inp_check_rows, inp_check_cols,	/* total input rows/cols */
      out_check_rows, out_check_cols;	/* total output rows/cols */
    int first_row, last_row;	/* first and last input row of segment */
    int first_col, last_col;	/* first and last input col of segment */
    int num, prev;
    int div;			/* number of divides */
    int rem_out_row, rem_out_col;	/* output rows/cols remainders */
    int inp_seg_r, inp_seg_c,	/* # of input rows/cols in segment */
      out_seg_r, out_seg_c;	/* # of output rows/cols in segment */
    int ngstc, nszc		/* first and last output col of the
				 * segment */
     , ngstr, nszr;		/* first and last output row of the
				 * segment */
    int index;			/* index for input data */
    int c, r;
    int overlap1;
    int p_size;
    struct quaddata *data;
    double xmax, xmin, ymax, ymin;
    int totsegm;		/* total number of segments */
    int total_points = 0;
    struct triple triple;	/* contains garbage */


    xmin = params->x_orig;
    ymin = params->y_orig;
    xmax = xmin + ew_res * params->nsizc;
    ymax = ymin + ns_res * params->nsizr;
    prev = inp_rows * inp_cols;
    if (prev <= params->kmax)
	div = 1;		/* no segmentation */

    else {			/* find the number of divides */
	for (i = 2;; i++) {
	    c = inp_cols / i;
	    r = inp_rows / i;
	    num = c * r;
	    if (num < params->kmin) {
		if (((params->kmin - num) > (prev + 1 - params->kmax)) &&
		    (prev + 1 < params->KMAX2)) {
		    div = i - 1;
		    break;
		}
		else {
		    div = i;
		    break;
		}
	    }
	    if ((num > params->kmin) && (num + 1 < params->kmax)) {
		div = i;
		break;
	    }
	    prev = num;
	}
    }
    out_seg_r = params->nsizr / div;	/* output rows per segment */
    out_seg_c = params->nsizc / div;	/* output cols per segment */
    inp_seg_r = inp_rows / div;	/* input rows per segment */
    inp_seg_c = inp_cols / div;	/* input rows per segment */
    rem_out_col = params->nsizc % div;
    rem_out_row = params->nsizr % div;
    overlap1 = min1(overlap, inp_seg_c - 1);
    overlap1 = min1(overlap1, inp_seg_r - 1);
    out_check_rows = 0;
    out_check_cols = 0;
    inp_check_rows = 0;
    inp_check_cols = 0;

    if (div == 1) {
	p_size = inp_seg_c * inp_seg_r;
    }
    else {
	p_size = (overlap1 * 2 + inp_seg_c) * (overlap1 * 2 + inp_seg_r);
    }
    if (!in_points) {
	if (!
	    (in_points =
	     (struct fcell_triple *)G_malloc(sizeof(struct fcell_triple) *
					     p_size * div))) {
	    fprintf(stderr, "Cannot allocate memory for in_points\n");
	    return -1;
	}
    }

    *dnorm =
	sqrt(((xmax - xmin) * (ymax -
			       ymin) * p_size) / (inp_rows * inp_cols));

    if (dtens) {
	params->fi = params->fi * (*dnorm) / 1000.;
	fprintf(stderr, "dnorm = %f, rescaled tension = %f\n", *dnorm,
		params->fi);
    }

    if (div == 1) {		/* no segmentation */
	totsegm = 1;
	cursegm = 1;

	input_data(params, 1, inp_rows, in_points, fdsmooth, fdinp, inp_rows,
		   inp_cols, zmin, inp_ns_res, inp_ew_res);

	x_or = 0.;
	y_or = 0.;
	xm = params->nsizc * ew_res;
	ym = params->nsizr * ns_res;

	data = (struct quaddata *)quad_data_new(x_or, y_or, xm, ym,
						params->nsizr, params->nsizc,
						0, params->KMAX2);
	m1 = 0;
	for (k = 1; k <= p_size; k++) {
	    if (!Rast_is_f_null_value(&(in_points[k - 1].z))) {
		data->points[m1].x = in_points[k - 1].x / (*dnorm);
		data->points[m1].y = in_points[k - 1].y / (*dnorm);
		/*        data->points[m1].z = (double) (in_points[k - 1].z) / (*dnorm); */
		data->points[m1].z = (double)(in_points[k - 1].z);
		data->points[m1].sm = in_points[k - 1].smooth;
		m1++;
	    }
	}
	data->n_points = m1;
	total_points = m1;
	if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
	    fprintf(stderr, "Cannot allocate memory for indx\n");
	    return -1;
	}
	if (!(matrix = G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
	    fprintf(stderr, "Cannot allocate memory for matrix\n");
	    return -1;
	}
	if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
	    fprintf(stderr, "Cannot allocate memory for b\n");
	    return -1;
	}

	if (params->matrix_create(params, data->points, m1, matrix, indx) < 0)
	    return -1;
	for (i = 0; i < m1; i++) {
	    b[i + 1] = data->points[i].z;
	}
	b[0] = 0.;
	G_lubksb(matrix, m1 + 1, indx, b);

	params->check_points(params, data, b, ertot, zmin, *dnorm, triple);

	if (params->grid_calc(params, data, bitmask,
			      zmin, zmax, zminac, zmaxac, gmin, gmax,
			      c1min, c1max, c2min, c2max, ertot, b, offset1,
			      *dnorm) < 0) {
	    fprintf(stderr, "interpolation failed\n");
	    return -1;
	}
	else {
	    if (totsegm != 0) {
		G_percent(cursegm, totsegm, 1);
	    }
	    /*
	     * if (b) G_free_vector(b); if (matrix) G_free_matrix(matrix); if
	     * (indx) G_free_ivector(indx);
	     */
	    fprintf(stderr, "dnorm in ressegm after grid before out= %f \n",
		    *dnorm);
	    return total_points;
	}
    }

    out_seg_r = params->nsizr / div;	/* output rows per segment */
    out_seg_c = params->nsizc / div;	/* output cols per segment */
    inp_seg_r = inp_rows / div;	/* input rows per segment */
    inp_seg_c = inp_cols / div;	/* input rows per segment */
    rem_out_col = params->nsizc % div;
    rem_out_row = params->nsizr % div;
    overlap1 = min1(overlap, inp_seg_c - 1);
    overlap1 = min1(overlap1, inp_seg_r - 1);
    out_check_rows = 0;
    out_check_cols = 0;
    inp_check_rows = 0;
    inp_check_cols = 0;

    totsegm = div * div;

    /* set up a segment */
    for (i = 1; i <= div; i++) {	/* input and output rows */
	if (i <= div - rem_out_row)
	    n_rows = out_seg_r;
	else
	    n_rows = out_seg_r + 1;
	inp_r = inp_seg_r;
	out_check_cols = 0;
	inp_check_cols = 0;
	ngstr = out_check_rows + 1;	/* first output row of the segment */
	nszr = ngstr + n_rows - 1;	/* last output row of the segment */
	y_or = (ngstr - 1) * ns_res;	/* y origin of the segment */
	/*
	 * Calculating input starting and ending rows and columns of this
	 * segment
	 */
	first_row = (int)(y_or / inp_ns_res) + 1;
	if (first_row > overlap1) {
	    first_row -= overlap1;	/* middle */
	    last_row = first_row + inp_seg_r + overlap1 * 2 - 1;
	    if (last_row > inp_rows) {
		first_row -= (last_row - inp_rows);	/* bottom */
		last_row = inp_rows;
	    }
	}
	else {
	    first_row = 1;	/* top */
	    last_row = first_row + inp_seg_r + overlap1 * 2 - 1;
	}
	if ((last_row > inp_rows) || (first_row < 1)) {
	    fprintf(stderr, "Row overlap too large!\n");
	    return -1;
	}
	input_data(params, first_row, last_row, in_points, fdsmooth, fdinp,
		   inp_rows, inp_cols, zmin, inp_ns_res, inp_ew_res);

	for (j = 1; j <= div; j++) {	/* input and output cols */
	    if (j <= div - rem_out_col)
		n_cols = out_seg_c;
	    else
		n_cols = out_seg_c + 1;
	    inp_c = inp_seg_c;

	    ngstc = out_check_cols + 1;	/* first output col of the segment */
	    nszc = ngstc + n_cols - 1;	/* last output col of the segment */
	    x_or = (ngstc - 1) * ew_res;	/* x origin of the segment */

	    first_col = (int)(x_or / inp_ew_res) + 1;
	    if (first_col > overlap1) {
		first_col -= overlap1;	/* middle */
		last_col = first_col + inp_seg_c + overlap1 * 2 - 1;
		if (last_col > inp_cols) {
		    first_col -= (last_col - inp_cols);	/* right */
		    last_col = inp_cols;
		}
	    }
	    else {
		first_col = 1;	/* left */
		last_col = first_col + inp_seg_c + overlap1 * 2 - 1;
	    }
	    if ((last_col > inp_cols) || (first_col < 1)) {
		fprintf(stderr, "Column overlap too large!\n");
		return -1;
	    }
	    m = 0;
	    /* Getting points for interpolation (translated) */

	    xm = nszc * ew_res;
	    ym = nszr * ns_res;
	    data = (struct quaddata *)quad_data_new(x_or, y_or, xm, ym,
						    nszr - ngstr + 1,
						    nszc - ngstc + 1, 0,
						    params->KMAX2);
	    new_comp = 0;

	    for (k = 0; k <= last_row - first_row; k++) {
		for (l = first_col - 1; l < last_col; l++) {
		    index = k * inp_cols + l;
		    if (!Rast_is_f_null_value(&(in_points[index].z))) {
			/* if the point is inside the segment (not overlapping) */
			if ((in_points[index].x - x_or >= 0) &&
			    (in_points[index].y - y_or >= 0) &&
			    ((nszc - 1) * ew_res - in_points[index].x >= 0) &&
			    ((nszr - 1) * ns_res - in_points[index].y >= 0))
			    total_points += 1;
			data->points[m].x =
			    (in_points[index].x - x_or) / (*dnorm);
			data->points[m].y =
			    (in_points[index].y - y_or) / (*dnorm);
			/*            data->points[m].z = (double) (in_points[index].z) / (*dnorm); */
			data->points[m].z = (double)(in_points[index].z);
			data->points[m].sm = in_points[index].smooth;
			m++;
		    }
		    else
			new_comp = 1;

		    /*          fprintf(stderr,"%f,%f,%f
		       zmin=%f\n",in_points[index].x,in_points[index].y,in_points[index].z,zmin);
		     */
		}
	    }
	    /*      fprintf (stdout,"m,index:%di,%d\n",m,index); */
	    if (m <= params->KMAX2)
		data->n_points = m;
	    else
		data->n_points = params->KMAX2;
	    out_check_cols += n_cols;
	    inp_check_cols += inp_c;
	    cursegm = (i - 1) * div + j - 1;

	    /* show before to catch 0% */
	    if (totsegm != 0) {
		G_percent(cursegm, totsegm, 1);
	    }
	    if (m == 0) {
		/*
		 * fprintf(stderr,"Warning: segment with zero points encountered,
		 * insrease overlap\n");
		 */
		write_zeros(params, data, offset1);
	    }
	    else {
		if (new_comp) {
		    if (new_first) {
			new_first = 0;
			if (!b) {
			    if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
				fprintf(stderr,
					"Cannot allocate memory for b\n");
				return -1;
			    }
			}
			if (!(new_indx = G_alloc_ivector(params->KMAX2 + 1))) {
			    fprintf(stderr,
				    "Cannot allocate memory for new_indx\n");
			    return -1;
			}
			if (!
			    (new_matrix =
			     G_alloc_matrix(params->KMAX2 + 1,
					    params->KMAX2 + 1))) {
			    fprintf(stderr,
				    "Cannot allocate memory for new_matrix\n");
			    return -1;
			}
		    }		/*new_first */
		    if (params->
			matrix_create(params, data->points, data->n_points,
				      new_matrix, new_indx) < 0)
			return -1;

		    for (i1 = 0; i1 < m; i1++) {
			b[i1 + 1] = data->points[i1].z;
		    }
		    b[0] = 0.;
		    G_lubksb(new_matrix, data->n_points + 1, new_indx, b);

		    params->check_points(params, data, b, ertot, zmin,
					 *dnorm, triple);

		    if (params->grid_calc(params, data, bitmask,
					  zmin, zmax, zminac, zmaxac, gmin,
					  gmax, c1min, c1max, c2min, c2max,
					  ertot, b, offset1, *dnorm) < 0) {

			fprintf(stderr, "interpolate() failed\n");
			return -1;
		    }
		}		/*new_comp */
		else {
		    if (first) {
			first = 0;
			if (!b) {
			    if (!(b = G_alloc_vector(params->KMAX2 + 2))) {
				fprintf(stderr,
					"Cannot allocate memory for b\n");
				return -1;
			    }
			}
			if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
			    fprintf(stderr,
				    "Cannot allocate memory for indx\n");
			    return -1;
			}
			if (!
			    (matrix =
			     G_alloc_matrix(params->KMAX2 + 1,
					    params->KMAX2 + 1))) {
			    fprintf(stderr,
				    "Cannot allocate memory for matrix\n");
			    return -1;
			}
		    }		/* first */
		    if (params->
			matrix_create(params, data->points, data->n_points,
				      matrix, indx) < 0)
			return -1;
		    /*        } here it was bug */
		    for (i1 = 0; i1 < m; i1++)
			b[i1 + 1] = data->points[i1].z;
		    b[0] = 0.;
		    G_lubksb(matrix, data->n_points + 1, indx, b);

		    params->check_points(params, data, b, ertot, zmin,
					 *dnorm, triple);

		    if (params->grid_calc(params, data, bitmask,
					  zmin, zmax, zminac, zmaxac, gmin,
					  gmax, c1min, c1max, c2min, c2max,
					  ertot, b, offset1, *dnorm) < 0) {

			fprintf(stderr, "interpolate() failed\n");
			return -1;
		    }
		}
	    }
	    if (data) {
		G_free(data->points);
		G_free(data);
	    }
	    /*
	     * cursegm++;
	     */
	}

	inp_check_rows += inp_r;
	out_check_rows += n_rows;
    }

    /* run one last time after the loop is done to catch 100% */
    if (totsegm != 0)
	G_percent(1, 1, 1);	/* cursegm doesn't get to totsegm so we force 100% */

    /*
     * if (b) G_free_vector(b); if (indx) G_free_ivector(indx); if (matrix)
     * G_free_matrix(matrix);
     */
    fprintf(stderr, "dnorm in ressegm after grid before out2= %f \n", *dnorm);
    return total_points;
}
예제 #3
0
파일: segmen2d.c 프로젝트: caomw/grass
/*
 *
 *  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;
}