Source

clojure-geohash / src / geohash / core.clj

Ning Sun 1a74fc2 








Ning Sun 266a0ba 
Ning Sun 1a74fc2 

Ning Sun 266a0ba 
Ning Sun 1a74fc2 

Ning Sun 266a0ba 
Ning Sun 1a74fc2 










Ning Sun 266a0ba 
Ning Sun 1a74fc2 




Ning Sun 266a0ba 

Ning Sun 1a74fc2 










Ning Sun 266a0ba 
Ning Sun 1a74fc2 




Ning Sun 266a0ba 

Ning Sun 1a74fc2 

Ning Sun 266a0ba 
Ning Sun 1a74fc2 
Ning Sun 266a0ba 
Ning Sun 1a74fc2 
Ning Sun 266a0ba 

Ning Sun 1a74fc2 


Ning Sun 266a0ba 
Ning Sun 1a74fc2 

Ning Sun 266a0ba 

Ning Sun 1a74fc2 
Ning Sun 266a0ba 

Ning Sun 1a74fc2 


Ning Sun 266a0ba 
Ning Sun 1a74fc2 

Ning Sun 266a0ba 

Ning Sun 1a74fc2 
Ning Sun 266a0ba 
Ning Sun 1a74fc2 


Ning Sun 266a0ba 

Ning Sun 1a74fc2 



Ning Sun 266a0ba 
Ning Sun 1a74fc2 




Ning Sun 266a0ba 
(ns geohash.core)

(def base32-codes "0123456789bcdefghjkmnpqrstuvwxyz")

(defn- base32-index [ch]
  (. base32-codes indexOf (str ch)))

(defstruct geocode-data
  :maxlon :minlon :maxlat :minlat
  :islon :bits :hashcode :hashstring)

(defn- do-encode
  [lat lon prec geocode-data]
  (if (= (count (:hashstring geocode-data)) prec)
    (:hashstring geocode-data)
    (if (true? (:islon geocode-data))
      (let [
            mid (/ (+ (:maxlon geocode-data) (:minlon geocode-data)) 2)
            maxlon (if (> lon mid) (:maxlon geocode-data) mid)
            minlon (if (> lon mid) mid (:minlon geocode-data))
            hashcode (if (> lon mid) 
                       (+ (bit-shift-left (:hashcode geocode-data) 1) 1) 
                       (+ (bit-shift-left (:hashcode geocode-data) 1) 0))
            bits (inc (:bits geocode-data))
            hashstring (if (= bits 5) 
                         (str (:hashstring geocode-data) (nth base32-codes hashcode)) 
                         (:hashstring geocode-data))]
        (recur lat lon prec
          (assoc geocode-data
            :maxlon maxlon
            :minlon minlon
            :hashcode (if (= bits 5) 0 hashcode)
            :bits (if (= bits 5) 0 bits)
            :hashstring hashstring
            :islon (not (:islon geocode-data)))))
      (let [
            mid (/ (+ (:maxlat geocode-data) (:minlat geocode-data)) 2)
            maxlat (if (> lat mid) (:maxlat geocode-data) mid)
            minlat (if (> lat mid) mid (:minlat geocode-data))
            hashcode (if (> lat mid) 
                       (+ (bit-shift-left (:hashcode geocode-data) 1) 1) 
                       (+ (bit-shift-left (:hashcode geocode-data) 1) 0))
            bits (inc (:bits geocode-data))
            hashstring (if (= bits 5) 
                         (str (:hashstring geocode-data) (nth base32-codes hashcode)) 
                         (:hashstring geocode-data))]
        (recur lat lon prec
          (assoc geocode-data
            :maxlat maxlat
            :minlat minlat
            :hashcode (if (= bits 5) 0 hashcode)
            :bits (if (= bits 5) 0 bits)
            :hashstring hashstring
            :islon (not (:islon geocode-data))))))))

(defn- do-decode-hashcode
  [bits hash-code geocode-data]
  (if (< bits 0) geocode-data
    (if (true? (:islon geocode-data))
      (let [
            local-bits (dec bits)
            bit (bit-and (bit-shift-right hash-code local-bits) 1)
            mid (/ (+ (:maxlon geocode-data) (:minlon geocode-data)) 2)
            minlon (if (= bit 1) mid (:minlon geocode-data))
            maxlon (if (= bit 1) (:maxlon geocode-data) mid)]
        (recur local-bits hash-code
          (assoc geocode-data
            :minlon minlon
            :maxlon maxlon
            :islon (not (:islon geocode-data)))))
      (let [
            local-bits (dec bits)
            bit (bit-and (bit-shift-right hash-code local-bits) 1)
            mid (/ (+ (:maxlat geocode-data) (:minlat geocode-data)) 2)
            minlat (if (= bit 1) mid (:minlat geocode-data))
            maxlat (if (= bit 1) (:maxlat geocode-data) mid)]
        (recur local-bits hash-code
          (assoc geocode-data
            :minlat minlat
            :maxlat maxlat
            :islon (not (:islon geocode-data))))))))

(defn- do-decode [hash-codes geocode-data]
  (if (empty? hash-codes)
    (do (println geocode-data)
      geocode-data)
    (let [local-geocode-data (do-decode-hashcode 5 (first hash-codes) geocode-data)]
      (recur (rest hash-codes) local-geocode-data))))

(defn decode [hashstring]
  (let [
        hashcodes (map base32-index hashstring)
        bbox (do-decode hashcodes (struct geocode-data 180.0 -180.0 90.0 -90.0 true nil nil nil))
        lat (/ (+ (:maxlat bbox) (:minlat bbox)) 2)
        lon (/ (+ (:maxlon bbox) (:minlon bbox)) 2)]
    {:lat lat :lon lon}))

(defn encode [lat lon prec]
  (do-encode lat lon prec 
    (struct geocode-data 180 -180 90 -90 true 0 0 "")))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.