コード例 #1
0
ファイル: main.c プロジェクト: GRASS-GIS/grass-ci
int main(int argc, char *argv[])
{
    int i, type, stat;
    int day, yr, Out_proj;
    int out_zone = 0;
    int overwrite;		/* overwrite output map */
    const char *mapset;
    const char *omap_name, *map_name, *iset_name, *iloc_name;
    struct pj_info info_in;
    struct pj_info info_out;
    const char *gbase;
    char date[40], mon[4];
    struct GModule *module;
    struct Option *omapopt, *mapopt, *isetopt, *ilocopt, *ibaseopt, *smax;
    struct Key_Value *in_proj_keys, *in_unit_keys;
    struct Key_Value *out_proj_keys, *out_unit_keys;
    struct line_pnts *Points, *Points2;
    struct line_cats *Cats;
    struct Map_info Map;
    struct Map_info Out_Map;
    struct bound_box src_box, tgt_box;
    int nowrap = 0, recommend_nowrap = 0;
    double lmax;
    struct
    {
	struct Flag *list;	/* list files in source location */
	struct Flag *transformz;	/* treat z as ellipsoidal height */
	struct Flag *wrap;		/* latlon output: wrap to 0,360 */
	struct Flag *no_topol;		/* do not build topology */
    } flag;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("projection"));
    G_add_keyword(_("transformation"));
    G_add_keyword(_("import"));
    module->description = _("Re-projects a vector map from one location to the current location.");

    /* set up the options and flags for the command line parser */

    ilocopt = G_define_standard_option(G_OPT_M_LOCATION);
    ilocopt->required = YES;
    ilocopt->label = _("Location containing input vector map");
    ilocopt->guisection = _("Source");
    
    isetopt = G_define_standard_option(G_OPT_M_MAPSET);
    isetopt->label = _("Mapset containing input vector map");
    isetopt->description = _("Default: name of current mapset");
    isetopt->guisection = _("Source");

    mapopt = G_define_standard_option(G_OPT_V_INPUT);
    mapopt->required = NO;
    mapopt->label = _("Name of input vector map to re-project");
    mapopt->description = NULL;
    mapopt->guisection = _("Source");
    
    ibaseopt = G_define_standard_option(G_OPT_M_DBASE);
    ibaseopt->label = _("Path to GRASS database of input location");
    
    smax = G_define_option();
    smax->key = "smax";
    smax->type = TYPE_DOUBLE;
    smax->required = NO;
    smax->answer = "10000";
    smax->label = _("Maximum segment length in meters in output vector map");
    smax->description = _("Increases accuracy of reprojected shapes, disable with smax=0");
    smax->guisection = _("Target");

    omapopt = G_define_standard_option(G_OPT_V_OUTPUT);
    omapopt->required = NO;
    omapopt->description = _("Name for output vector map (default: input)");
    omapopt->guisection = _("Target");

    flag.list = G_define_flag();
    flag.list->key = 'l';
    flag.list->description = _("List vector maps in input mapset and exit");

    flag.transformz = G_define_flag();
    flag.transformz->key = 'z';
    flag.transformz->description = _("3D vector maps only");
    flag.transformz->label =
	_("Assume z coordinate is ellipsoidal height and "
	  "transform if possible");
    flag.transformz->guisection = _("Target");

    flag.wrap = G_define_flag();
    flag.wrap->key = 'w';
    flag.wrap->description = _("Latlon output only, default is -180,180");
    flag.wrap->label =
	_("Disable wrapping to -180,180 for latlon output");
    flag.transformz->guisection = _("Target");

    flag.no_topol = G_define_flag();
    flag.no_topol->key = 'b';
    flag.no_topol->label = _("Do not build vector topology");
    flag.no_topol->description = _("Recommended for massive point projection");

    /* The parser checks if the map already exists in current mapset,
       we switch out the check and do it
       in the module after the parser */
    overwrite = G_check_overwrite(argc, argv);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    /* start checking options and flags */
    /* set input vector map name and mapset */
    map_name = mapopt->answer;
    if (omapopt->answer)
	omap_name = omapopt->answer;
    else
	omap_name = map_name;
    if (omap_name && !flag.list->answer && !overwrite &&
	G_find_vector2(omap_name, G_mapset()))
	G_fatal_error(_("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"), omapopt->key,
		      omap_name);
    if (isetopt->answer)
	iset_name = isetopt->answer;
    else
	iset_name = G_store(G_mapset());

    iloc_name = ilocopt->answer;

    if (ibaseopt->answer)
	gbase = ibaseopt->answer;
    else
	gbase = G_store(G_gisdbase());

    if (!ibaseopt->answer && strcmp(iloc_name, G_location()) == 0)
	G_fatal_error(_("Input and output locations can not be the same"));

    lmax = atof(smax->answer);
    if (lmax < 0)
	lmax = 0;

    Out_proj = G_projection();
    if (Out_proj == PROJECTION_LL && flag.wrap->answer)
	nowrap = 1;
    
    G_begin_distance_calculations();

    /* Change the location here and then come back */

    select_target_env();
    G_setenv_nogisrc("GISDBASE", gbase);
    G_setenv_nogisrc("LOCATION_NAME", iloc_name);
    stat = G_mapset_permissions(iset_name);
    
    if (stat >= 0) {		/* yes, we can access the mapset */
	/* if requested, list the vector maps in source location - MN 5/2001 */
	if (flag.list->answer) {
	    int i;
	    char **list;
	    G_verbose_message(_("Checking location <%s> mapset <%s>"),
			      iloc_name, iset_name);
	    list = G_list(G_ELEMENT_VECTOR, G_getenv_nofatal("GISDBASE"),
			  G_getenv_nofatal("LOCATION_NAME"), iset_name);
	    if (list[0]) {
		for (i = 0; list[i]; i++) {
		    fprintf(stdout, "%s\n", list[i]);
		}
		fflush(stdout);
	    }
	    else {
		G_important_message(_("No vector maps found"));
	    }
	    exit(EXIT_SUCCESS);	/* leave v.proj after listing */
	}

	if (mapopt->answer == NULL) {
	    G_fatal_error(_("Required parameter <%s> not set"), mapopt->key);
	}

	G_setenv_nogisrc("MAPSET", iset_name);
	/* Make sure map is available */
	mapset = G_find_vector2(map_name, iset_name);
	if (mapset == NULL)
	    G_fatal_error(_("Vector map <%s> in location <%s> mapset <%s> not found"),
			  map_name, iloc_name, iset_name);

	 /*** Get projection info for input mapset ***/
	in_proj_keys = G_get_projinfo();
	if (in_proj_keys == NULL)
	    exit(EXIT_FAILURE);

	/* apparently the +over switch must be set in the input projection,
	 * not the output latlon projection */
	if (Out_proj == PROJECTION_LL && nowrap == 1)
	    G_set_key_value("+over", "defined", in_proj_keys);

	in_unit_keys = G_get_projunits();
	if (in_unit_keys == NULL)
	    exit(EXIT_FAILURE);

	if (pj_get_kv(&info_in, in_proj_keys, in_unit_keys) < 0)
	    exit(EXIT_FAILURE);

	Vect_set_open_level(1);
	G_debug(1, "Open old: location: %s mapset : %s", G_location_path(),
		G_mapset());
	if (Vect_open_old(&Map, map_name, mapset) < 0)
	    G_fatal_error(_("Unable to open vector map <%s>"), map_name);
    }
    else if (stat < 0)
    {				/* allow 0 (i.e. denied permission) */
	/* need to be able to read from others */
	if (stat == 0)
	    G_fatal_error(_("Mapset <%s> in input location <%s> - permission denied"),
			  iset_name, iloc_name);
	else
	    G_fatal_error(_("Mapset <%s> in input location <%s> not found"),
			  iset_name, iloc_name);
    }

    select_current_env();

    /****** get the output projection parameters ******/
    out_proj_keys = G_get_projinfo();
    if (out_proj_keys == NULL)
	exit(EXIT_FAILURE);

    out_unit_keys = G_get_projunits();
    if (out_unit_keys == NULL)
	exit(EXIT_FAILURE);

    if (pj_get_kv(&info_out, out_proj_keys, out_unit_keys) < 0)
	exit(EXIT_FAILURE);

    G_free_key_value(in_proj_keys);
    G_free_key_value(in_unit_keys);
    G_free_key_value(out_proj_keys);
    G_free_key_value(out_unit_keys);

    if (G_verbose() == G_verbose_max()) {
	pj_print_proj_params(&info_in, &info_out);
    }

    /* Initialize the Point / Cat structure */
    Points = Vect_new_line_struct();
    Points2 = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* test if latlon wrapping to -180,180 should be disabled */
    if (Out_proj == PROJECTION_LL && nowrap == 0) {
	int first = 1, counter = 0;
	double x, y;
	
	/* Cycle through all lines */
	Vect_rewind(&Map);
	while (1) {
	    type = Vect_read_next_line(&Map, Points, Cats);	/* read line */
	    if (type == 0)
		continue;		/* Dead */

	    if (type == -1)
		G_fatal_error(_("Reading input vector map"));
	    if (type == -2)
		break;
		
	    if (first && Points->n_points > 0) {
		first = 0;
		src_box.E = src_box.W = Points->x[0];
		src_box.N = src_box.S = Points->y[0];
		src_box.T = src_box.B = Points->z[0];
	    }
	    for (i = 0; i < Points->n_points; i++) {
		if (src_box.E < Points->x[i])
		    src_box.E = Points->x[i];
		if (src_box.W > Points->x[i])
		    src_box.W = Points->x[i];
		if (src_box.N < Points->y[i])
		    src_box.N = Points->y[i];
		if (src_box.S > Points->y[i])
		    src_box.S = Points->y[i];
	    }
	    counter++;
	}
	if (counter == 0) {
	    G_warning(_("Input vector map <%s> is empty"), omap_name);
	    exit(EXIT_SUCCESS);
	}
	/* NW corner */
	x = src_box.W;
	y = src_box.N;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	tgt_box.E = x;
	tgt_box.W = x;
	tgt_box.N = y;
	tgt_box.S = y;
	/* SW corner */
	x = src_box.W;
	y = src_box.S;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x)
	    tgt_box.W = x;
	if (tgt_box.E < x)
	    tgt_box.E = x;
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
	/* NE corner */
	x = src_box.E;
	y = src_box.N;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x) {
	    tgt_box.E = x + 360;
	    recommend_nowrap = 1;
	}
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
	/* SE corner */
	x = src_box.E;
	y = src_box.S;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x) {
	    if (tgt_box.E < x + 360)
		tgt_box.E = x + 360;
	    recommend_nowrap = 1;
	}
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
    }

    G_debug(1, "Open new: location: %s mapset : %s", G_location_path(),
	    G_mapset());

    if (Vect_open_new(&Out_Map, omap_name, Vect_is_3d(&Map)) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"), omap_name);

    Vect_set_error_handler_io(NULL, &Out_Map); /* register standard i/o error handler */
    
    Vect_copy_head_data(&Map, &Out_Map);
    Vect_hist_copy(&Map, &Out_Map);
    Vect_hist_command(&Out_Map);

    out_zone = info_out.zone;
    Vect_set_zone(&Out_Map, out_zone);

    /* Read and write header info */
    sprintf(date, "%s", G_date());
    sscanf(date, "%*s%s%d%*s%d", mon, &day, &yr);
    if (yr < 2000)
	yr = yr - 1900;
    else
	yr = yr - 2000;
    sprintf(date, "%s %d %d", mon, day, yr);
    Vect_set_date(&Out_Map, date);

    /* line densification works only with vector topology */
    if (Map.format != GV_FORMAT_NATIVE)
	lmax = 0;

    /* Cycle through all lines */
    Vect_rewind(&Map);
    i = 0;
    G_message(_("Reprojecting primitives ..."));
    while (TRUE) {
	++i;
	G_progress(i, 1e3);
	type = Vect_read_next_line(&Map, Points, Cats);	/* read line */
	if (type == 0)
	    continue;		/* Dead */

	if (type == -1)
	    G_fatal_error(_("Reading input vector map"));
	if (type == -2)
	    break;

	Vect_line_prune(Points);
	if (lmax > 0 && (type & GV_LINES) && Points->n_points > 1) {
	    double x1, y1, z1, x2, y2, z2;
	    double dx, dy, dz;
	    double l;
	    int i, n;

	    Vect_reset_line(Points2);
	    for (i = 0; i < Points->n_points - 1; i++) {
		x1 = Points->x[i];
		y1 = Points->y[i];
		z1 = Points->z[i];
		n = i + 1;
		x2 = Points->x[n];
		y2 = Points->y[n];
		z2 = Points->z[n];

		dx = x2 - x1;
		dy = y2 - y1;
		dz = z2 - z1;

		if (pj_do_transform(1, &x1, &y1,
				    flag.transformz->answer ? &z1 : NULL,
				    &info_in, &info_out) < 0) {
		  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
				Vect_get_full_name(&Map), ilocopt->answer);
		}

		if (pj_do_transform(1, &x2, &y2,
				    flag.transformz->answer ? &z2 : NULL,
				    &info_in, &info_out) < 0) {
		  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
				Vect_get_full_name(&Map), ilocopt->answer);
		}

		Vect_append_point(Points2, x1, y1, z1);

		l = G_distance(x1, y1, x2, y2);

		if (l > lmax) {
		    int j;
		    double x, y, z;

		    x1 = Points->x[i];
		    y1 = Points->y[i];
		    z1 = Points->z[i];

		    n = ceil(l / lmax);

		    for (j = 1; j < n; j++) {
			x = x1 + dx * j / n;
			y = y1 + dy * j / n;
			z = z1 + dz * j / n;

			if (pj_do_transform(1, &x, &y,
					    flag.transformz->answer ? &z : NULL,
					    &info_in, &info_out) < 0) {
			  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
					Vect_get_full_name(&Map), ilocopt->answer);
			}
			Vect_append_point(Points2, x, y, z);
		    }
		}
	    }
	    Vect_append_point(Points2, x2, y2, z2);
	    Vect_write_line(&Out_Map, type, Points2, Cats);	/* write line */
	}
	else {
	    if (pj_do_transform(Points->n_points, Points->x, Points->y,
				flag.transformz->answer ? Points->z : NULL,
				&info_in, &info_out) < 0) {
	      G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
			    Vect_get_full_name(&Map), ilocopt->answer);
	    }

	    Vect_write_line(&Out_Map, type, Points, Cats);	/* write line */
	}
    }				/* end lines section */
    G_progress(1, 1);

    /* Copy tables */
    if (Vect_copy_tables(&Map, &Out_Map, 0))
        G_warning(_("Failed to copy attribute table to output map"));

    Vect_close(&Map);

    if (!flag.no_topol->answer)
        Vect_build(&Out_Map);
    Vect_close(&Out_Map);

    if (recommend_nowrap)
	G_important_message(_("Try to disable wrapping to -180,180 "
			      "if topological errors occurred"));

    exit(EXIT_SUCCESS);
}
コード例 #2
0
ファイル: main.c プロジェクト: AsherBond/MondocosmOS
int main(int argc, char **argv)
{
    char *mapname,		/* ptr to name of output layer  */
     *setname,			/* ptr to name of input mapset  */
     *ipolname;			/* name of interpolation method */

    int fdi,			/* input map file descriptor    */
      fdo,			/* output map file descriptor   */
      method,			/* position of method in table  */
      permissions,		/* mapset permissions           */
      cell_type,		/* output celltype              */
      cell_size,		/* size of a cell in bytes      */
      row, col,			/* counters                     */
      irows, icols,		/* original rows, cols          */
      orows, ocols, have_colors,	/* Input map has a colour table */
      overwrite,		/* Overwrite                    */
      curr_proj;		/* output projection (see gis.h) */

    void *obuffer,		/* buffer that holds one output row     */
     *obufptr;			/* column ptr in output buffer  */
    struct cache *ibuffer;	/* buffer that holds the input map      */
    func interpolate;		/* interpolation routine        */

    double xcoord1, xcoord2,	/* temporary x coordinates      */
      ycoord1, ycoord2,		/* temporary y coordinates      */
      col_idx,			/* column index in input matrix */
      row_idx,			/* row index in input matrix    */
      onorth, osouth,		/* save original border coords  */
      oeast, owest, inorth, isouth, ieast, iwest;
    char north_str[30], south_str[30], east_str[30], west_str[30];

    struct Colors colr;		/* Input map colour table       */
    struct History history;

    struct pj_info iproj,	/* input map proj parameters    */
      oproj;			/* output map proj parameters   */

    struct Key_Value *in_proj_info,	/* projection information of    */
     *in_unit_info,		/* input and output mapsets     */
     *out_proj_info, *out_unit_info;

    struct GModule *module;

    struct Flag *list,		/* list files in source location */
     *nocrop,			/* don't crop output map        */
     *print_bounds,		/* print output bounds and exit */
     *gprint_bounds;		/* same but print shell style	*/

    struct Option *imapset,	/* name of input mapset         */
     *inmap,			/* name of input layer          */
     *inlocation,		/* name of input location       */
     *outmap,			/* name of output layer         */
     *indbase,			/* name of input database       */
     *interpol,			/* interpolation method:
				   nearest neighbor, bilinear, cubic */
     *memory,			/* amount of memory for cache   */
     *res;			/* resolution of target map     */
    struct Cell_head incellhd,	/* cell header of input map     */
      outcellhd;		/* and output map               */


    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("projection"));
    G_add_keyword(_("transformation"));
    module->description =
	_("Re-projects a raster map from given location to the current location.");

    inmap = G_define_standard_option(G_OPT_R_INPUT);
    inmap->description = _("Name of input raster map to re-project");
    inmap->required = NO;
    inmap->guisection = _("Source");

    inlocation = G_define_option();
    inlocation->key = "location";
    inlocation->type = TYPE_STRING;
    inlocation->required = YES;
    inlocation->description = _("Location containing input raster map");
    inlocation->gisprompt = "old,location,location";
    inlocation->key_desc = "name";

    imapset = G_define_standard_option(G_OPT_M_MAPSET);
    imapset->label = _("Mapset containing input raster map");
    imapset->description = _("default: name of current mapset");
    imapset->guisection = _("Source");

    indbase = G_define_option();
    indbase->key = "dbase";
    indbase->type = TYPE_STRING;
    indbase->required = NO;
    indbase->description = _("Path to GRASS database of input location");
    indbase->gisprompt = "old,dbase,dbase";
    indbase->key_desc = "path";
    indbase->guisection = _("Source");

    outmap = G_define_standard_option(G_OPT_R_OUTPUT);
    outmap->required = NO;
    outmap->description = _("Name for output raster map (default: same as 'input')");
    outmap->guisection = _("Target");

    ipolname = make_ipol_list();
    
    interpol = G_define_option();
    interpol->key = "method";
    interpol->type = TYPE_STRING;
    interpol->required = NO;
    interpol->answer = "nearest";
    interpol->options = ipolname;
    interpol->description = _("Interpolation method to use");
    interpol->guisection = _("Target");
    interpol->descriptions = make_ipol_desc();

    memory = G_define_option();
    memory->key = "memory";
    memory->type = TYPE_INTEGER;
    memory->required = NO;
    memory->description = _("Cache size (MiB)");

    res = G_define_option();
    res->key = "resolution";
    res->type = TYPE_DOUBLE;
    res->required = NO;
    res->description = _("Resolution of output raster map");
    res->guisection = _("Target");

    list = G_define_flag();
    list->key = 'l';
    list->description = _("List raster maps in input location and exit");

    nocrop = G_define_flag();
    nocrop->key = 'n';
    nocrop->description = _("Do not perform region cropping optimization");

    print_bounds = G_define_flag();
    print_bounds->key = 'p';
    print_bounds->description =
	_("Print input map's bounds in the current projection and exit");
    print_bounds->guisection = _("Target");
    
    gprint_bounds = G_define_flag();
    gprint_bounds->key = 'g';
    gprint_bounds->description =
	_("Print input map's bounds in the current projection and exit (shell style)");
    gprint_bounds->guisection = _("Target");

    /* The parser checks if the map already exists in current mapset,
       we switch out the check and do it
       in the module after the parser */
    overwrite = G_check_overwrite(argc, argv);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


    /* get the method */
    for (method = 0; (ipolname = menu[method].name); method++)
	if (strcmp(ipolname, interpol->answer) == 0)
	    break;

    if (!ipolname)
	G_fatal_error(_("<%s=%s> unknown %s"),
		      interpol->key, interpol->answer, interpol->key);
    interpolate = menu[method].method;

    mapname = outmap->answer ? outmap->answer : inmap->answer;
    if (mapname && !list->answer && !overwrite &&
	G_find_raster(mapname, G_mapset()))
	G_fatal_error(_("option <%s>: <%s> exists."), "output", mapname);

    setname = imapset->answer ? imapset->answer : G_store(G_mapset());
    if (strcmp(inlocation->answer, G_location()) == 0 &&
        (!indbase->answer || strcmp(indbase->answer, G_gisdbase()) == 0))
