// 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 ; }
/* Perform (Refine) spatial computation between 2 geometry objects */ bool join_with_predicate( struct query_op &stop, struct query_temp &sttemp, const geos::geom::Geometry * geom1 , const geos::geom::Geometry * geom2, const geos::geom::Envelope * env1, const geos::geom::Envelope * env2, const int jp) { bool flag = false; // flag == true means the predicate is satisfied BufferOp * buffer_op1; BufferOp * buffer_op2; Geometry* geom_buffer1; Geometry* geom_buffer2; Geometry* geomUni; Geometry* geomIntersect; #ifdef DEBUG cerr << "1: (envelope) " << env1->toString() << " and actual geom: " << geom1->toString() << " 2: (envelope)" << env2->toString() << " and actual geom: " << geom2->toString() << endl; #endif switch (jp) { case ST_INTERSECTS: flag = geom1->intersects(geom2); break; case ST_TOUCHES: flag = geom1->touches(geom2); break; case ST_CROSSES: flag = geom1->crosses(geom2); break; case ST_CONTAINS: flag = env1->contains(env2) && geom1->contains(geom2); break; case ST_ADJACENT: flag = !geom1->disjoint(geom2); break; case ST_DISJOINT: flag = geom1->disjoint(geom2); break; case ST_EQUALS: flag = env1->equals(env2) && geom1->equals(geom2); break; case ST_DWITHIN: /* Special spatial handling for the point-point case */ if (geom1->getGeometryTypeId() == geos::geom::GEOS_POINT && geom2->getGeometryTypeId() == geos::geom::GEOS_POINT) { /* Replace with spherical distance computation if points are on eath */ if (stop.use_earth_distance) { flag = get_distance_earth( dynamic_cast<const geos::geom::Point*>(geom1), dynamic_cast<const geos::geom::Point*>(geom2)) <= stop.expansion_distance; } else { flag = DistanceOp::distance(geom1, geom2) <= stop.expansion_distance; } /* flag = distance( dynamic_cast<const geos::geom::Point*>(geom1), dynamic_cast<const geos::geom::Point*>(geom2) ) <= stop.expansion_distance; */ } else { // Regular handling for other object types buffer_op1 = new BufferOp(geom1); // buffer_op2 = new BufferOp(geom2); if (NULL == buffer_op1) cerr << "NULL: buffer_op1" <<endl; geom_buffer1 = buffer_op1->getResultGeometry(stop.expansion_distance); env1 = geom_buffer1->getEnvelopeInternal(); // geom_buffer2 = buffer_op2->getResultGeometry(expansion_distance); //Envelope * env_temp = geom_buffer1->getEnvelopeInternal(); if (NULL == geom_buffer1) { cerr << "NULL: geom_buffer1" << endl; } flag = join_with_predicate(stop, sttemp, geom_buffer1, geom2, env1, env2, ST_INTERSECTS); delete geom_buffer1; delete buffer_op1; } break; case ST_WITHIN: flag = geom1->within(geom2); break; case ST_OVERLAPS: flag = geom1->overlaps(geom2); break; /* case ST_NEAREST: case ST_NEAREST_2: // Execution only reaches here if this is already the nearest neighbor flag = true; break; */ default: cerr << "ERROR: unknown spatial predicate " << endl; break; } /* Spatial computation is only performed once for a result pair */ if (flag) { if (stop.needs_area_1) { sttemp.area1 = geom1->getArea(); } if (stop.needs_area_2) { sttemp.area2 = geom2->getArea(); } if (stop.needs_union) { Geometry * geomUni = geom1->Union(geom2); sttemp.union_area = geomUni->getArea(); delete geomUni; } if (stop.needs_intersect) { Geometry * geomIntersect = geom1->intersection(geom2); sttemp.intersect_area = geomIntersect->getArea(); delete geomIntersect; } /* Statistics dependent on previously computed statistics */ if (stop.needs_jaccard) { sttemp.jaccard = compute_jaccard(sttemp.union_area, sttemp.intersect_area); } if (stop.needs_dice) { sttemp.dice = compute_dice(sttemp.area1, sttemp.area2, sttemp.intersect_area); } if (stop.needs_min_distance) { if (stop.use_earth_distance && geom1->getGeometryTypeId() == geos::geom::GEOS_POINT && geom2->getGeometryTypeId() == geos::geom::GEOS_POINT) { sttemp.distance = get_distance_earth( dynamic_cast<const geos::geom::Point*>(geom1), dynamic_cast<const geos::geom::Point*>(geom2)); } else { sttemp.distance = DistanceOp::distance(geom1, geom2); } } } return flag; }
bool join_with_predicate(const Geometry * geom1 , const Geometry * geom2, const Envelope * env1, const Envelope * env2, const int jp){ bool flag = false ; // const Envelope * env1 = geom1->getEnvelopeInternal(); // const Envelope * env2 = geom2->getEnvelopeInternal(); BufferOp * buffer_op1 = NULL ; BufferOp * buffer_op2 = NULL ; Geometry* geom_buffer1 = NULL; Geometry* geom_buffer2 = NULL; Geometry* geomUni = NULL; Geometry* geomIntersect = NULL; switch (jp){ case ST_INTERSECTS: cerr << "1: " << env1->toString() << " and " << geom1->toString() << endl; cerr << "2: " << env2->toString() << " and " << geom2->toString() << endl; cerr << "touching: " << env1->intersects(env2) << endl; flag = env1->intersects(env2) && geom1->intersects(geom2); if (flag && appendstats) { area1 = geom1->getArea(); area2 = geom2->getArea(); geomUni = geom1->Union(geom2); union_area = geomUni->getArea(); geomIntersect = geom1->intersection(geom2); intersect_area = geomIntersect->getArea(); delete geomUni; delete geomIntersect; } break; case ST_TOUCHES: flag = geom1->touches(geom2); break; case ST_CROSSES: flag = geom1->crosses(geom2); break; case ST_CONTAINS: flag = env1->contains(env2) && geom1->contains(geom2); break; case ST_ADJACENT: flag = ! geom1->disjoint(geom2); break; case ST_DISJOINT: flag = geom1->disjoint(geom2); break; case ST_EQUALS: flag = env1->equals(env2) && geom1->equals(geom2); break; case ST_DWITHIN: /* Special (exact) spatial handling for point-point distance case */ if (geom1->getGeometryTypeId() == geos::geom::GEOS_POINT && geom2->getGeometryTypeId() == geos::geom::GEOS_POINT) { const geos::geom::Point* p1 = dynamic_cast<const geos::geom::Point*>(geom1); const geos::geom::Point* p2 = dynamic_cast<const geos::geom::Point*>(geom2); flag = pow(p1->getX() - p2->getX(), 2) + pow(p1->getY() - p2->getY(), 2) <= pow(stop.expansion_distance, 2); break; } buffer_op1 = new BufferOp(geom1); // buffer_op2 = new BufferOp(geom2); if (NULL == buffer_op1) cerr << "NULL: buffer_op1" <<endl; geom_buffer1 = buffer_op1->getResultGeometry(stop.expansion_distance); env1 = geom_buffer1->getEnvelopeInternal(); // geom_buffer2 = buffer_op2->getResultGeometry(expansion_distance); //Envelope * env_temp = geom_buffer1->getEnvelopeInternal(); if (NULL == geom_buffer1) cerr << "NULL: geom_buffer1" <<endl; flag = join_with_predicate(geom_buffer1,geom2, env1, env2, ST_INTERSECTS); delete geom_buffer1; break; case ST_WITHIN: flag = geom1->within(geom2); break; case ST_OVERLAPS: flag = geom1->overlaps(geom2); break; default: std::cerr << "ERROR: unknown spatial predicate " << endl; break; } return flag; }
int joinBucket() { // cerr << "---------------------------------------------------" << endl; int pairs = 0; bool selfjoin = stop.join_cardinality ==1 ? true : false ; int idx1 = SID_1 ; int idx2 = selfjoin ? SID_1 : SID_2 ; double low[2], high[2]; // for each tile (key) in the input stream try { std::vector<Geometry*> & poly_set_one = polydata[idx1]; std::vector<Geometry*> & poly_set_two = polydata[idx2]; int len1 = poly_set_one.size(); int len2 = poly_set_two.size(); if (len1 <= 0 || len2 <= 0) { return 0; } map<int,Geometry*> geom_polygons2; for (int j = 0; j < len2; j++) { geom_polygons2[j] = poly_set_two[j]; } // build spatial index for input polygons from idx2 bool ret = buildIndex(geom_polygons2); if (ret == false) { return -1; } // cerr << "len1 = " << len1 << endl; // cerr << "len2 = " << len2 << endl; for (int i = 0; i < len1; i++) { 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 */ 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; } Region r(low, high, 2); hits.clear(); MyVisitor vis; spidx->intersectsWithQuery(r, vis); //cerr << "j = " << j << " hits: " << hits.size() << endl; for (uint32_t j = 0 ; j < hits.size(); j++ ) { if (hits[j] == i && selfjoin) { continue; } const Geometry* geom2 = poly_set_two[hits[j]]; const Envelope * env2 = geom2->getEnvelopeInternal(); if (join_with_predicate(geom1, geom2, env1, env2, stop.JOIN_PREDICATE)) { ReportResult(i,hits[j]); pairs++; } } } } // end of try //catch (Tools::Exception& e) { catch (...) { std::cerr << "******ERROR******" << std::endl; //std::string s = e.what(); //std::cerr << s << std::endl; return -1; } // end of catch return pairs ; }
bool join_with_predicate(const Geometry * geom1 , const Geometry * geom2, const Envelope * env1, const Envelope * env2, const int jp){ bool flag = false ; // const Envelope * env1 = geom1->getEnvelopeInternal(); // const Envelope * env2 = geom2->getEnvelopeInternal(); BufferOp * buffer_op1 = NULL ; BufferOp * buffer_op2 = NULL ; Geometry* geom_buffer1 = NULL; Geometry* geom_buffer2 = NULL; switch (jp){ case ST_INTERSECTS: flag = env1->intersects(env2) && geom1->intersects(geom2); break; case ST_TOUCHES: flag = geom1->touches(geom2); break; case ST_CROSSES: flag = geom1->crosses(geom2); break; case ST_CONTAINS: flag = env1->contains(env2) && geom1->contains(geom2); break; case ST_ADJACENT: flag = ! geom1->disjoint(geom2); break; case ST_DISJOINT: flag = geom1->disjoint(geom2); break; case ST_EQUALS: flag = env1->equals(env2) && geom1->equals(geom2); break; case ST_DWITHIN: buffer_op1 = new BufferOp(geom1); // buffer_op2 = new BufferOp(geom2); if (NULL == buffer_op1) cerr << "NULL: buffer_op1" <<endl; geom_buffer1 = buffer_op1->getResultGeometry(stop.expansion_distance); // geom_buffer2 = buffer_op2->getResultGeometry(expansion_distance); //Envelope * env_temp = geom_buffer1->getEnvelopeInternal(); if (NULL == geom_buffer1) cerr << "NULL: geom_buffer1" <<endl; flag = join_with_predicate(geom_buffer1,geom2, env1, env2, ST_INTERSECTS); break; case ST_WITHIN: flag = geom1->within(geom2); break; case ST_OVERLAPS: flag = geom1->overlaps(geom2); break; default: std::cerr << "ERROR: unknown spatial predicate " << endl; break; } return flag; }