1 /****************************************************************************** 2 * Copyright (c) 2014, Hobu Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following 8 * conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided 15 * with the distribution. 16 * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the 17 * names of its contributors may be used to endorse or promote 18 * products derived from this software without specific prior 19 * written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 * OF SUCH DAMAGE. 33 ****************************************************************************/ 34 35 #pragma once 36 37 #include <algorithm> 38 #include <list> 39 #include <vector> 40 41 #include "pdal/SpatialReference.hpp" 42 #include "pdal/Dimension.hpp" 43 #include "pdal/PointContainer.hpp" 44 #include "pdal/PointLayout.hpp" 45 #include "pdal/Metadata.hpp" 46 47 namespace pdal 48 { 49 50 class ArtifactManager; 51 52 class PDAL_DLL BasePointTable : public PointContainer 53 { 54 FRIEND_TEST(PointTable, srs); 55 friend class PointView; 56 57 protected: 58 BasePointTable(PointLayout& layout); 59 60 public: 61 virtual ~BasePointTable(); 62 63 // Layout operations. layout() const64 virtual PointLayoutPtr layout() const 65 { return &m_layoutRef; } 66 67 // Metadata operations. metadata()68 MetadataNode metadata() 69 { return m_metadata->getNode(); } finalize()70 virtual void finalize() 71 { m_layoutRef.finalize(); } setSpatialReference(const SpatialReference & srs)72 void setSpatialReference(const SpatialReference& srs) 73 { 74 clearSpatialReferences(); 75 addSpatialReference(srs); 76 } clearSpatialReferences()77 void clearSpatialReferences() 78 { m_spatialRefs.clear(); } 79 void addSpatialReference(const SpatialReference& srs); spatialReferenceUnique() const80 bool spatialReferenceUnique() const 81 { return m_spatialRefs.size() <= 1; } spatialReference() const82 SpatialReference spatialReference() const 83 { 84 return spatialReferenceUnique() ? anySpatialReference() : 85 SpatialReference(); 86 } anySpatialReference() const87 SpatialReference anySpatialReference() const 88 { 89 return m_spatialRefs.size() ? 90 *m_spatialRefs.begin() : SpatialReference(); 91 } supportsView() const92 virtual bool supportsView() const 93 { return false; } 94 MetadataNode privateMetadata(const std::string& name); 95 MetadataNode toMetadata() const; 96 ArtifactManager& artifactManager(); 97 98 private: 99 // Point data operations. 100 virtual PointId addPoint() = 0; 101 virtual char *getDimension(const Dimension::Detail *d, PointId idx) = 0; 102 103 protected: 104 virtual char *getPoint(PointId idx) = 0; 105 106 protected: 107 MetadataPtr m_metadata; 108 std::list<SpatialReference> m_spatialRefs; 109 PointLayout& m_layoutRef; 110 std::unique_ptr<ArtifactManager> m_artifactManager; 111 }; 112 typedef BasePointTable& PointTableRef; 113 typedef BasePointTable const & ConstPointTableRef; 114 115 class PDAL_DLL SimplePointTable : public BasePointTable 116 { 117 118 protected: SimplePointTable(PointLayout & layout)119 SimplePointTable(PointLayout& layout) : BasePointTable(layout) 120 {} 121 122 protected: pointsToBytes(point_count_t numPts) const123 std::size_t pointsToBytes(point_count_t numPts) const 124 { return m_layoutRef.pointSize() * numPts; } 125 126 private: 127 virtual void setFieldInternal(Dimension::Id id, PointId idx, 128 const void *value); 129 virtual void getFieldInternal(Dimension::Id id, PointId idx, 130 void *value) const; 131 getDimension(const Dimension::Detail * d,PointId idx)132 char *getDimension(const Dimension::Detail *d, PointId idx) 133 { return getPoint(idx) + d->offset(); } 134 getDimension(const Dimension::Detail * d,PointId idx) const135 const char *getDimension(const Dimension::Detail *d, PointId idx) const 136 { 137 SimplePointTable *ncThis = const_cast<SimplePointTable *>(this); 138 return ncThis->getPoint(idx) + d->offset(); 139 } 140 }; 141 142 // This provides a context for processing a set of points and allows the library 143 // to be used to process multiple point sets simultaneously. 144 class PDAL_DLL RowPointTable : public SimplePointTable 145 { 146 private: 147 // Point storage. 148 std::vector<char *> m_blocks; 149 point_count_t m_numPts; 150 151 // Make sure this is power-of-2 to facilitate fast div and mod ops. 152 static const point_count_t m_blockPtCnt = 65536; 153 154 public: RowPointTable()155 RowPointTable() : SimplePointTable(m_layout), m_numPts(0) 156 {} 157 virtual ~RowPointTable(); supportsView() const158 virtual bool supportsView() const 159 { return true; } 160 161 protected: 162 virtual char *getPoint(PointId idx); 163 164 private: 165 // Point data operations. 166 virtual PointId addPoint(); 167 168 PointLayout m_layout; 169 }; 170 using PointTable = RowPointTable; 171 172 // This provides a context for processing a set of points and allows the library 173 // to be used to process multiple point sets simultaneously. 174 class PDAL_DLL ColumnPointTable : public SimplePointTable 175 { 176 private: 177 // Point storage. 178 using DimBlockList = std::vector<char *>; 179 using MemBlocks = std::vector<DimBlockList>; 180 181 // List of dimension memory block lists. 182 MemBlocks m_blocks; 183 point_count_t m_numPts; 184 185 // Make sure this is power-of-2 to facilitate fast div and mod ops. 186 static const point_count_t m_blockPtCnt = 16384; 187 188 public: ColumnPointTable()189 ColumnPointTable() : SimplePointTable(m_layout), m_numPts(0) 190 {} 191 virtual ~ColumnPointTable(); supportsView() const192 virtual bool supportsView() const 193 { return true; } 194 virtual void finalize(); getPoint(PointId idx)195 virtual char *getPoint(PointId idx) 196 { return nullptr; } 197 198 private: 199 virtual void setFieldInternal(Dimension::Id id, PointId idx, 200 const void *value); 201 virtual void getFieldInternal(Dimension::Id id, PointId idx, 202 void *value) const; 203 204 virtual PointId addPoint(); 205 206 // Hide base class calls for now. 207 const char *getDimension(const Dimension::Detail *d, PointId idx) const; 208 char *getDimension(const Dimension::Detail *d, PointId idx); 209 210 PointLayout m_layout; 211 }; 212 213 /// A StreamPointTable must provide storage for point data up to its capacity. 214 /// It must implement getPoint() which returns a pointer to a buffer of 215 /// sufficient size to contain a point's data. The minimum size required 216 /// is constant and can be determined by calling pointsToBytes(1) in the 217 /// finalize() method. 218 class PDAL_DLL StreamPointTable : public SimplePointTable 219 { 220 protected: StreamPointTable(PointLayout & layout,point_count_t capacity)221 StreamPointTable(PointLayout& layout, point_count_t capacity) 222 : SimplePointTable(layout) 223 , m_capacity(capacity) 224 , m_numPoints(0) 225 , m_skips(m_capacity, false) 226 {} 227 228 public: 229 /// Called when a new point should be added. Probably a no-op for 230 /// streaming. addPoint()231 virtual PointId addPoint() 232 { return 0; } 233 234 /// Called when execute() is started. Typically used to set buffer size 235 /// when all dimensions are known. finalize()236 virtual void finalize() 237 {} 238 clear(point_count_t count)239 void clear(point_count_t count) 240 { 241 if (!count) 242 return; 243 244 m_numPoints = count; 245 reset(); 246 std::fill(m_skips.begin(), m_skips.end(), false); 247 } 248 249 /// Returns true if a point in the table was filtered out and should be 250 /// considered omitted. skip(PointId n) const251 bool skip(PointId n) const 252 { return m_skips[n]; } setSkip(PointId n)253 void setSkip(PointId n) 254 { m_skips[n] = true; } 255 capacity() const256 point_count_t capacity() const 257 { return m_capacity; } 258 259 /// During a given call to reset(), this indicates the number of points 260 /// populated in the table. This value will always be less then or equal 261 /// to capacity(), and also includes skipped points. numPoints() const262 point_count_t numPoints() const 263 { return m_numPoints; } 264 265 protected: 266 /// Called when the contents of StreamPointTable have been consumed and 267 /// the point data will be potentially overwritten. reset()268 virtual void reset() 269 {} 270 271 private: 272 point_count_t m_capacity; 273 point_count_t m_numPoints; 274 std::vector<bool> m_skips; 275 }; 276 277 class PDAL_DLL FixedPointTable : public StreamPointTable 278 { 279 public: FixedPointTable(point_count_t capacity)280 FixedPointTable(point_count_t capacity) 281 : StreamPointTable(m_layout, capacity) 282 {} 283 finalize()284 virtual void finalize() 285 { 286 if (!m_layout.finalized()) 287 { 288 BasePointTable::finalize(); 289 m_buf.resize(pointsToBytes(capacity() + 1)); 290 } 291 } 292 293 protected: reset()294 virtual void reset() 295 { std::fill(m_buf.begin(), m_buf.end(), 0); } 296 getPoint(PointId idx)297 virtual char *getPoint(PointId idx) 298 { return m_buf.data() + pointsToBytes(idx); } 299 300 private: 301 std::vector<char> m_buf; 302 PointLayout m_layout; 303 }; 304 305 } //namespace 306 307