[Liblas-commits] r1242 - in trunk: apps include/liblas src

liblas-commits at liblas.org liblas-commits at liblas.org
Mon Apr 20 13:14:31 EDT 2009


Author: hobu
Date: Mon Apr 20 13:14:30 2009
New Revision: 1242
URL: http://liblas.org/changeset/1242

Log:
indexing prototype

Added:
   trunk/apps/lasindex.cpp
Modified:
   trunk/apps/   (props changed)
   trunk/apps/Makefile.am
   trunk/include/liblas/lasindex.hpp
   trunk/include/liblas/lasreader.hpp
   trunk/src/Makefile.am
   trunk/src/lasindex.cpp
   trunk/src/lasreader.cpp

Modified: trunk/apps/Makefile.am
==============================================================================
--- trunk/apps/Makefile.am	(original)
+++ trunk/apps/Makefile.am	Mon Apr 20 13:14:30 2009
@@ -6,7 +6,11 @@
 GEOTIFF_CPPFLAGS = @GEOTIFF_INC@ -DHAVE_LIBGEOTIFF=1
 endif
 
-AM_CPPFLAGS = $(GEOTIFF_CPPFLAGS) $(GDAL_CPPFLAGS) -I../include/liblas/capi -I../include
+if SPATIALINDEX_IS_CONFIG
+SPATIALINDEX_CPPFLAGS = @SPATIALINDEX_INC@/spatialindex @SPATIALINDEX_INC@ -DHAVE_SPATIALINDEX=1
+endif
+
+AM_CPPFLAGS = $(GEOTIFF_CPPFLAGS) $(GDAL_CPPFLAGS) $(SPATIALINDEX_CPPFLAGS) -I../include/liblas/capi -I../include
 
 lasinfo_SOURCES = lasinfo.c lascommon.c
 las2las_SOURCES = las2las.c lascommon.c
@@ -14,9 +18,10 @@
 las2txt_SOURCES = las2txt.c lascommon.c
 txt2las_SOURCES = txt2las.c
 ts2las_SOURCES = ts2las.cpp
+lasindex_SOURCES = lasindex.cpp
 
 
-bin_PROGRAMS = lasinfo las2las lasmerge las2txt txt2las ts2las
+bin_PROGRAMS = lasinfo las2las lasmerge las2txt txt2las ts2las lasindex
 
 bin_SCRIPTS = liblas-config
 

