[Liblas-commits] r1325 - in trunk: include/liblas include/liblas/capi include/liblas/detail python/liblas python/tests src src/detail

liblas-commits at liblas.org liblas-commits at liblas.org
Tue Jul 28 14:46:00 EDT 2009


Author: hobu
Date: Tue Jul 28 14:45:59 2009
New Revision: 1325
URL: http://liblas.org/changeset/1325

Log:
fix for #136

Modified:
   trunk/include/liblas/capi/liblas.h
   trunk/include/liblas/detail/reader.hpp
   trunk/include/liblas/detail/writer.hpp
   trunk/include/liblas/lasheader.hpp
   trunk/python/liblas/core.py
   trunk/python/liblas/header.py
   trunk/python/tests/File.txt
   trunk/python/tests/Header.txt
   trunk/python/tests/VLR.txt
   trunk/src/detail/reader.cpp
   trunk/src/detail/reader10.cpp
   trunk/src/detail/reader11.cpp
   trunk/src/detail/reader12.cpp
   trunk/src/detail/writer.cpp
   trunk/src/detail/writer10.cpp
   trunk/src/detail/writer11.cpp
   trunk/src/detail/writer12.cpp
   trunk/src/las_c_api.cpp
   trunk/src/lasheader.cpp
   trunk/src/lasreader.cpp

Modified: trunk/include/liblas/capi/liblas.h
==============================================================================
--- trunk/include/liblas/capi/liblas.h	(original)
+++ trunk/include/liblas/capi/liblas.h	Tue Jul 28 14:45:59 2009
@@ -640,6 +640,14 @@
 */
 LAS_DLL uint32_t LASHeader_GetDataOffset(const LASHeaderH hHeader);
 
