BOOL LASreaderBuffered::open() { if (!lasreadopener.active()) { fprintf(stderr, "ERROR: no input name\n"); return FALSE; } // open the main file lasreader = lasreadopener.open(); if (lasreader == 0) { fprintf(stderr, "ERROR: opening '%s'\n", lasreadopener.get_file_name()); return FALSE; } // populate the merged header header = lasreader->header; // zero the pointers of the other header so they don't get deallocated twice lasreader->header.user_data_in_header = 0; lasreader->header.vlrs = 0; lasreader->header.laszip = 0; lasreader->header.vlr_lastiling = 0; lasreader->header.vlr_lasoriginal = 0; lasreader->header.user_data_after_header = 0; // special check for extra attributes if (header.number_extra_attributes) { header.number_extra_attributes = 0; header.init_extra_attributes(lasreader->header.number_extra_attributes, lasreader->header.extra_attributes); } // initialize the point with the header info if (header.laszip) { if (!point.init(&header, header.laszip->num_items, header.laszip->items)) return FALSE; } else { if (!point.init(&header, header.point_data_format, header.point_data_record_length)) return FALSE; } // maybe we have to look for neighbors from which we load buffer points if (lasreadopener_neighbors.active()) { F64 xyz; lasreadopener_neighbors.set_inside_rectangle(header.min_x - buffer_size, header.min_y - buffer_size, header.max_x + buffer_size, header.max_y + buffer_size); // store current counts and bounding box in LASbufferVLR header.set_lasoriginal(); while (lasreadopener_neighbors.active()) { LASreader* lasreader_neighbor = lasreadopener_neighbors.open(); if (lasreader_neighbor == 0) { fprintf(stderr, "ERROR: opening neighbor '%s'\n", lasreadopener_neighbors.get_file_name()); return FALSE; } // a point type change could be problematic if (header.point_data_format != lasreader_neighbor->header.point_data_format) { if (!point_type_change) fprintf(stderr, "WARNING: files have different point types: %d vs %d\n", header.point_data_format, lasreader_neighbor->header.point_data_format); point_type_change = TRUE; } // a point size change could be problematic if (header.point_data_record_length != lasreader_neighbor->header.point_data_record_length) { if (!point_size_change) fprintf(stderr, "WARNING: files have different point sizes: %d vs %d\n", header.point_data_record_length, lasreader_neighbor->header.point_data_record_length); point_size_change = TRUE; } while (lasreader_neighbor->read_point()) { // copy point = lasreader_neighbor->point; // copy_point_to_buffer copy_point_to_buffer(); // increment number of points by return if (point.number_of_returns_of_given_pulse == 1) { header.number_of_points_by_return[0]++; } else if (point.number_of_returns_of_given_pulse == 2) { header.number_of_points_by_return[1]++; } else if (point.number_of_returns_of_given_pulse == 3) { header.number_of_points_by_return[2]++; } else if (point.number_of_returns_of_given_pulse == 4) { header.number_of_points_by_return[3]++; } else if (point.number_of_returns_of_given_pulse == 5) { header.number_of_points_by_return[4]++; } // grow bounding box xyz = point.get_x(); if (header.min_x > xyz) header.min_x = xyz; else if (header.max_x < xyz) header.max_x = xyz; xyz = point.get_y(); if (header.min_y > xyz) header.min_y = xyz; else if (header.max_y < xyz) header.max_y = xyz; xyz = point.get_z(); if (header.min_z > xyz) header.min_z = xyz; else if (header.max_z < xyz) header.max_z = xyz; } lasreader_neighbor->close(); delete lasreader_neighbor; } header.number_of_point_records += buffered_points; fprintf(stderr, "LASreaderBuffered: adding %u buffer points.\n", buffered_points); } // check if the header can support the enlarged bounding box // check x if ((((header.max_x - header.x_offset) / header.x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / header.x_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 x_offset = (F64)I64_QUANTIZE((header.min_x + header.max_x)/2); F64 x_scale_factor = header.x_scale_factor; while ((((header.max_x - x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - x_offset) / x_scale_factor) < I32_MIN)) { x_scale_factor *= 10; } if (header.x_scale_factor != x_scale_factor) { fprintf(stderr, "WARNING: i changed x_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.x_scale_factor, x_scale_factor); header.x_scale_factor = x_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_x - header.x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / x_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed x_offset from %g to %g to accommodate enlarged bounding box\n", header.x_offset, x_offset); header.x_offset = x_offset; reoffset = TRUE; } } // check y if ((((header.max_y - header.y_offset) / header.y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / header.y_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 y_offset = (F64)I64_QUANTIZE((header.min_y + header.max_y)/2); F64 y_scale_factor = header.y_scale_factor; while ((((header.max_y - y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - y_offset) / y_scale_factor) < I32_MIN)) { y_scale_factor *= 10; } if (header.y_scale_factor != y_scale_factor) { fprintf(stderr, "WARNING: i changed y_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.y_scale_factor, y_scale_factor); header.y_scale_factor = y_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_y - header.y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / y_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed y_offset from %g to %g to accommodate enlarged bounding box\n", header.y_offset, y_offset); header.y_offset = y_offset; reoffset = TRUE; } } // check z if ((((header.max_z - header.z_offset) / header.z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / header.z_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 z_offset = (F64)I64_QUANTIZE((header.min_z + header.max_z)/2); F64 z_scale_factor = header.z_scale_factor; while ((((header.max_z - z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - z_offset) / z_scale_factor) < I32_MIN)) { z_scale_factor *= 10; } if (header.z_scale_factor != z_scale_factor) { fprintf(stderr, "WARNING: i changed z_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.z_scale_factor, z_scale_factor); header.z_scale_factor = z_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_z - header.z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / z_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed z_offset from %g to %g to accommodate enlarged bounding box\n", header.z_offset, z_offset); header.z_offset = z_offset; reoffset = TRUE; } } npoints = header.number_of_point_records; p_count = 0; return TRUE; }
BOOL LASreaderMerged::open() { if (file_name_number == 0) { fprintf(stderr, "ERROR: no valid file names\n"); return FALSE; } // allocate space for the individual bounding_boxes if (bounding_boxes) delete [] bounding_boxes; bounding_boxes = new F64[file_name_number*4]; // clean header header.clean(); // combine all headers U32 i; for (i = 0; i < file_name_number; i++) { // open the lasreader with the next file name if (lasreaderlas) { if (!lasreaderlas->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderlas for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderbin) { if (!lasreaderbin->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderbin for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreadershp) { if (!lasreadershp->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreadershp for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderqfit) { if (!lasreaderqfit->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderqfit for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderasc) { if (!lasreaderasc->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderasc for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderbil) { if (!lasreaderbil->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderbil for file '%s'\n", file_names[i]); return FALSE; } } else { lasreadertxt->set_translate_intensity(translate_intensity); lasreadertxt->set_scale_intensity(scale_intensity); lasreadertxt->set_translate_scan_angle(translate_scan_angle); lasreadertxt->set_scale_scan_angle(scale_scan_angle); lasreadertxt->set_scale_factor(scale_factor); lasreadertxt->set_offset(offset); if (!lasreadertxt->open(file_names[i], parse_string, skip_lines, populate_header)) { fprintf(stderr, "ERROR: could not open lasreadertxt for file '%s'\n", file_names[i]); return FALSE; } } // record individual bounding box info bounding_boxes[4*i+0] = lasreader->header.min_x; bounding_boxes[4*i+1] = lasreader->header.min_y; bounding_boxes[4*i+2] = lasreader->header.max_x; bounding_boxes[4*i+3] = lasreader->header.max_y; // populate the merged header if (i == 0) { // delete lastiling (meaningless) lasreader->header.clean_lastiling(); // use the header info from the first file header = lasreader->header; // zero the pointers of the other header so they don't get deallocated twice lasreader->header.user_data_in_header = 0; lasreader->header.vlrs = 0; lasreader->header.laszip = 0; lasreader->header.vlr_lastiling = 0; lasreader->header.vlr_lasoriginal = 0; lasreader->header.user_data_after_header = 0; // count the points up to 64 bits npoints = header.number_of_point_records; // special check for extra attributes if (header.number_extra_attributes) { header.number_extra_attributes = 0; header.init_extra_attributes(lasreader->header.number_extra_attributes, lasreader->header.extra_attributes); } } else { // count the points up to 64 bits npoints += lasreader->header.number_of_point_records; // but increment point counters and widen the bounding box header.number_of_point_records += lasreader->header.number_of_point_records; header.number_of_points_by_return[0] += lasreader->header.number_of_points_by_return[0]; header.number_of_points_by_return[1] += lasreader->header.number_of_points_by_return[1]; header.number_of_points_by_return[2] += lasreader->header.number_of_points_by_return[2]; header.number_of_points_by_return[3] += lasreader->header.number_of_points_by_return[3]; header.number_of_points_by_return[4] += lasreader->header.number_of_points_by_return[4]; if (header.max_x < lasreader->header.max_x) header.max_x = lasreader->header.max_x; if (header.max_y < lasreader->header.max_y) header.max_y = lasreader->header.max_y; if (header.max_z < lasreader->header.max_z) header.max_z = lasreader->header.max_z; if (header.min_x > lasreader->header.min_x) header.min_x = lasreader->header.min_x; if (header.min_y > lasreader->header.min_y) header.min_y = lasreader->header.min_y; if (header.min_z > lasreader->header.min_z) header.min_z = lasreader->header.min_z; // a point type change could be problematic if (header.point_data_format != lasreader->header.point_data_format) { if (!point_type_change) fprintf(stderr, "WARNING: files have different point types: %d vs %d\n", header.point_data_format, lasreader->header.point_data_format); point_type_change = TRUE; } // a point size change could be problematic if (header.point_data_record_length != lasreader->header.point_data_record_length) { if (!point_size_change) fprintf(stderr, "WARNING: files have different point sizes: %d vs %d\n", header.point_data_record_length, lasreader->header.point_data_record_length); point_size_change = TRUE; } // and check if we need to resample points because scalefactor of offsets change if (header.x_scale_factor != lasreader->header.x_scale_factor || header.y_scale_factor != lasreader->header.y_scale_factor || header.z_scale_factor != lasreader->header.z_scale_factor) { // if (!rescale) fprintf(stderr, "WARNING: files have different scale factors: %g %g %g vs %g %g %g\n", header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, lasreader->header.x_scale_factor, lasreader->header.y_scale_factor, lasreader->header.z_scale_factor); rescale = TRUE; } if (header.x_offset != lasreader->header.x_offset || header.y_offset != lasreader->header.y_offset || header.z_offset != lasreader->header.z_offset) { // if (!reoffset) fprintf(stderr, "WARNING: files have different offsets: %g %g %g vs %g %g %g\n", header.x_offset, header.y_offset, header.z_offset, lasreader->header.x_offset, lasreader->header.y_offset, lasreader->header.z_offset); reoffset = TRUE; } } lasreader->close(); } // was it requested to rescale or reoffset if (scale_factor) { if (scale_factor[0] && (header.x_scale_factor != scale_factor[0])) { header.x_scale_factor = scale_factor[0]; rescale = TRUE; } if (scale_factor[1] && (header.y_scale_factor != scale_factor[1])) { header.y_scale_factor = scale_factor[1]; rescale = TRUE; } if (scale_factor[2] && (header.z_scale_factor != scale_factor[2])) { header.z_scale_factor = scale_factor[2]; rescale = TRUE; } } if (offset) { if (header.x_offset != offset[0]) { header.x_offset = offset[0]; reoffset = TRUE; } if (header.y_offset != offset[1]) { header.y_offset = offset[1]; reoffset = TRUE; } if (header.z_offset != offset[2]) { header.z_offset = offset[2]; reoffset = TRUE; } } // initialize the point with the header info if (header.laszip) { if (!point.init(&header, header.laszip->num_items, header.laszip->items)) return FALSE; } else { if (!point.init(&header, header.point_data_format, header.point_data_record_length)) return FALSE; } // check if the header can support the enlarged bounding box // check x if ((((header.max_x - header.x_offset) / header.x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / header.x_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 x_offset = (F64)I64_QUANTIZE((header.min_x + header.max_x)/2); F64 x_scale_factor = header.x_scale_factor; while ((((header.max_x - x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - x_offset) / x_scale_factor) < I32_MIN)) { x_scale_factor *= 10; } if (header.x_scale_factor != x_scale_factor) { fprintf(stderr, "WARNING: i changed x_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.x_scale_factor, x_scale_factor); header.x_scale_factor = x_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_x - header.x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / x_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed x_offset from %g to %g to accommodate enlarged bounding box\n", header.x_offset, x_offset); header.x_offset = x_offset; reoffset = TRUE; } } // check y if ((((header.max_y - header.y_offset) / header.y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / header.y_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 y_offset = (F64)I64_QUANTIZE((header.min_y + header.max_y)/2); F64 y_scale_factor = header.y_scale_factor; while ((((header.max_y - y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - y_offset) / y_scale_factor) < I32_MIN)) { y_scale_factor *= 10; } if (header.y_scale_factor != y_scale_factor) { fprintf(stderr, "WARNING: i changed y_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.y_scale_factor, y_scale_factor); header.y_scale_factor = y_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_y - header.y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / y_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed y_offset from %g to %g to accommodate enlarged bounding box\n", header.y_offset, y_offset); header.y_offset = y_offset; reoffset = TRUE; } } // check z if ((((header.max_z - header.z_offset) / header.z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / header.z_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 z_offset = (F64)I64_QUANTIZE((header.min_z + header.max_z)/2); F64 z_scale_factor = header.z_scale_factor; while ((((header.max_z - z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - z_offset) / z_scale_factor) < I32_MIN)) { z_scale_factor *= 10; } if (header.z_scale_factor != z_scale_factor) { fprintf(stderr, "WARNING: i changed z_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.z_scale_factor, z_scale_factor); header.z_scale_factor = z_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_z - header.z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / z_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed z_offset from %g to %g to accommodate enlarged bounding box\n", header.z_offset, z_offset); header.z_offset = z_offset; reoffset = TRUE; } } if (rescale || reoffset) { if (lasreaderlas) { delete lasreaderlas; if (rescale && reoffset) lasreaderlas = new LASreaderLASrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderlas = new LASreaderLASrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderlas = new LASreaderLASreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderlas; } else if (lasreaderbin) { delete lasreaderbin; if (rescale && reoffset) lasreaderbin = new LASreaderBINrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderbin = new LASreaderBINrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderbin = new LASreaderBINreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderbin; } else if (lasreadershp) { delete lasreadershp; if (rescale && reoffset) lasreadershp = new LASreaderSHPrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreadershp = new LASreaderSHPrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreadershp = new LASreaderSHPreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreadershp; } else if (lasreaderqfit) { delete lasreaderqfit; if (rescale && reoffset) lasreaderqfit = new LASreaderQFITrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderqfit = new LASreaderQFITrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderqfit = new LASreaderQFITreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderqfit; } else if (lasreaderasc) { delete lasreaderasc; if (rescale && reoffset) lasreaderasc = new LASreaderASCrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderasc = new LASreaderASCrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderasc = new LASreaderASCreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderasc; } else if (lasreaderbil) { delete lasreaderbil; if (rescale && reoffset) lasreaderbil = new LASreaderBILrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderbil = new LASreaderBILrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderbil = new LASreaderBILreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderbil; } else { delete lasreadertxt; if (rescale && reoffset) lasreadertxt = new LASreaderTXTrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreadertxt = new LASreaderTXTrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreadertxt = new LASreaderTXTreoffset(header.x_offset, header.y_offset, header.z_offset); lasreadertxt->set_translate_intensity(translate_intensity); lasreadertxt->set_scale_intensity(scale_intensity); lasreadertxt->set_translate_scan_angle(translate_scan_angle); lasreadertxt->set_scale_scan_angle(scale_scan_angle); lasreadertxt->set_scale_factor(scale_factor); lasreadertxt->set_offset(offset); lasreader = lasreadertxt; } } p_count = 0; file_name_current = 0; return TRUE; }
BOOL LASreaderMerged::open() { // mpi MPI_Comm_size(MPI_COMM_WORLD, &process_count); MPI_Comm_rank(MPI_COMM_WORLD,&rank); if (file_name_number == 0) { fprintf(stderr, "ERROR: no valid file names\n"); return FALSE; } // allocate space for the individual bounding_boxes if (bounding_boxes) delete [] bounding_boxes; bounding_boxes = new F64[file_name_number*4]; // clean header header.clean(); // combine all headers U32 i,j; BOOL first = TRUE; // mpi, allocate storage file_point_counts = (I64*)malloc(sizeof(I64)*file_name_number); for (i = 0; i < file_name_number; i++) { // open the lasreader with the next file name if (lasreaderlas) { if (!lasreaderlas->open(file_names[i], 512, (first == FALSE))) // starting from second just "peek" into file to get bounding box and count { fprintf(stderr, "ERROR: could not open lasreaderlas for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderbin) { if (!lasreaderbin->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderbin for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreadershp) { if (!lasreadershp->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreadershp for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderqfit) { if (!lasreaderqfit->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderqfit for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderasc) { if (!lasreaderasc->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderasc for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderbil) { if (!lasreaderbil->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderbil for file '%s'\n", file_names[i]); return FALSE; } } else if (lasreaderdtm) { if (!lasreaderdtm->open(file_names[i])) { fprintf(stderr, "ERROR: could not open lasreaderdtm for file '%s'\n", file_names[i]); return FALSE; } } else { lasreadertxt->set_translate_intensity(translate_intensity); lasreadertxt->set_scale_intensity(scale_intensity); lasreadertxt->set_translate_scan_angle(translate_scan_angle); lasreadertxt->set_scale_scan_angle(scale_scan_angle); lasreadertxt->set_scale_factor(scale_factor); lasreadertxt->set_offset(offset); if (!lasreadertxt->open(file_names[i], parse_string, skip_lines, populate_header)) { fprintf(stderr, "ERROR: could not open lasreadertxt for file '%s'\n", file_names[i]); return FALSE; } } // mpi, store the point count for this file file_point_counts[i] = lasreader->npoints; // ignore bounding box if the file has no points if (lasreader->npoints == 0) { // record ignoring bounding box info bounding_boxes[4*i+0] = F64_MAX; bounding_boxes[4*i+1] = F64_MAX; bounding_boxes[4*i+2] = F64_MIN; bounding_boxes[4*i+3] = F64_MIN; } else { // record individual bounding box info bounding_boxes[4*i+0] = lasreader->header.min_x; bounding_boxes[4*i+1] = lasreader->header.min_y; bounding_boxes[4*i+2] = lasreader->header.max_x; bounding_boxes[4*i+3] = lasreader->header.max_y; } // populate the merged header if (first) { first = FALSE; // check for lastiling buffer if (lasreader->header.vlr_lastiling) { if (lasreader->header.vlr_lastiling->buffer) { fprintf(stderr, "WARNING: first file is a buffered tile. maybe remove buffers first?\n"); } } // maybe we should keep the tiling if (keep_lastiling) { if (lasreader->header.vlr_lastiling == 0) { fprintf(stderr, "WARNING: first file has no LAStiling VLR cannot '-keep_lastiling' ...\n"); } } else { // usually we delete the lastiling information as it becomes meaningless lasreader->header.clean_lastiling(); } // use the entire header info from the first file header = lasreader->header; // unlink the pointers for other header so they don't get deallocated twice lasreader->header.unlink(); // count the points up to 64 bits npoints = lasreader->npoints; // special check for attributes in extra bytes if (header.number_attributes) { header.number_attributes = 0; header.init_attributes(lasreader->header.number_attributes, lasreader->header.attributes); } // when merging multiple flightlines the merged header must have a file source ID of 0 if (files_are_flightlines || apply_file_source_ID) { header.file_source_ID = 0; } } else if (lasreader->npoints) { // count the points up to 64 bits npoints += lasreader->npoints; // have there not been any points before if (npoints == lasreader->npoints) { // use the counters header.number_of_point_records = lasreader->header.number_of_point_records; for (j = 0; j < 5; j++) { header.number_of_points_by_return[j] = lasreader->header.number_of_points_by_return[j]; } // and use the bounding box header.max_x = lasreader->header.max_x; header.max_y = lasreader->header.max_y; header.max_z = lasreader->header.max_z; header.min_x = lasreader->header.min_x; header.min_y = lasreader->header.min_y; header.min_z = lasreader->header.min_z; // as well as scale factor and offset header.x_scale_factor = lasreader->header.x_scale_factor; header.y_scale_factor = lasreader->header.y_scale_factor; header.z_scale_factor = lasreader->header.z_scale_factor; header.x_offset = lasreader->header.x_offset; header.y_offset = lasreader->header.y_offset; header.z_offset = lasreader->header.z_offset; // for LAS 1.4 if (header.version_minor >= 4) { header.extended_number_of_point_records = (lasreader->header.extended_number_of_point_records ? lasreader->header.extended_number_of_point_records : lasreader->header.number_of_point_records); for (j = 0; j < 15; j++) { header.extended_number_of_points_by_return[j] = lasreader->header.extended_number_of_points_by_return[j]; } } } else { // increment point counters header.number_of_point_records += lasreader->header.number_of_point_records; for (j = 0; j < 5; j++) { header.number_of_points_by_return[j] += lasreader->header.number_of_points_by_return[j]; } // widen the bounding box if (header.max_x < lasreader->header.max_x) header.max_x = lasreader->header.max_x; if (header.max_y < lasreader->header.max_y) header.max_y = lasreader->header.max_y; if (header.max_z < lasreader->header.max_z) header.max_z = lasreader->header.max_z; if (header.min_x > lasreader->header.min_x) header.min_x = lasreader->header.min_x; if (header.min_y > lasreader->header.min_y) header.min_y = lasreader->header.min_y; if (header.min_z > lasreader->header.min_z) header.min_z = lasreader->header.min_z; // for LAS 1.4 if (header.version_minor >= 4) { header.extended_number_of_point_records += (lasreader->header.extended_number_of_point_records ? lasreader->header.extended_number_of_point_records : lasreader->header.number_of_point_records); for (j = 0; j < 15; j++) { header.extended_number_of_points_by_return[j] += lasreader->header.extended_number_of_points_by_return[j]; } } } // a point type change could be problematic if (header.point_data_format != lasreader->header.point_data_format) { if (!point_type_change) fprintf(stderr, "WARNING: files have different point types: %d vs %d\n", header.point_data_format, lasreader->header.point_data_format); point_type_change = TRUE; } // a point size change could be problematic if (header.point_data_record_length != lasreader->header.point_data_record_length) { if (!point_size_change) fprintf(stderr, "WARNING: files have different point sizes: %d vs %d\n", header.point_data_record_length, lasreader->header.point_data_record_length); point_size_change = TRUE; } // and check if we need to resample points because scalefactor of offsets change if (header.x_scale_factor != lasreader->header.x_scale_factor || header.y_scale_factor != lasreader->header.y_scale_factor || header.z_scale_factor != lasreader->header.z_scale_factor) { // if (!rescale) fprintf(stderr, "WARNING: files have different scale factors: %g %g %g vs %g %g %g\n", header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, lasreader->header.x_scale_factor, lasreader->header.y_scale_factor, lasreader->header.z_scale_factor); rescale = TRUE; } if (header.x_offset != lasreader->header.x_offset || header.y_offset != lasreader->header.y_offset || header.z_offset != lasreader->header.z_offset) { // if (!reoffset) fprintf(stderr, "WARNING: files have different offsets: %g %g %g vs %g %g %g\n", header.x_offset, header.y_offset, header.z_offset, lasreader->header.x_offset, lasreader->header.y_offset, lasreader->header.z_offset); reoffset = TRUE; } } lasreader->close(); } // was it requested to rescale or reoffset if (scale_factor) { if (scale_factor[0] && (header.x_scale_factor != scale_factor[0])) { header.x_scale_factor = scale_factor[0]; rescale = TRUE; } if (scale_factor[1] && (header.y_scale_factor != scale_factor[1])) { header.y_scale_factor = scale_factor[1]; rescale = TRUE; } if (scale_factor[2] && (header.z_scale_factor != scale_factor[2])) { header.z_scale_factor = scale_factor[2]; rescale = TRUE; } } if (offset) { if (header.x_offset != offset[0]) { header.x_offset = offset[0]; reoffset = TRUE; } if (header.y_offset != offset[1]) { header.y_offset = offset[1]; reoffset = TRUE; } if (header.z_offset != offset[2]) { header.z_offset = offset[2]; reoffset = TRUE; } } // initialize the point with the header info if (header.laszip) { if (!point.init(&header, header.laszip->num_items, header.laszip->items)) return FALSE; } else { if (!point.init(&header, header.point_data_format, header.point_data_record_length)) return FALSE; } // check if the header can support the enlarged bounding box // check x if ((((header.max_x - header.x_offset) / header.x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / header.x_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 x_offset = (F64)I64_QUANTIZE((header.min_x + header.max_x)/2); F64 x_scale_factor = header.x_scale_factor; while ((((header.max_x - x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - x_offset) / x_scale_factor) < I32_MIN)) { x_scale_factor *= 10; } if (header.x_scale_factor != x_scale_factor) { fprintf(stderr, "WARNING: i changed x_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.x_scale_factor, x_scale_factor); header.x_scale_factor = x_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_x - header.x_offset) / x_scale_factor) > I32_MAX) || (((header.min_x - header.x_offset) / x_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed x_offset from %g to %g to accommodate enlarged bounding box\n", header.x_offset, x_offset); header.x_offset = x_offset; reoffset = TRUE; } } // check y if ((((header.max_y - header.y_offset) / header.y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / header.y_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 y_offset = (F64)I64_QUANTIZE((header.min_y + header.max_y)/2); F64 y_scale_factor = header.y_scale_factor; while ((((header.max_y - y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - y_offset) / y_scale_factor) < I32_MIN)) { y_scale_factor *= 10; } if (header.y_scale_factor != y_scale_factor) { fprintf(stderr, "WARNING: i changed y_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.y_scale_factor, y_scale_factor); header.y_scale_factor = y_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_y - header.y_offset) / y_scale_factor) > I32_MAX) || (((header.min_y - header.y_offset) / y_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed y_offset from %g to %g to accommodate enlarged bounding box\n", header.y_offset, y_offset); header.y_offset = y_offset; reoffset = TRUE; } } // check z if ((((header.max_z - header.z_offset) / header.z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / header.z_scale_factor) < I32_MIN)) { // maybe we can fix it by adjusting the offset (and if needed by lowering the resolution via the scale factor) F64 z_offset = (F64)I64_QUANTIZE((header.min_z + header.max_z)/2); F64 z_scale_factor = header.z_scale_factor; while ((((header.max_z - z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - z_offset) / z_scale_factor) < I32_MIN)) { z_scale_factor *= 10; } if (header.z_scale_factor != z_scale_factor) { fprintf(stderr, "WARNING: i changed z_scale_factor from %g to %g to accommodate enlarged bounding box\n", header.z_scale_factor, z_scale_factor); header.z_scale_factor = z_scale_factor; rescale = TRUE; } // maybe we changed the resolution ... so do we really need to adjuste the offset if ((((header.max_z - header.z_offset) / z_scale_factor) > I32_MAX) || (((header.min_z - header.z_offset) / z_scale_factor) < I32_MIN)) { fprintf(stderr, "WARNING: i changed z_offset from %g to %g to accommodate enlarged bounding box\n", header.z_offset, z_offset); header.z_offset = z_offset; reoffset = TRUE; } } if (rescale || reoffset) { if (lasreaderlas) { delete lasreaderlas; if (rescale && reoffset) lasreaderlas = new LASreaderLASrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderlas = new LASreaderLASrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderlas = new LASreaderLASreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderlas; } else if (lasreaderbin) { delete lasreaderbin; if (rescale && reoffset) lasreaderbin = new LASreaderBINrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderbin = new LASreaderBINrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderbin = new LASreaderBINreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderbin; } else if (lasreadershp) { delete lasreadershp; if (rescale && reoffset) lasreadershp = new LASreaderSHPrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreadershp = new LASreaderSHPrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreadershp = new LASreaderSHPreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreadershp; } else if (lasreaderqfit) { delete lasreaderqfit; if (rescale && reoffset) lasreaderqfit = new LASreaderQFITrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderqfit = new LASreaderQFITrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderqfit = new LASreaderQFITreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderqfit; } else if (lasreaderasc) { delete lasreaderasc; if (rescale && reoffset) lasreaderasc = new LASreaderASCrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderasc = new LASreaderASCrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderasc = new LASreaderASCreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderasc; } else if (lasreaderbil) { delete lasreaderbil; if (rescale && reoffset) lasreaderbil = new LASreaderBILrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderbil = new LASreaderBILrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderbil = new LASreaderBILreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderbil; } else if (lasreaderdtm) { delete lasreaderdtm; if (rescale && reoffset) lasreaderdtm = new LASreaderDTMrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreaderdtm = new LASreaderDTMrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreaderdtm = new LASreaderDTMreoffset(header.x_offset, header.y_offset, header.z_offset); lasreader = lasreaderdtm; } else { delete lasreadertxt; if (rescale && reoffset) lasreadertxt = new LASreaderTXTrescalereoffset(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor, header.x_offset, header.y_offset, header.z_offset); else if (rescale) lasreadertxt = new LASreaderTXTrescale(header.x_scale_factor, header.y_scale_factor, header.z_scale_factor); else lasreadertxt = new LASreaderTXTreoffset(header.x_offset, header.y_offset, header.z_offset); lasreadertxt->set_translate_intensity(translate_intensity); lasreadertxt->set_scale_intensity(scale_intensity); lasreadertxt->set_translate_scan_angle(translate_scan_angle); lasreadertxt->set_scale_scan_angle(scale_scan_angle); lasreadertxt->set_scale_factor(scale_factor); lasreadertxt->set_offset(offset); lasreader = lasreadertxt; } } p_count = 0; file_name_current = 0; return TRUE; }