Changeset 1553:c57db71565c3
- Timestamp:
- 02/04/10 19:11:35 (6 months ago)
- Branch:
- hobu-writer-refactor
- Parents:
- 1552:f69ab0ecaa8e (diff), 1545:6623c88bd02f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 8 edited
-
include/liblas/detail/writer/header.hpp (modified) (1 diff)
-
include/liblas/detail/writer/writer10.hpp (modified) (2 diffs)
-
src/detail/reader/reader.cpp (modified) (1 diff)
-
src/detail/reader/reader.cpp (modified) (1 diff)
-
src/detail/writer/header.cpp (modified) (2 diffs)
-
src/detail/writer/writer.cpp (modified) (4 diffs)
-
src/detail/writer/writer10.cpp (modified) (3 diffs)
-
src/laswriter.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
include/liblas/detail/writer/header.hpp
r1545 r1553 43 43 #define LIBLAS_DETAIL_WRITER_HEADER_HPP_INCLUDED 44 44 45 #include <liblas/lasversion.hpp>46 #include <liblas/lasspatialreference.hpp>47 45 #include <liblas/detail/fwd.hpp> 48 46 #include <liblas/detail/utility.hpp> 49 47 48 #include <liblas/lasheader.hpp> 49 #include <liblas/detail/writer/writer10.hpp> 50 50 51 51 // std 52 //#include <iosfwd>52 #include <iosfwd> 53 53 54 54 namespace liblas { namespace detail { namespace writer { 55 55 56 class Header 56 class Header : public WriterCan 57 57 { 58 58 59 public: 60 typedef WriterCan Base; 59 61 60 Header(std::ostream& ofs );61 virtual ~Header();62 63 LASHeader write(const LASHeader& header);64 62 Header(std::ostream& ofs, liblas::uint32_t& count, LASHeader const& header ); 63 64 LASHeader GetHeader() const { return m_header; } 65 void write(); 66 65 67 protected: 66 68 69 private: 70 71 int32_t WriteVLRs(); 72 void WriteLAS10PadSignature(); 73 LASHeader m_header; 74 75 }; 67 76 68 std::ostream& m_ofs;69 70 private:71 72 // Blocked copying operations, declared but not defined.73 Header(Header const& other);74 Header& operator=(Header const& rhs);75 76 77 };78 79 77 }}} // namespace liblas::detail::writer 80 78 -
include/liblas/detail/writer/writer10.hpp
r1545 r1553 44 44 45 45 #include <liblas/lasversion.hpp> 46 #include <liblas/detail/writer/writer.hpp> 47 #include <liblas/ detail/fwd.hpp>46 47 #include <liblas/lasspatialreference.hpp> 48 48 #include <liblas/cstdint.hpp> 49 50 51 #ifndef HAVE_GDAL 52 typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH; 53 typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH; 54 #endif 55 56 49 57 // std 50 58 #include <iosfwd> 51 59 52 namespace liblas { namespace detail { namespace v10 {60 namespace liblas { namespace detail { 53 61 54 class Writer Impl : public Writer62 class WriterCan 55 63 { 56 64 public: 57 65 58 typedef Writer Base; 66 WriterCan(std::ostream& ofs, liblas::uint32_t& count); 67 ~WriterCan(); 68 69 std::ostream& GetStream() const { return m_ofs; } 70 liblas::uint32_t& GetPointCount() const { return m_pointCount; } 71 void SetPointCount(liblas::uint32_t& count) { m_pointCount = count; } 72 73 74 private: 75 76 // Blocked copying operations, declared but not defined. 77 WriterCan(WriterCan const& other); 78 WriterCan& operator=(WriterCan const& rhs); 79 80 81 liblas::uint32_t& m_pointCount; 82 std::ostream& m_ofs; 83 84 85 }; 86 87 88 89 class WriterImpl 90 { 91 public: 92 59 93 60 94 WriterImpl(std::ostream& ofs); 95 ~WriterImpl(); 61 96 LASVersion GetVersion() const; 62 97 void WriteHeader(LASHeader& header); … … 64 99 void WritePointRecord(LASPoint const& record, const LASHeader& header); 65 100 101 std::ostream& GetStream() const; 102 103 void SetSRS(const LASSpatialReference& srs); 104 void SetInputSRS(const LASSpatialReference& srs); 105 void SetOutputSRS(const LASSpatialReference& srs); 106 107 protected: 108 PointRecord m_record; 109 std::ostream& m_ofs; 110 111 void FillPointRecord(PointRecord& record, const LASPoint& point, const LASHeader& header); 112 113 void Project(LASPoint& point); 114 LASSpatialReference m_out_srs; 115 LASSpatialReference m_in_srs; 116 117 OGRCoordinateTransformationH m_transform; 118 OGRSpatialReferenceH m_in_ref; 119 OGRSpatialReferenceH m_out_ref; 120 66 121 private: 67 122 123 void CreateTransform(); 68 124 liblas::uint32_t m_pointCount; 69 125 }; 70 126 71 }} } // namespace liblas::detail::v10127 }} // namespace liblas::detail 72 128 73 129 #endif // LIBLAS_DETAIL_WRITER10_HPP_INCLUDED -
src/detail/reader/reader.cpp
r1545 r1553 257 257 // Determine version of given LAS file and 258 258 // instantiate appropriate reader. 259 uint8_t verMajor = 0;260 uint8_t verMinor = 0;261 ifs.seekg(24, std::ios::beg);262 detail::read_n(verMajor, ifs, 1);263 detail::read_n(verMinor, ifs, 1);259 // uint8_t verMajor = 0; 260 // uint8_t verMinor = 0; 261 // ifs.seekg(24, std::ios::beg); 262 // detail::read_n(verMajor, ifs, 1); 263 // detail::read_n(verMinor, ifs, 1); 264 264 265 265 return new ReaderImpl(ifs); -
src/detail/reader/reader.cpp
r1547 r1553 40 40 ****************************************************************************/ 41 41 42 #include <liblas/detail/reader/reader 10.hpp>42 #include <liblas/detail/reader/reader.hpp> 43 43 #include <liblas/detail/reader/header.hpp> 44 44 #include <liblas/detail/reader/vlr.hpp> 45 45 46 #include <liblas/detail/utility.hpp> 46 47 #include <liblas/lasvariablerecord.hpp> -
src/detail/writer/header.cpp
r1545 r1553 49 49 #include <cstdlib> // std::size_t 50 50 #include <fstream> 51 #include <iosfwd> 51 52 #include <ostream> 53 #include <sstream> 54 #include <stdexcept> 55 #include <string> 52 56 #include <vector> 53 57 … … 55 59 namespace liblas { namespace detail { namespace writer { 56 60 57 Header::Header(std::ostream& ofs ) :58 m_ofs(ofs)61 Header::Header(std::ostream& ofs, liblas::uint32_t& count, LASHeader const& header) : 62 Base(ofs, count) 59 63 { 64 m_header = header; 60 65 } 61 66 62 Header::~Header()67 void Header::write() 63 68 { 64 69 70 uint8_t n1 = 0; 71 uint16_t n2 = 0; 72 uint32_t n4 = 0; 73 74 // Rewrite the georeference VLR entries if they exist 75 m_header.SetGeoreference(); 76 77 // Seek to the beginning 78 GetStream().seekp(0, std::ios::beg); 79 std::ios::pos_type beginning = GetStream().tellp(); 80 81 // Seek to the end 82 GetStream().seekp(0, std::ios::end); 83 std::ios::pos_type end = GetStream().tellp(); 84 85 // Figure out how many points we already have. Each point record 86 // should be 20 bytes long, and header.GetDataOffset tells 87 // us the location to start counting points from. 88 89 // This test should only be true if we were opened in both 90 // std::ios::in *and* std::ios::out, otherwise it should return false 91 // and we won't adjust the point count. 92 93 if ((beginning != end) && ((uint32_t)end != 0)) { 94 uint32_t count = ((uint32_t) end - m_header.GetDataOffset())/m_header.GetDataRecordLength(); 95 SetPointCount(count); 96 97 // Position to the beginning of the file to start writing the header 98 GetStream().seekp(0, std::ios::beg); 99 } 100 101 // 1. File Signature 102 std::string const filesig(m_header.GetFileSignature()); 103 assert(filesig.size() == 4); 104 detail::write_n(GetStream(), filesig, 4); 105 106 107 // 2. File SourceId / Reserved 108 if (m_header.GetVersionMinor() == 0) { 109 n4 = m_header.GetReserved(); 110 detail::write_n(GetStream(), n4, sizeof(n4)); 111 } else if (m_header.GetVersionMinor() > 0) { 112 n2 = m_header.GetFileSourceId(); 113 detail::write_n(GetStream(), n2, sizeof(n2)); 114 n2 = m_header.GetReserved(); 115 detail::write_n(GetStream(), n2, sizeof(n2)); 116 } 117 118 119 // 3-6. GUID data 120 uint32_t d1 = 0; 121 uint16_t d2 = 0; 122 uint16_t d3 = 0; 123 uint8_t d4[8] = { 0 }; 124 liblas::guid g = m_header.GetProjectId(); 125 g.output_data(d1, d2, d3, d4); 126 detail::write_n(GetStream(), d1, sizeof(d1)); 127 detail::write_n(GetStream(), d2, sizeof(d2)); 128 detail::write_n(GetStream(), d3, sizeof(d3)); 129 detail::write_n(GetStream(), d4, sizeof(d4)); 130 131 // 7. Version major 132 n1 = m_header.GetVersionMajor(); 133 assert(1 == n1); 134 detail::write_n(GetStream(), n1, sizeof(n1)); 135 136 // 8. Version minor 137 n1 = m_header.GetVersionMinor(); 138 detail::write_n(GetStream(), n1, sizeof(n1)); 139 140 // 9. System ID 141 std::string sysid(m_header.GetSystemId(true)); 142 assert(sysid.size() == 32); 143 detail::write_n(GetStream(), sysid, 32); 144 145 // 10. Generating Software ID 146 std::string softid(m_header.GetSoftwareId(true)); 147 assert(softid.size() == 32); 148 detail::write_n(GetStream(), softid, 32); 149 150 // 11. Flight Date Julian 151 n2 = m_header.GetCreationDOY(); 152 detail::write_n(GetStream(), n2, sizeof(n2)); 153 154 // 12. Year 155 n2 = m_header.GetCreationYear(); 156 detail::write_n(GetStream(), n2, sizeof(n2)); 157 158 // 13. Header Size 159 n2 = m_header.GetHeaderSize(); 160 assert(227 <= n2); 161 detail::write_n(GetStream(), n2, sizeof(n2)); 162 163 // 14. Offset to data 164 // For 1.0 data, we must also add pad bytes to the end of the 165 // m_header. This means resetting the dataoffset +=2 166 if (m_header.GetVersionMinor() == 0) { 167 int32_t difference = m_header.GetDataOffset() - m_header.GetHeaderSize(); 168 if ( (m_header.GetDataOffset() != m_header.GetHeaderSize()) && 169 (difference > 0) && ( difference >= 2) 170 ) 171 { 172 n4 = m_header.GetDataOffset(); 173 } 174 else if (difference == 0) 175 { 176 n4 = m_header.GetDataOffset() + 2; 177 } 178 else if (difference < 0) 179 { 180 throw std::out_of_range("DataOffset is smaller than HeaderSize!"); 181 } 182 else 183 { 184 n4 = m_header.GetDataOffset() + 2; 185 } 186 // n4 = m_header.GetDataOffset() + 2; 187 } else { 188 n4 = m_header.GetDataOffset(); 189 } 190 detail::write_n(GetStream(), n4, sizeof(n4)); 191 192 // 15. Number of variable length records 193 // TODO: This value must be updated after new variable length record is added. 194 n4 = m_header.GetRecordsCount(); 195 detail::write_n(GetStream(), n4, sizeof(n4)); 196 197 // 16. Point Data Format ID 198 n1 = static_cast<uint8_t>(m_header.GetDataFormatId()); 199 detail::write_n(GetStream(), n1, sizeof(n1)); 200 201 // 17. Point Data Record Length 202 n2 = m_header.GetDataRecordLength(); 203 detail::write_n(GetStream(), n2, sizeof(n2)); 204 205 // 18. Number of point records 206 // This value is updated if necessary, see UpdateHeader function. 207 n4 = m_header.GetPointRecordsCount(); 208 detail::write_n(GetStream(), n4, sizeof(n4)); 209 210 // 19. Number of points by return 211 std::vector<uint32_t>::size_type const srbyr = 5; 212 std::vector<uint32_t> const& vpbr = m_header.GetPointRecordsByReturnCount(); 213 assert(vpbr.size() <= srbyr); 214 uint32_t pbr[srbyr] = { 0 }; 215 std::copy(vpbr.begin(), vpbr.end(), pbr); 216 detail::write_n(GetStream(), pbr, sizeof(pbr)); 217 218 // 20-22. Scale factors 219 detail::write_n(GetStream(), m_header.GetScaleX(), sizeof(double)); 220 detail::write_n(GetStream(), m_header.GetScaleY(), sizeof(double)); 221 detail::write_n(GetStream(), m_header.GetScaleZ(), sizeof(double)); 222 223 // 23-25. Offsets 224 detail::write_n(GetStream(), m_header.GetOffsetX(), sizeof(double)); 225 detail::write_n(GetStream(), m_header.GetOffsetY(), sizeof(double)); 226 detail::write_n(GetStream(), m_header.GetOffsetZ(), sizeof(double)); 227 228 // 26-27. Max/Min X 229 detail::write_n(GetStream(), m_header.GetMaxX(), sizeof(double)); 230 detail::write_n(GetStream(), m_header.GetMinX(), sizeof(double)); 231 232 // 28-29. Max/Min Y 233 detail::write_n(GetStream(), m_header.GetMaxY(), sizeof(double)); 234 detail::write_n(GetStream(), m_header.GetMinY(), sizeof(double)); 235 236 // 30-31. Max/Min Z 237 detail::write_n(GetStream(), m_header.GetMaxZ(), sizeof(double)); 238 detail::write_n(GetStream(), m_header.GetMinZ(), sizeof(double)); 239 240 // If WriteVLR returns a value, it is because the header's 241 // offset is not large enough to contain the VLRs. The value 242 // it returns is the number of bytes we must increase the header 243 // by in order for it to contain the VLRs. 244 245 int32_t difference = WriteVLRs(); 246 if (difference < 0) { 247 m_header.SetDataOffset(m_header.GetDataOffset() + abs(difference) ); 248 WriteVLRs(); 249 250 // Make sure to rewrite the dataoffset in the header portion now that 251 // we've changed it. 252 std::streamsize const current_pos = GetStream().tellp(); 253 std::streamsize const offset_pos = 96; 254 GetStream().seekp(offset_pos, std::ios::beg); 255 detail::write_n(GetStream(), m_header.GetDataOffset() , sizeof(m_header.GetDataOffset())); 256 GetStream().seekp(current_pos, std::ios::beg); 257 } 258 259 260 261 // Write the 1.0 pad signature if we need to. 262 WriteLAS10PadSignature(); 263 264 // If we already have points, we're going to put it at the end of the file. 265 // If we don't have any points, we're going to leave it where it is. 266 if (GetPointCount() != 0) 267 GetStream().seekp(0, std::ios::end); 65 268 } 66 269 67 68 LASHeader Header::write(const LASHeader& header) 270 int32_t Header::WriteVLRs() 69 271 { 70 LASHeader output(header); 71 return output; 72 // 73 // uint8_t n1 = 0; 74 // uint16_t n2 = 0; 75 // uint32_t n4 = 0; 76 // 77 // // Rewrite the georeference VLR entries if they exist 78 // output.SetGeoreference(); 79 // 80 // // Seek to the beginning 81 // m_ofs.seekp(0, std::ios::beg); 82 // std::ios::pos_type beginning = m_ofs.tellp(); 83 // 84 // // Seek to the end 85 // m_ofs.seekp(0, std::ios::end); 86 // std::ios::pos_type end = m_ofs.tellp(); 87 // 88 // // Figure out how many points we already have. Each point record 89 // // should be 20 bytes long, and header.GetDataOffset tells 90 // // us the location to start counting points from. 91 // 92 // // This test should only be true if we were opened in both 93 // // std::ios::in *and* std::ios::out, otherwise it should return false 94 // // and we won't adjust the point count. 95 // 96 // if ((beginning != end) && ((uint32_t)end != 0)) { 97 // m_pointCount = ((uint32_t) end - output.GetDataOffset())/output.GetDataRecordLength(); 98 // 99 // // Position to the beginning of the file to start writing the header 100 // m_ofs.seekp(0, std::ios::beg); 101 // } 102 // 103 // // 1. File Signature 104 // std::string const filesig(output.GetFileSignature()); 105 // assert(filesig.size() == 4); 106 // detail::write_n(m_ofs, filesig, 4); 107 // 108 // // 2. Reserved 109 // n4 = output.GetReserved(); 110 // detail::write_n(m_ofs, n4, sizeof(n4)); 111 // 112 // // 3-6. GUID data 113 // uint32_t d1 = 0; 114 // uint16_t d2 = 0; 115 // uint16_t d3 = 0; 116 // uint8_t d4[8] = { 0 }; 117 // liblas::guid g = output.GetProjectId(); 118 // g.output_data(d1, d2, d3, d4); 119 // detail::write_n(m_ofs, d1, sizeof(d1)); 120 // detail::write_n(m_ofs, d2, sizeof(d2)); 121 // detail::write_n(m_ofs, d3, sizeof(d3)); 122 // detail::write_n(m_ofs, d4, sizeof(d4)); 123 // 124 // // 7. Version major 125 // n1 = output.GetVersionMajor(); 126 // assert(1 == n1); 127 // detail::write_n(m_ofs, n1, sizeof(n1)); 128 // 129 // // 8. Version minor 130 // n1 = output.GetVersionMinor(); 131 // assert(0 == n1); 132 // detail::write_n(m_ofs, n1, sizeof(n1)); 133 // 134 // // 9. System ID 135 // std::string sysid(output.GetSystemId(true)); 136 // assert(sysid.size() == 32); 137 // detail::write_n(m_ofs, sysid, 32); 138 // 139 // // 10. Generating Software ID 140 // std::string softid(output.GetSoftwareId(true)); 141 // assert(softid.size() == 32); 142 // detail::write_n(m_ofs, softid, 32); 143 // 144 // // 11. Flight Date Julian 145 // n2 = output.GetCreationDOY(); 146 // detail::write_n(m_ofs, n2, sizeof(n2)); 147 // 148 // // 12. Year 149 // n2 = output.GetCreationYear(); 150 // detail::write_n(m_ofs, n2, sizeof(n2)); 151 // 152 // // 13. Header Size 153 // n2 = output.GetHeaderSize(); 154 // assert(227 <= n2); 155 // detail::write_n(m_ofs, n2, sizeof(n2)); 156 // 157 // // 14. Offset to data 158 // // Because we are 1.0, we must also add pad bytes to the end of the 159 // // header. This means resetting the dataoffset +=2, but we 160 // // don't want to change the header's actual offset until after we 161 // // write the VLRs or else we'll be off by 2 when we write the pad 162 // // bytes 163 // n4 = output.GetDataOffset() + 2; 164 // detail::write_n(m_ofs, n4, sizeof(n4)); 165 // 166 // // 15. Number of variable length records 167 // // TODO: This value must be updated after new variable length record is added. 168 // n4 = output.GetRecordsCount(); 169 // detail::write_n(m_ofs, n4, sizeof(n4)); 170 // 171 // // 16. Point Data Format ID 172 // n1 = static_cast<uint8_t>(output.GetDataFormatId()); 173 // detail::write_n(m_ofs, n1, sizeof(n1)); 174 // 175 // // 17. Point Data Record Length 176 // n2 = output.GetDataRecordLength(); 177 // detail::write_n(m_ofs, n2, sizeof(n2)); 178 // 179 // // 18. Number of point records 180 // // This value is updated if necessary, see UpdateHeader function. 181 // n4 = output.GetPointRecordsCount(); 182 // detail::write_n(m_ofs, n4, sizeof(n4)); 183 // 184 // // 19. Number of points by return 185 // std::vector<uint32_t>::size_type const srbyr = 5; 186 // std::vector<uint32_t> const& vpbr = output.GetPointRecordsByReturnCount(); 187 // assert(vpbr.size() <= srbyr); 188 // uint32_t pbr[srbyr] = { 0 }; 189 // std::copy(vpbr.begin(), vpbr.end(), pbr); 190 // detail::write_n(m_ofs, pbr, sizeof(pbr)); 191 // 192 // // 20-22. Scale factors 193 // detail::write_n(m_ofs, output.GetScaleX(), sizeof(double)); 194 // detail::write_n(m_ofs, output.GetScaleY(), sizeof(double)); 195 // detail::write_n(m_ofs, output.GetScaleZ(), sizeof(double)); 196 // 197 // // 23-25. Offsets 198 // detail::write_n(m_ofs, output.GetOffsetX(), sizeof(double)); 199 // detail::write_n(m_ofs, output.GetOffsetY(), sizeof(double)); 200 // detail::write_n(m_ofs, output.GetOffsetZ(), sizeof(double)); 201 // 202 // // 26-27. Max/Min X 203 // detail::write_n(m_ofs, output.GetMaxX(), sizeof(double)); 204 // detail::write_n(m_ofs, output.GetMinX(), sizeof(double)); 205 // 206 // // 28-29. Max/Min Y 207 // detail::write_n(m_ofs, output.GetMaxY(), sizeof(double)); 208 // detail::write_n(m_ofs, output.GetMinY(), sizeof(double)); 209 // 210 // // 30-31. Max/Min Z 211 // detail::write_n(m_ofs, output.GetMaxZ(), sizeof(double)); 212 // detail::write_n(m_ofs, output.GetMinZ(), sizeof(double)); 213 // 214 // // If WriteVLR returns a value, it is because the header's 215 // // offset is not large enough to contain the VLRs. The value 216 // // it returns is the number of bytes we must increase the header 217 // // by in order for it to contain the VLRs. 218 // 219 // int32_t difference = WriteVLR(header); 220 // if (difference < 0) { 221 // output.SetDataOffset(output.GetDataOffset() + abs(difference) ); 222 // WriteVLR(output); 223 // } 224 // 225 // // Write the pad bytes. 226 // uint8_t const sgn1 = 0xCC; 227 // uint8_t const sgn2 = 0xDD; 228 // detail::write_n(m_ofs, sgn1, sizeof(uint8_t)); 229 // detail::write_n(m_ofs, sgn2, sizeof(uint8_t)); 230 // 231 // // We can now reset the header's offset to +=2. If we monkeypatched 232 // // the offset because we were too small to write the VLRs, this will 233 // // end up being header.GetDataOffset() + difference + 2 (see above). 234 // output.SetDataOffset(output.GetDataOffset() + 2); 235 // 236 // // Make sure to rewrite the dataoffset in the header portion now that 237 // // we've changed it. 238 // std::streamsize const current_pos = m_ofs.tellp(); 239 // std::streamsize const offset_pos = 96; 240 // m_ofs.seekp(offset_pos, std::ios::beg); 241 // detail::write_n(m_ofs, output.GetDataOffset() , sizeof(output.GetDataOffset())); 242 // m_ofs.seekp(current_pos, std::ios::beg); 243 // 244 // 245 // 246 // // If we already have points, we're going to put it at the end of the file. 247 // // If we don't have any points, we're going to leave it where it is. 248 // if (m_pointCount != 0) 249 // m_ofs.seekp(0, std::ios::end); 272 // If this function returns a value, it is the size that the header's 273 // data offset must be increased by in order for the VLRs to fit in 274 // the header. 275 GetStream().seekp(m_header.GetHeaderSize(), std::ios::beg); 276 277 // if the VLRs won't fit because the data offset is too 278 // small, we need to throw an error. 279 uint32_t vlr_total_size = 0; 280 281 // Calculate a new data offset size 282 for (uint32_t i = 0; i < m_header.GetRecordsCount(); ++i) 283 { 284 LASVariableRecord vlr = m_header.GetVLR(i); 285 vlr_total_size += vlr.GetTotalSize(); 286 } 287 288 int32_t difference = m_header.GetDataOffset() - (vlr_total_size + m_header.GetHeaderSize()); 289 290 if (difference < 0) 291 { 292 return difference; 293 } 294 295 for (uint32_t i = 0; i < m_header.GetRecordsCount(); ++i) 296 { 297 LASVariableRecord vlr = m_header.GetVLR(i); 298 299 detail::write_n(GetStream(), vlr.GetReserved(), sizeof(uint16_t)); 300 detail::write_n(GetStream(), vlr.GetUserId(true).c_str(), 16); 301 detail::write_n(GetStream(), vlr.GetRecordId(), sizeof(uint16_t)); 302 detail::write_n(GetStream(), vlr.GetRecordLength(), sizeof(uint16_t)); 303 detail::write_n(GetStream(), vlr.GetDescription(true).c_str(), 32); 304 std::vector<uint8_t> const& data = vlr.GetData(); 305 std::streamsize const size = static_cast<std::streamsize>(data.size()); 306 detail::write_n(GetStream(), data.front(), size); 307 } 308 309 // if we had more room than we need for the VLRs, we need to pad that with 310 // 0's. We must also not forget to add the 1.0 pad bytes to the end of this 311 // but the impl should be the one doing that, not us. 312 if (difference > 0) { 313 detail::write_n(GetStream(), "\0", difference); 314 } 315 return 0; 250 316 } 251 317 318 void Header::WriteLAS10PadSignature() 319 { 320 // Only write pad signature bytes for LAS 1.0 files. Any other files 321 // will not get the pad bytes and we are *not* allowing anyone to 322 // override this either - hobu 323 324 if (m_header.GetVersionMinor() > 0) { 325 return; 326 } 327 328 // Write the pad bytes. 329 uint8_t const sgn1 = 0xCC; 330 uint8_t const sgn2 = 0xDD; 331 detail::write_n(GetStream(), sgn1, sizeof(uint8_t)); 332 detail::write_n(GetStream(), sgn2, sizeof(uint8_t)); 333 } 334 335 252 336 }}} // namespace liblas::detail::writer -
src/detail/writer/writer.cpp
r1545 r1553 42 42 #include <liblas/detail/writer/writer.hpp> 43 43 #include <liblas/detail/writer/writer10.hpp> 44 #include <liblas/detail/writer/writer11.hpp> 45 #include <liblas/detail/writer/writer12.hpp> 44 46 45 #include <liblas/detail/utility.hpp> 47 46 #include <liblas/lasheader.hpp> … … 66 65 namespace liblas { namespace detail { 67 66 68 Writer::Writer(std::ostream& ofs) : m_ofs(ofs), m_transform(0), m_in_ref(0), m_out_ref(0)69 {70 }71 72 Writer::~Writer()73 {74 #ifdef HAVE_GDAL75 if (m_transform) {76 OCTDestroyCoordinateTransformation(m_transform);77 }78 if (m_in_ref) {79 OSRDestroySpatialReference(m_in_ref);80 }81 if (m_out_ref) {82 OSRDestroySpatialReference(m_out_ref);83 }84 #endif85 }86 87 std::ostream& Writer::GetStream() const88 {89 return m_ofs;90 }91 92 93 void Writer::FillPointRecord(PointRecord& record, const LASPoint& point, const LASHeader& header)94 {95 96 if (m_transform) {97 // let's just copy the point for now.98 LASPoint p = LASPoint(point);99 Project(p);100 record.x = static_cast<int32_t>((p.GetX() - header.GetOffsetX()) / header.GetScaleX());101 record.y = static_cast<int32_t>((p.GetY() - header.GetOffsetY()) / header.GetScaleY());102 record.z = static_cast<int32_t>((p.GetZ() - header.GetOffsetZ()) / header.GetScaleZ());103 } else {104 record.x = static_cast<int32_t>((point.GetX() - header.GetOffsetX()) / header.GetScaleX());105 record.y = static_cast<int32_t>((point.GetY() - header.GetOffsetY()) / header.GetScaleY());106 record.z = static_cast<int32_t>((point.GetZ() - header.GetOffsetZ()) / header.GetScaleZ());107 }108 109 LASClassification::bitset_type clsflags(point.GetClassification());110 record.classification = static_cast<uint8_t>(clsflags.to_ulong());111 112 record.intensity = point.GetIntensity();113 record.flags = point.GetScanFlags();114 record.scan_angle_rank = point.GetScanAngleRank();115 record.user_data = point.GetUserData();116 record.point_source_id = point.GetPointSourceID();117 }118 119 uint32_t Writer::WriteVLR(LASHeader const& header)120 {121 // If this function returns a value, it is the size that the header's122 // data offset must be increased by in order for the VLRs to fit in123 // the header.124 m_ofs.seekp(header.GetHeaderSize(), std::ios::beg);125 126 // if the VLRs won't fit because the data offset is too127 // small, we need to throw an error.128 uint32_t vlr_total_size = 0;129 130 // Calculate a new data offset size131 for (uint32_t i = 0; i < header.GetRecordsCount(); ++i)132 {133 LASVariableRecord vlr = header.GetVLR(i);134 vlr_total_size += vlr.GetTotalSize();135 }136 137 int32_t difference = header.GetDataOffset() - (vlr_total_size + header.GetHeaderSize());138 139 if (difference < 0)140 {141 return difference;142 }143 144 for (uint32_t i = 0; i < header.GetRecordsCount(); ++i)145 {146 LASVariableRecord vlr = header.GetVLR(i);147 148 detail::write_n(m_ofs, vlr.GetReserved(), sizeof(uint16_t));149 detail::write_n(m_ofs, vlr.GetUserId(true).c_str(), 16);150 detail::write_n(m_ofs, vlr.GetRecordId(), sizeof(uint16_t));151 detail::write_n(m_ofs, vlr.GetRecordLength(), sizeof(uint16_t));152 detail::write_n(m_ofs, vlr.GetDescription(true).c_str(), 32);153 std::vector<uint8_t> const& data = vlr.GetData();154 std::streamsize const size = static_cast<std::streamsize>(data.size());155 detail::write_n(m_ofs, data.front(), size);156 }157 158 // if we had more room than we need for the VLRs, we need to pad that with159 // 0's. We must also not forget to add the 1.0 pad bytes to the end of this160 // but the impl should be the one doing that, not us.161 if (difference > 0) {162 detail::write_n(m_ofs, "\0", difference);163 }164 return 0;165 }166 167 168 void Writer::SetOutputSRS(const LASSpatialReference& srs )169 {170 m_out_srs = srs;171 CreateTransform();172 173 }174 175 void Writer::SetSRS(const LASSpatialReference& srs )176 {177 SetOutputSRS(srs);178 }179 180 void Writer::SetInputSRS(const LASSpatialReference& srs )181 {182 m_in_srs = srs;183 }184 185 void Writer::CreateTransform()186 {187 #ifdef HAVE_GDAL188 if (m_transform)189 {190 OCTDestroyCoordinateTransformation(m_transform);191 }192 if (m_in_ref)193 {194 OSRDestroySpatialReference(m_in_ref);195 }196 if (m_out_ref)197 {198 OSRDestroySpatialReference(m_out_ref);199 }200 201 m_in_ref = OSRNewSpatialReference(0);202 m_out_ref = OSRNewSpatialReference(0);203 204 int result = OSRSetFromUserInput(m_in_ref, m_in_srs.GetWKT().c_str());205 if (result != OGRERR_NONE)206 {207 std::ostringstream msg;208 msg << "Could not import input spatial reference for Writer::" << CPLGetLastErrorMsg() << result;209 std::string message(msg.str());210 throw std::runtime_error(message);211 }212 213 result = OSRSetFromUserInput(m_out_ref, m_out_srs.GetWKT().c_str());214 if (result != OGRERR_NONE)215 {216 std::ostringstream msg;217 msg << "Could not import output spatial reference for Writer::" << CPLGetLastErrorMsg() << result;218 std::string message(msg.str());219 throw std::runtime_error(message);220 }221 222 m_transform = OCTNewCoordinateTransformation( m_in_ref, m_out_ref);223 #endif224 }225 226 void Writer::Project(LASPoint& p)227 {228 #ifdef HAVE_GDAL229 230 int ret = 0;231 double x = p.GetX();232 double y = p.GetY();233 double z = p.GetZ();234 235 ret = OCTTransform(m_transform, 1, &x, &y, &z);236 237 if (!ret) {238 std::ostringstream msg;239 msg << "Could not project point for Writer::" << CPLGetLastErrorMsg() << ret;240 std::string message(msg.str());241 throw std::runtime_error(message);242 }243 244 p.SetX(x);245 p.SetY(y);246 p.SetZ(z);247 #else248 detail::ignore_unused_variable_warning(p);249 #endif250 }251 252 Writer * WriterFactory::Create(std::ostream& ofs, LASHeader const& header)67 // Writer::Writer(std::ostream& ofs) : m_ofs(ofs), m_transform(0), m_in_ref(0), m_out_ref(0) 68 // { 69 // } 70 // 71 // Writer::~Writer() 72 // { 73 // #ifdef HAVE_GDAL 74 // if (m_transform) { 75 // OCTDestroyCoordinateTransformation(m_transform); 76 // } 77 // if (m_in_ref) { 78 // OSRDestroySpatialReference(m_in_ref); 79 // } 80 // if (m_out_ref) { 81 // OSRDestroySpatialReference(m_out_ref); 82 // } 83 // #endif 84 // } 85 // 86 // std::ostream& Writer::GetStream() const 87 // { 88 // return m_ofs; 89 // } 90 // 91 // 92 // void Writer::FillPointRecord(PointRecord& record, const LASPoint& point, const LASHeader& header) 93 // { 94 // 95 // if (m_transform) { 96 // // let's just copy the point for now. 97 // LASPoint p = LASPoint(point); 98 // Project(p); 99 // record.x = static_cast<int32_t>((p.GetX() - header.GetOffsetX()) / header.GetScaleX()); 100 // record.y = static_cast<int32_t>((p.GetY() - header.GetOffsetY()) / header.GetScaleY()); 101 // record.z = static_cast<int32_t>((p.GetZ() - header.GetOffsetZ()) / header.GetScaleZ()); 102 // } else { 103 // record.x = static_cast<int32_t>((point.GetX() - header.GetOffsetX()) / header.GetScaleX()); 104 // record.y = static_cast<int32_t>((point.GetY() - header.GetOffsetY()) / header.GetScaleY()); 105 // record.z = static_cast<int32_t>((point.GetZ() - header.GetOffsetZ()) / header.GetScaleZ()); 106 // } 107 // 108 // LASClassification::bitset_type clsflags(point.GetClassification()); 109 // record.classification = static_cast<uint8_t>(clsflags.to_ulong()); 110 // 111 // record.intensity = point.GetIntensity(); 112 // record.flags = point.GetScanFlags(); 113 // record.scan_angle_rank = point.GetScanAngleRank(); 114 // record.user_data = point.GetUserData(); 115 // record.point_source_id = point.GetPointSourceID(); 116 // } 117 // 118 // // uint32_t Writer::WriteVLR(LASHeader const& header) 119 // // { 120 // // // If this function returns a value, it is the size that the header's 121 // // // data offset must be increased by in order for the VLRs to fit in 122 // // // the header. 123 // // m_ofs.seekp(header.GetHeaderSize(), std::ios::beg); 124 // // 125 // // // if the VLRs won't fit because the data offset is too 126 // // // small, we need to throw an error. 127 // // uint32_t vlr_total_size = 0; 128 // // 129 // // // Calculate a new data offset size 130 // // for (uint32_t i = 0; i < header.GetRecordsCount(); ++i) 131 // // { 132 // // LASVariableRecord vlr = header.GetVLR(i); 133 // // vlr_total_size += vlr.GetTotalSize(); 134 // // } 135 // // 136 // // int32_t difference = header.GetDataOffset() - (vlr_total_size + header.GetHeaderSize()); 137 // // 138 // // if (difference < 0) 139 // // { 140 // // return difference; 141 // // } 142 // // 143 // // for (uint32_t i = 0; i < header.GetRecordsCount(); ++i) 144 // // { 145 // // LASVariableRecord vlr = header.GetVLR(i); 146 // // 147 // // detail::write_n(m_ofs, vlr.GetReserved(), sizeof(uint16_t)); 148 // // detail::write_n(m_ofs, vlr.GetUserId(true).c_str(), 16); 149 // // detail::write_n(m_ofs, vlr.GetRecordId(), sizeof(uint16_t)); 150 // // detail::write_n(m_ofs, vlr.GetRecordLength(), sizeof(uint16_t)); 151 // // detail::write_n(m_ofs, vlr.GetDescription(true).c_str(), 32); 152 // // std::vector<uint8_t> const& data = vlr.GetData(); 153 // // std::streamsize const size = static_cast<std::streamsize>(data.size()); 154 // // detail::write_n(m_ofs, data.front(), size); 155 // // } 156 // // 157 // // // if we had more room than we need for the VLRs, we need to pad that with 158 // // // 0's. We must also not forget to add the 1.0 pad bytes to the end of this 159 // // // but the impl should be the one doing that, not us. 160 // // if (difference > 0) { 161 // // detail::write_n(m_ofs, "\0", difference); 162 // // } 163 // // return 0; 164 // // } 165 // 166 // 167 // void Writer::SetOutputSRS(const LASSpatialReference& srs ) 168 // { 169 // m_out_srs = srs; 170 // CreateTransform(); 171 // 172 // } 173 // 174 // void Writer::SetSRS(const LASSpatialReference& srs ) 175 // { 176 // SetOutputSRS(srs); 177 // } 178 // 179 // void Writer::SetInputSRS(const LASSpatialReference& srs ) 180 // { 181 // m_in_srs = srs; 182 // } 183 // 184 // void Writer::CreateTransform() 185 // { 186 // #ifdef HAVE_GDAL 187 // if (m_transform) 188 // { 189 // OCTDestroyCoordinateTransformation(m_transform); 190 // } 191 // if (m_in_ref) 192 // { 193 // OSRDestroySpatialReference(m_in_ref); 194 // } 195 // if (m_out_ref) 196 // { 197 // OSRDestroySpatialReference(m_out_ref); 198 // } 199 // 200 // m_in_ref = OSRNewSpatialReference(0); 201 // m_out_ref = OSRNewSpatialReference(0); 202 // 203 // int result = OSRSetFromUserInput(m_in_ref, m_in_srs.GetWKT().c_str()); 204 // if (result != OGRERR_NONE) 205 // { 206 // std::ostringstream msg; 207 // msg << "Could not import input spatial reference for Writer::" << CPLGetLastErrorMsg() << result; 208 // std::string message(msg.str()); 209 // throw std::runtime_error(message); 210 // } 211 // 212 // result = OSRSetFromUserInput(m_out_ref, m_out_srs.GetWKT().c_str()); 213 // if (result != OGRERR_NONE) 214 // { 215 // std::ostringstream msg; 216 // msg << "Could not import output spatial reference for Writer::" << CPLGetLastErrorMsg() << result; 217 // std::string message(msg.str()); 218 // throw std::runtime_error(message); 219 // } 220 // 221 // m_transform = OCTNewCoordinateTransformation( m_in_ref, m_out_ref); 222 // #endif 223 // } 224 // 225 // void Writer::Project(LASPoint& p) 226 // { 227 // #ifdef HAVE_GDAL 228 // 229 // int ret = 0; 230 // double x = p.GetX(); 231 // double y = p.GetY(); 232 // double z = p.GetZ(); 233 // 234 // ret = OCTTransform(m_transform, 1, &x, &y, &z); 235 // 236 // if (!ret) { 237 // std::ostringstream msg; 238 // msg << "Could not project point for Writer::" << CPLGetLastErrorMsg() << ret; 239 // std::string message(msg.str()); 240 // throw std::runtime_error(message); 241 // } 242 // 243 // p.SetX(x); 244 // p.SetY(y); 245 // p.SetZ(z); 246 // #else 247 // detail::ignore_unused_variable_warning(p); 248 // #endif 249 // } 250 251 WriterImpl* WriterFactory::Create(std::ostream& ofs, LASHeader const& header) 253 252 { 254 253 if (!ofs) … … 258 257 259 258 // Select writer implementation based on requested LAS version. 260 uint8_t major = header.GetVersionMajor();261 uint8_t minor = header.GetVersionMinor();259 // uint8_t major = header.GetVersionMajor(); 260 // uint8_t minor = header.GetVersionMinor(); 262 261 263 if (1 == major && 0 == minor) 264 { 265 return new v10::WriterImpl(ofs); 266 } 267 if (1 == major && 1 == minor) 268 { 269 return new v11::WriterImpl(ofs); 270 } 271 if (1 == major && 2 == minor) 272 { 273 return new v12::WriterImpl(ofs); 274 } 275 else if (2 == major && 0 == minor) 276 { 277 // TODO: LAS 2.0 read/write support 278 throw std::runtime_error("LAS 2.0 file detected but unsupported"); 279 } 280 281 throw std::runtime_error("LAS file of unknown version"); 282 } 283 284 void WriterFactory::Destroy(Writer* p) 262 return new detail::WriterImpl(ofs); 263 // else if (2 == major && 0 == minor) 264 // { 265 // // TODO: LAS 2.0 read/write support 266 // throw std::runtime_error("LAS 2.0 file detected but unsupported"); 267 // } 268 // 269 // throw std::runtime_error("LAS file of unknown version"); 270 } 271 272 void WriterFactory::Destroy(detail::WriterImpl* p) 285 273 { 286 274 delete p; … … 288 276 } 289 277 278 279 WriterCan::WriterCan(std::ostream& ofs, liblas::uint32_t& count) : m_pointCount(count), m_ofs(ofs) 280 { 281 } 282 283 WriterCan::~WriterCan() 284 { 285 286 } 287 290 288 }} // namespace liblas::detail -
src/detail/writer/writer10.cpp
r1545 r1553 41 41 42 42 #include <liblas/detail/writer/writer10.hpp> 43 #include <liblas/detail/writer/header.hpp> 43 44 #include <liblas/detail/utility.hpp> 44 45 #include <liblas/lasheader.hpp> … … 52 53 #include <cassert> 53 54 54 namespace liblas { namespace detail { namespace v10 {55 namespace liblas { namespace detail { 55 56 56 57 WriterImpl::WriterImpl(std::ostream& ofs) : 57 Base(ofs), m_pointCount(0) 58 { 59 } 60 61 LASVersion WriterImpl::GetVersion() const 62 { 63 return eLASVersion10; 64 } 58 m_ofs(ofs), m_transform(0), m_in_ref(0), m_out_ref(0), m_pointCount(0) 59 { 60 } 61 65 62 66 63 void WriterImpl::WriteHeader(LASHeader& header) 67 64 { 68 uint8_t n1 = 0; 69 uint16_t n2 = 0; 70 uint32_t n4 = 0; 71 72 // Rewrite the georeference VLR entries if they exist 73 header.SetGeoreference(); 74 75 // Seek to the beginning 76 m_ofs.seekp(0, std::ios::beg); 77 std::ios::pos_type beginning = m_ofs.tellp(); 78 79 // Seek to the end 80 m_ofs.seekp(0, std::ios::end); 81 std::ios::pos_type end = m_ofs.tellp(); 82 83 // Figure out how many points we already have. Each point record 84 // should be 20 bytes long, and header.GetDataOffset tells 85 // us the location to start counting points from. 86 87 // This test should only be true if we were opened in both 88 // std::ios::in *and* std::ios::out, otherwise it should return false 89 // and we won't adjust the point count. 90 91 if ((beginning != end) && ((uint32_t)end != 0)) { 92 m_pointCount = ((uint32_t) end - header.GetDataOffset())/header.GetDataRecordLength(); 93 94 // Position to the beginning of the file to start writing the header 95 m_ofs.seekp(0, std::ios::beg); 96 } 97 98 // 1. File Signature 99 std::string const filesig(header.GetFileSignature()); 100 assert(filesig.size() == 4); 101 detail::write_n(m_ofs, filesig, 4); 102 103 // 2. Reserved 104 n4 = header.GetReserved(); 105 detail::write_n(m_ofs, n4, sizeof(n4)); 106 107 // 3-6. GUID data 108 uint32_t d1 = 0; 109 uint16_t d2 = 0; 110 uint16_t d3 = 0; 111 uint8_t d4[8] = { 0 }; 112 liblas::guid g = header.GetProjectId(); 113 g.output_data(d1, d2, d3, d4); 114 detail::write_n(m_ofs, d1, sizeof(d1)); 115 detail::write_n(m_ofs, d2, sizeof(d2)); 116 detail::write_n(m_ofs, d3, sizeof(d3)); 117 detail::write_n(m_ofs, d4, sizeof(d4)); 118 119 // 7. Version major 120 n1 = header.GetVersionMajor(); 121 assert(1 == n1); 122 detail::write_n(m_ofs, n1, sizeof(n1)); 123 124 // 8. Version minor 125 n1 = header.GetVersionMinor(); 126 assert(0 == n1); 127 detail::write_n(m_ofs, n1, sizeof(n1)); 128 129 // 9. System ID 130 std::string sysid(header.GetSystemId(true)); 131 assert(sysid.size() == 32); 132 detail::write_n(m_ofs, sysid, 32); 133 134 // 10. Generating Software ID 135 std::string softid(header.GetSoftwareId(true)); 136 assert(softid.size() == 32); 137 detail::write_n(m_ofs, softid, 32); 138 139 // 11. Flight Date Julian 140 n2 = header.GetCreationDOY(); 141 detail::write_n(m_ofs, n2, sizeof(n2)); 142 143 // 12. Year 144 n2 = header.GetCreationYear(); 145 detail::write_n(m_ofs, n2, sizeof(n2)); 146 147 // 13. Header Size 148 n2 = header.GetHeaderSize(); 149 assert(227 <= n2); 150 detail::write_n(m_ofs, n2, sizeof(n2)); 151 152 // 14. Offset to data 153 // Because we are 1.0, we must also add pad bytes to the end of the 154 // header. This means resetting the dataoffset +=2, but we 155 // don't want to change the header's actual offset until after we 156 // write the VLRs or else we'll be off by 2 when we write the pad 157 // bytes 158 n4 = header.GetDataOffset() + 2; 159 detail::write_n(m_ofs, n4, sizeof(n4)); 160 161 // 15. Number of variable length records 162 // TODO: This value must be updated after new variable length record is added. 163 n4 = header.GetRecordsCount(); 164 detail::write_n(m_ofs, n4, sizeof(n4)); 165 166 // 16. Point Data Format ID 167 n1 = static_cast<uint8_t>(header.GetDataFormatId()); 168 detail::write_n(m_ofs, n1, sizeof(n1)); 169 170 // 17. Point Data Record Length 171 n2 = header.GetDataRecordLength(); 172 detail::write_n(m_ofs, n2, sizeof(n2)); 173 174 // 18. Number of point records 175 // This value is updated if necessary, see UpdateHeader function. 176 n4 = header.GetPointRecordsCount(); 177 detail::write_n(m_ofs, n4, sizeof(n4)); 178 179 // 19. Number of points by return 180 std::vector<uint32_t>::size_type const srbyr = 5; 181 std::vector<uint32_t> const& vpbr = header.GetPointRecordsByReturnCount(); 182 assert(vpbr.size() <= srbyr); 183 uint32_t pbr[srbyr] = { 0 }; 184 std::copy(vpbr.begin(), vpbr.end(), pbr); 185 detail::write_n(m_ofs, pbr, sizeof(pbr)); 186 187 // 20-22. Scale factors 188 detail::write_n(m_ofs, header.GetScaleX(), sizeof(double)); 189 detail::write_n(m_ofs, header.GetScaleY(), sizeof(double)); 190 detail::write_n(m_ofs, header.GetScaleZ(), sizeof(double)); 191 192 // 23-25. Offsets 193 detail::write_n(m_ofs, header.GetOffsetX(), sizeof(double)); 194 detail::write_n(m_ofs, header.GetOffsetY(), sizeof(double)); 195 detail::write_n(m_ofs, header.GetOffsetZ(), sizeof(double)); 196 197 // 26-27. Max/Min X 198 detail::write_n(m_ofs, header.GetMaxX(), sizeof(double)); 199 detail::write_n(m_ofs, header.GetMinX(), sizeof(double)); 200 201 // 28-29. Max/Min Y 202 detail::write_n(m_ofs, header.GetMaxY(), sizeof(double)); 203 detail::write_n(m_ofs, header.GetMinY(), sizeof(double)); 204 205 // 30-31. Max/Min Z 206 detail::write_n(m_ofs, header.GetMaxZ(), sizeof(double)); 207 detail::write_n(m_ofs, header.GetMinZ(), sizeof(double)); 208 209 // If WriteVLR returns a value, it is because the header's 210 // offset is not large enough to contain the VLRs. The value 211 // it returns is the number of bytes we must increase the header 212 // by in order for it to contain the VLRs. 213 214 int32_t difference = WriteVLR(header); 215 if (difference < 0) { 216 header.SetDataOffset(header.GetDataOffset() + abs(difference) ); 217 WriteVLR(header); 218 } 219 220 // Write the pad bytes. 221 uint8_t const sgn1 = 0xCC; 222 uint8_t const sgn2 = 0xDD; 223 detail::write_n(m_ofs, sgn1, sizeof(uint8_t)); 224 detail::write_n(m_ofs, sgn2, sizeof(uint8_t)); 225 226 // We can now reset the header's offset to +=2. If we monkeypatched 227 // the offset because we were too small to write the VLRs, this will 228 // end up being header.GetDataOffset() + difference + 2 (see above). 229 header.SetDataOffset(header.GetDataOffset() + 2); 230 231 // Make sure to rewrite the dataoffset in the header portion now that 232 // we've changed it. 233 std::streamsize const current_pos = m_ofs.tellp(); 234 std::streamsize const offset_pos = 96; 235 m_ofs.seekp(offset_pos, std::ios::beg); 236 detail::write_n(m_ofs, header.GetDataOffset() , sizeof(header.GetDataOffset())); 237 m_ofs.seekp(current_pos, std::ios::beg); 238 239 240 241 // If we already have points, we're going to put it at the end of the file. 242 // If we don't have any points, we're going to leave it where it is. 243 if (m_pointCount != 0) 244 m_ofs.seekp(0, std::ios::end); 65 detail::writer::Header hwriter(m_ofs,m_pointCount, header ); 66 hwriter.write(); 67 header = hwriter.GetHeader(); 68 245 69 } 246 70 … … 262 86 263 87 double t = 0; 88 uint16_t red = 0; 89 uint16_t blue = 0; 90 uint16_t green = 0; 91 LASColor color; 92 264 93 assert(liblas::ePointSize0 == sizeof(m_record)); 265 Writer::FillPointRecord(m_record, point, header);94 FillPointRecord(m_record, point, header); 266 95 detail::write_n(m_ofs, m_record, sizeof(m_record)); 267 96 268 if (header.GetDataFormatId() == liblas::ePointFormat1) { 97 if (header.GetDataFormatId() == liblas::ePointFormat1) 98 { 269 99 t = point.GetTime(); 270 100 detail::write_n(m_ofs, t, sizeof(double)); 271 101 } 102 else if (header.GetDataFormatId() == liblas::ePointFormat2) 103 { 104 color = point.GetColor(); 105 red = color.GetRed(); 106 green = color.GetGreen(); 107 blue = color.GetBlue(); 108 detail::write_n(m_ofs, red, sizeof(uint16_t)); 109 detail::write_n(m_ofs, green, sizeof(uint16_t)); 110 detail::write_n(m_ofs, blue, sizeof(uint16_t)); 111 } 112 else if (header.GetDataFormatId() == liblas::ePointFormat3) 113 { 114 t = point.GetTime(); 115 detail::write_n(m_ofs, t, sizeof(double)); 116 color = point.GetColor(); 117 red = color.GetRed(); 118 green = color.GetGreen(); 119 blue = color.GetBlue(); 120 detail::write_n(m_ofs, red, sizeof(uint16_t)); 121 detail::write_n(m_ofs, green, sizeof(uint16_t)); 122 detail::write_n(m_ofs, blue, sizeof(uint16_t)); 123 } 272 124 ++m_pointCount; 273 125 } 274 126 275 }}} // namespace liblas::detail::v10 127 WriterImpl::~WriterImpl() 128 { 129 #ifdef HAVE_GDAL 130 if (m_transform) { 131 OCTDestroyCoordinateTransformation(m_transform); 132 } 133 if (m_in_ref) { 134 OSRDestroySpatialReference(m_in_ref); 135 } 136 if (m_out_ref) { 137 OSRDestroySpatialReference(m_out_ref); 138 } 139 #endif 140 } 141 142 std::ostream& WriterImpl::GetStream() const 143 { 144 return m_ofs; 145 } 146 147 148 void WriterImpl::FillPointRecord(PointRecord& record, const LASPoint& point, const LASHeader& header) 149 { 150 151 if (m_transform) { 152 // let's just copy the point for now. 153 LASPoint p = LASPoint(point); 154 Project(p); 155 record.x = static_cast<int32_t>((p.GetX() - header.GetOffsetX()) / header.GetScaleX()); 156 record.y = static_cast<int32_t>((p.GetY() - header.GetOffsetY()) / header.GetScaleY()); 157 record.z = static_cast<int32_t>((p.GetZ() - header.GetOffsetZ()) / header.GetScaleZ()); 158 } else { 159 record.x = static_cast<int32_t>((point.GetX() - header.GetOffsetX()) / header.GetScaleX()); 160 record.y = static_cast<int32_t>((point.GetY() - header.GetOffsetY()) / header.GetScaleY()); 161 record.z = static_cast<int32_t>((point.GetZ() - header.GetOffsetZ()) / header.GetScaleZ()); 162 } 163 164 LASClassification::bitset_type clsflags(point.GetClassification()); 165 record.classification = static_cast<uint8_t>(clsflags.to_ulong()); 166 167 record.intensity = point.GetIntensity(); 168 record.flags = point.GetScanFlags(); 169 record.scan_angle_rank = point.GetScanAngleRank(); 170 record.user_data = point.GetUserData(); 171 record.point_source_id = point.GetPointSourceID(); 172 } 173 174 175 void WriterImpl::SetOutputSRS(const LASSpatialReference& srs ) 176 { 177 m_out_srs = srs; 178 CreateTransform(); 179 180 } 181 182 void WriterImpl::SetSRS(const LASSpatialReference& srs ) 183 { 184 SetOutputSRS(srs); 185 } 186 187 void WriterImpl::SetInputSRS(const LASSpatialReference& srs ) 188 { 189 m_in_srs = srs; 190 } 191 192 void WriterImpl::CreateTransform() 193 { 194 #ifdef HAVE_GDAL 195 if (m_transform) 196 { 197 OCTDestroyCoordinateTransformation(m_transform); 198 } 199 if (m_in_ref) 200 { 201 OSRDestroySpatialReference(m_in_ref); 202 } 203 if (m_out_ref) 204 { 205 OSRDestroySpatialReference(m_out_ref); 206 } 207 208 m_in_ref = OSRNewSpatialReference(0); 209 m_out_ref = OSRNewSpatialReference(0); 210 211 int result = OSRSetFromUserInput(m_in_ref, m_in_srs.GetWKT().c_str()); 212 if (result != OGRERR_NONE) 213 { 214 std::ostringstream msg; 215 msg << "Could not import input spatial reference for Writer::" << CPLGetLastErrorMsg() << result; 216 std::string message(msg.str()); 217 throw std::runtime_error(message); 218 } 219 220 result = OSRSetFromUserInput(m_out_ref, m_out_srs.GetWKT().c_str()); 221 if (result != OGRERR_NONE) 222 { 223 std::ostringstream msg; 224 msg << "Could not import output spatial reference for Writer::" << CPLGetLastErrorMsg() << result; 225 std::string message(msg.str()); 226 throw std::runtime_error(message); 227 } 228 229 m_transform = OCTNewCoordinateTransformation( m_in_ref, m_out_ref); 230 #endif 231 } 232 233 void WriterImpl::Project(LASPoint& p) 234 { 235 #ifdef HAVE_GDAL 236 237 int ret = 0; 238 double x = p.GetX(); 239 double y = p.GetY(); 240 double z = p.GetZ(); 241 242 ret = OCTTransform(m_transform, 1, &x, &y, &z); 243 244 if (!ret) { 245 std::ostringstream msg; 246 msg << "Could not project point for Writer::" << CPLGetLastErrorMsg() << ret; 247 std::string message(msg.str()); 248 throw std::runtime_error(message); 249 } 250 251 p.SetX(x); 252 p.SetY(y); 253 p.SetZ(z); 254 #else 255 detail::ignore_unused_variable_warning(p); 256 #endif 257 } 258 259 }} // namespace liblas::detail -
src/laswriter.cpp
r1545 r1553 43 43 #include <liblas/laswriter.hpp> 44 44 #include <liblas/detail/writer/writer.hpp> 45 #include <liblas/detail/writer/header.hpp>46 47 45 // std 48 46 #include <stdexcept> … … 66 64 67 65 m_pimpl->UpdateHeader(m_header); 68 }69 70 LASVersion LASWriter::GetVersion() const71 {72 return m_pimpl->GetVersion();73 66 } 74 67
Note: See TracChangeset
for help on using the changeset viewer.
