diff --git a/index.html b/index.html
index fec78cf5c..9f0c7a6f5 100644
--- a/index.html
+++ b/index.html
@@ -48,6 +48,7 @@
+
diff --git a/js/id/geo/raw_mercator.js b/js/id/geo/raw_mercator.js
new file mode 100644
index 000000000..f34cb5d96
--- /dev/null
+++ b/js/id/geo/raw_mercator.js
@@ -0,0 +1,50 @@
+/*
+ Bypasses features of D3's default projection stream pipeline that are unnecessary:
+ * Antimeridian clipping
+ * Spherical rotation
+ * Resampling
+*/
+iD.geo.RawMercator = function () {
+ var project = d3.geo.mercator.raw,
+ k = 512 / Math.PI, // scale
+ x = 0, y = 0, // translate
+ clipExtent = [[0, 0], [0, 0]];
+
+ function projection(point) {
+ point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
+ return [point[0] * k + x, y - point[1] * k];
+ }
+
+ projection.invert = function(point) {
+ point = project.invert((point[0] - x) / k, (y - point[1]) / k);
+ return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
+ };
+
+ projection.scale = function(_) {
+ if (!arguments.length) return k;
+ k = +_;
+ return projection;
+ };
+
+ projection.translate = function(_) {
+ if (!arguments.length) return [x, y];
+ x = +_[0];
+ y = +_[1];
+ return projection;
+ };
+
+ projection.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent;
+ clipExtent = _;
+ return projection;
+ };
+
+ projection.stream = d3.geo.transform({
+ point: function(x, y) {
+ x = projection([x, y]);
+ this.stream.point(x[0], x[1]);
+ }
+ }).stream;
+
+ return projection;
+};
diff --git a/js/id/id.js b/js/id/id.js
index 2dfc664d1..af51ef051 100644
--- a/js/id/id.js
+++ b/js/id/id.js
@@ -197,52 +197,7 @@ window.iD = function () {
};
/* Projection */
- function rawMercator() {
- var project = d3.geo.mercator.raw,
- k = 512 / Math.PI, // scale
- x = 0, y = 0, // translate
- clipExtent = [[0, 0], [0, 0]];
-
- function projection(point) {
- point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
- return [point[0] * k + x, y - point[1] * k];
- }
-
- projection.invert = function(point) {
- point = project.invert((point[0] - x) / k, (y - point[1]) / k);
- return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
- };
-
- projection.scale = function(_) {
- if (!arguments.length) return k;
- k = +_;
- return projection;
- };
-
- projection.translate = function(_) {
- if (!arguments.length) return [x, y];
- x = +_[0];
- y = +_[1];
- return projection;
- };
-
- projection.clipExtent = function(_) {
- if (!arguments.length) return clipExtent;
- clipExtent = _;
- return projection;
- };
-
- projection.stream = d3.geo.transform({
- point: function(x, y) {
- x = projection([x, y]);
- this.stream.point(x[0], x[1]);
- }
- }).stream;
-
- return projection;
- }
-
- context.projection = rawMercator();
+ context.projection = iD.geo.RawMercator();
/* Background */
var background = iD.Background(context);
diff --git a/test/index.html b/test/index.html
index 8fe2bc698..85dfeba68 100644
--- a/test/index.html
+++ b/test/index.html
@@ -46,6 +46,7 @@
+