Added: trunk/apps/lasindex.cpp
==============================================================================
--- (empty file)
+++ trunk/apps/lasindex.cpp	Mon Apr 20 13:14:30 2009
@@ -0,0 +1,121 @@
+#include <liblas/cstdint.hpp>
+#include <liblas/detail/utility.hpp>
+
+#include <liblas/laswriter.hpp>
+#include <liblas/laspoint.hpp>
+#include <liblas/lascolor.hpp>
+#include <liblas/lasreader.hpp>
+#include <liblas/lasheader.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#ifdef _WIN32
+#define compare_no_case(a,b,n)  _strnicmp( (a), (b), (n) )
+#else
+#define compare_no_case(a,b,n)  strncasecmp( (a), (b), (n) )
+#endif
+
+std::istream* OpenInput(std::string filename) 
+{
+    std::ios::openmode const mode = std::ios::in | std::ios::binary;
+    std::istream* istrm;
+    if (compare_no_case(filename.c_str(),"STDIN",5) == 0)
+    {
+        istrm = &std::cin;
+    }
+    else 
+    {
+        istrm = new std::ifstream(filename.c_str(), mode);
+    }
+    
+    if (!istrm->good())
+    {
+        delete istrm;
+        throw std::runtime_error("Reading stream was not able to be created");
+        exit(1);
+    }
+    return istrm;
+}
+
+void usage() {}
+
+using namespace liblas;
+
+int main(int argc, char* argv[])
+{
+    int rc = 0;
+
+    std::string input;
+    std::string output;
+    
+    for (int i = 1; i < argc; i++)
+    {
+        if (    strcmp(argv[i],"-h") == 0 ||
+                strcmp(argv[i],"--help") == 0
+            )
+        {
+            usage();
+            exit(0);
+        }
+        else if (   strcmp(argv[i],"--input") == 0  ||
+                    strcmp(argv[i],"-input") == 0   ||
+                    strcmp(argv[i],"-i") == 0       ||
+                    strcmp(argv[i],"-in") == 0
+                )
+        {
+            i++;
+            input = std::string(argv[i]);
+        }
+        else if (   strcmp(argv[i],"--output") == 0  ||
+                    strcmp(argv[i],"--out") == 0     ||
+                    strcmp(argv[i],"-out") == 0     ||
+                    strcmp(argv[i],"-o") == 0       
+                )
+        {
+            i++;
+            output = std::string(argv[i]);
+        }
+        else if (i == argc - 2 && output.empty() && input.empty())
+        {
+            input = std::string(argv[i]);
+        }
+        else if (i == argc - 1 && output.empty() && input.empty())
+        {
+            input = std::string(argv[i]);
+        }
+        else if (i == argc - 1 && output.empty() && input.empty())
+        {
+            output = std::string(argv[i]);
+        }
+        else 
+        {
+            usage();
+            exit(1);
+        }
+    }
+    
+    std::cout << "input: " << input<<  " output: " <<output<<std::endl;
+
+    std::istream* istrm = OpenInput(input);
+    LASReader* reader = new LASReader(*istrm);
+    reader->Index(input);
+    
+    LASHeader header = reader->GetHeader();
+    std::cout << "number of points: " << header.GetPointRecordsCount() << std::endl;
+    
+    for (int i=0; i< 23; i++) {
+        bool read = reader->ReadPointAt(i);
+        LASPoint p = reader->GetPoint();
+        std::cout.precision(2);
+        std::cout.setf(std::ios_base::fixed);
+        // std::cout << "x: " << p.GetX() << " y: " << p.GetY() << std::endl;
+    }
+    
+    LASIndex* idx = reader->GetIndex();
+    
+    std::vector<liblas::uint32_t>* ids = idx->intersects(289815.12,4320979.06, 289818.01,4320982.59);
+    
+    std::cout << "Vec length" << ids->size() << std::endl;
+}

Modified: trunk/include/liblas/lasindex.hpp
==============================================================================
--- trunk/include/liblas/lasindex.hpp	(original)
+++ trunk/include/liblas/lasindex.hpp	Mon Apr 20 13:14:30 2009
@@ -42,10 +42,20 @@
 #ifndef LIBLAS_LASINDEX_HPP_INCLUDED
 #define LIBLAS_LASINDEX_HPP_INCLUDED
 
+#include <liblas/lasvariablerecord.hpp>
+#include <liblas/laspoint.hpp>
+
+#ifdef HAVE_SPATIALINDEX
+#include <spatialindex/SpatialIndex.h>
+
+#endif
+
 
 //std
 #include <string>
 #include <vector>
+#include <stack>
+#include <sys/stat.h>
 
 namespace liblas {
 
@@ -56,7 +66,7 @@
 
     
     LASIndex();
-
+    LASIndex(std::string& filename);
     /// Copy constructor.
     LASIndex(LASIndex const& other);
 
@@ -64,12 +74,113 @@
     LASIndex& operator=(LASIndex const& rhs);
     
     /// Comparison operator.
-    bool operator==(const LASIndex& other) const;    
+    bool operator==(const LASIndex& other) const;
+
+    SpatialIndex::ISpatialIndex& index() {return *m_rtree;}
+    
+    void insert(LASPoint& p, int64_t id);
+    std::vector<uint32_t>* intersects(double minx, double miny, double maxx, double maxy);
 private:
+
+    SpatialIndex::IStorageManager* m_storage;
+    SpatialIndex::StorageManager::IBuffer* m_buffer;
+    SpatialIndex::ISpatialIndex* m_rtree;
+    std::string m_indexname;
+    
+    void Init();
     
 
 };
 
