Exemple #1
0
int main(int argc, char *argv[])
{
  MPI_Init(&argc, &argv);
  int i;
#ifdef COMPILE_WITH_GUI
  bool gui = false;
#endif
  bool verbose = false;
  bool keep_lastiling = false;
  U32 chopchop = 0;
  bool projection_was_set = false;
  double start_time = 0;

  LASreadOpener lasreadopener;
  GeoProjectionConverter geoprojectionconverter;
  LASwriteOpener laswriteopener;

  if (argc == 1)
  {
#ifdef COMPILE_WITH_GUI
    return lasmerge_gui(argc, argv, 0);
#else
    fprintf(stderr,"%s is better run in the command line\n", argv[0]);
    char file_name[256];
    fprintf(stderr,"enter input file 1: "); fgets(file_name, 256, stdin);
    file_name[strlen(file_name)-1] = '\0';
    lasreadopener.add_file_name(file_name);
    fprintf(stderr,"enter input file 2: "); fgets(file_name, 256, stdin);
    file_name[strlen(file_name)-1] = '\0';
    lasreadopener.add_file_name(file_name);
    fprintf(stderr,"enter output file: "); fgets(file_name, 256, stdin);
    file_name[strlen(file_name)-1] = '\0';
    laswriteopener.set_file_name(file_name);
#endif
  }
  else
  {
    for (i = 1; i < argc; i++)
    {
      if (argv[i][0] == '�') argv[i][0] = '-';
    }


    if (!geoprojectionconverter.parse(argc, argv)) byebye(true);
    if (!lasreadopener.parse(argc, argv)) byebye(true);
    if (lasreadopener.get_file_name_number()<2)
    {
      fprintf(stderr,"Must specify more than one input file.\n");
      byebye(true); // only support merging more than one file
    }
    if (!laswriteopener.parse(argc, argv)) byebye(true);
  }

  for (i = 1; i < argc; i++)
  {
    if (argv[i][0] == '\0')
    {
      continue;
    }
    else if (strcmp(argv[i],"-h") == 0 || strcmp(argv[i],"-help") == 0)
    {
      fprintf(stderr, "LAStools (by [email protected]) version %d\n", LAS_TOOLS_VERSION);
      usage();
    }
    else if (strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"-verbose") == 0)
    {
      verbose = true;
    }
    else if (strcmp(argv[i],"-version") == 0)
    {
      fprintf(stderr, "LAStools (by [email protected]) version %d\n", LAS_TOOLS_VERSION);
      byebye();
    }
    else if (strcmp(argv[i],"-gui") == 0)
    {
#ifdef COMPILE_WITH_GUI
      gui = true;
#else
      fprintf(stderr, "WARNING: not compiled with GUI support. ignoring '-gui' ...\n");
#endif
    }
    else if (strcmp(argv[i],"-split") == 0)
    {
      if ((i+1) >= argc)
      {
        fprintf(stderr,"ERROR: '%s' needs 1 argument: size\n", argv[i]);
        byebye(true);
      }
      i++;
      chopchop = atoi(argv[i]);
    }
    else if (strcmp(argv[i],"-keep_lastiling") == 0)
    {
      keep_lastiling = true;
    }
    else if ((argv[i][0] != '-') && (lasreadopener.get_file_name_number() == 0))
    {
      lasreadopener.add_file_name(argv[i]);
      argv[i][0] = '\0';
    }
    else
    {
      fprintf(stderr, "ERROR: cannot understand argument '%s'\n", argv[i]);
      byebye(true);
    }
  }

#ifdef COMPILE_WITH_GUI
  if (gui)
  {
    return lasmerge_gui(argc, argv, &lasreadopener);
  }
