Ejemplo n.º 1
0
int camera_angle(char *name)
{
    int row, col, nrows, ncols;
    double XC = group.XC;
    double YC = group.YC;
    double ZC = group.ZC;
    double c_angle, c_angle_min, c_alt, c_az, slope, aspect;
    double radians_to_degrees = 180.0 / M_PI;
    /* double degrees_to_radians = M_PI / 180.0; */
    DCELL e1, e2, e3, e4, e5, e6, e7, e8, e9;
    double factor, V, H, dx, dy, dz, key;
    double north, south, east, west, ns_med;
    FCELL *fbuf0, *fbuf1, *fbuf2, *tmpbuf, *outbuf;
    int elevfd, outfd;
    struct Cell_head cellhd;
    struct Colors colr;
    FCELL clr_min, clr_max;
    struct History hist;
    char *type;

    G_message(_("Calculating camera angle to local surface..."));
    
    select_target_env();
    
    /* align target window to elevation map, otherwise we get artefacts
     * like in r.slope.aspect -a */
     
    Rast_get_cellhd(elev_name, elev_mapset, &cellhd);

    Rast_align_window(&target_window, &cellhd);
    Rast_set_window(&target_window);
    
    elevfd = Rast_open_old(elev_name, elev_mapset);
    if (elevfd < 0) {
	G_fatal_error(_("Could not open elevation raster"));
	return 1;
    }

    nrows = target_window.rows;
    ncols = target_window.cols;
    
    outfd = Rast_open_new(name, FCELL_TYPE);
    fbuf0 = Rast_allocate_buf(FCELL_TYPE);
    fbuf1 = Rast_allocate_buf(FCELL_TYPE);
    fbuf2 = Rast_allocate_buf(FCELL_TYPE);
    outbuf = Rast_allocate_buf(FCELL_TYPE);
    
    /* give warning if location units are different from meters and zfactor=1 */
    factor = G_database_units_to_meters_factor();
    if (factor != 1.0)
	G_warning(_("Converting units to meters, factor=%.6f"), factor);

    G_begin_distance_calculations();
    north = Rast_row_to_northing(0.5, &target_window);
    ns_med = Rast_row_to_northing(1.5, &target_window);
    south = Rast_row_to_northing(2.5, &target_window);
    east = Rast_col_to_easting(2.5, &target_window);
    west = Rast_col_to_easting(0.5, &target_window);
    V = G_distance(east, north, east, south) * 4;
    H = G_distance(east, ns_med, west, ns_med) * 4;
    
    c_angle_min = 90;
    Rast_get_row(elevfd, fbuf1, 0, FCELL_TYPE);
    Rast_get_row(elevfd, fbuf2, 1, FCELL_TYPE);

    for (row = 0; row < nrows; row++) {
	G_percent(row, nrows, 2);
	
	Rast_set_null_value(outbuf, ncols, FCELL_TYPE);

	/* first and last row */
	if (row == 0 || row == nrows - 1) {
	    Rast_put_row(outfd, outbuf, FCELL_TYPE);
	    continue;
	}
	
	tmpbuf = fbuf0;
	fbuf0 = fbuf1;
	fbuf1 = fbuf2;
	fbuf2 = tmpbuf;
	
	Rast_get_row(elevfd, fbuf2, row + 1, FCELL_TYPE);

	north = Rast_row_to_northing(row + 0.5, &target_window);

	for (col = 1; col < ncols - 1; col++) {
	    
	    e1 = fbuf0[col - 1];
	    if (Rast_is_d_null_value(&e1))
		continue;
	    e2 = fbuf0[col];
	    if (Rast_is_d_null_value(&e2))
		continue;
	    e3 = fbuf0[col + 1];
	    if (Rast_is_d_null_value(&e3))
		continue;
	    e4 = fbuf1[col - 1];
	    if (Rast_is_d_null_value(&e4))
		continue;
	    e5 = fbuf1[col];
	    if (Rast_is_d_null_value(&e5))
		continue;
	    e6 = fbuf1[col + 1];
	    if (Rast_is_d_null_value(&e6))
		continue;
	    e7 = fbuf2[col - 1];
	    if (Rast_is_d_null_value(&e7))
		continue;
	    e8 = fbuf2[col];
	    if (Rast_is_d_null_value(&e8))
		continue;
	    e9 = fbuf2[col + 1];
	    if (Rast_is_d_null_value(&e9))
		continue;
	    
	    dx = ((e1 + e4 + e4 + e7) - (e3 + e6 + e6 + e9)) / H;
	    dy = ((e7 + e8 + e8 + e9) - (e1 + e2 + e2 + e3)) / V;
	    
	    /* compute topographic parameters */
	    key = dx * dx + dy * dy;
	    /* slope in radians */
	    slope = atan(sqrt(key));

	    /* aspect in radians */
	    if (key == 0.)
		aspect = 0.;
	    else if (dx == 0) {
		if (dy > 0)
		    aspect = M_PI / 2;
		else
		    aspect = 1.5 * M_PI;
	    }
	    else {
		aspect = atan2(dy, dx);
		if (aspect <= 0.)
		    aspect = 2 * M_PI + aspect;
	    }
	    
	    /* camera altitude angle in radians */
	    east = Rast_col_to_easting(col + 0.5, &target_window);
	    dx = east - XC;
	    dy = north - YC;
	    dz = ZC - e5;
	    c_alt = atan(sqrt(dx * dx + dy * dy) / dz);

	    /* camera azimuth angle in radians */
	    c_az = atan(dy / dx);
	    if (east < XC && north != YC)
		c_az += M_PI;
	    else if (north < YC && east > XC)
		c_az += 2 * M_PI;
		
	    /* camera angle to real ground */
	    /* orthogonal to ground: 90 degrees */
	    /* parallel to ground: 0 degrees */
	    c_angle = asin(cos(c_alt) * cos(slope) - sin(c_alt) * sin(slope) * cos(c_az - aspect));
	    
	    outbuf[col] = c_angle * radians_to_degrees;
	    if (c_angle_min > outbuf[col])
		c_angle_min = outbuf[col];
	}
	Rast_put_row(outfd, outbuf, FCELL_TYPE);
    }
    G_percent(row, nrows, 2);

    Rast_close(elevfd);
    Rast_close(outfd);
    G_free(fbuf0);
    G_free(fbuf1);
    G_free(fbuf2);
    G_free(outbuf);

    type = "raster";
    Rast_short_history(name, type, &hist);
    Rast_command_history(&hist);
    Rast_write_history(name, &hist);
    
    Rast_init_colors(&colr);
    if (c_angle_min < 0) {
	clr_min = (FCELL)((int)(c_angle_min / 10 - 1)) * 10;
	clr_max = 0;
	Rast_add_f_color_rule(&clr_min, 0, 0, 0, &clr_max, 0,
				  0, 0, &colr);
    }
    clr_min = 0;
    clr_max = 10;
    Rast_add_f_color_rule(&clr_min, 0, 0, 0, &clr_max, 255,
			      0, 0, &colr);
    clr_min = 10;
    clr_max = 40;
    Rast_add_f_color_rule(&clr_min, 255, 0, 0, &clr_max, 255,
			      255, 0, &colr);
    clr_min = 40;
    clr_max = 90;
    Rast_add_f_color_rule(&clr_min, 255, 255, 0, &clr_max, 0,
			      255, 0, &colr);

    Rast_write_colors(name, G_mapset(), &colr);

    select_current_env();

    return 1;
}
Ejemplo n.º 2
0
int main(int argc, char *argv[])
{
    int i;
    int print_flag = 0;
    int flat_flag; 
    int set_flag;
    double x;
    int ival;
    int row_flag = 0, col_flag = 0;
    struct Cell_head window, temp_window;
    const char *value;
    const char *name;
    const char *mapset;
    char **rast_ptr, **vect_ptr;

    struct GModule *module;
    struct
    {
	struct Flag
	    *update, *print, *gprint, *flprint, *lprint, *eprint, *nangle,
	    *center, *res_set, *dist_res, *dflt, *z, *savedefault,
	    *bbox, *gmt_style, *wms_style;
    } flag;
    struct
    {
	struct Option
	    *north, *south, *east, *west, *top, *bottom,
	    *res, *nsres, *ewres, *res3, *tbres, *rows, *cols,
	    *save, *region, *raster, *raster3d, *align,
	    *zoom, *vect;
    } parm;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("general"));
    G_add_keyword(_("settings"));
    module->description =
	_("Manages the boundary definitions for the " "geographic region.");

    /* flags */

    flag.dflt = G_define_flag();
    flag.dflt->key = 'd';
    flag.dflt->description = _("Set from default region");
    flag.dflt->guisection = _("Existing");

    flag.savedefault = G_define_flag();
    flag.savedefault->key = 's';
    flag.savedefault->label = _("Save as default region");
    flag.savedefault->description = _("Only possible from the PERMANENT mapset");
    flag.savedefault->guisection = _("Existing");

    flag.print = G_define_flag();
    flag.print->key = 'p';
    flag.print->description = _("Print the current region");
    flag.print->guisection = _("Print");

    flag.lprint = G_define_flag();
    flag.lprint->key = 'l';
    flag.lprint->description = _("Print the current region in lat/long "
				 "using the current ellipsoid/datum");
    flag.lprint->guisection = _("Print");

    flag.eprint = G_define_flag();
    flag.eprint->key = 'e';
    flag.eprint->description = _("Print the current region extent");
    flag.eprint->guisection = _("Print");

    flag.center = G_define_flag();
    flag.center->key = 'c';
    flag.center->description =
	_("Print the current region map center coordinates");
    flag.center->guisection = _("Print");

    flag.gmt_style = G_define_flag();
    flag.gmt_style->key = 't';
    flag.gmt_style->description =
	_("Print the current region in GMT style");
    flag.gmt_style->guisection = _("Print");

    flag.wms_style = G_define_flag();
    flag.wms_style->key = 'w';
    flag.wms_style->description =
	_("Print the current region in WMS style");
    flag.wms_style->guisection = _("Print");

    flag.dist_res = G_define_flag();
    flag.dist_res->key = 'm';
    flag.dist_res->description =
	_("Print region resolution in meters (geodesic)");
    flag.dist_res->guisection = _("Print");

    flag.nangle = G_define_flag();
    flag.nangle->key = 'n';
    flag.nangle->label = _("Print the convergence angle (degrees CCW)");
    flag.nangle->description =
	_("The difference between the projection's grid north and true north, "
	  "measured at the center coordinates of the current region.");
    flag.nangle->guisection = _("Print");

    flag.z = G_define_flag();
    flag.z->key = '3';
    flag.z->description = _("Print also 3D settings");
    flag.z->guisection = _("Print");

    flag.bbox = G_define_flag();
    flag.bbox->key = 'b';
    flag.bbox->description =
	_("Print the maximum bounding box in lat/long on WGS84");
    flag.bbox->guisection = _("Print");

    flag.gprint = G_define_flag();
    flag.gprint->key = 'g';
    flag.gprint->description = _("Print in shell script style");
    flag.gprint->guisection = _("Print");

    flag.flprint = G_define_flag();
    flag.flprint->key = 'f';
    flag.flprint->description = _("Print in shell script style, but in one line (flat)");
    flag.flprint->guisection = _("Print");

    flag.res_set = G_define_flag();
    flag.res_set->key = 'a';
    flag.res_set->description =
	_("Align region to resolution (default = align to bounds, "
	  "works only for 2D resolution)");
    flag.res_set->guisection = _("Bounds");

    flag.update = G_define_flag();
    flag.update->key = 'u';
    flag.update->description = _("Do not update the current region");
    flag.update->guisection = _("Effects");

    /* parameters */

    parm.region = G_define_standard_option(G_OPT_M_REGION);
    parm.region->description = _("Set current region from named region");
    parm.region->guisection = _("Existing");

    parm.raster = G_define_standard_option(G_OPT_R_MAP);
    parm.raster->key = "raster";
    parm.raster->required = NO;
    parm.raster->multiple = YES;
    parm.raster->description = _("Set region to match raster map(s)");
    parm.raster->guisection = _("Existing");

    parm.raster3d = G_define_standard_option(G_OPT_R3_MAP);
    parm.raster3d->key = "raster_3d";
    parm.raster3d->required = NO;
    parm.raster3d->multiple = NO;
    parm.raster3d->description =
	_("Set region to match 3D raster map(s) (both 2D and 3D "
	  "values)");
    parm.raster3d->guisection = _("Existing");

    parm.vect = G_define_standard_option(G_OPT_V_MAP);
    parm.vect->key = "vector";
    parm.vect->required = NO;
    parm.vect->multiple = YES;
    parm.vect->label = _("Set region to match vector map(s)");
    parm.vect->description = NULL;
    parm.vect->guisection = _("Existing");

    parm.north = G_define_option();
    parm.north->key = "n";
    parm.north->key_desc = "value";
    parm.north->required = NO;
    parm.north->multiple = NO;
    parm.north->type = TYPE_STRING;
    parm.north->description = _("Value for the northern edge");
    parm.north->guisection = _("Bounds");

    parm.south = G_define_option();
    parm.south->key = "s";
    parm.south->key_desc = "value";
    parm.south->required = NO;
    parm.south->multiple = NO;
    parm.south->type = TYPE_STRING;
    parm.south->description = _("Value for the southern edge");
    parm.south->guisection = _("Bounds");

    parm.east = G_define_option();
    parm.east->key = "e";
    parm.east->key_desc = "value";
    parm.east->required = NO;
    parm.east->multiple = NO;
    parm.east->type = TYPE_STRING;
    parm.east->description = _("Value for the eastern edge");
    parm.east->guisection = _("Bounds");

    parm.west = G_define_option();
    parm.west->key = "w";
    parm.west->key_desc = "value";
    parm.west->required = NO;
    parm.west->multiple = NO;
    parm.west->type = TYPE_STRING;
    parm.west->description = _("Value for the western edge");
    parm.west->guisection = _("Bounds");

    parm.top = G_define_option();
    parm.top->key = "t";
    parm.top->key_desc = "value";
    parm.top->required = NO;
    parm.top->multiple = NO;
    parm.top->type = TYPE_STRING;
    parm.top->description = _("Value for the top edge");
    parm.top->guisection = _("Bounds");

    parm.bottom = G_define_option();
    parm.bottom->key = "b";
    parm.bottom->key_desc = "value";
    parm.bottom->required = NO;
    parm.bottom->multiple = NO;
    parm.bottom->type = TYPE_STRING;
    parm.bottom->description = _("Value for the bottom edge");
    parm.bottom->guisection = _("Bounds");

    parm.rows = G_define_option();
    parm.rows->key = "rows";
    parm.rows->key_desc = "value";
    parm.rows->required = NO;
    parm.rows->multiple = NO;
    parm.rows->type = TYPE_INTEGER;
    parm.rows->description = _("Number of rows in the new region");
    parm.rows->guisection = _("Resolution");

    parm.cols = G_define_option();
    parm.cols->key = "cols";
    parm.cols->key_desc = "value";
    parm.cols->required = NO;
    parm.cols->multiple = NO;
    parm.cols->type = TYPE_INTEGER;
    parm.cols->description = _("Number of columns in the new region");
    parm.cols->guisection = _("Resolution");

    parm.res = G_define_option();
    parm.res->key = "res";
    parm.res->key_desc = "value";
    parm.res->required = NO;
    parm.res->multiple = NO;
    parm.res->type = TYPE_STRING;
    parm.res->description =
	_("2D grid resolution (north-south and east-west)");
    parm.res->guisection = _("Resolution");

    parm.res3 = G_define_option();
    parm.res3->key = "res3";
    parm.res3->key_desc = "value";
    parm.res3->required = NO;
    parm.res3->multiple = NO;
    parm.res3->type = TYPE_STRING;
    parm.res3->description =
	_("3D grid resolution (north-south, east-west and top-bottom)");
    parm.res3->guisection = _("Resolution");

    parm.nsres = G_define_option();
    parm.nsres->key = "nsres";
    parm.nsres->key_desc = "value";
    parm.nsres->required = NO;
    parm.nsres->multiple = NO;
    parm.nsres->type = TYPE_STRING;
    parm.nsres->description = _("North-south 2D grid resolution");
    parm.nsres->guisection = _("Resolution");

    parm.ewres = G_define_option();
    parm.ewres->key = "ewres";
    parm.ewres->key_desc = "value";
    parm.ewres->required = NO;
    parm.ewres->multiple = NO;
    parm.ewres->type = TYPE_STRING;
    parm.ewres->description = _("East-west 2D grid resolution");
    parm.ewres->guisection = _("Resolution");

    parm.tbres = G_define_option();
    parm.tbres->key = "tbres";
    parm.tbres->key_desc = "value";
    parm.tbres->required = NO;
    parm.tbres->multiple = NO;
    parm.tbres->type = TYPE_STRING;
    parm.tbres->description = _("Top-bottom 3D grid resolution");
    parm.tbres->guisection = _("Resolution");

    parm.zoom = G_define_option();
    parm.zoom->key = "zoom";
    parm.zoom->key_desc = "name";
    parm.zoom->required = NO;
    parm.zoom->multiple = NO;
    parm.zoom->type = TYPE_STRING;
    parm.zoom->description =
	_("Shrink region until it meets non-NULL data from this raster map");
    parm.zoom->gisprompt = "old,cell,raster";
    parm.zoom->guisection = _("Bounds");

    parm.align = G_define_option();
    parm.align->key = "align";
    parm.align->key_desc = "name";
    parm.align->required = NO;
    parm.align->multiple = NO;
    parm.align->type = TYPE_STRING;
    parm.align->description =
	_("Adjust region cells to cleanly align with this raster map");
    parm.align->gisprompt = "old,cell,raster";
    parm.align->guisection = _("Bounds");

    parm.save = G_define_option();
    parm.save->key = "save";
    parm.save->key_desc = "name";
    parm.save->required = NO;
    parm.save->multiple = NO;
    parm.save->type = TYPE_STRING;
    parm.save->description =
	_("Save current region settings in named region file");
    parm.save->gisprompt = "new,windows,region";
    parm.save->guisection = _("Effects");

    G_option_required(flag.dflt, flag.savedefault, flag.print, flag.lprint,
                      flag.eprint, flag.center, flag.gmt_style, flag.wms_style,
                      flag.dist_res, flag.nangle, flag. z, flag.bbox, flag.gprint,
                      flag.res_set, flag.update, parm.region, parm.raster,
                      parm.raster3d, parm.vect, parm.north, parm.south, parm.east,
                      parm.west, parm.top, parm.bottom, parm.rows, parm.cols,
                      parm.res, parm.res3, parm.nsres, parm.ewres, parm.tbres,
                      parm.zoom, parm.align, parm.save, NULL);

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

    G_get_default_window(&window);

    set_flag = !flag.update->answer;
    flat_flag = flag.flprint->answer;

    if (flag.print->answer)
	print_flag |= PRINT_REG;

    if (flag.gprint->answer)
	print_flag |= PRINT_SH;

    if (flag.lprint->answer)
	print_flag |= PRINT_LL;

    if (flag.eprint->answer)
	print_flag |= PRINT_EXTENT;

    if (flag.center->answer)
	print_flag |= PRINT_CENTER;

    if (flag.gmt_style->answer)
	print_flag |= PRINT_GMT;

    if (flag.wms_style->answer)
	print_flag |= PRINT_WMS;

    if (flag.nangle->answer)
	print_flag |= PRINT_NANGLE;

    if (flag.dist_res->answer)
	print_flag |= PRINT_METERS;

    if (flag.z->answer)
	print_flag |= PRINT_3D;

    if (flag.bbox->answer)
	print_flag |= PRINT_MBBOX;

    if (print_flag == PRINT_METERS)
	print_flag |= PRINT_SH;

    if (print_flag == PRINT_SH ||
	print_flag & PRINT_3D || print_flag == PRINT_METERS + PRINT_SH) {
	print_flag |= PRINT_REG;
    }

    if (!flag.dflt->answer)
	G_get_window(&window);

    /* region= */
    if ((name = parm.region->answer)) {
	mapset = G_find_file2("windows", name, "");
	if (!mapset)
	    G_fatal_error(_("Region <%s> not found"), name);
	G_get_element_window(&window, "windows", name, mapset);
    }

    /* raster= */
    if (parm.raster->answer) {
	int first = 0;

	rast_ptr = parm.raster->answers;
	for (; *rast_ptr != NULL; rast_ptr++) {
	    char rast_name[GNAME_MAX];

	    strcpy(rast_name, *rast_ptr);
	    mapset = G_find_raster2(rast_name, "");
	    if (!mapset)
		G_fatal_error(_("Raster map <%s> not found"), rast_name);
	    Rast_get_cellhd(rast_name, mapset, &temp_window);
	    if (!first) {
		window = temp_window;
		first = 1;
	    }
	    else {
		window.north = (window.north > temp_window.north) ?
		    window.north : temp_window.north;
		window.south = (window.south < temp_window.south) ?
		    window.south : temp_window.south;
		window.east = (window.east > temp_window.east) ?
		    window.east : temp_window.east;
		window.west = (window.west < temp_window.west) ?
		    window.west : temp_window.west;
	    }
	}
	G_adjust_Cell_head3(&window, 0, 0, 0);
    }


    /* raster3d= */
    if ((name = parm.raster3d->answer)) {
	RASTER3D_Region win;

	if ((mapset = G_find_raster3d(name, "")) == NULL)
	    G_fatal_error(_("3D raster map <%s> not found"), name);

	if (Rast3d_read_region_map(name, mapset, &win) < 0)
	    G_fatal_error(_("Unable to read header of 3D raster map <%s@%s>"),
			  name, mapset);

	Rast3d_region_to_cell_head(&win, &window);
    }

    /* vector= */
    if (parm.vect->answer) {
	int first = 0;

	vect_ptr = parm.vect->answers;
	for (; *vect_ptr != NULL; vect_ptr++) {
	    struct Map_info Map;
	    struct bound_box box;
	    char vect_name[GNAME_MAX];
	    struct Cell_head map_window;

	    strcpy(vect_name, *vect_ptr);
	    mapset = G_find_vector2(vect_name, "");
	    if (!mapset)
		G_fatal_error(_("Vector map <%s> not found"), vect_name);

	    temp_window = window;

	    Vect_set_open_level(2);
	    if (2 > Vect_open_old_head(&Map, vect_name, mapset))
		G_fatal_error(_("Unable to open vector map <%s> on topological level"),
			      vect_name);
            
	    Vect_get_map_box(&Map, &box);
	    map_window = window;
	    map_window.north = box.N;
	    map_window.south = box.S;
	    map_window.west = box.W;
	    map_window.east = box.E;
	    map_window.top = box.T;
	    map_window.bottom = box.B;

	    if (!first) {
		window = map_window;
		first = 1;
	    }
	    else {
		window.north = (window.north > map_window.north) ?
		    window.north : map_window.north;
		window.south = (window.south < map_window.south) ?
		    window.south : map_window.south;
		window.east = (window.east > map_window.east) ?
		    window.east : map_window.east;
		window.west = (window.west < map_window.west) ?
		    window.west : map_window.west;
		if (map_window.top > window.top)
		    window.top = map_window.top;
		if (map_window.bottom < window.bottom)
		    window.bottom = map_window.bottom;
	    }

	    if (window.north == window.south) {
		window.north = window.north + 0.5 * temp_window.ns_res;
		window.south = window.south - 0.5 * temp_window.ns_res;
	    }
	    if (window.east == window.west) {
		window.west = window.west - 0.5 * temp_window.ew_res;
		window.east = window.east + 0.5 * temp_window.ew_res;
	    }
	    if (window.top == window.bottom) {
		window.bottom = (window.bottom - 0.5 * temp_window.tb_res);
		window.top = (window.top + 0.5 * temp_window.tb_res);
	    }

	    if (flag.res_set->answer)
		Rast_align_window(&window, &temp_window);

	    Vect_close(&Map);
	}
    }

    /* n= */
    if ((value = parm.north->answer)) {
	if ((i = nsew(value, "n+", "n-", "s+"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.north);
	    switch (i) {
	    case 1:
		window.north += x;
		break;
	    case 2:
		window.north -= x;
		break;
	    case 3:
		window.north = window.south + x;
		break;
	    }
	}
	else if (G_scan_northing(value, &x, window.proj))
	    window.north = x;
	else
	    die(parm.north);
    }

    /* s= */
    if ((value = parm.south->answer)) {
	if ((i = nsew(value, "s+", "s-", "n-"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.south);
	    switch (i) {
	    case 1:
		window.south += x;
		break;
	    case 2:
		window.south -= x;
		break;
	    case 3:
		window.south = window.north - x;
		break;
	    }
	}
	else if (G_scan_northing(value, &x, window.proj))
	    window.south = x;
	else
	    die(parm.south);
    }

    /* e= */
    if ((value = parm.east->answer)) {
	if ((i = nsew(value, "e+", "e-", "w+"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.east);
	    switch (i) {
	    case 1:
		window.east += x;
		break;
	    case 2:
		window.east -= x;
		break;
	    case 3:
		window.east = window.west + x;
		break;
	    }
	}
	else if (G_scan_easting(value, &x, window.proj))
	    window.east = x;
	else
	    die(parm.east);
    }

    /* w= */
    if ((value = parm.west->answer)) {
	if ((i = nsew(value, "w+", "w-", "e-"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.west);
	    switch (i) {
	    case 1:
		window.west += x;
		break;
	    case 2:
		window.west -= x;
		break;
	    case 3:
		window.west = window.east - x;
		break;
	    }
	}
	else if (G_scan_easting(value, &x, window.proj))
	    window.west = x;
	else
	    die(parm.west);
    }

    /* t= */
    if ((value = parm.top->answer)) {
	if ((i = nsew(value, "t+", "t-", "b+"))) {
	    if (sscanf(value + 2, "%lf", &x) != 1)
		die(parm.top);
	    switch (i) {
	    case 1:
		window.top += x;
		break;
	    case 2:
		window.top -= x;
		break;
	    case 3:
		window.top = window.bottom + x;
		break;
	    }
	}
	else if (sscanf(value, "%lf", &x) == 1)
	    window.top = x;
	else
	    die(parm.top);
    }

    /* b= */
    if ((value = parm.bottom->answer)) {
	if ((i = nsew(value, "b+", "b-", "t-"))) {
	    if (sscanf(value + 2, "%lf", &x) != 1)
		die(parm.bottom);
	    switch (i) {
	    case 1:
		window.bottom += x;
		break;
	    case 2:
		window.bottom -= x;
		break;
	    case 3:
		window.bottom = window.top - x;
		break;
	    }
	}
	else if (sscanf(value, "%lf", &x) == 1)
	    window.bottom = x;
	else
	    die(parm.bottom);
    }

    /* res= */
    if ((value = parm.res->answer)) {
	if (!G_scan_resolution(value, &x, window.proj))
	    die(parm.res);
	window.ns_res = x;
	window.ew_res = x;

	if (flag.res_set->answer) {
	    window.north = ceil(window.north / x) * x;
	    window.south = floor(window.south / x) * x;
	    window.east = ceil(window.east / x) * x;
	    window.west = floor(window.west / x) * x;
	}
    }

    /* res3= */
    if ((value = parm.res3->answer)) {
	if (!G_scan_resolution(value, &x, window.proj))
	    die(parm.res);
	window.ns_res3 = x;
	window.ew_res3 = x;
	window.tb_res = x;
    }

    /* nsres= */
    if ((value = parm.nsres->answer)) {
	if (!G_scan_resolution(value, &x, window.proj))
	    die(parm.nsres);
	window.ns_res = x;

	if (flag.res_set->answer) {
	    window.north = ceil(window.north / x) * x;
	    window.south = floor(window.south / x) * x;
	}
    }

    /* ewres= */
    if ((value = parm.ewres->answer)) {
	if (!G_scan_resolution(value, &x, window.proj))
	    die(parm.ewres);
	window.ew_res = x;

	if (flag.res_set->answer) {
	    window.east = ceil(window.east / x) * x;
	    window.west = floor(window.west / x) * x;
	}
    }

    /* tbres= */
    if ((value = parm.tbres->answer)) {
	if (sscanf(value, "%lf", &x) != 1)
	    die(parm.tbres);
	window.tb_res = x;

	if (flag.res_set->answer) {
	    window.top = ceil(window.top / x) * x;
	    window.bottom = floor(window.bottom / x) * x;
	}
    }

    /* rows= */
    if ((value = parm.rows->answer)) {
	if (sscanf(value, "%i", &ival) != 1)
	    die(parm.rows);
	window.rows = ival;
	row_flag = 1;
    }

    /* cols= */
    if ((value = parm.cols->answer)) {
	if (sscanf(value, "%i", &ival) != 1)
	    die(parm.cols);
	window.cols = ival;
	col_flag = 1;
    }

    /* zoom= */
    if ((name = parm.zoom->answer)) {
	mapset = G_find_raster2(name, "");
	if (!mapset)
	    G_fatal_error(_("Raster map <%s> not found"), name);
	zoom(&window, name, mapset);
    }

    /* align= */
    if ((name = parm.align->answer)) {
	mapset = G_find_raster2(name, "");
	if (!mapset)
	    G_fatal_error(_("Raster map <%s> not found"), name);
	Rast_get_cellhd(name, mapset, &temp_window);
	Rast_align_window(&window, &temp_window);
    }

    /* save= */
    if ((name = parm.save->answer)) {
	temp_window = window;
	G_adjust_Cell_head3(&temp_window, 0, 0, 0);
	if (G_put_element_window(&temp_window, "windows", name) < 0)
	    G_fatal_error(_("Unable to set region <%s>"), name);
    }

    G_adjust_Cell_head3(&window, row_flag, col_flag, 0);
    if (set_flag) {
	if (G_put_window(&window) < 0)
	    G_fatal_error(_("Unable to update current region"));
    }

    if (flag.savedefault->answer) {
	if (strcmp(G_mapset(), "PERMANENT") == 0) {
	    G_put_element_window(&window, "", "DEFAULT_WIND");
	}
	else {
	    G_fatal_error(_("Unable to change default region. "
			    "The current mapset is not <PERMANENT>."));
	}
    }				/* / flag.savedefault->answer */


    if (print_flag)
	print_window(&window, print_flag, flat_flag);

    exit(EXIT_SUCCESS);
}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
    int out_fd, base_raster;
    char *infile, *outmap;
    int percent;
    double zrange_min, zrange_max, d_tmp;
    double irange_min, irange_max;
    unsigned long estimated_lines;

    RASTER_MAP_TYPE rtype, base_raster_data_type;
    struct History history;
    char title[64];
    SEGMENT base_segment;
    struct PointBinning point_binning;
    void *base_array;
    void *raster_row;
    struct Cell_head region;
    struct Cell_head input_region;
    int rows, last_rows, row0, cols;		/* scan box size */
    int row;		/* counters */

    int pass, npasses;
    unsigned long line, line_total;
    unsigned int counter;
    unsigned long n_invalid;
    char buff[BUFFSIZE];
    double x, y, z;
    double intensity;
    int arr_row, arr_col;
    unsigned long count, count_total;
    int point_class;

    double zscale = 1.0;
    double iscale = 1.0;
    double res = 0.0;

    struct BinIndex bin_index_nodes;
    bin_index_nodes.num_nodes = 0;
    bin_index_nodes.max_nodes = 0;
    bin_index_nodes.nodes = 0;

    struct GModule *module;
    struct Option *input_opt, *output_opt, *percent_opt, *type_opt, *filter_opt, *class_opt;
    struct Option *method_opt, *base_raster_opt;
    struct Option *zrange_opt, *zscale_opt;
    struct Option *irange_opt, *iscale_opt;
    struct Option *trim_opt, *pth_opt, *res_opt;
    struct Option *file_list_opt;
    struct Flag *print_flag, *scan_flag, *shell_style, *over_flag, *extents_flag;
    struct Flag *intens_flag, *intens_import_flag;
    struct Flag *set_region_flag;
    struct Flag *base_rast_res_flag;
    struct Flag *only_valid_flag;

    /* LAS */
    LASReaderH LAS_reader;
    LASHeaderH LAS_header;
    LASSRSH LAS_srs;
    LASPointH LAS_point;
    int return_filter;

    const char *projstr;
    struct Cell_head cellhd, loc_wind;

    unsigned int n_filtered;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("import"));
    G_add_keyword(_("LIDAR"));
    G_add_keyword(_("statistics"));
    G_add_keyword(_("conversion"));
    G_add_keyword(_("aggregation"));
    G_add_keyword(_("binning"));
    module->description =
	_("Creates a raster map from LAS LiDAR points using univariate statistics.");

    input_opt = G_define_standard_option(G_OPT_F_BIN_INPUT);
    input_opt->required = NO;
    input_opt->label = _("LAS input file");
    input_opt->description = _("LiDAR input files in LAS format (*.las or *.laz)");
    input_opt->guisection = _("Input");

    output_opt = G_define_standard_option(G_OPT_R_OUTPUT);
    output_opt->required = NO;
    output_opt->guisection = _("Output");

    file_list_opt = G_define_standard_option(G_OPT_F_INPUT);
    file_list_opt->key = "file";
    file_list_opt->label = _("File containing names of LAS input files");
    file_list_opt->description = _("LiDAR input files in LAS format (*.las or *.laz)");
    file_list_opt->required = NO;
    file_list_opt->guisection = _("Input");

    method_opt = G_define_option();
    method_opt->key = "method";
    method_opt->type = TYPE_STRING;
    method_opt->required = NO;
    method_opt->description = _("Statistic to use for raster values");
    method_opt->options =
	"n,min,max,range,sum,mean,stddev,variance,coeff_var,median,percentile,skewness,trimmean";
    method_opt->answer = "mean";
    method_opt->guisection = _("Statistic");
    G_asprintf((char **)&(method_opt->descriptions),
               "n;%s;"
               "min;%s;"
               "max;%s;"
               "range;%s;"
               "sum;%s;"
               "mean;%s;"
               "stddev;%s;"
               "variance;%s;"
               "coeff_var;%s;"
               "median;%s;"
               "percentile;%s;"
               "skewness;%s;"
               "trimmean;%s",
               _("Number of points in cell"),
               _("Minimum value of point values in cell"),
               _("Maximum value of point values in cell"),
               _("Range of point values in cell"),
               _("Sum of point values in cell"),
               _("Mean (average) value of point values in cell"),
               _("Standard deviation of point values in cell"),
               _("Variance of point values in cell"),
               _("Coefficient of variance of point values in cell"),
               _("Median value of point values in cell"),
               _("pth (nth) percentile of point values in cell"),
               _("Skewness of point values in cell"),
               _("Trimmed mean of point values in cell"));

    type_opt = G_define_standard_option(G_OPT_R_TYPE);
    type_opt->required = NO;
    type_opt->answer = "FCELL";

    base_raster_opt = G_define_standard_option(G_OPT_R_INPUT);
    base_raster_opt->key = "base_raster";
    base_raster_opt->required = NO;
    base_raster_opt->label =
        _("Subtract raster values from the Z coordinates");
    base_raster_opt->description =
        _("The scale for Z is applied beforehand, the range filter for"
          " Z afterwards");
    base_raster_opt->guisection = _("Transform");

    zrange_opt = G_define_option();
    zrange_opt->key = "zrange";
    zrange_opt->type = TYPE_DOUBLE;
    zrange_opt->required = NO;
    zrange_opt->key_desc = "min,max";
    zrange_opt->description = _("Filter range for Z data (min,max)");
    zrange_opt->guisection = _("Selection");

    zscale_opt = G_define_option();
    zscale_opt->key = "zscale";
    zscale_opt->type = TYPE_DOUBLE;
    zscale_opt->required = NO;
    zscale_opt->answer = "1.0";
    zscale_opt->description = _("Scale to apply to Z data");
    zscale_opt->guisection = _("Transform");

    irange_opt = G_define_option();
    irange_opt->key = "intensity_range";
    irange_opt->type = TYPE_DOUBLE;
    irange_opt->required = NO;
    irange_opt->key_desc = "min,max";
    irange_opt->description = _("Filter range for intensity values (min,max)");
    irange_opt->guisection = _("Selection");

    iscale_opt = G_define_option();
    iscale_opt->key = "intensity_scale";
    iscale_opt->type = TYPE_DOUBLE;
    iscale_opt->required = NO;
    iscale_opt->answer = "1.0";
    iscale_opt->description = _("Scale to apply to intensity values");
    iscale_opt->guisection = _("Transform");

    percent_opt = G_define_option();
    percent_opt->key = "percent";
    percent_opt->type = TYPE_INTEGER;
    percent_opt->required = NO;
    percent_opt->answer = "100";
    percent_opt->options = "1-100";
    percent_opt->description = _("Percent of map to keep in memory");

    /* I would prefer to call the following "percentile", but that has too
     * much namespace overlap with the "percent" option above */
    pth_opt = G_define_option();
    pth_opt->key = "pth";
    pth_opt->type = TYPE_INTEGER;
    pth_opt->required = NO;
    pth_opt->options = "1-100";
    pth_opt->description = _("pth percentile of the values");
    pth_opt->guisection = _("Statistic");

    trim_opt = G_define_option();
    trim_opt->key = "trim";
    trim_opt->type = TYPE_DOUBLE;
    trim_opt->required = NO;
    trim_opt->options = "0-50";
    trim_opt->label = _("Discard given percentage of the smallest and largest values");
    trim_opt->description =
	_("Discard <trim> percent of the smallest and <trim> percent of the largest observations");
    trim_opt->guisection = _("Statistic");

    res_opt = G_define_option();
    res_opt->key = "resolution";
    res_opt->type = TYPE_DOUBLE;
    res_opt->required = NO;
    res_opt->description =
	_("Output raster resolution");
    res_opt->guisection = _("Output");

    filter_opt = G_define_option();
    filter_opt->key = "return_filter";
    filter_opt->type = TYPE_STRING;
    filter_opt->required = NO;
    filter_opt->label = _("Only import points of selected return type");
    filter_opt->description = _("If not specified, all points are imported");
    filter_opt->options = "first,last,mid";
    filter_opt->guisection = _("Selection");

    class_opt = G_define_option();
    class_opt->key = "class_filter";
    class_opt->type = TYPE_INTEGER;
    class_opt->multiple = YES;
    class_opt->required = NO;
    class_opt->label = _("Only import points of selected class(es)");
    class_opt->description = _("Input is comma separated integers. "
                               "If not specified, all points are imported.");
    class_opt->guisection = _("Selection");

    print_flag = G_define_flag();
    print_flag->key = 'p';
    print_flag->description =
	_("Print LAS file info and exit");

    extents_flag = G_define_flag();
    extents_flag->key = 'e';
    extents_flag->label =
        _("Use the extent of the input for the raster extent");
    extents_flag->description =
        _("Set internally computational region extents based on the"
          " point cloud");
    extents_flag->guisection = _("Output");

    set_region_flag = G_define_flag();
    set_region_flag->key = 'n';
    set_region_flag->label =
        _("Set computation region to match the new raster map");
    set_region_flag->description =
        _("Set computation region to match the 2D extent and resolution"
          " of the newly created new raster map");
    set_region_flag->guisection = _("Output");

    over_flag = G_define_flag();
    over_flag->key = 'o';
    over_flag->label =
	_("Override projection check (use current location's projection)");
    over_flag->description =
	_("Assume that the dataset has same projection as the current location");

    scan_flag = G_define_flag();
    scan_flag->key = 's';
    scan_flag->description = _("Scan data file for extent then exit");

    shell_style = G_define_flag();
    shell_style->key = 'g';
    shell_style->description =
	_("In scan mode, print using shell script style");

    intens_flag = G_define_flag();
    intens_flag->key = 'i';
    intens_flag->label =
        _("Use intensity values rather than Z values");
    intens_flag->description =
        _("Uses intensity values everywhere as if they would be Z"
          " coordinates");

    intens_import_flag = G_define_flag();
    intens_import_flag->key = 'j';
    intens_import_flag->description =
        _("Use Z values for filtering, but intensity values for statistics");

    base_rast_res_flag = G_define_flag();
    base_rast_res_flag->key = 'd';
    base_rast_res_flag->label =
        _("Use base raster resolution instead of computational region");
    base_rast_res_flag->description =
        _("For getting values from base raster, use its actual"
          " resolution instead of computational region resolution");

    only_valid_flag = G_define_flag();
    only_valid_flag->key = 'v';
    only_valid_flag->label = _("Use only valid points");
    only_valid_flag->description =
        _("Points invalid according to APSRS LAS specification will be"
          " filtered out");
    only_valid_flag->guisection = _("Selection");

    G_option_required(input_opt, file_list_opt, NULL);
    G_option_exclusive(input_opt, file_list_opt, NULL);
    G_option_required(output_opt, print_flag, scan_flag, shell_style, NULL);
    G_option_exclusive(intens_flag, intens_import_flag, NULL);
    G_option_requires(base_rast_res_flag, base_raster_opt, NULL);

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

    int only_valid = FALSE;
    n_invalid = 0;
    if (only_valid_flag->answer)
        only_valid = TRUE;

    /* we could use rules but this gives more info and allows continuing */
    if (set_region_flag->answer && !(extents_flag->answer || res_opt->answer)) {
        G_warning(_("Flag %c makes sense only with %s option or -%c flag"),
                  set_region_flag->key, res_opt->key, extents_flag->key);
        /* avoid the call later on */
        set_region_flag->answer = '\0';
    }

    struct StringList infiles;

    if (file_list_opt->answer) {
        if (access(file_list_opt->answer, F_OK) != 0)
            G_fatal_error(_("File <%s> does not exist"), file_list_opt->answer);
        string_list_from_file(&infiles, file_list_opt->answer);
    }
    else {
        string_list_from_one_item(&infiles, input_opt->answer);
    }

    /* parse input values */
    outmap = output_opt->answer;

    if (shell_style->answer && !scan_flag->answer) {
	scan_flag->answer = 1; /* pointer not int, so set = shell_style->answer ? */
    }

    /* check zrange and extent relation */
    if (scan_flag->answer || extents_flag->answer) {
        if (zrange_opt->answer)
            G_warning(_("zrange will not be taken into account during scan"));
    }

    Rast_get_window(&region);
    /* G_get_window seems to be unreliable if the location has been changed */
    G_get_set_window(&loc_wind);        /* TODO: v.in.lidar uses G_get_default_window() */

    estimated_lines = 0;
    int i;
    for (i = 0; i < infiles.num_items; i++) {
        infile = infiles.items[i];
        /* don't if file not found */
        if (access(infile, F_OK) != 0)
            G_fatal_error(_("Input file <%s> does not exist"), infile);
        /* Open LAS file*/
        LAS_reader = LASReader_Create(infile);
        if (LAS_reader == NULL)
            G_fatal_error(_("Unable to open file <%s> as a LiDAR point cloud"),
                          infile);
        LAS_header = LASReader_GetHeader(LAS_reader);
        if  (LAS_header == NULL) {
            G_fatal_error(_("Unable to read LAS header of <%s>"), infile);
        }

        LAS_srs = LASHeader_GetSRS(LAS_header);

        /* print info or check projection if we are actually importing */
        if (print_flag->answer) {
            /* print filename when there is more than one file */
            if (infiles.num_items > 1)
                fprintf(stdout, "File: %s\n", infile);
            /* Print LAS header */
            print_lasinfo(LAS_header, LAS_srs);
        }
        else {
            /* report that we are checking more files */
            if (i == 1)
                G_message(_("First file's projection checked,"
                            " checking projection of the other files..."));
            /* Fetch input map projection in GRASS form. */
            projstr = LASSRS_GetWKT_CompoundOK(LAS_srs);
            /* we are printing the non-warning messages only for first file */
            projection_check_wkt(cellhd, loc_wind, projstr, over_flag->answer,
                                 shell_style->answer || i);
            /* if there is a problem in some other file, first OK message
             * is printed but than a warning, this is not ideal but hopefully
             * not so confusing when importing multiple files */
        }
        if (scan_flag->answer || extents_flag->answer) {
            /* we assign to the first one (i==0) but update for the rest */
            scan_bounds(LAS_reader, shell_style->answer, extents_flag->answer, i,
                        zscale, &region);
        }
        /* number of estimated point across all files */
        /* TODO: this should be ull which won't work with percent report */
        estimated_lines += LASHeader_GetPointRecordsCount(LAS_header);
        /* We are closing all again and we will be opening them later,
         * so we don't have to worry about limit for open files. */
        LASSRS_Destroy(LAS_srs);
        LASHeader_Destroy(LAS_header);
        LASReader_Destroy(LAS_reader);
    }
    /* if we are not importing, end */
    if (print_flag->answer || scan_flag->answer)
        exit(EXIT_SUCCESS);

    return_filter = LAS_ALL;
    if (filter_opt->answer) {
	if (strcmp(filter_opt->answer, "first") == 0)
	    return_filter = LAS_FIRST;
	else if (strcmp(filter_opt->answer, "last") == 0)
	    return_filter = LAS_LAST;
	else if (strcmp(filter_opt->answer, "mid") == 0)
	    return_filter = LAS_MID;
	else
	    G_fatal_error(_("Unknown filter option <%s>"), filter_opt->answer);
    }
    struct ReturnFilter return_filter_struct;
    return_filter_struct.filter = return_filter;
    struct ClassFilter class_filter;
    class_filter_create_from_strings(&class_filter, class_opt->answers);

    percent = atoi(percent_opt->answer);
    /* TODO: we already used zscale */
    /* TODO: we don't report intensity range */
    if (zscale_opt->answer)
        zscale = atof(zscale_opt->answer);
    if (iscale_opt->answer)
        iscale = atof(iscale_opt->answer);

    /* parse zrange */
    if (zrange_opt->answer != NULL) {
	if (zrange_opt->answers[0] == NULL)
	    G_fatal_error(_("Invalid zrange"));

	sscanf(zrange_opt->answers[0], "%lf", &zrange_min);
	sscanf(zrange_opt->answers[1], "%lf", &zrange_max);

	if (zrange_min > zrange_max) {
	    d_tmp = zrange_max;
	    zrange_max = zrange_min;
	    zrange_min = d_tmp;
	}
    }
    /* parse irange */
    if (irange_opt->answer != NULL) {
        if (irange_opt->answers[0] == NULL)
            G_fatal_error(_("Invalid %s"), irange_opt->key);

        sscanf(irange_opt->answers[0], "%lf", &irange_min);
        sscanf(irange_opt->answers[1], "%lf", &irange_max);

        if (irange_min > irange_max) {
            d_tmp = irange_max;
            irange_max = irange_min;
            irange_min = d_tmp;
        }
    }

    point_binning_set(&point_binning, method_opt->answer, pth_opt->answer,
                      trim_opt->answer, FALSE);

    base_array = NULL;

    if (strcmp("CELL", type_opt->answer) == 0)
	rtype = CELL_TYPE;
    else if (strcmp("DCELL", type_opt->answer) == 0)
	rtype = DCELL_TYPE;
    else
	rtype = FCELL_TYPE;

    if (point_binning.method == METHOD_N)
	rtype = CELL_TYPE;

    if (res_opt->answer) {
	/* align to resolution */
	res = atof(res_opt->answer);

	if (!G_scan_resolution(res_opt->answer, &res, region.proj))
	    G_fatal_error(_("Invalid input <%s=%s>"), res_opt->key, res_opt->answer);

	if (res <= 0)
	    G_fatal_error(_("Option '%s' must be > 0.0"), res_opt->key);
	
	region.ns_res = region.ew_res = res;

	region.north = ceil(region.north / res) * res;
	region.south = floor(region.south / res) * res;
	region.east = ceil(region.east / res) * res;
	region.west = floor(region.west / res) * res;

	G_adjust_Cell_head(&region, 0, 0);
    }
    else if (extents_flag->answer) {
	/* align to current region */
	Rast_align_window(&region, &loc_wind);
    }
    Rast_set_output_window(&region);

    rows = last_rows = region.rows;
    npasses = 1;
    if (percent < 100) {
	rows = (int)(region.rows * (percent / 100.0));
	npasses = region.rows / rows;
	last_rows = region.rows - npasses * rows;
	if (last_rows)
	    npasses++;
	else
	    last_rows = rows;

    }
    cols = region.cols;

    G_debug(2, "region.n=%f  region.s=%f  region.ns_res=%f", region.north,
	    region.south, region.ns_res);
    G_debug(2, "region.rows=%d  [box_rows=%d]  region.cols=%d", region.rows,
	    rows, region.cols);

    /* using row-based chunks (used for output) when input and output
     * region matches and using segment library when they don't */
    int use_segment = 0;
    int use_base_raster_res = 0;
    /* TODO: see if the input region extent is smaller than the raster
     * if yes, the we need to load the whole base raster if the -e
     * flag was defined (alternatively clip the regions) */
    if (base_rast_res_flag->answer)
        use_base_raster_res = 1;
    if (base_raster_opt->answer && (res_opt->answer || use_base_raster_res
                                    || extents_flag->answer))
        use_segment = 1;
    if (base_raster_opt->answer && !use_segment) {
        /* TODO: do we need to test existence first? mapset? */
        base_raster = Rast_open_old(base_raster_opt->answer, "");
        base_raster_data_type = Rast_get_map_type(base_raster);
        base_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(base_raster_data_type));
    }
    if (base_raster_opt->answer && use_segment) {
        if (use_base_raster_res) {
            /* read raster actual extent and resolution */
            Rast_get_cellhd(base_raster_opt->answer, "", &input_region);
            /* TODO: make it only as small as the output is or points are */
            Rast_set_input_window(&input_region);  /* we have split window */
        } else {
            Rast_get_input_window(&input_region);
        }
        rast_segment_open(&base_segment, base_raster_opt->answer, &base_raster_data_type);
    }

    if (!scan_flag->answer) {
        if (!check_rows_cols_fit_to_size_t(rows, cols))
		G_fatal_error(_("Unable to process the hole map at once. "
                        "Please set the '%s' option to some value lower than 100."),
				percent_opt->key);
        point_binning_memory_test(&point_binning, rows, cols, rtype);
	}

    /* open output map */
    out_fd = Rast_open_new(outmap, rtype);

    /* allocate memory for a single row of output data */
    raster_row = Rast_allocate_output_buf(rtype);

    G_message(_("Reading data ..."));

    count_total = line_total = 0;

    /* main binning loop(s) */
    for (pass = 1; pass <= npasses; pass++) {

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

	/* figure out segmentation */
	row0 = (pass - 1) * rows;
	if (pass == npasses) {
	    rows = last_rows;
	}

        if (base_array) {
            G_debug(2, "filling base raster array");
            for (row = 0; row < rows; row++) {
                Rast_get_row(base_raster, base_array + ((size_t) row * cols * Rast_cell_size(base_raster_data_type)), row, base_raster_data_type);
            }
        }

	G_debug(2, "pass=%d/%d  rows=%d", pass, npasses, rows);

    point_binning_allocate(&point_binning, rows, cols, rtype);

	line = 0;
	count = 0;
	counter = 0;
	G_percent_reset();

        /* loop of input files */
        for (i = 0; i < infiles.num_items; i++) {
            infile = infiles.items[i];
            /* we already know file is there, so just do basic checks */
            LAS_reader = LASReader_Create(infile);
            if (LAS_reader == NULL)
                G_fatal_error(_("Unable to open file <%s>"), infile);

            while ((LAS_point = LASReader_GetNextPoint(LAS_reader)) != NULL) {
                line++;
                counter++;

                if (counter == 100000) {        /* speed */
                    if (line < estimated_lines)
                        G_percent(line, estimated_lines, 3);
                    counter = 0;
                }

                /* We always count them and report because behavior
                 * changed in between 7.0 and 7.2 from undefined (but skipping
                 * invalid points) to filtering them out only when requested. */
                if (!LASPoint_IsValid(LAS_point)) {
                    n_invalid++;
                    if (only_valid)
                        continue;
                }

                x = LASPoint_GetX(LAS_point);
                y = LASPoint_GetY(LAS_point);
                if (intens_flag->answer)
                    /* use intensity as z here to allow all filters (and
                     * modifications) below to be applied for intensity */
                    z = LASPoint_GetIntensity(LAS_point);
                else
                    z = LASPoint_GetZ(LAS_point);

                int return_n = LASPoint_GetReturnNumber(LAS_point);
                int n_returns = LASPoint_GetNumberOfReturns(LAS_point);
                if (return_filter_is_out(&return_filter_struct, return_n, n_returns)) {
                    n_filtered++;
                    continue;
                }
                point_class = (int) LASPoint_GetClassification(LAS_point);
                if (class_filter_is_out(&class_filter, point_class))
                    continue;

                if (y <= region.south || y > region.north) {
                    continue;
                }
                if (x < region.west || x >= region.east) {
                    continue;
                }

                /* find the bin in the current array box */
		arr_row = (int)((region.north - y) / region.ns_res) - row0;
		if (arr_row < 0 || arr_row >= rows)
		    continue;
                arr_col = (int)((x - region.west) / region.ew_res);

                z = z * zscale;

                if (base_array) {
                    double base_z;
                    if (row_array_get_value_row_col(base_array, arr_row, arr_col,
                                                    cols, base_raster_data_type,
                                                    &base_z))
                        z -= base_z;
                    else
                        continue;
                }
                else if (use_segment) {
                    double base_z;
                    if (rast_segment_get_value_xy(&base_segment, &input_region,
                                                  base_raster_data_type, x, y,
                                                  &base_z))
                        z -= base_z;
                    else
                        continue;
                }

                if (zrange_opt->answer) {
                    if (z < zrange_min || z > zrange_max) {
                        continue;
                    }
                }

                if (intens_import_flag->answer || irange_opt->answer) {
                    intensity = LASPoint_GetIntensity(LAS_point);
                    intensity *= iscale;
                    if (irange_opt->answer) {
                        if (intensity < irange_min || intensity > irange_max) {
                            continue;
                        }
                    }
                    /* use intensity for statistics */
                    if (intens_import_flag->answer)
                        z = intensity;
                }

                count++;
                /*          G_debug(5, "x: %f, y: %f, z: %f", x, y, z); */

                update_value(&point_binning, &bin_index_nodes, cols,
                             arr_row, arr_col, rtype, x, y, z);
            }                        /* while !EOF of one input file */
            /* close input LAS file */
            LASReader_Destroy(LAS_reader);
        }           /* end of loop for all input files files */

	G_percent(1, 1, 1);	/* flush */
	G_debug(2, "pass %d finished, %lu coordinates in box", pass, count);
	count_total += count;
	line_total += line;

	/* calc stats and output */
	G_message(_("Writing to map ..."));
	for (row = 0; row < rows; row++) {
        /* potentially vector writing can be independent on the binning */
        write_values(&point_binning, &bin_index_nodes, raster_row, row,
            cols, rtype, NULL);
	    /* write out line of raster data */
        Rast_put_row(out_fd, raster_row, rtype);
	}

	/* free memory */
	point_binning_free(&point_binning, &bin_index_nodes);
    }				/* passes loop */
    if (base_array)
        Rast_close(base_raster);
    if (use_segment)
        Segment_close(&base_segment);

    G_percent(1, 1, 1);		/* flush */
    G_free(raster_row);

    /* close raster file & write history */
    Rast_close(out_fd);

    sprintf(title, "Raw X,Y,Z data binned into a raster grid by cell %s",
            method_opt->answer);
    Rast_put_cell_title(outmap, title);

    Rast_short_history(outmap, "raster", &history);
    Rast_command_history(&history);
    Rast_set_history(&history, HIST_DATSRC_1, infile);
    Rast_write_history(outmap, &history);

    /* set computation region to the new raster map */
    /* TODO: should be in the done message */
    if (set_region_flag->answer)
        G_put_window(&region);

    if (n_invalid && only_valid)
        G_message(_("%lu input points were invalid and filtered out"),
                  n_invalid);
    if (n_invalid && !only_valid)
        G_message(_("%lu input points were invalid, use -%c flag to filter"
                    " them out"), n_invalid, only_valid_flag->key);
    if (infiles.num_items > 1) {
        sprintf(buff, _("Raster map <%s> created."
                        " %lu points from %d files found in region."),
                outmap, count_total, infiles.num_items);
    }
    else {
        sprintf(buff, _("Raster map <%s> created."
                        " %lu points found in region."),
                outmap, count_total);
    }

    G_done_msg("%s", buff);
    G_debug(1, "Processed %lu points.", line_total);

    string_list_free(&infiles);

    exit(EXIT_SUCCESS);

}
Ejemplo n.º 4
0
int main(int argc, char *argv[])
{
    char *p;
    int method;
    int in_fd;
    int selection_fd;
    int out_fd;
    DCELL *result;
    char *selection;
    RASTER_MAP_TYPE map_type;
    int row, col;
    int readrow;
    int nrows, ncols;
    int n;
    int copycolr;
    int half;
    stat_func *newvalue;
    stat_func_w *newvalue_w;
    ifunc cat_names;
    double quantile;
    const void *closure;
    struct Colors colr;
    struct Cell_head cellhd;
    struct Cell_head window;
    struct History history;
    struct GModule *module;
    struct
    {
	struct Option *input, *output, *selection;
	struct Option *method, *size;
	struct Option *title;
	struct Option *weight;
	struct Option *gauss;
	struct Option *quantile;
    } parm;
    struct
    {
	struct Flag *align, *circle;
    } flag;

    DCELL *values;		/* list of neighborhood values */

    DCELL(*values_w)[2];	/* list of neighborhood values and weights */

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("algebra"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Makes each cell category value a "
	  "function of the category values assigned to the cells "
	  "around it, and stores new cell values in an output raster "
	  "map layer.");

    parm.input = G_define_standard_option(G_OPT_R_INPUT);

    parm.selection = G_define_standard_option(G_OPT_R_INPUT);
    parm.selection->key = "selection";
    parm.selection->required = NO;
    parm.selection->description = _("Name of an input raster map to select the cells which should be processed");

    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);

    parm.method = G_define_option();
    parm.method->key = "method";
    parm.method->type = TYPE_STRING;
    parm.method->required = NO;
    parm.method->answer = "average";
    p = G_malloc(1024);
    for (n = 0; menu[n].name; n++) {
	if (n)
	    strcat(p, ",");
	else
	    *p = 0;
	strcat(p, menu[n].name);
    }
    parm.method->options = p;
    parm.method->description = _("Neighborhood operation");
    parm.method->guisection = _("Neighborhood");

    parm.size = G_define_option();
    parm.size->key = "size";
    parm.size->type = TYPE_INTEGER;
    parm.size->required = NO;
    parm.size->description = _("Neighborhood size");
    parm.size->answer = "3";
    parm.size->guisection = _("Neighborhood");

    parm.title = G_define_option();
    parm.title->key = "title";
    parm.title->key_desc = "phrase";
    parm.title->type = TYPE_STRING;
    parm.title->required = NO;
    parm.title->description = _("Title of the output raster map");

    parm.weight = G_define_standard_option(G_OPT_F_INPUT);
    parm.weight->key = "weight";
    parm.weight->required = NO;
    parm.weight->description = _("Text file containing weights");

    parm.gauss = G_define_option();
    parm.gauss->key = "gauss";
    parm.gauss->type = TYPE_DOUBLE;
    parm.gauss->required = NO;
    parm.gauss->description = _("Sigma (in cells) for Gaussian filter");

    parm.quantile = G_define_option();
    parm.quantile->key = "quantile";
    parm.quantile->type = TYPE_DOUBLE;
    parm.quantile->required = NO;
    parm.quantile->description = _("Quantile to calculate for method=quantile");
    parm.quantile->options = "0.0-1.0";
    parm.quantile->answer = "0.5";

    flag.align = G_define_flag();
    flag.align->key = 'a';
    flag.align->description = _("Do not align output with the input");

    flag.circle = G_define_flag();
    flag.circle->key = 'c';
    flag.circle->description = _("Use circular neighborhood");
    flag.circle->guisection = _("Neighborhood");

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

    sscanf(parm.size->answer, "%d", &ncb.nsize);
    if (ncb.nsize <= 0)
	G_fatal_error(_("Neighborhood size must be positive"));
    if (ncb.nsize % 2 == 0)
	G_fatal_error(_("Neighborhood size must be odd"));
    ncb.dist = ncb.nsize / 2;

    if (parm.weight->answer && flag.circle->answer)
	G_fatal_error(_("weight= and -c are mutually exclusive"));

    if (parm.weight->answer && parm.gauss->answer)
	G_fatal_error(_("weight= and gauss= are mutually exclusive"));

    ncb.oldcell = parm.input->answer;
    ncb.newcell = parm.output->answer;

    if (!flag.align->answer) {
	Rast_get_cellhd(ncb.oldcell, "", &cellhd);
	G_get_window(&window);
	Rast_align_window(&window, &cellhd);
	Rast_set_window(&window);
    }

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

    /* open raster maps */
    in_fd = Rast_open_old(ncb.oldcell, "");
    map_type = Rast_get_map_type(in_fd);

    /* get the method */
    for (method = 0; (p = menu[method].name); method++)
	if ((strcmp(p, parm.method->answer) == 0))
	    break;
    if (!p) {
	G_warning(_("<%s=%s> unknown %s"),
		  parm.method->key, parm.method->answer, parm.method->key);
	G_usage();
	exit(EXIT_FAILURE);
    }

    if (menu[method].method == c_quant) {
	quantile = atoi(parm.quantile->answer);
	closure = &quantile;
    }

    half = (map_type == CELL_TYPE) ? menu[method].half : 0;

    /* establish the newvalue routine */
    newvalue = menu[method].method;
    newvalue_w = menu[method].method_w;

    /* copy color table? */
    copycolr = menu[method].copycolr;
    if (copycolr) {
	G_suppress_warnings(1);
	copycolr =
	    (Rast_read_colors(ncb.oldcell, "", &colr) > 0);
	G_suppress_warnings(0);
    }

    /* read the weights */
    if (parm.weight->answer) {
	read_weights(parm.weight->answer);
	if (!newvalue_w)
	    weights_mask();
    }
    else if (parm.gauss->answer) {
	if (!newvalue_w)
	    G_fatal_error(_("Method %s not compatible with Gaussian filter"), parm.method->answer);
	gaussian_weights(atof(parm.gauss->answer));
    }
    else
	newvalue_w = NULL;

    /* allocate the cell buffers */
    allocate_bufs();
    result = Rast_allocate_d_buf();

    /* get title, initialize the category and stat info */
    if (parm.title->answer)
	strcpy(ncb.title, parm.title->answer);
    else
	sprintf(ncb.title, "%dx%d neighborhood: %s of %s",
		ncb.nsize, ncb.nsize, menu[method].name, ncb.oldcell);


    /* initialize the cell bufs with 'dist' rows of the old cellfile */

    readrow = 0;
    for (row = 0; row < ncb.dist; row++)
	readcell(in_fd, readrow++, nrows, ncols);

    /* open the selection raster map */
    if (parm.selection->answer) {
	G_message(_("Opening selection map <%s>"), parm.selection->answer);
	selection_fd = Rast_open_old(parm.selection->answer, "");
        selection = Rast_allocate_null_buf();
    } else {
        selection_fd = -1;
        selection = NULL;
    }

    /*open the new raster map */
    out_fd = Rast_open_new(ncb.newcell, map_type);

    if (flag.circle->answer)
	circle_mask();

    if (newvalue_w)
	values_w =
	    (DCELL(*)[2]) G_malloc(ncb.nsize * ncb.nsize * 2 * sizeof(DCELL));
    else
	values = (DCELL *) G_malloc(ncb.nsize * ncb.nsize * sizeof(DCELL));

    for (row = 0; row < nrows; row++) {
	G_percent(row, nrows, 2);
	readcell(in_fd, readrow++, nrows, ncols);

	if (selection)
            Rast_get_null_value_row(selection_fd, selection, row);

	for (col = 0; col < ncols; col++) {
	    DCELL *rp = &result[col];

            if (selection && selection[col]) {
		*rp = ncb.buf[ncb.dist][col];
		continue;
	    }

	    if (newvalue_w)
		n = gather_w(values_w, col);
	    else
		n = gather(values, col);

	    if (n < 0)
		Rast_set_d_null_value(rp, 1);
	    else {
		if (newvalue_w)
		    newvalue_w(rp, values_w, n, closure);
		else
		    newvalue(rp, values, n, closure);

		if (half && !Rast_is_d_null_value(rp))
		    *rp += 0.5;
	    }
	}

	Rast_put_d_row(out_fd, result);
    }
    G_percent(row, nrows, 2);

    Rast_close(out_fd);
    Rast_close(in_fd);

    if (selection)
        Rast_close(selection_fd);

    /* put out category info */
    null_cats();
    if ((cat_names = menu[method].cat_names))
	cat_names();

    Rast_write_cats(ncb.newcell, &ncb.cats);

    if (copycolr)
	Rast_write_colors(ncb.newcell, G_mapset(), &colr);

    Rast_short_history(ncb.newcell, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(ncb.newcell, &history);


    exit(EXIT_SUCCESS);
}
Ejemplo n.º 5
0
Archivo: main.c Proyecto: caomw/grass
int main(int argc, char *argv[])
{
    int i;
    double x;
    struct Cell_head cellhd, window;
    const char *value;
    const char *name;

    struct GModule *module;
    struct
    {
	struct Flag *dflt, *cur;
    } flag;
    struct
    {
	struct Option
	    *map,
	    *north, *south, *east, *west,
	    *raster, *vect, *region, *align;
    } parm;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("metadata"));
    module->description =
	_("Sets the boundary definitions for a raster map.");

    /* flags */

    flag.cur = G_define_flag();
    flag.cur->key = 'c';
    flag.cur->description = _("Set from current region");
    flag.cur->guisection = _("Existing");

    flag.dflt = G_define_flag();
    flag.dflt->key = 'd';
    flag.dflt->description = _("Set from default region");
    flag.dflt->guisection = _("Existing");

    /* parameters */

    parm.map = G_define_standard_option(G_OPT_R_MAP);
    parm.map->description = _("Name of raster map to change");

    parm.region = G_define_option();
    parm.region->key = "region";
    parm.region->key_desc = "name";
    parm.region->required = NO;
    parm.region->multiple = NO;
    parm.region->type = TYPE_STRING;
    parm.region->description = _("Set region from named region");
    parm.region->gisprompt = "old,windows,region";
    parm.region->guisection = _("Existing");
    
    parm.raster = G_define_standard_option(G_OPT_R_MAP);
    parm.raster->key = "raster";
    parm.raster->required = NO;
    parm.raster->multiple = NO;
    parm.raster->description = _("Set region to match this raster map");
    parm.raster->guisection = _("Existing");

    parm.vect = G_define_standard_option(G_OPT_V_MAP);
    parm.vect->key = "vector";
    parm.vect->required = NO;
    parm.vect->multiple = NO;
    parm.vect->description = _("Set region to match this vector map");
    parm.vect->guisection = _("Existing");

    parm.north = G_define_option();
    parm.north->key = "n";
    parm.north->key_desc = "value";
    parm.north->required = NO;
    parm.north->multiple = NO;
    parm.north->type = TYPE_STRING;
    parm.north->description = _("Value for the northern edge");
    parm.north->guisection = _("Bounds");

    parm.south = G_define_option();
    parm.south->key = "s";
    parm.south->key_desc = "value";
    parm.south->required = NO;
    parm.south->multiple = NO;
    parm.south->type = TYPE_STRING;
    parm.south->description = _("Value for the southern edge");
    parm.south->guisection = _("Bounds");

    parm.east = G_define_option();
    parm.east->key = "e";
    parm.east->key_desc = "value";
    parm.east->required = NO;
    parm.east->multiple = NO;
    parm.east->type = TYPE_STRING;
    parm.east->description = _("Value for the eastern edge");
    parm.east->guisection = _("Bounds");

    parm.west = G_define_option();
    parm.west->key = "w";
    parm.west->key_desc = "value";
    parm.west->required = NO;
    parm.west->multiple = NO;
    parm.west->type = TYPE_STRING;
    parm.west->description = _("Value for the western edge");
    parm.west->guisection = _("Bounds");
    
    parm.align = G_define_standard_option(G_OPT_R_MAP);
    parm.align->key = "align";
    parm.align->required = NO;
    parm.align->multiple = NO;
    parm.align->description = _("Raster map to align to");
    parm.align->guisection = _("Existing");

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

    G_get_window(&window);

    name = parm.map->answer;

    Rast_get_cellhd(name, G_mapset(), &cellhd);

    window = cellhd;

    if (flag.dflt->answer)
	G_get_default_window(&window);

    if (flag.cur->answer)
	G_get_window(&window);

    if ((name = parm.region->answer))	/* region= */
	G__get_window(&window, "windows", name, "");

    if ((name = parm.raster->answer)) {	/* raster= */
	Rast_get_cellhd(name, "", &window);
    }

    if ((name = parm.vect->answer)) {	/* vect= */
	struct Map_info Map;
	struct bound_box box;

	Vect_set_open_level(1);
	if (Vect_open_old(&Map, name, "") != 1)
	    G_fatal_error(_("Unable to open vector map <%s>"), name);

	Vect_get_map_box(&Map, &box);
	window.north = box.N;
	window.south = box.S;
	window.west = box.W;
	window.east = box.E;

	Rast_align_window(&window, &cellhd);

	Vect_close(&Map);
    }

    if ((value = parm.north->answer)) {	/* n= */
	if ((i = nsew(value, "n+", "n-", "s+"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.north);
	    switch (i) {
	    case 1:
		window.north += x;
		break;
	    case 2:
		window.north -= x;
		break;
	    case 3:
		window.north = window.south + x;
		break;
	    }
	}
	else if (G_scan_northing(value, &x, window.proj))
	    window.north = x;
	else
	    die(parm.north);
    }

    if ((value = parm.south->answer)) {	/* s= */
	if ((i = nsew(value, "s+", "s-", "n-"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.south);
	    switch (i) {
	    case 1:
		window.south += x;
		break;
	    case 2:
		window.south -= x;
		break;
	    case 3:
		window.south = window.north - x;
		break;
	    }
	}
	else if (G_scan_northing(value, &x, window.proj))
	    window.south = x;
	else
	    die(parm.south);
    }

    if ((value = parm.east->answer)) {	/* e= */
	if ((i = nsew(value, "e+", "e-", "w+"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.east);
	    switch (i) {
	    case 1:
		window.east += x;
		break;
	    case 2:
		window.east -= x;
		break;
	    case 3:
		window.east = window.west + x;
		break;
	    }
	}
	else if (G_scan_easting(value, &x, window.proj))
	    window.east = x;
	else
	    die(parm.east);
    }

    if ((value = parm.west->answer)) {	/* w= */
	if ((i = nsew(value, "w+", "w-", "e-"))) {
	    if (!G_scan_resolution(value + 2, &x, window.proj))
		die(parm.west);
	    switch (i) {
	    case 1:
		window.west += x;
		break;
	    case 2:
		window.west -= x;
		break;
	    case 3:
		window.west = window.east - x;
		break;
	    }
	}
	else if (G_scan_easting(value, &x, window.proj))
	    window.west = x;
	else
	    die(parm.west);
    }

    if ((name = parm.align->answer)) {	/* align= */
	struct Cell_head temp_window;

	Rast_get_cellhd(name, "", &temp_window);

	Rast_align_window(&window, &temp_window);
    }

    window.rows = cellhd.rows;
    window.cols = cellhd.cols;

    G_adjust_Cell_head(&window, 1, 1);

    cellhd.north = window.north;
    cellhd.south = window.south;
    cellhd.east = window.east;
    cellhd.west = window.west;

    Rast_put_cellhd(parm.map->answer, &cellhd);

    G_done_msg(" ");

    return 0;
}