Decode Google Encoded Polyline using Execute Script
I worked on decoding an encoded Google Polyline using the execute script operator. I have incldued the script below for anyone wishing to use it. It is based upon https://github.com/scoutant/polyline-decoder however has some changes to address the incompatibility with Execute Script.
An example using the script where the exampleSet has a field called geofence with the encoded polyline is at the end.
import com.rapidminer.tools.Ontology;
import java.util.ArrayList;
import java.util.List;
import java.io.Serializable;
import java.util.Iterator;
public class PolylineUtils {
public static String toString(List<Point> polyline) {
String str = "[ ";
for( Point p : polyline) {
str += p;
}
return str + " ]";
}
public static String toMarkers(List<Point> polyline) {
String str = "";
for( Point p : polyline) {
str += "|" + p.getLat()+","+p.getLng();
}
return str.substring(1, str.length());
}
}
public class Point implements Serializable {
private static final long serialVersionUID = 1L;
private final double lat;
private final double lng;
public Point(double lat, double lng) {
this.lat = lat;
this.lng = lng;
}
public double getLat() {
return lat;
}
public double getLng() {
return lng;
}
@Override
public String toString() {
return "(" + lat + ", " + lng + ")";
}
public static String toGeoJSON(List<Point> points) {
StringBuilder buff = new StringBuilder("[");
Iterator<Point> itr = points.iterator();
while (itr.hasNext()) {
buff.append(toGeoJSON(itr.next()));
if (itr.hasNext()) {
buff.append(",");
}
}
buff.append("]");
return buff.toString();
}
public static String toGeoJSON(Point point) {
return "[" + point.getLng() + "," + point.getLat() + "]";
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Point)) {
return false;
}
Point that = (Point) o;
if (Math.abs(that.getLat() - lat) > 0.001) {
return false;
}
return Math.abs(that.getLng() - lng) <= 0.001;
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + (int) (Double.doubleToLongBits(this.lat) ^ (Double.doubleToLongBits(this.lat) >>> 32));
hash = 37 * hash + (int) (Double.doubleToLongBits(this.lng) ^ (Double.doubleToLongBits(this.lng) >>> 32));
return hash;
}
}
public class PolylineDecoder {
private static final double DEFAULT_PRECISION = 1E5;
public List<Point> decode(String encoded) {
return decode(encoded, DEFAULT_PRECISION);
}
public List<Point> decode(String encoded, double precision) {
List<Point> track = new ArrayList<Point>();
int index = 0;
int lat = 0, lng = 0;
while (index < encoded.length()) {
int b, shift = 0, result = 0;
while ({
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
b >= 0x20
}());
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
while ({
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
b >= 0x20
}());
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
Point p = new Point((double) lat / precision, (double) lng / precision);
track.add(p);
}
return track;
}
}
// To get the exampleset as an input
ExampleSet exampleSet = input[0];
// Get all attributes
Attributes atts = exampleSet.getAttributes();
// Select the attribute to process - use name to link to data
Attribute att1 = atts.get("geofence");
// Create new attributes
Attribute att2 = AttributeFactory.createAttribute("geofence_decoded", Ontology.STRING);
atts.addRegular(att2);
exampleSet.getExampleTable().addAttribute(att2);
for (Example example : exampleSet) {
String geofenceString = example.getNominalValue(att1);
PolylineDecoder decoder = new PolylineDecoder();
String result = decoder.decode(geofenceString);
example.setValue(att2, result);
}
return exampleSet;