1
/******************************************************************************
4
* Project: libLAS - http://liblas.org - A BSD library for LAS format data.
5
* Purpose: LAS 1.1 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/reader11.hpp>
43
#include <liblas/detail/utility.hpp>
44
#include <liblas/liblas.hpp>
45
#include <liblas/lasheader.hpp>
46
#include <liblas/laspoint.hpp>
47
#include <liblas/lasvariablerecord.hpp>
53
#include <cstdlib> // std::size_t
56
namespace liblas { namespace detail { namespace v11 {
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
read_n(n2, m_ifs, sizeof(n2));
92
header.SetFileSourceId(n2);
95
// This data must always contain Zeros.
96
read_n(n2, m_ifs, sizeof(n2));
102
uint8_t d4[8] = { 0 };
103
read_n(d1, m_ifs, sizeof(d1));
104
read_n(d2, m_ifs, sizeof(d2));
105
read_n(d3, m_ifs, sizeof(d3));
106
read_n(d4, m_ifs, sizeof(d4));
107
liblas::guid g(d1, d2, d3, d4);
108
header.SetProjectId(g);
111
read_n(n1, m_ifs, sizeof(n1));
112
header.SetVersionMajor(n1);
115
read_n(n1, m_ifs, sizeof(n1));
116
header.SetVersionMinor(n1);
119
read_n(buf, m_ifs, 32);
120
header.SetSystemId(buf);
122
// 11. Generating Software ID
123
read_n(buf, m_ifs, 32);
124
header.SetSoftwareId(buf);
126
// 12. File Creation Day of Year
127
read_n(n2, m_ifs, sizeof(n2));
128
header.SetCreationDOY(n2);
130
// 13. File Creation Year
131
read_n(n2, m_ifs, sizeof(n2));
132
header.SetCreationYear(n2);
135
// NOTE: Size of the stanard header block must always be 227 bytes
136
read_n(n2, m_ifs, sizeof(n2));
138
// 15. Offset to data
139
read_n(n4, m_ifs, sizeof(n4));
140
if (n4 < header.GetHeaderSize())
142
// TODO: Move this test to LASHeader::Validate()
143
throw std::domain_error("offset to point data smaller than header size");
145
header.SetDataOffset(n4);
147
// 16. Number of variable length records
148
read_n(n4, m_ifs, sizeof(n4));
149
header.SetRecordsCount(n4);
151
// 17. Point Data Format ID
152
read_n(n1, m_ifs, sizeof(n1));
153
if (n1 == LASHeader::ePointFormat0) {
154
header.SetDataFormatId(LASHeader::ePointFormat0);
156
else if (n1 == LASHeader::ePointFormat1) {
157
header.SetDataFormatId(LASHeader::ePointFormat1);
159
else if (n1 == LASHeader::ePointFormat2) {
160
header.SetDataFormatId(LASHeader::ePointFormat2);
162
else if (n1 == LASHeader::ePointFormat3) {
163
header.SetDataFormatId(LASHeader::ePointFormat3);
166
throw std::domain_error("invalid point data format");
169
// 18. Point Data Record Length
170
// NOTE: No need to set record length because it's
171
// determined on basis of point data format.
172
read_n(n2, m_ifs, sizeof(n2));
174
// 19. Number of point records
175
read_n(n4, m_ifs, sizeof(n4));
176
header.SetPointRecordsCount(n4);
178
// 20. Number of points by return
179
std::vector<uint32_t>::size_type const srbyr = 5;
180
uint32_t rbyr[srbyr] = { 0 };
181
read_n(rbyr, m_ifs, sizeof(rbyr));
182
for (std::size_t i = 0; i < srbyr; ++i)
184
header.SetPointRecordsByReturnCount(i, rbyr[i]);
187
// 21-23. Scale factors
188
read_n(x1, m_ifs, sizeof(x1));
189
read_n(y1, m_ifs, sizeof(y1));
190
read_n(z1, m_ifs, sizeof(z1));
191
header.SetScale(x1, y1, z1);
194
read_n(x1, m_ifs, sizeof(x1));
195
read_n(y1, m_ifs, sizeof(y1));
196
read_n(z1, m_ifs, sizeof(z1));
197
header.SetOffset(x1, y1, z1);
200
read_n(x1, m_ifs, sizeof(x1));
201
read_n(x2, m_ifs, sizeof(x2));
204
read_n(y1, m_ifs, sizeof(y1));
205
read_n(y2, m_ifs, sizeof(y2));
208
read_n(z1, m_ifs, sizeof(z1));
209
read_n(z2, m_ifs, sizeof(z2));
211
header.SetMax(x1, y1, z1);
212
header.SetMin(x2, y2, z2);
214
m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
221
bool ReaderImpl::ReadNextPoint(LASPoint& point, const LASHeader& header)
223
// Read point data record format 0
225
// TODO: Replace with compile-time assert
228
detail::PointRecord record;
229
assert(LASHeader::ePointSize0 == sizeof(record));
234
m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
237
if (m_current < m_size)
241
detail::read_n(record, m_ifs, sizeof(PointRecord));
244
catch (std::out_of_range const& e) // we reached the end of the file
246
std::cerr << e.what() << std::endl;
250
Reader::FillPoint(record, point);
251
point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
253
if (header.GetDataFormatId() == LASHeader::ePointFormat1) {
254
detail::read_n(t, m_ifs, sizeof(double));
264
bool ReaderImpl::ReadPointAt(std::size_t n, LASPoint& point, const LASHeader& header)
266
// Read point data record format 0
268
// TODO: Replace with compile-time assert
271
detail::PointRecord record;
272
assert(LASHeader::ePointSize0 == sizeof(record));
277
std::streamsize pos = (static_cast<std::streamsize>(n) * header.GetDataRecordLength()) + header.GetDataOffset();
280
m_ifs.seekg(pos, std::ios::beg);
281
detail::read_n(record, m_ifs, sizeof(record));
283
Reader::FillPoint(record, point);
284
point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
286
if (header.GetDataFormatId() == LASHeader::ePointFormat1) {
287
detail::read_n(t, m_ifs, sizeof(double));
294
}}} // namespace liblas::detail::v11