Skip to content
Snippets Groups Projects
Commit 34a6c9ac authored by Cam Saul's avatar Cam Saul
Browse files

tile fixes so far

parent 04a86eaa
Branches
Tags
No related merge requests found
(ns metabase.api.tiles
(:require [clojure.data.json :as json]
(:require [clojure.core.match :refer [match]]
[clojure.data.json :as json]
[clojure.tools.logging :as log]
[compojure.core :refer [GET]]
[metabase.api.common :refer :all]
......@@ -7,10 +8,10 @@
[metabase.driver :as driver]))
(def tile-size 256)
(def pixel-origin (float (/ tile-size 2)))
(def pixel-per-lon-degree (float (/ tile-size 360.0)))
(def pixel-per-lon-radian (float (/ tile-size (* 2 java.lang.Math/PI))))
(def ^:const tile-size 256)
(def ^:const pixel-origin (float (/ tile-size 2)))
(def ^:const pixel-per-lon-degree (float (/ tile-size 360.0)))
(def ^:const pixel-per-lon-radian (float (/ tile-size (* 2 java.lang.Math/PI))))
(defn- radians->degrees [rad]
(/ rad (float (/ java.lang.Math/PI 180))))
......@@ -18,13 +19,13 @@
(defn- tile-lat-lon
"Get the Latitude & Longitude of the upper left corner of a given tile"
[x y zoom]
(let [num-tiles (bit-shift-left 1 zoom)
corner-x (float (/ (* x tile-size) num-tiles))
corner-y (float (/ (* y tile-size) num-tiles))
lon (float (/ (- corner-x pixel-origin) pixel-per-lon-degree))
(let [num-tiles (bit-shift-left 1 zoom)
corner-x (float (/ (* x tile-size) num-tiles))
corner-y (float (/ (* y tile-size) num-tiles))
lon (float (/ (- corner-x pixel-origin) pixel-per-lon-degree))
lat-radians (/ (- corner-y pixel-origin) (* pixel-per-lon-radian -1))
lat (radians->degrees (- (* 2 (java.lang.Math/atan (java.lang.Math/exp lat-radians)))
(/ java.lang.Math/PI 2)))]
lat (radians->degrees (- (* 2 (java.lang.Math/atan (java.lang.Math/exp lat-radians)))
(/ java.lang.Math/PI 2)))]
{:lat lat
:lon lon}))
......@@ -36,44 +37,46 @@
{bot-rt-lat :lat bot-rt-lon :lon} (tile-lat-lon (+ x 1) (+ y 1) zoom)
inside-filter ["INSIDE", lat-field-id, lon-field-id, top-lt-lat, top-lt-lon, bot-rt-lat, bot-rt-lon]]
(update-in details [:filter]
#(clojure.core.match/match %
nil inside-filter
["AND" & _] (conj % inside-filter)
[& _] (conj ["AND"] % inside-filter)))))
#(match %
["AND" & _] (conj % inside-filter)
[(_ :guard string?) & _] (conj ["AND"] % inside-filter)
:else inside-filter))))
(defn- extract-points
"Takes in a dataset query result object and pulls out the Latitude/Longitude pairs into nested `java.util.ArrayLists`.
This is specific to the way we plan to feed data into `com.metabase.corvus.api.tiles.GoogleMapPinsOverlay`."
[{{:keys [rows cols]} :data}]
(if-not (> (count rows) 0)
;; if we have no rows then return an empty list of points
(java.util.ArrayList. [])
;; otherwise we go over the data, pull out the lat/lon columns, and convert them to ArrayLists
(let [find-col-idx (fn [special-type]
(->> (map-indexed (fn [idx itm] (when (= special-type (:special_type itm)) idx)) cols)
(filter identity)
(first)))
lat-col-idx (find-col-idx "latitude")
lon-col-idx (find-col-idx "longitude")]
(->> (map (fn [row] (java.util.ArrayList. [(nth row lat-col-idx) (nth row lon-col-idx)])) rows)
(java.util.ArrayList.)))))
(try
(if-not (> (count rows) 0)
;; if we have no rows then return an empty list of points
(java.util.ArrayList. [])
;; otherwise we go over the data, pull out the lat/lon columns, and convert them to ArrayLists
(let [find-col-idx (fn [special-type]
(->> (map-indexed (fn [idx itm] (when (= special-type (:special_type itm)) idx)) cols)
(filter identity)
first))
lat-col-idx (find-col-idx "latitude")
lon-col-idx (find-col-idx "longitude")]
(->> (map (fn [row] (java.util.ArrayList. [(nth row lat-col-idx) (nth row lon-col-idx)])) rows)
(java.util.ArrayList.))))
(catch Throwable e
(log/debug "CAUGHT EXCEPTION IN EXTRACT-POINTS (WHY?): " e))))
;; This endpoints provides an image with the appropriate pins rendered given a json query
;; We evaluate the query and find the set of lat/lon pairs which are relevant and then render the appropriate ones
;; It's expected that to render a full map view several calls will be made to this endpoint in parallel
(defendpoint GET "/:zoom/:x/:y/:lat-field/:lon-field/:lat-col-idx/:lon-col-idx/"
"This endpoints provides an image with the appropriate pins rendered given a json query.
We evaluate the query and find the set of lat/lon pairs which are relevant and then render the appropriate ones.
It's expected that to render a full map view several calls will be made to this endpoint in parallel."
[zoom x y lat-field lon-field lat-col-idx lon-col-idx query :as request]
{zoom String->Integer
x String->Integer
y String->Integer
lat-field String->Integer
lon-field String->Integer
{zoom String->Integer
x String->Integer
y String->Integer
lat-field String->Integer
lon-field String->Integer
lat-col-idx String->Integer
lon-col-idx String->Integer
query String->Dict}
;; TODO - tried to use `query String->Dict` above, but got errors with json parsing for some reason
query String->Dict}
(let [updated-query (assoc query :query (query-with-inside-filter (:query query) lat-field lon-field x y zoom))
result (driver/dataset-query updated-query {:executed_by *current-user-id*
:synchronously true})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment