From 08ca06211b3433f2292ed4103c18559ec4763b29 Mon Sep 17 00:00:00 2001 From: ibell13 Date: Tue, 1 Oct 2024 14:13:32 -0500 Subject: [PATCH] docs update and error handling --- doc/stages/filters.hexbin.md | 8 ++++++++ filters/HexBinFilter.cpp | 9 +++++++-- filters/private/hexer/BaseGrid.hpp | 4 ++-- filters/private/hexer/H3grid.cpp | 13 ++++++++++--- filters/private/hexer/H3grid.hpp | 2 +- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/doc/stages/filters.hexbin.md b/doc/stages/filters.hexbin.md index 6ee0e139ec..2faa0ef0a6 100755 --- a/doc/stages/filters.hexbin.md +++ b/doc/stages/filters.hexbin.md @@ -22,6 +22,14 @@ with other H3 datasets. When writing to a file with `density`, a unique [H3Index is provided for each hexagon. Boundary smoothing is disabled for H3, and `h3_resolution` is used in place of `edge_length`. +```{note} +H3 processing can also work with an existing "H3" dimension in the point input, +created by {ref}`filters.h3`. If `h3_grid` is set to "true", point clouds +containing an H3 field will always be processed using the data in that field; all +H3 indices must be at the same resolution, which will override the `h3_resolution` +option. +``` + The hexbin filter reads a point stream and writes out a metadata record that contains a boundary, expressed as a well-known text polygon. The filter counts the points in each hexagonal area to determine if that area should be included diff --git a/filters/HexBinFilter.cpp b/filters/HexBinFilter.cpp index 08ca0048f9..bd2f2d02d3 100644 --- a/filters/HexBinFilter.cpp +++ b/filters/HexBinFilter.cpp @@ -133,6 +133,9 @@ void HexBin::prepared(PointTableRef table) { const PointLayoutPtr layout(table.layout()); m_h3Dim = layout->hasDim(Dimension::Id::H3); + if (m_h3Dim && (m_h3Res != -1) && m_isH3) + log()->get(LogLevel::Warning) << "Processing hexes using H3 indices in " + "input file's 'H3' field. Ignoring user-provided 'h3_resolution'\n"; } @@ -178,8 +181,10 @@ bool HexBin::processOne(PointRef& point) { if (m_isH3 && m_h3Dim) { - // this should throw a more descriptive error - m_grid->addH3Dim(point.getFieldAs(Dimension::Id::H3)); + if (!m_grid->addH3Dim(point.getFieldAs(Dimension::Id::H3))) + throwError("Unable to process H3 dimension from input file! " + "All values must be valid H3 cell indexes at a single " + "resolution."); } else { diff --git a/filters/private/hexer/BaseGrid.hpp b/filters/private/hexer/BaseGrid.hpp index be32427634..21c2490c80 100644 --- a/filters/private/hexer/BaseGrid.hpp +++ b/filters/private/hexer/BaseGrid.hpp @@ -56,8 +56,8 @@ class PDAL_DLL BaseGrid // is there a better way to do this? taking two arguments seems weird virtual uint64_t getID(int& n, const HexId& ij) = 0; - virtual void addH3Dim(H3Index h3) - {} + virtual bool addH3Dim(H3Index h3) + { return true; } virtual H3Index ij2h3(HexId ij) { return 0; } virtual HexId h32ij(H3Index h3) diff --git a/filters/private/hexer/H3grid.cpp b/filters/private/hexer/H3grid.cpp index 2582625ab6..c83cfc2fe1 100644 --- a/filters/private/hexer/H3grid.cpp +++ b/filters/private/hexer/H3grid.cpp @@ -33,15 +33,22 @@ void H3Grid::processHeight(double height) //std::cout << "H3 resolution: " << m_res << std::endl; } -void H3Grid::addH3Dim(H3Index h3) +bool H3Grid::addH3Dim(H3Index h3) { if (!m_origin) { m_origin = h3; m_res = PDALH3getResolution(h3); } - HexId ij = h32ij(h3); - addHexagon(ij); + HexId ij; + // using this instead of h32ij to throw a better error + if (PDALH3cellToLocalIj(m_origin, h3, 0, &ij) != E_SUCCESS) + return false; + else + { + addHexagon(ij); + return true; + } } HexId H3Grid::findHexagon(Point p) diff --git a/filters/private/hexer/H3grid.hpp b/filters/private/hexer/H3grid.hpp index 3280b6f48a..031278238d 100644 --- a/filters/private/hexer/H3grid.hpp +++ b/filters/private/hexer/H3grid.hpp @@ -48,7 +48,7 @@ class PDAL_DLL H3Grid : public BaseGrid } return ij; } - void addH3Dim(H3Index h3); + bool addH3Dim(H3Index h3); Point findPoint(Segment& s); void addXY(double& x, double& y)