Changeset 1553:c57db71565c3


Ignore:
Timestamp:
02/04/10 19:11:35 (6 months ago)
Author:
Howard Butler <hobu.inc@…>
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.
Message:

merge

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • include/liblas/detail/writer/header.hpp

    r1545 r1553  
    4343#define LIBLAS_DETAIL_WRITER_HEADER_HPP_INCLUDED 
    4444 
    45 #include <liblas/lasversion.hpp> 
    46 #include <liblas/lasspatialreference.hpp> 
    4745#include <liblas/detail/fwd.hpp> 
    4846#include <liblas/detail/utility.hpp> 
    4947 
     48#include <liblas/lasheader.hpp> 
     49#include <liblas/detail/writer/writer10.hpp> 
    5050 
    5151// std 
    52 // #include <iosfwd> 
     52#include <iosfwd> 
    5353 
    5454namespace liblas { namespace detail { namespace writer { 
    5555 
    56 class Header 
     56class Header : public WriterCan 
    5757{ 
     58     
    5859public: 
     60    typedef WriterCan Base; 
    5961 
    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     
    6567protected: 
    6668 
     69private: 
     70     
     71    int32_t WriteVLRs(); 
     72    void WriteLAS10PadSignature(); 
     73    LASHeader m_header; 
     74     
     75}; 
    6776 
    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      
    7977}}} // namespace liblas::detail::writer 
    8078 
  • include/liblas/detail/writer/writer10.hpp

    r1545 r1553  
    4444 
    4545#include <liblas/lasversion.hpp> 
    46 #include <liblas/detail/writer/writer.hpp> 
    47 #include <liblas/detail/fwd.hpp> 
     46 
     47#include <liblas/lasspatialreference.hpp> 
    4848#include <liblas/cstdint.hpp> 
     49 
     50 
     51#ifndef HAVE_GDAL 
     52    typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH; 
     53    typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH; 
     54#endif 
     55 
     56 
    4957// std 
    5058#include <iosfwd> 
    5159 
    52 namespace liblas { namespace detail { namespace v10 { 
     60namespace liblas { namespace detail {  
    5361 
    54 class WriterImpl : public Writer 
     62class WriterCan 
    5563{ 
    5664public: 
    5765 
    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     
     74private: 
     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 
     89class WriterImpl  
     90{ 
     91public: 
     92 
    5993     
    6094    WriterImpl(std::ostream& ofs); 
     95    ~WriterImpl(); 
    6196    LASVersion GetVersion() const; 
    6297    void WriteHeader(LASHeader& header); 
     
    6499    void WritePointRecord(LASPoint const& record, const LASHeader& header); 
    65100 
     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 
     107protected: 
     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         
    66121private: 
    67122 
     123    void CreateTransform(); 
    68124    liblas::uint32_t m_pointCount; 
    69125}; 
    70126 
    71 }}} // namespace liblas::detail::v10 
     127}} // namespace liblas::detail 
    72128 
    73129#endif // LIBLAS_DETAIL_WRITER10_HPP_INCLUDED 
  • src/detail/reader/reader.cpp

    r1545 r1553  
    257257    // Determine version of given LAS file and 
    258258    // 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); 
    264264 
    265265    return new ReaderImpl(ifs); 
  • src/detail/reader/reader.cpp

    r1547 r1553  
    4040 ****************************************************************************/ 
    4141 
    42 #include <liblas/detail/reader/reader10.hpp> 
     42#include <liblas/detail/reader/reader.hpp> 
    4343#include <liblas/detail/reader/header.hpp> 
    4444#include <liblas/detail/reader/vlr.hpp> 
     45 
    4546#include <liblas/detail/utility.hpp> 
    4647#include <liblas/lasvariablerecord.hpp> 
  • src/detail/writer/header.cpp

    r1545 r1553  
    4949#include <cstdlib> // std::size_t 
    5050#include <fstream> 
     51#include <iosfwd> 
    5152#include <ostream> 
     53#include <sstream> 
     54#include <stdexcept> 
     55#include <string> 
    5256#include <vector> 
    5357 
     
    5559namespace liblas { namespace detail { namespace writer { 
    5660 
    57 Header::Header(std::ostream& ofs) : 
    58     m_ofs(ofs) 
     61Header::Header(std::ostream& ofs, liblas::uint32_t& count, LASHeader const& header) : 
     62    Base(ofs, count) 
    5963{ 
     64    m_header = header; 
    6065} 
    6166 
    62 Header::~Header() 
     67void Header::write() 
    6368{ 
    6469 
     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);     
    65268} 
    66269 
    67  
    68 LASHeader Header::write(const LASHeader& header) 
     270int32_t Header::WriteVLRs()  
    69271{ 
    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; 
    250316} 
    251317 
     318void 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 
    252336}}} // namespace liblas::detail::writer 
  • src/detail/writer/writer.cpp

    r1545 r1553  
    4242#include <liblas/detail/writer/writer.hpp> 
    4343#include <liblas/detail/writer/writer10.hpp> 
    44 #include <liblas/detail/writer/writer11.hpp> 
    45 #include <liblas/detail/writer/writer12.hpp> 
     44 
    4645#include <liblas/detail/utility.hpp> 
    4746#include <liblas/lasheader.hpp> 
     
    6665namespace liblas { namespace detail { 
    6766 
    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_GDAL 
    75     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 #endif 
    85 } 
    86  
    87 std::ostream& Writer::GetStream() const 
    88 { 
    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's  
    122     // data offset must be increased by in order for the VLRs to fit in  
    123     // the header.   
    124     m_ofs.seekp(header.GetHeaderSize(), std::ios::beg); 
    125  
    126     // if the VLRs won't fit because the data offset is too  
    127     // small, we need to throw an error. 
    128     uint32_t vlr_total_size = 0; 
    129          
    130     // Calculate a new data offset size 
    131     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 with  
    159     // 0's.  We must also not forget to add the 1.0 pad bytes to the end of this 
    160     // 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_GDAL 
    188     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 #endif 
    224 } 
    225  
    226 void Writer::Project(LASPoint& p) 
    227 { 
    228 #ifdef HAVE_GDAL 
    229      
    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 #else 
    248     detail::ignore_unused_variable_warning(p); 
    249 #endif 
    250 } 
    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 
     251WriterImpl* WriterFactory::Create(std::ostream& ofs, LASHeader const& header) 
    253252{ 
    254253    if (!ofs) 
     
    258257 
    259258    // 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(); 
    262261     
    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 
     272void WriterFactory::Destroy(detail::WriterImpl* p)  
    285273{ 
    286274    delete p; 
     
    288276} 
    289277 
     278 
     279WriterCan::WriterCan(std::ostream& ofs, liblas::uint32_t& count) : m_pointCount(count), m_ofs(ofs)  
     280{ 
     281} 
     282 
     283WriterCan::~WriterCan() 
     284{ 
     285 
     286} 
     287 
    290288}} // namespace liblas::detail 
  • src/detail/writer/writer10.cpp

    r1545 r1553  
    4141 
    4242#include <liblas/detail/writer/writer10.hpp> 
     43#include <liblas/detail/writer/header.hpp> 
    4344#include <liblas/detail/utility.hpp> 
    4445#include <liblas/lasheader.hpp> 
     
    5253#include <cassert> 
    5354 
    54 namespace liblas { namespace detail { namespace v10 { 
     55namespace liblas { namespace detail {  
    5556 
    5657WriterImpl::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 
    6562 
    6663void WriterImpl::WriteHeader(LASHeader& header) 
    6764{ 
    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     
    24569} 
    24670 
     
    26286     
    26387    double t = 0; 
     88    uint16_t red = 0; 
     89    uint16_t blue = 0; 
     90    uint16_t green = 0; 
     91    LASColor color; 
     92     
    26493    assert(liblas::ePointSize0 == sizeof(m_record)); 
    265     Writer::FillPointRecord(m_record, point, header); 
     94    FillPointRecord(m_record, point, header); 
    26695    detail::write_n(m_ofs, m_record, sizeof(m_record)); 
    26796 
    268     if (header.GetDataFormatId() == liblas::ePointFormat1) { 
     97    if (header.GetDataFormatId() == liblas::ePointFormat1) 
     98    { 
    26999        t = point.GetTime(); 
    270100        detail::write_n(m_ofs, t, sizeof(double)); 
    271101    } 
     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    } 
    272124    ++m_pointCount; 
    273125} 
    274126 
    275 }}} // namespace liblas::detail::v10 
     127WriterImpl::~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 
     142std::ostream& WriterImpl::GetStream() const 
     143{ 
     144    return m_ofs; 
     145} 
     146 
     147 
     148void 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 
     175void WriterImpl::SetOutputSRS(const LASSpatialReference& srs ) 
     176{ 
     177    m_out_srs = srs; 
     178    CreateTransform(); 
     179 
     180} 
     181 
     182void WriterImpl::SetSRS(const LASSpatialReference& srs ) 
     183{ 
     184    SetOutputSRS(srs); 
     185} 
     186 
     187void WriterImpl::SetInputSRS(const LASSpatialReference& srs ) 
     188{ 
     189    m_in_srs = srs; 
     190} 
     191 
     192void 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 
     233void 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  
    4343#include <liblas/laswriter.hpp> 
    4444#include <liblas/detail/writer/writer.hpp> 
    45 #include <liblas/detail/writer/header.hpp> 
    46  
    4745// std 
    4846#include <stdexcept> 
     
    6664 
    6765    m_pimpl->UpdateHeader(m_header); 
    68 } 
    69  
    70 LASVersion LASWriter::GetVersion() const 
    71 { 
    72     return m_pimpl->GetVersion(); 
    7366} 
    7467 
Note: See TracChangeset for help on using the changeset viewer.