Repository: incubator-hivemall
Updated Branches:
  refs/heads/master 6e24d3a95 -> f538c891f


Close #73: [HIVEMALL-96] Add GEO Spatial UDFs (tile, map_url)


Project: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-hivemall/commit/f538c891
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/tree/f538c891
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/diff/f538c891

Branch: refs/heads/master
Commit: f538c891fdbae83ec48768bcbf2ad9223a90e9ba
Parents: 6e24d3a
Author: myui <[email protected]>
Authored: Mon Apr 24 19:17:43 2017 +0900
Committer: myui <[email protected]>
Committed: Mon Apr 24 19:17:43 2017 +0900

----------------------------------------------------------------------
 .../java/hivemall/geospatial/MapURLUDF.java     | 160 +++++++++++++++++++
 .../main/java/hivemall/geospatial/TileUDF.java  | 102 ++++++++++++
 .../utils/geospatial/GeoSpatialUtils.java       |  67 ++++++++
 .../java/hivemall/utils/math/MathUtils.java     |   7 +
 .../utils/geospatial/GeoSpatialUtilsTest.java   |  50 ++++++
 docs/gitbook/SUMMARY.md                         |   4 +
 docs/gitbook/geospatial/latlon.md               | 113 +++++++++++++
 resources/ddl/define-all-as-permanent.hive      |  10 ++
 resources/ddl/define-all.hive                   |  10 ++
 resources/ddl/define-all.spark                  |  10 ++
 resources/ddl/define-udfs.td.hql                |   2 +
 11 files changed, 535 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/core/src/main/java/hivemall/geospatial/MapURLUDF.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/hivemall/geospatial/MapURLUDF.java 
