示例#1
0
int main(int argc, char *argv[])
{
    struct Map_info In, Out, Error;
    struct line_pnts *Points;
    struct line_cats *Cats;
    int i, type, iter;
    struct GModule *module;	/* GRASS module for parsing arguments */
    struct Option *map_in, *map_out, *error_out, *thresh_opt, *method_opt,
	*look_ahead_opt;
    struct Option *iterations_opt, *cat_opt, *alpha_opt, *beta_opt, *type_opt;
    struct Option *field_opt, *where_opt, *reduction_opt, *slide_opt;
    struct Option *angle_thresh_opt, *degree_thresh_opt,
	*closeness_thresh_opt;
    struct Option *betweeness_thresh_opt;
    struct Flag *notab_flag, *loop_support_flag;
    int with_z;
    int total_input, total_output;	/* Number of points in the input/output map respectively */
    double thresh, alpha, beta, reduction, slide, angle_thresh;
    double degree_thresh, closeness_thresh, betweeness_thresh;
    int method;
    int look_ahead, iterations;
    int loop_support;
    int layer;
    int n_lines;
    int simplification, mask_type;
    struct cat_list *cat_list = NULL;
    char *s, *descriptions;

    /* initialize GIS environment */
    G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */

    /* initialize module */
    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("generalization"));
    G_add_keyword(_("simplification"));
    G_add_keyword(_("smoothing"));
    G_add_keyword(_("displacement"));
    G_add_keyword(_("network generalization"));
    module->description = _("Performs vector based generalization.");

    /* Define the different options as defined in gis.h */
    map_in = G_define_standard_option(G_OPT_V_INPUT);

    field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);

    type_opt = G_define_standard_option(G_OPT_V_TYPE);
    type_opt->options = "line,boundary,area";
    type_opt->answer = "line,boundary,area";
    type_opt->guisection = _("Selection");
    
    map_out = G_define_standard_option(G_OPT_V_OUTPUT);

    error_out = G_define_standard_option(G_OPT_V_OUTPUT);
    error_out->key = "error";
    error_out->required = NO;
    error_out->description =
	_("Error map of all lines and boundaries not being generalized due to topology issues or over-simplification");

    method_opt = G_define_option();
    method_opt->key = "method";
    method_opt->type = TYPE_STRING;
    method_opt->required = YES;
    method_opt->multiple = NO;
    method_opt->options =
	"douglas,douglas_reduction,lang,reduction,reumann,boyle,sliding_averaging,distance_weighting,chaiken,hermite,snakes,network,displacement";
    descriptions = NULL;
    G_asprintf(&descriptions,
               "douglas;%s;"
               "douglas_reduction;%s;"
               "lang;%s;"
               "reduction;%s;"
               "reumann;%s;"
               "boyle;%s;"
               "sliding_averaging;%s;"
               "distance_weighting;%s;"
               "chaiken;%s;"
               "hermite;%s;"
               "snakes;%s;"
               "network;%s;"
               "displacement;%s;",
               _("Douglas-Peucker Algorithm"),
               _("Douglas-Peucker Algorithm with reduction parameter"),
               _("Lang Simplification Algorithm"),
               _("Vertex Reduction Algorithm eliminates points close to each other"),
               _("Reumann-Witkam Algorithm"),
               _("Boyle's Forward-Looking Algorithm"),
               _("McMaster's Sliding Averaging Algorithm"),
               _("McMaster's Distance-Weighting Algorithm"),
               _("Chaiken's Algorithm"),
               _("Interpolation by Cubic Hermite Splines"),
               _("Snakes method for line smoothing"),
               _("Network generalization"),
               _("Displacement of lines close to each other"));
    method_opt->descriptions = G_store(descriptions);
    
    method_opt->description = _("Generalization algorithm");

    thresh_opt = G_define_option();
    thresh_opt->key = "threshold";
    thresh_opt->type = TYPE_DOUBLE;
    thresh_opt->required = YES;
    thresh_opt->options = "0-1000000000";
    thresh_opt->description = _("Maximal tolerance value");

    look_ahead_opt = G_define_option();
    look_ahead_opt->key = "look_ahead";
    look_ahead_opt->type = TYPE_INTEGER;
    look_ahead_opt->required = NO;
    look_ahead_opt->answer = "7";
    look_ahead_opt->description = _("Look-ahead parameter");

    reduction_opt = G_define_option();
    reduction_opt->key = "reduction";
    reduction_opt->type = TYPE_DOUBLE;
    reduction_opt->required = NO;
    reduction_opt->answer = "50";
    reduction_opt->options = "0-100";
    reduction_opt->description =
	_("Percentage of the points in the output of 'douglas_reduction' algorithm");
    
    slide_opt = G_define_option();
    slide_opt->key = "slide";
    slide_opt->type = TYPE_DOUBLE;
    slide_opt->required = NO;
    slide_opt->answer = "0.5";
    slide_opt->options = "0-1";
    slide_opt->description =
	_("Slide of computed point toward the original point");

    angle_thresh_opt = G_define_option();
    angle_thresh_opt->key = "angle_thresh";
    angle_thresh_opt->type = TYPE_DOUBLE;
    angle_thresh_opt->required = NO;
    angle_thresh_opt->answer = "3";
    angle_thresh_opt->options = "0-180";
    angle_thresh_opt->description =
	_("Minimum angle between two consecutive segments in Hermite method");

    degree_thresh_opt = G_define_option();
    degree_thresh_opt->key = "degree_thresh";
    degree_thresh_opt->type = TYPE_INTEGER;
    degree_thresh_opt->required = NO;
    degree_thresh_opt->answer = "0";
    degree_thresh_opt->description =
	_("Degree threshold in network generalization");

    closeness_thresh_opt = G_define_option();
    closeness_thresh_opt->key = "closeness_thresh";
    closeness_thresh_opt->type = TYPE_DOUBLE;
    closeness_thresh_opt->required = NO;
    closeness_thresh_opt->answer = "0";
    closeness_thresh_opt->options = "0-1";
    closeness_thresh_opt->description =
	_("Closeness threshold in network generalization");

    betweeness_thresh_opt = G_define_option();
    betweeness_thresh_opt->key = "betweeness_thresh";
    betweeness_thresh_opt->type = TYPE_DOUBLE;
    betweeness_thresh_opt->required = NO;
    betweeness_thresh_opt->answer = "0";
    betweeness_thresh_opt->description =
	_("Betweeness threshold in network generalization");

    alpha_opt = G_define_option();
    alpha_opt->key = "alpha";
    alpha_opt->type = TYPE_DOUBLE;
    alpha_opt->required = NO;
    alpha_opt->answer = "1.0";
    alpha_opt->description = _("Snakes alpha parameter");

    beta_opt = G_define_option();
    beta_opt->key = "beta";
    beta_opt->type = TYPE_DOUBLE;
    beta_opt->required = NO;
    beta_opt->answer = "1.0";
    beta_opt->description = _("Snakes beta parameter");

    iterations_opt = G_define_option();
    iterations_opt->key = "iterations";
    iterations_opt->type = TYPE_INTEGER;
    iterations_opt->required = NO;
    iterations_opt->answer = "1";
    iterations_opt->description = _("Number of iterations");

    cat_opt = G_define_standard_option(G_OPT_V_CATS);
    cat_opt->guisection = _("Selection");
    
    where_opt = G_define_standard_option(G_OPT_DB_WHERE);
    where_opt->guisection = _("Selection");

    loop_support_flag = G_define_flag();
    loop_support_flag->key = 'l';
    loop_support_flag->label = _("Disable loop support");
    loop_support_flag->description = _("Do not modify end points of lines forming a closed loop");

    notab_flag = G_define_standard_flag(G_FLG_V_TABLE);
    notab_flag->description = _("Do not copy attributes");
    notab_flag->guisection = _("Attributes");
    
    /* options and flags parser */
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    thresh = atof(thresh_opt->answer);
    look_ahead = atoi(look_ahead_opt->answer);
    alpha = atof(alpha_opt->answer);
    beta = atof(beta_opt->answer);
    reduction = atof(reduction_opt->answer);
    iterations = atoi(iterations_opt->answer);
    slide = atof(slide_opt->answer);
    angle_thresh = atof(angle_thresh_opt->answer);
    degree_thresh = atof(degree_thresh_opt->answer);
    closeness_thresh = atof(closeness_thresh_opt->answer);
    betweeness_thresh = atof(betweeness_thresh_opt->answer);

    mask_type = type_mask(type_opt);
    G_debug(3, "Method: %s", method_opt->answer);

    s = method_opt->answer;

    if (strcmp(s, "douglas") == 0)
	method = DOUGLAS;
    else if (strcmp(s, "lang") == 0)
	method = LANG;
    else if (strcmp(s, "reduction") == 0)
	method = VERTEX_REDUCTION;
    else if (strcmp(s, "reumann") == 0)
	method = REUMANN;
    else if (strcmp(s, "boyle") == 0)
	method = BOYLE;
    else if (strcmp(s, "distance_weighting") == 0)
	method = DISTANCE_WEIGHTING;
    else if (strcmp(s, "chaiken") == 0)
	method = CHAIKEN;
    else if (strcmp(s, "hermite") == 0)
	method = HERMITE;
    else if (strcmp(s, "snakes") == 0)
	method = SNAKES;
    else if (strcmp(s, "douglas_reduction") == 0)
	method = DOUGLAS_REDUCTION;
    else if (strcmp(s, "sliding_averaging") == 0)
	method = SLIDING_AVERAGING;
    else if (strcmp(s, "network") == 0)
	method = NETWORK;
    else if (strcmp(s, "displacement") == 0) {
	method = DISPLACEMENT;
	/* we can displace only the lines */
	mask_type = GV_LINE;
    }
    else {
	G_fatal_error(_("Unknown method"));
	exit(EXIT_FAILURE);
    }


    /* simplification or smoothing? */
    switch (method) {
    case DOUGLAS:
    case DOUGLAS_REDUCTION:
    case LANG:
    case VERTEX_REDUCTION:
    case REUMANN:
	simplification = 1;
	break;
    default:
	simplification = 0;
	break;
    }


    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    Vect_check_input_output_name(map_in->answer, map_out->answer,
				 G_FATAL_EXIT);

    Vect_set_open_level(2);

    if (Vect_open_old2(&In, map_in->answer, "", field_opt->answer) < 1)
	G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer);

    if (Vect_get_num_primitives(&In, mask_type) == 0) {
	G_warning(_("No lines found in input map <%s>"), map_in->answer);
	Vect_close(&In);
	exit(EXIT_SUCCESS);
    }
    with_z = Vect_is_3d(&In);

    if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
	Vect_close(&In);
	G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
    }

    if (error_out->answer) {
        if (0 > Vect_open_new(&Error, error_out->answer, with_z)) {
	    Vect_close(&In);
	    G_fatal_error(_("Unable to create error vector map <%s>"), error_out->answer);
        }
    }


    Vect_copy_head_data(&In, &Out);
    Vect_hist_copy(&In, &Out);
    Vect_hist_command(&Out);

    total_input = total_output = 0;

    layer = Vect_get_field_number(&In, field_opt->answer);
    /* parse filter options */
    if (layer > 0)
	cat_list = Vect_cats_set_constraint(&In, layer, 
			      where_opt->answer, cat_opt->answer);

    if (method == DISPLACEMENT) {
	/* modifies only lines, all other features including boundaries are preserved */
	/* options where, cats, and layer are respected */
	G_message(_("Displacement..."));
	snakes_displacement(&In, &Out, thresh, alpha, beta, 1.0, 10.0,
			    iterations, cat_list, layer);
    }

    /* TODO: rearrange code below. It's really messy */
    if (method == NETWORK) {
	/* extracts lines of selected type, all other features are discarded */
	/* options where, cats, and layer are ignored */
	G_message(_("Network generalization..."));
	total_output =
	    graph_generalization(&In, &Out, mask_type, degree_thresh, 
	                         closeness_thresh, betweeness_thresh);
    }

    /* copy tables here because method == NETWORK is complete and 
     * tables for Out may be needed for parse_filter_options() below */
    if (!notab_flag->answer) {
	if (method == NETWORK)
	    copy_tables_by_cats(&In, &Out);
	else
	    Vect_copy_tables(&In, &Out, -1);
    }
    else if (where_opt->answer && method < NETWORK) {
	G_warning(_("Attributes are needed for 'where' option, copying table"));
	Vect_copy_tables(&In, &Out, -1);
    }

    /* smoothing/simplification */
    if (method < NETWORK) {
	/* modifies only lines of selected type, all other features are preserved */
	int not_modified_boundaries = 0, n_oversimplified = 0;
	struct line_pnts *APoints;  /* original Points */

	set_topo_debug();

	Vect_copy_map_lines(&In, &Out);
	Vect_build_partial(&Out, GV_BUILD_CENTROIDS);

	G_message("-----------------------------------------------------");
	G_message(_("Generalization (%s)..."), method_opt->answer);
	G_message(_("Using threshold: %g %s"), thresh, G_database_unit_name(1));
	G_percent_reset();

	APoints = Vect_new_line_struct();

	n_lines = Vect_get_num_lines(&Out);
	for (i = 1; i <= n_lines; i++) {
	    int after = 0;

	    G_percent(i, n_lines, 1);

	    type = Vect_read_line(&Out, APoints, Cats, i);

	    if (!(type & GV_LINES) || !(mask_type & type))
		continue;

	    if (layer > 0) {
		if ((type & GV_LINE) &&
		    !Vect_cats_in_constraint(Cats, layer, cat_list))
		    continue;
		else if ((type & GV_BOUNDARY)) {
		    int do_line = 0;
		    int left, right;
		    
		    do_line = Vect_cats_in_constraint(Cats, layer, cat_list);

		    if (!do_line) {
			
			/* check if any of the centroids is selected */
			Vect_get_line_areas(&Out, i, &left, &right);
			if (left < 0)
			    left = Vect_get_isle_area(&Out, abs(left));
			if (right < 0)
			    right = Vect_get_isle_area(&Out, abs(right));

			if (left > 0) {
			    Vect_get_area_cats(&Out, left, Cats);
			    do_line = Vect_cats_in_constraint(Cats, layer, cat_list);
			}
			
			if (!do_line && right > 0) {
			    Vect_get_area_cats(&Out, right, Cats);
			    do_line = Vect_cats_in_constraint(Cats, layer, cat_list);
			}
		    }
		    if (!do_line)
			continue;
		}
	    }

	    Vect_line_prune(APoints);

	    if (APoints->n_points < 2)
		/* Line of length zero, delete if boundary ? */
		continue;

	    total_input += APoints->n_points;

	    /* copy points */
	    Vect_reset_line(Points);
	    Vect_append_points(Points, APoints, GV_FORWARD);
	    
	    loop_support = 0;
	    if (!loop_support_flag->answer) {
		int n1, n2;

		Vect_get_line_nodes(&Out, i, &n1, &n2);
		if (n1 == n2) {
		    if (Vect_get_node_n_lines(&Out, n1) == 2) {
			if (abs(Vect_get_node_line(&Out, n1, 0)) == i &&
			    abs(Vect_get_node_line(&Out, n1, 1)) == i)
			    loop_support = 1;
		    }
		}
	    }
		
	    for (iter = 0; iter < iterations; iter++) {
		switch (method) {
		case DOUGLAS:
		    douglas_peucker(Points, thresh, with_z);
		    break;
		case DOUGLAS_REDUCTION:
		    douglas_peucker_reduction(Points, thresh, reduction,
					      with_z);
		    break;
		case LANG:
		    lang(Points, thresh, look_ahead, with_z);
		    break;
		case VERTEX_REDUCTION:
		    vertex_reduction(Points, thresh, with_z);
		    break;
		case REUMANN:
		    reumann_witkam(Points, thresh, with_z);
		    break;
		case BOYLE:
		    boyle(Points, look_ahead, loop_support, with_z);
		    break;
		case SLIDING_AVERAGING:
		    sliding_averaging(Points, slide, look_ahead, loop_support, with_z);
		    break;
		case DISTANCE_WEIGHTING:
		    distance_weighting(Points, slide, look_ahead, loop_support, with_z);
		    break;
		case CHAIKEN:
		    chaiken(Points, thresh, loop_support, with_z);
		    break;
		case HERMITE:
		    hermite(Points, thresh, angle_thresh, loop_support, with_z);
		    break;
		case SNAKES:
		    snakes(Points, alpha, beta, loop_support, with_z);
		    break;
		}
	    }

	    if (loop_support == 0) { 
		/* safety check, BUG in method if not passed */
		if (APoints->x[0] != Points->x[0] || 
		    APoints->y[0] != Points->y[0] ||
		    APoints->z[0] != Points->z[0])
		    G_fatal_error(_("Method '%s' did not preserve first point"), method_opt->answer);
		    
		if (APoints->x[APoints->n_points - 1] != Points->x[Points->n_points - 1] || 
		    APoints->y[APoints->n_points - 1] != Points->y[Points->n_points - 1] ||
		    APoints->z[APoints->n_points - 1] != Points->z[Points->n_points - 1])
		    G_fatal_error(_("Method '%s' did not preserve last point"), method_opt->answer);
	    }
	    else {
		/* safety check, BUG in method if not passed */
		if (Points->x[0] != Points->x[Points->n_points - 1] || 
		    Points->y[0] != Points->y[Points->n_points - 1] ||
		    Points->z[0] != Points->z[Points->n_points - 1])
		    G_fatal_error(_("Method '%s' did not preserve loop"), method_opt->answer);
	    }

	    Vect_line_prune(Points);

	    /* oversimplified line */
	    if (Points->n_points < 2) {
		after = APoints->n_points;
		n_oversimplified++;
                if (error_out->answer)
		    Vect_write_line(&Error, type, APoints, Cats);
	    }
	    /* check for topology corruption */
	    else if (type == GV_BOUNDARY) {
		if (!check_topo(&Out, i, APoints, Points, Cats)) {
		    after = APoints->n_points;
		    not_modified_boundaries++;
                    if (error_out->answer)
		        Vect_write_line(&Error, type, APoints, Cats);
		}
		else
		    after = Points->n_points;
	    }
	    else {
		/* type == GV_LINE */
		Vect_rewrite_line(&Out, i, type, Points, Cats);
		after = Points->n_points;
	    }

	    total_output += after;
	}
	if (not_modified_boundaries > 0)
	    G_warning(_("%d boundaries were not modified because modification would damage topology"),
		      not_modified_boundaries);
	if (n_oversimplified > 0)
	    G_warning(_("%d lines/boundaries were not modified due to over-simplification"),
		      n_oversimplified);
	G_message("-----------------------------------------------------");

	/* make sure that clean topo is built at the end */
	Vect_build_partial(&Out, GV_BUILD_NONE);
        if (error_out->answer)
	    Vect_build_partial(&Error, GV_BUILD_NONE);
    }

    Vect_build(&Out);
    if (error_out->answer)
        Vect_build(&Error);

    Vect_close(&In);
    Vect_close(&Out);
    if (error_out->answer)
        Vect_close(&Error);

    G_message("-----------------------------------------------------");
    if (total_input != 0 && total_input != total_output)
	G_done_msg(_("Number of vertices for selected features %s from %d to %d (%d%% remaining)"),
                   simplification ? _("reduced") : _("changed"), 
                   total_input, total_output,
                   (total_output * 100) / total_input);
    else
        G_done_msg(" ");

    exit(EXIT_SUCCESS);
}
示例#2
0
文件: main.c 项目: caomw/grass
int main(int argc, char *argv[])
{
    char *output, buf[DB_SQL_MAX];
    double (*rng)(void) = G_drand48;
    double zmin, zmax;
    int seed;
    int i, j, k, n, type, usefloat;
    int area, nareas, field;
    struct boxlist *List = NULL;
    BOX_SIZE *size_list = NULL;
    int alloc_size_list = 0;
    struct Map_info In, Out;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct cat_list *cat_list;
    struct bound_box box;
    struct Cell_head window;
    struct GModule *module;
    struct
    {
	struct Option *input, *field, *cats, *where, *output, *nsites,
		      *zmin, *zmax, *zcol, *ztype, *seed;
    } parm;
    struct
    {
	struct Flag *z, *notopo, *a;
    } flag;
    struct field_info *Fi;
    dbDriver *driver;
    dbTable *table;
    dbString sql;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("sampling"));
    G_add_keyword(_("statistics"));
    G_add_keyword(_("random"));
    module->description = _("Generates random 2D/3D vector points.");

    parm.output = G_define_standard_option(G_OPT_V_OUTPUT);

    parm.nsites = G_define_option();
    parm.nsites->key = "n";
    parm.nsites->type = TYPE_INTEGER;
    parm.nsites->required = YES;
    parm.nsites->description = _("Number of points to be created");

    parm.input = G_define_standard_option(G_OPT_V_INPUT);
    parm.input->required = NO;
    parm.input->description = _("Restrict points to areas in input vector");
    parm.input->guisection = _("Selection");

    parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
    parm.field->guisection = _("Selection");

    parm.cats = G_define_standard_option(G_OPT_V_CATS);
    parm.cats->guisection = _("Selection");
    
    parm.where = G_define_standard_option(G_OPT_DB_WHERE);
    parm.where->guisection = _("Selection");

    parm.zmin = G_define_option();
    parm.zmin->key = "zmin";
    parm.zmin->type = TYPE_DOUBLE;
    parm.zmin->required = NO;
    parm.zmin->description =
	_("Minimum z height (needs -z flag or column name)");
    parm.zmin->answer = "0.0";
    parm.zmin->guisection = _("3D output");

    parm.zmax = G_define_option();
    parm.zmax->key = "zmax";
    parm.zmax->type = TYPE_DOUBLE;
    parm.zmax->required = NO;
    parm.zmax->description =
	_("Maximum z height (needs -z flag or column name)");
    parm.zmax->answer = "0.0";
    parm.zmax->guisection = _("3D output");

    parm.seed = G_define_option();
    parm.seed->key = "seed";
    parm.seed->type = TYPE_INTEGER;
    parm.seed->required = NO;
    parm.seed->description =
	_("The seed to initialize the random generator. If not set the process ID is used");

    parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
    parm.zcol->label = _("Name of column for z values");
    parm.zcol->description =
	_("Writes z values to column");
    parm.zcol->guisection = _("3D output");

    parm.ztype = G_define_option();
    parm.ztype->key = "column_type";
    parm.ztype->type = TYPE_STRING;
    parm.ztype->required = NO;
    parm.ztype->multiple = NO;
    parm.ztype->description = _("Type of column for z values");
    parm.ztype->options = "integer,double precision";
    parm.ztype->answer = "double precision";
    parm.ztype->guisection = _("3D output");

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

    flag.a = G_define_flag();
    flag.a->key = 'a';
    flag.a->description = _("Generate n points for each individual area");

    flag.notopo = G_define_standard_flag(G_FLG_V_TOPO);

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

    output = parm.output->answer;
    n = atoi(parm.nsites->answer);
    
    if(parm.seed->answer)
        seed = atoi(parm.seed->answer);

    if (n <= 0) {
	G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
    }

    nareas = 0;
    cat_list = NULL;
    field = -1;
    if (parm.input->answer) {
	Vect_set_open_level(2); /* topology required */
	if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer))
	    G_fatal_error(_("Unable to open vector map <%s>"),
			  parm.input->answer);

	if (parm.field->answer)
	    field = Vect_get_field_number(&In, parm.field->answer);

	if ((parm.cats->answer || parm.where->answer) && field == -1) {
	    G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."),
		      field, parm.cats->key, parm.where->key);
	    field = 1;
	}
	if (field > 0)
	    cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer,
						parm.cats->answer);
	nareas = Vect_get_num_areas(&In);
	if (nareas == 0) {
	    Vect_close(&In);
	    G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer);
	}
    }
    else {
	if (flag.a->answer)
	    G_fatal_error(_("The <-%c> flag requires an input vector with areas"),
	                  flag.a->key);
    }

    /* create new vector map */
    if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z))
        G_fatal_error(_("Unable to create vector map <%s>"), output);
    Vect_set_error_handler_io(NULL, &Out);

    /* Do we need to write random values into attribute table? */
    usefloat = -1;
    if (parm.zcol->answer) {
	Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
	driver =
	    db_start_driver_open_database(Fi->driver,
					  Vect_subst_var(Fi->database, &Out));
	if (driver == NULL) {
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Vect_subst_var(Fi->database, &Out), Fi->driver);
	}
        db_set_error_handler_driver(driver);
        
	db_begin_transaction(driver);

	db_init_string(&sql);
	sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN,
		parm.zcol->answer, parm.ztype->answer);
	db_set_string(&sql, buf);
	Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
			    Fi->driver);

	/* Create table */
	G_debug(3, db_get_string(&sql));
	if (db_execute_immediate(driver, &sql) != DB_OK) {
	    G_fatal_error(_("Unable to create table: %s"),
			  db_get_string(&sql));
	}

	/* Create index */
	if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK)
	    G_warning(_("Unable to create index"));

	/* Grant */
	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);
	}

	/* OK. Let's check what type of column user has created */
	db_set_string(&sql, Fi->table);
	if (db_describe_table(driver, &sql, &table) != DB_OK) {
	    G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
	}

	if (db_get_table_number_of_columns(table) != 2) {
	    G_fatal_error(_("Table should contain only two columns"));
	}

	type = db_get_column_sqltype(db_get_table_column(table, 1));
	if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
	    usefloat = 0;
	if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
	    usefloat = 1;
	if (usefloat < 0) {
	    G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
			   " and DOUBLE PRECISION column types."));
	}
    }

    Vect_hist_command(&Out);

    /* Init the random seed */
    if(parm.seed->answer)
	G_srand48(seed);
    else
	G_srand48_auto();

    G_get_window(&window);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    if (nareas > 0) {
	int first = 1, count;
	struct bound_box abox, bbox;

	box.W = window.west;
	box.E = window.east;
	box.S = window.south;
	box.N = window.north;
	box.B = -PORT_DOUBLE_MAX;
	box.T = PORT_DOUBLE_MAX;

	count = 0;

	for (i = 1; i <= nareas; i++) {
	    
	    if (!Vect_get_area_centroid(&In, i))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, i, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list))
		    continue;
	    }

	    Vect_get_area_box(&In, i, &abox);
	    if (!Vect_box_overlap(&abox, &box))
		continue;

	    if (first) {
		Vect_box_copy(&bbox, &abox);
		first = 0;
	    }
	    else
		Vect_box_extend(&bbox, &abox);
	    count++;
	}
	if (count == 0) {
	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"),
			  parm.input->answer);
	}
	Vect_box_copy(&box, &bbox);

	/* does the vector overlap with the current region ? */
	if (box.W >= window.east || box.E <= window.west ||
	    box.S >= window.north || box.N <= window.south) {

	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Input vector <%s> does not overlap with the current region"),
	                  parm.input->answer);
	}

	/* try to reduce the current region */
	if (window.east > box.E)
	    window.east = box.E;
	if (window.west < box.W)
	    window.west = box.W;
	if (window.north > box.N)
	    window.north = box.N;
	if (window.south < box.S)
	    window.south = box.S;

	List = Vect_new_boxlist(1);
	alloc_size_list = 10;
	size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
    }

    zmin = zmax = 0;
    if (flag.z->answer || parm.zcol->answer) {
	zmax = atof(parm.zmax->answer);
	zmin = atof(parm.zmin->answer);
    }

    G_message(_("Generating points..."));
    if (flag.a->answer && nareas > 0) {
	struct bound_box abox, bbox;
	int cat = 1;

	/* n points for each area */
	nareas = Vect_get_num_areas(&In);
	
	G_percent(0, nareas, 1);
	for (area = 1; area <= nareas; area++) {

	    G_percent(area, nareas, 1);

	    if (!Vect_get_area_centroid(&In, area))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, area, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
		    continue;
		}
	    }

	    box.W = window.west;
	    box.E = window.east;
	    box.S = window.south;
	    box.N = window.north;
	    box.B = -PORT_DOUBLE_MAX;
	    box.T = PORT_DOUBLE_MAX;
	    
	    Vect_get_area_box(&In, area, &abox);
	    if (!Vect_box_overlap(&box, &abox))
		continue;
		
	    bbox = abox;
	    if (bbox.W < box.W)
		bbox.W = box.W;
	    if (bbox.E > box.E)
		bbox.E = box.E;
	    if (bbox.S < box.S)
		bbox.S = box.S;
	    if (bbox.N > box.N)
		bbox.N = box.N;

	    for (i = 0; i < n; ++i) {
		double x, y, z;
		int outside = 1;
		int ret;

		Vect_reset_line(Points);
		Vect_reset_cats(Cats);

		while (outside) {
		    x = rng() * (bbox.W - bbox.E) + bbox.E;
		    y = rng() * (bbox.N - bbox.S) + bbox.S;
		    z = rng() * (zmax - zmin) + zmin;

		    ret = Vect_point_in_area(x, y, &In, area, &abox);

		    G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

		    if (ret >= 1) {
			outside = 0;
		    }
		}

		if (flag.z->answer)
		    Vect_append_point(Points, x, y, z);
		else
		    Vect_append_point(Points, x, y, 0.0);

		if (parm.zcol->answer) {
		    sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		    db_set_string(&sql, buf);
		    /* Round random value if column is integer type */
		    if (usefloat)
			sprintf(buf, "%f )", z);
		    else
			sprintf(buf, "%.0f )", z);
		    db_append_string(&sql, buf);

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

		Vect_cat_set(Cats, 1, cat++);
		Vect_write_line(&Out, GV_POINT, Points, Cats);
	    }
	}
    }
    else {
	/* n points in total */
	for (i = 0; i < n; ++i) {
	    double x, y, z;

	    G_percent(i, n, 4);

	    Vect_reset_line(Points);
	    Vect_reset_cats(Cats);

	    x = rng() * (window.west - window.east) + window.east;
	    y = rng() * (window.north - window.south) + window.south;
	    z = rng() * (zmax - zmin) + zmin;
	    
	    if (nareas) {
		int outside = 1;

		do {
		    /* select areas by box */
		    box.E = x;
		    box.W = x;
		    box.N = y;
		    box.S = y;
		    box.T = PORT_DOUBLE_MAX;
		    box.B = -PORT_DOUBLE_MAX;
		    Vect_select_areas_by_box(&In, &box, List);
		    G_debug(3, "  %d areas selected by box", List->n_values);

		    /* sort areas by size, the smallest is likely to be the nearest */
		    if (alloc_size_list < List->n_values) {
			alloc_size_list = List->n_values;
			size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
		    }

		    k = 0;
		    for (j = 0; j < List->n_values; j++) {
			area = List->id[j];

			if (!Vect_get_area_centroid(&In, area))
			    continue;

			if (field > 0) {
			    if (Vect_get_area_cats(&In, area, Cats))
				continue;

			    if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
				continue;
			    }
			}

			List->id[k] = List->id[j];
			List->box[k] = List->box[j];
			size_list[k].i = List->id[k];
			box = List->box[k];
			size_list[k].box = List->box[k];
			size_list[k].size = (box.N - box.S) * (box.E - box.W);
			k++;
		    }
		    List->n_values = k;
		    
		    if (List->n_values == 2) {
			/* simple swap */
			if (size_list[1].size < size_list[0].size) {
			    size_list[0].i = List->id[1];
			    size_list[1].i = List->id[0];
			    size_list[0].box = List->box[1];
			    size_list[1].box = List->box[0];
			}
		    }
		    else if (List->n_values > 2)
			qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);

		    for (j = 0; j < List->n_values; j++) {
			int ret;

			area = size_list[j].i;
			ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box);

			G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

			if (ret >= 1) {
			    outside = 0;
			    break;
			}
		    }
		    if (outside) {
			x = rng() * (window.west - window.east) + window.east;
			y = rng() * (window.north - window.south) + window.south;
			z = rng() * (zmax - zmin) + zmin;
		    }
		} while (outside);
	    }

	    if (flag.z->answer)
		Vect_append_point(Points, x, y, z);
	    else
		Vect_append_point(Points, x, y, 0.0);

	    if (parm.zcol->answer) {
		sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		db_set_string(&sql, buf);
		/* Round random value if column is integer type */
		if (usefloat)
		    sprintf(buf, "%f )", z);
		else
		    sprintf(buf, "%.0f )", z);
		db_append_string(&sql, buf);

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

	    Vect_cat_set(Cats, 1, i + 1);
	    Vect_write_line(&Out, GV_POINT, Points, Cats);
	}
	G_percent(1, 1, 1);
    }
    
    if (parm.zcol->answer) {
	db_commit_transaction(driver);
	db_close_database_shutdown_driver(driver);
    }

    if (!flag.notopo->answer) {
	Vect_build(&Out);
    }
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
示例#3
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct {
        struct Option *input, *output, *zshift, *height, *elevation, *hcolumn,
            *type, *field, *cats, *where, *interp, *scale, *null;
    } opt;
    struct {
        struct Flag *trace;
    } flag;
    
    struct Map_info In, Out;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct bound_box map_box;

    struct cat_list *cat_list;
    
    struct Cell_head window;
    
    int field;
    int only_type, cat;
    int fdrast, interp_method, trace;
    double objheight, objheight_default, voffset;
    double scale, null_val;
    
    struct field_info *Fi;
    dbDriver *driver = NULL;
    
    char *comment;
    
    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("geometry"));
    G_add_keyword(_("sampling"));
    G_add_keyword(_("3D"));
    module->label =
	_("Extrudes flat vector features to 3D vector features with defined height.");
    module->description = 
        _("Optionally the height can be derived from sampling of elevation raster map.");
    
    flag.trace = G_define_flag();
    flag.trace->key = 't';
    flag.trace->description = _("Trace elevation");
    flag.trace->guisection = _("Elevation");

    opt.input = G_define_standard_option(G_OPT_V_INPUT);

    opt.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
    opt.field->guisection = _("Selection");

    opt.cats = G_define_standard_option(G_OPT_V_CATS);
    opt.cats->guisection = _("Selection");
    
    opt.where = G_define_standard_option(G_OPT_DB_WHERE);
    opt.where->guisection = _("Selection");

    opt.type = G_define_standard_option(G_OPT_V_TYPE);
    opt.type->answer = "point,line,area";
    opt.type->options = "point,line,area";
    opt.type->guisection = _("Selection");

    opt.output = G_define_standard_option(G_OPT_V_OUTPUT);

    opt.zshift = G_define_option();
    opt.zshift->key = "zshift";
    opt.zshift->description = _("Shifting value for z coordinates");
    opt.zshift->type = TYPE_DOUBLE;
    opt.zshift->required = NO;
    opt.zshift->answer = "0";
    opt.zshift->guisection = _("Height");

    opt.height = G_define_option();
    opt.height->key = "height";
    opt.height->type = TYPE_DOUBLE;
    opt.height->required = NO;
    opt.height->multiple = NO;
    opt.height->description = _("Fixed height for 3D vector features");
    opt.height->guisection = _("Height");

    opt.hcolumn = G_define_standard_option(G_OPT_DB_COLUMN);
    opt.hcolumn->key = "height_column";
    opt.hcolumn->multiple = NO;
    opt.hcolumn->description = _("Name of attribute column with feature height");
    opt.hcolumn->guisection = _("Height");
 
    /* raster sampling */
    opt.elevation = G_define_standard_option(G_OPT_R_ELEV);
    opt.elevation->required = NO;
    opt.elevation->description = _("Elevation raster map for height extraction");
    opt.elevation->guisection = _("Elevation");

    opt.interp = G_define_standard_option(G_OPT_R_INTERP_TYPE);
    opt.interp->answer = "nearest";
    opt.interp->guisection = _("Elevation");

    opt.scale = G_define_option();
    opt.scale->key = "scale";
    opt.scale->type = TYPE_DOUBLE;
    opt.scale->description = _("Scale factor sampled raster values");
    opt.scale->answer = "1.0";
    opt.scale->guisection = _("Elevation");

    opt.null = G_define_option();
    opt.null->key = "null_value";
    opt.null->type = TYPE_DOUBLE;
    opt.null->description =
	_("Height for sampled raster NULL values");
    opt.null->guisection = _("Elevation");

    G_gisinit(argv[0]);

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

    if (!opt.height->answer && !opt.hcolumn->answer) {
	G_fatal_error(_("One of '%s' or '%s' parameters must be set"),
		      opt.height->key, opt.hcolumn->key);
    }

    sscanf(opt.zshift->answer, "%lf", &voffset);
    G_debug(1, "voffset = %f", voffset);
    
    if (opt.height->answer)
	sscanf(opt.height->answer, "%lf", &objheight);
    else
	objheight = 0.;
    G_debug(1, "objheight = %f", objheight);
    objheight_default = objheight;

    only_type = Vect_option_to_types(opt.type);

    /* sampling method */
    interp_method = Rast_option_to_interp_type(opt.interp);

    /* used to scale sampled raster values */
    scale = atof(opt.scale->answer);

    /* is null value defined */
    if (opt.null->answer)
	null_val = atof(opt.null->answer);

    /* trace elevation */
    trace = flag.trace->answer ? TRUE : FALSE;
    
    /* set input vector map name and mapset */
    Vect_check_input_output_name(opt.input->answer, opt.output->answer, G_FATAL_EXIT);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    Vect_set_open_level(2); /* topology required for input */

    /* opening input vector map */
    if (Vect_open_old2(&In, opt.input->answer, "", opt.field->answer) < 0)
	G_fatal_error(_("Unable to open vector map <%s>"), opt.input->answer);

    Vect_set_error_handler_io(&In, &Out);

    /* creating output vector map */
    if (Vect_open_new(&Out, opt.output->answer, WITH_Z) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"),
			opt.output->answer);

    field = Vect_get_field_number(&In, opt.field->answer);

    if ((opt.hcolumn->answer || opt.cats->answer || opt.where->answer) && field == -1) {
        G_warning(_("Invalid layer number (%d). "
                    "Parameter '%s', '%s' or '%s' specified, assuming layer '1'."),
                  field, opt.hcolumn->key, opt.cats->key, opt.where->key);
        field = 1;
    }

    /* set constraint for cats or where */
    cat_list = NULL;
    if (field > 0)
	cat_list = Vect_cats_set_constraint(&In, field, opt.where->answer,
                                            opt.cats->answer);
    
    
    Vect_hist_copy(&In, &Out);
    Vect_hist_command(&Out);

    /* opening database connection, if required */
    if (opt.hcolumn->answer) {
        int ctype;
        dbColumn *column;
        
	if ((Fi = Vect_get_field(&In, field)) == NULL)
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  field);

	if ((driver =
	     db_start_driver_open_database(Fi->driver, Fi->database)) == NULL)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Fi->database, Fi->driver);
        db_set_error_handler_driver(driver);
        
	if (db_get_column(driver, Fi->table, opt.hcolumn->answer, &column) != DB_OK)
	    G_fatal_error(_("Column <%s> does not exist"),
			  opt.hcolumn->answer);
	else
	    db_free_column(column);

	ctype = db_column_Ctype(driver, Fi->table, opt.hcolumn->answer);

	if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_STRING &&
	    ctype != DB_C_TYPE_DOUBLE) {
	    G_fatal_error(_("Column <%s>: invalid data type"),
			  opt.hcolumn->answer);
	}
    }

    /* do we work with elevation raster? */
    fdrast = -1;
    if (opt.elevation->answer) {
	/* raster setup */
	G_get_window(&window);

	/* open the elev raster, and check for error condition */
	fdrast = Rast_open_old(opt.elevation->answer, "");
    }

    /* if area */
    if (only_type & GV_AREA) {
        int area, nareas, centroid;
        
        nareas = Vect_get_num_areas(&In);
	G_debug(2, "n_areas = %d", nareas);
	if (nareas > 0)
	    G_message(_("Extruding areas..."));
	for (area = 1; area <= nareas; area++) {
	    G_debug(3, "area = %d", area);
	    G_percent(area, nareas, 2);
            
	    if (!Vect_area_alive(&In, area))
		continue;
            
	    centroid = Vect_get_area_centroid(&In, area);
	    if (!centroid) {
		G_warning(_("Skipping area %d without centroid"), area);
		continue;
	    }

	    Vect_read_line(&In, NULL, Cats, centroid);
	    if (field > 0 && !Vect_cats_in_constraint(Cats, field, cat_list))
		continue;
            
	    /* height attribute */
	    if (opt.hcolumn->answer) {
		cat = Vect_get_area_cat(&In, area, field);
                if (cat == -1) {
                    G_warning(_("No category defined for area %d. Using default fixed height %f."),
                              area, objheight_default);
                    objheight = objheight_default;
                }
                if (get_height(Fi, opt.hcolumn->answer,
                               driver, cat, &objheight) != 0) {
                    G_warning(_("Unable to fetch height from DB for area %d. Using default fixed height %f."),
                              area, objheight_default);
                    objheight = objheight_default;
                }
	    } /* if opt.hcolumn->answer */

	    Vect_get_area_points(&In, area, Points);

	    G_debug(3, "area: %d height: %f", area, objheight);

	    extrude(&In, &Out, Cats, Points,
		    fdrast, trace, interp_method, scale,
                    opt.null->answer ? TRUE : FALSE, null_val,
                    objheight, voffset, &window, GV_AREA,
		    centroid);
	} /* foreach area */

    }

    if (only_type > 0) {
        int line, nlines;
        int type;
        
	G_debug(1, "other than areas");
	/* loop through each line in the dataset */
        nlines = Vect_get_num_lines(&In);
	G_message(_("Extruding features..."));
	for (line = 1; line <= nlines; line++) {
	    /* progress feedback */
	    G_percent(line, nlines, 2);

	    if (!Vect_line_alive(&In, line))
		continue;

	    /* read line */
	    type = Vect_read_line(&In, Points, Cats, line);

	    if (!(type & only_type))
		continue;

	    if (field > 0 && !Vect_cats_in_constraint(Cats, field, cat_list))
		continue;

	    /* height attribute */
	    if (opt.hcolumn->answer) {
		cat = Vect_get_line_cat(&In, line, field);
                if (cat == -1) {
                    G_warning(_("No category defined for feature %d. Using default fixed height %f."),
                              line, objheight_default);
                    objheight = objheight_default;
                }
                if (get_height(Fi, opt.hcolumn->answer,
                               driver, cat, &objheight) != 0) {
                    G_warning(_("Unable to fetch height from DB for line %d. Using default fixed height %f."),
                              line, objheight_default);
                    objheight = objheight_default;
                }
	    } /* if opt.hcolumn->answer */
            
	    extrude(&In, &Out, Cats, Points,
		    fdrast, trace, interp_method, scale,
                    opt.null->answer ? TRUE : FALSE, null_val,
                    objheight, voffset, &window, type, -1);
	} /* for each line */
    }	  /* else if area */

    if (driver) {
	db_close_database(driver);
	db_shutdown_driver(driver);
    }

    G_important_message(_("Copying attribute table..."));
    if (field < 0)
        Vect_copy_tables(&In, &Out, 0);
    else 
        Vect_copy_table_by_cat_list(&In, &Out, field, field, NULL,
                                    GV_1TABLE, cat_list);
    
    Vect_build(&Out);

    /* header */
    G_asprintf(&comment, "Generated by %s from vector map <%s>",
	       G_program_name(), Vect_get_full_name(&In));
    Vect_set_comment(&Out, comment);
    G_free(comment);

    Vect_get_map_box(&Out, &map_box);

    Vect_close(&In);
    Vect_close(&Out);

    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    G_done_msg("T: %f B: %f.", map_box.T, map_box.B);
    
    exit(EXIT_SUCCESS);
}
示例#4
0
int vect_to_rast(const char *vector_map, const char *raster_map, const char *field_name,
		 const char *column, int cache_mb, int use, double value,
		 int value_type, const char *rgbcolumn, const char *labelcolumn,
		 int ftype, char *where, char *cats, int dense)
{
    struct Map_info Map;
    struct line_pnts *Points;
    int i, field;
    struct cat_list *cat_list = NULL;
    int fd;			/* for raster map */
    int nareas, nlines;		/* number of converted features */
    int nareas_all, nplines_all;	/* number of all areas, points/lines */
    int stat;
    int format;
    int pass, npasses;

    /* Attributes */
    int nrec;
    int ctype = 0;
    struct field_info *Fi;
    dbDriver *Driver;
    dbCatValArray cvarr;
    int is_fp = 0;

    nareas = 0;

    G_verbose_message(_("Loading data..."));
    Vect_set_open_level(2);
    if (Vect_open_old2(&Map, vector_map, "", field_name) < 0)
	G_fatal_error(_("Unable to open vector map <%s>"), vector_map);

    field = Vect_get_field_number(&Map, field_name);

    if (field > 0)
	cat_list = Vect_cats_set_constraint(&Map, field, where, cats);


    if ((use == USE_Z) && !(Vect_is_3d(&Map)))
	G_fatal_error(_("Vector map <%s> is not 3D"),
		      Vect_get_full_name(&Map));

    switch (use) {
    case USE_ATTR:
	db_CatValArray_init(&cvarr);
	if (!(Fi = Vect_get_field(&Map, field)))
	    G_fatal_error(_("Database connection not defined for layer <%s>"),
			  field_name);

	if ((Driver =
	     db_start_driver_open_database(Fi->driver, Fi->database)) == NULL)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Fi->database, Fi->driver);
        db_set_error_handler_driver(Driver);

	/* Note do not check if the column exists in the table because it may be expression */

	if ((nrec =
	     db_select_CatValArray(Driver, Fi->table, Fi->key, column, NULL,
				   &cvarr)) == -1)
	    G_fatal_error(_("Column <%s> not found"), column);
	G_debug(3, "nrec = %d", nrec);

	ctype = cvarr.ctype;
	if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
	    G_fatal_error(_("Column type (%s) not supported (did you mean 'labelcolumn'?)"),
			  db_sqltype_name(ctype));

	if (nrec < 0)
	    G_fatal_error(_("No records selected from table <%s>"),
			  Fi->table);

	G_debug(1, "%d records selected from table", nrec);

	db_close_database_shutdown_driver(Driver);

	for (i = 0; i < cvarr.n_values; i++) {
	    if (ctype == DB_C_TYPE_INT) {
		G_debug(3, "cat = %d val = %d", cvarr.value[i].cat,
			cvarr.value[i].val.i);
	    }
	    else if (ctype == DB_C_TYPE_DOUBLE) {
		G_debug(3, "cat = %d val = %f", cvarr.value[i].cat,
			cvarr.value[i].val.d);
	    }
	}
	
	switch (ctype) {
	case DB_C_TYPE_INT:
	    format = CELL_TYPE;
	    break;
	case DB_C_TYPE_DOUBLE:
	    format = DCELL_TYPE;
	    break;
	default:
	    G_fatal_error(_("Unable to use column <%s>"), column);
	    break;
	}
	break;
    case USE_CAT:
	format = CELL_TYPE;
	break;
    case USE_VAL:
	format = value_type;
	break;
    case USE_Z:
	format = DCELL_TYPE;
	is_fp = 1;
	break;
    case USE_D:
	format = DCELL_TYPE;
	break;
    default:
	G_fatal_error(_("Unknown use type: %d"), use);
    }

    fd = Rast_open_new(raster_map, format);

    Points = Vect_new_line_struct();

    if (use != USE_Z && use != USE_D && (ftype & GV_AREA)) {
	if ((nareas = sort_areas(&Map, Points, field, cat_list)) == 0)
	    G_warning(_("No areas selected from vector map <%s>"),
			  vector_map);

	G_debug(1, "%d areas sorted", nareas);
    }
    if (nareas > 0 && dense) {
	G_warning(_("Area conversion and line densification are mutually exclusive, disabling line densification."));
	dense = 0;
    }

    nlines = Vect_get_num_primitives(&Map, ftype);
    nplines_all = nlines;
    npasses = begin_rasterization(cache_mb, format, dense);
    pass = 0;

    nareas_all = Vect_get_num_areas(&Map);

    do {
	pass++;

	if (npasses > 1)
	    G_message(_("Pass %d of %d:"), pass, npasses);

	stat = 0;

	if ((use != USE_Z && use != USE_D) && nareas) {
	    if (do_areas
		(&Map, Points, &cvarr, ctype, use, value,
		 value_type) < 0) {
		G_warning(_("Problem processing areas from vector map <%s>, continuing..."),
			  vector_map);
		stat = -1;
		break;
	    }
	}

	if (nlines) {
	    if ((nlines =
		 do_lines(&Map, Points, &cvarr, ctype, field, cat_list, 
		          use, value, value_type, ftype,
			  &nplines_all, dense)) < 0) {
		G_warning(_("Problem processing lines from vector map <%s>, continuing..."),
			  vector_map);
		stat = -1;
		break;
	    }
	}

	G_important_message(_("Writing raster map..."));

	stat = output_raster(fd);
    } while (stat == 0);

    G_suppress_warnings(0);
    /* stat: 0 == repeat; 1 == done; -1 == error; */

    Vect_destroy_line_struct(Points);

    if (stat < 0) {
	Rast_unopen(fd);

	return 1;
    }

    Vect_close(&Map);

    G_verbose_message(_("Creating support files for raster map..."));
    Rast_close(fd);
    update_hist(raster_map, vector_map, Map.head.orig_scale);

    /* colors */
    if (rgbcolumn) {
	if (use != USE_ATTR && use != USE_CAT) {
	    G_warning(_("Color can be updated from database only if use=attr"));
	    update_colors(raster_map);
	}
	else {
	  update_dbcolors(raster_map, vector_map, field, rgbcolumn, is_fp,
			  column);
	}
    }
    else if (use == USE_D)
	update_fcolors(raster_map);
    else
	update_colors(raster_map);

    update_cats(raster_map);

    /* labels */
    update_labels(raster_map, vector_map, field, labelcolumn, use, value,
		  column);

#if 0
    /* maximum possible numer of areas: number of centroids
     * actual number of areas, currently unknown:
     * number of areas with centroid that are within cat constraint
     * and overlap with current region */
    if (nareas_all > 0)
	G_message(_("Converted areas: %d of %d"), nareas,
	          Vect_get_num_primitives(&Map, GV_CENTROID));
    /* maximum possible numer of lines: number of GV_LINE + GV_POINT
     * actual number of lines, currently unknown:
     * number of lines are within cat constraint
     * and overlap with current region */
    if (nlines > 0 && nplines_all > 0)
	G_message(_("Converted points/lines: %d of %d"), nlines, nplines_all);
#endif

    return 0;
}