1
/******************************************************************************
4
* Project: libLAS - http://liblas.org - A BSD library for LAS format data.
5
* Purpose: LAS 1.0 reader implementation for C++ libLAS
6
* Author: Mateusz Loskot, mateusz@loskot.net
8
******************************************************************************
9
* Copyright (c) 2008, Mateusz Loskot
11
* All rights reserved.
13
* Redistribution and use in source and binary forms, with or without
14
* modification, are permitted provided that the following
17
* * Redistributions of source code must retain the above copyright
18
* notice, this list of conditions and the following disclaimer.
19
* * Redistributions in binary form must reproduce the above copyright
20
* notice, this list of conditions and the following disclaimer in
21
* the documentation and/or other materials provided
22
* with the distribution.
23
* * Neither the name of the Martin Isenburg or Iowa Department
24
* of Natural Resources nor the names of its contributors may be
25
* used to endorse or promote products derived from this software
26
* without specific prior written permission.
28
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
35
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
36
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
37
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
38
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
40
****************************************************************************/
42
#include <liblas/detail/reader10.hpp>
43
#include <liblas/detail/utility.hpp>
44
#include <liblas/lasvariablerecord.hpp>
45
#include <liblas/liblas.hpp>
46
#include <liblas/lasheader.hpp>
47
#include <liblas/laspoint.hpp>
53
#include <cstdlib> // std::size_t, std::free
56
namespace liblas { namespace detail { namespace v10 {
58
ReaderImpl::ReaderImpl(std::istream& ifs) : Base(ifs)
62
std::size_t ReaderImpl::GetVersion() const
67
bool ReaderImpl::ReadHeader(LASHeader& header)
87
read_n(fsig, m_ifs, 4);
88
header.SetFileSignature(fsig);
91
// This data must always contain Zeros.
92
read_n(n4, m_ifs, sizeof(n4));
98
uint8_t d4[8] = { 0 };
99
read_n(d1, m_ifs, sizeof(d1));
100
read_n(d2, m_ifs, sizeof(d2));
101
read_n(d3, m_ifs, sizeof(d3));
102
read_n(d4, m_ifs, sizeof(d4));
103
liblas::guid g(d1, d2, d3, d4);
104
header.SetProjectId(g);
107
read_n(n1, m_ifs, sizeof(n1));
108
header.SetVersionMajor(n1);
111
read_n(n1, m_ifs, sizeof(n1));
112
header.SetVersionMinor(n1);
115
read_n(buf, m_ifs, 32);
116
header.SetSystemId(buf);
118
// 10. Generating Software ID
119
read_n(buf, m_ifs, 32);
120
header.SetSoftwareId(buf);
122
// 11. Flight Date Julian
123
read_n(n2, m_ifs, sizeof(n2));
124
header.SetCreationDOY(n2);
127
read_n(n2, m_ifs, sizeof(n2));
128
header.SetCreationYear(n2);
131
// NOTE: Size of the stanard header block must always be 227 bytes
132
read_n(n2, m_ifs, sizeof(n2));
134
// 14. Offset to data
135
read_n(n4, m_ifs, sizeof(n4));
136
if (n4 < header.GetHeaderSize())
138
// TODO: Move this test to LASHeader::Validate()
139
throw std::domain_error("offset to point data smaller than header size");
141
header.SetDataOffset(n4);
143
// 15. Number of variable length records
144
read_n(n4, m_ifs, sizeof(n4));
145
header.SetRecordsCount(n4);
147
// 16. Point Data Format ID
148
read_n(n1, m_ifs, sizeof(n1));
149
if (n1 == LASHeader::ePointFormat0) {
150
header.SetDataFormatId(LASHeader::ePointFormat0);
152
else if (n1 == LASHeader::ePointFormat1) {
153
header.SetDataFormatId(LASHeader::ePointFormat1);
155
else if (n1 == LASHeader::ePointFormat2) {
156
header.SetDataFormatId(LASHeader::ePointFormat2);
158
else if (n1 == LASHeader::ePointFormat3) {
159
header.SetDataFormatId(LASHeader::ePointFormat3);
162
throw std::domain_error("invalid point data format");
165
// 17. Point Data Record Length
166
// NOTE: No need to set record length because it's
167
// determined on basis of point data format.
168
read_n(n2, m_ifs, sizeof(n2));
170
// 18. Number of point records
171
read_n(n4, m_ifs, sizeof(n4));
172
header.SetPointRecordsCount(n4);
174
// 19. Number of points by return
175
std::vector<uint32_t>::size_type const srbyr = 5;
176
uint32_t rbyr[srbyr] = { 0 };
177
read_n(rbyr, m_ifs, sizeof(rbyr));
178
for (std::size_t i = 0; i < srbyr; ++i)
180
header.SetPointRecordsByReturnCount(i, rbyr[i]);
183
// 20-22. Scale factors
184
read_n(x1, m_ifs, sizeof(x1));
185
read_n(y1, m_ifs, sizeof(y1));
186
read_n(z1, m_ifs, sizeof(z1));
187
header.SetScale(x1, y1, z1);
190
read_n(x1, m_ifs, sizeof(x1));
191
read_n(y1, m_ifs, sizeof(y1));
192
read_n(z1, m_ifs, sizeof(z1));
193
header.SetOffset(x1, y1, z1);
196
read_n(x1, m_ifs, sizeof(x1));
197
read_n(x2, m_ifs, sizeof(x2));
200
read_n(y1, m_ifs, sizeof(y1));
201
read_n(y2, m_ifs, sizeof(y2));
204
read_n(z1, m_ifs, sizeof(z1));
205
read_n(z2, m_ifs, sizeof(z2));
207
header.SetMax(x1, y1, z1);
208
header.SetMin(x2, y2, z2);
215
bool ReaderImpl::ReadNextPoint(LASPoint& point, const LASHeader& header)
217
// Read point data record format 0
219
// TODO: Replace with compile-time assert
221
detail::PointRecord record;
224
assert(LASHeader::ePointSize0 == sizeof(record));
229
m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
232
if (m_current < m_size)
236
detail::read_n(record, m_ifs, sizeof(PointRecord));
239
catch (std::out_of_range const& e) // we reached the end of the file
241
std::cerr << e.what() << std::endl;
245
Reader::FillPoint(record, point);
246
point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
248
if (header.GetDataFormatId() == LASHeader::ePointFormat1) {
249
detail::read_n(t, m_ifs, sizeof(double));
258
bool ReaderImpl::ReadPointAt(std::size_t n, LASPoint& point, const LASHeader& header)
260
// Read point data record format 0
262
// TODO: Replace with compile-time assert
264
detail::PointRecord record;
265
assert(LASHeader::ePointSize0 == sizeof(record));
269
std::streamsize pos = (static_cast<std::streamsize>(n) * header.GetDataRecordLength()) + header.GetDataOffset();
272
m_ifs.seekg(pos, std::ios::beg);
273
detail::read_n(record, m_ifs, sizeof(record));
275
Reader::FillPoint(record, point);
276
point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
279
if (header.GetDataFormatId() == LASHeader::ePointFormat1) {
280
detail::read_n(t, m_ifs, sizeof(double));
287
}}} // namespace liblas::detail::v10