Ning Sun avatar Ning Sun committed 1a74fc2

initial commit

Comments (0)

Files changed (5)

+syntax:glob
+pom.xml
+*.jar
+/lib/
+/classes/
+.lein-deps-sum
+# geohash
+
+FIXME: write description
+
+## Usage
+
+FIXME: write
+
+## License
+
+Copyright (C) 2011 FIXME
+
+Distributed under the Eclipse Public License, the same as Clojure.
+(defproject org.clojars.sunng/geohash "1.0.0-SNAPSHOT"
+  :description "Geohash in clojure"
+  :dependencies [[org.clojure/clojure "1.2.1"]])

src/geohash/core.clj

+(ns geohash.core)
+
+(def base32-codes "0123456789bcdefghjkmnpqrstuvwxyz")
+
+(defn- base32-index [ch]
+  (. base32-codes indexOf (str ch)))
+
+(defstruct geocode-data
+  :maxlon :minlon :maxlat :minlat
+  :bits :hashcode :hashstring)
+
+(defn- do-encode
+  [lat lon prec islon geocode-data]
+  (if (= (count (:hashstring geocode-data)) prec)
+    (:hashstring geocode-data)
+    (if (true? islon)
+      (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 (not islon)
+          (assoc geocode-data
+            :maxlon maxlon
+            :minlon minlon
+            :hashcode (if (= bits 5) 0 hashcode)
+            :bits (if (= bits 5) 0 bits)
+            :hashstring hashstring)))
+      (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 (not islon)
+          (assoc geocode-data
+            :maxlat maxlat
+            :minlat minlat
+            :hashcode (if (= bits 5) 0 hashcode)
+            :bits (if (= bits 5) 0 bits)
+            :hashstring hashstring))))))
+
+(defn- do-decode-hashcode
+  [bits hash-code islon geocode-data]
+  (println geocode-data)
+  (if (< bits 0) geocode-data
+    (if (true? islon)
+      (let [
+            bits (dec bits)
+            bit (bit-and (bit-shift-right hash-code 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 bits hash-code (not islon) 
+          (assoc geocode-data
+            :minlon minlon
+            :maxlon maxlon)))
+      (let [
+            bits (dec bits)
+            bit (bit-and (bit-shift-right hash-code 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 bits hash-code (not islon) 
+          (assoc geocode-data
+            :minlat minlat
+            :maxlat maxlat))))))
+
+(defn- do-decode [hash-codes geocode-data islon]
+  (if (empty? hash-codes)
+    (do (println geocode-data)
+      geocode-data)
+    (let [local-geocode-data (do-decode-hashcode 5 (first hash-codes) islon geocode-data)]
+      (recur (rest hash-codes) local-geocode-data (not islon)))))
+
+(defn decode [hashstring]
+  (let [
+        hashcodes (map base32-index hashstring)
+        bbox (do-decode hashcodes (struct geocode-data 180.0 -180.0 90.0 -90.0 nil nil nil) true)
+        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 true 
+    (struct geocode-data 180 -180 90 -90 0 0 "")))

test/geohash/test/core.clj

+(ns geohash.test.core
+  (:use [geohash.core])
+  (:use [clojure.test]))
+
+(deftest test-encode 
+  (is (= "ww8p1r4t8" (encode 37.8324 112.5584 9))))
+
+(deftest test-decode
+  (let [geodata (decode "ww8p1r4t8")]
+    (is (< (Math/abs (- (:lat geodata) 37.8324)) 0.0001))
+    (is (< (Math/abs (- (:lon geodata) 112.5584)) 0.0001))))
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.