bool ReaderImpl::ReadPointAt(std::size_t n, LASPoint& point, const LASHeader& header) { // Read point data record format 0 // TODO: Replace with compile-time assert double t=0; detail::PointRecord record; assert(LASHeader::ePointSize0 == sizeof(record)); if (m_size <= n) return false; std::streamsize pos = (static_cast<std::streamsize>(n) * m_recordlength) + m_offset; m_ifs.clear(); m_ifs.seekg(pos, std::ios::beg); detail::read_n(record, m_ifs, sizeof(record)); Reader::FillPoint(record, point); point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ()); if (header.GetDataFormatId() == LASHeader::ePointFormat1) { detail::read_n(t, m_ifs, sizeof(double)); point.SetTime(t); } return true; }
void WriterImpl::WriteVLR(LASHeader const& header) { m_ofs.seekp(header.GetHeaderSize(), std::ios::beg); for (uint32_t i = 0; i < header.GetRecordsCount(); ++i) { LASVLR vlr = header.GetVLR(i); detail::write_n(m_ofs, vlr.GetReserved(), sizeof(uint16_t)); detail::write_n(m_ofs, vlr.GetUserId(true).c_str(), 16); detail::write_n(m_ofs, vlr.GetRecordId(), sizeof(uint16_t)); detail::write_n(m_ofs, vlr.GetRecordLength(), sizeof(uint16_t)); detail::write_n(m_ofs, vlr.GetDescription(true).c_str(), 32); std::vector<uint8_t> const& data = vlr.GetData(); std::streamsize const size = static_cast<std::streamsize>(data.size()); detail::write_n(m_ofs, data.front(), size); } }
void WriterImpl::UpdateHeader(LASHeader const& header) { if (m_pointCount != header.GetPointRecordsCount()) { // Skip to first byte of number of point records data member std::streamsize const dataPos = 107; m_ofs.seekp(dataPos, std::ios::beg); detail::write_n(m_ofs, m_pointCount , sizeof(m_pointCount)); } }
bool ReaderImpl::ReadNextPoint(LASPoint& point, const LASHeader& header) { // Read point data record format 0 // TODO: Replace with compile-time assert detail::PointRecord record; double t=0; assert(LASHeader::ePointSize0 == sizeof(record)); if (0 == m_current) { m_ifs.clear(); m_ifs.seekg(m_offset, std::ios::beg); } if (m_current < m_size) { try { detail::read_n(record, m_ifs, sizeof(PointRecord)); ++m_current; } catch (std::out_of_range const& e) // we reached the end of the file { std::cerr << e.what() << std::endl; return false; } Reader::FillPoint(record, point); point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ()); if (header.GetDataFormatId() == LASHeader::ePointFormat1) { detail::read_n(t, m_ifs, sizeof(double)); point.SetTime(t); } return true; } return false; }
void WriterImpl::WriteHeader(LASHeader& header) { uint8_t n1 = 0; uint16_t n2 = 0; uint32_t n4 = 0; // Rewrite the georeference VLR entries if they exist header.SetGeoreference(); // Seek to the beginning m_ofs.seekp(0, std::ios::beg); std::ios::pos_type beginning = m_ofs.tellp(); // Seek to the end m_ofs.seekp(0, std::ios::end); std::ios::pos_type end = m_ofs.tellp(); // Figure out how many points we already have. Each point record // should be 20 bytes long, and header.GetDataOffset tells // us the location to start counting points from. // This test should only be true if we were opened in both // std::ios::in *and* std::ios::out, otherwise it should return false // and we won't adjust the point count. if ((beginning != end) && ((uint32_t)end != 0)) { m_pointCount = ((uint32_t) end - header.GetDataOffset())/header.GetDataRecordLength(); // Position to the beginning of the file to start writing the header m_ofs.seekp(0, std::ios::beg); } // 1. File Signature std::string const filesig(header.GetFileSignature()); assert(filesig.size() == 4); detail::write_n(m_ofs, filesig, 4); // 2. Reserved n4 = header.GetReserved(); detail::write_n(m_ofs, n4, sizeof(n4)); // 3-6. GUID data uint32_t d1 = 0; uint16_t d2 = 0; uint16_t d3 = 0; uint8_t d4[8] = { 0 }; liblas::guid g = header.GetProjectId(); g.output_data(d1, d2, d3, d4); detail::write_n(m_ofs, d1, sizeof(d1)); detail::write_n(m_ofs, d2, sizeof(d2)); detail::write_n(m_ofs, d3, sizeof(d3)); detail::write_n(m_ofs, d4, sizeof(d4)); // 7. Version major n1 = header.GetVersionMajor(); assert(1 == n1); detail::write_n(m_ofs, n1, sizeof(n1)); // 8. Version minor n1 = header.GetVersionMinor(); assert(0 == n1); detail::write_n(m_ofs, n1, sizeof(n1)); // 9. System ID std::string sysid(header.GetSystemId(true)); assert(sysid.size() == 32); detail::write_n(m_ofs, sysid, 32); // 10. Generating Software ID std::string softid(header.GetSoftwareId(true)); assert(softid.size() == 32); detail::write_n(m_ofs, softid, 32); // 11. Flight Date Julian n2 = header.GetCreationDOY(); detail::write_n(m_ofs, n2, sizeof(n2)); // 12. Year n2 = header.GetCreationYear(); detail::write_n(m_ofs, n2, sizeof(n2)); // 13. Header Size n2 = header.GetHeaderSize(); assert(227 <= n2); detail::write_n(m_ofs, n2, sizeof(n2)); // 14. Offset to data n4 = header.GetDataOffset(); detail::write_n(m_ofs, n4, sizeof(n4)); // 15. Number of variable length records // TODO: This value must be updated after new variable length record is added. n4 = header.GetRecordsCount(); detail::write_n(m_ofs, n4, sizeof(n4)); // 16. Point Data Format ID n1 = static_cast<uint8_t>(header.GetDataFormatId()); detail::write_n(m_ofs, n1, sizeof(n1)); // 17. Point Data Record Length n2 = header.GetDataRecordLength(); detail::write_n(m_ofs, n2, sizeof(n2)); // 18. Number of point records // This value is updated if necessary, see UpdateHeader function. n4 = header.GetPointRecordsCount(); detail::write_n(m_ofs, n4, sizeof(n4)); // 19. Number of points by return std::vector<uint32_t>::size_type const srbyr = 5; std::vector<uint32_t> const& vpbr = header.GetPointRecordsByReturnCount(); assert(vpbr.size() <= srbyr); uint32_t pbr[srbyr] = { 0 }; std::copy(vpbr.begin(), vpbr.end(), pbr); detail::write_n(m_ofs, pbr, sizeof(pbr)); // 20-22. Scale factors detail::write_n(m_ofs, header.GetScaleX(), sizeof(double)); detail::write_n(m_ofs, header.GetScaleY(), sizeof(double)); detail::write_n(m_ofs, header.GetScaleZ(), sizeof(double)); // 23-25. Offsets detail::write_n(m_ofs, header.GetOffsetX(), sizeof(double)); detail::write_n(m_ofs, header.GetOffsetY(), sizeof(double)); detail::write_n(m_ofs, header.GetOffsetZ(), sizeof(double)); // 26-27. Max/Min X detail::write_n(m_ofs, header.GetMaxX(), sizeof(double)); detail::write_n(m_ofs, header.GetMinX(), sizeof(double)); // 28-29. Max/Min Y detail::write_n(m_ofs, header.GetMaxY(), sizeof(double)); detail::write_n(m_ofs, header.GetMinY(), sizeof(double)); // 30-31. Max/Min Z detail::write_n(m_ofs, header.GetMaxZ(), sizeof(double)); detail::write_n(m_ofs, header.GetMinZ(), sizeof(double)); WriteVLR(header); uint8_t const sgn1 = 0xCC; uint8_t const sgn2 = 0xDD; detail::write_n(m_ofs, sgn1, sizeof(uint8_t)); detail::write_n(m_ofs, sgn2, sizeof(uint8_t)); // If we already have points, we're going to put it at the end of the file. // If we don't have any points, we're going to leave it where it is. if (m_pointCount != 0) m_ofs.seekp(0, std::ios::end); }
bool ReaderImpl::ReadHeader(LASHeader& header) { using detail::read_n; // Helper variables uint8_t n1 = 0; uint16_t n2 = 0; uint32_t n4 = 0; double x1 = 0; double y1 = 0; double z1 = 0; double x2 = 0; double y2 = 0; double z2 = 0; std::string buf; std::string fsig; m_ifs.seekg(0); // 1. File Signature read_n(fsig, m_ifs, 4); header.SetFileSignature(fsig); // 2. Reserved // This data must always contain Zeros. read_n(n4, m_ifs, sizeof(n4)); // 3-6. GUID data uint32_t d1 = 0; uint16_t d2 = 0; uint16_t d3 = 0; uint8_t d4[8] = { 0 }; read_n(d1, m_ifs, sizeof(d1)); read_n(d2, m_ifs, sizeof(d2)); read_n(d3, m_ifs, sizeof(d3)); read_n(d4, m_ifs, sizeof(d4)); liblas::guid g(d1, d2, d3, d4); header.SetProjectId(g); // 7. Version major read_n(n1, m_ifs, sizeof(n1)); header.SetVersionMajor(n1); // 8. Version minor read_n(n1, m_ifs, sizeof(n1)); header.SetVersionMinor(n1); // 9. System ID read_n(buf, m_ifs, 32); header.SetSystemId(buf); // 10. Generating Software ID read_n(buf, m_ifs, 32); header.SetSoftwareId(buf); // 11. Flight Date Julian read_n(n2, m_ifs, sizeof(n2)); header.SetCreationDOY(n2); // 12. Year read_n(n2, m_ifs, sizeof(n2)); header.SetCreationYear(n2); // 13. Header Size // NOTE: Size of the stanard header block must always be 227 bytes read_n(n2, m_ifs, sizeof(n2)); // 14. Offset to data read_n(n4, m_ifs, sizeof(n4)); if (n4 < header.GetHeaderSize()) { // TODO: Move this test to LASHeader::Validate() throw std::domain_error("offset to point data smaller than header size"); } header.SetDataOffset(n4); // 15. Number of variable length records read_n(n4, m_ifs, sizeof(n4)); header.SetRecordsCount(n4); // 16. Point Data Format ID read_n(n1, m_ifs, sizeof(n1)); if (n1 == LASHeader::ePointFormat0) { header.SetDataFormatId(LASHeader::ePointFormat0); } else if (n1 == LASHeader::ePointFormat1) { header.SetDataFormatId(LASHeader::ePointFormat1); } else if (n1 == LASHeader::ePointFormat2) { header.SetDataFormatId(LASHeader::ePointFormat2); } else if (n1 == LASHeader::ePointFormat3) { header.SetDataFormatId(LASHeader::ePointFormat3); } else { throw std::domain_error("invalid point data format"); } // 17. Point Data Record Length // NOTE: No need to set record length because it's // determined on basis of point data format. read_n(n2, m_ifs, sizeof(n2)); // 18. Number of point records read_n(n4, m_ifs, sizeof(n4)); header.SetPointRecordsCount(n4); // 19. Number of points by return std::vector<uint32_t>::size_type const srbyr = 5; uint32_t rbyr[srbyr] = { 0 }; read_n(rbyr, m_ifs, sizeof(rbyr)); for (std::size_t i = 0; i < srbyr; ++i) { header.SetPointRecordsByReturnCount(i, rbyr[i]); } // 20-22. Scale factors read_n(x1, m_ifs, sizeof(x1)); read_n(y1, m_ifs, sizeof(y1)); read_n(z1, m_ifs, sizeof(z1)); header.SetScale(x1, y1, z1); // 23-25. Offsets read_n(x1, m_ifs, sizeof(x1)); read_n(y1, m_ifs, sizeof(y1)); read_n(z1, m_ifs, sizeof(z1)); header.SetOffset(x1, y1, z1); // 26-27. Max/Min X read_n(x1, m_ifs, sizeof(x1)); read_n(x2, m_ifs, sizeof(x2)); // 28-29. Max/Min Y read_n(y1, m_ifs, sizeof(y1)); read_n(y2, m_ifs, sizeof(y2)); // 30-31. Max/Min Z read_n(z1, m_ifs, sizeof(z1)); read_n(z2, m_ifs, sizeof(z2)); header.SetMax(x1, y1, z1); header.SetMin(x2, y2, z2); Reset(header); return true; }