1 /***************************************************************************** 2 * Copyright (c) 2020, Hobu, Inc. (info@hobu.co) * 3 * * 4 * All rights reserved. * 5 * * 6 * This program is free software; you can redistribute it and/or modify * 7 * it under the terms of the GNU General Public License as published by * 8 * the Free Software Foundation; either version 3 of the License, or * 9 * (at your option) any later version. * 10 * * 11 ****************************************************************************/ 12 13 #pragma once 14 15 #include <array> 16 #include <unordered_map> 17 18 #include "../untwine/FileDimInfo.hpp" 19 #include "../untwine/GridKey.hpp" 20 #include "../untwine/Point.hpp" 21 #include "../untwine/VoxelKey.hpp" 22 23 #include "OctantInfo.hpp" 24 25 namespace untwine 26 { 27 namespace bu 28 { 29 30 class VoxelInfo 31 { 32 public: 33 // This probably needs a data structure geared for sparse data as I *think* that many 34 // of our lookups will fail. 35 using Grid = std::unordered_map<GridKey, int>; 36 VoxelInfo(const pdal::BOX3D & fullBounds,const VoxelKey & key)37 VoxelInfo(const pdal::BOX3D& fullBounds, const VoxelKey& key) : 38 m_fullBounds(fullBounds), m_octant(key) 39 { 40 //ABELL - This shouldn't be necessary. The key should be in the children 41 // when they're pulled out of the queue. 42 for (int i = 0; i < 8; ++i) 43 m_children[i].setKey(key.child(i)); 44 45 int cells = (int)std::pow(2, key.level()); 46 m_xWidth = (fullBounds.maxx - fullBounds.minx) / cells; 47 m_yWidth = (fullBounds.maxy - fullBounds.miny) / cells; 48 m_zWidth = (fullBounds.maxz - fullBounds.minz) / cells; 49 // Calculate the bounds of this voxel. 50 m_bounds.minx = fullBounds.minx + (key.x() * m_xWidth); 51 m_bounds.maxx = m_bounds.minx + m_xWidth; 52 m_bounds.miny = fullBounds.miny + (key.y() * m_yWidth); 53 m_bounds.maxy = m_bounds.miny + m_yWidth; 54 m_bounds.minz = fullBounds.minz + (key.z() * m_zWidth); 55 m_bounds.maxz = m_bounds.minz + m_zWidth; 56 57 // Determine spacing between points. 58 // m_spacing = minWidth() / 128.0; 59 m_spacing = maxWidth() / 128.0; 60 61 // Make the spacing smaller than what we expect as the final spacing since we're 62 // going to select points from the grid for the parent. 63 if (key != VoxelKey(0, 0, 0, 0)) 64 m_spacing *= 1.5; 65 m_squareSpacing = m_spacing * m_spacing; 66 67 static const double sqrt3 = std::sqrt(3); 68 m_gridCellWidth = m_spacing / sqrt3; 69 m_gridXCount = (int)std::ceil((m_bounds.maxx - m_bounds.minx) / m_gridCellWidth); 70 m_gridYCount = (int)std::ceil((m_bounds.maxy - m_bounds.miny) / m_gridCellWidth); 71 m_gridZCount = (int)std::ceil((m_bounds.maxz - m_bounds.minz) / m_gridCellWidth); 72 } 73 key() const74 VoxelKey key() const 75 { return m_octant.key(); } 76 operator [](int dir)77 OctantInfo& operator[](int dir) 78 { return m_children[dir]; } 79 octant()80 OctantInfo& octant() 81 { return m_octant; } 82 numPoints() const83 size_t numPoints() const 84 { 85 size_t cnt = 0; 86 for (const OctantInfo& oi : m_children) 87 cnt += oi.numPoints(); 88 return cnt; 89 } 90 hasPoints() const91 bool hasPoints() const 92 { 93 for (const OctantInfo& oi : m_children) 94 if (oi.hasPoints()) 95 return true; 96 return false; 97 } 98 spacing() const99 double spacing() const 100 { return m_spacing; } 101 squareSpacing() const102 double squareSpacing() const 103 { return m_squareSpacing; } 104 minWidth() const105 double minWidth() const 106 { return (std::min)((std::min)(m_xWidth, m_yWidth), m_zWidth); } 107 maxWidth() const108 double maxWidth() const 109 { return (std::max)((std::max)(m_xWidth, m_yWidth), m_zWidth); } 110 xWidth() const111 double xWidth() const 112 { return m_xWidth; } 113 yWidth() const114 double yWidth() const 115 { return m_yWidth; } 116 zWidth() const117 double zWidth() const 118 { return m_zWidth; } 119 gridKey(const Point & p) const120 GridKey gridKey(const Point& p) const 121 { 122 double x = p.x() - m_bounds.minx; 123 double y = p.y() - m_bounds.miny; 124 double z = p.z() - m_bounds.minz; 125 126 return GridKey((int)(x / m_gridCellWidth), (int)(y / m_gridCellWidth), 127 (int)(z / m_gridCellWidth)); 128 } 129 130 //ABELL - Really torn WRT making Grid its own thing. 131 grid()132 Grid& grid() 133 { return m_grid; } 134 gridXCount() const135 int gridXCount() const 136 { return m_gridXCount; } 137 gridYCount() const138 int gridYCount() const 139 { return m_gridYCount; } 140 gridZCount() const141 int gridZCount() const 142 { return m_gridZCount; } 143 bounds() const144 pdal::BOX3D bounds() const 145 { return m_bounds; } 146 147 private: 148 pdal::BOX3D m_fullBounds; 149 pdal::BOX3D m_bounds; 150 double m_xWidth; 151 double m_yWidth; 152 double m_zWidth; 153 double m_gridCellWidth; 154 int m_gridXCount; 155 int m_gridYCount; 156 int m_gridZCount; 157 std::array<OctantInfo, 8> m_children; 158 OctantInfo m_octant; 159 double m_spacing; 160 double m_squareSpacing; 161 162 Grid m_grid; 163 }; 164 165 } // namespace bu 166 } // namespace untwine 167