Skip to content

Commit

Permalink
Checkpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
abellgithub committed Jun 23, 2021
1 parent dd34012 commit b2649a0
Show file tree
Hide file tree
Showing 16 changed files with 1,719 additions and 0 deletions.
Binary file added io/private/eptwriter/.Processor.cpp.swp
Binary file not shown.
191 changes: 191 additions & 0 deletions io/private/eptwriter/BuPyramid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#include <iomanip>
#include <regex>
#include <set>
#include <string>
#include <vector>

#include <pdal/util/FileUtils.hpp>
#include <pdal/util/ProgramArgs.hpp>

#include "BuPyramid.hpp"
#include "FileInfo.hpp"
#include "OctantInfo.hpp"
#include "../untwine/Common.hpp"
#include "../untwine/ProgressWriter.hpp"

namespace untwine
{
namespace bu
{

/// BuPyramid

BuPyramid::BuPyramid(BaseInfo& common) : m_b(common), m_manager(m_b)
{}


void BuPyramid::run(CellManager& cells)
{
m_b.outputDir = options.outputDir;
m_b.stats = options.stats;

size_t count = queueWork(cells);

std::thread runner(&PyramidManager::run, &m_manager);
runner.join();
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(m_b.outputDir + "/ept.json");

out << "{\n";

pdal::BOX3D& b = m_b.bounds;

// Set fixed output for bounds output to get sufficient precision.
out << std::fixed;
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)) << "\", ";
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 << "\"size\": " << pdal::Dimension::size(fdi.type);
const Stats *stats = m_manager.stats(fdi.name);
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 << "\"maximum\": " << stats->maximum() << ", ";
out << "\"minimum\": " << stats->minimum() << ", ";
out << "\"mean\": " << stats->average() << ", ";
out << "\"stddev\": " << stats->stddev() << ", ";
out << "\"variance\": " << stats->variance();
}
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";
}


size_t BuPyramid::queueWork()
{
std::set<VoxelKey> needed;
std::set<VoxelKey> parentsToProcess;
std::vector<OctantInfo> have;
const VoxelKey root;

for (auto& kv : m_cells)
{
VoxelKey k = kv.first;
PointViewPtr cell = kv.second;

// Stick an OctantInfo for this cell in the 'have' list.
OctantInfo o(k);
o.appendCell(cell);
have.push_back(o);

// Walk up the tree and make sure that we're populated for all children necessary
// to process to the top level. We do this in order to facilitate processing --
// a parent node is ready to be processed when all its children have been processed,
// so making sure a parent has all 8 children makes this easy.
while (k != root)
{
k = k.parent();
parentsToProcess.insert(k);
for (int i = 0; i < 8; ++i)
needed.insert(k.child(i));
}
}

// Now remove entries for the cells we have and their parents.
for (const OctantInfo& o : have)
{
VoxelKey k = o.key();
while (k != root)
{
needed.erase(k);
k = k.parent();
}
}

// Queue what we have.
for (const OctantInfo& o : have)
m_manager.queue(o);
// Queue what we need but have no data for.
for (const VoxelKey& k : needed)
m_manager.queue(OctantInfo(k));
return parentsToProcess.size();
}

} // namespace bu
} // namespace untwine
56 changes: 56 additions & 0 deletions io/private/eptwriter/BuPyramid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*****************************************************************************
* Copyright (c) 2020, Hobu, Inc. (info@hobu.co) *
* *
* 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. *
* *
****************************************************************************/


#pragma once

#include <string>
#include <unordered_map>
#include <vector>

#include "PyramidManager.hpp"

namespace pdal
{
class ProgramArgs;
}

namespace untwine
{

struct Options;
class ProgressWriter;

namespace bu
{

class FileInfo;

class BuPyramid
{
public:
BuPyramid(BaseInfo& common);
void run(const Options& options, ProgressWriter& progress);

private:
void getInputFiles();
void readBaseInfo();
size_t queueWork();
void writeInfo();

BaseInfo m_b;
PyramidManager m_manager;
std::unordered_map<VoxelKey, FileInfo> m_allFiles;
};

} // namespace bu
} // namespace untwine
81 changes: 81 additions & 0 deletions io/private/eptwriter/CellManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*****************************************************************************
* Copyright (c) 2021, Hobu, Inc. (info@hobu.co) *
* *
* 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. *
* *
****************************************************************************/

#pragma once

#include "VoxelKey.hpp"

#include <unordered_map>

namespace pdal
{
namespace ept
{

class CellManager
{
public:
using Cells = std::unordered_map<VoxelKey, PointViewPtr>;
using iterator = Cells::iterator;
using const_iterator = Cells::const_iterator;

CellManager(PointViewPtr sourceView) : m_sourceView(sourceView)
{}

PointViewPtr& get(VoxelKey key)
{
PointViewPtr& v = m_cells[key];
if (!v)
v = m_sourceView->makeNew();
return v;
}

iterator erase(iterator it)
{
return m_cells.erase(it);
}

const_iterator begin() const
{
return m_cells.begin();
}

const_iterator end() const
{
return m_cells.end();
}

iterator begin()
{
return m_cells.begin();
}

iterator end()
{
return m_cells.end();
}

// Note that C++17 has functions to do this.
void merge(CellManager&& src)
{
for (auto& kv : src)
m_cells.insert(std::move(kv));
}

private:
Cells m_cells;

PointViewPtr m_sourceView;
};

} // namespace ept
} // namespace pdal
24 changes: 24 additions & 0 deletions io/private/eptwriter/Ept.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*****************************************************************************
* Copyright (c) 2021, Hobu, Inc. (info@hobu.co) *
* *
* 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. *
* *
****************************************************************************/


#pragma once

namespace pdal
{
namespace ept
{

static const int MaxPointsPerNode = 100000;

} // namespace ept
} // namespace pdal

0 comments on commit b2649a0

Please sign in to comment.