geo相关的函数,直接跳过吧,无非就是position相关的转换,没啥好看的。对理解整体的作用不大。
- int geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,
- const GeoHashBits hash, GeoHashArea *area) {
- if (HASHISZERO(hash) || NULL == area || RANGEISZERO(lat_range) ||
- RANGEISZERO(long_range)) {
- return 0;
- }
-
- area->hash = hash;
- uint8_t step = hash.step;
- uint64_t hash_sep = deinterleave64(hash.bits); /* hash = [LAT][LONG] */
-
- double lat_scale = lat_range.max - lat_range.min;
- double long_scale = long_range.max - long_range.min;
-
- uint32_t ilato = hash_sep; /* get lat part of deinterleaved hash */
- uint32_t ilono = hash_sep >> 32; /* shift over to get long part of hash */
-
- /* divide by 2**step.
- * Then, for 0-1 coordinate, multiply times scale and add
- to the min to get the absolute coordinate. */
- area->latitude.min =
- lat_range.min + (ilato * 1.0 / (1ull << step)) * lat_scale;
- area->latitude.max =
- lat_range.min + ((ilato + 1) * 1.0 / (1ull << step)) * lat_scale;
- area->longitude.min =
- long_range.min + (ilono * 1.0 / (1ull << step)) * long_scale;
- area->longitude.max =
- long_range.min + ((ilono + 1) * 1.0 / (1ull << step)) * long_scale;
-
- return 1;
- }
-
- int geohashDecodeType(const GeoHashBits hash, GeoHashArea *area) {
- GeoHashRange r[2] = {{0}};
- geohashGetCoordRange(&r[0], &r[1]);
- return geohashDecode(r[0], r[1], hash, area);
- }
-
- int geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area) {
- return geohashDecodeType(hash, area);
- }
-
- int geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy) {
- if (!xy) return 0;
- xy[0] = (area->longitude.min + area->longitude.max) / 2;
- if (xy[0] > GEO_LONG_MAX) xy[0] = GEO_LONG_MAX;
- if (xy[0] < GEO_LONG_MIN) xy[0] = GEO_LONG_MIN;
- xy[1] = (area->latitude.min + area->latitude.max) / 2;
- if (xy[1] > GEO_LAT_MAX) xy[1] = GEO_LAT_MAX;
- if (xy[1] < GEO_LAT_MIN) xy[1] = GEO_LAT_MIN;
- return 1;
- }
-
- int geohashDecodeToLongLatType(const GeoHashBits hash, double *xy) {
- GeoHashArea area = {{0}};
- if (!xy || !geohashDecodeType(hash, &area))
- return 0;
- return geohashDecodeAreaToLongLat(&area, xy);
- }
-
- int geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy) {
- return geohashDecodeToLongLatType(hash, xy);
- }
-
- static void geohash_move_x(GeoHashBits *hash, int8_t d) {
- if (d == 0)
- return;
-
- uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;
- uint64_t y = hash->bits & 0x5555555555555555ULL;
-
- uint64_t zz = 0x5555555555555555ULL >> (64 - hash->step * 2);
-
- if (d > 0) {
- x = x + (zz + 1);
- } else {
- x = x | zz;
- x = x - (zz + 1);
- }
-
- x &= (0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2));
- hash->bits = (x | y);
- }
-
- static void geohash_move_y(GeoHashBits *hash, int8_t d) {
- if (d == 0)
- return;
-
- uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;
- uint64_t y = hash->bits & 0x5555555555555555ULL;
-
- uint64_t zz = 0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2);
- if (d > 0) {
- y = y + (zz + 1);
- } else {
- y = y | zz;
- y = y - (zz + 1);
- }
- y &= (0x5555555555555555ULL >> (64 - hash->step * 2));
- hash->bits = (x | y);
- }
-
- void geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors) {
- neighbors->east = *hash;
- neighbors->west = *hash;
- neighbors->north = *hash;
- neighbors->south = *hash;
- neighbors->south_east = *hash;
- neighbors->south_west = *hash;
- neighbors->north_east = *hash;
- neighbors->north_west = *hash;
-
- geohash_move_x(&neighbors->east, 1);
- geohash_move_y(&neighbors->east, 0);
-
- geohash_move_x(&neighbors->west, -1);
- geohash_move_y(&neighbors->west, 0);
-
- geohash_move_x(&neighbors->south, 0);
- geohash_move_y(&neighbors->south, -1);
-
- geohash_move_x(&neighbors->north, 0);
- geohash_move_y(&neighbors->north, 1);
-
- geohash_move_x(&neighbors->north_west, -1);
- geohash_move_y(&neighbors->north_west, 1);
-
- geohash_move_x(&neighbors->north_east, 1);
- geohash_move_y(&neighbors->north_east, 1);
-
- geohash_move_x(&neighbors->south_east, 1);
- geohash_move_y(&neighbors->south_east, -1);
-
- geohash_move_x(&neighbors->south_west, -1);
- geohash_move_y(&neighbors->south_west, -1);
- }