[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