getPrecisionForBBox is a function imitating PostGIS's ability to go from a world bounding box and truncating a GeoHash to fit the given bounding box. The algorithm halves the world bounding box until it intersects with the feature bounding box to get a precision that will encompass the entire boundi
(bbox *geopb.BoundingBox)
| 237 | // feature bounding box to get a precision that will encompass the entire |
| 238 | // bounding box. |
| 239 | func getPrecisionForBBox(bbox *geopb.BoundingBox) int { |
| 240 | bitPrecision := 0 |
| 241 | |
| 242 | // This is a point, for points we use the full bitPrecision. |
| 243 | if bbox.LoX == bbox.HiX && bbox.LoY == bbox.HiY { |
| 244 | return GeoHashMaxPrecision |
| 245 | } |
| 246 | |
| 247 | // Starts from a world bounding box: |
| 248 | lonMin := -180.0 |
| 249 | lonMax := 180.0 |
| 250 | latMin := -90.0 |
| 251 | latMax := 90.0 |
| 252 | |
| 253 | // Each iteration shrinks the world bounding box by half in the dimension that |
| 254 | // does not fit, making adjustments each iteration until it intersects with |
| 255 | // the object bbox. |
| 256 | for { |
| 257 | lonWidth := lonMax - lonMin |
| 258 | latWidth := latMax - latMin |
| 259 | latMaxDelta, lonMaxDelta, latMinDelta, lonMinDelta := 0.0, 0.0, 0.0, 0.0 |
| 260 | |
| 261 | // Look at whether the longitudes of the bbox are to the left or |
| 262 | // the right of the world bbox longitudes, shrinks it and makes adjustments |
| 263 | // for the next iteration. |
| 264 | if bbox.LoX > lonMin+lonWidth/2.0 { |
| 265 | lonMinDelta = lonWidth / 2.0 |
| 266 | } else if bbox.HiX < lonMax-lonWidth/2.0 { |
| 267 | lonMaxDelta = lonWidth / -2.0 |
| 268 | } |
| 269 | // Look at whether the latitudes of the bbox are to the left or |
| 270 | // the right of the world bbox latitudes, shrinks it and makes adjustments |
| 271 | // for the next iteration. |
| 272 | if bbox.LoY > latMin+latWidth/2.0 { |
| 273 | latMinDelta = latWidth / 2.0 |
| 274 | } else if bbox.HiY < latMax-latWidth/2.0 { |
| 275 | latMaxDelta = latWidth / -2.0 |
| 276 | } |
| 277 | |
| 278 | // Every change we make that splits the box up adds precision. |
| 279 | // If we detect no change, we've intersected a box and so must exit. |
| 280 | precisionDelta := 0 |
| 281 | if lonMinDelta != 0.0 || lonMaxDelta != 0.0 { |
| 282 | lonMin += lonMinDelta |
| 283 | lonMax += lonMaxDelta |
| 284 | precisionDelta++ |
| 285 | } else { |
| 286 | break |
| 287 | } |
| 288 | if latMinDelta != 0.0 || latMaxDelta != 0.0 { |
| 289 | latMin += latMinDelta |
| 290 | latMax += latMaxDelta |
| 291 | precisionDelta++ |
| 292 | } else { |
| 293 | break |
| 294 | } |
| 295 | bitPrecision += precisionDelta |
| 296 | } |
no outgoing calls
no test coverage detected
searching dependent graphs…