Skip to content

Instantly share code, notes, and snippets.

@edma2
Created June 16, 2012 07:33

Revisions

  1. edma2 revised this gist Jun 16, 2012. 1 changed file with 8 additions and 16 deletions.
    24 changes: 8 additions & 16 deletions geohash.c
    Original file line number Diff line number Diff line change
    @@ -7,12 +7,12 @@ static char *base32_encoder = "0123456789bcdefghjkmnpqrstuvwxyz";
    typedef struct {
    double current_guess;
    double error_margin;
    } Guess;
    double real_value;
    } BitIterator;

    /** Returns 0 if real_value is less than current_guess, 1 if greater. */
    int guess_next_bit(Guess *g, double real_value) {
    int next_bit(BitIterator *g) {
    g->error_margin = g->error_margin/2;
    if (real_value < g->current_guess) {
    if (g->real_value < g->current_guess) {
    g->current_guess -= g->error_margin;
    return 0;
    }
    @@ -22,24 +22,16 @@ int guess_next_bit(Guess *g, double real_value) {

    void geohash_encode(double lat, double lon, char buf[], int len) {
    int i;
    Guess lat_guess = {0, 90};
    Guess lon_guess = {0, 180};
    BitIterator lat_bits = {0, 90, lat};
    BitIterator lon_bits = {0, 180, lon};

    for (i = 0; i < len; i++) {
    int bits = 0;
    int j;
    for (j = 0; j < 5; j++) {
    int bit_position = i * 5 + j;
    Guess *g;
    double *d;
    if (EVEN(bit_position)) {
    g = &lon_guess;
    d = &lon;
    } else {
    g = &lat_guess;
    d = &lat;
    }
    int bit = guess_next_bit(g, *d);
    int bit = next_bit(EVEN(bit_position) ?
    &lon_bits : &lat_bits);
    bits |= bit << (4-j);
    }
    buf[i] = base32_encoder[bits];
  2. edma2 created this gist Jun 16, 2012.
    57 changes: 57 additions & 0 deletions geohash.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    #include <stdio.h>

    #define EVEN(x) ((x % 2) == 0)

    static char *base32_encoder = "0123456789bcdefghjkmnpqrstuvwxyz";

    typedef struct {
    double current_guess;
    double error_margin;
    } Guess;

    /** Returns 0 if real_value is less than current_guess, 1 if greater. */
    int guess_next_bit(Guess *g, double real_value) {
    g->error_margin = g->error_margin/2;
    if (real_value < g->current_guess) {
    g->current_guess -= g->error_margin;
    return 0;
    }
    g->current_guess += g->error_margin;
    return 1;
    }

    void geohash_encode(double lat, double lon, char buf[], int len) {
    int i;
    Guess lat_guess = {0, 90};
    Guess lon_guess = {0, 180};

    for (i = 0; i < len; i++) {
    int bits = 0;
    int j;
    for (j = 0; j < 5; j++) {
    int bit_position = i * 5 + j;
    Guess *g;
    double *d;
    if (EVEN(bit_position)) {
    g = &lon_guess;
    d = &lon;
    } else {
    g = &lat_guess;
    d = &lat;
    }
    int bit = guess_next_bit(g, *d);
    bits |= bit << (4-j);
    }
    buf[i] = base32_encoder[bits];
    }
    buf[i] = '\0';
    }

    int main(void) {
    char hash[51];

    geohash_encode(42.6, -5.6, hash, 22);
    printf("%s\n", hash);

    return 0;
    }