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

liblas-commits at liblas.org liblas-commits at liblas.org
Tue Jul 28 22:52:39 EDT 2009


Author: hobu
Date: Tue Jul 28 22:52:35 2009
New Revision: 1326
URL: http://liblas.org/changeset/1326

Log:
fix #142 to handle the case where the recordlength does not actually match a the size defined by the point format

Modified:
   trunk/include/liblas/capi/liblas.h
   trunk/include/liblas/lasheader.hpp
   trunk/python/liblas/core.py
   trunk/python/liblas/header.py
   trunk/python/tests/Header.txt
   trunk/src/detail/reader10.cpp
   trunk/src/detail/reader11.cpp
   trunk/src/detail/reader12.cpp
   trunk/src/las_c_api.cpp
   trunk/src/lasheader.cpp

Modified: trunk/include/liblas/capi/liblas.h
==============================================================================
--- trunk/include/liblas/capi/liblas.h	(original)
+++ trunk/include/liblas/capi/liblas.h	Tue Jul 28 22:52:35 2009
@@ -660,6 +660,14 @@
 */
 LAS_DLL uint16_t LASHeader_GetDataRecordLength(const LASHeaderH hHeader);
 
+/** Explicitly set the record length for the file.  If you set the DataFormatId,
+ *  default values will be set for you.
+ *  @param hHeader LASHeaderH instance
+ *  @param value the value for the data record length (in bytes).
+ *  @return LASError enum
+*/
+LAS_DLL LASError LASHeader_SetDataRecordLength(const LASHeaderH hHeader, uint16_t value);
+
 /** Returns the data format id.  If this value is 1, the point data have time values
  *  associated with them.  If it is 0, the point data do not have time values.  
  *  @param hHeader LASHeaderH instance

Modified: trunk/include/liblas/lasheader.hpp
==============================================================================
--- trunk/include/liblas/lasheader.hpp	(original)
+++ trunk/include/liblas/lasheader.hpp	Tue Jul 28 22:52:35 2009
@@ -249,6 +249,11 @@
 
     /// \todo To be documented
     uint16_t GetDataRecordLength() const;
+
+    /// Set the length of the point format.  Evidently, there are 
+    /// LAS files in the wild that contain point formats of sizes that 
+    /// are different than the prescribed set specified in the specification.
+    void SetDataRecordLength(uint16_t v);
     
     /// Get total number of point records stored in the LAS file.
     uint32_t GetPointRecordsCount() const;

Modified: trunk/python/liblas/core.py
==============================================================================
--- trunk/python/liblas/core.py	(original)
+++ trunk/python/liblas/core.py	Tue Jul 28 22:52:35 2009
@@ -378,6 +378,10 @@
 las.LASHeader_GetDataRecordLength.argtypes = [ctypes.c_void_p]
 las.LASHeader_GetDataRecordLength.errcheck = check_value
 
+las.LASHeader_SetDataRecordLength.restype = ctypes.c_int
+las.LASHeader_SetDataRecordLength.argtypes = [ctypes.c_void_p, ctypes.c_ushort]
+las.LASHeader_SetDataRecordLength.errcheck = check_return
+
 las.LASHeader_GetPointRecordsCount.restype = ctypes.c_ulong
 las.LASHeader_GetPointRecordsCount.argtypes = [ctypes.c_void_p]
 las.LASHeader_GetPointRecordsCount.errcheck = check_value

Modified: trunk/python/liblas/header.py
==============================================================================
--- trunk/python/liblas/header.py	(original)
+++ trunk/python/liblas/header.py	Tue Jul 28 22:52:35 2009
@@ -220,7 +220,11 @@
     
     def get_datarecordlength(self):
         return core.las.LASHeader_GetDataRecordLength(self.handle)
-    data_record_length = property(get_datarecordlength)
+    def set_datarecordlength(self, value):
+        """Don't use this if ya know what's good for ya ;)
+        """
+        return core.las.LASHeader_SetDataRecordLength(self.handle, value)
+    data_record_length = property(get_datarecordlength, set_datarecordlength)
     
     def get_pointrecordscount(self):
         """Returns the expected number of point records in the file.  

Modified: trunk/python/tests/Header.txt
==============================================================================
--- trunk/python/tests/Header.txt	(original)
+++ trunk/python/tests/Header.txt	Tue Jul 28 22:52:35 2009
@@ -113,3 +113,12 @@
   >>> h.data_offset
   742L
 
+  >>> h.data_record_length
+  20
+  >>> h.dataformat_id = 3
+  >>> h.data_record_length
+  34
+  
+  >>> h.data_record_length = 24
+  >>> h.data_record_length
+  24

Modified: trunk/src/detail/reader10.cpp
==============================================================================
--- trunk/src/detail/reader10.cpp	(original)
+++ trunk/src/detail/reader10.cpp	Tue Jul 28 22:52:35 2009
@@ -168,9 +168,8 @@
     }
     
     // 17. Point Data Record Length
-    // NOTE: No need to set record length because it's
-    // determined on basis of point data format.
     read_n(n2, m_ifs, sizeof(n2));
+    header.SetDataRecordLength(n2);
 
     // 18. Number of point records
     read_n(n4, m_ifs, sizeof(n4));
@@ -227,6 +226,10 @@
 
     if (m_current < m_size)
     {
+        // accounting to keep track of the fact that the DataRecordLength 
+        // might not map to ePointSize0 or ePointSize1 (see http://liblas.org/ticket/142)
+        size_t bytesread = 0;
+        
         detail::PointRecord record;
         // TODO: Replace with compile-time assert
         assert(LASHeader::ePointSize0 == sizeof(record));
@@ -234,7 +237,8 @@
         try
         {
             detail::read_n(record, m_ifs, sizeof(PointRecord));
-            ++m_current;    
+            ++m_current;
+            bytesread += sizeof(PointRecord);
         }
         catch (std::out_of_range const& e) // we reached the end of the file
         {
@@ -251,7 +255,10 @@
 
             detail::read_n(gpst, m_ifs, sizeof(double));
             point.SetTime(gpst);
+            bytesread += sizeof(double);
         }
+        if (bytesread != header.GetDataRecordLength())
+            m_ifs.seekg(header.GetDataRecordLength() - bytesread, std::ios::cur);
         return true;
     }
 
@@ -271,9 +278,15 @@
     // TODO: Replace with compile-time assert
     detail::PointRecord record;
     assert(LASHeader::ePointSize0 == sizeof(record));
+    
+    // accounting to keep track of the fact that the DataRecordLength 
+    // might not map to ePointSize0 or ePointSize1 (see http://liblas.org/ticket/142)
+    size_t bytesread = 0;
 
     detail::read_n(record, m_ifs, sizeof(record));
 
+    bytesread += sizeof(PointRecord);
+
     Reader::FillPoint(record, point);
     point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
 
@@ -282,8 +295,12 @@
         double gpst(0);
         detail::read_n(gpst, m_ifs, sizeof(double));
         point.SetTime(gpst);
+        bytesread += sizeof(double);
     }
 
+    if (bytesread != header.GetDataRecordLength())
+        m_ifs.seekg(header.GetDataRecordLength() - bytesread, std::ios::cur);
+
     return true;
 }
 

Modified: trunk/src/detail/reader11.cpp
==============================================================================
--- trunk/src/detail/reader11.cpp	(original)
+++ trunk/src/detail/reader11.cpp	Tue Jul 28 22:52:35 2009
@@ -172,9 +172,8 @@
     }
     
     // 18. Point Data Record Length
-    // NOTE: No need to set record length because it's
-    // determined on basis of point data format.
     read_n(n2, m_ifs, sizeof(n2));
+    header.SetDataRecordLength(n2);
 
     // 19. Number of point records
     read_n(n4, m_ifs, sizeof(n4));
@@ -231,6 +230,8 @@
 
     if (m_current < m_size)
     {
+        size_t bytesread = 0;
+        
         detail::PointRecord record;
         // TODO: Replace with compile-time assert
         assert(LASHeader::ePointSize0 == sizeof(record));
@@ -238,7 +239,8 @@
         try
         {
             detail::read_n(record, m_ifs, sizeof(PointRecord));
-            ++m_current;    
+            ++m_current;
+            bytesread += sizeof(PointRecord);
         }        
         catch (std::out_of_range const& e) // we reached the end of the file
         {
@@ -254,8 +256,12 @@
             double gpst = 0;
             detail::read_n(gpst, m_ifs, sizeof(double));
             point.SetTime(gpst);
+            bytesread += sizeof(double);
         }
+        if (bytesread != header.GetDataRecordLength())
+            m_ifs.seekg(header.GetDataRecordLength() - bytesread, std::ios::cur);
         return true;
+        
     }
 
     return false;
@@ -272,11 +278,17 @@
     m_ifs.clear();
     m_ifs.seekg(pos, std::ios::beg);
 
+    
+    // accounting to keep track of the fact that the DataRecordLength 
+    // might not map to ePointSize0 or ePointSize1 (see http://liblas.org/ticket/142)
+    size_t bytesread = 0;
+    
     detail::PointRecord record;
     // TODO: Replace with compile-time assert
     assert(LASHeader::ePointSize0 == sizeof(record));
 
     detail::read_n(record, m_ifs, sizeof(record));
+    bytesread += sizeof(PointRecord);
 
     Reader::FillPoint(record, point);
     point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
@@ -286,8 +298,11 @@
         double gpst = 0;
         detail::read_n(gpst, m_ifs, sizeof(double));
         point.SetTime(gpst);
+        bytesread += sizeof(double);
     }
 
+    if (bytesread != header.GetDataRecordLength())
+        m_ifs.seekg(header.GetDataRecordLength() - bytesread, std::ios::cur);
     return true;
 }
 

Modified: trunk/src/detail/reader12.cpp
==============================================================================
--- trunk/src/detail/reader12.cpp	(original)
+++ trunk/src/detail/reader12.cpp	Tue Jul 28 22:52:35 2009
@@ -174,9 +174,8 @@
     }
 
     // 18. Point Data Record Length
-    // NOTE: No need to set record length because it's
-    // determined on basis of point data format.
     read_n(n2, m_ifs, sizeof(n2));
+    header.SetDataRecordLength(n2);
 
     // 19. Number of point records
     read_n(n4, m_ifs, sizeof(n4));
@@ -233,6 +232,8 @@
 
     if (m_current < m_size)
     {
+        size_t bytesread = 0;
+        
         detail::PointRecord record;
         // TODO: Replace with compile-time assert
         assert(LASHeader::ePointSize0 == sizeof(record));
@@ -240,7 +241,8 @@
         try
         {
             detail::read_n(record, m_ifs, sizeof(PointRecord));
-            ++m_current;    
+            ++m_current;
+            bytesread += sizeof(PointRecord);
         }        
         catch (std::out_of_range const& e) // we reached the end of the file
         {
@@ -260,6 +262,8 @@
         {
             detail::read_n(gpst, m_ifs, sizeof(double));
             point.SetTime(gpst);
+            
+            bytesread += sizeof(double);
         }
         else if (header.GetDataFormatId() == LASHeader::ePointFormat2)
         {
@@ -269,6 +273,8 @@
 
             LASColor color(red, green, blue);
             point.SetColor(color);
+            
+            bytesread += 3 * sizeof(uint16_t);
         }
         else if (header.GetDataFormatId() == LASHeader::ePointFormat3)
         {
@@ -281,8 +287,13 @@
             
             LASColor color(red, green, blue);
             point.SetColor(color);
+            
+            bytesread += sizeof(double) + 3 * sizeof(uint16_t);
         }
 
+        if (bytesread != header.GetDataRecordLength())
+            m_ifs.seekg(header.GetDataRecordLength() - bytesread, std::ios::cur);
+            
         return true;
     }
     
@@ -313,8 +324,14 @@
 
     m_ifs.clear();
     m_ifs.seekg(pos, std::ios::beg);
+
+    // accounting to keep track of the fact that the DataRecordLength 
+    // might not map to ePointSize0 or ePointSize1 (see http://liblas.org/ticket/142)
+    size_t bytesread = 0;
     detail::read_n(record, m_ifs, sizeof(record));
 
+    bytesread += sizeof(PointRecord);
+    
     Reader::FillPoint(record, point);
     point.SetCoordinates(header, point.GetX(), point.GetY(), point.GetZ());
 
@@ -322,6 +339,8 @@
     {
         detail::read_n(t, m_ifs, sizeof(double));
         point.SetTime(t);
+        
+        bytesread += sizeof(double);
     }
     else if (header.GetDataFormatId() == LASHeader::ePointFormat2)
     {
@@ -332,6 +351,8 @@
         color.SetBlue(blue);
         color.SetGreen(green);
         point.SetColor(color);
+        
+        bytesread += 3 * sizeof(uint16_t);
     }
     else if (header.GetDataFormatId() == LASHeader::ePointFormat3)
     {
@@ -344,6 +365,8 @@
         color.SetBlue(blue);
         color.SetGreen(green);
         point.SetColor(color);
+        
+        bytesread += sizeof(double) + 3 * sizeof(uint16_t);
     }
              
         

Modified: trunk/src/las_c_api.cpp
==============================================================================
--- trunk/src/las_c_api.cpp	(original)
+++ trunk/src/las_c_api.cpp	Tue Jul 28 22:52:35 2009
@@ -934,6 +934,20 @@
     return value;
 }
 
+LAS_DLL LASErrorEnum LASHeader_SetDataRecordLength(const LASHeaderH hHeader, liblas::uint16_t value){
+    VALIDATE_LAS_POINTER1(hHeader, "LASHeader_SetDataRecordLength", LE_Failure);
+
+    try {
+        ((LASHeader*) hHeader)->SetDataRecordLength(value);    
+    } catch (std::exception const& e)
+    {
+        LASError_PushError(LE_Failure, e.what(), "LASHeader_SetDataRecordLength");
+        return LE_Failure;
+    }
+ 
+    return LE_None;    
+}
+
 
 LAS_DLL liblas::uint32_t LASHeader_GetPointRecordsByReturnCount(const LASHeaderH hHeader, int index) {
     VALIDATE_LAS_POINTER1(hHeader, "LASHeader_GetPointRecordsByReturnCount", 0);

Modified: trunk/src/lasheader.cpp
==============================================================================
--- trunk/src/lasheader.cpp	(original)
+++ trunk/src/lasheader.cpp	Tue Jul 28 22:52:35 2009
@@ -394,44 +394,26 @@
     m_dataFormatId = static_cast<uint8_t>(v);
 
     if (ePointFormat0 == m_dataFormatId)
-        m_dataRecordLen = ePointSize0;
+        SetDataRecordLength(ePointSize0);
     else if (ePointFormat1 == m_dataFormatId) 
-        m_dataRecordLen = ePointSize1;
+        SetDataRecordLength(ePointSize1);
     else if (ePointFormat2 == m_dataFormatId)
-        m_dataRecordLen = ePointSize2;
+        SetDataRecordLength(ePointSize2);
     else if (ePointFormat3 == m_dataFormatId)
-        m_dataRecordLen = ePointSize3;
+        SetDataRecordLength(ePointSize3);
     else
-        m_dataRecordLen = ePointSize3;
+        SetDataRecordLength(ePointSize3);
 }
 
 uint16_t LASHeader::GetDataRecordLength() const
 {
-    // NOTE: assertions below are used to check if our assumption is correct,
-    // for debugging purpose only.
-
-    if (ePointFormat0 == m_dataFormatId)
-    {
-        assert(ePointSize0 == m_dataRecordLen);
-        return ePointSize0;
-    }
-    if (ePointFormat1 == m_dataFormatId)
-    {
-        assert(ePointSize1 == m_dataRecordLen);
-        return ePointSize1;
-    }
-    if (ePointFormat2 == m_dataFormatId)
-    {
-        assert(ePointSize2 == m_dataRecordLen);
-        return ePointSize2;
-    }
-    else
-    {
-        assert(ePointSize3 == m_dataRecordLen);
-        return ePointSize3;
-    }
+    return m_dataRecordLen;
 }
 
+void LASHeader::SetDataRecordLength( uint16_t v )
+{
+    m_dataRecordLen = v;
+}
 uint32_t LASHeader::GetPointRecordsCount() const
 {
     return m_pointRecordsCount;


More information about the Liblas-commits mailing list