+/** Sets the location in number of bytes to start writing point data.  Any
+ *  space between the end of the LASVLRHs and this value will be written with 0's.
+ *  @param hHeader LASHeaderH instance
+ *  @param value the long integer to set for byte location determining the end of the header
+ *  @return LASError enum
+*/
+ LAS_DLL LASError LASHeader_SetDataOffset(const LASHeaderH hHeader, uint32_t value);
+
 /** Returns the number of variable length records in the header
  *  @param hHeader LASHeaderH instance
  *  @return the number of variable length records in the header

Modified: trunk/include/liblas/detail/reader.hpp
==============================================================================
--- trunk/include/liblas/detail/reader.hpp	(original)
+++ trunk/include/liblas/detail/reader.hpp	Tue Jul 28 14:45:59 2009
@@ -74,21 +74,17 @@
     bool ReadGeoreference(LASHeader& header);
     void Reset(LASHeader const& header);
     void SetSRS(const LASSpatialReference& srs);
-    void SkipPointDataSignature();
     
 protected:
     
     std::istream& m_ifs;
-    std::streamoff m_offset;
     uint32_t m_size;
     uint32_t m_current;
-    uint32_t m_recordlength;    
     LASSpatialReference m_out_srs;
     LASSpatialReference m_in_srs;    
     OGRCoordinateTransformationH m_transform;
     OGRSpatialReferenceH m_in_ref;
     OGRSpatialReferenceH m_out_ref;
-    bool m_has_pad_bytes;
 
     void FillPoint(PointRecord& record, LASPoint& point);
     void Project(LASPoint& point);

Modified: trunk/include/liblas/detail/writer.hpp
==============================================================================
--- trunk/include/liblas/detail/writer.hpp	(original)
+++ trunk/include/liblas/detail/writer.hpp	Tue Jul 28 14:45:59 2009
@@ -67,7 +67,7 @@
     virtual void UpdateHeader(LASHeader const& header) = 0;
     virtual void WritePointRecord(LASPoint const& point, const LASHeader& header) = 0;
     std::ostream& GetStream() const;
-    void WriteVLR(LASHeader const& header);
+    uint32_t WriteVLR(LASHeader const& header);
 
     void SetSRS(const LASSpatialReference& srs);
     

Modified: trunk/include/liblas/lasheader.hpp
==============================================================================
--- trunk/include/liblas/lasheader.hpp	(original)
+++ trunk/include/liblas/lasheader.hpp	Tue Jul 28 14:45:59 2009
@@ -330,7 +330,7 @@
     
     /// Set the georeference
     void SetSRS(LASSpatialReference& srs);
-    
+
 private:
     
     typedef detail::Point<double> PointScales;

Modified: trunk/python/liblas/core.py
==============================================================================
--- trunk/python/liblas/core.py	(original)
+++ trunk/python/liblas/core.py	Tue Jul 28 14:45:59 2009
@@ -358,6 +358,10 @@
 las.LASHeader_GetDataOffset.argtypes = [ctypes.c_void_p]
 las.LASHeader_GetDataOffset.errcheck = check_value
 
+las.LASHeader_SetDataOffset.restype = ctypes.c_int
+las.LASHeader_SetDataOffset.argtypes = [ctypes.c_void_p, ctypes.c_int]
+las.LASHeader_SetDataOffset.errcheck = check_return
+
 las.LASHeader_GetRecordsCount.restype = ctypes.c_ulong
 las.LASHeader_GetRecordsCount.argtypes = [ctypes.c_void_p]
 las.LASHeader_GetRecordsCount.errcheck = check_value

Modified: trunk/python/liblas/header.py
==============================================================================
--- trunk/python/liblas/header.py	(original)
+++ trunk/python/liblas/header.py	Tue Jul 28 14:45:59 2009
@@ -187,7 +187,13 @@
     def get_dataoffset(self):
         """Returns the location in bytes of where the data block of the LAS file starts"""
         return core.las.LASHeader_GetDataOffset(self.handle)
-    data_offset = property(get_dataoffset)
+    def set_dataoffset(self, value):
+        """Sets the data offset
+        
+        Any space between this value and the end of the VLRs will be written with 0's
+        """
+        return core.las.LASHeader_SetDataOffset(self.handle, value)
+    data_offset = property(get_dataoffset, set_dataoffset)
     
     def get_recordscount(self):
         """Returns the number of user-defined header records in the header.  
@@ -205,7 +211,7 @@
     def set_dataformatid(self, value):
         """Sets the point format value
         
-        It can only be  1 (for 1.1 compatible) or 0 (for 1.0 compatible).
+        It can be 3, 2, 1, or 0.
         """
         if value not in [3, 2,1,0]:
             raise core.LASException("Format ID must be 3, 2, 1, or 0")

Modified: trunk/python/tests/File.txt
==============================================================================
--- trunk/python/tests/File.txt	(original)
+++ trunk/python/tests/File.txt	Tue Jul 28 14:45:59 2009
@@ -101,10 +101,103 @@
   
   >>> cnt
   16
+
+  >>> buffered_header = f.header
+  >>> del f 
+
+  >>> buffered_header.data_offset = 1024
+  >>> f3 = file.File('junk2.las',mode='w',header=buffered_header)
+
+  >>> f3.header.data_offset
+  1024L
+
+  >>> for i in points:
+  ...    f3.write(i)
+    
+  >>> f3.close()
+
+  >>> del f3
+ 
+The header's offset will change +=2 because of the 1.0
+requirement to write pad bytes at the end of the header
   
-  >>> f.close()
+  >>> f = file.File('junk2.las')
+  >>> f.header.data_offset
+  1026L
+  
+  >>> points = []
+  >>> for i in f:
+  ...   points.append(i)
+  ...   print i # doctest: +ELLIPSIS
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+
+  >>> for g in points:
+  ...   print int(g.x), int(g.y)
+  630262 4834500
+  630282 4834500
+  630300 4834500
+  630346 4834500
+  630327 4834500
+  630323 4834500
+  630320 4834500
+  630280 4834500
+
+Now try writing a 1.2 version of the junk2.las file above to ensure that
+the data_offset *doesn't* change at all
+
+  >>> buffered_header.data_offset = 1024
+  >>> buffered_header.minor_version = 2
+  >>> f3 = file.File('junk3.las',mode='w',header=buffered_header)
+
+  >>> f3.header.data_offset
+  1024L
+
+  >>> for i in points:
+  ...    f3.write(i)
+    
+  >>> f3.close()
+
+  >>> del f3
+
+  >>> f = file.File('junk3.las')
+  >>> f.header.data_offset
+  1024L
+  
+  >>> points = []
+  >>> for i in f:
+  ...   points.append(i)
+  ...   print i # doctest: +ELLIPSIS
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+  <liblas.point.Point object at ...>
+
+  >>> for g in points:
+  ...   print int(g.x), int(g.y)
+  630262 4834500
+  630282 4834500
+  630300 4834500
+  630346 4834500
+  630327 4834500
+  630323 4834500
+  630320 4834500
+  630280 4834500
+    
   >>> import os
   >>> os.remove('junk.las')
+  >>> os.remove('junk2.las')
+  >>> os.remove('junk3.las')
 
   >>> f = file.File('junk.las', mode="w", header=header)
   >>> import liblas.core
@@ -117,7 +210,7 @@
   ...
   LASException: LASError in "LASWriter_Destroy": Pointer 'hWriter' is NULL in 'LASWriter_Destroy'.
 
-#  >>> f = file.File('junk.las2')
-#  Traceback (most recent call last):
-#  ...
-#  LASException: LASError in "LASReader_Create": can not open file /Users/hobu/svn/liblas/trunk/python/junk.las2
+  >>> import os
+  >>> os.remove('junk.las')
+  
+

Modified: trunk/python/tests/Header.txt
==============================================================================
--- trunk/python/tests/Header.txt	(original)
+++ trunk/python/tests/Header.txt	Tue Jul 28 14:45:59 2009
@@ -105,4 +105,11 @@
   
   >>> test_srs()
   True
+  
+  >>> h.data_offset
+  227L
+  
+  >>> h.data_offset = 742
+  >>> h.data_offset
+  742L
 

Modified: trunk/python/tests/VLR.txt
==============================================================================
--- trunk/python/tests/VLR.txt	(original)
+++ trunk/python/tests/VLR.txt	Tue Jul 28 14:45:59 2009
@@ -99,3 +99,19 @@
   
   >>> del f
   
+  >>> f = file.File('../test/data/srs.las')
+  >>> h = f.header
+  >>> f2 = file.File('junk_srs.las',mode='w',header=h)
+  >>> for p in f:
+  ...     f2.write(p)
+  
+  >>> f2.close()
+  >>> del f2
+  
+  >>> f3 = file.File('junk_srs.las')
+  >>> f3.header.records_count
+  3L
+  >>> f3.header.data_offset
+  761L
+  >>> import os
+  >>> os.remove('junk_srs.las')
\ No newline at end of file

Modified: trunk/src/detail/reader.cpp
==============================================================================
--- trunk/src/detail/reader.cpp	(original)
+++ trunk/src/detail/reader.cpp	Tue Jul 28 14:45:59 2009
@@ -69,9 +69,8 @@
 namespace liblas { namespace detail {
 
 Reader::Reader(std::istream& ifs) :
-    m_ifs(ifs), m_offset(0), m_size(0), m_current(0),
-    m_recordlength(0), m_transform(0),
-    m_in_ref(0), m_out_ref(0)
+    m_ifs(ifs), m_size(0), m_current(0),
+    m_transform(0), m_in_ref(0), m_out_ref(0)
 {
 }
 
@@ -179,39 +178,7 @@
 
     // Reset sizes and set internal cursor to the beginning of file.
     m_current = 0;
-    m_offset = header.GetDataOffset();
     m_size = header.GetPointRecordsCount();
-    m_recordlength = header.GetDataRecordLength();
-}
-
-void Reader::SkipPointDataSignature() 
-{
-    uint8_t const sgn1 = 0xCC;
-    uint8_t const sgn2 = 0xDD;
-    uint8_t pad1 = 0x0; 
-    uint8_t pad2 = 0x0;
-    
-    detail::read_n(pad1, m_ifs, sizeof(uint8_t));
-    detail::read_n(pad2, m_ifs, sizeof(uint8_t));
-    
-    LIBLAS_SWAP_BYTES(pad1);
-    LIBLAS_SWAP_BYTES(pad2);
-    
-    // FIXME: we have to worry about swapping issues
-    // but some people write the pad bytes backwards 
-    // anyway.  Let's check both ways.
-    bool found = false;
-    if (sgn1 == pad2 && sgn2 == pad1) found = true;
-    if (sgn1 == pad1 && sgn2 == pad2) found = true;
-    if (!found)
-    {
-        // If the two bytes we read weren't signature bytes
-        // we'll throw an exception.  Depending on the version
-        // we may want ot throw an error to the user or 
-        // silently continue on.
-        throw std::domain_error("point data signature (1.0's 0xCC and 0xDD padding) not found");
-        
-    }
 }
 
 void Reader::SetSRS(const LASSpatialReference& srs)

Modified: trunk/src/detail/reader10.cpp
==============================================================================
--- trunk/src/detail/reader10.cpp	(original)
+++ trunk/src/detail/reader10.cpp	Tue Jul 28 14:45:59 2009
@@ -212,33 +212,6 @@
     header.SetMax(x1, y1, z1);
     header.SetMin(x2, y2, z2);
 
-    // The 1.0 version *requires* the pad bytes, but in 
-    // many instances, there are files without them.  What 
-    // a fucking mess -- hobu.
-    m_has_pad_bytes = false;
-
-    try
-    {
-        SkipPointDataSignature();
-        m_has_pad_bytes = true;
-    }
-    catch (std::out_of_range const&)
-    {
-        // Ignore the out_of_range here for the case of a 
-        // file with just a header and no pad
-    }
-    catch (std::runtime_error const&)
-    {
-        // Ignore the runtime_error here for the case of a 
-        // file with just a header and no pad
-        // This is what is thrown when we compile *without* debug
-    }    
-    catch (std::domain_error const&)
-    {
-        // TODO: We'll want to put this error on the validation errors stack
-        // but for now, we'll just move back to the offset
-    }
-
     Reset(header);
 
     return true;
@@ -249,21 +222,7 @@
     if (0 == m_current)
     {
         m_ifs.clear();
-        m_ifs.seekg(m_offset, std::ios::beg);
-
-        // The 1.0 version *requires* the pad bytes, but in 
-        // many instances, there are files without them.  What 
-        // a fucking mess -- hobu.
-        try
-        {
-            SkipPointDataSignature();
-        }
-        catch (std::domain_error const&)
-        {
-            // TODO: We'll want to put this error on the validation errors stack
-            // but for now, we'll just move back to the offset
-            m_ifs.seekg(m_offset, std::ios::beg);
-        }
+        m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
     }
 
     if (m_current < m_size)
@@ -302,16 +261,15 @@
 bool ReaderImpl::ReadPointAt(std::size_t n, LASPoint& point, const LASHeader& header)
 {
     if (m_size <= n)
-    {
         return false;
-    }
 
-    std::streamsize pos = (static_cast<std::streamsize>(n) * m_recordlength) + m_offset;
+    std::streamsize pos = (static_cast<std::streamsize>(n) * header.GetDataRecordLength()) + header.GetDataOffset();    
+
     m_ifs.clear();
     m_ifs.seekg(pos, std::ios::beg);
 
-    detail::PointRecord record;
     // TODO: Replace with compile-time assert
+    detail::PointRecord record;
     assert(LASHeader::ePointSize0 == sizeof(record));
 
     detail::read_n(record, m_ifs, sizeof(record));

Modified: trunk/src/detail/reader11.cpp
==============================================================================
--- trunk/src/detail/reader11.cpp	(original)
+++ trunk/src/detail/reader11.cpp	Tue Jul 28 14:45:59 2009
@@ -215,35 +215,7 @@
 
     header.SetMax(x1, y1, z1);
     header.SetMin(x2, y2, z2);
-
-    m_has_pad_bytes = false;
-
-    m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
-    try
-    {
-        // If this call succeeds, we'll want to put this on the 
-        // validation errors stack.  1.1 files shouldn't have 
-        // pad bytes.
-        SkipPointDataSignature();
-        m_has_pad_bytes = true;
-    }
-    catch (std::out_of_range const&)
-    {
-        // Ignore the out_of_range here for the case of a 
-        // file with just a header and no pad
-    }
-    catch (std::runtime_error const&)
-    {
-        // Ignore the runtime_error here for the case of a 
-        // file with just a header and no pad
-        // This is what is thrown when we compile *without* debug
-    }    
-    catch (std::domain_error const&)
-    {
-        // TODO: We'll want to put this error on the validation errors stack
-        // but for now, we'll just move back to the offset
-    }
-
+    
     Reset(header);
 
     return true;
@@ -254,18 +226,7 @@
     if (0 == m_current)
     {
         m_ifs.clear();
-        m_ifs.seekg(m_offset, std::ios::beg);
-
-        try
-        {
-            // If this call succeeds, we'll want to put this on the 
-            // validation errors stack.  1.1 files shouldn't have pad bytes.
-            SkipPointDataSignature();
-        }
-        catch (std::domain_error const&)
-        {
-            m_ifs.seekg(m_offset, std::ios::beg);
-        }
+        m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
     }
 
     if (m_current < m_size)
@@ -304,16 +265,10 @@
 bool ReaderImpl::ReadPointAt(std::size_t n, LASPoint& point, const LASHeader& header)
 {
     if (m_size <= n)
-    {
         return false;
-    }
 
-    std::streamsize pos = (static_cast<std::streamsize>(n) * m_recordlength) + m_offset;
+    std::streamsize pos = (static_cast<std::streamsize>(n) * header.GetDataRecordLength()) + header.GetDataOffset();
 
-    if (m_has_pad_bytes)
-    {
-        pos += 2;
-    }    
     m_ifs.clear();
     m_ifs.seekg(pos, std::ios::beg);
 

Modified: trunk/src/detail/reader12.cpp
==============================================================================
--- trunk/src/detail/reader12.cpp	(original)
+++ trunk/src/detail/reader12.cpp	Tue Jul 28 14:45:59 2009
@@ -217,34 +217,6 @@
 
     header.SetMax(x1, y1, z1);
     header.SetMin(x2, y2, z2);
-    
-    m_has_pad_bytes = false;
-
-    m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
-    try
-    {
-        // If this call succeeds, we'll want to put this on the 
-        // validation errors stack.  1.2 files shouldn't have pad bytes.
-        SkipPointDataSignature();
-        m_has_pad_bytes = true;
-    }
-    catch (std::out_of_range const&)
-    {
-        // Ignore the out_of_range here for the case of a 
-        // file with just a header and no pad
-        // This is what is thrown when we compile *with* debug
-    }
-    catch (std::runtime_error const&)
-    {
-        // Ignore the runtime_error here for the case of a 
-        // file with just a header and no pad
-        // This is what is thrown when we compile *without* debug
-    }    
-    catch (std::domain_error const&)
-    {
-        // TODO: We'll want to put this error on the validation errors stack
-        // but for now, we'll just move back to the offset
-    }
 
     Reset(header);
 
@@ -256,19 +228,7 @@
     if (0 == m_current)
     {
         m_ifs.clear();
-        m_ifs.seekg(m_offset, std::ios::beg);
-
-        try
-        {
-            // If this call succeeds, we'll want to put this on the 
-            // validation errors stack.  1.2 files shouldn't have 
-            // pad bytes.
-            SkipPointDataSignature();
-        }
-        catch (std::domain_error const&)
-        {
-            m_ifs.seekg(m_offset, std::ios::beg);
-        }
+        m_ifs.seekg(header.GetDataOffset(), std::ios::beg);
     }
 
     if (m_current < m_size)
@@ -349,9 +309,7 @@
         return false;
     }
 
-    std::streamsize pos = (static_cast<std::streamsize>(n) * m_recordlength) + m_offset;
-
-    if (m_has_pad_bytes) pos += 2;
+    std::streamsize pos = (static_cast<std::streamsize>(n) * header.GetDataRecordLength()) + header.GetDataOffset();
 
     m_ifs.clear();
     m_ifs.seekg(pos, std::ios::beg);

Modified: trunk/src/detail/writer.cpp
==============================================================================
--- trunk/src/detail/writer.cpp	(original)
+++ trunk/src/detail/writer.cpp	Tue Jul 28 14:45:59 2009
@@ -107,10 +107,31 @@
     record.point_source_id = point.GetPointSourceID();
 }
 
-void Writer::WriteVLR(LASHeader const& header) 
+uint32_t Writer::WriteVLR(LASHeader const& header) 
 {
+    // If this function returns a value, it is the size that the header's 
+    // data offset must be increased by in order for the VLRs to fit in 
+    // the header.  
     m_ofs.seekp(header.GetHeaderSize(), std::ios::beg);
 
+    // if the VLRs won't fit because the data offset is too 
+    // small, we need to throw an error.
+    uint32_t vlr_total_size = 0;
+        
+    // Calculate a new data offset size
+    for (uint32_t i = 0; i < header.GetRecordsCount(); ++i)
+    {
+        LASVariableRecord vlr = header.GetVLR(i);
+        vlr_total_size += vlr.GetTotalSize();
+    }
+    
+    int32_t difference = header.GetDataOffset() - (vlr_total_size + header.GetHeaderSize());
+    
+    if (difference < 0) 
+    {
+        return difference;
+    }
+    
     for (uint32_t i = 0; i < header.GetRecordsCount(); ++i)
     {
         LASVariableRecord vlr = header.GetVLR(i);
@@ -124,6 +145,14 @@
         std::streamsize const size = static_cast<std::streamsize>(data.size());
         detail::write_n(m_ofs, data.front(), size);
     }
+    
+    // if we had more room than we need for the VLRs, we need to pad that with 
+    // 0's.  We must also not forget to add the 1.0 pad bytes to the end of this
+    // but the impl should be the one doing that, not us.
+    if (difference > 0) {
+        detail::write_n(m_ofs, "\0", difference);
+    }
+    return 0;
 }
 
 

Modified: trunk/src/detail/writer10.cpp
==============================================================================
--- trunk/src/detail/writer10.cpp	(original)
+++ trunk/src/detail/writer10.cpp	Tue Jul 28 14:45:59 2009
@@ -150,7 +150,12 @@
     detail::write_n(m_ofs, n2, sizeof(n2));
 
     // 14. Offset to data
-    n4 = header.GetDataOffset();
+    // Because we are 1.0, we must also add pad bytes to the end of the 
+    // header.  This means resetting the dataoffset +=2, but we 
+    // don't want to change the header's actual offset until after we 
+    // write the VLRs or else we'll be off by 2 when we write the pad
+    // bytes
+    n4 = header.GetDataOffset() + 2;
     detail::write_n(m_ofs, n4, sizeof(n4));
 
     // 15. Number of variable length records
@@ -201,14 +206,28 @@
     detail::write_n(m_ofs, header.GetMaxZ(), sizeof(double));
     detail::write_n(m_ofs, header.GetMinZ(), sizeof(double));
 
-
-    WriteVLR(header);
-
+    // If WriteVLR returns a value, it is because the header's 
+    // offset is not large enough to contain the VLRs.  The value 
+    // it returns is the number of bytes we must increase the header
+    // by in order for it to contain the VLRs.
+    
+    int32_t difference = WriteVLR(header);
+    if (difference < 0) {
+        header.SetDataOffset(header.GetDataOffset() + difference );
+        WriteVLR(header);
+    }
+    
+    // Write the pad bytes.
     uint8_t const sgn1 = 0xCC;
     uint8_t const sgn2 = 0xDD;
     detail::write_n(m_ofs, sgn1, sizeof(uint8_t));
     detail::write_n(m_ofs, sgn2, sizeof(uint8_t));
 
+    // We can now reset the header's offset to +=2.  If we monkeypatched
+    // the offset because we were too small to write the VLRs, this will 
+    // end up being header.GetDataOffset() + difference + 2 (see above).
+    header.SetDataOffset(header.GetDataOffset() + 2);
+    
     // If we already have points, we're going to put it at the end of the file.  
     // If we don't have any points,  we're going to leave it where it is.
     if (m_pointCount != 0)

Modified: trunk/src/detail/writer11.cpp
==============================================================================
--- trunk/src/detail/writer11.cpp	(original)
+++ trunk/src/detail/writer11.cpp	Tue Jul 28 14:45:59 2009
@@ -208,7 +208,15 @@
     detail::write_n(m_ofs, header.GetMaxZ(), sizeof(double));
     detail::write_n(m_ofs, header.GetMinZ(), sizeof(double));
     
-    WriteVLR(header);
+    // If WriteVLR returns a value, it is because the header's 
+    // offset is not large enough to contain the VLRs.  The value 
+    // it returns is the number of bytes we must increase the header
+    // by in order for it to contain the VLRs.
+    int32_t difference = WriteVLR(header);
+    if (difference != 0) {
+        header.SetDataOffset(header.GetDataOffset() + difference);
+        WriteVLR(header);
+    }
 
     // If we already have points, we're going to put it at the end of the file.  
     // If we don't have any points,  we're going to leave it where it is.

Modified: trunk/src/detail/writer12.cpp
==============================================================================
--- trunk/src/detail/writer12.cpp	(original)
+++ trunk/src/detail/writer12.cpp	Tue Jul 28 14:45:59 2009
@@ -210,7 +210,15 @@
     detail::write_n(m_ofs, header.GetMaxZ(), sizeof(double));
     detail::write_n(m_ofs, header.GetMinZ(), sizeof(double));
     
-    WriteVLR(header);
+    // If WriteVLR returns a value, it is because the header's 
+    // offset is not large enough to contain the VLRs.  The value 
+    // it returns is the number of bytes we must increase the header
+    // by in order for it to contain the VLRs.
+    int32_t difference = WriteVLR(header);
+    if (difference != 0) {
+        header.SetDataOffset(header.GetDataOffset() + difference);
+        WriteVLR(header);
+    }
 
     // If we already have points, we're going to put it at the end of the file.  
     // If we don't have any points,  we're going to leave it where it is.

Modified: trunk/src/las_c_api.cpp
==============================================================================
--- trunk/src/las_c_api.cpp	(original)
+++ trunk/src/las_c_api.cpp	Tue Jul 28 14:45:59 2009
@@ -884,7 +884,19 @@
     return value;
 }
 
+LAS_DLL LASErrorEnum LASHeader_SetDataOffset(const LASHeaderH hHeader, liblas::uint32_t value) {
+    VALIDATE_LAS_POINTER1(hHeader, "LASHeader_SetDataOffset", LE_Failure);
 
+    try {
+        ((LASHeader*) hHeader)->SetDataOffset(value);    
+    } catch (std::exception const& e)
+    {
+        LASError_PushError(LE_Failure, e.what(), "LASHeader_SetDataOffset");
+        return LE_Failure;
+    }
+ 
+    return LE_None;    
+}
 
 
 LAS_DLL liblas::uint32_t LASHeader_GetRecordsCount(const LASHeaderH hHeader) {
@@ -970,6 +982,7 @@
  
     return LE_None;    
 }
+
 LAS_DLL double LASHeader_GetScaleX(const LASHeaderH hHeader) {
     VALIDATE_LAS_POINTER1(hHeader, "LASHeader_GetScaleX", 0.0);
 

Modified: trunk/src/lasheader.cpp
==============================================================================
--- trunk/src/lasheader.cpp	(original)
+++ trunk/src/lasheader.cpp	Tue Jul 28 14:45:59 2009
@@ -262,17 +262,6 @@
         throw std::out_of_range("version minor out of range");
     
     m_versionMinor = v;
-    
-    uint32_t size = 0;
-    uint32_t const dataSignatureSize = 2;
-    
-    // Add the signature if we're a 1.0 file    
-    if (eVersionMinorMin == m_versionMinor) {
-        size = dataSignatureSize; 
-    } 
-
-    SetDataOffset(GetHeaderSize()+size);
-    
 }
 
 std::string LASHeader::GetSystemId(bool pad /*= false*/) const