+class LASVisitor : public SpatialIndex::IVisitor
+{
+public:
+    // size_t m_indexIO;
+    // size_t m_leafIO;
+	
+    std::vector<uint32_t>* m_vector;
+	
+
+public:
+    LASVisitor(std::vector<uint32_t>* vect){m_vector = vect;}
+
+	void visitNode(const SpatialIndex::INode& n)
+	{
+        //         std::cout << "visitNode" << std::endl;
+        // if (n.isLeaf()) m_leafIO++;
+        // else m_indexIO++;
+	}
+
+	void visitData(const SpatialIndex::IData& d)
+	{
+		SpatialIndex::IShape* pS;
+		d.getShape(&pS);
+			// do something.
+		delete pS;
+
+		// data should be an array of characters representing a Region as a string.
+		uint8_t* pData = 0;
+		size_t cLen = 0;
+		d.getData(cLen, &pData);
+		// do something.
+		//string s = reinterpret_cast<char*>(pData);
+		//cout << s << endl;
+		delete[] pData;
+
+        // std::cout << d.getIdentifier() << std::endl;
+        m_vector->push_back(d.getIdentifier());
+			// the ID of this data entry is an answer to the query. I will just print it to stdout.
+	}
+
+	void visitData(std::vector<const SpatialIndex::IData*>& v)
+	{
+		std::cout << v[0]->getIdentifier() << " " << v[1]->getIdentifier() << std::endl;
+	}
+};
+
 } // namespace liblas
 
+namespace SpatialIndex
+{
+
+
+	namespace StorageManager
+	{
+		extern IStorageManager* returnLASStorageManager(Tools::PropertySet& in);
+		extern IStorageManager* createNewLASStorageManager();
+		
+		class LASStorageManager : public SpatialIndex::IStorageManager
+		{
+		public:
+			LASStorageManager(Tools::PropertySet&);
+
+			virtual ~LASStorageManager();
+
+			virtual void loadByteArray(const id_type id, size_t& len, uint8_t** data);
+			virtual void storeByteArray(id_type& id, const size_t len, const uint8_t* const data);
+			virtual void deleteByteArray(const id_type id);
+
+		private:
+			class Entry
+			{
+			public:
+				byte* m_pData;
+				size_t m_length;
+
+				Entry(size_t l, const uint8_t* const d) : m_pData(0), m_length(l)
+				{
+					m_pData = new uint8_t[m_length];
+					memcpy(m_pData, d, m_length);
+				}
+
+				~Entry() { delete[] m_pData; }
+			}; // Entry
+
+			std::vector<Entry*> m_buffer;
+			std::stack<id_type> m_emptyPages;
+		}; // MemoryStorageManager
+	}
+}
+
+
 #endif // LIBLAS_LASINDEX_HPP_INCLUDED

Modified: trunk/include/liblas/lasreader.hpp
==============================================================================
--- trunk/include/liblas/lasreader.hpp	(original)
+++ trunk/include/liblas/lasreader.hpp	Mon Apr 20 13:14:30 2009
@@ -47,6 +47,7 @@
 #include <liblas/laspoint.hpp>
 #include <liblas/lasvariablerecord.hpp>
 #include <liblas/lasspatialreference.hpp>
+#include <liblas/lasindex.hpp>
 #include <liblas/detail/fwd.hpp>
 // std
 #include <iosfwd>
@@ -83,6 +84,11 @@
 
     /// The operator is not const because it updates file stream position.
     LASPoint const& operator[](std::size_t n);
+    
+    void Index(std::string& filename);
+    void Index();
+
+    LASIndex* GetIndex();
 
 private:
 
@@ -96,6 +102,9 @@
     LASHeader m_header;
     LASPoint m_point;
     std::vector<LASVariableRecord> m_vlrs;
+    
+    LASIndex* m_index;
+    bool m_doindex;
 };
 
 } // namespace liblas

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Mon Apr 20 13:14:30 2009
@@ -10,7 +10,7 @@
 endif
 
 if SPATIALINDEX_IS_CONFIG
