diff --git a/src/ol/proj/epsg3857.js b/src/ol/proj/epsg3857.js index 16dfe11d98..09864be283 100644 --- a/src/ol/proj/epsg3857.js +++ b/src/ol/proj/epsg3857.js @@ -116,10 +116,17 @@ ol.proj.EPSG3857.fromEPSG4326 = function(input, opt_output, opt_dimension) { } ol.DEBUG && console.assert(output.length % dimension === 0, 'modulus of output.length with dimension should be 0'); + var halfSize = ol.proj.EPSG3857.HALF_SIZE; for (var i = 0; i < length; i += dimension) { - output[i] = ol.proj.EPSG3857.RADIUS * Math.PI * input[i] / 180; - output[i + 1] = ol.proj.EPSG3857.RADIUS * + output[i] = halfSize * input[i] / 180; + var y = ol.proj.EPSG3857.RADIUS * Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360)); + if (y > halfSize) { + y = halfSize; + } else if (y < -halfSize) { + y = -halfSize; + } + output[i + 1] = y; } return output; }; @@ -148,7 +155,7 @@ ol.proj.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) { ol.DEBUG && console.assert(output.length % dimension === 0, 'modulus of output.length with dimension should be 0'); for (var i = 0; i < length; i += dimension) { - output[i] = 180 * input[i] / (ol.proj.EPSG3857.RADIUS * Math.PI); + output[i] = 180 * input[i] / ol.proj.EPSG3857.HALF_SIZE; output[i + 1] = 360 * Math.atan( Math.exp(input[i + 1] / ol.proj.EPSG3857.RADIUS)) / Math.PI - 90; } diff --git a/test/spec/ol/proj/epsg3857.test.js b/test/spec/ol/proj/epsg3857.test.js index 9854d96c20..2402b2854e 100644 --- a/test/spec/ol/proj/epsg3857.test.js +++ b/test/spec/ol/proj/epsg3857.test.js @@ -2,6 +2,7 @@ goog.provide('ol.test.proj.EPSG3857'); goog.require('ol.proj'); goog.require('ol.proj.common'); + describe('ol.proj.EPSG3857', function() { afterEach(function() { @@ -9,6 +10,38 @@ describe('ol.proj.EPSG3857', function() { ol.proj.common.add(); }); + describe('fromEPSG4326()', function() { + + it('transforms from geographic to Web Mercator', function() { + var forward = ol.proj.EPSG3857.fromEPSG4326; + var edge = ol.proj.EPSG3857.HALF_SIZE; + + var tolerance = 1e-5; + + var cases = [{ + g: [0, 0], + m: [0, 0] + }, { + g: [-180, -90], + m: [-edge, -edge] + }, { + g: [180, 90], + m: [edge, edge] + }, { + g: [-111.0429, 45.6770], + m: [-12361239.084208, 5728738.469095] + }]; + + for (var i = 0, ii = cases.length; i < ii; ++i) { + var point = cases[i].g; + var transformed = forward(point); + expect(transformed[0]).to.roughlyEqual(cases[i].m[0], tolerance); + expect(transformed[1]).to.roughlyEqual(cases[i].m[1], tolerance); + } + }); + + }); + describe('getPointResolution', function() { it('returns the correct point scale at the equator', function() { @@ -37,7 +70,7 @@ describe('ol.proj.EPSG3857', function() { var epsg4326 = ol.proj.get('EPSG:4326'); var resolution = 19.11; var latitude; - for (latitude = 0; latitude < 90; ++latitude) { + for (latitude = 0; latitude <= 85; ++latitude) { var point = ol.proj.transform([0, latitude], epsg4326, epsg3857); expect(epsg3857.getPointResolution(resolution, point)). to.roughlyEqual(19.11 * Math.cos(Math.PI * latitude / 180), 1e-9); diff --git a/test_rendering/spec/ol/layer/expected/inverted-star.png b/test_rendering/spec/ol/layer/expected/inverted-star.png new file mode 100644 index 0000000000..07399ffcb4 Binary files /dev/null and b/test_rendering/spec/ol/layer/expected/inverted-star.png differ diff --git a/test_rendering/spec/ol/layer/vector.test.js b/test_rendering/spec/ol/layer/vector.test.js index 563d231fb4..3bdaeea688 100644 --- a/test_rendering/spec/ol/layer/vector.test.js +++ b/test_rendering/spec/ol/layer/vector.test.js @@ -3,6 +3,7 @@ goog.provide('ol.test.rendering.layer.Vector'); goog.require('ol.Feature'); goog.require('ol.Map'); goog.require('ol.View'); +goog.require('ol.format.GeoJSON'); goog.require('ol.geom.Circle'); goog.require('ol.geom.LineString'); goog.require('ol.geom.Polygon'); @@ -271,6 +272,64 @@ describe('ol.rendering.layer.Vector', function() { }); }); + describe.only('polygon rendering', function() { + + var map; + beforeEach(function() { + map = new ol.Map({ + target: createMapDiv(128, 128), + view: new ol.View({ + center: [0, 0], + zoom: 0 + }) + }); + }); + + afterEach(function() { + disposeMap(map); + }); + + it('renders a feature that spans the world', function(done) { + var json = { + type: 'Feature', + geometry: { + type: 'Polygon', + coordinates: [ + [ + [-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90] + ], + [ + [0, 60], [-17.6336, 24.2705], [-57.0634, 18.5410], [-28.5317, -9.2705], [-35.2671, -48.5410], [0, -30], [35.2671, -48.5410], [28.5317, -9.2705], [57.0634, 18.5410], [17.6336, 24.2705], [0, 60] + ] + ] + }, + properties: {} + }; + + var format = new ol.format.GeoJSON({featureProjection: 'EPSG:3857'}); + var feature = format.readFeature(json); + + var layer = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: [feature] + }), + style: new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'blue' + }) + }) + }); + + map.addLayer(layer); + + map.once('postrender', function() { + expectResemble(map, 'spec/ol/layer/expected/inverted-star.png', 1, done); + }); + + }); + + }); + describe('Polygon simplification', function() { var layer, map;