[Liblas-commits] libpc: use constant-time field indexing

liblas-commits at liblas.org liblas-commits at liblas.org
Wed Feb 23 18:06:16 EST 2011


details:   http://hg.liblas.orglibpc/rev/f1fb059c0456
changeset: 79:f1fb059c0456
user:      Michael P. Gerlek <mpg at flaxen.com>
date:      Wed Feb 23 15:06:04 2011 -0800
description:
use constant-time field indexing

diffstat:

 apps/pc2pc.cpp              |   2 +-
 include/libpc/Dimension.hpp |  52 ++++++++++++++++++++++++++++--
 include/libpc/Schema.hpp    |  11 +++--
 src/ColorFilter.cpp         |  14 ++++----
 src/CropFilter.cpp          |   6 +-
 src/Dimension.cpp           |  72 +++++++++++++++++++++++++++++++++++++----
 src/FauxReader.cpp          |  16 ++++----
 src/LasHeader.cpp           |  35 ++++++++++---------
 src/LasReader.cpp           |  32 +++++++++---------
 src/LasWriter.cpp           |  34 +++++++++---------
 src/PointData.cpp           |   2 +-
 src/Schema.cpp              |  77 +++++++++++++++++++++-----------------------
 test/unit/DimensionTest.cpp |  15 ++++----
 test/unit/PointDataTest.cpp |  10 ++--
 test/unit/SchemaTest.cpp    |  20 +++++++----
 15 files changed, 253 insertions(+), 145 deletions(-)

diffs (truncated from 889 to 300 lines):

diff -r a3591d60a9f3 -r f1fb059c0456 apps/pc2pc.cpp
--- a/apps/pc2pc.cpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/apps/pc2pc.cpp	Wed Feb 23 15:06:04 2011 -0800
@@ -114,7 +114,7 @@
     }
 
     {
-        Dimension dim("foo", Dimension::Uint8);
+        Dimension dim(Dimension::Field_User1, Dimension::Uint8);
         std::cout << dim << std::endl;
     }
 
diff -r a3591d60a9f3 -r f1fb059c0456 include/libpc/Dimension.hpp
--- a/include/libpc/Dimension.hpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/include/libpc/Dimension.hpp	Wed Feb 23 15:06:04 2011 -0800
@@ -64,6 +64,43 @@
 class LIBPC_DLL Dimension
 {
 public:
+    enum Field
+    {
+        Field_INVALID = 0,
+        Field_X,
+        Field_Y,
+        Field_Z,
+        Field_Red,
+        Field_Green,
+        Field_Blue,
+        Field_Time,
+        Field_Intensity,
+        Field_ReturnNumber,
+        Field_NumberOfReturns,
+        Field_ScanDirection,
+        Field_FlightLineEdge,
+        Field_Classification,
+        Field_ScanAngleRank,
+        Field_UserData,
+        Field_PointSourceId,
+        // ...
+
+        // add more here (but be sure and call setFieldName()!)
+        Field_User1 = 512,
+        Field_User2,
+        Field_User3,
+        Field_User4,
+        Field_User5,
+        Field_User6,
+        Field_User7,
+        Field_User8,
+        Field_User9,
+        // ...
+        // feel free to use your own int here
+
+        Field_LAST = 1023
+    };
+
     enum DataType
     {
         Int8,
@@ -79,16 +116,18 @@
     };
 
 public:
-    Dimension(std::string const& name, DataType type);
+    Dimension(Field field, DataType type);
     Dimension& operator=(Dimension const& rhs);
     Dimension(Dimension const& other);
 
     bool operator==(const Dimension& other) const;
     bool operator!=(const Dimension& other) const;
 
-    inline std::string const& getName() const
+    std::string const& getFieldName() const;
+
+    Field getField() const
     {
-        return m_name;
+        return m_field;
     }
 
     DataType getDataType() const
@@ -102,6 +141,7 @@
     static bool getDataTypeIsNumeric(DataType);
     static bool getDataTypeIsSigned(DataType);
     static bool getDataTypeIsInteger(DataType);
+    static std::string const& getFieldName(Field);
 
     /// bytes, physical/serialisation size of record
     // for bitfields, this will be rounded up to the next largest byte
@@ -199,7 +239,7 @@
 
 private:
     DataType m_dataType;
-    std::string m_name;
+    Field m_field;
     std::size_t m_byteSize;
     std::string m_description;
     double m_min;
@@ -207,6 +247,10 @@
     bool m_precise;
     double m_numericScale;
     double m_numericOffset;
+
+    static void initFieldNames();
+    static bool s_fieldNamesValid;
+    static std::string s_fieldNames[Field_LAST];
 };
 
 
