Skip to content

Commit

Permalink
Add a basic test.
Browse files Browse the repository at this point in the history
  • Loading branch information
abellgithub committed Feb 8, 2024
1 parent 9fafef0 commit bb05f3e
Show file tree
Hide file tree
Showing 76 changed files with 28,744 additions and 275 deletions.
17 changes: 14 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,25 @@ set_package_properties(Threads PROPERTIES DESCRIPTION

configure_file(untwine/Config.hpp.in include/Config.hpp)

file(GLOB LAZPERF_SRCS
lazperf/*.cpp
lazperf/detail/*.cpp
)

file(GLOB SRCS
untwine/*.cpp
epf/*.cpp
bu/*.cpp
lazperf/*.cpp
lazperf/detail/*.cpp
)

if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \
/SUBSYSTEM:WINDOWS /ENTRY:wmainCRTStartup")
endif()

add_executable(untwine ${SRCS})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)

add_executable(untwine ${SRCS} ${LAZPERF_SRCS})

untwine_target_compile_settings(untwine)

Expand All @@ -44,3 +49,9 @@ target_link_libraries(untwine
)

install(TARGETS untwine DESTINATION bin)

#-----------------

enable_testing()
add_subdirectory(test)

114 changes: 0 additions & 114 deletions bu/BuPyramid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,123 +35,9 @@ void BuPyramid::run(ProgressWriter& progress)
progress.setPercent(.6);
progress.setIncrement(.4 / count);
m_manager.setProgress(&progress);
//ABELL - Not sure why this was being run in a separate thread. The current thread
// would block in join() anyway.
/**
std::thread runner(&PyramidManager::run, &m_manager);
runner.join();
**/
m_manager.run();
if (!m_b.opts.singleFile)
writeInfo();
}


void BuPyramid::writeInfo()
{
auto typeString = [](pdal::Dimension::BaseType b)
{
using namespace pdal::Dimension;

switch (b)
{
case BaseType::Signed:
return "signed";
case BaseType::Unsigned:
return "unsigned";
case BaseType::Floating:
return "float";
default:
return "";
}
};

std::ofstream out(toNative(m_b.opts.outputName + "/ept.json"));
int maxdigits = std::numeric_limits<double>::max_digits10;

out << "{\n";

pdal::BOX3D& b = m_b.bounds;

// Set fixed output for bounds output to get sufficient precision.
out << std::fixed << std::setprecision(maxdigits);
out << "\"bounds\": [" <<
b.minx << ", " << b.miny << ", " << b.minz << ", " <<
b.maxx << ", " << b.maxy << ", " << b.maxz << "],\n";

pdal::BOX3D& tb = m_b.trueBounds;
out << "\"boundsConforming\": [" <<
tb.minx << ", " << tb.miny << ", " << tb.minz << ", " <<
tb.maxx << ", " << tb.maxy << ", " << tb.maxz << "],\n";
// Reset to default float output to match PDAL option handling for now.
out << std::defaultfloat;

out << "\"dataType\": \"laszip\",\n";
out << "\"hierarchyType\": \"json\",\n";
out << "\"points\": " << m_manager.totalPoints() << ",\n";
out << "\"span\": 128,\n";
out << "\"version\": \"1.0.0\",\n";
out << "\"schema\": [\n";
for (auto di = m_b.dimInfo.begin(); di != m_b.dimInfo.end(); ++di)
{
const FileDimInfo& fdi = *di;

out << "\t{";
out << "\"name\": \"" << fdi.name << "\", ";
out << "\"type\": \"" << typeString(pdal::Dimension::base(fdi.type)) << "\", ";
out << std::fixed << std::setprecision(maxdigits);
if (fdi.name == "X")
out << "\"scale\": " << m_b.scale[0] << ", \"offset\": " << m_b.offset[0] << ", ";
if (fdi.name == "Y")
out << "\"scale\": " << m_b.scale[1] << ", \"offset\": " << m_b.offset[1] << ", ";
if (fdi.name == "Z")
out << "\"scale\": " << m_b.scale[2] << ", \"offset\": " << m_b.offset[2] << ", ";
out << std::defaultfloat;
out << "\"size\": " << pdal::Dimension::size(fdi.type);
const Stats *stats = m_manager.stats(fdi.dim);
if (stats)
{
const Stats::EnumMap& v = stats->values();
out << ", ";
if (v.size())
{
out << "\"counts\": [ ";
for (auto ci = v.begin(); ci != v.end(); ++ci)
{
auto c = *ci;
if (ci != v.begin())
out << ", ";
out << "{\"value\": " << c.first << ", \"count\": " << c.second << "}";
}
out << "], ";
}
out << "\"count\": " << m_manager.totalPoints() << ", ";
out << std::fixed << std::setprecision(maxdigits);
out << "\"maximum\": " << stats->maximum() << ", ";
out << "\"minimum\": " << stats->minimum() << ", ";
out << "\"mean\": " << stats->average() << ", ";
out << "\"stddev\": " << stats->stddev() << ", ";
out << "\"variance\": " << stats->variance();
out << std::defaultfloat;
}
out << "}";
if (di + 1 != m_b.dimInfo.end())
out << ",";
out << "\n";
}
out << "],\n";

out << "\"srs\": {\n";
if (m_b.srs.valid())
{
out << "\"wkt\": " << "\"" << pdal::Utils::escapeJSON(m_b.srs.getWKT()) << "\"\n";
}
out << "}\n";

out << "}\n";
}


void BuPyramid::getInputFiles()
{
auto matches = [](const std::string& f)
Expand Down
1 change: 0 additions & 1 deletion bu/BuPyramid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class BuPyramid
void getInputFiles();
void readBaseInfo();
size_t queueWork();
void writeInfo();

BaseInfo m_b;
PyramidManager m_manager;
Expand Down
57 changes: 2 additions & 55 deletions bu/Processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ Processor::writeOctantCompressed(const OctantInfo& o, Index& index, IndexIter po
// For single file output we need the counts by return number.
if (fdi.dim == pdal::Dimension::Id::Classification)
stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)});
else if (fdi.dim == pdal::Dimension::Id::ReturnNumber && m_b.opts.singleFile)
else if (fdi.dim == pdal::Dimension::Id::ReturnNumber)
stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)});
else
stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::NoEnum, false)});
Expand Down Expand Up @@ -431,62 +431,9 @@ void Processor::flushCompressed(pdal::PointViewPtr view, const OctantInfo& oi, I
}
}

