|
@@ -0,0 +1,190 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <cstdlib>
|
|
|
+#include <random>
|
|
|
+#include <chrono>
|
|
|
+#include <vector>
|
|
|
+#include <spatialindex/capi/sidx_api.h>
|
|
|
+#include <spatialindex/capi/sidx_impl.h>
|
|
|
+#include <spatialindex/capi/sidx_config.h>
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+using namespace SpatialIndex;
|
|
|
+
|
|
|
+struct MyPoint{
|
|
|
+ double x;
|
|
|
+ double y;
|
|
|
+ double z;
|
|
|
+ void init(double newX, double newY, double newZ) {
|
|
|
+ x = newX;
|
|
|
+ y = newY;
|
|
|
+ z = newZ;
|
|
|
+ }
|
|
|
+ double distance(){
|
|
|
+ return x * x + y * y + z * z ;
|
|
|
+ }
|
|
|
+};
|
|
|
+const long long pointNum = 1000000; //节点数;
|
|
|
+const int knn = 100; //k近邻;
|
|
|
+long long queryNum = 1;
|
|
|
+
|
|
|
+vector<MyPoint> pointVector;
|
|
|
+
|
|
|
+double* generateRandomPoint() {
|
|
|
+ std::random_device rd;
|
|
|
+ std::mt19937_64 gen(rd());
|
|
|
+ //范围
|
|
|
+ std::uniform_real_distribution<double> dis(0, 10);
|
|
|
+
|
|
|
+ double* coords = new double[3];
|
|
|
+ coords[0] = dis(gen);
|
|
|
+ coords[1] = dis(gen);
|
|
|
+ coords[2] = dis(gen);
|
|
|
+ //可注释
|
|
|
+ MyPoint myPoint ;
|
|
|
+ myPoint.init(coords[0], coords[1], coords[2]);
|
|
|
+ pointVector.push_back(myPoint);
|
|
|
+ //Print
|
|
|
+ //for(int i = 0; i < 3; i++) cout<<coords[i]<<" "; printf("\n");
|
|
|
+ return coords;
|
|
|
+}
|
|
|
+
|
|
|
+Index* createIndex()
|
|
|
+{
|
|
|
+ // create a property set with default values.
|
|
|
+ // see utility.cc for all defaults http://libspatialindex.github.io/doxygen/Utility_8cc_source.html#l00031
|
|
|
+ Tools::PropertySet* ps = GetDefaults();
|
|
|
+ Tools::Variant var;
|
|
|
+
|
|
|
+ // set index type to R*-Tree
|
|
|
+ var.m_varType = Tools::VT_ULONG;
|
|
|
+ var.m_val.ulVal = RT_RTree;
|
|
|
+ ps->setProperty("IndexType", var);
|
|
|
+
|
|
|
+ // Set index to store in memory (default is disk)
|
|
|
+ var.m_varType = Tools::VT_ULONG;
|
|
|
+ var.m_val.ulVal = RT_Memory;
|
|
|
+ ps->setProperty("IndexStorageType", var);
|
|
|
+
|
|
|
+ var.m_varType = Tools::VT_ULONG;
|
|
|
+ var.m_val.ulVal = 3;
|
|
|
+ ps->setProperty("Dimension", var);
|
|
|
+ // initialize index
|
|
|
+ Index* idx = new Index(*ps);
|
|
|
+ delete ps;
|
|
|
+
|
|
|
+ // check index is ok
|
|
|
+ if (!idx->index().isIndexValid())
|
|
|
+ throw "Failed to create a valid index";
|
|
|
+ else
|
|
|
+ cout << "created index" << endl;
|
|
|
+
|
|
|
+ return idx;
|
|
|
+}
|
|
|
+
|
|
|
+void addPoint(Index* idx, double x, double y, double z, int64_t id)
|
|
|
+{
|
|
|
+ // create array with x, y, z coordinates
|
|
|
+ //double coords[] = {x, y, z};
|
|
|
+ double* coords = generateRandomPoint();
|
|
|
+ // shapes can also have an object associated with them but we'll leave that for the moment.
|
|
|
+ uint8_t* pData = 0;
|
|
|
+ uint32_t nDataLength = 0;
|
|
|
+
|
|
|
+ // create shape - three-dimensional
|
|
|
+ SpatialIndex::IShape* shape = 0;
|
|
|
+ shape = new SpatialIndex::Point(coords, 3);
|
|
|
+
|
|
|
+ // insert into the index along with an object and an ID
|
|
|
+ idx->index().insertData(nDataLength, pData, *shape, id);
|
|
|
+ //Print
|
|
|
+ //cout << "Point " << id << " inserted into the index.";
|
|
|
+
|
|
|
+ delete shape;
|
|
|
+ delete[] coords;
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<SpatialIndex::IData*>* getNearest(Index* idx, double x, double y, double z, long long k)
|
|
|
+{
|
|
|
+ double coords[] = {x, y, z};
|
|
|
+
|
|
|
+ // get a visitor object and a point from which to search
|
|
|
+ ObjVisitor* visitor = new ObjVisitor;
|
|
|
+ // make the point from x, y, z coordinates
|
|
|
+ SpatialIndex::Point* r = new SpatialIndex::Point(coords, 3);
|
|
|
+
|
|
|
+ // get nearest maxResults shapes from the index
|
|
|
+ idx->index().nearestNeighborQuery(k, *r, *visitor);
|
|
|
+
|
|
|
+ // get the count of results
|
|
|
+ int64_t nResultCount;
|
|
|
+ nResultCount = visitor->GetResultCount();
|
|
|
+
|
|
|
+ // get the actual results
|
|
|
+ std::vector<SpatialIndex::IData*>& results = visitor->GetResults();
|
|
|
+ // an empty vector that we will copy the results to
|
|
|
+ vector<SpatialIndex::IData*>* resultsCopy = new vector<SpatialIndex::IData*>();
|
|
|
+
|
|
|
+ // copy the items into the newly allocated vector array
|
|
|
+ // we need to make sure to clone the actual item instead
|
|
|
+ // of just the pointers, as the visitor will nuke them
|
|
|
+ // upon destroy
|
|
|
+ for (int64_t i = 0; i < nResultCount; ++i)
|
|
|
+ {
|
|
|
+ resultsCopy->push_back(dynamic_cast<SpatialIndex::IData*>(results[i]->clone()));
|
|
|
+ }
|
|
|
+
|
|
|
+ delete r;
|
|
|
+ delete visitor;
|
|
|
+ //Print
|
|
|
+ //cout << "found " << nResultCount << " results." << endl;
|
|
|
+
|
|
|
+ return resultsCopy;
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char* argv[])
|
|
|
+{
|
|
|
+ cout<<"knn = "<< knn<<endl;
|
|
|
+ try {
|
|
|
+ // initialize the Index pointer
|
|
|
+ Index* idx = createIndex();
|
|
|
+ // add some points
|
|
|
+ auto insertStart = std::chrono::high_resolution_clock::now();
|
|
|
+ for(int i = 0; i < pointNum; i++) {
|
|
|
+ addPoint(idx, 0,0,0, i);
|
|
|
+ //Print
|
|
|
+ //cout<<"distance:"<<pointVector[i].distance()<<endl;
|
|
|
+ }
|
|
|
+ auto insertEnd = std::chrono::high_resolution_clock::now();
|
|
|
+ std::chrono::duration<double> duration = insertEnd - insertStart;
|
|
|
+ double insertTime = duration.count();
|
|
|
+ cout<< "插入数据花费的时间为"<< insertTime << "秒"<<"("<<pointNum<<")"<<endl;
|
|
|
+
|
|
|
+ // get the nearest two locations to the royal albert hall
|
|
|
+ auto queryStart = std::chrono::high_resolution_clock::now();
|
|
|
+ for(int i = 0 ; i<queryNum; i++){
|
|
|
+ double* coords = generateRandomPoint();
|
|
|
+ std::vector<SpatialIndex::IData*>* results = getNearest(idx, coords[0], coords[1], coords[2], knn);
|
|
|
+ delete[] coords;
|
|
|
+ }
|
|
|
+ auto queryEnd = std::chrono::high_resolution_clock::now();
|
|
|
+ std::chrono::duration<double> duration2 = queryEnd - queryStart;
|
|
|
+ double queryTime = duration2.count();
|
|
|
+ cout<< "查询数据花费的时间为"<< queryTime << "秒"<<"("<<queryNum<<")"<<endl;
|
|
|
+ /*//Print
|
|
|
+ if(knn <= pointNum){
|
|
|
+ for(SpatialIndex::IData* point : *results){
|
|
|
+ int id = point->getIdentifier();
|
|
|
+ cout<<"最近的n个点:"<<id;
|
|
|
+ cout<<"("<<pointVector[id].x<<", "<<pointVector[id].y<<", "<<pointVector[id].z<<")"<<endl;
|
|
|
+ }//endfor
|
|
|
+ }//endif
|
|
|
+ */
|
|
|
+ }//end try
|
|
|
+ catch (const char* ex) {
|
|
|
+ cout << "Exception: " << ex << endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+//g++ xxx.cpp -o xxx -I/home/marioh/usr/include -L/home/marioh/usr/lib -lspatialindex
|
|
|
+
|