Options

Decode Google Encoded Polyline using Execute Script

pgirgispgirgis Member Posts: 1 Contributor I
edited November 2018 in Help

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;

 

Sign In or Register to comment.