⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lasmerge.cpp

📁 Lidar数据处理时
💻 CPP
字号:
/*
===============================================================================

  FILE:  lasmerge.cpp
  
  CONTENTS:
  
    This tool merges multiple LAS file into a single LAS file and outputs it in
    the LAS format. As input the user either provides multiple LAS file names or
    a text file containing a list of LAS file names.

  PROGRAMMERS:
  
    martin isenburg@cs.unc.edu
  
  COPYRIGHT:
  
    copyright (C) 2007  martin isenburg@cs.unc.edu
    
    This software is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  CHANGE HISTORY:
  
    07 November 2007 -- created after email from luis.viveros@digimapas.cl
  
===============================================================================
*/

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lasreader.h"
#include "laswriter.h"

#ifdef _WIN32
extern "C" FILE* fopenGzipped(const char* filename, const char* mode);
#endif

void usage()
{
  fprintf(stderr,"usage:\n");
  fprintf(stderr,"lasmerge -i lasfiles.txt -o out.las\n");
  fprintf(stderr,"lasmerge -i file1.las -i file2.las -i file3.las -o out.las\n");
  fprintf(stderr,"lasmerge -i file1.las -i file2.las -olas > out.las\n");
  fprintf(stderr,"lasmerge -i lasfiles.txt -scale 0.01 -verbose -o out.las\n");
  fprintf(stderr,"lasmerge -h\n");
  exit(1);
}

void ptime(const char *const msg)
{
  float t= ((float)clock())/CLOCKS_PER_SEC;
  fprintf(stderr, "cumulative CPU time thru %s = %f\n", msg, t);
}