if (m_b.opts.singleFile)
{
createChunk(oi.key(), view);
}
else
{
std::string filename = m_b.opts.outputName + "/ept-data/" + oi.key().toString() + ".laz";
writeEptFile(filename, view);
}
createChunk(oi.key(), view);
}

void Processor::writeEptFile(const std::string& filename, pdal::PointViewPtr view)
{
using namespace pdal;

StageFactory factory;

BufferReader r;
r.addView(view);

Stage *prev = &r;

if (view->layout()->hasDim(Dimension::Id::GpsTime))
{
Stage *f = factory.createStage("filters.sort");
pdal::Options fopts;
fopts.add("dimension", "gpstime");
f->setOptions(fopts);
f->setInput(*prev);
prev = f;
}

Stage *w = factory.createStage("writers.las");
pdal::Options wopts;
wopts.add("extra_dims", "all");
wopts.add("software_id", "Entwine 1.0");
wopts.add("compression", "laszip");
wopts.add("filename", filename);
wopts.add("offset_x", m_b.offset[0]);
wopts.add("offset_y", m_b.offset[1]);
wopts.add("offset_z", m_b.offset[2]);
wopts.add("scale_x", m_b.scale[0]);
wopts.add("scale_y", m_b.scale[1]);
wopts.add("scale_z", m_b.scale[2]);
wopts.add("minor_version", 4);
wopts.add("dataformat_id", m_b.pointFormatId);
if (m_b.opts.a_srs.size())
wopts.add("a_srs", m_b.opts.a_srs);
if (m_b.opts.metadata)
wopts.add("pdal_metadata", m_b.opts.metadata);
w->setOptions(wopts);
w->setInput(*prev);

w->prepare(view->table());
w->execute(view->table());
}

void Processor::sortChunk(pdal::PointViewPtr view)
{
Expand Down
86 changes: 6 additions & 80 deletions bu/PyramidManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,12 @@ void PyramidManager::run()
}