-SPATIALINDEX_CPPFLAGS = @SPATIALINDEX_INC@ -DHAVE_SPATIALINDEX=1
+SPATIALINDEX_CPPFLAGS = @SPATIALINDEX_INC@/spatialindex @SPATIALINDEX_INC@ -DHAVE_SPATIALINDEX=1
 endif
 
 AM_CPPFLAGS = $(GEOTIFF_CPPFLAGS) $(GDAL_CPPFLAGS) $(SPATIALINDEX_CPPFLAGS) -I../include -I../include/detail

Modified: trunk/src/lasindex.cpp
==============================================================================
--- trunk/src/lasindex.cpp	(original)
+++ trunk/src/lasindex.cpp	Mon Apr 20 13:14:30 2009
@@ -57,17 +57,65 @@
 namespace liblas
 {
 
+
 LASIndex::LASIndex()
 {
+    m_storage = SpatialIndex::StorageManager::createNewLASStorageManager();
+    Init();
+    // m_storage = SpatialIndex::StorageManager::createNewMemoryStorageManager();
+}
+
+void LASIndex::Init()
+{    
+    uint16_t capacity = 10;
+    bool writeThrough = false;
+    m_buffer = SpatialIndex::StorageManager::createNewRandomEvictionsBuffer(*m_storage, capacity, writeThrough);
+
+    // R-Tree parameters
+    double fillFactor = 0.7;
+    uint32_t indexCapacity = 10;
+    uint32_t leafCapacity = 10;
+    uint32_t dimension = 2;
+    SpatialIndex::RTree::RTreeVariant variant = SpatialIndex::RTree::RV_RSTAR;
+
+    // create R-tree
+    SpatialIndex::id_type indexId=1;
+    m_rtree = SpatialIndex::RTree::createNewRTree(*m_buffer, fillFactor, indexCapacity,
+                                   leafCapacity, dimension, variant, indexId); 
+
+
 }
 
+LASIndex::LASIndex(std::string& filename) 
+{
+    struct stat stats;
+    std::ostringstream os;
+    os << filename << ".dat";
+    std::cout << "index name: " << os.str() << std::endl;
+
+    std::string indexname = os.str();
+    int ret = stat(indexname.c_str(),&stats);
+    if (!ret) {
+        std::cout << "loading existing index " << indexname << std::endl;
+        m_storage = SpatialIndex::StorageManager::loadDiskStorageManager(filename);
+    }
+    else
+    {
+        std::cout << "Creating new index ... " << std::endl;
+        m_storage = SpatialIndex::StorageManager::createNewDiskStorageManager(filename, 24);
+	}
+
+    Init();
+}
 LASIndex::LASIndex(LASIndex const& other) 
 {
+    std::cout << "Index copy called" << std::endl;
 
 }
 
 LASIndex& LASIndex::operator=(LASIndex const& rhs)
 {
+    std::cout << "Index assignment called" << std::endl;
     if (&rhs != this)
     {
     }
@@ -81,7 +129,141 @@
     return true;
 }
 
+void LASIndex::insert(LASPoint& p, int64_t id) 
+{
+    double min[2];
+    double max[2];
+    
+    min[0] = p.GetX(); min[1] = p.GetY();
+    max[0] = p.GetX(); max[1] = p.GetY();
+    index().insertData(0, 0, SpatialIndex::Region(min, max, 2), id);
+}
+
+std::vector<uint32_t>* LASIndex::intersects(double minx, double miny, double maxx, double maxy)
+{
+    double min[2];
+    double max[2];
+    
+    min[0] = minx; min[1] = miny;
+    max[0] = maxx; max[1] = maxy;
+    
+    std::cout.setf(std::ios_base::fixed);
+    
+    std::cout << "minx: " << min[0] << " miny: "<<min[1] << " maxx: " <<max[0] << " maxy: " << max[1] << std::endl;
+    if (min[0] > max[0] || min[1] > max[1]) {std::cout << "epic fail!" << std::endl;};
+    std::vector<uint32_t>* vect = new std::vector<uint32_t>;
+    LASVisitor* visitor = new LASVisitor(vect);
+    
+    const SpatialIndex::Region *region = new SpatialIndex::Region(min, max, 2);
+    std::cout << *region << std::endl;
+    index().intersectsWithQuery(*region, *visitor);
+    
+    return vect;
+    
+}
 
 
 } // namespace liblas
 
