GridPointDataList * SinglePointReader::readNearest_(const GEOSGeom location, double exactX, double exactY, FileId dataId) const { // Check if the position we are about to return is inside the grid GridPointData data; int x = math::round(exactX); int y = math::round(exactY); if ( reader_.readPoint(data, x, y, dataId) ) { GridPointDataList * list = GridPointDataListNew(1); memcpy(list->data, & data, sizeof(GridPointData)); return list; } return GridPointDataListNew(0); }
GridPointDataList * PolygonReader::readPolygon( const std::vector<GridPointData> & points, FileId dataId ) const { size_t noOfPointsToReturn = 0; for (std::vector<GridPointData>::const_iterator it = points.begin(); it != points.end(); ++it) if (not reader_.indexRefersToPointOutsideFile(it->x, it->y)) ++noOfPointsToReturn; const unsigned MAX_RETURN = 100000; if (noOfPointsToReturn > MAX_RETURN) { std::ostringstream errorMsg; errorMsg << "Too many rows to return! A single field will return " << noOfPointsToReturn << " rows, but maximum is " << MAX_RETURN; throw std::runtime_error(errorMsg.str()); } GridPointDataList * ret = GridPointDataListNew(noOfPointsToReturn); unsigned pos = 0; for (std::vector<GridPointData>::const_iterator it = points.begin(); it != points.end() and pos < noOfPointsToReturn; ++it) if (reader_.readPoint(ret->data[pos], it->x, it->y, dataId)) ++pos; return ret; }
GridPointDataList * SinglePointReader::readSurround_(const GEOSGeom location, double exactX, double exactY, int interpolationParam, FileId dataId) const { // In case we ask for a position which is exactly on a grid line, we cheat // to be able to return four points, by adding 0.5 to the value if ( exactX == int(exactX) ) exactX += 0.5; if ( exactY == int(exactY) ) exactY += 0.5; int sizeRet = (interpolationParam * 2) * ( interpolationParam * 2); GridPointData out[sizeRet]; int startX = std::floor(exactX) - (interpolationParam - 1); int endX = std::ceil(exactX) + (interpolationParam - 1); int startY = std::floor(exactY) - (interpolationParam - 1); int endY = std::ceil(exactY) + (interpolationParam - 1); int count = 0; for ( int y = startY; y<=endY; y++ ) { for ( int x = startX; x<= endX; x++ ) { if ( reader_.readPoint(out[count], x, y, dataId) ) ++ count; } } GridPointDataList * list = GridPointDataListNew(count); memcpy(list->data, out, sizeof(GridPointData) * count); return list; }
GridPointDataList * SinglePointReader::readExact_(const GEOSGeom location, double exactX, double exactY, FileId dataId) const { if ( math::distanceToNearestInteger(exactX) > 0.001 or math::distanceToNearestInteger(exactY) > 0.001 ) return GridPointDataListNew(0); else return readNearest_(location, exactX, exactY, dataId); }
struct GridPointDataListIterator * readPoints( const struct PlaceSpecification * ps, GEOSGeom location, enum InterpolationType interpolation, int interpolationParam, FileId dataId) { const BaseDataReader & dataReader = BaseDataReader::getInstance(* ps); GridPointDataListIterator * ret = NULL; try { if ( ! location ) { //AllPointsReader reader(dataReader); //struct GridPointDataList * list = reader.read(dataId); // On NULL geometries we won't return anything struct GridPointDataList * list = GridPointDataListNew(0); ret = GridPointDataListIteratorNew(list); } else { int geometryType = GEOSGeomTypeId(location); if (geometryType == GEOS_POINT) { SinglePointReader reader(dataReader); GridPointDataList * list = reader.read(location, interpolation, interpolationParam, dataId); ret = GridPointDataListIteratorNew(list); } else if ((geometryType == GEOS_POLYGON)|| (geometryType == GEOS_MULTIPOLYGON)) { PolygonReader reader(dataReader); GridPointDataList * list = reader.read(location, interpolation, dataId); ret = GridPointDataListIteratorNew(list); } else throw std::runtime_error("This geometry type is not supported"); } } catch (std::exception & e) { if ( ret ) GridPointDataListDelete(ret->list, false); ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg(e.what()))); } catch (...) { // This should never happen, but just in case... if ( ret ) GridPointDataListDelete(ret->list, false); ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), "Unknown error when fetching point data. Please tell someone about this")); } return ret; }
GridPointDataList * PolygonReader::read( const GEOSGeom location, InterpolationType interpolation, FileId dataId ) { std::vector <GridPointData> points; gridPointsInPolygon( points, location ); GridPointDataList * list = 0; if ( points.size() > 0 ) list = readPolygon( points, dataId ); else { list = GridPointDataListNew(0); } return list; }
GridPointDataList * SinglePointReader::readBilinear_(const GEOSGeom location, double exactX, double exactY, FileId dataId) const { GridPointDataList * surroundingPoints = readSurround_(location, exactX, exactY, 1, dataId); if ( surroundingPoints->count < 4 ) { GridPointDataListDelete(surroundingPoints, false); return GridPointDataListNew(0); } GridPointDataList * list = GridPointDataListNew(1); GridPointData & data = * list->data; data.x = exactX; data.y = exactY; data.value = interpolate::bilinear(surroundingPoints, exactX, exactY); data.location = GEOSGeom_clone(location); // Delete intermediate data, but don't touch te stored geometry objects, // since they are in the cache. GridPointDataListDelete(surroundingPoints, false); return list; }