[Liblas-commits] hg-main-tree: add some more user fields

liblas-commits at liblas.org liblas-commits at liblas.org
Fri May 6 11:59:58 EDT 2011


details:   http://hg.libpc.orghg-main-tree/rev/eea5ec3e2d46
changeset: 701:eea5ec3e2d46
user:      Howard Butler <hobu.inc at gmail.com>
date:      Fri May 06 10:58:56 2011 -0500
description:
add some more user fields
Subject: hg-main-tree: construct schema for QFIT data based on the three possible formats and calculate a point count based on point format size and header offset information

details:   http://hg.libpc.orghg-main-tree/rev/3114d8b05ac7
changeset: 702:3114d8b05ac7
user:      Howard Butler <hobu.inc at gmail.com>
date:      Fri May 06 10:59:44 2011 -0500
description:
construct schema for QFIT data based on the three possible formats and calculate a point count based on point format size and header offset information

diffstat:

 include/libpc/Dimension.hpp           |    6 +
 include/libpc/drivers/qfit/Reader.hpp |   47 +++
 src/drivers/qfit/Reader.cpp           |  442 +++++++++++++++++++++++----------
 test/unit/QFITReaderTest.cpp          |    2 +
 4 files changed, 365 insertions(+), 132 deletions(-)

diffs (truncated from 606 to 300 lines):

diff -r b24b73d5636d -r 3114d8b05ac7 include/libpc/Dimension.hpp
--- a/include/libpc/Dimension.hpp	Fri May 06 09:25:56 2011 -0500
+++ b/include/libpc/Dimension.hpp	Fri May 06 10:59:44 2011 -0500
@@ -97,6 +97,12 @@
         Field_User7,
         Field_User8,
         Field_User9,
+        Field_User10,
+        Field_User11,
+        Field_User12,
+        Field_User13,
+        Field_User14,
+        Field_User15,
         // ...
         // feel free to use your own int here
 
diff -r b24b73d5636d -r 3114d8b05ac7 include/libpc/drivers/qfit/Reader.hpp
--- a/include/libpc/drivers/qfit/Reader.hpp	Fri May 06 09:25:56 2011 -0500
+++ b/include/libpc/drivers/qfit/Reader.hpp	Fri May 06 10:59:44 2011 -0500
@@ -38,16 +38,60 @@
 #include <libpc/libpc.hpp>
 
 #include <libpc/Stage.hpp>
+
+#include <libpc/SchemaLayout.hpp>
+
 #include <libpc/Iterator.hpp>
+#include <libpc/exceptions.hpp>
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_array.hpp>
 
 #include <vector>
 