diff -r a3591d60a9f3 -r f1fb059c0456 include/libpc/Schema.hpp
--- a/include/libpc/Schema.hpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/include/libpc/Schema.hpp	Wed Feb 23 15:06:04 2011 -0800
@@ -75,8 +75,6 @@
 
     void addDimension(Dimension const& dim);
 
-    std::vector<std::string> getDimensionNames() const;
-
     const Dimension& getDimension(std::size_t index) const
     {
         return m_dimensions[index];
@@ -94,16 +92,19 @@
 
     // returns true if found and sets index, otherwise returns false
     // BUG: this is deadly slow, need to use old assoc array or fixed enum for field names
-    bool findDimensionIndex(const std::string& name, std::size_t& index) const; 
-    bool hasDimension(const std::string& name) const;
+    bool findDimensionIndex(Dimension::Field field, std::size_t& index) const; 
+    bool hasDimension(Dimension::Field field) const;
 
     // this version throws if the index not found
-    std::size_t getDimensionIndex(const std::string& name) const; 
+    std::size_t getDimensionIndex(Dimension::Field field) const; 
 
     boost::property_tree::ptree getPTree() const;
 
 private:
     std::vector<Dimension> m_dimensions;
+
+    // BUG: use boost::array?
+    int m_indexTable[Dimension::Field_LAST]; // mapping from field name to index position, or -1 if field not present
 };
 
 
diff -r a3591d60a9f3 -r f1fb059c0456 src/ColorFilter.cpp
--- a/src/ColorFilter.cpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/src/ColorFilter.cpp	Wed Feb 23 15:06:04 2011 -0800
@@ -45,9 +45,9 @@
     Schema& schema = getHeader().getSchema();
 
     // add the three u8 fields
-    schema.addDimension(Dimension("Zred", Dimension::Uint8));
-    schema.addDimension(Dimension("Zgreen", Dimension::Uint8));
-    schema.addDimension(Dimension("Zblue", Dimension::Uint8));
+    schema.addDimension(Dimension(Dimension::Field_Red, Dimension::Uint8));
+    schema.addDimension(Dimension(Dimension::Field_Green, Dimension::Uint8));
+    schema.addDimension(Dimension(Dimension::Field_Blue, Dimension::Uint8));
 
     return;
 }
@@ -68,13 +68,13 @@
     std::size_t offsetZ;
     bool ok;
 
-    ok = schema.findDimensionIndex("Zred", fieldIndexR);
+    ok = schema.findDimensionIndex(Dimension::Field_Red, fieldIndexR);
     assert(ok);
-    ok = schema.findDimensionIndex("Zgreen", fieldIndexG);
+    ok = schema.findDimensionIndex(Dimension::Field_Green, fieldIndexG);
     assert(ok);
-    ok = schema.findDimensionIndex("Zblue", fieldIndexB);
+    ok = schema.findDimensionIndex(Dimension::Field_Blue, fieldIndexB);
     assert(ok);
-    ok = schema.findDimensionIndex("ZPos", offsetZ);
+    ok = schema.findDimensionIndex(Dimension::Field_Z, offsetZ);
     assert(ok);
 
     for (int pointIndex=0; pointIndex<numPoints; pointIndex++)
diff -r a3591d60a9f3 -r f1fb059c0456 src/CropFilter.cpp
--- a/src/CropFilter.cpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/src/CropFilter.cpp	Wed Feb 23 15:06:04 2011 -0800
@@ -63,11 +63,11 @@
     std::size_t fieldZ;
     bool ok;
 
