// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). #pragma once #include <string> #include <algorithm> #include "rocksdb/utilities/spatial_db.h" namespace rocksdb { namespace spatial { // indexing idea from http://msdn.microsoft.com/en-us/library/bb259689.aspx inline uint64_t GetTileFromCoord(double x, double start, double end, uint32_t tile_bits) { if (x < start) { return 0; } uint64_t tiles = 1ull << tile_bits; uint64_t r = static_cast<uint64_t>(((x - start) / (end - start)) * tiles); return std::min(r, tiles - 1); } inline uint64_t GetQuadKeyFromTile(uint64_t tile_x, uint64_t tile_y, uint32_t tile_bits) { uint64_t quad_key = 0; for (uint32_t i = 0; i < tile_bits; ++i) { uint64_t mask = (1ull << i); quad_key |= (tile_x & mask) << i; quad_key |= (tile_y & mask) << (i + 1); } return quad_key; } inline BoundingBox<uint64_t> GetTileBoundingBox( const SpatialIndexOptions& spatial_index, BoundingBox<double> bbox) { return BoundingBox<uint64_t>( GetTileFromCoord(bbox.min_x, spatial_index.bbox.min_x, spatial_index.bbox.max_x, spatial_index.tile_bits), GetTileFromCoord(bbox.min_y, spatial_index.bbox.min_y, spatial_index.bbox.max_y, spatial_index.tile_bits), GetTileFromCoord(bbox.max_x, spatial_index.bbox.min_x, spatial_index.bbox.max_x, spatial_index.tile_bits), GetTileFromCoord(bbox.max_y, spatial_index.bbox.min_y, spatial_index.bbox.max_y, spatial_index.tile_bits)); } // big endian can be compared using memcpy inline void PutFixed64BigEndian(std::string* dst, uint64_t value) { char buf[sizeof(value)]; buf[0] = (value >> 56) & 0xff; buf[1] = (value >> 48) & 0xff; buf[2] = (value >> 40) & 0xff; buf[3] = (value >> 32) & 0xff; buf[4] = (value >> 24) & 0xff; buf[5] = (value >> 16) & 0xff; buf[6] = (value >> 8) & 0xff; buf[7] = value & 0xff; dst->append(buf, sizeof(buf)); } // big endian can be compared using memcpy inline bool GetFixed64BigEndian(const Slice& input, uint64_t* value) { if (input.size() < sizeof(uint64_t)) { return false; } auto ptr = input.data(); *value = (static_cast<uint64_t>(static_cast<unsigned char>(ptr[0])) << 56) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[1])) << 48) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[2])) << 40) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[3])) << 32) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[4])) << 24) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[5])) << 16) | (static_cast<uint64_t>(static_cast<unsigned char>(ptr[6])) << 8) | static_cast<uint64_t>(static_cast<unsigned char>(ptr[7])); return true; } inline void PutDouble(std::string* dst, double d) { dst->append(reinterpret_cast<char*>(&d), sizeof(double)); } inline bool GetDouble(Slice* input, double* d) { if (input->size() < sizeof(double)) { return false; } memcpy(d, input->data(), sizeof(double)); input->remove_prefix(sizeof(double)); return true; } } // namespace spatial } // namespace rocksdb