createHierarchy();
if (m_b.opts.singleFile)
{
m_copc.writeChunkTable();
m_copc.writeHierarchy(m_childCounts);
m_copc.updateHeader(m_stats);
// The header is last because we don't have the evlr position until the end.
m_copc.writeHeader();
}
else
writeHierarchy();

m_copc.writeChunkTable();
m_copc.writeHierarchy(m_childCounts);
m_copc.updateHeader(m_stats);
// The header is last because we don't have the evlr position until the end.
m_copc.writeHeader();
}

// Take the item off the queue and stick it on the complete list. If we have all 8 octants,
Expand Down Expand Up @@ -211,76 +207,6 @@ void PyramidManager::createHierarchy()
calcCounts(VoxelKey(0, 0, 0, 0));
}

void PyramidManager::writeHierarchy()
{
std::deque<VoxelKey> roots;

roots.push_back(VoxelKey(0, 0, 0, 0));
while (roots.size())
{
VoxelKey k = roots.front();
roots.pop_front();
auto newRoots = emitRoot(k);
roots.insert(roots.end(), newRoots.begin(), newRoots.end());
}
}

std::deque<VoxelKey> PyramidManager::emitRoot(const VoxelKey& root)
{
int level = root.level();
int stopLevel = level + LevelBreak;

Entries entries;
entries.push_back({root, m_written[root]});
std::deque<VoxelKey> roots = emit(root, stopLevel, entries);

std::string filename = m_b.opts.outputName + "/ept-hierarchy/" + root.toString() + ".json";
std::ofstream out(toNative(filename));

out << "{\n";

for (auto it = entries.begin(); it != entries.end(); ++it)
{
if (it != entries.begin())
out << ",\n";
out << "\"" << it->first << "\": " << it->second;
}
out << "\n";

out << "}\n";

return roots;
}


std::deque<VoxelKey> PyramidManager::emit(const VoxelKey& p, int stopLevel, Entries& entries)
{
std::deque<VoxelKey> roots;

for (int i = 0; i < 8; ++i)
{
VoxelKey c = p.child(i);
auto ci = m_childCounts.find(c);
if (ci != m_childCounts.end())
{

if (c.level() != stopLevel || ci->second <= MinHierarchySize)
{
entries.push_back({c, m_written[c]});
auto r = emit(c, stopLevel, entries);
roots.insert(roots.end(), r.begin(), r.end());
}
else
{
entries.push_back({c, -1});
roots.push_back(c);
}
}
}
return roots;
}


Stats *PyramidManager::stats(pdal::Dimension::Id id)
{
auto si = m_stats.find(id);
Expand Down
3 changes: 0 additions & 3 deletions bu/PyramidManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ class PyramidManager
size_t extraByteSize();
//
void createHierarchy();
void writeHierarchy();
std::deque<VoxelKey> emitRoot(const VoxelKey& root);
std::deque<VoxelKey> emit(const VoxelKey& p, int stopLevel, Entries& entries);
};

} // namespace bu
Expand Down
10 changes: 6 additions & 4 deletions lazperf/readers.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/*
===============================================================================
FILE: io.cpp
CONTENTS:
LAZ io
FILE: readers.cpp
PROGRAMMERS:
Expand Down Expand Up @@ -404,6 +401,11 @@ laz_vlr basic_file::lazVlr() const
return p_->laz;
}

eb_vlr basic_file::ebVlr() const
{
return p_->eb;
}

std::vector<char> basic_file::vlrData(const std::string& user_id, uint16_t record_id)
{
return p_->vlrData(user_id, record_id);
Expand Down
1 change: 1 addition & 0 deletions lazperf/readers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class basic_file
LAZPERF_EXPORT const header14& header() const;
LAZPERF_EXPORT void readPoint(char *out);
LAZPERF_EXPORT laz_vlr lazVlr() const;
LAZPERF_EXPORT eb_vlr ebVlr() const;
LAZPERF_EXPORT std::vector<char> vlrData(const std::string& user_id, uint16_t record_id);

private:
Expand Down
Loading

0 comments on commit bb05f3e

Please sign in to comment.