+
+#include <stdexcept>
+
+
+using namespace SpatialIndex;
+using namespace SpatialIndex::StorageManager;
+
+SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnLASStorageManager(Tools::PropertySet& ps)
+{
+	IStorageManager* sm = new LASStorageManager(ps);
+	return sm;
+}
+
+SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewLASStorageManager()
+{
+	Tools::PropertySet ps;
+	return returnLASStorageManager(ps);
+}
+
+LASStorageManager::LASStorageManager(Tools::PropertySet& ps)
+{
+}
+
+LASStorageManager::~LASStorageManager()
+{
+	for (std::vector<Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); it++) delete *it;
+}
+
+void LASStorageManager::loadByteArray(const id_type id, size_t& len, uint8_t** data)
+{
+	Entry* e;
+	try
+	{
+		e = m_buffer.at(id);
+		if (e == 0) throw Tools::InvalidPageException(id);
+	}
+	catch (std::out_of_range)
+	{
+		throw Tools::InvalidPageException(id);
+	}
+
+	len = e->m_length;
+	*data = new uint8_t[len];
+
+	memcpy(*data, e->m_pData, len);
+}
+
+void LASStorageManager::storeByteArray(id_type& id, const size_t len, const uint8_t* const data)
+{
+	if (id == NewPage)
+	{
+		Entry* e = new Entry(len, data);
+
+		if (m_emptyPages.empty())
+		{
+			m_buffer.push_back(e);
+			id = m_buffer.size() - 1;
+		}
+		else
+		{
+			id = m_emptyPages.top(); m_emptyPages.pop();
+			m_buffer[id] = e;
+		}
+	}
+	else
+	{
+		Entry* e_old;
+		try
+		{
+			e_old = m_buffer.at(id);
+			if (e_old == 0) throw Tools::InvalidPageException(id);
+		}
+		catch (std::out_of_range)
+		{
+			throw Tools::InvalidPageException(id);
+		}
+
+		Entry* e = new Entry(len, data);
+
+		delete e_old;
+		m_buffer[id] = e;
+	}
+}
+
+void LASStorageManager::deleteByteArray(const id_type id)
+{
+	Entry* e;
+	try
+	{
+		e = m_buffer.at(id);
+		if (e == 0) throw Tools::InvalidPageException(id);
+	}
+	catch (std::out_of_range)
+	{
+		throw Tools::InvalidPageException(id);
+	}
+
+	m_buffer[id] = 0;
+	m_emptyPages.push(id);
+
+	delete e;
+}
\ No newline at end of file

Modified: trunk/src/lasreader.cpp
==============================================================================
--- trunk/src/lasreader.cpp	(original)
+++ trunk/src/lasreader.cpp	Mon Apr 20 13:14:30 2009
@@ -50,6 +50,7 @@
 #include <cassert>
 #include <iostream>
 
+
 namespace liblas
 {
 
@@ -57,6 +58,7 @@
     m_pimpl(detail::ReaderFactory::Create(ifs))
 {
     //MakePIMPL(ifs);
+    m_doindex = false;
     Init();
 }
 
@@ -90,6 +92,7 @@
 bool LASReader::ReadPointAt(std::size_t n)
 {
     bool ret = m_pimpl->ReadPointAt(n, m_point, m_header);
+    if (m_doindex) m_index->insert(m_point, n);
     return ret;
 }
 
@@ -121,6 +124,7 @@
 
     m_pimpl->ReadGeoreference(m_header);
     m_pimpl->Reset(m_header);
+
 }
 
 std::istream& LASReader::GetStream() const
@@ -144,6 +148,23 @@
     return true;
 }
 
+void LASReader::Index()
+{
+    m_doindex = true;
+    m_index = new LASIndex();
+}
+
+void LASReader::Index(std::string& filename)
+{
+    m_doindex = true;
+    m_index = new LASIndex(filename);
+
+}
+
+LASIndex* LASReader::GetIndex()
+{
+    return m_index;
+}
 
 } // namespace liblas
 


More information about the Liblas-commits mailing list