Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

154 lines
4.3 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2023, Lutra Consulting Ltd. and Hobu, Inc. *
* *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
****************************************************************************/
#include "alg.hpp"
#include "utils.hpp"
#include "vpc.hpp"
#include <thread>
#include <pdal/QuickInfo.hpp>
2023-04-12 08:41:16 +03:00
#include <pdal/util/Bounds.hpp>
using namespace pdal;
bool runAlg(std::vector<std::string> args, Alg &alg)
{
try
{
if ( !alg.parseArgs(args) )
return false;
}
catch (const pdal::arg_error& err)
{
std::cerr << "Failed to parse arguments: " << err.what() << std::endl;
return false;
}
if (alg.hasSingleInput)
{
if (ends_with(alg.inputFile, ".vpc"))
{
VirtualPointCloud vpc;
if (!vpc.read(alg.inputFile))
return false;
2023-05-31 18:13:56 +03:00
alg.totalPoints = vpc.totalPoints();
alg.bounds = vpc.box3d();
if (!alg.needsSingleCrs)
alg.crs = SpatialReference(vpc.crsWkt);
if (alg.needsSingleCrs && vpc.crsWkt == "_mix_")
{
std::cerr << "Algorithm requires that all inputs are in the same CRS. Please transform them to a single CRS first." << std::endl;
return false;
}
}
else
{
QuickInfo qi = getQuickInfo(alg.inputFile);
2023-05-31 18:13:56 +03:00
alg.totalPoints = qi.m_pointCount;
alg.bounds = qi.m_bounds;
alg.crs = qi.m_srs;
}
}
std::vector<std::unique_ptr<PipelineManager>> pipelines;
2023-05-31 18:13:56 +03:00
alg.preparePipelines(pipelines);
if (pipelines.empty())
return false;
2023-05-31 18:13:56 +03:00
runPipelineParallel(alg.totalPoints, alg.isStreaming, pipelines, alg.max_threads, alg.verbose);
alg.finalize(pipelines);
return true;
}
bool Alg::parseArgs(std::vector<std::string> args)
2023-04-12 08:41:16 +03:00
{
pdal::Arg* argInput = nullptr;
if (hasSingleInput)
{
argInput = &programArgs.add("input,i", "Input point cloud file", inputFile);
}
2023-04-06 17:28:16 +10:00
(void)programArgs.add("filter,f", "Filter expression for input data", filterExpression);
2023-04-12 08:41:16 +03:00
(void)programArgs.add("bounds", "Filter by rectangle", filterBounds);
addArgs(); // impl in derived
// 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);
}
catch(pdal::arg_error err)
{
std::cerr << "failed to parse arguments: " << err.what() << std::endl;
return false;
}
// TODO: ProgramArgs does not support required options
if (argInput && !argInput->set())
{
std::cerr << "missing input" << std::endl;
return false;
}
2023-04-12 08:41:16 +03:00
if (!filterBounds.empty())
{
try
{
parseBounds(filterBounds);
}
2023-04-14 07:31:24 +10:00
catch (pdal::Bounds::error& err)
2023-04-12 08:41:16 +03:00
{
std::cerr << "invalid bounds: " << err.what() << std::endl;
return false;
}
}
if (!checkArgs()) // impl in derived class
return false;
if (!args.empty())
{
std::cerr << "unexpected args!" << std::endl;
for ( auto & a : args )
std::cerr << " - " << a << std::endl;
return false;
}
if (!argThreads.set()) // in such case our value is reset to zero
{
// use number of cores if not specified by the user
max_threads = std::thread::hardware_concurrency();
if (max_threads == 0)
{
// in case the value can't be detected, use something reasonable...
max_threads = 4;
}
}
return true;
}