#if 0
	G_fatal_error(_("Input and output locations can not be the same"));
#else
	G_warning(_("Input and output locations are the same"));
#endif
    G_get_window(&outcellhd);

    if(gprint_bounds->answer && !print_bounds->answer)
	print_bounds->answer = gprint_bounds->answer;
    curr_proj = G_projection();

    /* Get projection info for output mapset */
    if ((out_proj_info = G_get_projinfo()) == NULL)
	G_fatal_error(_("Unable to get projection info of output raster map"));

    if ((out_unit_info = G_get_projunits()) == NULL)
	G_fatal_error(_("Unable to get projection units of output raster map"));

    if (pj_get_kv(&oproj, out_proj_info, out_unit_info) < 0)
	G_fatal_error(_("Unable to get projection key values of output raster map"));

    /* Change the location           */
    G__create_alt_env();
    G__setenv("GISDBASE", indbase->answer ? indbase->answer : G_gisdbase());
    G__setenv("LOCATION_NAME", inlocation->answer);

    permissions = G__mapset_permissions(setname);
    if (permissions < 0)	/* can't access mapset       */
	G_fatal_error(_("Mapset <%s> in input location <%s> - %s"),
		      setname, inlocation->answer,
		      permissions == 0 ? _("permission denied")
		      : _("not found"));

    /* if requested, list the raster maps in source location - MN 5/2001 */
    if (list->answer) {
	int i;
	char **list;
	G_verbose_message(_("Checking location <%s> mapset <%s>"),
			  inlocation->answer, setname);
	list = G_list(G_ELEMENT_RASTER, G__getenv("GISDBASE"),
		      G__getenv("LOCATION_NAME"), setname);
	for (i = 0; list[i]; i++) {
	    fprintf(stdout, "%s\n", list[i]);
	}
	fflush(stdout);
	exit(EXIT_SUCCESS);	/* leave r.proj after listing */
    }

    if (!inmap->answer)
	G_fatal_error(_("Required parameter <%s> not set"), inmap->key);

    if (!G_find_raster(inmap->answer, setname))
	G_fatal_error(_("Raster map <%s> in location <%s> in mapset <%s> not found"),
		      inmap->answer, inlocation->answer, setname);

    /* Read input map colour table */
    have_colors = Rast_read_colors(inmap->answer, setname, &colr);

    /* Get projection info for input mapset */
    if ((in_proj_info = G_get_projinfo()) == NULL)
	G_fatal_error(_("Unable to get projection info of input map"));

    if ((in_unit_info = G_get_projunits()) == NULL)
	G_fatal_error(_("Unable to get projection units of input map"));

    if (pj_get_kv(&iproj, in_proj_info, in_unit_info) < 0)
	G_fatal_error(_("Unable to get projection key values of input map"));

    G_free_key_value(in_proj_info);
    G_free_key_value(in_unit_info);
    G_free_key_value(out_proj_info);
    G_free_key_value(out_unit_info);
    if (G_verbose() > G_verbose_std())
	pj_print_proj_params(&iproj, &oproj);

    /* this call causes r.proj to read the entire map into memeory */
    Rast_get_cellhd(inmap->answer, setname, &incellhd);

    Rast_set_input_window(&incellhd);

    if (G_projection() == PROJECTION_XY)
	G_fatal_error(_("Unable to work with unprojected data (xy location)"));

    /* Save default borders so we can show them later */
    inorth = incellhd.north;
    isouth = incellhd.south;
    ieast = incellhd.east;
    iwest = incellhd.west;
    irows = incellhd.rows;
    icols = incellhd.cols;

    onorth = outcellhd.north;
    osouth = outcellhd.south;
    oeast = outcellhd.east;
    owest = outcellhd.west;
    orows = outcellhd.rows;
    ocols = outcellhd.cols;


    if (print_bounds->answer) {
	G_message(_("Input map <%s@%s> in location <%s>:"),
	    inmap->answer, setname, inlocation->answer);

	if (pj_do_proj(&iwest, &isouth, &iproj, &oproj) < 0)
	    G_fatal_error(_("Error in pj_do_proj (projection of input coordinate pair)"));
	if (pj_do_proj(&ieast, &inorth, &iproj, &oproj) < 0)
	    G_fatal_error(_("Error in pj_do_proj (projection of input coordinate pair)"));

	G_format_northing(inorth, north_str, curr_proj);
	G_format_northing(isouth, south_str, curr_proj);
	G_format_easting(ieast, east_str, curr_proj);
	G_format_easting(iwest, west_str, curr_proj);

	if(gprint_bounds->answer) {
	    fprintf(stdout, "n=%s s=%s w=%s e=%s rows=%d cols=%d\n",
		north_str, south_str, west_str, east_str, irows, icols);
	}
	else {
	    fprintf(stdout, "Source cols: %d\n", icols);
	    fprintf(stdout, "Source rows: %d\n", irows);
	    fprintf(stdout, "Local north: %s\n",  north_str);
	    fprintf(stdout, "Local south: %s\n", south_str);
	    fprintf(stdout, "Local west: %s\n", west_str);
	    fprintf(stdout, "Local east: %s\n", east_str);
	}

	/* somehow approximate local ewres, nsres ?? (use 'g.region -m' on lat/lon side) */

	exit(EXIT_SUCCESS);
    }


    /* Cut non-overlapping parts of input map */
    if (!nocrop->answer)
	bordwalk(&outcellhd, &incellhd, &oproj, &iproj);

    /* Add 2 cells on each side for bilinear/cubic & future interpolation methods */
    /* (should probably be a factor based on input and output resolution) */
    incellhd.north += 2 * incellhd.ns_res;
    incellhd.east += 2 * incellhd.ew_res;
    incellhd.south -= 2 * incellhd.ns_res;
    incellhd.west -= 2 * incellhd.ew_res;
    if (incellhd.north > inorth)
	incellhd.north = inorth;
    if (incellhd.east > ieast)
	incellhd.east = ieast;
    if (incellhd.south < isouth)
	incellhd.south = isouth;
    if (incellhd.west < iwest)
	incellhd.west = iwest;

    Rast_set_input_window(&incellhd);

    /* And switch back to original location */

    G__switch_env();

    /* Adjust borders of output map */

    if (!nocrop->answer)
	bordwalk(&incellhd, &outcellhd, &iproj, &oproj);

#if 0
    outcellhd.west = outcellhd.south = HUGE_VAL;
    outcellhd.east = outcellhd.north = -HUGE_VAL;
    for (row = 0; row < incellhd.rows; row++) {
	ycoord1 = Rast_row_to_northing((double)(row + 0.5), &incellhd);
	for (col = 0; col < incellhd.cols; col++) {
	    xcoord1 = Rast_col_to_easting((double)(col + 0.5), &incellhd);
	    pj_do_proj(&xcoord1, &ycoord1, &iproj, &oproj);
	    if (xcoord1 > outcellhd.east)
		outcellhd.east = xcoord1;
	    if (ycoord1 > outcellhd.north)
		outcellhd.north = ycoord1;
	    if (xcoord1 < outcellhd.west)
		outcellhd.west = xcoord1;
	    if (ycoord1 < outcellhd.south)
		outcellhd.south = ycoord1;
	}
    }
