int main() { LASHeaderH header = NULL; LASWriterH writer = NULL; LASReaderH reader = NULL; LASError err; // Limitation about seeking past 4GB output size. At 20 bytes / record, we // can successfully write 204 million records, but not 205. const unsigned long nMillionPoints = 205; const unsigned long NPOINTS = 1024*1024*nMillionPoints ; const char * OutputName = "Issue147.las"; // Write a LAS file and after the points are in, update the header. header = LASHeader_Create(); writer = LASWriter_Create(OutputName, header, LAS_MODE_WRITE); for (unsigned long i = 0; i < NPOINTS; i++) { double percentDone = ((double)i)/NPOINTS * 100.0; if (i % 1000 == 0) printf("\b\b\b\b\b\b\b%6.2f%%", percentDone); LASPointH pt = LASPoint_Create(); err = LASPoint_SetX(pt, 0); if (err) printf ("For point %lu, failed to set point value X\n", i); err = LASPoint_SetY(pt, 0); if (err) printf ("For point %lu, failed to set point value Y\n", i); err = LASPoint_SetZ(pt, 0); if (err) printf ("For point %lu, failed to set point value Z\n", i); err = LASWriter_WritePoint(writer, pt); if (err) printf ("For point %lu, failed to WritePoint\n", i); LASPoint_Destroy(pt); } err = LASHeader_SetPointRecordsCount(header, NPOINTS); if (err) dumperror ("Failed to LASHeader_SetPointRecordsCount\n"); err = LASWriter_WriteHeader(writer, header); if (err) dumperror ("Failed to LASWriter_WriteHeader"); LASWriter_Destroy(writer); LASHeader_Destroy(header); // Read the file we just wrote and check the header data. reader = LASReader_Create(OutputName); header = LASReader_GetHeader(reader); unsigned long npoints = LASHeader_GetPointRecordsCount(header); printf ("\n\nWrote %lu, Read %lu (testing %lu Million (1024 x 1024) Points)\n", NPOINTS, npoints, nMillionPoints); }
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int verbose = FALSE, got_R = FALSE, scanC = FALSE, scanD = FALSE, get_BB_only = FALSE; int i, argc = 0, n_arg_no_char = 0, classif = 0, intens = 0, nRet = 0, srcID = 0; unsigned int nPoints; char **argv, *fname = NULL, *parse_string = "xyz"; double *bbox, west, east, south, north, z_min = -1001, z_max, angle = 0; LASReaderH reader = NULL; LASHeaderH header = NULL; LASPointH p = NULL; if (nrhs == 0) { mexPrintf ("usage: [xyz, bbox] = lasreader_mex ('filename', ['-A<ang>'], ['-C<class>'], ['-D<id>']\n"); mexPrintf (" [-I<intens>]', ['-N<return>'], ['-R<x_min/x_max/y_min/y_max[/z_min/z_max]>']);\n"); mexPrintf (" OR\n"); mexPrintf (" [class, bbox] = lasreader_mex ('filename', '-S'),\n\n"); mexPrintf (" OR\n"); mexPrintf (" [IDs, bbox] = lasreader_mex ('filename', '-D'),\n\n"); mexPrintf (" OR\n"); mexPrintf (" bbox = lasreader_mex ('filename', '-B'),\n\n"); mexPrintf ("First case usage:\n"); mexPrintf ("where xyz is 3xN array with the XYZ point coordinates:\n"); mexPrintf ("and bbox is a 1x6 vector with [xmin xmax ymin ymax zmin zmax]\n"); mexPrintf (" -A<ang> Clip out points with scan angle > ang\n"); mexPrintf (" -C<class> Retain only points with classification = class\n"); mexPrintf (" -D<id> Retain only points with Source IDs = id (DO NOT CONFUSE WITH -D)\n"); mexPrintf (" -D Scan file for a list of Source IDs (see below) (DO NOT CONFUSE WITH -D<id>).\n"); mexPrintf (" -I<intens> Clip out points with intensity < intens\n"); mexPrintf (" -N<return> Select first return (-N1) or last return (-N10)\n"); mexPrintf (" -R<x_min/x_max/y_min/y_max> - Clip to bounding box.\n"); mexPrintf (" Optionaly add z_min/z_max to make a 3D bounding box.\n\n"); mexPrintf (" -S Scan file for a list of Classifications (see below).\n"); mexPrintf (" -V Prints header contents info on ML shell.\n"); mexPrintf ("Second/Third cases:\n"); mexPrintf ("class|ID is a 1xN vector with a list of different classificatins|IDs\n"); mexPrintf ("present in file. No other data (except optional BBox) is return here.\n"); mexPrintf ("Fourth case:\n"); mexPrintf ("\tReturns only the bonding box 1x6 vector.\n"); return; } if (!mxIsChar(prhs[0])) mexErrMsgTxt ("First arg must contain the filename string.\n"); if (nlhs != 1 && get_BB_only) mexErrMsgTxt ("-B option implies one output only.\n"); fname = (char *) mxArrayToString (prhs[0]); /* Load the file name into a char string */ if (nrhs > 1) { argc = nrhs; for (i = 1; i < nrhs; i++) { /* Check input to find how many arguments are of type char */ if(!mxIsChar(prhs[i])) { argc--; n_arg_no_char++; /* Number of arguments that have a type other than char */ } } argc++; /* to account for the program's name to be inserted in argv[0] */ /* get the length of the input string */ argv = (char **)mxCalloc(argc, sizeof(char *)); argv[0] = "LASreader"; for (i = 1; i < argc; i++) argv[i] = (char *)mxArrayToString(prhs[i+n_arg_no_char-1]); } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'A': angle = atof(&argv[i][2]); break; case 'B': get_BB_only = TRUE; break; case 'C': classif = atoi(&argv[i][2]); break; case 'D': if (argv[i][2]) srcID = atoi(&argv[i][2]); else scanD = TRUE; break; case 'I': intens = atoi(&argv[i][2]); break; case 'N': nRet = atoi(&argv[i][2]); break; case 'R': if (decode_R (argv[i], &west, &east, &south, &north, &z_min, &z_max)) mexErrMsgTxt("Error decoding -R option!"); got_R = TRUE; break; case 'S': scanC = TRUE; break; case 'V': verbose = TRUE; break; } } } reader = LASReader_Create(fname); if (!reader) mexErrMsgTxt("LASREADER Error! Unable to read file!"); header = LASReader_GetHeader(reader); if (!header) mexErrMsgTxt("LASREADER: Unable to fetch header for file"); if (get_BB_only && (scanC || scanD) ) mexPrintf("LASREADER WARNING: option -B takes precedence over -C or -D\n"); else if (scanC && scanD) mexPrintf("LASREADER WARNING: option -C takes precedence over -D\n"); if (get_BB_only) { plhs[0] = mxCreateDoubleMatrix(1, 6, mxREAL); bbox = mxGetPr(plhs[0]); bbox[0] = LASHeader_GetMinX(header); bbox[1] = LASHeader_GetMaxX(header); bbox[2] = LASHeader_GetMinY(header); bbox[3] = LASHeader_GetMaxY(header); bbox[4] = LASHeader_GetMinZ(header); bbox[5] = LASHeader_GetMaxZ(header); return; } if (verbose) print_header(header, FALSE); if (!(scanC || scanD)) { if ((got_R + nRet + intens + classif + angle + srcID) == 0) plain_xyz(plhs, reader, header); else conditional_xyz(plhs, reader, header, angle, classif, intens, nRet, srcID, got_R, west, east, south, north, z_min, z_max); } else if (scanC) /* Scan file for a list of different classifications */ get_classification_list ( plhs, reader); else if (scanD) /* Scan file for a list of different Source IDs */ get_ID_list ( plhs, reader); if (nlhs == 2) { plhs[1] = mxCreateDoubleMatrix(1, 6, mxREAL); bbox = mxGetPr(plhs[1]); bbox[0] = LASHeader_GetMinX(header); bbox[1] = LASHeader_GetMaxX(header); bbox[2] = LASHeader_GetMinY(header); bbox[3] = LASHeader_GetMaxY(header); bbox[4] = LASHeader_GetMinZ(header); bbox[5] = LASHeader_GetMaxZ(header); } LASReader_Destroy(reader); LASHeader_Destroy(header); return; }
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(®ion); /* 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, ®ion); } /* 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(®ion, 0, 0); } else if (extents_flag->answer) { /* align to current region */ Rast_align_window(®ion, &loc_wind); } Rast_set_output_window(®ion); 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(®ion); 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); }
int main (int argc, char **argv) { Las2GhtConfig config; Las2GhtState state; GhtTreePtr tree; int num_points; /* Set up to use the GHT system memory management / logging */ ght_init(); /* We can't do anything if we don't have GDAL/GeoTIFF support in libLAS */ if ( ! (LAS_IsGDALEnabled() && LAS_IsLibGeoTIFFEnabled()) ) { ght_error("%s: requires LibLAS built with GDAL and GeoTIFF support", EXENAME); return 1; } /* Ensure state is clean */ memset(&state, 0, sizeof(Las2GhtState)); /* If no options are specified, display l2g_usage */ if (argc <= 1) { l2g_usage(); return 1; } /* Parse command line options and set configuration */ if ( ! l2g_getopts(argc, argv, &config) ) { l2g_usage(); return 1; } /* Hard code resolution for now */ config.resolution = GHT_MAX_HASH_LENGTH; config.maxpoints = 2000000; /* Temporary info printout */ l2g_config_printf(&config); /* Input file exists? */ if ( ! l2g_fexists(config.lasfile) ) { ght_error("%s: LAS file '%s' does not exist\n", EXENAME, config.lasfile); return 1; } /* Output file is writeable? */ if ( ! l2g_writable(config.ghtfile) ) { ght_error("%s: GHT file '%s' is not writable\n", EXENAME, config.ghtfile); return 1; } /* Can we open the LAS file? */ state.reader = LASReader_Create(config.lasfile); if ( ! state.reader ) { ght_error("%s: unable to open LAS file '%s'\n", EXENAME, config.lasfile); return 1; } ght_info("Opened LAS file '%s' for reading", config.lasfile); /* Get the header */ state.header = LASReader_GetHeader(state.reader); if ( ! state.header) { l2g_state_free(&state); ght_error("%s: unable to read LAS header in '%s'\n", EXENAME, config.lasfile); return 1; } /* Schema is needed to create nodes/attributes */ if ( GHT_OK != l2g_build_schema(&config, &state) ) { l2g_state_free(&state); ght_error("%s: unable to build schema!", EXENAME); return 1; } /* Project info is needed to get points into lat/lon space */ if ( GHT_OK != l2g_read_projection(&config, &state) ) { l2g_state_free(&state); ght_error("%s: unable to build projection information", EXENAME); return 1; } // char *xmlstr; // size_t xmlsize; // ght_schema_to_xml_str(schema, &xmlstr, &xmlsize); // printf("\n%s\n\n", xmlstr); /* Break the problem into chunks. We might get a really really */ /* big LAS file, and we don't want to blow out memory, so we need to */ /* do this a few million records at a file */ do { num_points = l2g_build_tree(&config, &state, &tree); if ( num_points ) { GhtErr err; ght_tree_compact_attributes(tree); err = l2g_save_tree(&config, &state, tree); ght_tree_free(tree); if ( err != GHT_OK ) return 1; } } while ( num_points > 0 ); l2g_state_free(&state); l2g_config_free(&config); ght_info("conversion complete"); return 0; }
void* readFile(void *arg) { struct readThreadArgs *rTA = (struct readThreadArgs*) arg; LASReaderH reader = NULL; LASHeaderH header = NULL; LASPointH p = NULL; unsigned int index = 0; int read_index = 0; char *file_name_in = NULL; int i, j; while(1) { file_name_in = NULL; /*Get next file to read*/ MT_set_lock(&dataLock); file_name_in = files_name_in[files_in_index]; if (file_name_in == NULL) { MT_unset_lock(&dataLock); return NULL; } read_index = (files_in_index % rTA->num_read_threads); files_in_index++; struct writeT *dataWriteTT = (struct writeT*) malloc(sizeof(struct writeT)*rTA->num_of_entries); /*Lets read the data*/ reader = LASReader_Create(file_name_in); if (!reader) { LASError_Print("Unable to read file"); MT_unset_lock(&dataLock); exit(1); } MT_unset_lock(&dataLock); header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Unable to fetch header for file"); exit(1); } if (verbose) { print_header(stderr, header, file_name_in); } /*Allocate arrays for the columns*/ long num_points = LASHeader_GetPointRecordsCount(header); for (i = 0; i < rTA->num_of_entries; i++) { dataWriteTT[i].num_points = num_points; dataWriteTT[i].values = malloc(entriesType[i]*num_points); dataWriteTT[i].type = entriesType[i]; } /*Changes for Oscar's new Morton code function*/ //unsigned int factorX = (unsigned int) (LASHeader_GetOffsetX(header) / LASHeader_GetScaleX(header)); //unsigned int factorY = (unsigned int) (LASHeader_GetOffsetY(header) / LASHeader_GetScaleY(header)); /*Compute factors to add to X and Y and cehck sanity of generated codes*/ double file_scale_x = LASHeader_GetScaleX(header); double file_scale_y = LASHeader_GetScaleY(header); double file_scale_z = LASHeader_GetScaleZ(header); //printf("The scales are x:%lf y:%lf z:%lf\n", file_scale_x, file_scale_y, file_scale_z); /* scaled offsets to add for the morton encoding */ int64_t factorX = ((int64_t) (LASHeader_GetOffsetX(header) / file_scale_x)) - rTA->global_offset_x; int64_t factorY = ((int64_t) (LASHeader_GetOffsetY(header) / file_scale_y)) - rTA->global_offset_y; if (rTA->check) { // Check specified scales are like in the LAS file if (fabs(rTA->scale_x - file_scale_x) > TOLERANCE){ fprintf(stderr, "ERROR: x scale in input file (%lf) does not match specified x scale (%lf)\n",file_scale_x, rTA->scale_x); exit(1); } if (fabs(rTA->scale_y - file_scale_y) > TOLERANCE){ fprintf(stderr, "ERROR: y scale in input file (%lf) does not match specified y scale (%lf)\n",file_scale_y, rTA->scale_y); exit(1); } /* Check that the extent of the file (taking into account the global offset) * is within 0,2^31 */ double check_min_x = 1.0 + LASHeader_GetMinX(header) - (((double) rTA->global_offset_x) * rTA->scale_x); if (check_min_x < TOLERANCE) { fprintf(stderr, "ERROR: Specied X global offset is too large. (MinX - (GlobalX*ScaleX)) < 0\n"); exit(1); } double check_min_y = 1.0 + LASHeader_GetMinY(header) - (((double) rTA->global_offset_y) * rTA->scale_y); if (check_min_y < TOLERANCE) { fprintf(stderr, "ERROR: Specied Y global offset is too large. (MinY - (GlobalY*ScaleY)) < 0\n"); exit(1); } double check_max_x = LASHeader_GetMaxX(header) - (((double) rTA->global_offset_x) * rTA->scale_x); if (check_max_x > (MAX_INT_31 * rTA->scale_x)) { fprintf(stderr, "ERROR: Specied X global offset is too small. (MaxX - (GlobalX*ScaleX)) > (2^31)*ScaleX\n"); exit(1); } double check_max_y = LASHeader_GetMaxY(header) - (((double) rTA->global_offset_y) * rTA->scale_y); if (check_max_y > (MAX_INT_31 * rTA->scale_y)) { fprintf(stderr, "ERROR: Specied Y global offset is too small. (MaxY - (GlobalY*ScaleY)) > (2^31)*ScaleY\n"); exit(1); } } p = LASReader_GetNextPoint(reader); index = 0; while (p) { if (skip_invalid && !LASPoint_IsValid(p)) { if (verbose) { LASError_Print("Skipping writing invalid point..."); } p = LASReader_GetNextPoint(reader); index -=1; continue; } LASColorH color = NULL; for (j = 0; j < rTA->num_of_entries; j++) { uint64_t res; switch (entries[j]) { case ENTRY_x: case ENTRY_y: case ENTRY_z: ((double*) dataWriteTT[j].values)[index] = entriesFunc[j](p); //printf(" Point is:%lf\n", ((double*) dataWriteTT[j].values)[index]); break; case ENTRY_X: ((int*) dataWriteTT[j].values)[index] = entriesFunc[j](p) / file_scale_x; break; case ENTRY_Y: ((int*) dataWriteTT[j].values)[index] = entriesFunc[j](p) / file_scale_y; break; case ENTRY_Z: ((int*) dataWriteTT[j].values)[index] = entriesFunc[j](p) / file_scale_z; break; case ENTRY_k: entriesFunc[j](&res, p, factorX, factorY); ((int64_t*)dataWriteTT[j].values)[index] = res; break; case ENTRY_R: case ENTRY_G: case ENTRY_B: color = (color == NULL) ? LASPoint_GetColor(p) : color; dataWriteTT[j].values[index] = (double) entriesFunc[j](color); break; case ENTRY_M: dataWriteTT[j].values[index] = index; break; default: LASError_Print("las2col:readFile: Invalid Entry."); } } if (color != NULL) LASColor_Destroy(color); p = LASReader_GetNextPoint(reader); index +=1; } if (verbose) printf("Num of points:%d %ld for file:%s \n", index, num_points, file_name_in); /*Give the data to the writer threads*/ MT_set_lock(&dataLock); LASHeader_Destroy(header); header = NULL; LASReader_Destroy(reader); reader = NULL; /*TODO: make sure you are not overtaking other reading threads*/ while (data[read_index] != NULL) { MT_cond_wait(&readCond, &dataLock); } data[read_index] = dataWriteTT; /*Wake up the main*/ pthread_cond_broadcast(&mainCond); MT_unset_lock(&dataLock); } return NULL; }
int main(int argc, char *argv[]) { int i = 0; char* file_name = NULL; LASReaderH reader = NULL; LASHeaderH header = NULL; LASWriterH writer = NULL; int check_points = FALSE; int repair_header = FALSE; int change_header = FALSE; int repair_bounding_box = FALSE; int use_stdin = FALSE; int update_return_counts = FALSE; int skip_vlr = FALSE; int wkt = FALSE; char *system_identifier = NULL; char *generating_software = NULL; unsigned char file_creation_day = 0; unsigned char file_creation_year = 0; int err = 0; LASPointSummary* summary = NULL; for (i = 1; i < argc; i++) { if (strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--version") == 0) { char* ver = LAS_GetFullVersion(); fprintf(stderr,"%s", ver); LASString_Free(ver); exit(0); } else if (strcmp(argv[i],"-h") == 0 || strcmp(argv[i],"--help") == 0) { usage(); exit(0); } else if (strcmp(argv[i],"--input") == 0 || strcmp(argv[i],"-input") == 0 || strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"-in") == 0) { i++; file_name = argv[i]; } else if (strcmp(argv[i], "--points") == 0 || strcmp(argv[i], "--check") == 0 || strcmp(argv[i], "--check_points") == 0 || strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-points") == 0 || strcmp(argv[i], "-check") == 0 || strcmp(argv[i], "-check_points") == 0) { check_points = TRUE; } else if (strcmp(argv[i], "--nocheck") == 0 || strcmp(argv[i], "-nocheck") == 0) { check_points = FALSE; } else if (strcmp(argv[i], "--stdin") == 0 || strcmp(argv[i], "-ilas") == 0) { use_stdin = TRUE; } else if (strcmp(argv[i], "--repair") == 0 || strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-repair_header") == 0 || strcmp(argv[i], "-repair") == 0) { repair_header = TRUE; check_points = TRUE; } else if (strcmp(argv[i], "--repair_bb") == 0 || strcmp(argv[i], "--repair_bounding_box") == 0 || strcmp(argv[i], "--repair_boundingbox") == 0 || strcmp(argv[i], "-repair_bb") == 0 || strcmp(argv[i], "-repair_bounding_box") == 0 || strcmp(argv[i], "-repair_boundingbox") == 0 || strcmp(argv[i], "-repair") == 0 || strcmp(argv[i], "-rb") == 0) { repair_bounding_box = TRUE; check_points = TRUE; } else if (strcmp(argv[i],"--system_identifier") == 0 || strcmp(argv[i],"-system_identifier") == 0 || strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"-sys_id") == 0) { i++; system_identifier = (char*) malloc(31 * sizeof(char)); strcpy(system_identifier, argv[i]); change_header = TRUE; } else if (strcmp(argv[i],"--generating_software") == 0 || strcmp(argv[i],"-generating_software") == 0 || strcmp(argv[i],"-g") == 0 || strcmp(argv[i],"-gen_soft") == 0) { i++; generating_software = (char*) malloc(31*sizeof(char)); strcpy(generating_software, argv[i]); change_header = TRUE; } else if (strcmp(argv[i],"--file_creation") == 0 || strcmp(argv[i],"-file_creation") == 0) { /* XXX - mloskot: Consider replacing atoi with strtol, see http://www.iso-9899.info/wiki/Converting */ i++; file_creation_day = (unsigned char)atoi(argv[i]); i++; file_creation_year = (unsigned char)atoi(argv[i]); change_header = TRUE; } else if (strcmp(argv[i],"--skip_vlr") == 0 || strcmp(argv[i],"--no_vlr") == 0) { skip_vlr = TRUE; } else if (strcmp(argv[i],"--wkt") == 0) { wkt = TRUE; } else if (file_name == NULL) { file_name = argv[i]; } else { usage(); fprintf(stderr, "ERROR: unknown argument '%s'\n",argv[i]); exit(1); } } if (use_stdin) { file_name = "stdin"; } if (!file_name) { LASError_Print("No filename was provided to be opened"); usage(); exit(1); } reader = LASReader_Create(file_name); if (!reader) { LASError_Print("Could not open file "); exit(1); } header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Could not get LASHeader "); exit(1); } print_header(stdout, header, file_name, skip_vlr, wkt); if (change_header) { if (system_identifier) { err = LASHeader_SetSystemId (header, system_identifier); if (err) LASError_Print("Could not set SystemId"); } if (generating_software) { err = LASHeader_SetSoftwareId(header, generating_software); if (err) LASError_Print("Could not set SoftwareId"); } if ( file_creation_day || file_creation_year) { err = LASHeader_SetCreationDOY(header, file_creation_day); if (err) LASError_Print("Could not set file creation day"); err = LASHeader_SetCreationYear(header, file_creation_year); if (err) LASError_Print("Could not set file creation year"); } /* We need to wipe out the reader and make a writer. */ if (reader) { LASReader_Destroy(reader); reader = NULL; } writer = LASWriter_Create(file_name, header, LAS_MODE_APPEND); if (!writer) { LASError_Print("Problem creating LASWriterH object"); LASHeader_Destroy(header); header = NULL; exit(1); } if (writer) LASWriter_Destroy(writer); writer = NULL; if (header) LASHeader_Destroy(header); header = NULL; } if (check_points) { if (!reader) { reader = LASReader_Create(file_name); if (!reader) { LASError_Print("Could not open file "); exit(1); } } if (! header) { header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Could not get LASHeader "); exit(1); } } if (!summary) summary = SummarizePoints(reader); print_point_summary(stdout, summary, header); if (repair_header) { fprintf(stdout, "\n---------------------------------------------------------\n"); fprintf(stdout, " Repair Summary\n"); fprintf(stdout, "---------------------------------------------------------\n"); if (use_stdin) { LASError_Print("Cannot update header information on piped input!"); exit(1); } if (! header) { header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Could not get LASHeader "); exit(1); } } if (! repair_bounding_box) { if ( LASHeader_GetMinX(header) != LASPoint_GetX(summary->pmin) ) repair_bounding_box = TRUE; if ( LASHeader_GetMinY(header) != LASPoint_GetY(summary->pmin) ) repair_bounding_box = TRUE; if ( LASHeader_GetMinZ(header) != LASPoint_GetZ(summary->pmin) ) repair_bounding_box = TRUE; if ( LASHeader_GetMaxX(header) != LASPoint_GetX(summary->pmax) ) repair_bounding_box = TRUE; if ( LASHeader_GetMaxY(header) != LASPoint_GetY(summary->pmax) ) repair_bounding_box = TRUE; if ( LASHeader_GetMaxZ(header) != LASPoint_GetZ(summary->pmax) ) repair_bounding_box = TRUE; } if (repair_bounding_box) { fprintf(stdout, " Reparing Bounding Box...\n"); err = LASHeader_SetMin( header, LASPoint_GetX(summary->pmin), LASPoint_GetY(summary->pmin), LASPoint_GetZ(summary->pmin) ); if (err) { LASError_Print("Could not set minimum for header "); exit(1); } err = LASHeader_SetMax( header, LASPoint_GetX(summary->pmax), LASPoint_GetY(summary->pmax), LASPoint_GetZ(summary->pmax) ); if (err) { LASError_Print("Could not set minimum for header "); exit(1); } } for (i = 0; i < 5; i++) { if (LASHeader_GetPointRecordsByReturnCount(header, i) != summary->number_of_points_by_return[i]) { update_return_counts = TRUE; break; } } if (update_return_counts) { fprintf(stdout, " Reparing Point Count by Return...\n"); for (i = 0; i < 5; i++) { LASHeader_SetPointRecordsByReturnCount( header, i, summary->number_of_points_by_return[i]); } } if (reader) { LASReader_Destroy(reader); reader = NULL; } writer = LASWriter_Create(file_name, header, LAS_MODE_APPEND); if (!writer) { LASError_Print("Problem creating LASWriterH object for append"); LASHeader_Destroy(header); header = NULL; exit(1); } LASWriter_Destroy(writer); writer = NULL; LASHeader_Destroy(header); header = NULL; } if (summary) { LASPoint_Destroy(summary->pmin); LASPoint_Destroy(summary->pmax); free(summary); } } if (reader) LASReader_Destroy(reader); if (header) LASHeader_Destroy(header); #ifdef HAVE_GDAL /* Various GDAL related cleanups */ #ifdef OSRCleanup OSRCleanup(); #endif CPLFinderClean(); CPLFreeConfig(); CPLCleanupTLS(); #endif return 0; }
int main(int argc, char *argv[]) { int i; int use_stdin = FALSE; int use_stdout = FALSE; int skip_invalid = FALSE; int verbose = FALSE; char* file_name_in = 0; char* file_name_out = 0; char separator_sign = ' '; char header_comment_sign = '\0'; char* parse_string = "xyz"; char printstring[256]; LASReaderH reader = NULL; LASHeaderH header = NULL; LASPointH p = NULL; FILE* file_out = NULL; int len; uint32_t index = 0; for (i = 1; i < argc; i++) { if ( strcmp(argv[i],"-h") == 0 || strcmp(argv[i],"--help") == 0 ) { usage(); exit(0); } else if ( strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0 ) { verbose = TRUE; } else if ( strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--skip_invalid") == 0 ) { skip_invalid = TRUE; } else if ( strcmp(argv[i], "--parse") == 0 || strcmp(argv[i], "-parse") == 0 ) { i++; parse_string = argv[i]; } else if ( strcmp(argv[i], "--sep") == 0 || strcmp(argv[i], "-sep") == 0 ) { i++; if (strcmp(argv[i],"komma") == 0) { separator_sign = ','; } else if (strcmp(argv[i],"tab") == 0) { separator_sign = '\t'; } else if ( strcmp(argv[i],"dot") == 0 || strcmp(argv[i],"period") == 0 ) { separator_sign = '.'; } else if (strcmp(argv[i],"colon") == 0) { separator_sign = ':'; } else if ( strcmp(argv[i],"scolon") == 0 || strcmp(argv[i],"semicolon") == 0 ) { separator_sign = ';'; } else if ( strcmp(argv[i],"hyphen") == 0 || strcmp(argv[i],"minus") == 0 ) { separator_sign = '-'; } else if (strcmp(argv[i],"space") == 0) { separator_sign = ' '; } else { fprintf(stderr, "ERROR: unknown seperator '%s'\n",argv[i]); usage(); exit(1); } } else if ( strcmp(argv[i], "--header") == 0 || strcmp(argv[i], "--comment") == 0 || strcmp(argv[i], "-header") == 0 || strcmp(argv[i], "-comment") == 0 || strcmp(argv[i], "-head") == 0 ) { i++; if (strcmp(argv[i],"komma") == 0) { header_comment_sign = ','; } else if (strcmp(argv[i],"colon") == 0) { header_comment_sign = ':'; } else if ( strcmp(argv[i],"scolon") == 0 || strcmp(argv[i],"semicolon") == 0 ) { header_comment_sign = ';'; } else if ( strcmp(argv[i],"pound") == 0 || strcmp(argv[i],"hash") == 0 ) { header_comment_sign = '#'; } else if (strcmp(argv[i],"percent") == 0) { header_comment_sign = '%'; } else if (strcmp(argv[i],"dollar") == 0) { header_comment_sign = '$'; } else if (strcmp(argv[i],"star") == 0) { header_comment_sign = '*'; } else { fprintf(stderr, "ERROR: unknown comment symbol '%s'\n",argv[i]); usage(); exit(1); } } else if ( strcmp(argv[i], "--stdin") == 0 || strcmp(argv[i], "-ilas") == 0 ) { use_stdin = TRUE; } else if ( strcmp(argv[i], "--stdout") == 0 ) { use_stdout = TRUE; } else if ( strcmp(argv[i],"--input") == 0 || strcmp(argv[i],"-input") == 0 || strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"-in") == 0 ) { i++; file_name_in = argv[i]; } else if ( strcmp(argv[i],"--output") == 0 || strcmp(argv[i],"--out") == 0 || strcmp(argv[i],"-out") == 0 || strcmp(argv[i],"-o") == 0 ) { i++; file_name_out = argv[i]; } else if (i == argc - 2 && file_name_in == 0 && file_name_out == 0) { file_name_in = argv[i]; } else if (i == argc - 1 && file_name_in == 0 && file_name_out == 0) { file_name_in = argv[i]; } else if (i == argc - 1 && file_name_in && file_name_out == 0) { file_name_out = argv[i]; } else { fprintf(stderr, "ERROR: unknown argument '%s'\n",argv[i]); usage(); exit(1); } } /* end looping through argc/argv */ if (use_stdin) file_name_in = "stdin"; reader = LASReader_Create(file_name_in); if (!reader) { LASError_Print("Unable to read file"); exit(1); } header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Unable to fetch header for file"); exit(1); } if (use_stdout) { file_out = stdout; } else { if (file_name_out == NULL) { if (file_name_in == NULL) { LASError_Print("No input filename was specified"); usage(); exit(1); } len = (int)strlen(file_name_in); file_name_out = strdup(file_name_in); if (file_name_out[len-3] == '.' && file_name_out[len-2] == 'g' && file_name_out[len-1] == 'z') { len = len - 4; } while (len > 0 && file_name_out[len] != '.') { len--; } file_name_out[len] = '.'; file_name_out[len+1] = 't'; file_name_out[len+2] = 'x'; file_name_out[len+3] = 't'; file_name_out[len+4] = '\0'; } file_out = fopen(file_name_out, "w"); if (file_out == 0) { LASError_Print("Could not open file for write"); usage(); exit(1); } } if (verbose) { print_header(stderr, header, file_name_in); } if (header_comment_sign) { fprintf(file_out, "%c file signature: '%s'\012", header_comment_sign, LASHeader_GetFileSignature(header) ); fprintf(file_out, "%c file source ID: %d\012", header_comment_sign, LASHeader_GetFileSourceId(header) ); fprintf(file_out, "%c reserved: %d\012", header_comment_sign, LASHeader_GetReserved(header) ); fprintf(file_out, "%c project ID GUID: %s\012", header_comment_sign, LASHeader_GetProjectId(header) ); fprintf(file_out, "%c version major.minor: %d.%d\012", header_comment_sign, LASHeader_GetVersionMajor(header), LASHeader_GetVersionMinor(header) ); fprintf(file_out, "%c system_identifier: '%s'\012", header_comment_sign, LASHeader_GetSystemId(header) ); fprintf(file_out, "%c generating_software: '%s'\012", header_comment_sign, LASHeader_GetSoftwareId(header) ); fprintf(file_out, "%c file creation day/year: %d/%d\012", header_comment_sign, LASHeader_GetCreationDOY(header), LASHeader_GetCreationYear(header) ); fprintf(file_out, "%c header size %d\012", header_comment_sign, LASHeader_GetHeaderSize(header) ); fprintf(file_out, "%c offset to point data %d\012", header_comment_sign, LASHeader_GetDataOffset(header) ); fprintf(file_out, "%c number var. length records %d\012", header_comment_sign, LASHeader_GetRecordsCount(header) ); fprintf(file_out, "%c point data format %d\012", header_comment_sign, LASHeader_GetDataFormatId(header) ); fprintf(file_out, "%c point data record length %d\012", header_comment_sign, LASHeader_GetDataRecordLength(header) ); fprintf(file_out, "%c number of point records %d\012", header_comment_sign, LASHeader_GetPointRecordsCount(header) ); fprintf(file_out, "%c number of points by return %d %d %d %d %d\012", header_comment_sign, LASHeader_GetPointRecordsByReturnCount(header, 0), LASHeader_GetPointRecordsByReturnCount(header, 1), LASHeader_GetPointRecordsByReturnCount(header, 2), LASHeader_GetPointRecordsByReturnCount(header, 3), LASHeader_GetPointRecordsByReturnCount(header, 4) ); fprintf(file_out, "%c scale factor x y z %.6f %.6f %.6f\n", header_comment_sign, LASHeader_GetScaleX(header), LASHeader_GetScaleY(header), LASHeader_GetScaleZ(header) ); fprintf(file_out, "%c offset x y z %.6f %.6f %.6f\n", header_comment_sign, LASHeader_GetOffsetX(header), LASHeader_GetOffsetY(header), LASHeader_GetOffsetZ(header) ); fprintf(file_out, "%c min x y z %.6f %.6f %.6f\n", header_comment_sign, LASHeader_GetMinX(header), LASHeader_GetMinY(header), LASHeader_GetMinZ(header) ); fprintf(file_out, "%c max x y z %.6f %.6f %.6f\n", header_comment_sign, LASHeader_GetMaxX(header), LASHeader_GetMaxY(header), LASHeader_GetMaxZ(header) ); } p = LASReader_GetNextPoint(reader); while (p) { if (skip_invalid && !LASPoint_IsValid(p)) { if (verbose) { LASError_Print("Skipping writing invalid point..."); } p = LASReader_GetNextPoint(reader); index -=1; continue; } i = 0; for (;;) { LASColorH color = LASPoint_GetColor(p); switch (parse_string[i]) { /* // the x coordinate */ case 'x': lidardouble2string(printstring, LASPoint_GetX(p)); fprintf(file_out, printstring); break; /* // the y coordinate */ case 'y': lidardouble2string(printstring, LASPoint_GetY(p)); fprintf(file_out, printstring); break; /* // the z coordinate */ case 'z': lidardouble2string(printstring, LASPoint_GetZ(p)); fprintf(file_out, printstring); break; /* // the gps-time */ case 't': lidardouble2string(printstring,LASPoint_GetTime(p)); fprintf(file_out, printstring); break; /* // the intensity */ case 'i': fprintf(file_out, "%d", LASPoint_GetIntensity(p)); break; /* the scan angle */ case 'a': fprintf(file_out, "%d", LASPoint_GetScanAngleRank(p)); break; /* the number of the return */ case 'r': fprintf(file_out, "%d", LASPoint_GetReturnNumber(p)); break; /* the classification */ case 'c': fprintf(file_out, "%d", LASPoint_GetClassification(p)); break; /* the user data */ case 'u': fprintf(file_out, "%d", LASPoint_GetUserData(p)); break; /* the number of returns of given pulse */ case 'n': fprintf(file_out, "%d", LASPoint_GetNumberOfReturns(p)); break; /* the red channel color */ case 'R': fprintf(file_out, "%d", LASColor_GetRed(color)); break; /* the green channel color */ case 'G': fprintf(file_out, "%d", LASColor_GetGreen(color)); break; /* the blue channel color */ case 'B': fprintf(file_out, "%d", LASColor_GetBlue(color)); break; case 'M': fprintf(file_out, "%d", index); break; /* case 'p': // the point source ID fprintf(file_out, "%d", lasreader->point.point_source_ID); break; */ /* the edge of flight line flag */ case 'e': fprintf(file_out, "%d", LASPoint_GetFlightLineEdge(p)); break; /* the direction of scan flag */ case 'd': fprintf(file_out, "%d", LASPoint_GetScanDirection(p)); break; } i++; if (parse_string[i]) { fprintf(file_out, "%c", separator_sign); } else { fprintf(file_out, "\012"); break; } LASColor_Destroy(color); } p = LASReader_GetNextPoint(reader); index +=1; } LASReader_Destroy(reader); LASHeader_Destroy(header); fclose(file_out); return 0; }
int main(int argc, char *argv[]) { int i; int j; char* buffer; int use_stdout = FALSE; int skip_invalid = FALSE; int num_entries = 0; int verbose = FALSE; char* file_name_in = 0; char* file_name_out = 0; char separator_sign = ' '; char* parse_string = "xyz"; int64_t global_offset_x = 0; int64_t global_offset_y = 0; int check = FALSE; double scale_x; double scale_y; LASReaderH reader = NULL; LASHeaderH header = NULL; LASPointH p = NULL; FILE* file_out; int len; unsigned int index = 0; if (argc == 1) { usage(); exit(0); } for (i = 1; i < argc; i++) { if ( strcmp(argv[i],"-h") == 0 || strcmp(argv[i],"-help") == 0 || strcmp(argv[i],"--help") == 0 ) { usage(); exit(0); } else if ( strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0 ) { verbose = TRUE; } else if ( strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--skip_invalid") == 0 ) { skip_invalid = TRUE; } else if ( strcmp(argv[i], "--parse") == 0 || strcmp(argv[i], "-parse") == 0 ) { i++; parse_string = argv[i]; } else if ( strcmp(argv[i], "--moffset") == 0 || strcmp(argv[i], "-moffset") == 0 ) { i++; buffer = strtok (argv[i], ","); j = 0; while (buffer) { if (j == 0) { global_offset_x = S64(buffer); } else if (j == 1) { global_offset_y = S64(buffer); } j++; buffer = strtok (NULL, ","); while (buffer && *buffer == '\040') buffer++; } if (j != 2){ fprintf(stderr, "Only two int64_t are required in moffset option!\n"); exit(1); } } else if ( strcmp(argv[i], "--check") == 0 || strcmp(argv[i], "-check") == 0 ) { i++; check = TRUE; buffer = strtok (argv[i], ","); j = 0; while (buffer) { if (j == 0) { sscanf(buffer, "%lf", &scale_x); } else if (j == 1) { sscanf(buffer, "%lf", &scale_y); } j++; buffer = strtok (NULL, ","); while (buffer && *buffer == '\040') buffer++; } if (j != 2){ fprintf(stderr, "Only two doubles are required in moffset option!\n"); exit(1); } } else if ( strcmp(argv[i], "--stdout") == 0 ) { use_stdout = TRUE; } else if ( strcmp(argv[i],"--input") == 0 || strcmp(argv[i],"-input") == 0 || strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"-in") == 0 ) { i++; file_name_in = argv[i]; } else if ( strcmp(argv[i],"--output") == 0 || strcmp(argv[i],"--out") == 0 || strcmp(argv[i],"-out") == 0 || strcmp(argv[i],"-o") == 0 ) { i++; file_name_out = argv[i]; } else if (file_name_in == 0 && file_name_out == 0) { file_name_in = argv[i]; } else if (file_name_in && file_name_out == 0) { file_name_out = argv[i]; } else { fprintf(stderr, "ERROR: unknown argument '%s'\n",argv[i]); usage(); exit(1); } } /* end looping through argc/argv */ num_entries = strlen(parse_string); if (use_stdout == TRUE && file_name_out){ LASError_Print("If an output file is specified, --stdout must not be used!"); exit(1); } reader = LASReader_Create(file_name_in); if (!reader) { LASError_Print("Unable to read file"); exit(1); } header = LASReader_GetHeader(reader); if (!header) { LASError_Print("Unable to fetch header for file"); exit(1); } if (use_stdout) { file_out = stdout; } else { if (file_name_out == NULL) { if (file_name_in == NULL) { LASError_Print("No input filename was specified"); usage(); exit(1); } len = (int)strlen(file_name_in); file_name_out = LASCopyString(file_name_in); if (file_name_out[len-3] == '.' && file_name_out[len-2] == 'g' && file_name_out[len-1] == 'z') { len = len - 4; } while (len > 0 && file_name_out[len] != '.') { len--; } file_name_out[len] = '\0'; } file_out = fopen(file_name_out, "wb"); } if (file_out == 0) { LASError_Print("Could not open file for write"); usage(); exit(1); } if (verbose) { print_header(stderr, header, file_name_in); } // Compute factors to add to X and Y and check sanity of generated codes double file_scale_x = LASHeader_GetScaleX(header); double file_scale_y = LASHeader_GetScaleY(header); if (check) { // Check specified scales are like in the LAS file if (fabs(scale_x - file_scale_x) > TOLERANCE){ fprintf(stderr, "ERROR: x scale in input file (%lf) does not match specified x scale (%lf)\n",file_scale_x, scale_x); exit(1); } if (fabs(scale_y - file_scale_y) > TOLERANCE){ fprintf(stderr, "ERROR: y scale in input file (%lf) does not match specified y scale (%lf)\n",file_scale_y, scale_y); exit(1); } /* Check that the extent of the file (taking into account the global offset) * is within 0,2^31 */ double check_min_x = 1.0 + LASHeader_GetMinX(header) - (((double) global_offset_x) * scale_x); if (check_min_x < TOLERANCE) { fprintf(stderr, "ERROR: Specied X global offset is too large. (MinX - (GlobalX*ScaleX)) < 0\n"); exit(1); } double check_min_y = 1.0 + LASHeader_GetMinY(header) - (((double) global_offset_y) * scale_y); if (check_min_y < TOLERANCE) { fprintf(stderr, "ERROR: Specied Y global offset is too large. (MinY - (GlobalY*ScaleY)) < 0\n"); exit(1); } double check_max_x = LASHeader_GetMaxX(header) - (((double) global_offset_x) * scale_x); if (check_max_x > (MAX_INT_31 * scale_x)) { fprintf(stderr, "ERROR: Specied X global offset is too small. (MaxX - (GlobalX*ScaleX)) > (2^31)*ScaleX\n"); exit(1); } double check_max_y = LASHeader_GetMaxY(header) - (((double) global_offset_y) * scale_y); if (check_max_y > (MAX_INT_31 * scale_y)) { fprintf(stderr, "ERROR: Specied Y global offset is too small. (MaxY - (GlobalY*ScaleY)) > (2^31)*ScaleY\n"); exit(1); } } /*Write Postgres header*/ struct postHeader pgHeader; pgHeader.s = "PGCOPY\n\377\r\n\0"; int i1T = 0, i2T = 0; pgHeader.i1 = htonl(i1T); pgHeader.i2 = htonl(i2T); fwrite(pgHeader.s, 11, 1, file_out); fwrite(&pgHeader.i1, sizeof(uint32_t), 1, file_out); fwrite(&pgHeader.i2, sizeof(uint32_t), 1, file_out); /* declaration for morton*/ uint32_t rawx = 0; uint32_t rawy = 0; uint64_t mortonkey = 0; /* scaled offsets to add for the morton encoding */ int64_t factorX = ((int64_t) (LASHeader_GetOffsetX(header) / file_scale_x)) - global_offset_x; int64_t factorY = ((int64_t) (LASHeader_GetOffsetY(header) / file_scale_y)) - global_offset_y; p = LASReader_GetNextPoint(reader); while (p) { if (skip_invalid && !LASPoint_IsValid(p)) { if (verbose) { LASError_Print("Skipping writing invalid point..."); } p = LASReader_GetNextPoint(reader); index -=1; continue; } struct postRow pgRow; uint32_t size; uint16_t hT = num_entries; pgRow.h = htons(hT); fwrite(& pgRow.h, 2, 1, file_out); size = sizeof(double); pgRow.vardSize = htonl(size); size = sizeof(uint32_t); pgRow.varSize = htonl(size); i = 0; for (;;) { LASColorH color = LASPoint_GetColor(p); double vard; int var; unsigned long long int vardL, varL; switch (parse_string[i]) { /* // the morton code on xy */ case 'k': rawx = (uint32_t) (((int64_t) LASPoint_GetRawX(p)) + factorX); rawy = (uint32_t) (((int64_t) LASPoint_GetRawY(p)) + factorY); mortonkey = EncodeMorton2D(rawx,rawy); varL = htobe64(mortonkey); fwrite(&pgRow.vardSize, sizeof(uint32_t), 1, file_out); fwrite(&varL, sizeof(uint64_t), 1, file_out); break; /* // the x coordinate */ case 'x': vard = LASPoint_GetX(p); fwrite(&pgRow.vardSize, sizeof(uint32_t), 1, file_out); vardL = bigEndian_double(vard); fwrite(&vardL, sizeof(double), 1, file_out); break; /* // the y coordinate */ case 'y': vard = LASPoint_GetY(p); fwrite(&pgRow.vardSize, sizeof(uint32_t), 1, file_out); vardL = bigEndian_double(vard); fwrite(&vardL, sizeof(double), 1, file_out); break; /* // the z coordinate */ case 'z': vard = LASPoint_GetZ(p); fwrite(&pgRow.vardSize, sizeof(uint32_t), 1, file_out); vardL = bigEndian_double(vard); fwrite(&vardL, sizeof(double), 1, file_out); break; /* // the gps-time */ case 't': vard = LASPoint_GetTime(p); fwrite(&pgRow.vardSize, sizeof(uint32_t), 1, file_out); vardL = bigEndian_double(vard); fwrite(&vardL, sizeof(double), 1, file_out); break; /* // the intensity */ case 'i': var = LASPoint_GetIntensity(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the scan angle */ case 'a': var = LASPoint_GetScanAngleRank(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the number of the return */ case 'r': var = LASPoint_GetReturnNumber(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the classification */ case 'c': var = LASPoint_GetClassification(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the user data */ case 'u': var = LASPoint_GetUserData(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the number of returns of given pulse */ case 'n': var = LASPoint_GetNumberOfReturns(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the red channel color */ case 'R': var = LASColor_GetRed(color); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the green channel color */ case 'G': var = LASColor_GetGreen(color); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the blue channel color */ case 'B': var = LASColor_GetBlue(color); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; case 'M': var = index; fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; case 'p': var = LASPoint_GetPointSourceId(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the edge of flight line flag */ case 'e': var = LASPoint_GetFlightLineEdge(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; /* the direction of scan flag */ case 'd': var = LASPoint_GetScanDirection(p); fwrite(&pgRow.varSize, sizeof(uint32_t), 1, file_out); varL = htonl(var); fwrite(&varL, sizeof(uint32_t), 1, file_out); break; } i++; if (!parse_string[i]) { break; } LASColor_Destroy(color); } p = LASReader_GetNextPoint(reader); index +=1; } short endT = -1; short end = htons(endT); fwrite(&end, sizeof(end), 1, file_out); fflush(file_out); fclose(file_out); LASReader_Destroy(reader); LASHeader_Destroy(header); return 0; }