int main(int argc, char *argv[])
{
  int i;
  bool verbose = false;
  int num_file_name_in = 0;
  int alloced_file_name_in = 32;
  char** file_names_in = (char**)malloc(sizeof(char*)*alloced_file_name_in);
  char* file_name_out = 0;
  bool olas = false;
  bool olaz = false;
  double* xyz_scale = 0;
  double* xyz_offset = 0;

  for (i = 1; i < argc; i++)
  {
    if (strcmp(argv[i],"-verbose") == 0)
    {
      verbose = true;
    }
    else if (strcmp(argv[i],"-h") == 0)
    {
      usage();
    }
    else if (strcmp(argv[i],"-i") == 0)
    {
      i++;
      if (num_file_name_in == alloced_file_name_in)
      {
        alloced_file_name_in *= 2;
        file_names_in = (char**)realloc(file_names_in,sizeof(char*)*alloced_file_name_in);
      }
      file_names_in[num_file_name_in] = argv[i];
      num_file_name_in++;
    }
    else if (strcmp(argv[i],"-o") == 0)
    {
      i++;
      file_name_out = argv[i];
    }
    else if (strcmp(argv[i],"-scale") == 0)
    {
      xyz_scale = new double[3];
			i++;
			sscanf(argv[i], "%lf", &(xyz_scale[2]));
 			xyz_scale[0] = xyz_scale[1] = xyz_scale[2];
    }
    else if (strcmp(argv[i],"-xyz_scale") == 0)
    {
      xyz_scale = new double[3];
			i++;
			sscanf(argv[i], "%lf", &(xyz_scale[0]));
			i++;
			sscanf(argv[i], "%lf", &(xyz_scale[1]));
			i++;
			sscanf(argv[i], "%lf", &(xyz_scale[2]));
    }
    else if (strcmp(argv[i],"-xyz_offset") == 0)
    {
      xyz_offset = new double[3];
			i++;
			sscanf(argv[i], "%lf", &(xyz_offset[0]));
			i++;
			sscanf(argv[i], "%lf", &(xyz_offset[1]));
			i++;
			sscanf(argv[i], "%lf", &(xyz_offset[2]));
    }
    else if (strcmp(argv[i],"-olas") == 0)
    {
      olas = true;
    }
    else if (strcmp(argv[i],"-olaz") == 0)
    {
      olaz = true;
    }
    else if (i == argc - 2 && num_file_name_in == 0 && file_name_out == 0)
    {
      file_names_in[0] = argv[i];
      num_file_name_in = 1;
    }
    else if (i == argc - 1 && num_file_name_in == 0 && file_name_out == 0)
    {
      file_names_in[0] = argv[i];
      num_file_name_in = 1;
    }
    else if (i == argc - 1 && num_file_name_in != 0 && file_name_out == 0)
    {
      file_name_out = argv[i];
    }
  }

  if (num_file_name_in == 0)
  {
    fprintf(stderr, "ERROR: no input specified\n");
    usage();
  }

  // if we have just one input file with extension different from *.las and *.LAS 
  if (num_file_name_in == 1 && strstr(file_names_in[0],".las") == 0 && strstr(file_names_in[0],".LAS") == 0)
  {
    char line[512];
    // then it should be a file containing filenames and we load the filenames
    num_file_name_in = 0;
    FILE* file = fopen(file_names_in[0], "r");
	  while (fgets(line, sizeof(char) * 512, file))
    {
      if (strstr(line,".las") || strstr(line,".LAS") || strstr(line,".laz") || strstr(line,".LAZ"))
      {
        if (num_file_name_in == alloced_file_name_in)
        {
          alloced_file_name_in *= 2;
          file_names_in = (char**)realloc(file_names_in,sizeof(char*)*alloced_file_name_in);
        }
        file_names_in[num_file_name_in] = strdup(line);
        i = strlen(file_names_in[num_file_name_in]) - 1;
        while (i && file_names_in[num_file_name_in][i] != 's' && file_names_in[num_file_name_in][i] != 'S' && file_names_in[num_file_name_in][i] != 'z' && file_names_in[num_file_name_in][i] != 'Z') i--;
        if (i)
        {
          file_names_in[num_file_name_in][i+1] = '\0';
          num_file_name_in++;
        }
        else
        {
          fprintf(stderr, "WARNING: cannot parse line '%s'\n",line);
        }
      }
      else
      {
        fprintf(stderr, "WARNING: no a valid LAS file name '%s'\n",line);
      }
    }
  }

  // create merged header
  LASheader merged_header;

  if (verbose) ptime("starting first pass.");
  fprintf(stderr, "first pass ... reading headers of %d LAS files...\n", num_file_name_in);

  for (i = 0; i < num_file_name_in; i++)
  {
    FILE* file_in;
    if (strstr(file_names_in[i], ".gz"))
    {
#ifdef _WIN32
      file_in = fopenGzipped(file_names_in[i], "rb");
#else
      fprintf(stderr, "ERROR: no support for gzipped input\n");
      exit(1);
#endif
    }
    else
    {
      file_in = fopen(file_names_in[i], "rb");
    }
    if (file_in == 0)
    {
      fprintf(stderr, "ERROR: could not open '%s'\n",file_names_in[i]);
      usage();
    }

    LASreader* lasreader = new LASreader();

    if (lasreader->open(file_in, false) == false)
    {
      fprintf(stderr, "ERROR: could not open lasreader\n");
      exit(1);
    }

    if (i == 0)
    {
      merged_header = lasreader->header;
    }
    else
    {
      merged_header.number_of_point_records += lasreader->header.number_of_point_records;
      merged_header.number_of_points_by_return[0] += lasreader->header.number_of_points_by_return[0];
      merged_header.number_of_points_by_return[1] += lasreader->header.number_of_points_by_return[1];
      merged_header.number_of_points_by_return[2] += lasreader->header.number_of_points_by_return[2];
      merged_header.number_of_points_by_return[3] += lasreader->header.number_of_points_by_return[3];
      merged_header.number_of_points_by_return[4] += lasreader->header.number_of_points_by_return[4];
      if (merged_header.max_x < lasreader->header.max_x) merged_header.max_x = lasreader->header.max_x;
      if (merged_header.max_y < lasreader->header.max_y) merged_header.max_y = lasreader->header.max_y;
      if (merged_header.max_z < lasreader->header.max_z) merged_header.max_z = lasreader->header.max_z;
      if (merged_header.min_x > lasreader->header.min_x) merged_header.min_x = lasreader->header.min_x;
      if (merged_header.min_y > lasreader->header.min_y) merged_header.min_y = lasreader->header.min_y;
      if (merged_header.min_z > lasreader->header.min_z) merged_header.min_z = lasreader->header.min_z;
    }

    lasreader->close();
    fclose(file_in);
  }

  if (verbose)
  {
    fprintf(stderr, "number_of_point_records %d\n",merged_header.number_of_point_records);
    fprintf(stderr, "number_of_points_by_return %d %d %d %d %d\n",merged_header.number_of_points_by_return[0],merged_header.number_of_points_by_return[1],merged_header.number_of_points_by_return[2],merged_header.number_of_points_by_return[3],merged_header.number_of_points_by_return[4]);
    fprintf(stderr, "x min %.8g max %.8\n", merged_header.min_x, merged_header.max_x);
    fprintf(stderr, "y min %.8g max %.8\n", merged_header.min_y, merged_header.max_y);
    fprintf(stderr, "z min %.8g max %.8\n", merged_header.min_z, merged_header.max_z);
  }

  if (xyz_scale)
  {
    merged_header.x_scale_factor = xyz_scale[0];
    merged_header.y_scale_factor = xyz_scale[1];
    merged_header.z_scale_factor = xyz_scale[2];
  }

  if (xyz_offset)
  {
    merged_header.x_offset = xyz_scale[0];
    merged_header.y_offset = xyz_scale[1];
    merged_header.z_offset = xyz_scale[2];
  }

  // check if the merged_header can support the enlarged bounding box
  int smallest_int = (1<<31)+10;
  int largest_int = smallest_int-1-20;

  // check x scale
  if (((merged_header.max_x - merged_header.x_offset) / merged_header.x_scale_factor) > largest_int ||
      ((merged_header.min_x - merged_header.x_offset) / merged_header.x_scale_factor) < smallest_int )
  {
    merged_header.x_scale_factor = 0.0000001;
    while (((merged_header.max_x - merged_header.x_offset) / merged_header.x_scale_factor) > largest_int ||
          ((merged_header.min_x - merged_header.x_offset) / merged_header.x_scale_factor) < smallest_int )
    {
      merged_header.x_scale_factor *= 10;
    }
    fprintf(stderr, "x_scale_factor of merged_header changed to %g\n", merged_header.x_scale_factor);
  }

  // check y scale
  if (((merged_header.max_y - merged_header.y_offset) / merged_header.y_scale_factor) > largest_int ||
      ((merged_header.min_y - merged_header.y_offset) / merged_header.y_scale_factor) < smallest_int )
  {
    merged_header.y_scale_factor = 0.0000001;
    while (((merged_header.max_y - merged_header.y_offset) / merged_header.y_scale_factor) > largest_int ||
          ((merged_header.min_y - merged_header.y_offset) / merged_header.y_scale_factor) < smallest_int )
    {
      merged_header.y_scale_factor *= 10;
    }
    fprintf(stderr, "y_scale_factor of merged_header changed to %g\n", merged_header.y_scale_factor);
  }
  
  // check z offset and z scale
  if (((merged_header.max_z - merged_header.z_offset) / merged_header.z_scale_factor) > largest_int ||
      ((merged_header.min_z - merged_header.z_offset) / merged_header.z_scale_factor) < smallest_int )
  {
    merged_header.z_scale_factor = 0.0000001;
    // re-check z offset and z scale
    if (((merged_header.max_z - merged_header.z_offset) / merged_header.z_scale_factor) > largest_int ||
        ((merged_header.min_z - merged_header.z_offset) / merged_header.z_scale_factor) < smallest_int )
    {
      merged_header.z_scale_factor *= 10;
    }
    fprintf(stderr, "z_scale_factor of merged_header changed to %g\n", merged_header.z_scale_factor);
  }
  

  // quit if no output specified

  if (file_name_out == 0 && !olas && !olaz)
  {
    fprintf(stderr, "no output specified. exiting ...\n");
    exit(1);
  }

  // open output file

  int compression = 0;

  FILE* file_out;
  if (file_name_out)
  {
    file_out = fopen(file_name_out, "wb");
    if (strstr(file_name_out, ".laz") || strstr(file_name_out, ".las.lz"))
    {
      compression = 1;
    }
  }
  else if (olas || olaz)
  {
    file_out = stdout;
    if (olaz)
    {
      compression = 1;
    }
  }
  else
  {
    fprintf (stderr, "ERROR: no output specified\n");
    usage();
  }

  // create the writer

  LASwriter* laswriter = new LASwriter();

  if (laswriter->open(file_out, &merged_header, compression) == false)
  {
    fprintf(stderr, "ERROR: could not open laswriter\n");
    exit(1);
  }

  if (verbose) ptime("starting second pass.");
  fprintf(stderr, "second pass ... merge %d LAS files into one ...\n", num_file_name_in);

  for (i = 0; i < num_file_name_in; i++)
  {
    FILE* file_in;
    if (strstr(file_names_in[i], ".gz"))
    {
#ifdef _WIN32
      file_in = fopenGzipped(file_names_in[i], "rb");
#else
      fprintf(stderr, "ERROR: no support for gzipped input\n");
      exit(1);
#endif
    }
    else
    {
      file_in = fopen(file_names_in[i], "rb");
    }
    if (file_in == 0)
    {
      fprintf(stderr, "ERROR: could not open '%s'\n",file_names_in[i]);
      usage();
    }

    LASreader* lasreader = new LASreader();

    if (lasreader->open(file_in, i != 0) == false)
    {
      fprintf(stderr, "ERROR: could not open lasreader\n");
      exit(1);
    }

    if (i == 0)
    {
      // copy variable header (and user data) from the first file
      for (unsigned int u = lasreader->header.header_size; u < lasreader->header.offset_to_point_data; u++)
      {
        fputc(fgetc(file_in),file_out);
      }
    }

    // do reader and writer have the same point transformation
    bool same = true;
    if (merged_header.x_offset != lasreader->header.x_offset) same = false;
    if (merged_header.y_offset != lasreader->header.y_offset) same = false;
    if (merged_header.z_offset != lasreader->header.z_offset) same = false;
    if (merged_header.x_scale_factor != lasreader->header.x_scale_factor) same = false;
    if (merged_header.y_scale_factor != lasreader->header.y_scale_factor) same = false;
    if (merged_header.z_scale_factor != lasreader->header.z_scale_factor) same = false;

    if (same)
    {
      while (lasreader->read_point())
      {
        laswriter->write_point(&(lasreader->point), lasreader->gps_time);
      }
    }
    else
    {
      double xyz[3];
      while (lasreader->read_point(xyz))
      {
			  lasreader->point.x = (int)(0.5 + (xyz[0] - merged_header.x_offset) / merged_header.x_scale_factor);
			  lasreader->point.y = (int)(0.5 + (xyz[1] - merged_header.y_offset) / merged_header.y_scale_factor);
			  lasreader->point.z = (int)(0.5 + (xyz[2] - merged_header.z_offset) / merged_header.z_scale_factor);
        laswriter->write_point(&(lasreader->point), lasreader->gps_time);
      }
    }

    lasreader->close();
    fclose(file_in);
  }

  laswriter->close();
  fclose(file_out);

  if (verbose) ptime("done.");

  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -