Projection handling improvements

* The Map's private createProjection_ method is now a public
  method of the Projection. It is also used by TiledWMSSource
  to calculate the appropriate projection from the user
  configuration.
* ol.Projection.addProjection now adds the transformation for
  the source == target case. This makes it easy for the user
  to create custom projection maps without including proj4js and
  without adding a custom transformation, as long as the
  userProjection equals the projection.
* The TiledWMSSource now uses the same default resolutions as
  the map (i.e. the OSM resolutions)
* The modulo calculation for wrapping extents now works for all
  grid configurations, by not calculating the number of columns
  based on an assumption about the way the zoom levels relate to
  resolutions.
* The wms-custom-proj example now shows how to properly
  configure a custom resolution, i.e. by using the validity
  extent of the projection as its extent.
This commit is contained in:
ahocevar
2012-10-31 13:17:58 +01:00
parent 7af152cc49
commit eb4a8683e2
4 changed files with 47 additions and 35 deletions

View File

@@ -13,11 +13,12 @@ if (goog.DEBUG) {
goog.debug.Logger.getLogger('ol').setLevel(goog.debug.Logger.Level.INFO);
}
var epsg21781 = new ol.Projection('EPSG:21781', ol.ProjectionUnits.METERS,
// Validity extent from http://spatialreference.org
new ol.Extent(485869.5728, 76443.1884, 837076.5648, 299941.7864));
ol.Projection.addProjection(epsg21781);
var extent = new ol.Extent(420000, 30000, 900000, 350000);
var epsg21781 = new ol.Projection('EPSG:21781',
ol.ProjectionUnits.METERS, extent);
var layers = new ol.Collection([
new ol.layer.TileLayer({
source: new ol.source.TiledWMS({
@@ -28,7 +29,8 @@ var layers = new ol.Collection([
'Pixelmap 1:1000000 / geo.admin.ch</a>')],
crossOrigin: null,
params: {'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale'},
projection: epsg21781
projection: epsg21781,
extent: extent
})
}),
new ol.layer.TileLayer({
@@ -40,7 +42,8 @@ var layers = new ol.Collection([
'National parks / geo.admin.ch</a>')],
crossOrigin: null,
params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
projection: epsg21781
projection: epsg21781,
extent: extent
})
})
]);
@@ -49,6 +52,9 @@ var map = new ol.Map({
renderer: ol.RendererHint.DOM,
center: new ol.Coordinate(660000, 190000),
projection: epsg21781,
// By setting userProjection to the same as projection, we do not need
// proj4js because we do not need any transforms.
userProjection: epsg21781,
layers: layers,
target: 'map',
zoom: 9

View File

@@ -980,7 +980,7 @@ ol.Map.createOptionsInternal = function(mapOptions) {
values[ol.MapProperty.LAYERS] = goog.isDef(mapOptions.layers) ?
mapOptions.layers : new ol.Collection();
values[ol.MapProperty.PROJECTION] = ol.Map.createProjection_(
values[ol.MapProperty.PROJECTION] = ol.Projection.createProjection(
mapOptions.projection, 'EPSG:3857');
if (goog.isDef(mapOptions.resolution)) {
@@ -990,7 +990,7 @@ ol.Map.createOptionsInternal = function(mapOptions) {
ol.Projection.EPSG_3857_HALF_SIZE / (128 << mapOptions.zoom);
}
values[ol.MapProperty.USER_PROJECTION] = ol.Map.createProjection_(
values[ol.MapProperty.USER_PROJECTION] = ol.Projection.createProjection(
mapOptions.userProjection, 'EPSG:4326');
/**
@@ -1183,21 +1183,3 @@ ol.Map.createInteractions_ = function(mapOptions) {
return interactions;
};
/**
* @private
* @param {ol.Projection|string|undefined} projection Projection.
* @param {string} defaultCode Default code.
* @return {ol.Projection} Projection.
*/
ol.Map.createProjection_ = function(projection, defaultCode) {
if (!goog.isDefAndNotNull(projection)) {
return ol.Projection.getFromCode(defaultCode);
} else if (goog.isString(projection)) {
return ol.Projection.getFromCode(projection);
} else {
goog.asserts.assert(projection instanceof ol.Projection);
return projection;
}
};

View File

@@ -137,8 +137,10 @@ ol.Projection.addEquivalentProjections_ = function(projections) {
ol.Projection.addProjections(projections);
goog.array.forEach(projections, function(source) {
goog.array.forEach(projections, function(destination) {
if (source !== destination) {
ol.Projection.addTransform(
source, destination, ol.Projection.cloneTransform);
}
});
});
};
@@ -181,6 +183,8 @@ ol.Projection.addProjection = function(projection) {
var code = projection.getCode();
goog.asserts.assert(!goog.object.containsKey(projections, code));
projections[code] = projection;
ol.Projection.addTransform(
projection, projection, ol.Projection.cloneTransform);
};
@@ -194,6 +198,23 @@ ol.Projection.addProjections = function(projections) {
};
/**
* @param {ol.Projection|string|undefined} projection Projection.
* @param {string} defaultCode Default code.
* @return {ol.Projection} Projection.
*/
ol.Projection.createProjection = function(projection, defaultCode) {
if (!goog.isDefAndNotNull(projection)) {
return ol.Projection.getFromCode(defaultCode);
} else if (goog.isString(projection)) {
return ol.Projection.getFromCode(projection);
} else {
goog.asserts.assert(projection instanceof ol.Projection);
return projection;
}
};
/**
* @param {ol.Projection} source Source.
* @param {ol.Projection} destination Destination.

View File

@@ -2,6 +2,7 @@
goog.provide('ol.source.TiledWMS');
goog.require('goog.asserts');
goog.require('goog.object');
goog.require('ol.Attribution');
@@ -19,8 +20,8 @@ goog.require('ol.tilegrid.TileGrid');
* @param {ol.source.TiledWMSOptions} tiledWMSOptions options.
*/
ol.source.TiledWMS = function(tiledWMSOptions) {
var projection = goog.isDef(tiledWMSOptions.projection) ?
tiledWMSOptions.projection : ol.Projection.getFromCode('EPSG:3857');
var projection = ol.Projection.createProjection(
tiledWMSOptions.projection, 'EPSG:3857');
var projectionExtent = projection.getExtent();
var extent = goog.isDef(tiledWMSOptions.extent) ?
@@ -39,7 +40,7 @@ ol.source.TiledWMS = function(tiledWMSOptions) {
tiledWMSOptions.maxZoom : 18;
var resolutions = new Array(maxZoom + 1);
for (var z = 0, zz = resolutions.length; z < zz; ++z) {
resolutions[z] = size / (256 << z);
resolutions[z] = ol.Projection.EPSG_3857_HALF_SIZE / (128 << z);
}
tileGrid = new ol.tilegrid.TileGrid({
origin: projectionExtent.getTopLeft(),
@@ -85,15 +86,17 @@ ol.source.TiledWMS = function(tiledWMSOptions) {
return null;
}
var x = tileCoord.x;
var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
// FIXME do we want a wrapDateLine param? The code below will break maps
// with projections that do not span the whole world width.
if (extent.minX === projectionExtent.minX &&
extent.maxX === projectionExtent.maxX) {
var n = 1 << tileCoord.z;
x = goog.math.modulo(x, n);
}
var tileExtent = tileGrid.getTileCoordExtent(
var numCols = Math.ceil(
(extent.maxX - extent.minX) / (tileExtent.maxX - tileExtent.minX));
x = goog.math.modulo(x, numCols);
tileExtent = tileGrid.getTileCoordExtent(
new ol.TileCoord(tileCoord.z, x, tileCoord.y));
}
// FIXME We shouldn't need a typecast here.
if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) {
return null;