#endif

    if (res->answer != NULL)	/* set user defined resolution */
	outcellhd.ns_res = outcellhd.ew_res = atof(res->answer);

    G_adjust_Cell_head(&outcellhd, 0, 0);
    Rast_set_output_window(&outcellhd);

    G_message(" ");
    G_message(_("Input:"));
    G_message(_("Cols: %d (%d)"), incellhd.cols, icols);
    G_message(_("Rows: %d (%d)"), incellhd.rows, irows);
    G_message(_("North: %f (%f)"), incellhd.north, inorth);
    G_message(_("South: %f (%f)"), incellhd.south, isouth);
    G_message(_("West: %f (%f)"), incellhd.west, iwest);
    G_message(_("East: %f (%f)"), incellhd.east, ieast);
    G_message(_("EW-res: %f"), incellhd.ew_res);
    G_message(_("NS-res: %f"), incellhd.ns_res);
    G_message(" ");

    G_message(_("Output:"));
    G_message(_("Cols: %d (%d)"), outcellhd.cols, ocols);
    G_message(_("Rows: %d (%d)"), outcellhd.rows, orows);
    G_message(_("North: %f (%f)"), outcellhd.north, onorth);
    G_message(_("South: %f (%f)"), outcellhd.south, osouth);
    G_message(_("West: %f (%f)"), outcellhd.west, owest);
    G_message(_("East: %f (%f)"), outcellhd.east, oeast);
    G_message(_("EW-res: %f"), outcellhd.ew_res);
    G_message(_("NS-res: %f"), outcellhd.ns_res);
    G_message(" ");

    /* open and read the relevant parts of the input map and close it */
    G__switch_env();
    Rast_set_input_window(&incellhd);
    fdi = Rast_open_old(inmap->answer, setname);
    cell_type = Rast_get_map_type(fdi);
    ibuffer = readcell(fdi, memory->answer);
    Rast_close(fdi);

    G__switch_env();
    Rast_set_output_window(&outcellhd);

    if (strcmp(interpol->answer, "nearest") == 0) {
	fdo = Rast_open_new(mapname, cell_type);
	obuffer = (CELL *) Rast_allocate_output_buf(cell_type);
    }
    else {
	fdo = Rast_open_fp_new(mapname);
	cell_type = FCELL_TYPE;
	obuffer = (FCELL *) Rast_allocate_output_buf(cell_type);
    }

    cell_size = Rast_cell_size(cell_type);

    xcoord1 = xcoord2 = outcellhd.west + (outcellhd.ew_res / 2);
    /**/ ycoord1 = ycoord2 = outcellhd.north - (outcellhd.ns_res / 2);
    /**/ G_important_message(_("Projecting..."));
    G_percent(0, outcellhd.rows, 2);

    for (row = 0; row < outcellhd.rows; row++) {
	obufptr = obuffer;

	for (col = 0; col < outcellhd.cols; col++) {
	    /* project coordinates in output matrix to       */
	    /* coordinates in input matrix                   */
	    if (pj_do_proj(&xcoord1, &ycoord1, &oproj, &iproj) < 0)
		Rast_set_null_value(obufptr, 1, cell_type);
	    else {
		/* convert to row/column indices of input matrix */
		col_idx = (xcoord1 - incellhd.west) / incellhd.ew_res;
		row_idx = (incellhd.north - ycoord1) / incellhd.ns_res;

		/* and resample data point               */
		interpolate(ibuffer, obufptr, cell_type,
			    &col_idx, &row_idx, &incellhd);
	    }

	    obufptr = G_incr_void_ptr(obufptr, cell_size);
	    xcoord2 += outcellhd.ew_res;
	    xcoord1 = xcoord2;
	    ycoord1 = ycoord2;
	}

	Rast_put_row(fdo, obuffer, cell_type);

	xcoord1 = xcoord2 = outcellhd.west + (outcellhd.ew_res / 2);
	ycoord2 -= outcellhd.ns_res;
	ycoord1 = ycoord2;
	G_percent(row, outcellhd.rows - 1, 2);
    }

    Rast_close(fdo);

    if (have_colors > 0) {
	Rast_write_colors(mapname, G_mapset(), &colr);
	Rast_free_colors(&colr);
    }

    Rast_short_history(mapname, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(mapname, &history);

    G_done_msg(NULL);
    exit(EXIT_SUCCESS);
}
コード例 #3
0
ファイル: main.c プロジェクト: rashadkm/grass_cmake
/* ************************************************************************* */
int main(int argc, char *argv[])
{
    RASTER3D_Region region, inputmap_bounds;
    struct Cell_head region2d;
    struct GModule *module;
    struct History history;
    void *map = NULL; /*The 3D Rastermap */
    int i = 0, changemask = 0;
    int *fd = NULL, output_type, cols, rows;
    char *RasterFileName;
    int overwrite = 0;

    /* Initialize GRASS */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster3d"));
    G_add_keyword(_("conversion"));
    G_add_keyword(_("raster"));
    G_add_keyword(_("voxel"));
    module->description = _("Converts 3D raster maps to 2D raster maps");

    /* Get parameters from user */
    set_params();

    /* Have GRASS get inputs */
    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    G_debug(3, "Open 3D raster map <%s>", param.input->answer);

    if (NULL == G_find_raster3d(param.input->answer, ""))
        Rast3d_fatal_error(_("3D raster map <%s> not found"),
                       param.input->answer);

    /*Set the defaults */
    Rast3d_init_defaults();

    /*Set the resolution of the output maps */
    if (param.res->answer) {

        /*Open the map with current region */
        map = Rast3d_open_cell_old(param.input->answer,
                              G_find_raster3d(param.input->answer, ""),
                              RASTER3D_DEFAULT_WINDOW, RASTER3D_TILE_SAME_AS_FILE,
                              RASTER3D_USE_CACHE_DEFAULT);
        if (map == NULL)
            Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
                           param.input->answer);


        /*Get the region of the map */
        Rast3d_get_region_struct_map(map, &region);
        /*set this region as current 3D window for map */
        Rast3d_set_window_map(map, &region);
        /*Set the 2d region appropriate */
        Rast3d_extract2d_region(&region, &region2d);
        /*Make the new 2d region the default */
        Rast_set_window(&region2d);

    } else {
        /* Figure out the region from the map */
        Rast3d_get_window(&region);

        /*Open the 3d raster map */
        map = Rast3d_open_cell_old(param.input->answer,
                              G_find_raster3d(param.input->answer, ""),
                              &region, RASTER3D_TILE_SAME_AS_FILE,
                              RASTER3D_USE_CACHE_DEFAULT);

        if (map == NULL)
            Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
                           param.input->answer);
    }

    /*Check if the g3d-region is equal to the 2D rows and cols */
    rows = Rast_window_rows();
    cols = Rast_window_cols();

    /*If not equal, set the 3D window correct */
    if (rows != region.rows || cols != region.cols) {
        G_message(_("The 2D and 3D region settings are different. "
                    "Using the 2D window settings to adjust the 2D part of the 3D region."));
        G_get_set_window(&region2d);
        region.ns_res = region2d.ns_res;
        region.ew_res = region2d.ew_res;
        region.rows = region2d.rows;
        region.cols = region2d.cols;
        
        Rast3d_adjust_region(&region);
        
        Rast3d_set_window_map(map, &region);
    }

    /* save the input map region for later use (history meta-data) */
    Rast3d_get_region_struct_map(map, &inputmap_bounds);

    /*Get the output type */
    output_type = Rast3d_file_type_map(map);


    /*prepare the filehandler */
    fd = (int *) G_malloc(region.depths * sizeof (int));

    if (fd == NULL)
        fatal_error(map, NULL, 0, _("Out of memory"));

    G_message(_("Creating %i raster maps"), region.depths);

    /*Loop over all output maps! open */
    for (i = 0; i < region.depths; i++) {
        /*Create the outputmaps */
        G_asprintf(&RasterFileName, "%s_%05d", param.output->answer, i + 1);
        G_message(_("Raster map %i Filename: %s"), i + 1, RasterFileName);

        overwrite = G_check_overwrite(argc, argv);
        
        if (G_find_raster2(RasterFileName, "") && !overwrite)
            G_fatal_error(_("Raster map %d Filename: %s already exists. Use the flag --o to overwrite."),
                      i + 1, RasterFileName);

        if (output_type == FCELL_TYPE)
            fd[i] = open_output_map(RasterFileName, FCELL_TYPE);
        else if (output_type == DCELL_TYPE)
            fd[i] = open_output_map(RasterFileName, DCELL_TYPE);

    }

    /*if requested set the Mask on */
    if (param.mask->answer) {
        if (Rast3d_mask_file_exists()) {
            changemask = 0;
            if (Rast3d_mask_is_off(map)) {
                Rast3d_mask_on(map);
                changemask = 1;
            }
        }
    }

    /*Create the Rastermaps */
    g3d_to_raster(map, region, fd);


    /*Loop over all output maps! close */
    for (i = 0; i < region.depths; i++) {
        close_output_map(fd[i]);

        /* write history */
        G_asprintf(&RasterFileName, "%s_%i", param.output->answer, i + 1);
        G_debug(4, "Raster map %d Filename: %s", i + 1, RasterFileName);
        Rast_short_history(RasterFileName, "raster", &history);

        Rast_set_history(&history, HIST_DATSRC_1, "3D Raster map:");
        Rast_set_history(&history, HIST_DATSRC_2, param.input->answer);

        Rast_append_format_history(&history, "Level %d of %d", i + 1, region.depths);
        Rast_append_format_history(&history, "Level z-range: %f to %f",
                                   region.bottom + (i * region.tb_res),
                                   region.bottom + (i + 1 * region.tb_res));

        Rast_append_format_history(&history, "Input map full z-range: %f to %f",
                                   inputmap_bounds.bottom, inputmap_bounds.top);
        Rast_append_format_history(&history, "Input map z-resolution: %f",
                                   inputmap_bounds.tb_res);

        if (!param.res->answer) {
            Rast_append_format_history(&history, "GIS region full z-range: %f to %f",
                                       region.bottom, region.top);
            Rast_append_format_history(&history, "GIS region z-resolution: %f",
                                       region.tb_res);
        }

        Rast_command_history(&history);
        Rast_write_history(RasterFileName, &history);
    }

    /*We set the Mask off, if it was off before */
    if (param.mask->answer) {
        if (Rast3d_mask_file_exists())
            if (Rast3d_mask_is_on(map) && changemask)
                Rast3d_mask_off(map);
    }


    /*Cleaning */
    if (RasterFileName)
        G_free(RasterFileName);

    if (fd)
        G_free(fd);

    /* Close files and exit */
    if (!Rast3d_close(map))
        fatal_error(map, NULL, 0, _("Unable to close 3D raster map"));

    map = NULL;

    return (EXIT_SUCCESS);
}
コード例 #4
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct _param {
        struct Option *dsn, *out, *layer, *spat, *where,
                   *min_area;
        struct Option *snap, *type, *outloc, *cnames;
    } param;
    struct _flag {
        struct Flag *list, *tlist, *no_clean, *z, *notab,
                   *region;
        struct Flag *over, *extend, *formats, *tolower, *no_import;
    } flag;

    int i, j, layer, arg_s_num, nogeom, ncnames;
    float xmin, ymin, xmax, ymax;
    int ncols = 0, type;
    double min_area, snap;
    char buf[2000], namebuf[2000], tempvect[GNAME_MAX];
    char *separator;

    struct Key_Value *loc_proj_info, *loc_proj_units;
    struct Key_Value *proj_info, *proj_units;
    struct Cell_head cellhd, loc_wind, cur_wind;
    char error_msg[8192];

    /* Vector */
    struct Map_info Map, Tmp, *Out;
    int cat;

    /* Attributes */
    struct field_info *Fi;
    dbDriver *driver;
    dbString sql, strval;
    int dim, with_z;

    /* OGR */
    OGRDataSourceH Ogr_ds;
    OGRLayerH Ogr_layer;
    OGRFieldDefnH Ogr_field;
    char *Ogr_fieldname;
    OGRFieldType Ogr_ftype;
    OGRFeatureH Ogr_feature;
    OGRFeatureDefnH Ogr_featuredefn;
    OGRGeometryH Ogr_geometry, Ogr_oRing, poSpatialFilter;
    OGRSpatialReferenceH Ogr_projection;
    OGREnvelope oExt;
    OGRwkbGeometryType Ogr_geom_type;

    int OFTIntegerListlength;

    char *output;
    char **layer_names;		/* names of layers to be imported */
    int *layers;		/* layer indexes */
    int nlayers;		/* number of layers to import */
    char **available_layer_names;	/* names of layers to be imported */
    int navailable_layers;
    int layer_id;
    unsigned int n_features, feature_count;
    int overwrite;
    double area_size;
    int use_tmp_vect;

    xmin = ymin = xmax = ymax = 0.0;
    loc_proj_info = loc_proj_units = NULL;
    Ogr_ds = Ogr_oRing = poSpatialFilter = NULL;
    OFTIntegerListlength = 40;	/* hack due to limitation in OGR */
    area_size = 0.0;
    use_tmp_vect = FALSE;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("import"));
    module->description = _("Converts vector data into a GRASS vector map using OGR library.");

    param.dsn = G_define_option();
    param.dsn->key = "dsn";
    param.dsn->type = TYPE_STRING;
    param.dsn->required =YES;
    param.dsn->label = _("OGR datasource name");
    param.dsn->description = _("Examples:\n"
                               "\t\tESRI Shapefile: directory containing shapefiles\n"
                               "\t\tMapInfo File: directory containing mapinfo files");

    param.layer = G_define_option();
    param.layer->key = "layer";
    param.layer->type = TYPE_STRING;
    param.layer->required = NO;
    param.layer->multiple = YES;
    param.layer->label =
        _("OGR layer name. If not given, all available layers are imported");
    param.layer->description =
        _("Examples:\n" "\t\tESRI Shapefile: shapefile name\n"
          "\t\tMapInfo File: mapinfo file name");
    param.layer->guisection = _("Selection");

    param.out = G_define_standard_option(G_OPT_V_OUTPUT);
    param.out->required = NO;
    param.out->guisection = _("Output");

    param.spat = G_define_option();
    param.spat->key = "spatial";
    param.spat->type = TYPE_DOUBLE;
    param.spat->multiple = YES;
    param.spat->required = NO;
    param.spat->key_desc = "xmin,ymin,xmax,ymax";
    param.spat->label = _("Import subregion only");
    param.spat->guisection = _("Selection");
    param.spat->description =
        _("Format: xmin,ymin,xmax,ymax - usually W,S,E,N");

    param.where = G_define_standard_option(G_OPT_DB_WHERE);
    param.where->guisection = _("Selection");

    param.min_area = G_define_option();
    param.min_area->key = "min_area";
    param.min_area->type = TYPE_DOUBLE;
    param.min_area->required = NO;
    param.min_area->answer = "0.0001";
    param.min_area->label =
        _("Minimum size of area to be imported (square units)");
    param.min_area->guisection = _("Selection");
    param.min_area->description = _("Smaller areas and "
                                    "islands are ignored. Should be greater than snap^2");

    param.type = G_define_standard_option(G_OPT_V_TYPE);
    param.type->options = "point,line,boundary,centroid";
    param.type->answer = "";
    param.type->description = _("Optionally change default input type");
    param.type->descriptions =
        _("point;import area centroids as points;"
          "line;import area boundaries as lines;"
          "boundary;import lines as area boundaries;"
          "centroid;import points as centroids");
    param.type->guisection = _("Selection");

    param.snap = G_define_option();
    param.snap->key = "snap";
    param.snap->type = TYPE_DOUBLE;
    param.snap->required = NO;
    param.snap->answer = "-1";
    param.snap->label = _("Snapping threshold for boundaries");
    param.snap->description = _("'-1' for no snap");

    param.outloc = G_define_option();
    param.outloc->key = "location";
    param.outloc->type = TYPE_STRING;
    param.outloc->required = NO;
    param.outloc->description = _("Name for new location to create");
    param.outloc->key_desc = "name";

    param.cnames = G_define_option();
    param.cnames->key = "cnames";
    param.cnames->type = TYPE_STRING;
    param.cnames->required = NO;
    param.cnames->multiple = YES;
    param.cnames->description =
        _("List of column names to be used instead of original names, "
          "first is used for category column");
    param.cnames->guisection = _("Attributes");

    flag.list = G_define_flag();
    flag.list->key = 'l';
    flag.list->description = _("List available OGR layers in data source and exit");
    flag.list->suppress_required = YES;
    flag.list->guisection = _("Print");

    flag.tlist = G_define_flag();
    flag.tlist->key = 'a';
    flag.tlist->description = _("List available OGR layers including feature types "
                                "in data source and exit");
    flag.tlist->suppress_required = YES;
    flag.tlist->guisection = _("Print");

    flag.formats = G_define_flag();
    flag.formats->key = 'f';
    flag.formats->description = _("List supported formats and exit");
    flag.formats->suppress_required = YES;
    flag.formats->guisection = _("Print");

    /* if using -c, you lose topological information ! */
    flag.no_clean = G_define_flag();
    flag.no_clean->key = 'c';
    flag.no_clean->description = _("Do not clean polygons (not recommended)");
    flag.no_clean->guisection = _("Output");

    flag.z = G_define_flag();
    flag.z->key = 'z';
    flag.z->description = _("Create 3D output");
    flag.z->guisection = _("Output");

    flag.notab = G_define_flag();
    flag.notab->key = 't';
    flag.notab->description = _("Do not create attribute table");
    flag.notab->guisection = _("Attributes");

    flag.over = G_define_flag();
    flag.over->key = 'o';
    flag.over->description =
        _("Override dataset projection (use location's projection)");

    flag.region = G_define_flag();
    flag.region->key = 'r';
    flag.region->guisection = _("Selection");
    flag.region->description = _("Limit import to the current region");

    flag.extend = G_define_flag();
    flag.extend->key = 'e';
    flag.extend->description =
        _("Extend location extents based on new dataset");

    flag.tolower = G_define_flag();
    flag.tolower->key = 'w';
    flag.tolower->description =
        _("Change column names to lowercase characters");
    flag.tolower->guisection = _("Attributes");

    flag.no_import = G_define_flag();
    flag.no_import->key = 'i';
    flag.no_import->description =
        _("Create the location specified by the \"location\" parameter and exit."
          " Do not import the vector data.");

    /* The parser checks if the map already exists in current mapset, this is
     * wrong if location options is used, so we switch out the check and do it
     * in the module after the parser */
    overwrite = G_check_overwrite(argc, argv);

    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    G_begin_polygon_area_calculations();	/* Used in geom() */

    OGRRegisterAll();

    /* list supported formats */
    if (flag.formats->answer) {
        int iDriver;

        G_message(_("Available OGR Drivers:"));

        for (iDriver = 0; iDriver < OGRGetDriverCount(); iDriver++) {
            OGRSFDriverH poDriver = OGRGetDriver(iDriver);
            const char *pszRWFlag;

            if (OGR_Dr_TestCapability(poDriver, ODrCCreateDataSource))
                pszRWFlag = "rw";
            else
                pszRWFlag = "ro";

            fprintf(stdout, " %s (%s): %s\n",
                    OGR_Dr_GetName(poDriver),
                    pszRWFlag, OGR_Dr_GetName(poDriver));
        }
        exit(EXIT_SUCCESS);
    }

    if (param.dsn->answer == NULL) {
        G_fatal_error(_("Required parameter <%s> not set"), param.dsn->key);
    }

    min_area = atof(param.min_area->answer);
    snap = atof(param.snap->answer);
    type = Vect_option_to_types(param.type);

    ncnames = 0;
    if (param.cnames->answers) {
        i = 0;
        while (param.cnames->answers[i++]) {
            ncnames++;
        }
    }

    /* Open OGR DSN */
    Ogr_ds = NULL;
    if (strlen(param.dsn->answer) > 0)
        Ogr_ds = OGROpen(param.dsn->answer, FALSE, NULL);

    if (Ogr_ds == NULL)
        G_fatal_error(_("Unable to open data source <%s>"), param.dsn->answer);

    /* Make a list of available layers */
    navailable_layers = OGR_DS_GetLayerCount(Ogr_ds);
    available_layer_names =
        (char **)G_malloc(navailable_layers * sizeof(char *));

    if (flag.list->answer || flag.tlist->answer)
        G_message(_("Data source <%s> (format '%s') contains %d layers:"),
                  param.dsn->answer,
                  OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)), navailable_layers);
    for (i = 0; i < navailable_layers; i++) {
        Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
        Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);

        available_layer_names[i] =
            G_store((char *)OGR_FD_GetName(Ogr_featuredefn));

        if (flag.tlist->answer)
            fprintf(stdout, "%s (%s)\n", available_layer_names[i],
                    OGRGeometryTypeToName(Ogr_geom_type));
        else if (flag.list->answer)
            fprintf(stdout, "%s\n", available_layer_names[i]);
    }
    if (flag.list->answer || flag.tlist->answer) {
        fflush(stdout);
        exit(EXIT_SUCCESS);
    }

    /* Make a list of layers to be imported */
    if (param.layer->answer) {	/* From option */
        nlayers = 0;
        while (param.layer->answers[nlayers])
            nlayers++;

        layer_names = (char **)G_malloc(nlayers * sizeof(char *));
        layers = (int *)G_malloc(nlayers * sizeof(int));

        for (i = 0; i < nlayers; i++) {
            layer_names[i] = G_store(param.layer->answers[i]);
            /* Find it in the source */
            layers[i] = -1;
            for (j = 0; j < navailable_layers; j++) {
                if (strcmp(available_layer_names[j], layer_names[i]) == 0) {
                    layers[i] = j;
                    break;
                }
            }
            if (layers[i] == -1)
                G_fatal_error(_("Layer <%s> not available"), layer_names[i]);
        }
    }
    else {			/* use list of all layers */
        nlayers = navailable_layers;
        layer_names = available_layer_names;
        layers = (int *)G_malloc(nlayers * sizeof(int));
        for (i = 0; i < nlayers; i++)
            layers[i] = i;
    }

    if (param.out->answer) {
        output = G_store(param.out->answer);
    }
    else {
        if (nlayers < 1)
            G_fatal_error(_("No OGR layers available"));
        output = G_store(layer_names[0]);
        G_message(_("All available OGR layers will be imported into vector map <%s>"), output);
    }

    if (!param.outloc->answer) {	/* Check if the map exists */
        if (G_find_vector2(output, G_mapset()) && !overwrite)
            G_fatal_error(_("Vector map <%s> already exists"),
                          output);
    }

    /* Get first imported layer to use for extents and projection check */
    Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layers[0]);

    if (flag.region->answer) {
        if (param.spat->answer)
            G_fatal_error(_("Select either the current region flag or the spatial option, not both"));

        G_get_window(&cur_wind);
        xmin = cur_wind.west;
        xmax = cur_wind.east;
        ymin = cur_wind.south;
        ymax = cur_wind.north;
    }
    if (param.spat->answer) {
        /* See as reference: gdal/ogr/ogr_capi_test.c */

        /* cut out a piece of the map */
        /* order: xmin,ymin,xmax,ymax */
        arg_s_num = 0;
        i = 0;
        while (param.spat->answers[i]) {
            if (i == 0)
                xmin = atof(param.spat->answers[i]);
            if (i == 1)
                ymin = atof(param.spat->answers[i]);
            if (i == 2)
                xmax = atof(param.spat->answers[i]);
            if (i == 3)
                ymax = atof(param.spat->answers[i]);
            arg_s_num++;
            i++;
        }
        if (arg_s_num != 4)
            G_fatal_error(_("4 parameters required for 'spatial' parameter"));
    }
    if (param.spat->answer || flag.region->answer) {
        G_debug(2, "cut out with boundaries: xmin:%f ymin:%f xmax:%f ymax:%f",
                xmin, ymin, xmax, ymax);

        /* in theory this could be an irregular polygon */
        poSpatialFilter = OGR_G_CreateGeometry(wkbPolygon);
        Ogr_oRing = OGR_G_CreateGeometry(wkbLinearRing);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymax, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmax, ymax, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmax, ymin, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0);
        OGR_G_AddGeometryDirectly(poSpatialFilter, Ogr_oRing);

        OGR_L_SetSpatialFilter(Ogr_layer, poSpatialFilter);
    }

    if (param.where->answer) {
        /* select by attribute */
        OGR_L_SetAttributeFilter(Ogr_layer, param.where->answer);
    }

    /* fetch boundaries */
    if ((OGR_L_GetExtent(Ogr_layer, &oExt, 1)) == OGRERR_NONE) {
        G_get_window(&cellhd);
        cellhd.north = oExt.MaxY;
        cellhd.south = oExt.MinY;
        cellhd.west = oExt.MinX;
        cellhd.east = oExt.MaxX;
        cellhd.rows = 20;	/* TODO - calculate useful values */
        cellhd.cols = 20;
        cellhd.ns_res = (cellhd.north - cellhd.south) / cellhd.rows;
        cellhd.ew_res = (cellhd.east - cellhd.west) / cellhd.cols;
    }
    else {
        cellhd.north = 1.;
        cellhd.south = 0.;
        cellhd.west = 0.;
        cellhd.east = 1.;
        cellhd.top = 1.;
        cellhd.bottom = 1.;
        cellhd.rows = 1;
        cellhd.rows3 = 1;
        cellhd.cols = 1;
        cellhd.cols3 = 1;
        cellhd.depths = 1;
        cellhd.ns_res = 1.;
        cellhd.ns_res3 = 1.;
        cellhd.ew_res = 1.;
        cellhd.ew_res3 = 1.;
        cellhd.tb_res = 1.;
    }

    /* suppress boundary splitting ? */
    if (flag.no_clean->answer) {
        split_distance = -1.;
    }
    else {
        split_distance = 0.;
        area_size =
            sqrt((cellhd.east - cellhd.west) * (cellhd.north - cellhd.south));
    }

    /* Fetch input map projection in GRASS form. */
    proj_info = NULL;
    proj_units = NULL;
    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);	/* should not be freed later */

    /* Do we need to create a new location? */
    if (param.outloc->answer != NULL) {
        /* Convert projection information non-interactively as we can't
         * assume the user has a terminal open */
        if (GPJ_osr_to_grass(&cellhd, &proj_info,
                             &proj_units, Ogr_projection, 0) < 0) {
            G_fatal_error(_("Unable to convert input map projection to GRASS "
                            "format; cannot create new location."));
        }
        else {
            G_make_location(param.outloc->answer, &cellhd,
                            proj_info, proj_units, NULL);
            G_message(_("Location <%s> created"), param.outloc->answer);
        }

        /* If the i flag is set, clean up? and exit here */
        if(flag.no_import->answer)
        {
            exit(EXIT_SUCCESS);
        }
    }
    else {
        int err = 0;

        /* Projection only required for checking so convert non-interactively */
        if (GPJ_osr_to_grass(&cellhd, &proj_info,
                             &proj_units, Ogr_projection, 0) < 0)
            G_warning(_("Unable to convert input map projection information to "
                        "GRASS format for checking"));

        /* Does the projection of the current location match the dataset? */
        /* G_get_window seems to be unreliable if the location has been changed */
        G__get_window(&loc_wind, "", "DEFAULT_WIND", "PERMANENT");
        /* fetch LOCATION PROJ info */
        if (loc_wind.proj != PROJECTION_XY) {
            loc_proj_info = G_get_projinfo();
            loc_proj_units = G_get_projunits();
        }

        if (flag.over->answer) {
            cellhd.proj = loc_wind.proj;
            cellhd.zone = loc_wind.zone;
            G_message(_("Over-riding projection check"));
        }
        else if (loc_wind.proj != cellhd.proj
                 || (err =
                         G_compare_projections(loc_proj_info, loc_proj_units,
                                               proj_info, proj_units)) != TRUE) {
            int i_value;

            strcpy(error_msg,
                   _("Projection of dataset does not"
                     " appear to match current location.\n\n"));

            /* TODO: output this info sorted by key: */
            if (loc_wind.proj != cellhd.proj || err != -2) {
                if (loc_proj_info != NULL) {
                    strcat(error_msg, _("GRASS LOCATION PROJ_INFO is:\n"));
                    for (i_value = 0; i_value < loc_proj_info->nitems;
                            i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                loc_proj_info->key[i_value],
                                loc_proj_info->value[i_value]);
                    strcat(error_msg, "\n");
                }

                if (proj_info != NULL) {
                    strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
                    for (i_value = 0; i_value < proj_info->nitems; i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                proj_info->key[i_value],
                                proj_info->value[i_value]);
                }
                else {
                    strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
                    if (cellhd.proj == PROJECTION_XY)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (unreferenced/unknown)\n",
                                cellhd.proj);
                    else if (cellhd.proj == PROJECTION_LL)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (lat/long)\n",
                                cellhd.proj);
                    else if (cellhd.proj == PROJECTION_UTM)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (UTM), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                    else if (cellhd.proj == PROJECTION_SP)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (State Plane), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                    else
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (unknown), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                }
            }
            else {
                if (loc_proj_units != NULL) {
                    strcat(error_msg, "GRASS LOCATION PROJ_UNITS is:\n");
                    for (i_value = 0; i_value < loc_proj_units->nitems;
                            i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                loc_proj_units->key[i_value],
                                loc_proj_units->value[i_value]);
                    strcat(error_msg, "\n");
                }

                if (proj_units != NULL) {
                    strcat(error_msg, "Import dataset PROJ_UNITS is:\n");
                    for (i_value = 0; i_value < proj_units->nitems; i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                proj_units->key[i_value],
                                proj_units->value[i_value]);
                }
            }
            sprintf(error_msg + strlen(error_msg),
                    _("\nYou can use the -o flag to %s to override this projection check.\n"),
                    G_program_name());
            strcat(error_msg,
                   _("Consider generating a new location with 'location' parameter"
                     " from input data set.\n"));
            G_fatal_error(error_msg);
        }
        else {
            G_message(_("Projection of input dataset and current location "
                        "appear to match"));
        }
    }

    db_init_string(&sql);
    db_init_string(&strval);

    /* open output vector */
    /* strip any @mapset from vector output name */
    G_find_vector(output, G_mapset());
    Vect_open_new(&Map, output, flag.z->answer != 0);
    Out = &Map;

    n_polygon_boundaries = 0;
    if (!flag.no_clean->answer) {
        /* check if we need a tmp vector */

        /* estimate distance for boundary splitting --> */
        for (layer = 0; layer < nlayers; layer++) {
            layer_id = layers[layer];

            Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
            Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);

            n_features = feature_count = 0;

            n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
            OGR_L_ResetReading(Ogr_layer);

            /* count polygons and isles */
            G_message(_("Counting polygons for %d features (OGR layer <%s>)..."),
                      n_features, layer_names[layer]);
            while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
                G_percent(feature_count++, n_features, 1);	/* show something happens */
                /* Geometry */
                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
                if (Ogr_geometry != NULL) {
                    poly_count(Ogr_geometry, (type & GV_BOUNDARY));
                }
                OGR_F_Destroy(Ogr_feature);
            }
        }

        G_debug(1, "n polygon boundaries: %d", n_polygon_boundaries);
        if (n_polygon_boundaries > 50) {
            split_distance =
                area_size / log(n_polygon_boundaries);
            /* divisor is the handle: increase divisor to decrease split_distance */
            split_distance = split_distance / 5.;
            G_debug(1, "root of area size: %f", area_size);
            G_verbose_message(_("Boundary splitting distance in map units: %G"),
                              split_distance);
        }
        /* <-- estimate distance for boundary splitting */

        use_tmp_vect = n_polygon_boundaries > 0;

        if (use_tmp_vect) {
            /* open temporary vector, do the work in the temporary vector
             * at the end copy alive lines to output vector
             * in case of polygons this reduces the coor file size by a factor of 2 to 5
             * only needed when cleaning polygons */
            sprintf(tempvect, "%s_tmp", output);
            G_verbose_message(_("Using temporary vector <%s>"), tempvect);
            Vect_open_new(&Tmp, tempvect, flag.z->answer != 0);
            Out = &Tmp;
        }
    }

    Vect_hist_command(&Map);

    /* Points and lines are written immediately with categories. Boundaries of polygons are
     * written to the vector then cleaned and centroids are calculated for all areas in cleaan vector.
     * Then second pass through finds all centroids in each polygon feature and adds its category
     * to the centroid. The result is that one centroids may have 0, 1 ore more categories
     * of one ore more (more input layers) fields. */
    with_z = 0;
    for (layer = 0; layer < nlayers; layer++) {
        layer_id = layers[layer];

        Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);

        /* Add DB link */
        if (!flag.notab->answer) {
            char *cat_col_name = GV_KEY_COLUMN;

            if (nlayers == 1) {	/* one layer only */
                Fi = Vect_default_field_info(&Map, layer + 1, NULL,
                                             GV_1TABLE);
            }
            else {
                Fi = Vect_default_field_info(&Map, layer + 1, NULL,
                                             GV_MTABLE);
            }

            if (ncnames > 0) {
                cat_col_name = param.cnames->answers[0];
            }
            Vect_map_add_dblink(&Map, layer + 1, layer_names[layer], Fi->table,
                                cat_col_name, Fi->database, Fi->driver);

            ncols = OGR_FD_GetFieldCount(Ogr_featuredefn);
            G_debug(2, "%d columns", ncols);

            /* Create table */
            sprintf(buf, "create table %s (%s integer", Fi->table,
                    cat_col_name);
            db_set_string(&sql, buf);
            for (i = 0; i < ncols; i++) {

                Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i);
                Ogr_ftype = OGR_Fld_GetType(Ogr_field);

                G_debug(3, "Ogr_ftype: %i", Ogr_ftype);	/* look up below */

                if (i < ncnames - 1) {
                    Ogr_fieldname = G_store(param.cnames->answers[i + 1]);
                }
                else {
                    /* Change column names to [A-Za-z][A-Za-z0-9_]* */
                    Ogr_fieldname = G_store(OGR_Fld_GetNameRef(Ogr_field));
                    G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname);

                    G_str_to_sql(Ogr_fieldname);

                    G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname);

                }

                /* avoid that we get the 'cat' column twice */
                if (strcmp(Ogr_fieldname, GV_KEY_COLUMN) == 0) {
                    sprintf(namebuf, "%s_", Ogr_fieldname);
                    Ogr_fieldname = G_store(namebuf);
                }

                /* captial column names are a pain in SQL */
                if (flag.tolower->answer)
                    G_str_to_lower(Ogr_fieldname);

                if (strcmp(OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname) != 0) {
                    G_warning(_("Column name changed: '%s' -> '%s'"),
                              OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname);
                }

                /** Simple 32bit integer                     OFTInteger = 0        **/

                /** List of 32bit integers                   OFTIntegerList = 1    **/

                /** Double Precision floating point          OFTReal = 2           **/

                /** List of doubles                          OFTRealList = 3       **/

                /** String of ASCII chars                    OFTString = 4         **/

                /** Array of strings                         OFTStringList = 5     **/

                /** Double byte string (unsupported)         OFTWideString = 6     **/

                /** List of wide strings (unsupported)       OFTWideStringList = 7 **/

                /** Raw Binary data (unsupported)            OFTBinary = 8         **/

                /**                                          OFTDate = 9           **/

                /**                                          OFTTime = 10          **/

                /**                                          OFTDateTime = 11      **/


                if (Ogr_ftype == OFTInteger) {
                    sprintf(buf, ", %s integer", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTIntegerList) {
                    /* hack: treat as string */
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            OFTIntegerListlength);
                    G_warning(_("Writing column <%s> with fixed length %d chars (may be truncated)"),
                              Ogr_fieldname, OFTIntegerListlength);
                }
                else if (Ogr_ftype == OFTReal) {
                    sprintf(buf, ", %s double precision", Ogr_fieldname);
#if GDAL_VERSION_NUM >= 1320
                }
                else if (Ogr_ftype == OFTDate) {
                    sprintf(buf, ", %s date", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTTime) {
                    sprintf(buf, ", %s time", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTDateTime) {
                    sprintf(buf, ", %s datetime", Ogr_fieldname);
#endif
                }
                else if (Ogr_ftype == OFTString) {
                    int fwidth;

                    fwidth = OGR_Fld_GetWidth(Ogr_field);
                    /* TODO: read all records first and find the longest string length */
                    if (fwidth == 0) {
                        G_warning(_("Width for column %s set to 255 (was not specified by OGR), "
                                    "some strings may be truncated!"),
                                  Ogr_fieldname);
                        fwidth = 255;
                    }
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            fwidth);
                }
                else if (Ogr_ftype == OFTStringList) {
                    /* hack: treat as string */
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            OFTIntegerListlength);
                    G_warning(_("Writing column %s with fixed length %d chars (may be truncated)"),
                              Ogr_fieldname, OFTIntegerListlength);
                }
                else {
                    G_warning(_("Column type not supported (%s)"),
                              Ogr_fieldname);
                    buf[0] = 0;
                }
                db_append_string(&sql, buf);
                G_free(Ogr_fieldname);
            }
            db_append_string(&sql, ")");
            G_debug(3, db_get_string(&sql));

            driver =
                db_start_driver_open_database(Fi->driver,
                                              Vect_subst_var(Fi->database,
                                                      &Map));
            if (driver == NULL) {
                G_fatal_error(_("Unable open database <%s> by driver <%s>"),
                              Vect_subst_var(Fi->database, &Map), Fi->driver);
            }

            if (db_execute_immediate(driver, &sql) != DB_OK) {
                db_close_database(driver);
                db_shutdown_driver(driver);
                G_fatal_error(_("Unable to create table: '%s'"),
                              db_get_string(&sql));
            }

            if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK)
                G_warning(_("Unable to create index for table <%s>, key <%s>"),
                          Fi->table, cat_col_name);

            if (db_grant_on_table
                    (driver, Fi->table, DB_PRIV_SELECT,
                     DB_GROUP | DB_PUBLIC) != DB_OK)
                G_fatal_error(_("Unable to grant privileges on table <%s>"),
                              Fi->table);

            db_begin_transaction(driver);
        }

        /* Import feature */
        cat = 1;
        nogeom = 0;
        OGR_L_ResetReading(Ogr_layer);
        n_features = feature_count = 0;

        n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);

        G_important_message(_("Importing %d features (OGR layer <%s>)..."),
                            n_features, layer_names[layer]);
        while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
            G_percent(feature_count++, n_features, 1);	/* show something happens */
            /* Geometry */
            Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
            if (Ogr_geometry == NULL) {
                nogeom++;
            }
            else {
                dim = OGR_G_GetCoordinateDimension(Ogr_geometry);
                if (dim > 2)
                    with_z = 1;

                geom(Ogr_geometry, Out, layer + 1, cat, min_area, type,
                     flag.no_clean->answer);
            }

            /* Attributes */
            if (!flag.notab->answer) {
                sprintf(buf, "insert into %s values ( %d", Fi->table, cat);
                db_set_string(&sql, buf);
                for (i = 0; i < ncols; i++) {
                    Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i);
                    Ogr_ftype = OGR_Fld_GetType(Ogr_field);
                    if (OGR_F_IsFieldSet(Ogr_feature, i)) {
                        if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) {
                            sprintf(buf, ", %s",
                                    OGR_F_GetFieldAsString(Ogr_feature, i));
#if GDAL_VERSION_NUM >= 1320
                            /* should we use OGR_F_GetFieldAsDateTime() here ? */
                        }
                        else if (Ogr_ftype == OFTDate || Ogr_ftype == OFTTime
                                 || Ogr_ftype == OFTDateTime) {
                            char *newbuf;

                            db_set_string(&strval, (char *)
                                          OGR_F_GetFieldAsString(Ogr_feature,
                                                                 i));
                            db_double_quote_string(&strval);
                            sprintf(buf, ", '%s'", db_get_string(&strval));
                            newbuf = G_str_replace(buf, "/", "-");	/* fix 2001/10/21 to 2001-10-21 */
                            sprintf(buf, "%s", newbuf);
#endif
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList) {
                            db_set_string(&strval, (char *)
                                          OGR_F_GetFieldAsString(Ogr_feature,
                                                                 i));
                            db_double_quote_string(&strval);
                            sprintf(buf, ", '%s'", db_get_string(&strval));
                        }

                    }
                    else {
                        /* G_warning (_("Column value not set" )); */
                        if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) {
                            sprintf(buf, ", NULL");
#if GDAL_VERSION_NUM >= 1320
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList ||
                                 Ogr_ftype == OFTDate) {
#else
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList) {
#endif
                            sprintf(buf, ", ''");
                        }
                    }
                    db_append_string(&sql, buf);
                }
                db_append_string(&sql, " )");
                G_debug(3, db_get_string(&sql));

                if (db_execute_immediate(driver, &sql) != DB_OK) {
                    db_close_database(driver);
                    db_shutdown_driver(driver);
                    G_fatal_error(_("Cannot insert new row: %s"),
                                  db_get_string(&sql));
                }
            }

            OGR_F_Destroy(Ogr_feature);
            cat++;
        }
        G_percent(1, 1, 1);	/* finish it */

        if (!flag.notab->answer) {
            db_commit_transaction(driver);
            db_close_database_shutdown_driver(driver);
        }

        if (nogeom > 0)
            G_warning(_("%d %s without geometry"), nogeom,
                      nogeom == 1 ? "feature" : "features");
    }


    separator = "-----------------------------------------------------";
    G_message("%s", separator);

    if (use_tmp_vect) {
        /* TODO: is it necessary to build here? probably not, consumes time */
        /* GV_BUILD_BASE is sufficient to toggle boundary cleaning */
        Vect_build_partial(&Tmp, GV_BUILD_BASE);
    }

    if (use_tmp_vect && !flag.no_clean->answer &&
            Vect_get_num_primitives(Out, GV_BOUNDARY) > 0) {
        int ret, centr, ncentr, otype, n_overlaps, n_nocat;
        CENTR *Centr;
        struct spatial_index si;
        double x, y, total_area, overlap_area, nocat_area;
        struct bound_box box;
        struct line_pnts *Points;
        int nmodif;

        Points = Vect_new_line_struct();

        G_message("%s", separator);

        G_warning(_("Cleaning polygons, result is not guaranteed!"));

        if (snap >= 0) {
            G_message("%s", separator);
            G_message(_("Snapping boundaries (threshold = %.3e)..."), snap);
            Vect_snap_lines(&Tmp, GV_BOUNDARY, snap, NULL);
        }

        /* It is not to clean to snap centroids, but I have seen data with 2 duplicate polygons
         * (as far as decimal places were printed) and centroids were not identical */
        /* Disabled, because overlapping polygons result in many duplicate centroids anyway */
        /*
           fprintf ( stderr, separator );
           fprintf ( stderr, "Snap centroids (threshold 0.000001):\n" );
           Vect_snap_lines ( &Map, GV_CENTROID, 0.000001, NULL, stderr );
         */

        G_message("%s", separator);
        G_message(_("Breaking polygons..."));
        Vect_break_polygons(&Tmp, GV_BOUNDARY, NULL);

        /* It is important to remove also duplicate centroids in case of duplicate input polygons */
        G_message("%s", separator);
        G_message(_("Removing duplicates..."));
        Vect_remove_duplicates(&Tmp, GV_BOUNDARY | GV_CENTROID, NULL);

        /* in non-pathological cases, the bulk of the cleaning is now done */

        /* Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections
         * are created. We must call Vect_break_lines(), Vect_remove_duplicates()
         * and Vect_clean_small_angles_at_nodes() until no more small angles are found */
        do {
            G_message("%s", separator);
            G_message(_("Breaking boundaries..."));
            Vect_break_lines(&Tmp, GV_BOUNDARY, NULL);

            G_message("%s", separator);
            G_message(_("Removing duplicates..."));
            Vect_remove_duplicates(&Tmp, GV_BOUNDARY, NULL);

            G_message("%s", separator);
            G_message(_("Cleaning boundaries at nodes..."));
            nmodif =
                Vect_clean_small_angles_at_nodes(&Tmp, GV_BOUNDARY, NULL);
        } while (nmodif > 0);

        /* merge boundaries */
        G_message("%s", separator);
        G_message(_("Merging boundaries..."));
        Vect_merge_lines(&Tmp, GV_BOUNDARY, NULL, NULL);

        G_message("%s", separator);
        if (type & GV_BOUNDARY) {	/* that means lines were converted to boundaries */
            G_message(_("Changing boundary dangles to lines..."));
            Vect_chtype_dangles(&Tmp, -1.0, NULL);
        }
        else {
            G_message(_("Removing dangles..."));
            Vect_remove_dangles(&Tmp, GV_BOUNDARY, -1.0, NULL);
        }

        G_message("%s", separator);
        if (type & GV_BOUNDARY) {
            G_message(_("Changing boundary bridges to lines..."));
            Vect_chtype_bridges(&Tmp, NULL);
        }
        else {
            G_message(_("Removing bridges..."));
            Vect_remove_bridges(&Tmp, NULL);
        }

        /* Boundaries are hopefully clean, build areas */
        G_message("%s", separator);
        Vect_build_partial(&Tmp, GV_BUILD_ATTACH_ISLES);

        /* Calculate new centroids for all areas, centroids have the same id as area */
        ncentr = Vect_get_num_areas(&Tmp);
        G_debug(3, "%d centroids/areas", ncentr);

        Centr = (CENTR *) G_calloc(ncentr + 1, sizeof(CENTR));
        Vect_spatial_index_init(&si, 0);
        for (centr = 1; centr <= ncentr; centr++) {
            Centr[centr].valid = 0;
            Centr[centr].cats = Vect_new_cats_struct();
            ret = Vect_get_point_in_area(&Tmp, centr, &x, &y);
            if (ret < 0) {
                G_warning(_("Unable to calculate area centroid"));
                continue;
            }

            Centr[centr].x = x;
            Centr[centr].y = y;
            Centr[centr].valid = 1;
            box.N = box.S = y;
            box.E = box.W = x;
            box.T = box.B = 0;
            Vect_spatial_index_add_item(&si, centr, &box);
        }

        /* Go through all layers and find centroids for each polygon */
        for (layer = 0; layer < nlayers; layer++) {
            G_message("%s", separator);
            G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]);
            layer_id = layers[layer];
            Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
            n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
            OGR_L_ResetReading(Ogr_layer);

            cat = 0;		/* field = layer + 1 */
            G_percent(cat, n_features, 2);
            while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
                cat++;
                G_percent(cat, n_features, 2);
                /* Geometry */
                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
                if (Ogr_geometry != NULL) {
                    centroid(Ogr_geometry, Centr, &si, layer + 1, cat,
                             min_area, type);
                }

                OGR_F_Destroy(Ogr_feature);
            }
        }

        /* Write centroids */
        G_message("%s", separator);
        G_message(_("Writing centroids..."));

        n_overlaps = n_nocat = 0;
        total_area = overlap_area = nocat_area = 0.0;
        for (centr = 1; centr <= ncentr; centr++) {
            double area;

            G_percent(centr, ncentr, 2);

            area = Vect_get_area_area(&Tmp, centr);
            total_area += area;

            if (!(Centr[centr].valid)) {
                continue;
            }

            if (Centr[centr].cats->n_cats == 0) {
                nocat_area += area;
                n_nocat++;
                continue;
            }

            if (Centr[centr].cats->n_cats > 1) {
                Vect_cat_set(Centr[centr].cats, nlayers + 1,
                             Centr[centr].cats->n_cats);
                overlap_area += area;
                n_overlaps++;
            }

            Vect_reset_line(Points);
            Vect_append_point(Points, Centr[centr].x, Centr[centr].y, 0.0);
            if (type & GV_POINT)
                otype = GV_POINT;
            else
                otype = GV_CENTROID;
            Vect_write_line(&Tmp, otype, Points, Centr[centr].cats);
        }
        if (Centr)
            G_free(Centr);

        Vect_spatial_index_destroy(&si);

        if (n_overlaps > 0) {
            G_warning(_("%d areas represent more (overlapping) features, because polygons overlap "
                        "in input layer(s). Such areas are linked to more than 1 row in attribute table. "
                        "The number of features for those areas is stored as category in layer %d"),
                      n_overlaps, nlayers + 1);
        }

        G_message("%s", separator);

        Vect_hist_write(&Map, separator);
        Vect_hist_write(&Map, "\n");
        sprintf(buf, _("%d input polygons\n"), n_polygons);
        G_message(_("%d input polygons"), n_polygons);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Total area: %G (%d areas)\n"), total_area, ncentr);
        G_message(_("Total area: %G (%d areas)"), total_area, ncentr);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Overlapping area: %G (%d areas)\n"), overlap_area,
                n_overlaps);
        G_message(_("Overlapping area: %G (%d areas)"), overlap_area,
                  n_overlaps);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Area without category: %G (%d areas)\n"), nocat_area,
                n_nocat);
        G_message(_("Area without category: %G (%d areas)"), nocat_area,
                  n_nocat);
        Vect_hist_write(&Map, buf);
        G_message("%s", separator);
    }

    /* needed?
     * OGR_DS_Destroy( Ogr_ds );
     */

    if (use_tmp_vect) {
        /* Copy temporary vector to output vector */
        Vect_copy_map_lines(&Tmp, &Map);
        /* release memory occupied by topo, we may need that memory for main output */
        Vect_set_release_support(&Tmp);
        Vect_close(&Tmp);
        Vect_delete(tempvect);
    }

    Vect_build(&Map);
    Vect_close(&Map);

    /* -------------------------------------------------------------------- */
    /*      Extend current window based on dataset.                         */
    /* -------------------------------------------------------------------- */
    if (flag.extend->answer) {
        G_get_default_window(&loc_wind);

        loc_wind.north = MAX(loc_wind.north, cellhd.north);
        loc_wind.south = MIN(loc_wind.south, cellhd.south);
        loc_wind.west = MIN(loc_wind.west, cellhd.west);
        loc_wind.east = MAX(loc_wind.east, cellhd.east);

        loc_wind.rows = (int)ceil((loc_wind.north - loc_wind.south)
                                  / loc_wind.ns_res);
        loc_wind.south = loc_wind.north - loc_wind.rows * loc_wind.ns_res;

        loc_wind.cols = (int)ceil((loc_wind.east - loc_wind.west)
                                  / loc_wind.ew_res);
        loc_wind.east = loc_wind.west + loc_wind.cols * loc_wind.ew_res;

        G__put_window(&loc_wind, "../PERMANENT", "DEFAULT_WIND");
    }

    if (with_z && !flag.z->answer)
        G_warning(_("Input data contains 3D features. Created vector is 2D only, "
                    "use -z flag to import 3D vector."));

    exit(EXIT_SUCCESS);
}
コード例 #5
0
ファイル: main.c プロジェクト: imincik/pkg-grass
int main(int argc, char *argv[])
{
    struct dxf_file *dxf;
    struct Map_info *Map;
    char *output = NULL;

    struct GModule *module;
    struct
    {
	struct Flag *list;
	struct Flag *extent;
	struct Flag *table;
	struct Flag *topo;
	struct Flag *invert;
	struct Flag *one_layer;
	struct Flag *frame;
    } flag;
    struct
    {
	struct Option *input;
	struct Option *output;
	struct Option *layers;
    } opt;

    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("vector, import");
    module->description =
	_("Converts files in DXF format to GRASS vector map format.");

    flag.extent = G_define_flag();
    flag.extent->key = 'e';
    flag.extent->description = _("Ignore the map extent of DXF file");

    flag.table = G_define_flag();
    flag.table->key = 't';
    flag.table->description = _("Do not create attribute tables");

    flag.topo = G_define_flag();
    flag.topo->key = 'b';
    flag.topo->description = _("Do not build topology");

    flag.frame = G_define_flag();
    flag.frame->key = 'f';
    flag.frame->description = _("Import polyface meshes as 3D wire frame");

    flag.list = G_define_flag();
    flag.list->key = 'l';
    flag.list->description = _("List available layers and exit");
    flag.list->guisection = _("DXF layers");

    flag.invert = G_define_flag();
    flag.invert->key = 'i';
    flag.invert->description =
	_("Invert selection by layers (don't import layers in list)");
    flag.invert->guisection = _("DXF layers");

    flag.one_layer = G_define_flag();
    flag.one_layer->key = '1';
    flag.one_layer->description = _("Import all objects into one layer");
    flag.one_layer->guisection = _("DXF layers");

    opt.input = G_define_standard_option(G_OPT_F_INPUT);
    opt.input->description = _("Name of input DXF file");

    opt.output = G_define_standard_option(G_OPT_V_OUTPUT);
    opt.output->required = NO;

    opt.layers = G_define_option();
    opt.layers->key = "layers";
    opt.layers->type = TYPE_STRING;
    opt.layers->required = NO;
    opt.layers->multiple = YES;
    opt.layers->description = _("List of layers to import");
    opt.layers->guisection = _("DXF layers");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    flag_list = flag.list->answer;
    flag_extent = flag.extent->answer;
    flag_table = flag.table->answer;
    flag_invert = flag.invert->answer;
    flag_one_layer = flag.one_layer->answer;
    flag_frame = flag.frame->answer;

    /* open DXF file */
    if (!(dxf = dxf_open(opt.input->answer)))
	G_fatal_error(_("Unable to open DXF file <%s>"), opt.input->answer);

    if (flag_list) {
	num_layers = 0;
	layers = NULL;
	Map = NULL;
    }
    else {
	/* make vector map name SQL compliant */
	if (opt.output->answer) {
	    output = G_store(opt.output->answer);
	}
	else {
	    char *p, *p2;

	    if ((p = G_rindex(dxf->name, '/')))
		p++;
	    else
		p = dxf->name;
	    output = G_store(p);
	    if ((p2 = G_rindex(p, '.')))
		output[p2 - p] = 0;
	}
	{
	    char *p;

	    for (p = output; *p; p++)
		if (*p == '.')
		    *p = '_';
	}

	layers = opt.layers->answers;

	if (!G_check_overwrite(argc, argv) &&
	    G_find_vector2(output, G_mapset())) {
	    G_fatal_error(_("Option <%s>: <%s> exists."), opt.output->key,
			  output);
	}

	if (Vect_legal_filename(output) < 0)
	    G_fatal_error(_("Use '%s' option to change vector map name"),
			  opt.output->key);

	/* create vector map */
	Map = (struct Map_info *)G_malloc(sizeof(struct Map_info));
	if (Vect_open_new(Map, output, 1) < 0)
	    G_fatal_error(_("Unable to create vector map <%s>"), output);

	Vect_set_map_name(Map, output);

	Vect_hist_command(Map);
    }

    /* import */
    dxf_to_vect(dxf, Map);

    dxf_close(dxf);

    if (flag_list)
	init_list();
    else {
	Vect_close(Map);

	if (found_layers) {
	    if (Vect_open_old(Map, output, G_mapset())) {
		if (!flag_topo)
		    if (!Vect_build(Map))
			G_warning(_("Building topology failed"));
		Vect_close(Map);
	    }
	}
	else {
	    Vect_delete(output);
	    G_fatal_error(_("Failed to import DXF file!"));
	}

	G_free(output);
	G_free(Map);
    }

    G_done_msg(" ");

    exit(EXIT_SUCCESS);
}
コード例 #6
0
ファイル: main.c プロジェクト: AsherBond/MondocosmOS
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct GParams params;
    struct Map_info Map;
    struct Map_info **BgMap;	/* backgroud vector maps */
    int nbgmaps;		/* number of registrated background maps */
    enum mode action_mode;
    FILE *ascii;

    int i;
    int move_first, snap;
    int ret, layer;
    double move_x, move_y, move_z, thresh[3];

    struct line_pnts *coord;

    struct ilist *List;

    struct cat_list *Clist;

    ascii = NULL;
    List = NULL;
    BgMap = NULL;
    nbgmaps = 0;
    coord = NULL;
    Clist = NULL;

    G_gisinit(argv[0]);

    module = G_define_module();
    module->overwrite = TRUE;
    G_add_keyword(_("vector"));
    G_add_keyword(_("editing"));
    G_add_keyword(_("geometry"));
    module->description = _("Edits a vector map, allows adding, deleting "
			    "and modifying selected vector features.");

    if (!parser(argc, argv, &params, &action_mode))
	exit(EXIT_FAILURE);

    /* get list of categories */
    Clist = Vect_new_cat_list();
    if (params.cat->answer && Vect_str_to_cat_list(params.cat->answer, Clist)) {
	G_fatal_error(_("Unable to get category list <%s>"),
		      params.cat->answer);
    }

    /* open input file */
    if (params.in->answer) {
	if (strcmp(params.in->answer, "-") != 0) {
	    ascii = fopen(params.in->answer, "r");
	    if (ascii == NULL)
		G_fatal_error(_("Unable to open file <%s>"),
			      params.in->answer);
	}
	else {
	    ascii = stdin;
	}
    }
    if (!ascii && action_mode == MODE_ADD)
	G_fatal_error(_("Required parameter <%s> not set"), params.in->key);
    
    if (action_mode == MODE_CREATE) {
	int overwrite;

	overwrite = G_check_overwrite(argc, argv);
	if (G_find_vector2(params.map->answer, G_mapset())) {
	    if (!overwrite)
		G_fatal_error(_("Vector map <%s> already exists"),
			      params.map->answer);
	}

	/* 3D vector maps? */
	ret = Vect_open_new(&Map, params.map->answer, WITHOUT_Z);
	if (Vect_maptype(&Map) == GV_FORMAT_OGR_DIRECT) {
	    int type;
	    type = Vect_option_to_types(params.type);
	    if (type != GV_POINT && type != GV_LINE &&
		type != GV_BOUNDARY)
		G_fatal_error(_("Supported feature type for OGR layer: "
				"%s, %s or %s"), "point", "line", "boundary");
	    V2_open_new_ogr(&Map, type);
	}
	if (ret == -1) {
	    G_fatal_error(_("Unable to create vector map <%s>"),
			  params.map->answer);
	}

	G_debug(1, "Map created");

	if (ascii) {
	    /* also add new vector features */
	    action_mode = MODE_ADD;
	}
    }
    else {			/* open selected vector file */
	if (action_mode == MODE_ADD)	/* write */
	    ret = Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
	else			/* read-only -- select features */
	    ret = Vect_open_old2(&Map, params.map->answer, G_mapset(), params.fld->answer);

	if (ret < 2)
	    G_fatal_error(_("Unable to open vector map <%s> at topological level %d"),
			  params.map->answer, 2);
    }

    G_debug(1, "Map opened");

    /* open backgroud maps */
    if (params.bmaps->answer) {
	i = 0;

	while (params.bmaps->answers[i]) {
	    const char *bmap = params.bmaps->answers[i];
	    const char *mapset = G_find_vector2(bmap, "");
	    if (!mapset)
		G_fatal_error(_("Vector map <%s> not found"), bmap);

	    if (strcmp(
		    G_fully_qualified_name(params.map->answer, G_mapset()),
		    G_fully_qualified_name(bmap, mapset)) == 0) {
		G_fatal_error(_("Unable to open vector map <%s> as the background map. "
			       "It is given as vector map to be edited."),
			      bmap);
	    }
	    nbgmaps++;
	    BgMap = (struct Map_info **)G_realloc(
		BgMap, nbgmaps * sizeof(struct Map_info *));
	    BgMap[nbgmaps - 1] =
		(struct Map_info *)G_malloc(sizeof(struct Map_info));
	    if (Vect_open_old(BgMap[nbgmaps - 1], bmap, "") == -1)
		G_fatal_error(_("Unable to open vector map <%s>"), bmap);
	    G_verbose_message(_("Background vector map <%s> registered"), bmap);
	    i++;
	}
    }

    layer = Vect_get_field_number(&Map, params.fld->answer);
    i = 0;
    while (params.maxdist->answers[i]) {
	switch (i) {
	case THRESH_COORDS:
	    thresh[THRESH_COORDS] =
		max_distance(atof(params.maxdist->answers[THRESH_COORDS]));
	    thresh[THRESH_SNAP] = thresh[THRESH_QUERY] =
		thresh[THRESH_COORDS];
	    break;
	case THRESH_SNAP:
	    thresh[THRESH_SNAP] =
		max_distance(atof(params.maxdist->answers[THRESH_SNAP]));
	    break;
	case THRESH_QUERY:
	    thresh[THRESH_QUERY] =
		atof(params.maxdist->answers[THRESH_QUERY]);
	    break;
	default:
	    break;
	}
	i++;
    }

    move_first = params.move_first->answer ? 1 : 0;
    snap = NO_SNAP;
    if (strcmp(params.snap->answer, "node") == 0)
	snap = SNAP;
    else if (strcmp(params.snap->answer, "vertex") == 0)
	snap = SNAPVERTEX;
    if (snap != NO_SNAP && thresh[THRESH_SNAP] <= 0) {
	G_warning(_("Threshold for snapping must be > 0. No snapping applied."));
	snap = NO_SNAP;
    }
    
    if (action_mode != MODE_CREATE && action_mode != MODE_ADD) {
	/* select lines */
	List = Vect_new_list();
	G_message(_("Selecting features..."));
	if (action_mode == MODE_COPY && BgMap && BgMap[0]) {
	    List = select_lines(BgMap[0], action_mode, &params, thresh, List);
	}
	else {
	    List = select_lines(&Map, action_mode, &params, thresh, List);
	}
    }

    if ((action_mode != MODE_CREATE && action_mode != MODE_ADD &&
	 action_mode != MODE_SELECT)) {
	if (List->n_values < 1) {
	    G_warning(_("No features selected, nothing to edit"));
	    action_mode = MODE_NONE;
	    ret = 0;
	}
	else {
	    /* reopen the map for updating */
	    if (action_mode == MODE_ZBULK && !Vect_is_3d(&Map)) {
		Vect_close(&Map);
		G_fatal_error(_("Vector map <%s> is not 3D. Tool '%s' requires 3D vector map. "
			       "Please convert the vector map "
			       "to 3D using e.g. %s."), params.map->answer,
			      params.tool->answer, "v.extrude");
	    }
	    Vect_close(&Map);

	    Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
	}
    }

    /* coords option -> array */
    if (params.coord->answers) {
	coord = Vect_new_line_struct();
	int i = 0;
	double east, north;

	while (params.coord->answers[i]) {
	    east = atof(params.coord->answers[i]);
	    north = atof(params.coord->answers[i + 1]);
	    Vect_append_point(coord, east, north, 0.0);
	    i += 2;
	}
    }

    /* perform requested editation */
    switch (action_mode) {
    case MODE_CREATE:
	break;
    case MODE_ADD:
	if (!params.header->answer)
	    Vect_read_ascii_head(ascii, &Map);
	int num_lines;
	num_lines = Vect_get_num_lines(&Map);
	
	ret = Vect_read_ascii(ascii, &Map);
	G_message(_("%d features added"), ret);
	if (ret > 0) {
	    int iline;
	    struct ilist *List_added;
	    
	    List_added = Vect_new_list();
	    for (iline = num_lines + 1; iline <= Vect_get_num_lines(&Map); iline++)
		Vect_list_append(List_added, iline);
	    
	    G_verbose_message(_("Threshold value for snapping is %.2f"),
			      thresh[THRESH_SNAP]);
	    if (snap != NO_SNAP) { /* apply snapping */
		/* snap to vertex ? */
		Vedit_snap_lines(&Map, BgMap, nbgmaps, List_added,
				 thresh[THRESH_SNAP],
				 snap == SNAP ? FALSE : TRUE); 
	    }
	    if (params.close->answer) {	/* close boundaries */
		int nclosed;

		nclosed = close_lines(&Map, GV_BOUNDARY, thresh[THRESH_SNAP]);
		G_message(_("%d boundaries closed"), nclosed);
	    }
	    Vect_destroy_list(List_added);
	}
	break;
    case MODE_DEL:
	ret = Vedit_delete_lines(&Map, List);
	G_message(_("%d features deleted"), ret);
	break;
    case MODE_MOVE:
	move_x = atof(params.move->answers[0]);
	move_y = atof(params.move->answers[1]);
	move_z = atof(params.move->answers[2]);
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_move_lines(&Map, BgMap, nbgmaps, List, move_x, move_y, move_z, snap, thresh[THRESH_SNAP]);
	G_message(_("%d features moved"), ret);
	break;
    case MODE_VERTEX_MOVE:
	move_x = atof(params.move->answers[0]);
	move_y = atof(params.move->answers[1]);
	move_z = atof(params.move->answers[2]);
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_move_vertex(&Map, BgMap, nbgmaps, List, coord, thresh[THRESH_COORDS], thresh[THRESH_SNAP], move_x, move_y, move_z, move_first, snap);
	G_message(_("%d vertices moved"), ret);
	break;
    case MODE_VERTEX_ADD:
	ret = Vedit_add_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
	G_message(_("%d vertices added"), ret);
	break;
    case MODE_VERTEX_DELETE:
	ret = Vedit_remove_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
	G_message(_("%d vertices removed"), ret);
	break;
    case MODE_BREAK:
	if (params.coord->answer) {
	    ret = Vedit_split_lines(&Map, List,
				    coord, thresh[THRESH_COORDS], NULL);
	}
	else {
	    ret = Vect_break_lines_list(&Map, List, NULL, GV_LINES, NULL);
	}
	G_message(_("%d lines broken"), ret);
	break;
    case MODE_CONNECT:
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_connect_lines(&Map, List, thresh[THRESH_SNAP]);
	G_message(_("%d lines connected"), ret);
	break;
    case MODE_MERGE:
	ret = Vedit_merge_lines(&Map, List);
	G_message(_("%d lines merged"), ret);
	break;
    case MODE_SELECT:
	ret = print_selected(List);
	break;
    case MODE_CATADD:
	ret = Vedit_modify_cats(&Map, List, layer, 0, Clist);
	G_message(_("%d features modified"), ret);
	break;
    case MODE_CATDEL:
	ret = Vedit_modify_cats(&Map, List, layer, 1, Clist);
	G_message(_("%d features modified"), ret);
	break;
    case MODE_COPY:
	if (BgMap && BgMap[0]) {
	    if (nbgmaps > 1)
		G_warning(_("Multiple background maps were given. "
			    "Selected features will be copied only from "
			    "vector map <%s>."),
			  Vect_get_full_name(BgMap[0]));

	    ret = Vedit_copy_lines(&Map, BgMap[0], List);
	}
	else {
	    ret = Vedit_copy_lines(&Map, NULL, List);
	}
	G_message(_("%d features copied"), ret);
	break;
    case MODE_SNAP:
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = snap_lines(&Map, List, thresh[THRESH_SNAP]);
	break;
    case MODE_FLIP:
	ret = Vedit_flip_lines(&Map, List);
	G_message(_("%d lines flipped"), ret);
	break;
    case MODE_NONE:
	break;
    case MODE_ZBULK:{
	    double start, step;
	    double x1, y1, x2, y2;

	    start = atof(params.zbulk->answers[0]);
	    step = atof(params.zbulk->answers[1]);

	    x1 = atof(params.bbox->answers[0]);
	    y1 = atof(params.bbox->answers[1]);
	    x2 = atof(params.bbox->answers[2]);
	    y2 = atof(params.bbox->answers[3]);

	    ret = Vedit_bulk_labeling(&Map, List,
				      x1, y1, x2, y2, start, step);

	    G_message(_("%d lines labeled"), ret);
	    break;
	}
    case MODE_CHTYPE:{
	    ret = Vedit_chtype_lines(&Map, List);

	    if (ret > 0) {
		G_message(_("%d features converted"), ret);
	    }
	    else {
		G_message(_("No feature modified"));
	    }
	    break;
	}
    default:
	G_warning(_("Operation not implemented"));
	ret = -1;
	break;
    }
    
    Vect_hist_command(&Map);

    /* build topology only if requested or if tool!=select */
    if (!(action_mode == MODE_SELECT || params.topo->answer == 1 ||
	 !MODE_NONE)) {
	Vect_build_partial(&Map, GV_BUILD_NONE);
	Vect_build(&Map);
    }

    if (List)
	Vect_destroy_list(List);

    Vect_close(&Map);

    G_debug(1, "Map closed");

    /* close background maps */
    for (i = 0; i < nbgmaps; i++) {
	Vect_close(BgMap[i]);
	G_free((void *)BgMap[i]);
    }
    G_free((void *)BgMap);

    if (coord)
	Vect_destroy_line_struct(coord);

    if (Clist)
	Vect_destroy_cat_list(Clist);

    G_done_msg(" ");

    if (ret > -1) {
	exit(EXIT_SUCCESS);
    }
    else {
	exit(EXIT_FAILURE);
    }
}
コード例 #7
0
ファイル: main.c プロジェクト: felipebetancur/grass-ci
int main(int argc, char *argv[])
{
    struct History history;
    struct GModule *module;
    char *desc;

    struct Cell_head cellhd, orig_cellhd;

    void *inrast, *outrast;
    int infd, outfd;
    void *ptr;
    int nrows, ncols, row, col;

    RASTER_MAP_TYPE in_data_type;

    struct Option *input_prefix, *output_prefix, *metfn, *sensor, *adate,
	*pdate, *elev, *bgain, *metho, *perc, *dark, *atmo, *lsatmet, *oscale;
    char *inputname, *met, *outputname, *sensorname;
    struct Flag *frad, *print_meta, *named;

    lsat_data lsat;
    char band_in[GNAME_MAX], band_out[GNAME_MAX];
    int i, j, q, method, pixel, dn_dark[MAX_BANDS], dn_mode[MAX_BANDS], dn_sat;
    int overwrite;
    double qcal, rad, ref, percent, ref_mode, rayleigh, scale;
    unsigned long hist[QCALMAX], h_max;

    struct Colors colors;
    struct FPRange range;
    double min, max;

    /* initialize GIS environment */
    G_gisinit(argv[0]);

    /* initialize module */
    module = G_define_module();
    module->description =
	_("Calculates top-of-atmosphere radiance or reflectance and temperature for Landsat MSS/TM/ETM+/OLI");
    G_add_keyword(_("imagery"));
    G_add_keyword(_("radiometric conversion"));
    G_add_keyword(_("radiance"));
    G_add_keyword(_("reflectance"));
    G_add_keyword(_("brightness temperature"));
    G_add_keyword(_("Landsat"));
    G_add_keyword(_("atmospheric correction"));
    module->overwrite = TRUE;

    /* It defines the different parameters */
    input_prefix = G_define_standard_option(G_OPT_R_BASENAME_INPUT);
    input_prefix->label = _("Base name of input raster bands");
    input_prefix->description = _("Example: 'B.' for B.1, B.2, ...");

    output_prefix = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT);
    output_prefix->label = _("Prefix for output raster maps");
    output_prefix->description =
	_("Example: 'B.toar.' generates B.toar.1, B.toar.2, ...");

    metfn = G_define_standard_option(G_OPT_F_INPUT);
    metfn->key = "metfile";
    metfn->required = NO;
    metfn->description = _("Name of Landsat metadata file (.met or MTL.txt)");
    metfn->guisection = _("Metadata");

    sensor = G_define_option();
    sensor->key = "sensor";
    sensor->type = TYPE_STRING;
    sensor->label = _("Spacecraft sensor");
    sensor->description = _("Required only if 'metfile' not given (recommended for sanity)");
    sensor->options = "mss1,mss2,mss3,mss4,mss5,tm4,tm5,tm7,oli8";
    desc = NULL;
    G_asprintf(&desc,
	        "mss1;%s;mss2;%s;mss3;%s;mss4;%s;mss5;%s;tm4;%s;tm5;%s;tm7;%s;oli8;%s",
	        _("Landsat-1 MSS"),
	        _("Landsat-2 MSS"),
	        _("Landsat-3 MSS"),
	        _("Landsat-4 MSS"),
	        _("Landsat-5 MSS"),
	        _("Landsat-4 TM"),
	        _("Landsat-5 TM"),
	        _("Landsat-7 ETM+"),
	        _("Landsat_8 OLI/TIRS"));
    sensor->descriptions = desc;
    sensor->required = NO;	/* perhaps YES for clarity */
    sensor->guisection = _("Metadata");

    metho = G_define_option();
    metho->key = "method";
    metho->type = TYPE_STRING;
    metho->required = NO;
    metho->options = "uncorrected,dos1,dos2,dos2b,dos3,dos4";
    metho->label = _("Atmospheric correction method");
    metho->description = _("Atmospheric correction method");
    metho->answer = "uncorrected";
    metho->guisection = _("Metadata");

    adate = G_define_option();
    adate->key = "date";
    adate->type = TYPE_STRING;
    adate->required = NO;
    adate->key_desc = "yyyy-mm-dd";
    adate->label = _("Image acquisition date (yyyy-mm-dd)");
    adate->description = _("Required only if 'metfile' not given");
    adate->guisection = _("Metadata");

    elev = G_define_option();
    elev->key = "sun_elevation";
    elev->type = TYPE_DOUBLE;
    elev->required = NO;
    elev->label = _("Sun elevation in degrees");
    elev->description = _("Required only if 'metfile' not given");
    elev->guisection = _("Metadata");

    pdate = G_define_option();
    pdate->key = "product_date";
    pdate->type = TYPE_STRING;
    pdate->required = NO;
    pdate->key_desc = "yyyy-mm-dd";
    pdate->label = _("Image creation date (yyyy-mm-dd)");
    pdate->description = _("Required only if 'metfile' not given");
    pdate->guisection = _("Metadata");

    bgain = G_define_option();
    bgain->key = "gain";
    bgain->type = TYPE_STRING;
    bgain->required = NO;
    bgain->label = _("Gain (H/L) of all Landsat ETM+ bands (1-5,61,62,7,8)");
    bgain->description = _("Required only if 'metfile' not given");
    bgain->guisection = _("Settings");

    perc = G_define_option();
    perc->key = "percent";
    perc->type = TYPE_DOUBLE;
    perc->required = NO;
    perc->label = _("Percent of solar radiance in path radiance");
    perc->description = _("Required only if 'method' is any DOS");
    perc->answer = "0.01";
    perc->guisection = _("Settings");

    dark = G_define_option();
    dark->key = "pixel";
    dark->type = TYPE_INTEGER;
    dark->required = NO;
    dark->label =
	_("Minimum pixels to consider digital number as dark object");
    dark->description = _("Required only if 'method' is any DOS");
    dark->answer = "1000";
    dark->guisection = _("Settings");

    atmo = G_define_option();
    atmo->key = "rayleigh";
    atmo->type = TYPE_DOUBLE;
    atmo->required = NO;
    atmo->label = _("Rayleigh atmosphere (diffuse sky irradiance)");	/* scattering coefficient? */
    atmo->description = _("Required only if 'method' is DOS3");
    atmo->answer = "0.0";
    atmo->guisection = _("Settings");

    lsatmet = G_define_option();
    lsatmet->key = "lsatmet";
    lsatmet->type = TYPE_STRING;
    lsatmet->required = NO;
    lsatmet->multiple = YES;
    lsatmet->label = _("return value stored for a given metadata");
    lsatmet->description = _("Required only if 'metfile' and -p given");
    lsatmet->options =
	"number,creation,date,sun_elev,sensor,bands,sunaz,time";
    desc = NULL;
    G_asprintf(&desc,
	       "number;%s;creation;%s;date;%s;sun_elev;%s;sensor;%s;bands;%s;sunaz;%s;time;%s",
	       _("Landsat Number"),
	       _("Creation timestamp"),
	       _("Date"),
	       _("Sun Elevation"),
	       _("Sensor"),
	       _("Bands count"), _("Sun Azimuth Angle"), _("Time"));
    lsatmet->descriptions = desc;
    lsatmet->guisection = _("Settings");

    oscale = G_define_option();
    oscale->key = "scale";
    oscale->type = TYPE_DOUBLE;
    oscale->answer = "1.0";
    oscale->required = NO;
    oscale->description = _("Scale factor for output");

    /* define the different flags */
    frad = G_define_flag();
    frad->key = 'r';
    frad->description =
	_("Output at-sensor radiance instead of reflectance for all bands");

    named = G_define_flag();
    named->key = 'n';
    named->description =
	_("Input raster maps use as extension the number of the band instead the code");

    print_meta = G_define_flag();
    print_meta->key = 'p';
    print_meta->description = _("Print output metadata info");

    /* options and afters parser */
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


  /*****************************************
  * ---------- START --------------------
  * Stores options and flags to variables
  *****************************************/
    met = metfn->answer;
    inputname = input_prefix->answer;
    outputname = output_prefix->answer;
    sensorname = sensor->answer ? sensor->answer : "";

    overwrite = G_check_overwrite(argc, argv);

    Rast_get_window(&orig_cellhd);

    G_zero(&lsat, sizeof(lsat));

    if (adate->answer != NULL) {
	strncpy(lsat.date, adate->answer, 11);
	lsat.date[10] = '\0';
	if (strlen(lsat.date) != 10)
	    G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"),
			  lsat.date);
    }

    if (pdate->answer != NULL) {
	strncpy(lsat.creation, pdate->answer, 11);
	lsat.creation[10] = '\0';
	if (strlen(lsat.creation) != 10)
	    G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"),
			  lsat.creation);
    }

    lsat.sun_elev = elev->answer == NULL ? 0. : atof(elev->answer);

    percent = atof(perc->answer);
    pixel = atoi(dark->answer);
    rayleigh = atof(atmo->answer);
    scale = atof(oscale->answer);

    /*
     * Data from metadata file
     */
    lsat.flag = NOMETADATAFILE;	/* Unnecessary because G_zero filled, but for sanity */
    if (met != NULL) {
	lsat.flag = METADATAFILE;
	lsat_metadata(met, &lsat);
	if (print_meta->answer) {
	    char *lsatmeta;

	    if (lsatmet->answer == NULL) {
		G_fatal_error(_("Please use a metadata keyword with -p"));
	    }

	    for (i = 0; lsatmet->answers[i] != NULL; i++) {
		lsatmeta = lsatmet->answers[i];

		if (strcmp(lsatmeta, "number") == 0) {
		    fprintf(stdout, "number=%d\n", lsat.number);
		}
		if (strcmp(lsatmeta, "creation") == 0) {
		    fprintf(stdout, "creation=%s\n", lsat.creation);
		}
		if (strcmp(lsatmeta, "date") == 0) {
		    fprintf(stdout, "date=%s\n", lsat.date);
		}
		if (strcmp(lsatmeta, "sun_elev") == 0) {
		    fprintf(stdout, "sun_elev=%f\n", lsat.sun_elev);
		}
		if (strcmp(lsatmeta, "sunaz") == 0) {
		    fprintf(stdout, "sunaz=%f\n", lsat.sun_az);
		}
		if (strcmp(lsatmeta, "sensor") == 0) {
		    fprintf(stdout, "sensor=%s\n", lsat.sensor);
		}
		if (strcmp(lsatmeta, "bands") == 0) {
		    fprintf(stdout, "bands=%d\n", lsat.bands);
		}
		if (strcmp(lsatmet->answer, "time") == 0) {
		    fprintf(stdout, "%f\n", lsat.time);
		}
	    }
	    exit(EXIT_SUCCESS);
	}
	G_debug(1, "lsat.number = %d, lsat.sensor = [%s]",
		lsat.number, lsat.sensor);

	if (!lsat.sensor || lsat.number > 8 || lsat.number < 1)
	    G_fatal_error(_("Failed to identify satellite"));

	G_debug(1, "Landsat-%d %s with data set in metadata file [%s]",
		lsat.number, lsat.sensor, met);

	if (elev->answer != NULL) {
	    lsat.sun_elev = atof(elev->answer);
	    G_warning("Overwriting solar elevation of metadata file");
	}
    }
    /*
     * Data from command line
     */
    else if (adate->answer == NULL || elev->answer == NULL) {
	G_fatal_error(_("Lacking '%s' and/or '%s' for this satellite"),
		      adate->key, elev->key);
    }
    else {
	if (strcmp(sensorname, "tm7") == 0) {
	    if (bgain->answer == NULL || strlen(bgain->answer) != 9)
		G_fatal_error(_("Landsat-7 requires band gain with 9 (H/L) characters"));
	    set_ETM(&lsat, bgain->answer);
	}
	else if (strcmp(sensorname, "oli8") == 0)
	    set_OLI(&lsat);
	else if (strcmp(sensorname, "tm5") == 0)
	    set_TM5(&lsat);
	else if (strcmp(sensorname, "tm4") == 0)
	    set_TM4(&lsat);
	else if (strcmp(sensorname, "mss5") == 0)
	    set_MSS5(&lsat);
	else if (strcmp(sensorname, "mss4") == 0)
	    set_MSS4(&lsat);
	else if (strcmp(sensorname, "mss3") == 0)
	    set_MSS3(&lsat);
	else if (strcmp(sensorname, "mss2") == 0)
	    set_MSS2(&lsat);
	else if (strcmp(sensorname, "mss1") == 0)
	    set_MSS1(&lsat);
	else
	    G_fatal_error(_("Unknown satellite type (defined by '%s')"),
			  sensorname);
    }

	/*****************************************
	* ------------ PREPARATION --------------
	*****************************************/
    if (strcasecmp(metho->answer, "corrected") == 0)	/* deleted 2013 */
	method = CORRECTED;
    else if (strcasecmp(metho->answer, "dos1") == 0)
	method = DOS1;
    else if (strcasecmp(metho->answer, "dos2") == 0)
	method = DOS2;
    else if (strcasecmp(metho->answer, "dos2b") == 0)
	method = DOS2b;
    else if (strcasecmp(metho->answer, "dos3") == 0)
	method = DOS3;
    else if (strcasecmp(metho->answer, "dos4") == 0)
	method = DOS4;
    else
	method = UNCORRECTED;

    /*
       if (metho->answer[3] == '2') method = (metho->answer[4] == '\0') ? DOS2 : DOS2b;
       else if (metho->answer[3] == '1') method = DOS1;
       else if (metho->answer[3] == '3') method = DOS3;
       else if (metho->answer[3] == '4') method = DOS4;
       else method = UNCORRECTED;
     */

    for (i = 0; i < lsat.bands; i++) {
	dn_mode[i] = 0;
	dn_dark[i] = (int)lsat.band[i].qcalmin;
	dn_sat = (int)(0.90 * lsat.band[i].qcalmax);
	/* Begin: calculate dark pixel */
	if (method > DOS && !lsat.band[i].thermal) {
	    for (q = 0; q <= lsat.band[i].qcalmax; q++)
		hist[q] = 0L;

	    sprintf(band_in, "%s%d", inputname, lsat.band[i].code);
	    Rast_get_cellhd(band_in, "", &cellhd);
	    Rast_set_window(&cellhd);
	    if ((infd = Rast_open_old(band_in, "")) < 0)
		G_fatal_error(_("Unable to open raster map <%s>"), band_in);

	    in_data_type = Rast_get_map_type(infd);
	    if (in_data_type < 0)
		G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in);
	    inrast = Rast_allocate_buf(in_data_type);

	    nrows = Rast_window_rows();
	    ncols = Rast_window_cols();

	    G_message("Calculating dark pixel of <%s>... ", band_in);
	    for (row = 0; row < nrows; row++) {
		Rast_get_row(infd, inrast, row, in_data_type);
		for (col = 0; col < ncols; col++) {
		    switch (in_data_type) {
		    case CELL_TYPE:
			ptr = (void *)((CELL *) inrast + col);
			q = (int)*((CELL *) ptr);
			break;
		    case FCELL_TYPE:
			ptr = (void *)((FCELL *) inrast + col);
			q = (int)*((FCELL *) ptr);
			break;
		    case DCELL_TYPE:
			ptr = (void *)((DCELL *) inrast + col);
			q = (int)*((DCELL *) ptr);
			break;
		    default:
			ptr = NULL;
			q = -1.;
		    }
		    if (!Rast_is_null_value(ptr, in_data_type) &&
			q >= lsat.band[i].qcalmin &&
			q <= lsat.band[i].qcalmax)
			hist[q]++;
		}
	    }
	    /* DN of dark object */
	    for (j = lsat.band[i].qcalmin; j <= lsat.band[i].qcalmax; j++) {
		if (hist[j] >= (unsigned int)pixel) {
		    dn_dark[i] = j;
		    break;
		}
	    }
	    /* Mode of DN (exclude potentially saturated) */
	    h_max = 0L;
	    for (j = lsat.band[i].qcalmin; j < dn_sat; j++) {
		/* G_debug(5, "%d-%ld", j, hist[j]); */
		if (hist[j] > h_max) {
		    h_max = hist[j];
		    dn_mode[i] = j;
		}
	    }
	    G_verbose_message
		("... DN = %.2d [%lu] : mode %.2d [%lu], excluding DN > %d",
		 dn_dark[i], hist[dn_dark[i]], dn_mode[i], hist[dn_mode[i]],
		 dn_sat);

	    G_free(inrast);
	    Rast_close(infd);
	}
	/* End: calculate dark pixel */

	/* Calculate transformation constants */
	lsat_bandctes(&lsat, i, method, percent, dn_dark[i], rayleigh);
    }

    /*
     * unnecessary or necessary with more checking as acquisition date,...
     * if (strlen(lsat.creation) == 0)
     * G_fatal_error(_("Unknown production date (defined by '%s')"), pdate->key);
     */

    if (G_verbose() > G_verbose_std()) {
	fprintf(stderr, "\n LANDSAT: %d SENSOR: %s\n", lsat.number,
		lsat.sensor);
	fprintf(stderr, " ACQUISITION DATE %s [production date %s]\n",
		lsat.date, lsat.creation);
	fprintf(stderr, "   Earth-sun distance    = %.8lf\n", lsat.dist_es);
	fprintf(stderr, "   Solar elevation angle = %.8lf\n", lsat.sun_elev);
	fprintf(stderr, "   Atmospheric correction: %s\n",
		(method == UNCORRECTED ? "UNCORRECTED" : metho->answer));
	if (method > DOS) {
	    fprintf(stderr,
		    "   Percent of solar irradiance in path radiance = %.4lf\n",
		    percent);
	}
	for (i = 0; i < lsat.bands; i++) {
	    fprintf(stderr, "-------------------\n");
	    fprintf(stderr, " BAND %d %s(code %d)\n", lsat.band[i].number,
		    (lsat.band[i].thermal ? "thermal " : ""),
		    lsat.band[i].code);
	    fprintf(stderr,
		    "   calibrated digital number (DN): %.1lf to %.1lf\n",
		    lsat.band[i].qcalmin, lsat.band[i].qcalmax);
	    fprintf(stderr, "   calibration constants (L): %.5lf to %.5lf\n",
		    lsat.band[i].lmin, lsat.band[i].lmax);
	    fprintf(stderr, "   at-%s radiance = %.8lf * DN + %.5lf\n",
		    (method > DOS ? "surface" : "sensor"), lsat.band[i].gain,
		    lsat.band[i].bias);
	    if (lsat.band[i].thermal) {
		fprintf(stderr,
			"   at-sensor temperature = %.5lf / log[(%.5lf / radiance) + 1.0]\n",
			lsat.band[i].K2, lsat.band[i].K1);
	    }
	    else {
		fprintf(stderr,
			"   mean solar exoatmospheric irradiance (ESUN): %.5lf\n",
			lsat.band[i].esun);
		fprintf(stderr, "   at-%s reflectance = radiance / %.5lf\n",
			(method > DOS ? "surface" : "sensor"),
			lsat.band[i].K1);
		if (method > DOS) {
		    fprintf(stderr,
			    "   the darkness DN with a least %d pixels is %d\n",
			    pixel, dn_dark[i]);
		    fprintf(stderr, "   the DN mode is %d\n", dn_mode[i]);
		}
	    }
	}
	fprintf(stderr, "-------------------\n");
	fflush(stderr);
    }

    /*****************************************
    * ------------ CALCULUS -----------------
    *****************************************/

    G_message(_("Calculating..."));
    for (i = 0; i < lsat.bands; i++) {
	sprintf(band_in, "%s%d", inputname,
		(named->answer ? lsat.band[i].number : lsat.band[i].code));
	sprintf(band_out, "%s%d", outputname, lsat.band[i].code);

	/* set same size as original band raster */
	Rast_get_cellhd(band_in, "", &cellhd);
	Rast_set_window(&cellhd);
	if ((infd = Rast_open_old(band_in, "")) < 0)
	    G_fatal_error(_("Unable to open raster map <%s>"), band_in);

	if (G_find_raster2(band_out, "")) {
	    if (overwrite) {
		G_warning(_("Raster map <%s> already exists and will be overwritten"),
			  band_out);
	    }
	    else {
		G_warning(_("Raster map <%s> exists. Skipping."), band_out);
		continue;
	    }
	}

	in_data_type = Rast_get_map_type(infd);
	if (in_data_type < 0)
	    G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in);

	/* controlling, if we can write the raster */
	if (G_legal_filename(band_out) < 0)
	    G_fatal_error(_("<%s> is an illegal file name"), band_out);

	if ((outfd = Rast_open_new(band_out, DCELL_TYPE)) < 0)
	    G_fatal_error(_("Unable to create raster map <%s>"), band_out);

	/* allocate input and output buffer */
	inrast = Rast_allocate_buf(in_data_type);
	outrast = Rast_allocate_buf(DCELL_TYPE);

	nrows = Rast_window_rows();
	ncols = Rast_window_cols();

	G_important_message(_("Writing %s of <%s> to <%s>..."),
			    (frad->
			     answer ? _("radiance") : (lsat.band[i].
						       thermal) ?
			     _("temperature") : _("reflectance")), band_in,
			    band_out);
	for (row = 0; row < nrows; row++) {
	    G_percent(row, nrows, 2);

	    Rast_get_row(infd, inrast, row, in_data_type);
	    for (col = 0; col < ncols; col++) {
		switch (in_data_type) {
		case CELL_TYPE:
		    ptr = (void *)((CELL *) inrast + col);
		    qcal = (double)((CELL *) inrast)[col];
		    break;
		case FCELL_TYPE:
		    ptr = (void *)((FCELL *) inrast + col);
		    qcal = (double)((FCELL *) inrast)[col];
		    break;
		case DCELL_TYPE:
		    ptr = (void *)((DCELL *) inrast + col);
		    qcal = (double)((DCELL *) inrast)[col];
		    break;
		default:
		    ptr = NULL;
		    qcal = -1.;
		}
		if (Rast_is_null_value(ptr, in_data_type) ||
		    qcal < lsat.band[i].qcalmin) {
		    Rast_set_d_null_value((DCELL *) outrast + col, 1);
		}
		else {
		    rad = lsat_qcal2rad(qcal, &lsat.band[i]);
		    if (frad->answer) {
			ref = rad;
		    }
		    else {
			if (lsat.band[i].thermal) {
			    ref = lsat_rad2temp(rad, &lsat.band[i]);
			}
			else {
			    ref = lsat_rad2ref(rad, &lsat.band[i]) * scale;
			    if (ref < 0. && method > DOS)
				ref = 0.;
			}
		    }
		    ((DCELL *) outrast)[col] = ref;
		}
	    }
	    Rast_put_row(outfd, outrast, DCELL_TYPE);
	}
	G_percent(1, 1, 1);

	ref_mode = 0.;
	if (method > DOS && !lsat.band[i].thermal) {
	    ref_mode = lsat_qcal2rad(dn_mode[i], &lsat.band[i]);
	    ref_mode = lsat_rad2ref(ref_mode, &lsat.band[i]);
	}


	G_free(inrast);
	Rast_close(infd);
	G_free(outrast);
	Rast_close(outfd);


	/*
	 * needed?
	 * if (out_type != CELL_TYPE)
	 * G_quantize_fp_map_range(band_out, G_mapset(), 0., 360., 0,
	 * 360);
	 */

	/* set grey255 colortable */
	Rast_init_colors(&colors);
	Rast_read_fp_range(band_out, G_mapset(), &range);
	Rast_get_fp_range_min_max(&range, &min, &max);
	Rast_make_grey_scale_fp_colors(&colors, min, max);
	Rast_write_colors(band_out, G_mapset(), &colors);

	/* Initialize the 'history' structure with basic info */
	Rast_short_history(band_out, "raster", &history);
	Rast_append_format_history(&history,
				   " %s of Landsat-%d %s (method %s)",
				   (frad->
				    answer ? "Radiance" : (lsat.band[i].
							   thermal ?
							   "Temperature" :
							   "Reflectance")),
				   lsat.number, lsat.sensor, metho->answer);
	Rast_append_history(&history,
			    "-----------------------------------------------------------------");
	Rast_append_format_history(&history,
				   " Acquisition date (and time) ........... %s (%.4lf h)",
				   lsat.date, lsat.time);
	Rast_append_format_history(&history,
				   " Production date ....................... %s\n",
				   lsat.creation);
	Rast_append_format_history(&history,
				   " Earth-sun distance (d) ................ %.7lf",
				   lsat.dist_es);
	Rast_append_format_history(&history,
				   " Sun elevation (and azimuth) ........... %.5lf (%.5lf)",
				   lsat.sun_elev, lsat.sun_az);
	Rast_append_format_history(&history,
				   " Digital number (DN) range ............. %.0lf to %.0lf",
				   lsat.band[i].qcalmin,
				   lsat.band[i].qcalmax);
	Rast_append_format_history(&history,
				   " Calibration constants (Lmin to Lmax) .. %+.5lf to %+.5lf",
				   lsat.band[i].lmin, lsat.band[i].lmax);
	Rast_append_format_history(&history,
				   " DN to Radiance (gain and bias) ........ %+.5lf and %+.5lf",
				   lsat.band[i].gain, lsat.band[i].bias);
	if (lsat.band[i].thermal) {
	    Rast_append_format_history(&history,
				       " Temperature (K1 and K2) ............... %.3lf and %.3lf",
				       lsat.band[i].K1, lsat.band[i].K2);
	}
	else {
	    Rast_append_format_history(&history,
				       " Mean solar irradiance (ESUN) .......... %.3lf",
				       lsat.band[i].esun);
	    Rast_append_format_history(&history,
				       " Radiance to Reflectance (divide by) ... %+.5lf",
				       lsat.band[i].K1);
	    if (method > DOS) {
		Rast_append_format_history(&history, " ");
		Rast_append_format_history(&history,
					   " Dark object (%4d pixels) DN = ........ %d",
					   pixel, dn_dark[i]);
		Rast_append_format_history(&history,
					   " Mode in reflectance histogram ......... %.5lf",
					   ref_mode);
	    }
	}
	Rast_append_history(&history,
			    "------------------------------------------------------------------");

	Rast_command_history(&history);
	Rast_write_history(band_out, &history);

	if (lsat.band[i].thermal)
	    Rast_write_units(band_out, "Kelvin");
	else if (frad->answer)
	    Rast_write_units(band_out, "W/(m^2 sr um)");
	else
	    Rast_write_units(band_out, "unitless");

	/*  set raster timestamp from acq date? (see r.timestamp module)  */
    }
    Rast_set_window(&orig_cellhd);

    exit(EXIT_SUCCESS);
}