-    ok = schema.findDimensionIndex("XPos", fieldX);
+    ok = schema.findDimensionIndex(Dimension::Field_X, fieldX);
     assert(ok);
-    ok = schema.findDimensionIndex("XPos", fieldY);
+    ok = schema.findDimensionIndex(Dimension::Field_Y, fieldY);
     assert(ok);
-    ok = schema.findDimensionIndex("XPos", fieldZ);
+    ok = schema.findDimensionIndex(Dimension::Field_Z, fieldZ);
     assert(ok);
 
 
diff -r a3591d60a9f3 -r f1fb059c0456 src/Dimension.cpp
--- a/src/Dimension.cpp	Wed Feb 23 11:44:54 2011 -0800
+++ b/src/Dimension.cpp	Wed Feb 23 15:06:04 2011 -0800
@@ -39,6 +39,7 @@
  * OF SUCH DAMAGE.
  ****************************************************************************/
 
+#include "libpc/exceptions.hpp"
 #include "libpc/Dimension.hpp"
 #include "libpc/Utils.hpp"
 
@@ -49,10 +50,13 @@
 namespace libpc
 {
 
+std::string Dimension::s_fieldNames[Field_LAST];
+bool Dimension::s_fieldNamesValid = false;
 
-Dimension::Dimension(std::string const& name, DataType dataType)
+
+Dimension::Dimension(Field field, DataType dataType)
     : m_dataType(dataType)
-    , m_name(name)
+    , m_field(field)
     , m_byteSize(0)
     , m_description(std::string(""))
     , m_min(0)
@@ -67,7 +71,7 @@
 /// copy constructor
 Dimension::Dimension(Dimension const& other) 
     : m_dataType(other.m_dataType)
-    , m_name(other.m_name)
+    , m_field(other.m_field)
     , m_byteSize(other.m_byteSize)
     , m_description(other.m_description)
     , m_min(other.m_min)
@@ -84,7 +88,7 @@
     if (&rhs != this)
     {
         m_dataType = rhs.m_dataType;
-        m_name = rhs.m_name;
+        m_field = rhs.m_field;
         m_byteSize = rhs.m_byteSize;
         m_description = rhs.m_description;
         m_min = rhs.m_min;
@@ -101,7 +105,7 @@
 bool Dimension::operator==(const Dimension& other) const
 {
     if (m_dataType == other.m_dataType &&
-        m_name == other.m_name &&
+        m_field == other.m_field &&
         m_byteSize == other.m_byteSize &&
         m_description == other.m_description &&
         m_min == other.m_min &&
@@ -127,7 +131,7 @@
 {
     using property_tree::ptree;
     ptree dim;
-    dim.put("name", getName());
+    dim.put("name", getFieldName());
     dim.put("datatype", getDataTypeName(getDataType()));
     dim.put("description", getDescription());
     dim.put("bytesize", getByteSize());
@@ -165,7 +169,7 @@
         pad << " ";
     }
     os << quoted_name.str() << pad.str() <<" -- "<< " size: " << tree.get<boost::uint32_t>("bytesize");
-    os << " offset: " << tree.get<boost::uint32_t>("byteoffset");
+    //os << " offset: " << tree.get<boost::uint32_t>("byteoffset");
     os << std::endl;
 
     return os;
@@ -310,8 +314,60 @@
 }
 
 
+std::string const& Dimension::getFieldName() const
+{
+    return getFieldName(m_field);
+}
 
 
+std::string const& Dimension::getFieldName(Field field)
+{
+    if (!s_fieldNamesValid)
+        initFieldNames();
+
+    if (field > Field_LAST)
+        throw libpc_error("invalid field value (too large)");
+
+    const std::string& s =  s_fieldNames[field];
+    if (s.empty())
+    {
+        throw libpc_error("Field name not set for built-in field value");
+    }        
+
+    return s;
+}
+
+
+void Dimension::initFieldNames()
+{
+    // BUG: not threadsafe
+    s_fieldNames[Field_INVALID] = "invalid";


More information about the Liblas-commits mailing list