#endif

  // read all the input files merged

  lasreadopener.set_merged(TRUE);

  // maybe we want to keep the lastiling 

  if (keep_lastiling)
  {
    lasreadopener.set_keep_lastiling(TRUE);
  }

  // we need to precompute the bounding box

  lasreadopener.set_populate_header(TRUE);

  // check input and output

  if (!lasreadopener.active())
  {
    fprintf(stderr, "ERROR: no input specified\n");
    byebye(true, argc==1);
  }

  if (!laswriteopener.active())
  {
    fprintf(stderr, "ERROR: no output specified\n");
    byebye(true, argc==1);
  }

  // make sure we do not corrupt the input file

  if (lasreadopener.get_file_name() && laswriteopener.get_file_name() && (strcmp(lasreadopener.get_file_name(), laswriteopener.get_file_name()) == 0))
  {
    fprintf(stderr, "ERROR: input and output file name are identical\n");
    usage(true);
  }

  // check if projection info was set in the command line

  int number_of_keys;
  GeoProjectionGeoKeys* geo_keys = 0;
  int num_geo_double_params;
  double* geo_double_params = 0;

  if (geoprojectionconverter.has_projection())
  {
    projection_was_set = geoprojectionconverter.get_geo_keys_from_projection(number_of_keys, &geo_keys, num_geo_double_params, &geo_double_params);
  }

  if (verbose) start_time = taketime();

  LASreader* lasreader = lasreadopener.open();
  lasreader->populate_rank_points();
  LASreaderMerged *lasreadermerged = (LASreaderMerged *)lasreader;
  I32 process_count = lasreadermerged->get_process_count();

  dbg(3, "rank %i, lasreadermerged->npoints %lli", lasreadermerged->get_rank(), lasreadermerged->npoints);
  for (i=0; i<process_count; i++)
  {
    dbg(3, "rank %i, rank_begin_point %lli", lasreadermerged->get_rank(), lasreadermerged->get_rank_begin_index()[i]);
    for(int j=lasreadermerged->get_file_name_start(); j< lasreadermerged->get_file_name_number(); j++)
    {
      dbg(3, "rank %i, number %i name %s count %lli, begin", lasreadermerged->get_rank(), j, lasreadermerged->get_file_names()[j], lasreadermerged->get_file_point_counts()[j]);
    }


  }
  dbg(3,"type of reader returned: class %s and declared name %s", typeid(*lasreader).name(), quote(*lasreader));


  if (lasreader == 0)
  {
    fprintf(stderr, "ERROR: could not open lasreader\n");
    byebye(true, argc==1);
  }

#ifdef _WIN32
  if (verbose) { fprintf(stderr,"merging headers took %g sec. there are %I64d points in total.\n", taketime()-start_time, lasreader->npoints); start_time = taketime(); }
#else
  if (verbose) { fprintf(stderr,"merging headers took %g sec. there are %lld points in total.\n", taketime()-start_time, lasreader->npoints); start_time = taketime(); }
