update pdal_wrench to the latest revision

This commit is contained in:
Alexander Bruy 2023-03-20 18:18:21 +02:00 committed by Martin Dobias
parent ed1378b527
commit c6d8e410a9
13 changed files with 112 additions and 257 deletions

View File

@ -70,7 +70,7 @@ bool runAlg(std::vector<std::string> args, Alg &alg)
if (pipelines.empty())
return false;
runPipelineParallel(totalPoints, alg.isStreaming, pipelines, alg.max_threads);
runPipelineParallel(totalPoints, alg.isStreaming, pipelines, alg.max_threads, alg.verbose);
alg.finalize(pipelines);
@ -93,6 +93,8 @@ bool Alg::parseArgs(std::vector<std::string> args)
// parallel run support (generic)
pdal::Arg& argThreads = programArgs.add("threads", "Max number of concurrent threads for parallel runs", max_threads);
programArgs.add("verbose", "Print extra debugging output", verbose);
try
{
programArgs.parseSimple(args);
@ -115,9 +117,9 @@ bool Alg::parseArgs(std::vector<std::string> args)
if (!args.empty())
{
std::cout << "unexpected args!" << std::endl;
std::cerr << "unexpected args!" << std::endl;
for ( auto & a : args )
std::cout << " - " << a << std::endl;
std::cerr << " - " << a << std::endl;
return false;
}

View File

@ -45,6 +45,8 @@ struct Alg
bool needsSingleCrs = true; // most algs assume that all input files in VPC are in the same CRS,
// and only few exceptions (e.g. info) tolerate mixture of multiple CRS
bool verbose = false; // write extra debugging output from the algorithm
pdal::ProgramArgs programArgs;
Alg() = default;
@ -99,6 +101,7 @@ struct Translate : public Alg
std::string outputFile;
std::string assignCrs;
std::string transformCrs;
std::string transformCoordOp;
std::string outputFormat; // las / laz / copc
// args - initialized in addArgs()
@ -147,9 +150,13 @@ struct Boundary : public Alg
{
// parameters from the user
std::string outputFile;
double resolution = 0; // cell size of the hexbin filter (if zero, it will be estimated by PDAL)
int pointsThreshold = 0; // min. number of points in order to have a cell considered occupied
// args - initialized in addArgs()
pdal::Arg* argOutput = nullptr;
pdal::Arg* argResolution = nullptr;
pdal::Arg* argPointsThreshold = nullptr;
// impl
virtual void addArgs() override;

View File

@ -31,6 +31,10 @@ using namespace pdal;
void Boundary::addArgs()
{
argOutput = &programArgs.add("output,o", "Output vector file", outputFile);
argResolution = &programArgs.add("resolution", "Resolution of cells used to calculate boundary. "
"If not specified, it will be estimated from first 5000 points.", resolution);
argPointsThreshold = &programArgs.add("threshold", "Minimal number of points in a cell to consider cell occupied.", pointsThreshold);
}
bool Boundary::checkArgs()
@ -40,10 +44,22 @@ bool Boundary::checkArgs()
std::cerr << "missing output" << std::endl;
return false;
}
if (!argResolution->set() && argPointsThreshold->set())
{
std::cerr << "Resolution argument must be set when points threshold is set." << std::endl;
return false;
}
if (!argPointsThreshold->set())
{
pointsThreshold = 15; // the same default as in PDAL for HexBin filter
}
return true;
}
static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile)
static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile, double resolution, int pointsThreshold)
{
assert(tile);
assert(tile->inputFilenames.size() == 1);
@ -57,8 +73,11 @@ static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile)
// btw. if threshold=0, there are still missing points because of simplification (smooth=True)
pdal::Options hexbin_opts;
hexbin_opts.add(pdal::Option("edge_size", 5));
hexbin_opts.add(pdal::Option("threshold", 0));
if (resolution != 0)
{
hexbin_opts.add(pdal::Option("edge_size", resolution));
}
hexbin_opts.add(pdal::Option("threshold", pointsThreshold));
if (!tile->filterExpression.empty())
{
@ -82,14 +101,14 @@ void Boundary::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& p
{
ParallelJobInfo tile(ParallelJobInfo::FileBased, BOX2D(), filterExpression);
tile.inputFilenames.push_back(f.filename);
pipelines.push_back(pipeline(&tile));
pipelines.push_back(pipeline(&tile, resolution, pointsThreshold));
}
}
else
{
ParallelJobInfo tile(ParallelJobInfo::Single, BOX2D(), filterExpression);
tile.inputFilenames.push_back(inputFile);
pipelines.push_back(pipeline(&tile));
pipelines.push_back(pipeline(&tile, resolution, pointsThreshold));
}
}
@ -123,21 +142,21 @@ void Boundary::finalize(std::vector<std::unique_ptr<PipelineManager>>& pipelines
OGRSFDriverH hDriver = OGRGetDriverByName("GPKG");
if (hDriver == nullptr)
{
std::cout << "failed to create GPKG driver" << std::endl;
std::cerr << "Failed to create GPKG driver" << std::endl;
return;
}
GDALDatasetH hDS = GDALCreate( hDriver, outputFile.c_str(), 0, 0, 0, GDT_Unknown, nullptr );
if (hDS == nullptr)
{
std::cout << "failed to create output file: " << outputFile << std::endl;
std::cerr << "Failed to create output file: " << outputFile << std::endl;
return;
}
OGRLayerH hLayer = GDALDatasetCreateLayer( hDS, "boundary", hSrs, wkbType, nullptr );
if (hLayer == nullptr)
{
std::cout << "failed to create layer in the output file: " << outputFile << std::endl;
std::cerr << "Failed to create layer in the output file: " << outputFile << std::endl;
return;
}
@ -152,16 +171,16 @@ void Boundary::finalize(std::vector<std::unique_ptr<PipelineManager>>& pipelines
char *wkt_ptr = wkt.data();
if (OGR_G_CreateFromWkt(&wkt_ptr, hSrs, &geom) != OGRERR_NONE)
{
std::cout << "Failed to parse geometry: " << wkt << std::endl;
std::cerr << "Failed to parse geometry: " << wkt << std::endl;
}
OGRFeatureH hFeature = OGR_F_Create(OGR_L_GetLayerDefn(hLayer));
if (OGR_F_SetGeometry(hFeature, geom) != OGRERR_NONE)
{
std::cout << "couldn't set geometry " << wkt << std::endl;
std::cerr << "Could not set geometry " << wkt << std::endl;
}
if (OGR_L_CreateFeature(hLayer, hFeature) != OGRERR_NONE)
{
std::cout << "failed to create a new feature in the output file!" << std::endl;
std::cerr << "Failed to create a new feature in the output file!" << std::endl;
}
OGR_F_Destroy(hFeature);

View File

@ -74,7 +74,7 @@ bool loadPolygons(const std::string &polygonFile, pdal::Options& crop_opts, BOX2
GDALDatasetH hDS = GDALOpenEx( polygonFile.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL );
if( hDS == NULL )
{
std::cout << "cannot open polygon " << polygonFile << std::endl;
std::cerr << "Could not open input polygon file: " << polygonFile << std::endl;
return false;
}
@ -148,7 +148,7 @@ void Clip::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& pipel
{
if (!ends_with(outputFile, ".vpc"))
{
std::cout << "output should be VPC too" << std::endl;
std::cerr << "If input file is a VPC, output should be VPC too." << std::endl;
return;
}
@ -167,11 +167,13 @@ void Clip::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& pipel
if (!bbox.overlaps(f.bbox.to2d()))
{
totalPoints -= f.count;
//std::cout << "skipping " << f.filename << std::endl;
continue; // we can safely skip
}
std::cout << "using " << f.filename << std::endl;
if (verbose)
{
std::cout << "using " << f.filename << std::endl;
}
ParallelJobInfo tile(ParallelJobInfo::FileBased, BOX2D(), filterExpression);
tile.inputFilenames.push_back(f.filename);

View File

@ -198,10 +198,10 @@ void Density::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& pi
if (unalignedFiles)
{
std::cout << std::endl;
std::cout << "Warning: input files not perfectly aligned with tile grid - processing may take longer." << std::endl;
std::cout << "Consider using --tile-size, --tile-origin-x, --tile-origin-y arguments" << std::endl;
std::cout << std::endl;
std::cerr << std::endl;
std::cerr << "Warning: input files not perfectly aligned with tile grid - processing may take longer." << std::endl;
std::cerr << "Consider using --tile-size, --tile-origin-x, --tile-origin-y arguments" << std::endl;
std::cerr << std::endl;
}
}
else if (ends_with(inputFile, ".copc.laz"))

View File

@ -32,7 +32,6 @@ extern int runTile(std::vector<std::string> arglist); // tile/tile.cpp
int main(int argc, char* argv[])
//#endif
{
#if 1
if (argc < 2)
{
std::cerr << "need to specify command:" << std::endl;
@ -56,208 +55,6 @@ int main(int argc, char* argv[])
std::vector<std::string> args;
for ( int i = 2; i < argc; ++i )
args.push_back(argv[i]);
#elif 0
std::string cmd = "density";
std::vector<std::string> args;
// args.push_back("-i");
// args.push_back("/home/martin/qgis/point-cloud-sandbox/data/24-fixed.las");
// args.push_back("-o");
// args.push_back("/tmp/dens.tif");
// args.push_back("-r");
// args.push_back("1");
//args.push_back("xxx");
args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/merged.copc.laz");
args.push_back("--output=/tmp/densX.tif");
args.push_back("--resolution=1");
args.push_back("--tile-size=250");
args.push_back("--tile-origin-x=0");
args.push_back("--tile-origin-y=0");
args.push_back("--threads=4");
#elif 0
std::string cmd = "boundary";
std::vector<std::string> args;
args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/24-fixed.las");
//args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/merged.copc.laz"); // TODO: empty boundary???
args.push_back("--output=/tmp/boundary.gpkg");
//args.push_back("--resolution=1");
//args.push_back("--tile-size=250");
//args.push_back("--threads=4");
//args.push_back("--filter=Classification==5");
#elif 0
std::string cmd = "clip";
std::vector<std::string> args;
args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/24-fixed.las");
args.push_back("--polygon=/home/martin/qgis/point-cloud-sandbox/data/24-polygon.gpkg");
args.push_back("--output=/tmp/clipped.las");
//args.push_back("--filter=Classification==5");
#elif 0
std::string cmd = "build_vpc";
std::vector<std::string> args;
args.push_back("--output=/tmp/tatry-9.vpc");
args.push_back("/home/martin/tatry-tiles/tatry_0_1.laz");
args.push_back("/home/martin/tatry-tiles/tatry_0_2.laz");
args.push_back("/home/martin/tatry-tiles/tatry_0_3.laz");
args.push_back("/home/martin/tatry-tiles/tatry_1_1.laz");
args.push_back("/home/martin/tatry-tiles/tatry_1_2.laz");
args.push_back("/home/martin/tatry-tiles/tatry_1_3.laz");
args.push_back("/home/martin/tatry-tiles/tatry_2_1.laz");
args.push_back("/home/martin/tatry-tiles/tatry_2_2.laz");
args.push_back("/home/martin/tatry-tiles/tatry_2_3.laz");
#elif 0
std::string cmd = "clip";
std::vector<std::string> args;
args.push_back("--input=/tmp/tatry-9.vpc");
args.push_back("--polygon=/home/martin/qgis/point-cloud-sandbox/data/tatry.gpkg");
args.push_back("--output=/tmp/tatry-clipped.vpc");
//args.push_back("--output-format=laz");
#elif 0
std::string cmd = "density";
std::vector<std::string> args;
args.push_back("--input=/tmp/first.vpc");
args.push_back("--output=/tmp/first.tif");
args.push_back("--resolution=1");
args.push_back("--threads=4");
//args.push_back("--filter=Classification==2");
// for good alignment of input and output
args.push_back("--tile-origin-x=377250");
args.push_back("--tile-origin-y=5441420");
#elif 0
std::string cmd = "boundary";
std::vector<std::string> args;
args.push_back("--input=/tmp/tatry-9.vpc");
args.push_back("--output=/tmp/tatry-9-boundary.gpkg");
#elif 0
std::string cmd = "merge";
std::vector<std::string> args;
args.push_back("--output=/tmp/merged.las");
args.push_back("/home/martin/qgis/point-cloud-sandbox/data/trencin-2-ground.laz");
args.push_back("/home/martin/qgis/point-cloud-sandbox/data/trencin-6-buildings.laz");
#elif 0
std::string cmd = "to_raster_tin";
std::vector<std::string> args;
args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/trencin-2-ground.laz");
args.push_back("--output=/tmp/raster_tin.tif");
args.push_back("--resolution=1");
#elif 0
std::string cmd = "to_raster";
std::vector<std::string> args;
args.push_back("--input=/tmp/first.vpc");
args.push_back("--output=/tmp/first-dem.tif");
args.push_back("--resolution=1");
args.push_back("--filter=Classification==2");
#elif 0
std::string cmd = "to_raster_tin";
std::vector<std::string> args;
// args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/merged.copc.laz");
// args.push_back("--output=/tmp/merged-tin.tif");
// args.push_back("--resolution=1");
// args.push_back("--tile-size=250");
// args.push_back("--tile-origin-x=0");
// args.push_back("--tile-origin-y=0");
// args.push_back("--threads=1");
args.push_back("--input=/tmp/first.vpc");
args.push_back("--output=/tmp/first-tin.tif");
args.push_back("--resolution=1");
args.push_back("--filter=Classification==2");
args.push_back("--threads=1");
//args.push_back("--tile-size=500");
// for good alignment of input and output
//args.push_back("--tile-origin-x=377250");
//args.push_back("--tile-origin-y=5441420");
#elif 0
std::string cmd = "thin";
std::vector<std::string> args;
args.push_back("--input=/tmp/first.vpc");
// args.push_back("--mode=every-nth");
// args.push_back("--step-every-nth=20");
// args.push_back("--output=/tmp/tatry-thinned.vpc");
args.push_back("--mode=sample");
args.push_back("--step-sample=1");
args.push_back("--output=/tmp/tatry-thinned-sample.vpc");
#elif 0
std::string cmd = "to_vector";
std::vector<std::string> args;
args.push_back("--input=/tmp/first.vpc");
//args.push_back("--step=20");
args.push_back("--output=/tmp/first.gpkg");
#elif 0
std::string cmd = "info";
std::vector<std::string> args;
args.push_back("--input=/tmp/clipped.las");
#elif 0
std::string cmd = "info";
std::vector<std::string> args;
args.push_back("--input=/tmp/tatry-9.vpc");
#elif 0
std::string cmd = "translate";
std::vector<std::string> args;
args.push_back("--input=/home/martin/qgis/point-cloud-sandbox/data/trencin.laz");
args.push_back("--assign-crs=EPSG:5514");
args.push_back("--output=/tmp/trencin-fixed-crs.las");
#elif 0
std::string cmd = "translate";
std::vector<std::string> args;
args.push_back("--input=/tmp/trencin-fixed-crs.las");
args.push_back("--transform-crs=EPSG:3857");
args.push_back("--filter=Classification==2");
args.push_back("--output=/tmp/trencin-3857.las");
#elif 0
std::string cmd = "tile";
std::vector<std::string> args;
//args.push_back("--threads=1");
args.push_back("--length=200");
args.push_back("--output=/tmp/tatry-3-tiled.vpc");
args.push_back("/home/martin/tatry-tiles/tatry_0_1.laz");
//args.push_back("/tmp/first.vpc");
#elif 0
std::string cmd = "build_vpc";
std::vector<std::string> args;
args.push_back("--output=/tmp/nrcan-test.vpc");
args.push_back("https://download-telecharger.services.geo.ca/pub/elevation/pointclouds_nuagespoints/NRCAN/Hamilton_Niagara_2021_2/ON_Niagara_20210525_NAD83CSRS_UTM17N_1km_E567_N4805_CLASS.copc.laz");
args.push_back("https://download-telecharger.services.geo.ca/pub/elevation/pointclouds_nuagespoints/NRCAN/Hamilton_Niagara_2021_2/ON_Niagara_20210525_NAD83CSRS_UTM17N_1km_E567_N4806_CLASS.copc.laz");
args.push_back("https://download-telecharger.services.geo.ca/pub/elevation/pointclouds_nuagespoints/NRCAN/Hamilton_Niagara_2021_2/ON_Niagara_20210525_NAD83CSRS_UTM17N_1km_E567_N4807_CLASS.copc.laz");
#else
std::string cmd = "info";
std::vector<std::string> args;
// compound
//args.push_back("--input=/home/martin/tmp/las/nrcan/ON_LAKE_NIPISSING_20190619_NAD83CSRS_UTMZ17_1KM_E5430_N51090_CLASS.laz");
//args.push_back("--input=/home/martin/tmp/las/autzen/autzen-classified.laz"); // using "US survey foot" as unit
//args.push_back("--input=/home/martin/tmp/las/bergen/data/32-1-468-145-45.laz");
//args.push_back("--input=/home/martin/tmp/las/estonia-nir/467494_2021_tava.laz");
// mixed lat/lon and meters
//args.push_back("--input=/home/martin/tmp/las/noaa/20140208_LA_37_20164901.laz");
// vertical only specifies it is in meters
//args.push_back("--input=/home/martin/tmp/las/fi/L4142G1_7.laz");
//args.push_back("--input=/home/martin/tmp/las/lene/ground.laz");
//args.push_back("--input=https://s3.amazonaws.com/hobu-lidar/montreal-2015.copc.laz");
// missing vertical
//args.push_back("--input=/home/martin/tmp/las/ba-hrad/03_Bratislava_18_214150_5339178_a_c_jtsk03_bpv_clip.las");
//args.push_back("--input=/home/martin/tmp/las/ign/PTS_LAMB93_IGN69_0965_6570.copc.laz");
//args.push_back("--input=/home/martin/tmp/las/Données_MNT_lidar/subset_samp.laz");
//args.push_back("--input=/home/martin/tmp/las/solothurn/2607000_1228000.laz");
// no crs
//args.push_back("--input=/home/martin/tmp/las/fi-helsinki/rgb_673496c.laz");
//args.push_back("--input=/home/martin/tmp/las/sdfe/1km_6210_527.laz");
//args.push_back("--input=https://s3-us-west-2.amazonaws.com/usgs-lidar-public/USGS_LPC_MD_VA_Sandy_NCR_2014_LAS_2015/ept.json");
#endif
std::cout << "command: " << cmd << std::endl;
if (cmd == "density")
{

View File

@ -137,7 +137,7 @@ void Thin::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& pipel
{
if (!ends_with(outputFile, ".vpc"))
{
std::cout << "output should be VPC too" << std::endl;
std::cerr << "If input file is a VPC, output should be VPC too." << std::endl;
return;
}

View File

@ -164,11 +164,14 @@ void ToRaster::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>& p
TileAlignment gridAlignment = tileAlignment;
gridAlignment.tileSize = resolution;
Tiling gridTiling = gridAlignment.coverBounds(bounds.to2d());
std::cout << "grid " << gridTiling.tileCountX << "x" << gridTiling.tileCountY << std::endl;
BOX2D gridBounds = gridTiling.fullBox();
Tiling t = tileAlignment.coverBounds(gridBounds);
std::cout << "tiles " << t.tileCountX << " " << t.tileCountY << std::endl;
if (verbose)
{
std::cout << "grid " << gridTiling.tileCountX << "x" << gridTiling.tileCountY << std::endl;
std::cout << "tiles " << t.tileCountX << " " << t.tileCountY << std::endl;
}
totalPoints = 0; // we need to recalculate as we may use some points multiple times
for (int iy = 0; iy < t.tileCountY; ++iy)

View File

@ -157,11 +157,14 @@ void ToRasterTin::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>
TileAlignment gridAlignment = tileAlignment;
gridAlignment.tileSize = resolution;
Tiling gridTiling = gridAlignment.coverBounds(bounds.to2d());
std::cout << "grid " << gridTiling.tileCountX << "x" << gridTiling.tileCountY << std::endl;
BOX2D gridBounds = gridTiling.fullBox();
Tiling t = tileAlignment.coverBounds(gridBounds);
std::cout << "tiles " << t.tileCountX << " " << t.tileCountY << std::endl;
if (verbose)
{
std::cout << "grid " << gridTiling.tileCountX << "x" << gridTiling.tileCountY << std::endl;
std::cout << "tiles " << t.tileCountX << " " << t.tileCountY << std::endl;
}
totalPoints = 0; // we need to recalculate as we may use some points multiple times
for (int iy = 0; iy < t.tileCountY; ++iy)

View File

@ -36,7 +36,10 @@ void Translate::addArgs()
argOutput = &programArgs.add("output,o", "Output point cloud file", outputFile);
argOutputFormat = &programArgs.add("output-format", "Output format (las/laz/copc)", outputFormat);
programArgs.add("assign-crs", "Assigns CRS to data (no reprojection)", assignCrs);
programArgs.add("transform-crs", "Transforms (reprojects) data to anoter CRS", transformCrs);
programArgs.add("transform-crs", "Transforms (reprojects) data to another CRS", transformCrs);
programArgs.add("transform-coord-op", "Details on how to do the transform of coordinates when --transform-crs is used. "
"It can be a PROJ pipeline or a WKT2 CoordinateOperation. "
"When not specified, PROJ will pick the default transform.", transformCoordOp);
}
bool Translate::checkArgs()
@ -59,11 +62,17 @@ bool Translate::checkArgs()
else
outputFormat = "las"; // uncompressed by default
if (!transformCoordOp.empty() && transformCrs.empty())
{
std::cerr << "Need to specify also --transform-crs when --transform-coord-op is used." << std::endl;
return false;
}
return true;
}
static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile, std::string assignCrs, std::string transformCrs)
static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile, std::string assignCrs, std::string transformCrs, std::string transformCoordOp)
{
std::unique_ptr<PipelineManager> manager( new PipelineManager );
@ -79,7 +88,15 @@ static std::unique_ptr<PipelineManager> pipeline(ParallelJobInfo *tile, std::str
{
Options transform_opts;
transform_opts.add(pdal::Option("out_srs", transformCrs));
reproject = &manager->makeFilter( "filters.reprojection", r, transform_opts);
if (!transformCoordOp.empty())
{
transform_opts.add(pdal::Option("coord_op", transformCoordOp));
reproject = &manager->makeFilter( "filters.projpipeline", r, transform_opts);
}
else
{
reproject = &manager->makeFilter( "filters.reprojection", r, transform_opts);
}
}
pdal::Options writer_opts;
@ -120,7 +137,7 @@ void Translate::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>&
{
if (!ends_with(outputFile, ".vpc"))
{
std::cout << "output should be VPC too" << std::endl;
std::cerr << "If input file is a VPC, output should be VPC too." << std::endl;
return;
}
@ -146,7 +163,7 @@ void Translate::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>&
tileOutputFiles.push_back(tile.outputFilename);
pipelines.push_back(pipeline(&tile, assignCrs, transformCrs));
pipelines.push_back(pipeline(&tile, assignCrs, transformCrs, transformCoordOp));
}
}
else
@ -154,7 +171,7 @@ void Translate::preparePipelines(std::vector<std::unique_ptr<PipelineManager>>&
ParallelJobInfo tile(ParallelJobInfo::Single, BOX2D(), filterExpression);
tile.inputFilenames.push_back(inputFile);
tile.outputFilename = outputFile;
pipelines.push_back(pipeline(&tile, assignCrs, transformCrs));
pipelines.push_back(pipeline(&tile, assignCrs, transformCrs, transformCoordOp));
}
}

View File

@ -57,7 +57,7 @@ QuickInfo getQuickInfo(std::string inputFile)
std::string driver = StageFactory::inferReaderDriver(inputFile);
if (driver.empty())
{
std::cout << "cannot infer driver for: " << inputFile << std::endl;
std::cerr << "Could not infer driver for input file: " << inputFile << std::endl;
return QuickInfo();
}
@ -66,7 +66,6 @@ QuickInfo getQuickInfo(std::string inputFile)
pdal::Options opts;
opts.add("filename", inputFile);
reader->setOptions(opts);
//std::cout << "name " << reader->getName() << std::endl;
return reader->preview();
// PipelineManager m;
@ -90,20 +89,23 @@ MetadataNode getReaderMetadata(std::string inputFile, MetadataNode *pointLayoutM
}
void runPipelineParallel(point_count_t totalPoints, bool isStreaming, std::vector<std::unique_ptr<PipelineManager>>& pipelines, int max_threads)
void runPipelineParallel(point_count_t totalPoints, bool isStreaming, std::vector<std::unique_ptr<PipelineManager>>& pipelines, int max_threads, bool verbose)
{
const int CHUNK_SIZE = 100'000;
int num_chunks = totalPoints / CHUNK_SIZE;
std::cout << "total points: " << (float)totalPoints / 1'000'000 << "M" << std::endl;
if (verbose)
{
std::cout << "total points: " << (float)totalPoints / 1'000'000 << "M" << std::endl;
std::cout << "jobs " << pipelines.size() << std::endl;
std::cout << "max threads " << max_threads << std::endl;
if (!isStreaming)
std::cout << "running in non-streaming mode!" << std::endl;
}
auto start = std::chrono::high_resolution_clock::now();
std::cout << "jobs " << pipelines.size() << std::endl;
std::cout << "max threads " << max_threads << std::endl;
if (!isStreaming)
std::cout << "running in non-streaming mode!" << std::endl;
sProgressBar.init(isStreaming ? num_chunks : pipelines.size());
int nThreads = std::min( (int)pipelines.size(), max_threads );
@ -144,7 +146,10 @@ void runPipelineParallel(point_count_t totalPoints, bool isStreaming, std::vecto
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << "time " << duration.count()/1000. << " s" << std::endl;
if (verbose)
{
std::cout << "time " << duration.count()/1000. << " s" << std::endl;
}
}

View File

@ -221,7 +221,7 @@ QuickInfo getQuickInfo(std::string inputFile);
MetadataNode getReaderMetadata(std::string inputFile, MetadataNode *pointLayoutMeta = nullptr);
void runPipelineParallel(point_count_t totalPoints, bool isStreaming, std::vector<std::unique_ptr<PipelineManager>>& pipelines, int max_threads);
void runPipelineParallel(point_count_t totalPoints, bool isStreaming, std::vector<std::unique_ptr<PipelineManager>>& pipelines, int max_threads, bool verbose);
std::string box_to_pdal_bounds(const BOX2D &box);

View File

@ -52,7 +52,7 @@ bool VirtualPointCloud::read(std::string filename)
std::ifstream inputJson(filename);
if (!inputJson.good())
{
std::cout << "failed to read file " << filename << std::endl;
std::cerr << "Failed to read input VPC file: " << filename << std::endl;
return false;
}
@ -65,17 +65,17 @@ bool VirtualPointCloud::read(std::string filename)
}
catch (std::exception &e)
{
std::cout << "json parsing error: " << e.what() << std::endl;
std::cerr << "JSON parsing error: " << e.what() << std::endl;
return false;
}
if (!data.contains("vpc"))
{
std::cout << "not a VPC file " << filename << std::endl;
std::cerr << "The input file is not a VPC file: " << filename << std::endl;
return false;
}
if (data["vpc"] != "1.0.0")
{
std::cout << "unsupported VPC file version " << data["vpc"] << std::endl;
std::cerr << "Unsupported VPC file version: " << data["vpc"] << std::endl;
return false;
}
@ -108,7 +108,7 @@ bool VirtualPointCloud::write(std::string filename)
std::ofstream outputJson(filename);
if (!outputJson.good())
{
std::cout << "failed to create file" << std::endl;
std::cerr << "Failed to create file: " << filename << std::endl;
return false;
}
@ -157,8 +157,8 @@ void buildVpc(std::vector<std::string> args)
return;
}
std::cout << "input " << inputFiles.size() << std::endl;
std::cout << "output " << outputFile << std::endl;
// std::cout << "input " << inputFiles.size() << std::endl;
// std::cout << "output " << outputFile << std::endl;
if (inputFiles.empty())
{
@ -200,7 +200,7 @@ void buildVpc(std::vector<std::string> args)
}
else
{
std::cout << "found a mixture of multiple CRS in input files (" << vpcCrsWkt.size() << ")" << std::endl;
std::cerr << "found a mixture of multiple CRS in input files (" << vpcCrsWkt.size() << ")" << std::endl;
vpc.crsWkt = "_mix_";
}