Пример #1
0
void TestSpatialIndexSpeed(string& wayDBFilePath)
{
	IStorageManager* diskfile = new CachedDiskStorageManager(wayDBFilePath);
	ISpatialIndex* tree = loadRTree(*diskfile, 1);

	high_resolution_clock::time_point t1 = high_resolution_clock::now();

	GetAllWaysWithKey getAllWays("highway");

	double min[3]{ 4.0, 52.0, 0.004 };
	double max[3]{ 5.0, 53.0, 500.0 };
	//double min[3]{ -180.0, -90.0, 0.0 };
	//double max[3]{ 180.0, 90.0, 500.0 };
	Region queryAABB(min, max, 3);
	tree->intersectsWithQuery(queryAABB, getAllWays);

	cout << "Num Ways returned: " << getAllWays.ways.size() << "                               " << endl;
	high_resolution_clock::time_point t2 = high_resolution_clock::now();
	duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

	cout << "Num Query took seconds: " << time_span.count() << "                               " << endl;
}
Пример #2
0
// performs spatial join on the current tile (bucket)
int join_bucket_spjoin(struct query_op &stop, struct query_temp &sttemp) {
    IStorageManager *storage = NULL;
    ISpatialIndex *spidx = NULL;
    bool selfjoin = stop.join_cardinality == 1  ? true : false;

    /* Indicates where original data is mapped to */
    int idx1 = SID_1;
    int idx2 = selfjoin ? SID_1 : SID_2;

    int pairs = 0; // number of satisfied results

    double low[2], high[2];  // Temporary value placeholders for MBB

    try {

        vector<Geometry*>  & poly_set_one = sttemp.polydata[idx1];
        vector<Geometry*>  & poly_set_two = sttemp.polydata[idx2];

        int len1 = poly_set_one.size();
        int len2 = poly_set_two.size();

#ifdef DEBUG
        cerr << "Bucket size: " << len1 << " joining with " << len2 << endl;
#endif
        cerr << "Bucket size: " << len1 << " joining with " << len2 << endl;

        if (len1 <= 0 || len2 <= 0) {
            return 0;
        }

        /* Build index on the "second data set */
        map<int, Geometry*> geom_polygons2;
        geom_polygons2.clear();

        // Make a copy of the vector to map to build index (API restriction)
        for (int j = 0; j < len2; j++) {
            geom_polygons2[j] = poly_set_two[j];
        }

        /* Handling for special nearest neighbor query */
        // build the actual spatial index for input polygons from idx2
        if (! build_index_geoms(geom_polygons2, spidx, storage)) {
#ifdef DEBUG
            cerr << "Building index on geometries from set 2 has failed" << endl;
#endif
            return -1;
        }

        for (int i = 0; i < len1; i++) {
            /* Extract minimum bounding box */
            const Geometry* geom1 = poly_set_one[i];
            const Envelope * env1 = geom1->getEnvelopeInternal();

            low[0] = env1->getMinX();
            low[1] = env1->getMinY();
            high[0] = env1->getMaxX();
            high[1] = env1->getMaxY();
            if (stop.join_predicate == ST_DWITHIN) {
                low[0] -= stop.expansion_distance;
                low[1] -= stop.expansion_distance;
                high[0] += stop.expansion_distance;
                high[1] += stop.expansion_distance;
            }

            /* Regular handling */
            Region r(low, high, 2);
            MyVisitor vis;
            vis.matches.clear();
            /* R-tree intersection check */
            spidx->intersectsWithQuery(r, vis);

            for (uint32_t j = 0; j < vis.matches.size(); j++)
            {
                /* Skip results that have been seen before (self-join case) */
                if (selfjoin && ((vis.matches[j] == i) ||  // same objects in self-join
                                 (!stop.result_pair_duplicate && vis.matches[j] <= i))) { // duplicate pairs
#ifdef DEBUG
                    cerr << "skipping (selfjoin): " << j << " " << vis.matches[j] << endl;
#endif
                    continue;
                }
                const Geometry* geom2 = poly_set_two[vis.matches[j]];
                const Envelope * env2 = geom2->getEnvelopeInternal();
                if (join_with_predicate(stop, sttemp, geom1, geom2, env1, env2,
                                        stop.join_predicate))  {
                    report_result(stop, sttemp, i, vis.matches[j]);
                    pairs++;
                }

            }
        }
    } // end of try
    catch (Tools::Exception& e) {
        //catch (...) {
        std::cerr << "******ERROR******" << std::endl;
#ifdef DEBUG
        cerr << e.what() << std::endl;
#endif
        return -1;
    } // end of catch

    cerr << "Done with tile" << endl;

    delete spidx;
    delete storage;
    return pairs ;
}
Пример #3
0
// Returns the number of satisfied pairs
int join_bucket_knn(struct query_op &stop, struct query_temp &sttemp)
{
	IStorageManager *storage = NULL;
	ISpatialIndex *spidx = NULL;
	bool selfjoin = stop.join_cardinality == 1  ? true : false;

	/* Indicates where original data is mapped to */
	int idx1 = SID_1; 
	int idx2 = selfjoin ? SID_1 : SID_2;
	
	int pairs = 0; // number of satisfied results

	double low[2], high[2];  // Temporary value placeholders for MBB
	double tmp_distance; // Temporary distance for nearest neighbor query
	double def_search_radius = -1; // Default search radius 
					//for nearest neighbor (NN) with unknown bounds
	double max_search_radius; // max_radius to search for NN

	try { 

		vector<Geometry*>  & poly_set_one = sttemp.polydata[idx1];
		vector<Geometry*>  & poly_set_two = sttemp.polydata[idx2];
		
		int len1 = poly_set_one.size();
		int len2 = poly_set_two.size();

		#ifdef DEBUG
		cerr << "Bucket size: " << len1 << " joining with " << len2 << endl;
		#endif
		cerr << "Bucket size: " << len1 << " joining with " << len2 << endl;

		if (len1 <= 0 || len2 <= 0) {
			return 0;
		}

		/* Build index on the "second data set */
		map<int, Geometry*> geom_polygons2;
		geom_polygons2.clear();

		// Make a copy of the vector to map to build index (API restriction)
		for (int j = 0; j < len2; j++) {
			geom_polygons2[j] = poly_set_two[j];
		}

		/* Handling for special nearest neighbor query */	
		
		if (stop.join_predicate == ST_NEAREST_2) {
			// Updating bucket information	
			if (len2 > 0) {
				const Envelope * envtmp = poly_set_two[0]->getEnvelopeInternal();
				sttemp.bucket_min_x = envtmp->getMinX();
				sttemp.bucket_min_y = envtmp->getMinY();
				sttemp.bucket_max_x = envtmp->getMaxX();
				sttemp.bucket_max_y = envtmp->getMaxY();
			}
			for (int j = 0; j < len1; j++) {
				update_bucket_dimension(stop, sttemp, poly_set_one[j]->getEnvelopeInternal());
			}
			if (!selfjoin) {
				for (int j = 0; j < len2; j++) {
					update_bucket_dimension(stop, sttemp, poly_set_two[j]->getEnvelopeInternal());
				}
			}
			
			max_search_radius = max(sttemp.bucket_max_x - sttemp.bucket_min_x, 
						sttemp.bucket_max_y - sttemp.bucket_min_y);
			def_search_radius = min(sqrt((sttemp.bucket_max_x - sttemp.bucket_min_x)
						* (sttemp.bucket_max_y - sttemp.bucket_min_y) 
						* stop.k_neighbors / len2), max_search_radius);
			if (def_search_radius == 0) {
				def_search_radius = DistanceOp::distance(poly_set_one[0], poly_set_two[0]);
			}
			#ifdef DEBUG
			cerr << "Bucket dimension min-max: " << sttemp.bucket_min_x << TAB 
				<< sttemp.bucket_min_y << TAB << sttemp.bucket_max_x
				<< TAB << sttemp.bucket_max_y << endl;
			cerr << "Width and height (x-y span) " 
			<< sttemp.bucket_max_x - sttemp.bucket_min_x
			<< TAB << sttemp.bucket_max_y - sttemp.bucket_min_y  << endl;
			#endif
		}

		// build the actual spatial index for input polygons from idx2
		if (! build_index_geoms(geom_polygons2, spidx, storage)) {
			#ifdef DEBUG
			cerr << "Building index on geometries from set 2 has failed" << endl;
			#endif
			return -1;
		}
		cerr << "done building indices" << endl;

		for (int i = 0; i < len1; i++) {		
			/* Extract minimum bounding box */
			const Geometry* geom1 = poly_set_one[i];
			const Envelope * env1 = geom1->getEnvelopeInternal();

			low[0] = env1->getMinX();
			low[1] = env1->getMinY();
			high[0] = env1->getMaxX();
			high[1] = env1->getMaxY();
			/* Handle the buffer expansion for R-tree in 
			the case of Dwithin and nearest neighbor predicate */
			if (stop.join_predicate == ST_NEAREST_2) {
				/* Nearest neighbor when max search radius 
					is not determined */
				stop.expansion_distance = def_search_radius;
				// Initial value
			}
			if (stop.join_predicate == ST_DWITHIN ||
				stop.join_predicate == ST_NEAREST) {
				low[0] -= stop.expansion_distance;
				low[1] -= stop.expansion_distance;
				high[0] += stop.expansion_distance;
				high[1] += stop.expansion_distance;
			}

			/* Regular handling */
			Region r(low, high, 2);
			MyVisitor vis;
			vis.matches.clear();
			/* R-tree intersection check */
			spidx->intersectsWithQuery(r, vis);

			/* Retrieve enough candidate neighbors */
			if (stop.join_predicate == ST_NEAREST_2) {
				double search_radius = def_search_radius;

				while (vis.matches.size() <= stop.k_neighbors + 1
					&& vis.matches.size() <= len2 // there can't be more neighbors than number of objects in the bucket
					&& search_radius <= sqrt(2) * max_search_radius) {
					// Increase the radius to find more neighbors
					// Stopping criteria when there are not enough neighbors in a tile
					low[0] = env1->getMinX() - search_radius;
					low[1] = env1->getMinY() - search_radius;
					high[0] = env1->getMaxX() + search_radius;
					high[1] = env1->getMaxY() + search_radius;
					
					Region r2(low, high, 2);
					
					vis.matches.clear();
					spidx->intersectsWithQuery(r2, vis);

					#ifdef DEBUG
					cerr << "Search radius:" << search_radius << " hits: " << vis.matches.size() << endl;
					#endif
					search_radius *= sqrt(2);
				}

				sttemp.nearest_distances.clear();

				/* Handle the special case of rectangular/circle expansion -sqrt(2) expansion */
				vis.matches.clear();
				low[0] = env1->getMinX() - search_radius;
				low[1] = env1->getMinY() - search_radius;
				high[0] = env1->getMaxX() + search_radius;
				high[1] = env1->getMaxY() + search_radius;
				Region r3(low, high, 2);
				spidx->intersectsWithQuery(r3, vis);
			}
			
			for (uint32_t j = 0; j < vis.matches.size(); j++) 
			{
				const Geometry* geom2 = poly_set_two[vis.matches[j]];
				const Envelope * env2 = geom2->getEnvelopeInternal();

				if (stop.join_predicate == ST_NEAREST 
					&& (!selfjoin || vis.matches[j] != i)) { // remove selfjoin candidates
					/* Handle nearest neighbor candidate */	
					tmp_distance = DistanceOp::distance(geom1, geom2);
					if (tmp_distance < stop.expansion_distance) {
						update_nn(stop, sttemp, vis.matches[j], tmp_distance);
					}
					
				}
				else if (stop.join_predicate == ST_NEAREST_2 
					&& (!selfjoin || vis.matches[j] != i)) {
					tmp_distance = DistanceOp::distance(geom1, geom2);
					update_nn(stop, sttemp, vis.matches[j], tmp_distance);
	//				cerr << "updating: " << vis.matches[j] << " " << tmp_distance << endl;
				}

			}
			/* Nearest neighbor outputting */
			for (std::list<struct query_nn_dist *>::iterator 
					it = sttemp.nearest_distances.begin(); 
					it != sttemp.nearest_distances.end(); it++) 
			{
					sttemp.distance = (*it)->distance;
					report_result(stop, sttemp, i, (*it)->object_id);	
					pairs++;
					/* Cleaning up memory */
					delete *it;
			}
			sttemp.nearest_distances.clear();
	
		}
	} // end of try
	catch (Tools::Exception& e) {
	//catch (...) {
		std::cerr << "******ERROR******" << std::endl;
		#ifdef DEBUG
		cerr << e.what() << std::endl;
		#endif
		return -1;
	} // end of catch

	cerr << "Done with tile" << endl;

	delete spidx;
	delete storage;
	return pairs ;
}