Exemplo n.º 1
0
/**
 * Expand a door. This function will try to sensibly connect doors so
 * that they meet up with adjacent walls. Note that it will also
 * presumptuously delete (ignore) doors that it doesn't know how to
 * correctly expand.
 * @param newlayout
 * Expanded layout.
 * @param i
 * X coordinate of door to expand in non expanded layout.
 * @param j
 * Y coordinate of door to expand in non expanded layout.
 * @param layout
 * Non expanded layout.
 * @param xsize
 * X size of the non expanded layout
 * @param ysize
 * Y size of the non expanded layout
 */
static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
{
    int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
    int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
    int join_pattern;

    /* Doors "like" to connect to walls more than other doors. If there is
     * a wall and another door, this door will connect to the wall and
     * disconnect from the other door. */
    if (wall_pattern & 3) {
        join_pattern = wall_pattern;
    } else {
        join_pattern = door_pattern;
    }

    newlayout[i * 2][j * 2] = 'D';

    if (i + 1 < xsize) {
        /* There is a door/wall to the right */
        if (join_pattern & 1) {
            newlayout[i * 2 + 1][j * 2] = 'D';
        }
    }

    if (j + 1 < ysize) {
        /* There is a door/wall below */
        if (join_pattern & 2) {
            newlayout[i * 2][j * 2 + 1] = 'D';
        }
    }
}
Exemplo n.º 2
0
/**
 * Expand a wall. This function will try to sensibly connect the
 * resulting wall to adjacent wall squares, so that the result won't have
 * disconnected walls.
 * @param newlayout
 * Nap layout.
 * @param i
 * X coordinate of wall to expand in non expanded layout.
 * @param j
 * Y coordinate of wall to expand in non expanded layout.
 * @param layout
 * Current (non expanded) layout.
 * @param xsize
 * X size of layout.
 * @param ysize
 * Y size of layout.
 */