@@ -373,8 +362,9 @@
     {
         throw std::out_of_range("data offset out of range");
     }
-
+    
     m_dataOffset = v;
+    
 }
 
 uint32_t LASHeader::GetRecordsCount() const
@@ -552,31 +542,6 @@
 void LASHeader::AddVLR(LASVariableRecord const& v) 
 {
     m_vlrs.push_back(v);
-
-    uint32_t end_size = 0;
-    std::vector<LASVariableRecord>::const_iterator i;
-        
-    // Calculate a new data offset size
-    for (i = m_vlrs.begin(); i != m_vlrs.end(); ++i) 
-    {
-        end_size += (*i).GetTotalSize();
-    }
-
-    uint32_t size = 0;
-    uint32_t const dataSignatureSize = 2;
-    
-    // Add the signature if we're a 1.0 file    
-    if (eVersionMinorMin == m_versionMinor) {
-        size = end_size + dataSignatureSize; 
-    } else {
-        size = end_size;
-    }
-
-    SetDataOffset(GetHeaderSize()+size);
-
-    // We're assuming that the reader or writer has reset 
-    // the VLR count to 0 before adding them back with AddVLR  
-    // FIXME I think this is still broken - hobu
     m_recordsCount += 1;
 }
 
@@ -592,14 +557,9 @@
 
     std::vector<LASVariableRecord>::iterator i = m_vlrs.begin() + index;
 
