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/liblas.hpp>
43
#include <liblas/detail/reader/reader.hpp>
44
#include <liblas/detail/private_utility.hpp>
46
#include <boost/cstdint.hpp>
52
#include <cstddef> // std::size_t
53
#include <cstdlib> // std::free
56
using namespace boost;
58
namespace liblas { namespace detail {
60
ReaderImpl::ReaderImpl(std::istream& ifs)
64
// , m_point_reader(PointReaderPtr())
65
, m_header_reader(new reader::Header(m_ifs))
66
, m_header(HeaderPtr())
67
, m_point(PointPtr(new liblas::Point()))
70
, bNeedHeaderCheck(false)
75
ReaderImpl::~ReaderImpl()
79
void ReaderImpl::Reset()
84
// Reset sizes and set internal cursor to the beginning of file.
86
m_size = m_header->GetPointRecordsCount();
88
m_record_size = m_header->GetSchema().GetByteSize();
91
void ReaderImpl::TransformPoint(liblas::Point& p)
94
// Apply the transforms to each point
95
std::vector<liblas::TransformPtr>::const_iterator ti;
97
for (ti = m_transforms.begin(); ti != m_transforms.end(); ++ti)
99
liblas::TransformPtr transform = *ti;
100
transform->transform(p);
105
bool ReaderImpl::FilterPoint(liblas::Point const& p)
107
// If there's no filters on this reader, we keep
108
// the point no matter what.
109
if (m_filters.empty() ) {
113
std::vector<liblas::FilterPtr>::const_iterator fi;
114
for (fi = m_filters.begin(); fi != m_filters.end(); ++fi)
116
liblas::FilterPtr filter = *fi;
117
if (!filter->filter(p))
127
void ReaderImpl::ReadHeader()
129
// If we're eof, we need to reset the state
133
m_header_reader->ReadHeader();
134
m_header = m_header_reader->GetHeader();
136
if (m_header->Compressed())
137
throw std::runtime_error("Internal error: uncompressed reader encountered compressed header");
139
m_point->SetHeader(m_header.get());
145
void ReaderImpl::SetHeader(liblas::Header const& header)
147
m_header = HeaderPtr(new liblas::Header(header));
148
m_point->SetHeader(m_header.get());
151
void ReaderImpl::ReadNextPoint()
156
m_ifs.seekg(m_header->GetDataOffset(), std::ios::beg);
159
if (m_current >= m_size ){
160
throw std::out_of_range("ReadNextPoint: file has no more points to read, end of file reached");
163
if (bNeedHeaderCheck)
165
if (!(m_point->GetHeader() == m_header.get()))
166
m_point->SetHeader(m_header.get());
171
detail::read_n(m_point->GetData().front(), m_ifs, m_record_size);
174
} catch (std::runtime_error&)
176
// If the stream is no good anymore, we're done reading points
177
throw std::out_of_range("ReadNextPoint: file has no more points to read, end of file reached");
181
// Filter the points and continue reading until we either find
182
// one to keep or throw an exception.
184
bool bLastPoint = false;
186
if (!m_filters.empty())
188
if (!FilterPoint(*m_point))
193
detail::read_n(m_point->GetData().front(), m_ifs, m_record_size);
196
} catch (std::runtime_error&)
198
// If the stream is no good anymore, we're done reading points
199
throw std::out_of_range("ReadNextPoint: file has no more points to read, end of file reached");
202
while (!FilterPoint(*m_point))
207
detail::read_n(m_point->GetData().front(), m_ifs, m_record_size);
210
} catch (std::runtime_error&)
212
// If the stream is no good anymore, we're done reading points
213
throw std::out_of_range("ReadNextPoint: file has no more points to read, end of file reached");
215
if (m_current == m_size)
225
if (!m_transforms.empty())
227
TransformPoint(*m_point);
231
throw std::out_of_range("ReadNextPoint: file has no more points to read, end of file reached");
236
liblas::Point const& ReaderImpl::ReadPointAt(std::size_t n)
239
throw std::out_of_range("file has no more points to read, end of file reached");
240
} else if (m_size < n) {
241
std::ostringstream msg;
242
msg << "ReadPointAt:: Inputted value: " << n << " is greater than the number of points: " << m_size;
243
throw std::runtime_error(msg.str());
246
std::streamsize const pos = (static_cast<std::streamsize>(n) * m_header->GetDataRecordLength()) + m_header->GetDataOffset();
249
m_ifs.seekg(pos, std::ios::beg);
251
if (bNeedHeaderCheck)
253
if (!(m_point->GetHeader() == m_header.get()))
254
m_point->SetHeader(m_header.get());
257
detail::read_n(m_point->GetData().front(), m_ifs, m_record_size);
259
if (!m_transforms.empty())
261
TransformPoint(*m_point);
266
void ReaderImpl::Seek(std::size_t n)
269
throw std::out_of_range("file has no more points to read, end of file reached");
270
} else if (m_size < n) {
271
std::ostringstream msg;
272
msg << "Seek:: Inputted value: " << n << " is greater than the number of points: " << m_size;
273
throw std::runtime_error(msg.str());
276
std::streamsize pos = (static_cast<std::streamsize>(n) * m_header->GetDataRecordLength()) + m_header->GetDataOffset();
279
m_ifs.seekg(pos, std::ios::beg);
284
void ReaderImpl::SetFilters(std::vector<liblas::FilterPtr> const& filters)
289
std::vector<liblas::FilterPtr> ReaderImpl::GetFilters() const
294
void ReaderImpl::SetTransforms(std::vector<liblas::TransformPtr> const& transforms)
296
m_transforms = transforms;
298
// Transforms are allowed to change the point, including moving the
299
// point's HeaderPtr. We need to check if we need to set that
300
// back on any subsequent reads.
301
if (m_transforms.size() > 0)
303
for (std::vector<liblas::TransformPtr>::const_iterator i = transforms.begin(); i != transforms.end(); i++)
305
if (i->get()->ModifiesHeader())
306
bNeedHeaderCheck = true;
311
std::vector<liblas::TransformPtr> ReaderImpl::GetTransforms() const
316
}} // namespace liblas::detail