#endif

  // prepare the header for the surviving points

  strncpy(lasreader->header.system_identifier, "LAStools (c) by rapidlasso GmbH", 32);
  lasreader->header.system_identifier[31] = '\0';
  char temp[64];
  sprintf(temp, "lasmerge (version %d)", LAS_TOOLS_VERSION);
  strncpy(lasreader->header.generating_software, temp, 32);
  lasreader->header.generating_software[31] = '\0';

  if (projection_was_set)
  {
    lasreader->header.set_geo_keys(number_of_keys, (LASvlr_key_entry*)geo_keys);
    free(geo_keys);
    if (geo_double_params)
    {
      lasreader->header.set_geo_double_params(num_geo_double_params, geo_double_params);
      free(geo_double_params);
    }
    else
    {
      lasreader->header.del_geo_double_params();
    }
    lasreader->header.del_geo_ascii_params();
  }

  if (chopchop)
  {
    I32 file_number = 0;
    LASwriter* laswriter = 0;
    // loop over the points
    while (lasreader->read_point())
    {
      if (laswriter == 0)
      {
        // open the next writer
        laswriteopener.make_file_name(0, file_number);
        file_number++;
        laswriter = laswriteopener.open(&lasreader->header);
      }
      laswriter->write_point(&lasreader->point);
      laswriter->update_inventory(&lasreader->point);
      if (laswriter->p_count == chopchop)
      {
        // close the current writer
        laswriter->update_header(&lasreader->header, TRUE);
        laswriter->close();
        if (verbose) { fprintf(stderr,"splitting file '%s' took %g sec.\n", laswriteopener.get_file_name(), taketime()-start_time); start_time = taketime(); }
        delete laswriter;
        laswriter = 0;
      }
    }
    if (laswriter && laswriter->p_count)
    {
      // close the current writer
      laswriter->update_header(&lasreader->header, TRUE);
      laswriter->close();
      if (verbose) { fprintf(stderr,"splitting file '%s' took %g sec.\n", laswriteopener.get_file_name(), taketime()-start_time); start_time = taketime(); }
      delete laswriter;
      laswriter = 0;
    }
  }
  else
  {
    // wait for all processes to open their input files
    MPI_Barrier(MPI_COMM_WORLD);

    // all processes open a writer
    LASwriter* laswriter = laswriteopener.open (&lasreader->header);

    // set the write file pointer... no filter support, assumes all input file's points are written to output file
    //ByteStreamOutFileLE *bs = (ByteStreamOutFileLE*) laswriter->get_stream ();  <-- this is the ByteStreamOut type for las files
    ByteStreamOut *bs = laswriter->get_stream ();

    I64 begin_index = (lasreadermerged->get_rank_begin_index())[lasreadermerged->get_rank ()];

    bs->seek (lasreader->header.point_data_record_length * begin_index + lasreader->header.offset_to_point_data);

    if (laswriter == 0)
    {
      fprintf (stderr, "ERROR: could not open laswriter\n");
      byebye (true, argc == 1);
    }

    // wait for all processes to open the output file and set their write file pointers.
    MPI_Barrier(MPI_COMM_WORLD);
    // loop over the points
    while (lasreader->read_point())
    {
      laswriter->write_point(&lasreader->point);
      laswriter->update_inventory(&lasreader->point);
    }

    int rank = lasreadermerged->get_rank();
    if(rank!=0)
    {
      laswriter->close(FALSE);
    }

    MPI_Barrier(MPI_COMM_WORLD); // not needed since reduce causes barrier, used for testing
    // this whole MPI_Reduce section is not technically needed since we don't yet support point filtering,
    // It was implemented now to ensure that it will work when point filtering of input files is supported
    MPI_Reduce(&(laswriter->inventory.extended_number_of_point_records), &extended_number_of_point_records, 1,
               MPI_LONG_LONG_INT,  MPI_SUM, 0, MPI_COMM_WORLD);
    int i;
    for(i=0; i<16; i++)
    {
      MPI_Reduce(&(laswriter->inventory.extended_number_of_points_by_return[i]), &extended_number_of_points_by_return[i], 1,
                     MPI_LONG_LONG_INT,  MPI_SUM, 0, MPI_COMM_WORLD);
    }
    MPI_Reduce(&(laswriter->inventory.max_X), &max_X, 1, MPI_INT,  MPI_MAX, 0, MPI_COMM_WORLD);
    MPI_Reduce(&(laswriter->inventory.min_X), &min_X, 1, MPI_INT,  MPI_MIN, 0, MPI_COMM_WORLD);
    MPI_Reduce(&(laswriter->inventory.max_Y), &max_Y, 1, MPI_INT,  MPI_MAX, 0, MPI_COMM_WORLD);
    MPI_Reduce(&(laswriter->inventory.min_Y), &min_Y, 1, MPI_INT,  MPI_MIN, 0, MPI_COMM_WORLD);
    MPI_Reduce(&(laswriter->inventory.max_Z), &max_Z, 1, MPI_INT,  MPI_MAX, 0, MPI_COMM_WORLD);
    MPI_Reduce(&(laswriter->inventory.min_Z), &min_Z, 1, MPI_INT,  MPI_MIN, 0, MPI_COMM_WORLD);

    if(rank==0)
    {
      dbg(3, "extended_number_of_point_records %lli", extended_number_of_point_records);
      laswriter->inventory.extended_number_of_point_records = extended_number_of_point_records;
      for(i=0; i<16; i++)
      {
        laswriter->inventory.extended_number_of_points_by_return[i] = extended_number_of_points_by_return[i];
      }
      laswriter->inventory.max_X = max_X;
      laswriter->inventory.min_X = min_X;
      laswriter->inventory.max_Y = max_Y;
      laswriter->inventory.min_Y = min_Y;
      laswriter->inventory.max_Z = max_Z;
      laswriter->inventory.min_Z = min_Z;
    }

    dbg(3, "rank %i, point data record length %i", lasreadermerged->get_rank(), lasreader->header.point_data_record_length);

    // close the writer
    if(rank==0)
    {
      // update header should only be called with TRUE when using the MPI_Reduce calls above,
      // lasreadopener.open(), called above, generates a correct header for the output file, provided no points are filtered during the read
      laswriter->update_header(&lasreader->header, TRUE);
      laswriter->close(FALSE);
    }

    if (verbose) fprintf(stderr,"merging files took %g sec.\n", taketime()-start_time); 
    delete laswriter;
  }
  MPI_Finalize();
  lasreader->close();
  delete lasreader;

  byebye(false, argc==1);

  return 0;
}
Exemple #2
0
BOOL LASindex::append(const char* file_name) const
{
#ifdef LASZIPDLL_EXPORTS
    return FALSE;
#else
    LASreadOpener lasreadopener;

    if (file_name == 0) return FALSE;

    // open reader

    LASreader* lasreader = lasreadopener.open(file_name);
    if (lasreader == 0) return FALSE;
    if (lasreader->header.laszip == 0) return FALSE;

    // close reader

    lasreader->close();

    FILE* file = fopen(file_name, "rb");
    ByteStreamIn* bytestreamin = 0;
    if (IS_LITTLE_ENDIAN())
        bytestreamin = new ByteStreamInFileLE(file);
    else
        bytestreamin = new ByteStreamInFileBE(file);

    // maybe write LASindex EVLR start position into LASzip VLR

    I64 offset_laz_vlr = -1;

    // where to write LASindex EVLR that will contain the LAX file

    I64 number_of_special_evlrs = lasreader->header.laszip->number_of_special_evlrs;
    I64 offset_to_special_evlrs = lasreader->header.laszip->offset_to_special_evlrs;

    if ((number_of_special_evlrs == -1) && (offset_to_special_evlrs == -1))
    {
        bytestreamin->seekEnd();
        number_of_special_evlrs = 1;
        offset_to_special_evlrs = bytestreamin->tell();

        // find LASzip VLR

        I64 total = lasreader->header.header_size + 2;
        U32 number_of_variable_length_records = lasreader->header.number_of_variable_length_records + 1 + (lasreader->header.vlr_lastiling != 0) + (lasreader->header.vlr_lasoriginal != 0);

        for (U32 u = 0; u < number_of_variable_length_records; u++)
        {
            bytestreamin->seek(total);

            CHAR user_id[16];
            try {
                bytestreamin->getBytes((U8*)user_id, 16);
            }
            catch(...)
            {
                fprintf(stderr,"ERROR: reading header.vlrs[%d].user_id\n", u);
                return FALSE;
            }
            if (strcmp(user_id, "laszip encoded") == 0)
            {
                offset_laz_vlr = bytestreamin->tell() - 18;
                break;
            }
            U16 record_id;
            try {
                bytestreamin->get16bitsLE((U8*)&record_id);
            }
            catch(...)
            {
                fprintf(stderr,"ERROR: reading header.vlrs[%d].record_id\n", u);
                return FALSE;
            }
            U16 record_length_after_header;
            try {
                bytestreamin->get16bitsLE((U8*)&record_length_after_header);
            }
            catch(...)
            {
                fprintf(stderr,"ERROR: reading header.vlrs[%d].record_length_after_header\n", u);
                return FALSE;
            }
            total += (54 + record_length_after_header);
        }

        if (number_of_special_evlrs == -1) return FALSE;
    }

    delete bytestreamin;
    fclose(file);

    ByteStreamOut* bytestreamout;
    file = fopen(file_name, "rb+");
    if (IS_LITTLE_ENDIAN())
        bytestreamout = new ByteStreamOutFileLE(file);
    else
        bytestreamout = new ByteStreamOutFileBE(file);
    bytestreamout->seek(offset_to_special_evlrs);

    LASevlr lax_evlr;
    sprintf(lax_evlr.user_id, "LAStools");
    lax_evlr.record_id = 30;
    sprintf(lax_evlr.description, "LAX spatial indexing (LASindex)");

    bytestreamout->put16bitsLE((U8*)&(lax_evlr.reserved));
    bytestreamout->putBytes((U8*)lax_evlr.user_id, 16);
    bytestreamout->put16bitsLE((U8*)&(lax_evlr.record_id));
    bytestreamout->put64bitsLE((U8*)&(lax_evlr.record_length_after_header));
    bytestreamout->putBytes((U8*)lax_evlr.description, 32);

    if (!write(bytestreamout))
    {
        fprintf(stderr,"ERROR (LASindex): cannot append LAX to '%s'\n", file_name);
        delete bytestreamout;
        fclose(file);
        delete lasreader;
        return FALSE;
    }

    // update LASindex EVLR

    lax_evlr.record_length_after_header = bytestreamout->tell() - offset_to_special_evlrs - 60;
    bytestreamout->seek(offset_to_special_evlrs + 20);
    bytestreamout->put64bitsLE((U8*)&(lax_evlr.record_length_after_header));

    // maybe update LASzip VLR

    if (number_of_special_evlrs != -1)
    {
        bytestreamout->seek(offset_laz_vlr + 54 + 16);
        bytestreamout->put64bitsLE((U8*)&number_of_special_evlrs);
        bytestreamout->put64bitsLE((U8*)&offset_to_special_evlrs);
    }

    // close writer

    bytestreamout->seekEnd();
    delete bytestreamout;
    fclose(file);

    // delete reader

    delete lasreader;

    return TRUE;
#endif
}