static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
{
    int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
    int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
    int both_pattern = wall_pattern | door_pattern;

    newlayout[i * 2][j * 2] = '#';

    if (i + 1 < xsize) {
        /* join walls/doors to the right */
        if (both_pattern & 1) {
            newlayout[i * 2 + 1][j * 2] = layout[i + 1][j];
        }
    }

    if (j + 1 < ysize) {
        /* join walls/doors to the bottom */
        if (both_pattern & 2) {
            newlayout[i * 2][j * 2 + 1] = layout[i][j + 1];
        }

        if (wall_pattern == 7) {
            /* if orig layout is a 2x2 wall block,
             * we fill the result with walls. */
            newlayout[i * 2 + 1][j * 2 + 1] = '#';
        }
    }
}
Exemplo n.º 3
0
int main(int argc, char **argv)
{
	IO rasters[] = { /* rasters stores output buffers */
		{"dem",YES,"Input dem","input",UNKNOWN,-1,NULL}, /* WARNING: this one map is input */
		{"forms",NO,"Most common geomorphic forms","patterns",CELL_TYPE,-1,NULL},
		{"ternary",NO,"code of ternary patterns","patterns",CELL_TYPE,-1,NULL},
		{"positive",NO,"code of binary positive patterns","patterns",CELL_TYPE,-1,NULL},
		{"negative",NO,"code of binary negative patterns","patterns",CELL_TYPE,-1,NULL},
		{"intensity",NO,"rasters containing mean relative elevation of the form","geometry",FCELL_TYPE,-1,NULL},
		{"exposition",NO,"rasters containing maximum difference between extend and central cell","geometry",FCELL_TYPE,-1,NULL},
		{"range",NO,"rasters containing difference between max and min elevation of the form extend","geometry",FCELL_TYPE,-1,NULL},
		{"variance",NO,"rasters containing variance of form boundary","geometry",FCELL_TYPE,-1,NULL},
		{"elongation",NO,"rasters containing local elongation","geometry",FCELL_TYPE,-1,NULL},
		{"azimuth",NO,"rasters containing local azimuth of the elongation","geometry",FCELL_TYPE,-1,NULL},
		{"extend",NO,"rasters containing local extend (area) of the form","geometry",FCELL_TYPE,-1,NULL},
		{"width",NO,"rasters containing local width of the form","geometry",FCELL_TYPE,-1,NULL}
	}; /* adding more maps change IOSIZE macro */
	
	CATCOLORS ccolors[CNT]={ /* colors and cats for forms */
		{ZERO, 0, 0, 0, "forms"},
		{FL, 220, 220, 220, "flat"},
		{PK, 56, 0, 0, "summit"},
		{RI, 200, 0, 0, "ridge"},
		{SH, 255, 80, 20, "shoulder"},
		{CV, 250, 210, 60, "spur"},
		{SL, 255, 255, 60, "slope"},
		{CN, 180, 230, 20, "hollow"},
		{FS, 60, 250, 150, "footslope"},
		{VL, 0, 0, 255, "valley"},
		{PT, 0, 0, 56, "depression"},
		{__, 255, 0, 255, "ERROR"}};

struct GModule *module;
	struct Option
					*opt_input,
					*opt_output[io_size],
					*par_search_radius,
					*par_skip_radius,
					*par_flat_treshold,
					*par_flat_distance;
	struct Flag *flag_units,
							*flag_extended;

	struct History history;

	int i,j, n;
	int meters=0, multires=0, extended=0; /* flags */
	int row,cur_row,col,radius;
	int pattern_size;
	double max_resolution;
	char prefix[20];

	G_gisinit(argv[0]);

{  /* interface  parameters */
	module = G_define_module();
	module->description =
	_("Calculate geomorphons (terrain forms)and associated geometry using machine vision approach");
	G_add_keyword("Geomorphons");
	G_add_keyword("Terrain patterns");
	G_add_keyword("Machine vision geomorphometry");

	opt_input = G_define_standard_option(G_OPT_R_INPUT);
	opt_input->key = rasters[0].name;
	opt_input->required = rasters[0].required;
	opt_input->description = _(rasters[0].description);

		for (i=1;i<io_size;++i) { /* WARNING: loop starts from one, zero is for input */
	opt_output[i] = G_define_standard_option(G_OPT_R_OUTPUT);
	opt_output[i]->key = rasters[i].name;
	opt_output[i]->required = NO;
	opt_output[i]->description = _(rasters[i].description);
	opt_output[i]->guisection = _(rasters[i].gui);
		}

	par_search_radius = G_define_option();
	par_search_radius->key = "search";
	par_search_radius->type = TYPE_INTEGER;
	par_search_radius->answer = "3";
	par_search_radius->required = YES;
	par_search_radius->description = _("Outer search radius");

	par_skip_radius = G_define_option();
	par_skip_radius->key = "skip";
	par_skip_radius->type = TYPE_INTEGER;
	par_skip_radius->answer = "0";
	par_skip_radius->required = YES;
	par_skip_radius->description = _("Inner search radius");

	par_flat_treshold = G_define_option();
	par_flat_treshold->key = "flat";
	par_flat_treshold->type = TYPE_DOUBLE;
	par_flat_treshold->answer = "1";
	par_flat_treshold->required = YES;
	par_flat_treshold->description = _("Flatenss treshold (degrees)");

	par_flat_distance = G_define_option();
	par_flat_distance->key = "dist";
	par_flat_distance->type = TYPE_DOUBLE;
	par_flat_distance->answer = "0";
	par_flat_distance->required = YES;
	par_flat_distance->description = _("Flatenss distance, zero for none");

	flag_units = G_define_flag();
	flag_units->key = 'm';
	flag_units->description = _("Use meters to define search units (default is cells)");

	flag_extended = G_define_flag();
	flag_extended->key = 'e';
	flag_extended->description = _("Use extended form correction");

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

{	/* calculate parameters */
	int num_outputs=0;
	double search_radius, skip_radius, start_radius, step_radius;
	double ns_resolution;

			for (i=1;i<io_size;++i) /* check for outputs */
	if(opt_output[i]->answer) {
			if (G_legal_filename(opt_output[i]->answer) < 0)
		G_fatal_error(_("<%s> is an illegal file name"), opt_output[i]->answer);
		num_outputs++;
	}
		if(!num_outputs && !multires)
	G_fatal_error(_("At least one output is required"));

	meters=(flag_units->answer != 0);
	extended=(flag_extended->answer != 0);
	nrows = Rast_window_rows();
	ncols = Rast_window_cols();
	Rast_get_window(&window);
	G_begin_distance_calculations();

	if(G_projection()==PROJECTION_LL)	{ /* for LL max_res should be NS */
		ns_resolution=G_distance(0,Rast_row_to_northing(0, &window),0,Rast_row_to_northing(1, &window));
		max_resolution=ns_resolution;
	} else {
		max_resolution=MAX(window.ns_res,window.ew_res); /* max_resolution MORE meters per cell */
	}
	G_message("NSRES, %f", ns_resolution);
	cell_res=max_resolution; /* this parameter is global */
	/* search distance */
	search_radius=atof(par_search_radius->answer);
	search_cells=meters?(int)(search_radius/max_resolution):search_radius;
		if(search_cells<1)
	G_fatal_error(_("Search radius size must cover at least 1 cell"));
	row_radius_size=meters?ceil(search_radius/max_resolution):search_radius;
	row_buffer_size=row_radius_size*2+1;
	search_distance=(meters)?search_radius:max_resolution*search_cells;
	/* skip distance */
	skip_radius=atof(par_skip_radius->answer);
	skip_cells=meters?(int)(skip_radius/max_resolution):skip_radius;
		if(skip_cells>=search_cells)
	G_fatal_error(_("Skip radius size must be at least 1 cell lower than radius"));
	skip_distance=(meters)?skip_radius:ns_resolution*skip_cells;

	/* flatness parameters */
	flat_threshold=atof(par_flat_treshold->answer);
		if(flat_threshold<=0.)
	G_fatal_error(_("Flatenss treshold must be grater than 0"));
	flat_threshold=DEGREE2RAD(flat_threshold);
	
	flat_distance=atof(par_flat_distance->answer);
	flat_distance=(meters)?flat_distance:ns_resolution*flat_distance;
	flat_threshold_height=tan(flat_threshold)*flat_distance;
	if((flat_distance>0&&flat_distance<=skip_distance)||flat_distance>=search_distance) {
		G_warning(_("Flatenss distance should be between skip and search radius. Otherwise ignored"));
		flat_distance=0;
	}
		if (search_distance<10*cell_res)
	extended=0;
	
	/* print information about distances */
	G_message("Search distance m: %f, cells: %d", search_distance, search_cells);
	G_message("Skip distance m: %f, cells: %d", skip_distance, skip_cells);
	G_message("Flat threshold distance m: %f, height: %f",flat_distance, flat_threshold_height);
	G_message("%s version",(extended)?"extended":"basic");
}

	/* generate global ternary codes */
		for(i=0;i<6561;++i)
	global_ternary_codes[i]=ternary_rotate(i);

	/* open DEM */
	strcpy(elevation.elevname,opt_input->answer);
	open_map(&elevation);

	PATTERN* pattern;
	PATTERN patterns[4];
	void* pointer_buf;
	int formA, formB, formC;
	double search_dist=search_distance;
	double skip_dist=skip_distance;
	double flat_dist=flat_distance;
	double area_of_octagon=4*(search_distance*search_distance)*sin(DEGREE2RAD(45.));

	cell_step=1;
	/* prepare outputs */
		for (i=1;i<io_size;++i) 
	if(opt_output[i]->answer) {
		rasters[i].fd=Rast_open_new(opt_output[i]->answer,rasters[i].out_data_type);
		rasters[i].buffer=Rast_allocate_buf(rasters[i].out_data_type);
	}
	
	/* main loop */
	for(row=0;row<nrows;++row) {
		G_percent(row, nrows, 2);
		cur_row = (row < row_radius_size)?row:
			((row >= nrows-row_radius_size-1) ? row_buffer_size - (nrows-row-1) : row_radius_size);
			
			if(row>(row_radius_size) && row<nrows-(row_radius_size+1))
		shift_buffers(row);
		for (col=0;col<ncols;++col) {
		/* on borders forms ussualy are innatural. */
			if(row<(skip_cells+1) || row>nrows-(skip_cells+2) ||
				col<(skip_cells+1) || col>ncols-(skip_cells+2) ||
				Rast_is_f_null_value(&elevation.elev[cur_row][col])) {
/* set outputs to NULL and do nothing if source value is null	or border*/
				for (i=1;i<io_size;++i)
					if(opt_output[i]->answer) {
						pointer_buf=rasters[i].buffer;
						switch (rasters[i].out_data_type) {
						case CELL_TYPE:
							Rast_set_c_null_value(&((CELL*)pointer_buf)[col],1);
							break;
						case FCELL_TYPE:
							Rast_set_f_null_value(&((FCELL*)pointer_buf)[col],1);
							break;
						case DCELL_TYPE:
							Rast_set_d_null_value(&((DCELL*)pointer_buf)[col],1);
							break;
						default:
							G_fatal_error(_("Unknown output data type"));
						}
					}
					continue; 
			} /* end null value */
{
	int cur_form, small_form;
	search_distance=search_dist;
	skip_distance=skip_dist;
	flat_distance=flat_dist;

	pattern_size=calc_pattern(&patterns[0],row,cur_row,col);
	pattern=&patterns[0];
	cur_form=determine_form(pattern->num_negatives,pattern->num_positives);

	/* correction of forms */
	if(extended) {
		/* 1) remove extensive innatural forms: ridges, peaks, shoulders and footslopes */
		if((cur_form==4||cur_form==8||cur_form==2||cur_form==3)) {
			search_distance=(search_dist/4.<4*max_resolution)? 4*max_resolution : search_dist/4.;
			skip_distance=0;
			flat_distance=0;
			pattern_size=calc_pattern(&patterns[1],row,cur_row,col);
			pattern=&patterns[1];
			small_form=determine_form(pattern->num_negatives,pattern->num_positives);
				if(cur_form==4||cur_form==8)
			cur_form=(small_form==1)? 1 : cur_form;
				if(cur_form==2||cur_form==3)
			cur_form=small_form;
		}
		
 } /* end of correction */
	pattern=&patterns[0];
		if(opt_output[o_forms]->answer) 
	((CELL*)rasters[o_forms].buffer)[col]=cur_form;
}

				if(opt_output[o_ternary]->answer)
			((CELL*)rasters[o_ternary].buffer)[col]=determine_ternary(pattern->pattern);
				if(opt_output[o_positive]->answer)
			((CELL*)rasters[o_positive].buffer)[col]=pattern->num_positives;//rotate(pattern->positives);
				if(opt_output[o_negative]->answer)
			((CELL*)rasters[o_negative].buffer)[col]=pattern->num_negatives;//rotate(pattern->negatives);
				if(opt_output[o_intensity]->answer)
			((FCELL*)rasters[o_intensity].buffer)[col]=intensity(pattern->elevation,pattern_size);
				if(opt_output[o_exposition]->answer)
			((FCELL*)rasters[o_exposition].buffer)[col]=exposition(pattern->elevation);
				if(opt_output[o_range]->answer)
			((FCELL*)rasters[o_range].buffer)[col]=range(pattern->elevation);
				if(opt_output[o_variance]->answer)
			((FCELL*)rasters[o_variance].buffer)[col]=variance(pattern->elevation, pattern_size);

//			 used only for next four shape functions 
			if(opt_output[o_elongation]->answer ||opt_output[o_azimuth]->answer||
				opt_output[o_extend]->answer || opt_output[o_width]->answer) {
				float azimuth,elongation,width;
				radial2cartesian(pattern);
				shape(pattern, pattern_size,&azimuth,&elongation,&width);
					if(opt_output[o_azimuth]->answer)
				((FCELL*)rasters[o_azimuth].buffer)[col]=azimuth;
					if(opt_output[o_elongation]->answer)
				((FCELL*)rasters[o_elongation].buffer)[col]=elongation;
					if(opt_output[o_width]->answer)
				((FCELL*)rasters[o_width].buffer)[col]=width;
			}
				if(opt_output[o_extend]->answer)
			((FCELL*)rasters[o_extend].buffer)[col]=extends(pattern, pattern_size)/area_of_octagon;

		} /* end for col */

		/* write existing outputs */
				for (i=1;i<io_size;++i)
			if(opt_output[i]->answer)
		Rast_put_row(rasters[i].fd, rasters[i].buffer, rasters[i].out_data_type);
	}
	G_percent(row, nrows, 2); /* end main loop */

	/* finish and close */
	free_map(elevation.elev, row_buffer_size+1);
		for (i=1;i<io_size;++i)
	if(opt_output[i]->answer) {
		G_free(rasters[i].buffer);
		Rast_close(rasters[i].fd);
		Rast_short_history(opt_output[i]->answer, "raster", &history);
		Rast_command_history(&history);
		Rast_write_history(opt_output[i]->answer, &history);
	}

		if(opt_output[o_forms]->answer)
	write_form_cat_colors(opt_output[o_forms]->answer,ccolors);
		if(opt_output[o_intensity]->answer)
	write_contrast_colors(opt_output[o_intensity]->answer);
		if(opt_output[o_exposition]->answer)
	write_contrast_colors(opt_output[o_exposition]->answer);
		if(opt_output[o_range]->answer)
	write_contrast_colors(opt_output[o_range]->answer);

G_message("Done!");
exit(EXIT_SUCCESS);
}