b/core/src/main/java/hivemall/geospatial/MapURLUDF.java
new file mode 100644
index 0000000..c2423e8
--- /dev/null
+++ b/core/src/main/java/hivemall/geospatial/MapURLUDF.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package hivemall.geospatial;
+
+import hivemall.UDFWithOptions;
+import hivemall.utils.geospatial.GeoSpatialUtils;
+import hivemall.utils.hadoop.HiveUtils;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.hive.ql.exec.Description;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.ql.udf.UDFType;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.io.Text;
+
+@Description(
+        name = "map_url",
+        value = "_FUNC_(double lat, double lon, int zoom [, const string 
option]) - Returns a URL string",
+        extended = "OpenStreetMap: 
http://tile.openstreetmap.org/${zoom}/${xtile}/${ytile}.png\n";
+                + "Google Maps: 
https://www.google.com/maps/@${lat},${lon},${zoom}z";)
+@UDFType(deterministic = true, stateful = false)
+public final class MapURLUDF extends UDFWithOptions {
+
+    private PrimitiveObjectInspector latOI;
+    private PrimitiveObjectInspector lonOI;
+    private PrimitiveObjectInspector zoomOI;
+
+    private MapType type = MapType.openstreetmap;
+    private Text result;
+
+    @Override
+    protected Options getOptions() {
+        Options opts = new Options();
+        opts.addOption("t", "type", true,
+            "Map type [default: openstreetmap|osm, googlemaps|google]");
+        return opts;
+    }
+
+    @Override
+    protected CommandLine processOptions(String optionValue) throws 
UDFArgumentException {
+        CommandLine cl = parseOptions(optionValue);
+
+        this.type = MapType.resolve(cl.getOptionValue("type", 
"openstreetmap"));
+        return cl;
+    }
+
+    public enum MapType {
+        openstreetmap, googlemaps;
+
+        @Nonnull
+        public static final MapType resolve(@Nonnull String type) throws 
UDFArgumentException {
+            if ("openstreetmap".equalsIgnoreCase(type) || 
"osm".equalsIgnoreCase(type)) {
+                return openstreetmap;
+            } else if ("googlemaps".equalsIgnoreCase(type) || 
"google".equalsIgnoreCase(type)) {
+                return googlemaps;
+            } else {
+                throw new UDFArgumentException("Illegal map type: " + type);
+            }
+        }
+    }
+
+    @Override
+    public ObjectInspector initialize(ObjectInspector[] argOIs) throws 
UDFArgumentException {
+        if (argOIs.length != 3 && argOIs.length != 4) {
+            throw new UDFArgumentException("_FUNC_ takes 3 or 4 arguments: " + 
argOIs.length);
+        }
+        if (argOIs.length == 4) {
+            String opts = HiveUtils.getConstString(argOIs[3]);
+            processOptions(opts);
+        }
+
+        this.latOI = HiveUtils.asDoubleCompatibleOI(argOIs[0]);
+        this.lonOI = HiveUtils.asDoubleCompatibleOI(argOIs[1]);
+        this.zoomOI = HiveUtils.asIntegerOI(argOIs[2]);
+
+        this.result = new Text();
+        return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
+    }
+
+    @Override
+    public Text evaluate(DeferredObject[] arguments) throws HiveException {
+        Object arg0 = arguments[0].get();
+        Object arg1 = arguments[1].get();
+        Object arg2 = arguments[2].get();
+
+        if (arg0 == null || arg1 == null) {
+            return null;
+        }
+        if (arg2 == null) {
+            throw new UDFArgumentException("zoom level is null");
+        }
+
+        double lat = PrimitiveObjectInspectorUtils.getDouble(arg0, latOI);
+        double lon = PrimitiveObjectInspectorUtils.getDouble(arg1, lonOI);
+        int zoom = PrimitiveObjectInspectorUtils.getInt(arg2, zoomOI);
+
+        result.set(toMapURL(lat, lon, zoom, type));
+        return result;
+    }
+
+    @Nonnull
+    private static String toMapURL(double lat, double lon, int zoom, @Nonnull 
MapType type)
+            throws UDFArgumentException {
+        if (type == MapType.openstreetmap) {// 
http://tile.openstreetmap.org/${zoom}/${xtile}/${ytile}.png            
+            if (zoom < 0 || zoom > 19) {
+                throw new UDFArgumentException(
+                    "Illegal zoom level. Supported zoom level for 
openstreetmap is [0,19]: " + zoom);
+            }
+            final int xtile, ytile;
+            try {
+                xtile = GeoSpatialUtils.lon2tile(lon, zoom);
+                ytile = GeoSpatialUtils.lat2tile(lat, zoom);
+            } catch (IllegalArgumentException ex) {
+                throw new UDFArgumentException(ex);
+            }
+            return "http://tile.openstreetmap.org/"; + Integer.toString(zoom) + 
'/'
+                    + Integer.toString(xtile) + '/' + Integer.toString(ytile) 
+ ".png";
+        } else if (type == MapType.googlemaps) {// 
https://www.google.com/maps/@${lat},${lon},${zoom}z
+            if (zoom < 0 || zoom > 21) {
+                throw new UDFArgumentException(
+                    "Illegal zoom level. Supported zoom level for Google Maps 
is [0,21]: " + zoom);
+            }
+            return "https://www.google.com/maps/@"; + Double.toString(lat) + ','
+                    + Double.toString(lon) + ',' + Integer.toString(zoom) + 
'z';
+        } else {
+            throw new UDFArgumentException("Unexpected map type: " + type);
+        }
+    }
+
+    @Override
+    public String getDisplayString(String[] children) {
+        return "map_url(" + Arrays.toString(children) + ")";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/core/src/main/java/hivemall/geospatial/TileUDF.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/hivemall/geospatial/TileUDF.java 
b/core/src/main/java/hivemall/geospatial/TileUDF.java
new file mode 100644
index 0000000..074b6a4
--- /dev/null
+++ b/core/src/main/java/hivemall/geospatial/TileUDF.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package hivemall.geospatial;
+
+import hivemall.utils.geospatial.GeoSpatialUtils;
+import hivemall.utils.hadoop.HiveUtils;
+import hivemall.utils.lang.Preconditions;
+
+import java.util.Arrays;
+
+import org.apache.hadoop.hive.ql.exec.Description;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.ql.udf.UDFType;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.io.IntWritable;
+
+/**
+ * @link http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+ */
+@Description(
+        name = "tile",
+        value = "_FUNC_(double lat, double lon, int zoom)::INT - Returns a 
tile number 2^2n where n is zoom level.\n"
+                + "_FUNC_(lat,lon,zoom) = xtile(lon,zoom) + ytile(lat,zoom) * 
2^n",
+        extended = "refer 
http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames for detail")
+@UDFType(deterministic = true, stateful = false)
+public final class TileUDF extends GenericUDF {
+
+    private PrimitiveObjectInspector latOI;
+    private PrimitiveObjectInspector lonOI;
+    private PrimitiveObjectInspector zoomOI;
+
+    private IntWritable result;
+
+    @Override
+    public ObjectInspector initialize(ObjectInspector[] argOIs) throws 
UDFArgumentException {
+        if (argOIs.length != 3) {
+            throw new UDFArgumentException("_FUNC_ takes exactly 3 arguments: 
" + argOIs.length);
+        }
+        this.latOI = HiveUtils.asDoubleCompatibleOI(argOIs[0]);
+        this.lonOI = HiveUtils.asDoubleCompatibleOI(argOIs[1]);
+        this.zoomOI = HiveUtils.asIntegerOI(argOIs[2]);
+
+        this.result = new IntWritable();
+        return PrimitiveObjectInspectorFactory.writableIntObjectInspector;
+    }
+
+    @Override
+    public IntWritable evaluate(DeferredObject[] arguments) throws 
HiveException {
+        Object arg0 = arguments[0].get();
+        Object arg1 = arguments[1].get();
+        Object arg2 = arguments[2].get();
+
+        if (arg0 == null || arg1 == null) {
+            return null;
+        }
+        if (arg2 == null) {
+            throw new UDFArgumentException("zoom level is null");
+        }
+
+        double lat = PrimitiveObjectInspectorUtils.getDouble(arg0, latOI);
+        double lon = PrimitiveObjectInspectorUtils.getDouble(arg1, lonOI);
+        int zoom = PrimitiveObjectInspectorUtils.getInt(arg2, zoomOI);
+        Preconditions.checkArgument(zoom >= 0, "Invalid zoom level", 
UDFArgumentException.class);
+
+        final int tile;
+        try {
+            tile = GeoSpatialUtils.tile(lat, lon, zoom);
+        } catch (IllegalArgumentException ex) {
+            throw new UDFArgumentException(ex);
+        }
+
+        result.set(tile);
+        return result;
+    }
+
+    @Override
+    public String getDisplayString(String[] children) {
+        return "tile(" + Arrays.toString(children) + ")";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/core/src/main/java/hivemall/utils/geospatial/GeoSpatialUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/hivemall/utils/geospatial/GeoSpatialUtils.java 
b/core/src/main/java/hivemall/utils/geospatial/GeoSpatialUtils.java
new file mode 100644
index 0000000..1cc254e
--- /dev/null
+++ b/core/src/main/java/hivemall/utils/geospatial/GeoSpatialUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package hivemall.utils.geospatial;
+
+import static hivemall.utils.math.MathUtils.sec;
+import static java.lang.Math.PI;
+import static java.lang.Math.floor;
+import static java.lang.Math.log;
+import static java.lang.Math.tan;
+
+import javax.annotation.Nonnegative;
+
+public final class GeoSpatialUtils {
+
+    public static final double MAX_LATITUDE = 85.0511d;
+    public static final double MIN_LATITUDE = -85.0511d;
+
+    private GeoSpatialUtils() {}
+
+    public static int lon2tile(final double lon, @Nonnegative final int zoom) {
+        if (lon < -180.d || lon > 180.d) {
+            throw new IllegalArgumentException("Longitude must be in range 
[-180,+180]: " + lon);
+        }
+        return (int) floor((lon + 180.d) / 360.d * (1 << zoom));
+    }
+
+    public static int lat2tile(final double lat, @Nonnegative final int zoom) {
+        if (lat < MIN_LATITUDE || lat > MAX_LATITUDE) {
+            throw new IllegalArgumentException("Latitude must be in range 
[-85.0511,+85.0511]: "
+                    + lat + "\nSee 
http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames";);
+        }
+        double lat_rad = Math.toRadians(lat);
+        int n = 1 << zoom;
+        return (int) floor((1.d - log(tan(lat_rad) + sec(lat_rad)) / PI) / 2.d 
* n);
+    }
+
+    /**
+     * @link https://en.wikipedia.org/wiki/Tiled_web_map#Tile_numbering_schemes
+     */
+    public static int tile(final double lat, final double lon, @Nonnegative 
final int zoom) {
+        int xtile = lon2tile(lon, zoom);
+        int ytile = lat2tile(lat, zoom);
+        int n = 1 << zoom; // 2^z
+        return xtile + (n * ytile);
+    }
+
+    public static int tiles(final int zoom) {
+        return 1 << (zoom * 2); // 2^2z
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/core/src/main/java/hivemall/utils/math/MathUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/hivemall/utils/math/MathUtils.java 
b/core/src/main/java/hivemall/utils/math/MathUtils.java
index 9b46527..061b75d 100644
--- a/core/src/main/java/hivemall/utils/math/MathUtils.java
+++ b/core/src/main/java/hivemall/utils/math/MathUtils.java
@@ -46,6 +46,13 @@ public final class MathUtils {
 
     private MathUtils() {}
 
+    /**    
+     * @return secant 1 / cos(d)
+     */
+    public static double sec(final double d) {
+        return 1.d / Math.cos(d);
+    }
+    
     /**
      * Returns a bit mask for the specified number of bits.
      */

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/core/src/test/java/hivemall/utils/geospatial/GeoSpatialUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/hivemall/utils/geospatial/GeoSpatialUtilsTest.java 
b/core/src/test/java/hivemall/utils/geospatial/GeoSpatialUtilsTest.java
new file mode 100644
index 0000000..6f551be
--- /dev/null
+++ b/core/src/test/java/hivemall/utils/geospatial/GeoSpatialUtilsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package hivemall.utils.geospatial;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GeoSpatialUtilsTest {
+
+    @Test
+    public void testTile() {
+        double[] lat_array = new double[] {GeoSpatialUtils.MIN_LATITUDE, 0.d,
+                GeoSpatialUtils.MAX_LATITUDE};
+        double[] lon_array = new double[] {-180.d, 0.d, 180.d};
+        for (double lat : lat_array) {
+            for (double lon : lon_array) {
+                Assert.assertTrue(
+                    String.format("lat=%s, lon=%s, tile=%s", lat, lon,
+                        GeoSpatialUtils.tile(lat, lon, 4)), 
GeoSpatialUtils.tile(lat, lon, 4) >= 0);
+            }
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testTileInvalidLat1() {
+        GeoSpatialUtils.tile(GeoSpatialUtils.MIN_LATITUDE - 0.1, 0, 4);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testTileInvalidLat2() {
+        GeoSpatialUtils.tile(GeoSpatialUtils.MAX_LATITUDE + 0.1, 0, 4);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/docs/gitbook/SUMMARY.md
----------------------------------------------------------------------
diff --git a/docs/gitbook/SUMMARY.md b/docs/gitbook/SUMMARY.md
index 78b1faa..fe109ec 100644
--- a/docs/gitbook/SUMMARY.md
+++ b/docs/gitbook/SUMMARY.md
@@ -154,6 +154,10 @@
 
 * [Latent Dirichlet Allocation](clustering/lda.md)
 
+## Part XI - GeoSpatial functions
+
+* [Lat/Lon functions](geospatial/latlon.md)
+
 ## Part XI - Hivemall on Spark
 
 * [Getting Started](spark/getting_started/README.md)

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/docs/gitbook/geospatial/latlon.md
----------------------------------------------------------------------
diff --git a/docs/gitbook/geospatial/latlon.md 
b/docs/gitbook/geospatial/latlon.md
new file mode 100644
index 0000000..96ca11b
--- /dev/null
+++ b/docs/gitbook/geospatial/latlon.md
@@ -0,0 +1,113 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+This page introduces Geo-spatial functions that treats latitude and longitude.
+
+<!-- toc -->
+
+> #### Note
+> This feature is supported from Hivemall v0.5-rc.1 or later.
+
+# Tile number function
+
+`tile(double lat, double lon, int zoom)` returns a tile number in 
`xtile(lon,zoom) + ytile(lat,zoom) * 2^n`. The tile number is in range 
`[0,2^2z]`.
+
+Formulas to convert latitude and longitude into tile x,y coordinates are as 
follows:
+
+{% math %}
+\begin{aligned}
+x &= \left\lfloor \frac{lon + 180}{360} \cdot 2^z \right\rfloor \\ \\
+y &=
+    \left\lfloor
+        \left(
+            1 - \frac{
+                \ln \left(
+                    \tan \left(
+                        lat \cdot \frac{\pi}{180}
+                    \right) + \frac{1}{\cos \left( lat \cdot \frac{\pi}{180} 
\right)}
+                \right)
+            }{\pi}
+        \right) \cdot 2^{z - 1}
+    \right\rfloor
+\end{aligned}
+{% endmath %}
+
+Refer [this page](http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) for 
detail. Zoom level is well described in [this 
page](http://wiki.openstreetmap.org/wiki/Zoom_levels).
+
+### Usage
+
+```sql
+WITH data as (
+  select 51.51202 as lat, 0.02435 as lon, 17 as zoom
+  union all
+  select 51.51202 as lat, 0.02435 as lon, 4 as zoom
+  union all
+  select null as lat, 0.02435 as lon, 17 as zoom
+)
+select 
+   tile(lat, lon, zoom) as tile
+from 
+   data;
+```
+
+| tile |
+|:--:|
+|1417478152|
+|88|
+|NULL|
+
+# Map URL function
+
+`map_url(double lat, double lon, int zoom [, const string option])` function 
returns a tile URL of openstreetmap.com or maps.google.com.
+
+The 4th argument takes the following optional arguments:
+```sql
+hive> select map_url(1,1,1,'-help');
+
+usage: map_url(double lat, double lon, int zoom [, const string option]) -
+       Returns a URL string [-help] [-t <arg>]
+ -help             Show function help
+ -t,--type <arg>   Map type [default: openstreetmap|osm,
+                   googlemaps|google]
+```
+
+### Usage
+
+```sql
+WITH data as (
+  select 51.51202 as lat, 0.02435 as lon, 17 as zoom
+  union all
+  select 51.51202 as lat, 0.02435 as lon, 4 as zoom
+  union all
+  select null, 0.02435, 17
+)
+select 
+   map_url(lat,lon,zoom) as osm_url,
+   map_url(lat,lon,zoom,'-type googlemaps') as gmap_url
+from
+  data;
+```
+
+|osm_url|gmap_url|
+|:------:|:--------:|
+|http://tile.openstreetmap.org/17/65544/43582.png | 
https://www.google.com/maps/@51.51202,0.02435,17z| 
+|http://tile.openstreetmap.org/4/8/5.png|https://www.google.com/maps/@51.51202,0.02435,4z|
+|NULL|NULL|
+
+![http://tile.openstreetmap.org/17/65544/43582.png](http://tile.openstreetmap.org/17/65544/43582.png
 "http://tile.openstreetmap.org/17/65544/43582.png";)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/resources/ddl/define-all-as-permanent.hive
----------------------------------------------------------------------
diff --git a/resources/ddl/define-all-as-permanent.hive 
b/resources/ddl/define-all-as-permanent.hive
index 1eb9c82..435466d 100644
--- a/resources/ddl/define-all-as-permanent.hive
+++ b/resources/ddl/define-all-as-permanent.hive
@@ -626,6 +626,16 @@ CREATE FUNCTION train_lda as 'hivemall.topicmodel.LDAUDTF' 
USING JAR '${hivemall
 DROP FUNCTION IF EXISTS lda_predict;
 CREATE FUNCTION lda_predict as 'hivemall.topicmodel.LDAPredictUDAF' USING JAR 
'${hivemall_jar}';
 
+---------------------------
+-- Geo-Spatial functions --
+---------------------------
+
+DROP FUNCTION IF EXISTS tile;
+CREATE FUNCTION tile as 'hivemall.geospatial.TileUDF' USING JAR 
'${hivemall_jar}';
+
+DROP FUNCTION IF EXISTS map_url;
+CREATE FUNCTION map_url as 'hivemall.geospatial.MapURLUDF' USING JAR 
'${hivemall_jar}';
+
 ----------------------------
 -- Smile related features --
 ----------------------------

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/resources/ddl/define-all.hive
----------------------------------------------------------------------
diff --git a/resources/ddl/define-all.hive b/resources/ddl/define-all.hive
index b503546..8982ef4 100644
--- a/resources/ddl/define-all.hive
+++ b/resources/ddl/define-all.hive
@@ -622,6 +622,16 @@ create temporary function train_lda as 
'hivemall.topicmodel.LDAUDTF';
 drop temporary function if exists lda_predict;
 create temporary function lda_predict as 'hivemall.topicmodel.LDAPredictUDAF';
 
+---------------------------
+-- Geo-Spatial functions --
+---------------------------
+
+drop temporary function if exists tile;
+create temporary function tile as 'hivemall.geospatial.TileUDF';
+
+drop temporary function if exists map_url;
+create temporary function map_url as 'hivemall.geospatial.MapURLUDF';
+
 ----------------------------
 -- Smile related features --
 ----------------------------

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/resources/ddl/define-all.spark
----------------------------------------------------------------------
diff --git a/resources/ddl/define-all.spark b/resources/ddl/define-all.spark
index b5239cf..a6473db 100644
--- a/resources/ddl/define-all.spark
+++ b/resources/ddl/define-all.spark
@@ -607,6 +607,16 @@ sqlContext.sql("DROP TEMPORARY FUNCTION IF EXISTS 
lda_predict")
 sqlContext.sql("CREATE TEMPORARY FUNCTION lda_predict AS 
'hivemall.topicmodel.LDAPredictUDAF'")
 
 /**
+ * Geo Spatial Functions
+ */
+
+sqlContext.sql("DROP TEMPORARY FUNCTION IF EXISTS tile")
+sqlContext.sql("CREATE TEMPORARY FUNCTION tile AS 
'hivemall.geospatial.TileUDF'")
+
+sqlContext.sql("DROP TEMPORARY FUNCTION IF EXISTS map_url")
+sqlContext.sql("CREATE TEMPORARY FUNCTION map_url AS 
'hivemall.geospatial.MapURLUDF'")
+
+/**
  * Smile related features
  */
 

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/f538c891/resources/ddl/define-udfs.td.hql
----------------------------------------------------------------------
diff --git a/resources/ddl/define-udfs.td.hql b/resources/ddl/define-udfs.td.hql
index 28d17ff..a2e5838 100644
--- a/resources/ddl/define-udfs.td.hql
+++ b/resources/ddl/define-udfs.td.hql
@@ -160,6 +160,8 @@ create temporary function changefinder as 
'hivemall.anomaly.ChangeFinderUDF';
 create temporary function sst as 
'hivemall.anomaly.SingularSpectrumTransformUDF';
 create temporary function train_lda as 'hivemall.topicmodel.LDAUDTF';
 create temporary function lda_predict as 'hivemall.topicmodel.LDAPredictUDAF';
+create temporary function tile as 'hivemall.geospatial.TileUDF';
+create temporary function map_url as 'hivemall.geospatial.MapURLUDF';
 
 -- NLP features
 create temporary function tokenize_ja as 'hivemall.nlp.tokenizer.KuromojiUDF';

Reply via email to