diff --git a/examples/encoded-polyline.html b/examples/encoded-polyline.html
new file mode 100644
index 0000000000..c40a243201
--- /dev/null
+++ b/examples/encoded-polyline.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Encoded Polyline Example
+
+
+ Encoded Polyline, Google
+
+
+
+ Demonstrate the use of the Encoded Polyline format.
+
+
+
+
This example uses the Encoded Polyline format.
+
+
+
diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js
index 4df00ddf62..b6d5b397ff 100644
--- a/lib/OpenLayers.js
+++ b/lib/OpenLayers.js
@@ -306,6 +306,7 @@
"OpenLayers/Format/GML/v2.js",
"OpenLayers/Format/GML/v3.js",
"OpenLayers/Format/Atom.js",
+ "OpenLayers/Format/EncodedPolyline.js",
"OpenLayers/Format/KML.js",
"OpenLayers/Format/GeoRSS.js",
"OpenLayers/Format/WFS.js",
diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js
new file mode 100644
index 0000000000..1255eb1c91
--- /dev/null
+++ b/lib/OpenLayers/Format/EncodedPolyline.js
@@ -0,0 +1,254 @@
+/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.EncodedPolyline
+ * Class for reading and writing encoded polylines. Create a new instance
+ * with the constructor.
+ *
+ * Inherits from:
+ * -
+ */
+OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * APIProperty: geometryType
+ * {String} Geometry type to output. One of: linestring (default),
+ * linearring, point, multipoint or polygon. If the geometryType is
+ * point, only the first point of the string is returned.
+ */
+ geometryType: "linestring",
+
+ /**
+ * Constructor: OpenLayers.Format.EncodedPolyline
+ * Create a new parser for encoded polylines
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance
+ *
+ * Returns:
+ * {} A new encoded polylines parser.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Deserialize an encoded polyline string and return a vector feature.
+ *
+ * Parameters:
+ * encoded - {String} An encoded polyline string
+ *
+ * Returns:
+ * {} A vector feature with a linestring.
+ */
+ read: function(encoded) {
+ var geomType;
+ if (this.geometryType == "linestring")
+ geomType = OpenLayers.Geometry.LineString;
+ else if (this.geometryType == "linearring")
+ geomType = OpenLayers.Geometry.LinearRing;
+ else if (this.geometryType == "multipoint")
+ geomType = OpenLayers.Geometry.MultiPoint;
+ else if (this.geometryType != "point" && this.geometryType != "polygon")
+ return null;
+
+ var points = this.decode(encoded, 2);
+ var pointGeometries = new Array();
+ for (i in points) {
+ var point = points[i];
+ pointGeometries.push(
+ new OpenLayers.Geometry.Point(point[1] * 1e-5, point[0] * 1e-5)
+ );
+ }
+
+ if (this.geometryType == "point")
+ return new OpenLayers.Feature.Vector(
+ pointGeometries[0]
+ );
+
+ if (this.geometryType == "polygon")
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Polygon([
+ new OpenLayers.Geometry.LinearRing(pointGeometries)
+ ])
+ );
+
+ return new OpenLayers.Feature.Vector(
+ new geomType(pointGeometries)
+ );
+ },
+
+ /**
+ * APIMethod: decode
+ * Deserialize an encoded string and return an array of n-dimensional
+ * points.
+ *
+ * Parameters:
+ * encoded - {String} An encoded string
+ * dims - {int} The dimension of the points that are returned
+ *
+ * Returns:
+ * {Array(Array(int))} An array containing n-dimensional arrays of
+ * coordinates.
+ */
+ decode: function(encoded, dims) {
+ var points = new Array();
+ var point = new Array(dims);
+
+ // Reset the point array
+ for (var i = 0; i < point.length; ++i)
+ point[i] = 0;
+
+ for (var i = 0; i < encoded.length;) {
+ for (var dim = 0; dim < dims; ++dim) {
+ var result = 0;
+ var shift = 0;
+
+ var b;
+ do {
+ b = encoded.charCodeAt(i++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+
+ point[dim] += ((result & 1) ? ~(result >> 1) : (result >> 1));
+ }
+
+ points.push(point.slice(0));
+ }
+
+ return points;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a feature or array of features into a WKT string.
+ *
+ * Parameters:
+ * features - {|Array} A feature or array of
+ * features
+ *
+ * Returns:
+ * {String} The WKT string representation of the input geometries
+ */
+ write: function(features) {
+ var feature;
+ if (features.constructor == Array)
+ feature = features[0];
+ else
+ feature = features;
+
+ var geometry = feature.geometry;
+ var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
+
+ var pointGeometries;
+ if (type == "point")
+ pointGeometries = new Array(geometry);
+ else if (type == "linestring" ||
+ type == "linearring" ||
+ type == "multipoint")
+ pointGeometries = geometry.components;
+ else if (type == "polygon")
+ pointGeometries = geometry.components[0].components;
+ else
+ return null;
+
+ var points = new Array();
+ for (var i in pointGeometries) {
+ var pointGeometry = pointGeometries[i];
+ var point = [Math.round(pointGeometry.y * 1e5),
+ Math.round(pointGeometry.x * 1e5)];
+ points.push(point);
+ }
+
+ var result = this.encode(points, 2);
+ return result;
+ },
+
+ /**
+ * APIMethod: encode
+ * Serialize an array of n-dimensional points and return an encoded string
+ *
+ * Parameters:
+ * points - {Array(Array(int))} An array containing n-dimensional
+ * arrays of coordinates
+ * dims - {int} The dimension of the points that should be read
+ *
+ * Returns:
+ * {String} An encoded string
+ */
+ encode: function (points, dims) {
+ var encoded_points = "";
+
+ var lastPoint = new Array(dims);
+ for (var i = 0; i < lastPoint.length; ++i)
+ lastPoint[i] = 0;
+
+ for (var i = 0; i < points.length; i++) {
+ var point = points[i];
+
+ for (var dim = 0; dim < lastPoint.length; ++dim) {
+ var delta = point[dim] - lastPoint[dim];
+ encoded_points += this.encodeSignedNumber(delta);
+ }
+
+ lastPoint = point;
+ }
+ return encoded_points;
+ },
+
+ /**
+ * Method: encodeSignedNumber
+ * Encode one single signed integer and return an encoded string
+ *
+ * Parameters:
+ * num - {int} A signed integer that should be encoded
+ *
+ * Returns:
+ * {String} An encoded string
+ */
+ encodeSignedNumber: function (num) {
+ var sgn_num = num << 1;
+ if (num < 0)
+ sgn_num = ~(sgn_num);
+
+ return this.encodeNumber(sgn_num);
+ },
+
+ /**
+ * Method: encodeNumber
+ * Encode one single unsigned integer and return an encoded string
+ *
+ * encodeSignedNumber should be used instead of using this method directly!
+ *
+ * Parameters:
+ * num - {int} An unsigned integer that should be encoded
+ *
+ * Returns:
+ * {String} An encoded string
+ */
+ encodeNumber: function (num) {
+ var encodeString = "";
+ var value;
+ while (num >= 0x20) {
+ value = (0x20 | (num & 0x1f)) + 63;
+ encodeString += (String.fromCharCode(value));
+ num >>= 5;
+ }
+ value = num + 63;
+ encodeString += (String.fromCharCode(value));
+ return encodeString;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.EncodedPolyline"
+});
diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html
new file mode 100644
index 0000000000..1a93a41afa
--- /dev/null
+++ b/tests/Format/EncodedPolyline.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
diff --git a/tests/list-tests.html b/tests/list-tests.html
index 8c37464b84..dfcaa2f4a0 100644
--- a/tests/list-tests.html
+++ b/tests/list-tests.html
@@ -66,6 +66,7 @@
Format/XML/VersionedOGC.html
Format/ArcXML/Features.html
Format/CQL.html
+ Format/EncodedPolyline.html
Format/GeoJSON.html
Format/GeoRSS.html
Format/GML.html