Skip to content

Commit

Permalink
untwine pdalprovider integration (#40404)
Browse files Browse the repository at this point in the history
[pointclouds] untwine pdalprovider integration
  • Loading branch information
PeterPetrik committed Dec 15, 2020
1 parent fe96e67 commit 221bd2f
Show file tree
Hide file tree
Showing 70 changed files with 5,376 additions and 84 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Expand Up @@ -408,6 +408,9 @@ if(WITH_CORE)
endif()

if (WITH_PDAL)
if (NOT WITH_EPT)
message(FATAL_ERROR "PDAL provider cannot be built with EPT disabled")
endif()
find_package(PDAL) # PDAL provider
endif()
if (PDAL_FOUND)
Expand Down
674 changes: 674 additions & 0 deletions external/untwine/LICENSE

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions external/untwine/api/QgisTest.cpp
@@ -0,0 +1,54 @@
#ifndef _WIN32
#include <unistd.h>
#endif

#include <iostream>

#include "QgisUntwine.hpp"

int main()
{
untwine::QgisUntwine::StringList files;
untwine::QgisUntwine::Options options;
// std::string exe = "C:\\Users\\andre\\untwine\\build\\untwine.exe";
std::string exe = "/Users/acbell/untwine/build/untwine";

untwine::QgisUntwine api(exe);

// files.push_back("C:\\Users\\andre\\nyc2");
// files.push_back("C:\\Users\\andre\\nyc2\\18TXL075075.las.laz");
// files.push_back("/Users/acbell/nyc/18TXL075075.las.laz");
// files.push_back("/Users/acbell/nyc/18TXL075090.las.laz");
files.push_back("/Users/acbell/nyc2");

options.push_back({"dims", "X, Y, Z, Red, Green, Blue, Intensity"});
// book ok = api.start(files, ".\\out", options);
bool ok = api.start(files, "./out", options);
if (! ok)
{
std::cerr << "Couldn't start '" << exe << "!\n";
exit(-1);
}

bool stopped = false;
while (true)
{
#ifdef _WIN32
Sleep(1000);
#else
::sleep(1);
#endif
int percent = api.progressPercent();
std::string s = api.progressMessage();
std::cerr << "Percent/Msg = " << percent << " / " << s << "!\n";
/**
if (!stopped && percent >= 50)
{
stopped = true;
api.stop();
}
**/
if (!api.running())
break;
}
}
55 changes: 55 additions & 0 deletions external/untwine/api/QgisUntwine.cpp
@@ -0,0 +1,55 @@
#include <iostream>

#include "QgisUntwine.hpp"

#ifdef WIN32
#include "QgisUntwine_win.cpp"
#else
#include "QgisUntwine_unix.cpp"
#endif

namespace untwine
{

QgisUntwine::QgisUntwine(const std::string& untwinePath) : m_path(untwinePath), m_running(false),
m_percent(0)
{}

bool QgisUntwine::start(const StringList& files, const std::string& outputDir,
const Options& argOptions)
{
if (m_running)
return false;

Options options(argOptions);
if (files.size() == 0 || outputDir.empty())
return false;

std::string s;
for (auto ti = files.begin(); ti != files.end(); ++ti)
{
s += *ti;
if (ti + 1 != files.end())
s += ", ";
}
options.push_back({"files", s});
options.push_back({"output_dir", outputDir});

return start(options);
}

int QgisUntwine::progressPercent() const
{
readPipe();

return m_percent;
}

std::string QgisUntwine::progressMessage() const
{
readPipe();

return m_progressMsg;
}

} // namespace untwine
48 changes: 48 additions & 0 deletions external/untwine/api/QgisUntwine.hpp
@@ -0,0 +1,48 @@
#pragma once

#include <map>
#include <string>
#include <vector>

#ifdef _WIN32
#include <Windows.h>
#endif

namespace untwine
{

class QgisUntwine
{
public:
using Option = std::pair<std::string, std::string>;
using Options = std::vector<Option>;
using StringList = std::vector<std::string>;

QgisUntwine(const std::string& untwinePath);

bool start(const StringList& files, const std::string& outputDir,
const Options& argOptions = Options());
bool stop();
bool running();
int progressPercent() const;
std::string progressMessage() const;

private:
std::string m_path;
mutable bool m_running;
mutable int m_percent;
mutable std::string m_progressMsg;
#ifndef _WIN32
pid_t m_pid;
int m_progressFd;
#else
HANDLE m_pid;
HANDLE m_progressFd;
#endif

bool start(Options& options);
void readPipe() const;
void childStopped();
};

} // namespace untwine
141 changes: 141 additions & 0 deletions external/untwine/api/QgisUntwine_unix.cpp
@@ -0,0 +1,141 @@
#include <iostream>

#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/wait.h>

#include "QgisUntwine.hpp"

namespace untwine
{

bool QgisUntwine::start(Options& options)
{
int fd[2];
int ret = ::pipe(fd);

m_pid = ::fork();

// Child
if (m_pid == 0)
{
// Close file descriptors other than the stdin/out/err and our pipe.
// There may be more open than FD_SETSIZE, but meh.
for (int i = STDERR_FILENO + 1; i < FD_SETSIZE; ++i)
if (i != fd[1])
close(i);

// Add the FD for the progress output
options.push_back({"progress_fd", std::to_string(fd[1])});

for (Option& op : options)
op.first = "--" + op.first;

std::vector<const char *> argv;
argv.push_back(m_path.data());
for (const Option& op : options)
{
argv.push_back(op.first.data());
argv.push_back(op.second.data());
}
argv.push_back(nullptr);
if (::execv(m_path.data(), const_cast<char *const *>(argv.data())) != 0)
{
std::cerr << "Couldn't start untwine '" << m_path << "'.\n";
exit(-1);
}
}
// Parent
else
{
close(fd[1]);
m_progressFd = fd[0];
// Don't block attempting to read progress.
::fcntl(m_progressFd, F_SETFL, O_NONBLOCK);
m_running = true;
}
return true;
}

bool QgisUntwine::stop()
{
if (!m_running)
return false;
::kill(m_pid, SIGINT);
(void)waitpid(m_pid, nullptr, 0);
m_pid = 0;
return true;
}

// Called when the child has stopped.
void QgisUntwine::childStopped()
{
m_running = false;
}

bool QgisUntwine::running()
{
if (m_running && (::waitpid(m_pid, nullptr, WNOHANG) != 0))
childStopped();
return m_running;
}

namespace
{

uint32_t readString(int fd, std::string& s)
{
uint32_t ssize;

// Loop while there's nothing to read. Generally this shouldn't loop.
while (true)
{
ssize_t numRead = read(fd, &ssize, sizeof(ssize));
if (numRead == -1 && errno != EAGAIN)
continue;
else if (numRead == sizeof(ssize))
break;
else
return -1; // Shouldn't happen.
}

// Loop reading string
char buf[80];
std::string t;
while (ssize)
{
ssize_t toRead = (std::min)((size_t)ssize, sizeof(buf));
ssize_t numRead = read(fd, buf, toRead);
if (numRead == 0 || (numRead == -1 && errno != EAGAIN))
return -1;
if (numRead > 0)
{
ssize -= numRead;
t += std::string(buf, numRead);
}
}
s = std::move(t);
return 0;
}

} // unnamed namespace

void QgisUntwine::readPipe() const
{
// Read messages until the pipe has been drained.
while (true)
{
ssize_t size = read(m_progressFd, &m_percent, sizeof(m_percent));
// If we didn't read the full size, just return.
if (size != sizeof(m_percent))
return;

// Read the string, waiting as necessary.
if (readString(m_progressFd, m_progressMsg) != 0)
break;
}
}

} // namespace untwine

0 comments on commit 221bd2f

Please sign in to comment.