-    // Deal with the dataoffset when deleting
-    uint32_t size = (*i).GetTotalSize();
-
     m_vlrs.erase(i);
     m_recordsCount = static_cast<uint32_t>(m_vlrs.size());
-    
-    SetDataOffset(GetDataOffset() - size);
-    
+
 }
 
 
@@ -655,9 +615,6 @@
 {
     std::string const uid("LASF_Projection");
 
-    uint32_t beg_size = 0;
-    uint32_t end_size = 0;
-
     std::vector<LASVariableRecord> vlrs = m_vlrs;
     std::vector<LASVariableRecord>::const_iterator i;
     std::vector<LASVariableRecord>::iterator j;
@@ -665,7 +622,7 @@
     for (i = m_vlrs.begin(); i != m_vlrs.end(); ++i)
     {
         LASVariableRecord record = *i;
-        beg_size += (*i).GetTotalSize();
+        // beg_size += (*i).GetTotalSize();
 
         std::string user = record.GetUserId(true);
         if (uid == user.c_str())
@@ -715,27 +672,6 @@
     // and update header information
     m_vlrs = vlrs;
     m_recordsCount = static_cast<uint32_t>(m_vlrs.size());
-    
-    // Calculate a new data offset size
-    for (i = m_vlrs.begin(); i != m_vlrs.end(); ++i) 
-    {
-        end_size += (*i).GetTotalSize();
-    }
-
-    uint32_t size = 0;
-    uint32_t const dataSignatureSize = 2;
-    
-    // Add the signature if we're a 1.0 file    
-    if (eVersionMinorMin == m_versionMinor)
-    {
-        size = end_size + dataSignatureSize; 
-    }
-    else
-    {
-        size = end_size;
-    }
-
-    SetDataOffset(GetHeaderSize()+size);
 
 }
 void LASHeader::SetGeoreference() 
@@ -763,6 +699,5 @@
     m_srs = srs;
 }
 
-
 } // namespace liblas
 

Modified: trunk/src/lasreader.cpp
==============================================================================
--- trunk/src/lasreader.cpp	(original)
+++ trunk/src/lasreader.cpp	Tue Jul 28 14:45:59 2009
@@ -122,7 +122,6 @@
 
     m_pimpl->ReadGeoreference(m_header);
     m_pimpl->Reset(m_header);
-
 }
 
 std::istream& LASReader::GetStream() const


More information about the Liblas-commits mailing list