+#include <boost/detail/endian.hpp>
+
+#ifdef BOOST_LITTLE_ENDIAN
+# define QFIT_SWAP_BE_TO_LE(p) \
+    do { \
+        char* first = static_cast<char*>(static_cast<void*>(&p)); \
+        char* last = first + sizeof(p) - 1; \
+        for(; first < last; ++first, --last) { \
+            char const x = *last; \
+            *last = *first; \
+            *first = x; \
+        }} while(false)
+
+# define QFIT_SWAP_BE_TO_LE_N(p, n) \
+    do { \
+        char* first = static_cast<char*>(static_cast<void*>(&p)); \
+        char* last = first + n - 1; \
+        for(; first < last; ++first, --last) { \
+            char const x = *last; \
+            *last = *first; \
+            *first = x; \
+        }} while(false)
+#endif
+
 namespace libpc { namespace drivers { namespace qfit {
 
 
+enum QFIT_Format_Type
+{
+    QFIT_Format_10 = 10,
+    QFIT_Format_12 = 12,
+    QFIT_Format_14 = 14,
+    QFIT_Format_Unknown = 128
+};
+
+class qfit_error : public libpc_error
+{
+public:
+
+    qfit_error(std::string const& msg)
+        : libpc_error(msg)
+    {}
+};
 
 class LIBPC_DLL Reader : public libpc::Stage
 {
@@ -71,6 +115,8 @@
     
     Options& getOptions() const { return m_options; }
 
+protected:
+    inline QFIT_Format_Type getFormat() const { return m_format; }
 
 private:
 
@@ -78,6 +124,7 @@
     Reader(const Reader&); // not implemented
 
     Options& m_options;
+    QFIT_Format_Type m_format;
     
     void registerFields();
 
diff -r b24b73d5636d -r 3114d8b05ac7 src/drivers/qfit/Reader.cpp
--- a/src/drivers/qfit/Reader.cpp	Fri May 06 09:25:56 2011 -0500
+++ b/src/drivers/qfit/Reader.cpp	Fri May 06 10:59:44 2011 -0500
@@ -32,6 +32,141 @@
 * OF SUCH DAMAGE.
 ****************************************************************************/
 
+/*
+
+Airborne Topographic Mapper (ATM) Project
+NASA, Goddard Space Flight Center, Wallops Flight Facility
+Principal Investigator: Bill Krabill (William.B.Krabill at nasa.gov)
+
+Description of ATM QFIT Output Data
+(revised 2009-feb-13 sm)
+
+ATM data is generally distributed in the output format of the
+processing  program, qfit, which combines airborne laser ranging
+data and aircraft attitude from the INS with positioning
+information from a processed kinematic  differential GPS
+trajectory.  Qfit output files, which usually have names ending
+in a .qi extension, are organized as 32-bit (4-byte)
+binary  words, equivalent to a C or IDL long integer, which are
+scaled to retain the precision of the measurements.  The format
+and the scaling factors are presented below.  The qfit program is
+run on an Apple PowerPC processor (and formerly Sun/Motorola).
+Accordingly, the output is written in a big-endian format and
+must be byte-swapped to be read with a PC (Intel processor)
+which uses a little-endian format to store 32-bit integers.
+
+The files are organized into fixed-length logical records. The
+beginning of the file contains a header of one or more records
+followed by a data segment, in which there is one record per
+laser shot. It is not necessary to interpret the header
+to use the laser data.
+
+The first word of the header (and the file) is a 32-bit  binary
+integer giving the number of bytes in each logical record.  Commonly
+qfit files have 12 words per record and this integer will be the 
+number 48.  The remainder of the initial logical record is padded 
+with blank bytes (in this case 44 blank bytes). 10-word and 14-word
+formats have also been used, as described below.
+
+The remainder of the header is generally a series of logical
+records  containing the processing history of the file.  In these
+logical records, the  initial word contains a 32-bit binary
+integer with a value between -9000000 and -9000008.  The 
+remaining bytes in each header record is filled with a string of 
+ascii characters containing information on file processing
+history.  In this case, the byte offset (as a longword integer) 
+from the start of file to the start of laser data will be the 
+second word of the second record of the header.  (Note: The header 
+records can be removed by eliminating records that begin with a 
+negative value since the first word of records in the data segment 
+is always a positive number.) 
+
+In the data segment of the file, the information contained in
+words 1-11 of the output record pertains to the  laser pulse, its
+footprint, and aircraft attitude.  The last word of each record is
+always the GPS time of day when the laser measurement was acquired.
+
+Prior to 2008 surveys, the GPS trajectory was edited to restrict PDOP<9
+in order to limit GPS errors to be less than roughly 5cm.  The output
+survey data would therefore have occasional gaps where the PDOP>9.  
+Some applications of ATM data have less stringent accuracy requirements
+that would be better served by preserving the data in these gaps.  
+Starting in 2008, the PDOP limit was changed to 20, which could allow
+occasional GPS errors up to about 15cm.  The PDOP value is carried in 
+the qfit output and can be used to edit data for applications requiring 
+greater precision.   Any file in the 10-word format, or files in the 12-word
+format processed prior to January 2009, will have PDOP limited
+<9.  
+
+The three data formats are described below.  The format is designated by
+the logical record length given in the first word of the data file.
+
+The qi 12-word format (in use since 2006):
+Word #       Content
+   1    Relative Time (msec from start of data file)  
+   2    Laser Spot Latitude (degrees X 1,000,000)
+   3    Laser Spot Longitude (degrees X 1,000,000) 
+   4    Elevation (millimeters)
+   5    Start Pulse Signal Strength (relative) 
+   6    Reflected Laser Signal Strength (relative) 
+   7    Scan Azimuth (degrees X 1,000)
+   8    Pitch (degrees X 1,000)
+   9    Roll (degrees X 1,000)
+  10    GPS PDOP (dilution of precision) (X 10) 
+  11    Laser received pulse width (digitizer samples)
+  12    GPS Time packed (example: 153320100 = 15h 33m 20s 100ms)
+
+10-word format (used prior to 2006):
+Word #       Content
+   1    Relative Time (msec from start of data file)  
+   2    Laser Spot Latitude (degrees X 1,000,000)
+   3    Laser Spot Longitude (degrees X 1,000,000) 
+   4    Elevation (millimeters)
+   5    Start Pulse Signal Strength (relative) 
+   6    Reflected Laser Signal Strength (relative) 
+   7    Scan Azimuth (degrees X 1,000)
+   8    Pitch (degrees X 1,000)
+   9    Roll (degrees X 1,000)
+  10    GPS Time packed (example: 153320100 = 15h 33m 20s 100ms)
+
+
+Between 1997 and 2004 some ATM surveys included 
+a separate sensor to measure passive brightness. 
+In the 14-word format, words 10-13 pertain to the
+passive brightness signal, which is essentially a relative
+measure of radiance reflected from the  earth's surface within
+the vicinity of the laser pulse.  The horizontal position of the
+passive footprint is determined relative to the laser footprint
+by a  delay formulated during ground testing at Wallops.  The
+elevation of the footprint is synthesized from surrounding laser
+elevation data.  NOTE:  The passive data is not calibrated and
+its use, if any, should  be qualitative in nature.  It may aid 
+the interpretation of terrain features. The measurement capability 
+was engineered into the ATM sensors to aid in the identification 
+of the water/beach interface acquired with  the instrument in 
+coastal mapping applications.
+
+14-word format:
+Word #       Content
+   1    Relative Time (msec from start of data file)  
+   2    Laser Spot Latitude (degrees X 1,000,000)
+   3    Laser Spot Longitude (degrees X 1,000,000) 
+   4    Elevation (millimeters)
+   5    Start Pulse Signal Strength (relative) 
+   6    Reflected Laser Signal Strength (relative) 
+   7    Scan Azimuth (degrees X 1,000)
+   8    Pitch (degrees X 1,000)
+   9    Roll (degrees X 1,000)
+  10    Passive Signal (relative)
+  11    Passive Footprint Latitude (degrees X 1,000,000)
+  12    Passive Footprint Longitude (degrees X 1,000,000)
+  13    Passive Footprint Synthesized Elevation (millimeters)
+  14    GPS Time packed (example: 153320100 = 15h 33m 20s 100ms)
+
+
+*/
+
+
 #include <libpc/drivers/qfit/Reader.hpp>
 #include <libpc/drivers/oci/Iterator.hpp>
 #include <libpc/Utils.hpp>
@@ -48,8 +183,80 @@
     : libpc::Stage()
     , m_options(options)
 {
+    std::string filename= m_options.GetPTree().get<std::string>("input");
+    
+    std::istream* str = Utils::openFile(filename);
+    
+    str->seekg(0);
+    
+    boost::int32_t int4(0);
+    
+    Utils::read_n(int4, *str, sizeof(int4));
+    QFIT_SWAP_BE_TO_LE(int4);
+    
+    if ( int4 % 4 != 0)
+        throw qfit_error("Base QFIT format is not a multiple of 4, unrecognized format!");
+    
+    m_format = static_cast<QFIT_Format_Type>(int4/sizeof(int4));
+    // std::cout << "QFIT Point format " << m_format << std::endl;
+    
+    // The offset to start reading point data should be here.
+    str->seekg(44);
 
+    Utils::read_n(int4, *str, sizeof(int4));
+    QFIT_SWAP_BE_TO_LE(int4);
+    std::size_t off = static_cast<std::size_t>(int4);
+    
+    registerFields();
+    
+    SchemaLayout layout(getSchemaRef());
 
+    // Seek to the beginning 
+    str->seekg(0, std::ios::beg);
+    std::ios::pos_type beginning = str->tellg();
+
+    // Seek to the end
+    str->seekg(0, std::ios::end);
+    std::ios::pos_type end = str->tellg();
+    std::ios::off_type size = end - beginning;
+
+    // First integer is the format of the file
+    std::ios::off_type offset = static_cast<std::ios::off_type>(off);  
+    std::ios::off_type length = static_cast<std::ios::off_type>(layout.getByteSize());
+    std::ios::off_type point_bytes = end - offset;
+
+    // Figure out how many points we have and whether or not we have 
+    // extra slop in there.
+    std::ios::off_type count = point_bytes / length;
+    std::ios::off_type remainder = point_bytes % length;    
+
+    // std::cout << "count: " << count << std::endl;
+    // std::cout <<" point_bytes: " << point_bytes << std::endl;
+    // std::cout <<" length: " << length << std::endl;
+    // std::cout <<" offset: " << offset << std::endl;
+    // std::cout <<" remainder: " << remainder << std::endl;
+    // std::cout <<" beginning: " << beginning << std::endl;
+


More information about the Liblas-commits mailing list