s/ol3/ol/
This commit is contained in:
59
src/ol/array.js
Normal file
59
src/ol/array.js
Normal file
@@ -0,0 +1,59 @@
|
||||
goog.provide('ol.array');
|
||||
|
||||
goog.require('goog.array');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} arr Array.
|
||||
* @param {number} target Target.
|
||||
* @return {number} Index.
|
||||
*/
|
||||
ol.array.binaryFindNearest = function(arr, target) {
|
||||
var index = goog.array.binarySearch(arr, target, function(a, b) {
|
||||
return b - a;
|
||||
});
|
||||
if (index >= 0) {
|
||||
return index;
|
||||
} else if (index == -1) {
|
||||
return 0;
|
||||
} else if (index == -arr.length - 1) {
|
||||
return arr.length - 1;
|
||||
} else {
|
||||
var left = -index - 2;
|
||||
var right = -index - 1;
|
||||
if (arr[left] - target < target - arr[right]) {
|
||||
return left;
|
||||
} else {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} arr Array.
|
||||
* @param {number} target Target.
|
||||
* @return {number} Index.
|
||||
*/
|
||||
ol.array.linearFindNearest = function(arr, target) {
|
||||
var n = arr.length;
|
||||
if (arr[0] <= target) {
|
||||
return 0;
|
||||
} else if (target <= arr[n - 1]) {
|
||||
return n - 1;
|
||||
} else {
|
||||
var i;
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] == target) {
|
||||
return i;
|
||||
} else if (arr[i] < target) {
|
||||
if (arr[i - 1] - target < target - arr[i]) {
|
||||
return i - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n - 1;
|
||||
}
|
||||
};
|
||||
46
src/ol/array_test.js
Normal file
46
src/ol/array_test.js
Normal file
@@ -0,0 +1,46 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.array');
|
||||
|
||||
|
||||
function testBinaryFindNearest() {
|
||||
var arr = [1000, 500, 100];
|
||||
|
||||
assertEquals(0, ol.array.binaryFindNearest(arr, 10000));
|
||||
assertEquals(0, ol.array.binaryFindNearest(arr, 1000));
|
||||
assertEquals(0, ol.array.binaryFindNearest(arr, 900));
|
||||
|
||||
assertEquals(1, ol.array.binaryFindNearest(arr, 750));
|
||||
|
||||
assertEquals(1, ol.array.binaryFindNearest(arr, 550));
|
||||
assertEquals(1, ol.array.binaryFindNearest(arr, 500));
|
||||
assertEquals(1, ol.array.binaryFindNearest(arr, 450));
|
||||
|
||||
assertEquals(2, ol.array.binaryFindNearest(arr, 300));
|
||||
|
||||
assertEquals(2, ol.array.binaryFindNearest(arr, 200));
|
||||
assertEquals(2, ol.array.binaryFindNearest(arr, 100));
|
||||
assertEquals(2, ol.array.binaryFindNearest(arr, 50));
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testLinearFindNearest() {
|
||||
var arr = [1000, 500, 100];
|
||||
|
||||
assertEquals(0, ol.array.linearFindNearest(arr, 10000));
|
||||
assertEquals(0, ol.array.linearFindNearest(arr, 1000));
|
||||
assertEquals(0, ol.array.linearFindNearest(arr, 900));
|
||||
|
||||
assertEquals(1, ol.array.linearFindNearest(arr, 750));
|
||||
|
||||
assertEquals(1, ol.array.linearFindNearest(arr, 550));
|
||||
assertEquals(1, ol.array.linearFindNearest(arr, 500));
|
||||
assertEquals(1, ol.array.linearFindNearest(arr, 450));
|
||||
|
||||
assertEquals(2, ol.array.linearFindNearest(arr, 300));
|
||||
|
||||
assertEquals(2, ol.array.linearFindNearest(arr, 200));
|
||||
assertEquals(2, ol.array.linearFindNearest(arr, 100));
|
||||
assertEquals(2, ol.array.linearFindNearest(arr, 50));
|
||||
|
||||
}
|
||||
58
src/ol/attribution.js
Normal file
58
src/ol/attribution.js
Normal file
@@ -0,0 +1,58 @@
|
||||
goog.provide('ol.Attribution');
|
||||
|
||||
goog.require('ol.CoverageArea');
|
||||
goog.require('ol.Projection');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string} html HTML.
|
||||
* @param {Array.<ol.CoverageArea>=} opt_coverageAreas Coverage areas.
|
||||
* @param {ol.Projection=} opt_projection Projection.
|
||||
*/
|
||||
ol.Attribution = function(html, opt_coverageAreas, opt_projection) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.html_ = html;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.CoverageArea>}
|
||||
*/
|
||||
this.coverageAreas_ = opt_coverageAreas || null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Projection}
|
||||
*/
|
||||
this.projection_ = opt_projection || null;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.CoverageArea>} Coverage areas.
|
||||
*/
|
||||
ol.Attribution.prototype.getCoverageAreas = function() {
|
||||
return this.coverageAreas_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} HTML.
|
||||
*/
|
||||
ol.Attribution.prototype.getHtml = function() {
|
||||
return this.html_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Projection} Projection.
|
||||
*/
|
||||
ol.Attribution.prototype.getProjection = function() {
|
||||
return this.projection_;
|
||||
};
|
||||
216
src/ol/collection.js
Normal file
216
src/ol/collection.js
Normal file
@@ -0,0 +1,216 @@
|
||||
|
||||
/**
|
||||
* @fileoverview An implementation of Google Maps' MVCArray.
|
||||
* @see https://developers.google.com/maps/documentation/javascript/reference
|
||||
*/
|
||||
|
||||
goog.provide('ol.Collection');
|
||||
goog.provide('ol.CollectionEvent');
|
||||
goog.provide('ol.CollectionEventType');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.CollectionEventType = {
|
||||
ADD: 'add',
|
||||
INSERT_AT: 'insert_at',
|
||||
REMOVE: 'remove',
|
||||
REMOVE_AT: 'remove_at',
|
||||
SET_AT: 'set_at'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @param {ol.CollectionEventType} type Type.
|
||||
* @param {*=} opt_elem Element.
|
||||
* @param {number=} opt_index Index.
|
||||
* @param {*=} opt_prev Value.
|
||||
* @param {Object=} opt_target Target.
|
||||
*/
|
||||
ol.CollectionEvent =
|
||||
function(type, opt_elem, opt_index, opt_prev, opt_target) {
|
||||
|
||||
goog.base(this, type, opt_target);
|
||||
|
||||
/**
|
||||
* @type {*}
|
||||
*/
|
||||
this.elem = opt_elem;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.index = opt_index;
|
||||
|
||||
/**
|
||||
* @type {*}
|
||||
*/
|
||||
this.prev = opt_prev;
|
||||
|
||||
};
|
||||
goog.inherits(ol.CollectionEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.CollectionProperty = {
|
||||
LENGTH: 'length'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {Array=} opt_array Array.
|
||||
*/
|
||||
ol.Collection = function(opt_array) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array}
|
||||
*/
|
||||
this.array_ = opt_array || [];
|
||||
|
||||
this.updateLength_();
|
||||
|
||||
};
|
||||
goog.inherits(ol.Collection, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* Remove all elements from the collection.
|
||||
*/
|
||||
ol.Collection.prototype.clear = function() {
|
||||
while (this[ol.CollectionProperty.LENGTH]) {
|
||||
this.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Function} f Function.
|
||||
* @param {Object=} opt_obj Object.
|
||||
*/
|
||||
ol.Collection.prototype.forEach = function(f, opt_obj) {
|
||||
goog.array.forEach(this.array_, f, opt_obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array} Array.
|
||||
*/
|
||||
ol.Collection.prototype.getArray = function() {
|
||||
return this.array_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @return {*} Element.
|
||||
*/
|
||||
ol.Collection.prototype.getAt = function(index) {
|
||||
return this.array_[index];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Length.
|
||||
*/
|
||||
ol.Collection.prototype.getLength = function() {
|
||||
return /** @type {number} */ this.get(ol.CollectionProperty.LENGTH);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @param {*} elem Element.
|
||||
*/
|
||||
ol.Collection.prototype.insertAt = function(index, elem) {
|
||||
goog.array.insertAt(this.array_, elem, index);
|
||||
this.updateLength_();
|
||||
this.dispatchEvent(new ol.CollectionEvent(
|
||||
ol.CollectionEventType.ADD, elem, undefined, undefined, this));
|
||||
this.dispatchEvent(new ol.CollectionEvent(
|
||||
ol.CollectionEventType.INSERT_AT, elem, index, undefined, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {*} Element.
|
||||
*/
|
||||
ol.Collection.prototype.pop = function() {
|
||||
return this.removeAt(this.getLength() - 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {*} elem Element.
|
||||
* @return {number} Length.
|
||||
*/
|
||||
ol.Collection.prototype.push = function(elem) {
|
||||
var n = this.array_.length;
|
||||
this.insertAt(n, elem);
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @return {*} Value.
|
||||
*/
|
||||
ol.Collection.prototype.removeAt = function(index) {
|
||||
var prev = this.array_[index];
|
||||
goog.array.removeAt(this.array_, index);
|
||||
this.updateLength_();
|
||||
this.dispatchEvent(new ol.CollectionEvent(
|
||||
ol.CollectionEventType.REMOVE, prev, undefined, undefined, this));
|
||||
this.dispatchEvent(new ol.CollectionEvent(ol.CollectionEventType.REMOVE_AT,
|
||||
undefined, index, prev, this));
|
||||
return prev;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @param {*} elem Element.
|
||||
*/
|
||||
ol.Collection.prototype.setAt = function(index, elem) {
|
||||
var n = this[ol.CollectionProperty.LENGTH];
|
||||
if (index < n) {
|
||||
var prev = this.array_[index];
|
||||
this.array_[index] = elem;
|
||||
this.dispatchEvent(new ol.CollectionEvent(ol.CollectionEventType.SET_AT,
|
||||
elem, index, prev, this));
|
||||
this.dispatchEvent(new ol.CollectionEvent(ol.CollectionEventType.REMOVE,
|
||||
prev, undefined, undefined, this));
|
||||
this.dispatchEvent(new ol.CollectionEvent(ol.CollectionEventType.ADD,
|
||||
elem, undefined, undefined, this));
|
||||
} else {
|
||||
var j;
|
||||
for (j = n; j < index; ++j) {
|
||||
this.insertAt(j, undefined);
|
||||
}
|
||||
this.insertAt(index, elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Collection.prototype.updateLength_ = function() {
|
||||
this.set(ol.CollectionProperty.LENGTH, this.array_.length);
|
||||
};
|
||||
238
src/ol/collection_test.js
Normal file
238
src/ol/collection_test.js
Normal file
@@ -0,0 +1,238 @@
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.CollectionEventType');
|
||||
|
||||
|
||||
function testEmpty() {
|
||||
var collection = new ol.Collection();
|
||||
assertEquals(0, collection.getLength());
|
||||
assertTrue(goog.array.equals(collection.getArray(), []));
|
||||
assertUndefined(collection.getAt(0));
|
||||
}
|
||||
|
||||
|
||||
function testConstruct() {
|
||||
var array = [0, 1, 2];
|
||||
var collection = new ol.Collection(array);
|
||||
assertEquals(0, collection.getAt(0));
|
||||
assertEquals(1, collection.getAt(1));
|
||||
assertEquals(2, collection.getAt(2));
|
||||
}
|
||||
|
||||
|
||||
function testPush() {
|
||||
var collection = new ol.Collection();
|
||||
collection.push(1);
|
||||
assertEquals(1, collection.getLength());
|
||||
assertTrue(goog.array.equals(collection.getArray(), [1]));
|
||||
assertEquals(1, collection.getAt(0));
|
||||
}
|
||||
|
||||
|
||||
function testPushPop() {
|
||||
var collection = new ol.Collection();
|
||||
collection.push(1);
|
||||
collection.pop();
|
||||
assertEquals(0, collection.getLength());
|
||||
assertTrue(goog.array.equals(collection.getArray(), []));
|
||||
assertUndefined(collection.getAt(0));
|
||||
}
|
||||
|
||||
|
||||
function testInsertAt() {
|
||||
var collection = new ol.Collection([0, 2]);
|
||||
collection.insertAt(1, 1);
|
||||
assertEquals(0, collection.getAt(0));
|
||||
assertEquals(1, collection.getAt(1));
|
||||
assertEquals(2, collection.getAt(2));
|
||||
}
|
||||
|
||||
|
||||
function testSetAt() {
|
||||
var collection = new ol.Collection();
|
||||
collection.setAt(1, 1);
|
||||
assertEquals(2, collection.getLength());
|
||||
assertUndefined(collection.getAt(0));
|
||||
assertEquals(1, collection.getAt(1));
|
||||
}
|
||||
|
||||
|
||||
function testRemoveAt() {
|
||||
var collection = new ol.Collection([0, 1, 2]);
|
||||
collection.removeAt(1);
|
||||
assertEquals(0, collection.getAt(0));
|
||||
assertEquals(2, collection.getAt(1));
|
||||
}
|
||||
|
||||
|
||||
function testForEachEmpty() {
|
||||
var collection = new ol.Collection();
|
||||
var forEachCalled = false;
|
||||
collection.forEach(function() {
|
||||
forEachCalled = true;
|
||||
});
|
||||
assertFalse(forEachCalled);
|
||||
}
|
||||
|
||||
|
||||
function testForEachPopulated() {
|
||||
var collection = new ol.Collection();
|
||||
collection.push(1);
|
||||
collection.push(2);
|
||||
var forEachCount = 0;
|
||||
collection.forEach(function() {
|
||||
++forEachCount;
|
||||
});
|
||||
assertEquals(2, forEachCount);
|
||||
}
|
||||
|
||||
|
||||
function testSetAtEvent() {
|
||||
var collection = new ol.Collection(['a', 'b']);
|
||||
var index, prev;
|
||||
goog.events.listen(collection, ol.CollectionEventType.SET_AT, function(e) {
|
||||
index = e.index;
|
||||
prev = e.prev;
|
||||
});
|
||||
collection.setAt(1, 1);
|
||||
assertEquals(1, index);
|
||||
assertEquals('b', prev);
|
||||
}
|
||||
|
||||
|
||||
function testRemoveAtEvent() {
|
||||
var collection = new ol.Collection(['a']);
|
||||
var index, prev;
|
||||
goog.events.listen(
|
||||
collection, ol.CollectionEventType.REMOVE_AT, function(e) {
|
||||
index = e.index;
|
||||
prev = e.prev;
|
||||
});
|
||||
collection.pop();
|
||||
assertEquals(0, index);
|
||||
assertEquals('a', prev);
|
||||
}
|
||||
|
||||
|
||||
function testInsertAtEvent() {
|
||||
var collection = new ol.Collection([0, 2]);
|
||||
var index;
|
||||
goog.events.listen(
|
||||
collection, ol.CollectionEventType.INSERT_AT, function(e) {
|
||||
index = e.index;
|
||||
});
|
||||
collection.insertAt(1, 1);
|
||||
assertEquals(1, index);
|
||||
}
|
||||
|
||||
|
||||
function testSetAtBeyondEnd() {
|
||||
var collection = new ol.Collection();
|
||||
var inserts = [];
|
||||
goog.events.listen(
|
||||
collection, ol.CollectionEventType.INSERT_AT, function(e) {
|
||||
inserts.push(e.index);
|
||||
});
|
||||
collection.setAt(2, 0);
|
||||
assertEquals(3, collection.getLength());
|
||||
assertUndefined(collection.getAt(0));
|
||||
assertUndefined(collection.getAt(1));
|
||||
assertEquals(0, collection.getAt(2));
|
||||
assertEquals(3, inserts.length);
|
||||
assertEquals(0, inserts[0]);
|
||||
assertEquals(1, inserts[1]);
|
||||
assertEquals(2, inserts[2]);
|
||||
}
|
||||
|
||||
|
||||
function testLengthChangeInsertAt() {
|
||||
var collection = new ol.Collection([0, 1, 2]);
|
||||
var lengthEventDispatched;
|
||||
goog.events.listen(collection, 'length_changed', function() {
|
||||
lengthEventDispatched = true;
|
||||
});
|
||||
collection.insertAt(2, 3);
|
||||
assertTrue(lengthEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testLengthChangeRemoveAt() {
|
||||
var collection = new ol.Collection([0, 1, 2]);
|
||||
var lengthEventDispatched;
|
||||
goog.events.listen(collection, 'length_changed', function() {
|
||||
lengthEventDispatched = true;
|
||||
});
|
||||
collection.removeAt(0);
|
||||
assertTrue(lengthEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testLengthChangeSetAt() {
|
||||
var collection = new ol.Collection([0, 1, 2]);
|
||||
var lengthEventDispatched;
|
||||
goog.events.listen(collection, 'length_changed', function() {
|
||||
lengthEventDispatched = true;
|
||||
});
|
||||
collection.setAt(1, 1);
|
||||
assertUndefined(lengthEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testForEach() {
|
||||
var collection = new ol.Collection([1, 2, 4]);
|
||||
var sum = 0;
|
||||
collection.forEach(function(elem) {
|
||||
sum += elem;
|
||||
});
|
||||
assertEquals(7, sum);
|
||||
}
|
||||
|
||||
|
||||
function testForEachScope() {
|
||||
var collection = new ol.Collection([0]);
|
||||
var that;
|
||||
var uniqueObj = {};
|
||||
collection.forEach(function(elem) {
|
||||
that = this;
|
||||
}, uniqueObj);
|
||||
assertTrue(that === uniqueObj);
|
||||
}
|
||||
|
||||
|
||||
function testAddEvent() {
|
||||
var collection = new ol.Collection();
|
||||
var elem;
|
||||
goog.events.listen(collection, ol.CollectionEventType.ADD, function(e) {
|
||||
elem = e.elem;
|
||||
});
|
||||
collection.push(1);
|
||||
assertEquals(1, elem);
|
||||
}
|
||||
|
||||
|
||||
function testAddRemoveEvent() {
|
||||
var collection = new ol.Collection([1]);
|
||||
var addedElem;
|
||||
goog.events.listen(collection, ol.CollectionEventType.ADD, function(e) {
|
||||
addedElem = e.elem;
|
||||
});
|
||||
var removedElem;
|
||||
goog.events.listen(collection, ol.CollectionEventType.REMOVE, function(e) {
|
||||
removedElem = e.elem;
|
||||
});
|
||||
collection.setAt(0, 2);
|
||||
assertEquals(1, removedElem);
|
||||
assertEquals(2, addedElem);
|
||||
}
|
||||
|
||||
|
||||
function testRemove() {
|
||||
var collection = new ol.Collection([1]);
|
||||
var elem;
|
||||
goog.events.listen(collection, ol.CollectionEventType.REMOVE, function(e) {
|
||||
elem = e.elem;
|
||||
});
|
||||
collection.pop();
|
||||
assertEquals(1, elem);
|
||||
}
|
||||
56
src/ol/color.js
Normal file
56
src/ol/color.js
Normal file
@@ -0,0 +1,56 @@
|
||||
goog.provide('ol.Color');
|
||||
|
||||
goog.require('goog.color');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} r Red.
|
||||
* @param {number} g Green.
|
||||
* @param {number} b Blue.
|
||||
* @param {number} a Alpha.
|
||||
*/
|
||||
ol.Color = function(r, g, b, a) {
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.r = r;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.g = g;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.b = b;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a = a;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} str String.
|
||||
* @param {number=} opt_a Alpha.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.Color.createFromString = function(str, opt_a) {
|
||||
var rgb = goog.color.hexToRgb(goog.color.parse(str).hex);
|
||||
var a = opt_a || 255;
|
||||
return new ol.Color(rgb[0], rgb[1], rgb[2], a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Color} Clone.
|
||||
*/
|
||||
ol.Color.prototype.clone = function() {
|
||||
return new ol.Color(this.r, this.g, this.b, this.a);
|
||||
};
|
||||
398
src/ol/control/attribution.js
Normal file
398
src/ol/control/attribution.js
Normal file
@@ -0,0 +1,398 @@
|
||||
// FIXME handle rotation
|
||||
// FIXME handle date line wrap
|
||||
// FIXME handle layer order
|
||||
// FIXME check clean-up code
|
||||
|
||||
goog.provide('ol.control.Attribution');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Control');
|
||||
goog.require('ol.CoverageArea');
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.MapProperty');
|
||||
goog.require('ol.TileCoverageArea');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Control}
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.control.Attribution = function(map) {
|
||||
|
||||
goog.base(this, map);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.ulElement_ = goog.dom.createElement(goog.dom.TagName.UL);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.layersListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, ?number>}
|
||||
*/
|
||||
this.layerVisibleChangeListenerKeys_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, Element>}
|
||||
*/
|
||||
this.attributionElements_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, Array.<ol.CoverageArea>>}
|
||||
*/
|
||||
this.coverageAreass_ = {};
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.CENTER),
|
||||
this.handleMapChanged, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS),
|
||||
this.handleMapLayersChanged, false, this);
|
||||
|
||||
goog.events.listen(map,
|
||||
ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION),
|
||||
this.handleMapChanged, false, this);
|
||||
|
||||
goog.events.listen(map, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
|
||||
this.handleMapChanged, false, this);
|
||||
|
||||
this.handleMapLayersChanged();
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Attribution, ol.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.addLayer = function(layer) {
|
||||
|
||||
var layerKey = goog.getUid(layer);
|
||||
|
||||
this.layerVisibleChangeListenerKeys_[layerKey] = goog.events.listen(
|
||||
layer, ol.Object.getChangedEventType(ol.LayerProperty.VISIBLE),
|
||||
this.handleLayerVisibleChanged, false, this);
|
||||
|
||||
if (layer.getStore().isReady()) {
|
||||
this.createAttributionElementsForLayer_(layer);
|
||||
} else {
|
||||
goog.events.listenOnce(layer, goog.events.EventType.LOAD,
|
||||
this.handleLayerLoad, false, this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.createAttributionElementsForLayer_ =
|
||||
function(layer) {
|
||||
|
||||
var store = layer.getStore();
|
||||
var attributions = store.getAttributions();
|
||||
if (goog.isNull(attributions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = this.getMap();
|
||||
var mapIsDef = map.isDef();
|
||||
var mapExtent = /** @type {ol.Extent} */ map.getExtent();
|
||||
var mapProjection = /** @type {ol.Projection} */ map.getProjection();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
|
||||
var layerVisible = layer.getVisible();
|
||||
|
||||
var attributionVisibilities;
|
||||
if (mapIsDef && layerVisible) {
|
||||
attributionVisibilities = this.getLayerAttributionVisiblities_(
|
||||
layer, mapExtent, mapResolution, mapProjection);
|
||||
} else {
|
||||
attributionVisibilities = null;
|
||||
}
|
||||
|
||||
goog.array.forEach(attributions, function(attribution) {
|
||||
|
||||
var attributionKey = goog.getUid(attribution);
|
||||
|
||||
var attributionElement = goog.dom.createElement(goog.dom.TagName.LI);
|
||||
attributionElement.innerHTML = attribution.getHtml();
|
||||
|
||||
if (!map.isDef ||
|
||||
!layerVisible ||
|
||||
goog.isNull(attributionVisibilities) ||
|
||||
!attributionVisibilities[attributionKey]) {
|
||||
goog.style.showElement(attributionElement, false);
|
||||
}
|
||||
|
||||
goog.dom.appendChild(this.ulElement_, attributionElement);
|
||||
|
||||
this.attributionElements_[attributionKey] = attributionElement;
|
||||
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.control.Attribution.prototype.getElement = function() {
|
||||
return this.ulElement_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @param {ol.Extent} mapExtent Map extent.
|
||||
* @param {number} mapResolution Map resolution.
|
||||
* @param {ol.Projection} mapProjection Map projection.
|
||||
* @return {Object.<number, boolean>} Attribution visibilities.
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.getLayerAttributionVisiblities_ =
|
||||
function(layer, mapExtent, mapResolution, mapProjection) {
|
||||
|
||||
var store = layer.getStore();
|
||||
var attributions = store.getAttributions();
|
||||
|
||||
if (goog.isNull(attributions)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var mapZ;
|
||||
if (store instanceof ol.TileStore) {
|
||||
var tileStore = /** @type {ol.TileStore} */ store;
|
||||
var tileGrid = tileStore.getTileGrid();
|
||||
mapZ = tileGrid.getZForResolution(mapResolution);
|
||||
}
|
||||
|
||||
var attributionVisibilities = {};
|
||||
goog.array.forEach(attributions, function(attribution) {
|
||||
|
||||
var attributionKey = goog.getUid(attribution);
|
||||
|
||||
var attributionVisible = true;
|
||||
|
||||
var coverageAreas;
|
||||
if (attributionKey in this.coverageAreass_) {
|
||||
coverageAreas = this.coverageAreass_[attributionKey];
|
||||
} else {
|
||||
var attributionProjection = attribution.getProjection();
|
||||
coverageAreas = attribution.getCoverageAreas();
|
||||
if (!goog.isNull(coverageAreas) &&
|
||||
!ol.Projection.equivalent(attributionProjection, mapProjection)) {
|
||||
var transformFn = ol.Projection.getTransform(
|
||||
attributionProjection, mapProjection);
|
||||
if (transformFn !== ol.Projection.cloneTransform) {
|
||||
coverageAreas = goog.array.map(coverageAreas, function(coverageArea) {
|
||||
return coverageArea.transform(transformFn);
|
||||
});
|
||||
}
|
||||
}
|
||||
this.coverageAreass_[attributionKey] = coverageAreas;
|
||||
}
|
||||
|
||||
if (!goog.isNull(coverageAreas)) {
|
||||
if (store instanceof ol.TileStore) {
|
||||
attributionVisible = goog.array.some(
|
||||
coverageAreas,
|
||||
/**
|
||||
* @param {ol.TileCoverageArea} tileCoverageArea
|
||||
* Tile coverage area.
|
||||
*/
|
||||
function(tileCoverageArea) {
|
||||
goog.asserts.assert(
|
||||
tileCoverageArea instanceof ol.TileCoverageArea);
|
||||
return tileCoverageArea.intersectsExtentAndZ(mapExtent, mapZ);
|
||||
});
|
||||
} else {
|
||||
attributionVisible = goog.array.some(
|
||||
coverageAreas,
|
||||
function(coverageArea) {
|
||||
return coverageArea.intersectsExtentAndResolution(
|
||||
mapExtent, mapResolution);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
attributionVisibilities[attributionKey] = attributionVisible;
|
||||
|
||||
}, this);
|
||||
|
||||
return attributionVisibilities;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleLayerLoad = function(event) {
|
||||
var layer = /** @type {ol.Layer} */ event.target;
|
||||
this.createAttributionElementsForLayer_(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleLayerVisibleChanged = function(event) {
|
||||
|
||||
var map = this.getMap();
|
||||
var mapIsDef = map.isDef();
|
||||
var mapExtent = /** @type {ol.Extent} */ map.getExtent();
|
||||
var mapProjection = /** @type {ol.Projection} */ map.getProjection();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
|
||||
var layer = /** @type {ol.Layer} */ event.target;
|
||||
|
||||
this.updateLayerAttributionsVisibility_(
|
||||
layer, mapIsDef, mapExtent, mapResolution, mapProjection);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleLayersAdd = function(collectionEvent) {
|
||||
var layer = /** @type {ol.Layer} */ collectionEvent.elem;
|
||||
this.addLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleLayersRemove =
|
||||
function(collectionEvent) {
|
||||
var layer = /** @type {ol.Layer} */ collectionEvent.elem;
|
||||
this.removeLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleMapChanged = function() {
|
||||
|
||||
var map = this.getMap();
|
||||
var mapIsDef = map.isDef();
|
||||
var mapExtent = /** @type {ol.Extent} */ map.getExtent();
|
||||
var mapProjection = /** @type {ol.Projection} */ map.getProjection();
|
||||
var mapResolution = map.getResolution();
|
||||
|
||||
var layers = map.getLayers();
|
||||
layers.forEach(function(layer) {
|
||||
this.updateLayerAttributionsVisibility_(
|
||||
layer, mapIsDef, mapExtent, mapResolution, mapProjection);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleMapLayersChanged = function() {
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
this.layersListenerKeys_ = null;
|
||||
}
|
||||
goog.object.forEach(this.attributionElements_, function(attributionElement) {
|
||||
goog.dom.removeNode(attributionElement);
|
||||
}, this);
|
||||
this.attributionElements_ = {};
|
||||
this.coverageAreass_ = {};
|
||||
var map = this.getMap();
|
||||
var layers = map.getLayers();
|
||||
if (goog.isDefAndNotNull(layers)) {
|
||||
layers.forEach(this.addLayer, this);
|
||||
this.layersListenerKeys_ = [
|
||||
goog.events.listen(layers, ol.CollectionEventType.ADD,
|
||||
this.handleLayersAdd, false, this),
|
||||
goog.events.listen(layers, ol.CollectionEventType.REMOVE,
|
||||
this.handleLayersRemove, false, this)
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.Attribution.prototype.removeLayer = function(layer) {
|
||||
|
||||
var layerKey = goog.getUid(layer);
|
||||
|
||||
goog.events.unlistenByKey(this.layerVisibleChangeListenerKeys_[layerKey]);
|
||||
delete this.layerVisibleChangeListenerKeys_[layerKey];
|
||||
|
||||
goog.array.forEach(layer.getStore().getAttributions(), function(attribution) {
|
||||
var attributionKey = goog.getUid(attribution);
|
||||
delete this.coverageAreass_[attributionKey];
|
||||
var attributionElement = this.attributionElements_[attributionKey];
|
||||
goog.dom.removeNode(attributionElement);
|
||||
delete this.attributionElements_[attributionKey];
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @param {boolean} mapIsDef Map is defined.
|
||||
* @param {ol.Extent} mapExtent Map extent.
|
||||
* @param {number} mapResolution Map resolution.
|
||||
* @param {ol.Projection} mapProjection Map projection.
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.updateLayerAttributionsVisibility_ =
|
||||
function(layer, mapIsDef, mapExtent, mapResolution, mapProjection) {
|
||||
if (mapIsDef && layer.getVisible()) {
|
||||
var attributionVisibilities = this.getLayerAttributionVisiblities_(
|
||||
layer, mapExtent, mapResolution, mapProjection);
|
||||
goog.object.forEach(
|
||||
attributionVisibilities,
|
||||
function(attributionVisible, attributionKey) {
|
||||
var attributionElement = this.attributionElements_[attributionKey];
|
||||
goog.style.showElement(attributionElement, attributionVisible);
|
||||
},
|
||||
this);
|
||||
} else {
|
||||
var store = layer.getStore();
|
||||
var attributions = store.getAttributions();
|
||||
if (!goog.isNull(attributions)) {
|
||||
goog.array.forEach(attributions, function(attribution) {
|
||||
var attributionKey = goog.getUid(attribution);
|
||||
var attributionElement = this.attributionElements_[attributionKey];
|
||||
goog.style.showElement(attributionElement, false);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
33
src/ol/control/control.js
Normal file
33
src/ol/control/control.js
Normal file
@@ -0,0 +1,33 @@
|
||||
goog.provide('ol.Control');
|
||||
|
||||
goog.require('ol.Map');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.Control = function(map) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Element.
|
||||
*/
|
||||
ol.Control.prototype.getElement = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.Control.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
128
src/ol/control/mouseposition.js
Normal file
128
src/ol/control/mouseposition.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// FIXME should listen on appropriate pane, once it is defined
|
||||
|
||||
goog.provide('ol.control.MousePosition');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.Control');
|
||||
goog.require('ol.MapProperty');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.TransformFunction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Control}
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {ol.Projection=} opt_projection Projection.
|
||||
* @param {ol.CoordinateFormatType=} opt_coordinateFormat Coordinate format.
|
||||
* @param {string=} opt_undefinedHTML Undefined HTML.
|
||||
*/
|
||||
ol.control.MousePosition =
|
||||
function(map, opt_projection, opt_coordinateFormat, opt_undefinedHTML) {
|
||||
|
||||
goog.base(this, map);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.divElement_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Projection}
|
||||
*/
|
||||
this.projection_ = opt_projection || null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.CoordinateFormatType|undefined}
|
||||
*/
|
||||
this.coordinateFormat_ = opt_coordinateFormat;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.undefinedHTML_ = opt_undefinedHTML || '';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TransformFunction}
|
||||
*/
|
||||
this.transform_ = ol.Projection.identityTransform;
|
||||
|
||||
goog.events.listen(map,
|
||||
ol.Object.getChangedEventType(ol.MapProperty.PROJECTION),
|
||||
this.handleMapProjectionChanged, false, this);
|
||||
|
||||
goog.events.listen(map.getViewport(), goog.events.EventType.MOUSEMOVE,
|
||||
this.handleMouseMove, false, this);
|
||||
|
||||
goog.events.listen(map.getViewport(), goog.events.EventType.MOUSEOUT,
|
||||
this.handleMouseOut, false, this);
|
||||
|
||||
this.handleMapProjectionChanged();
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.MousePosition, ol.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.control.MousePosition.prototype.getElement = function() {
|
||||
return this.divElement_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleMapProjectionChanged = function() {
|
||||
var map = this.getMap();
|
||||
var mapProjection = map.getProjection();
|
||||
if (!goog.isDef(mapProjection) || goog.isNull(this.projection_)) {
|
||||
this.transform_ = ol.Projection.identityTransform;
|
||||
} else {
|
||||
this.transform_ =
|
||||
ol.Projection.getTransform(mapProjection, this.projection_);
|
||||
}
|
||||
// FIXME should we instead re-calculate using the last known mouse position?
|
||||
this.divElement_.innerHTML = this.undefinedHTML_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleMouseMove = function(browserEvent) {
|
||||
var map = this.getMap();
|
||||
var pixel = new ol.Pixel(browserEvent.offsetX, browserEvent.offsetY);
|
||||
var coordinate = map.getCoordinateFromPixel(pixel);
|
||||
var html;
|
||||
if (goog.isDef(coordinate)) {
|
||||
coordinate = this.transform_(coordinate);
|
||||
if (goog.isDef(this.coordinateFormat_)) {
|
||||
html = this.coordinateFormat_(coordinate);
|
||||
} else {
|
||||
html = coordinate.toString();
|
||||
}
|
||||
} else {
|
||||
html = this.undefinedHTML_;
|
||||
}
|
||||
this.divElement_.innerHTML = html;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleMouseOut = function(browserEvent) {
|
||||
this.divElement_.innerHTML = this.undefinedHTML_;
|
||||
};
|
||||
31
src/ol/coordinate.js
Normal file
31
src/ol/coordinate.js
Normal file
@@ -0,0 +1,31 @@
|
||||
goog.provide('ol.Coordinate');
|
||||
|
||||
goog.require('goog.math.Vec2');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.math.Vec2}
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
ol.Coordinate = function(x, y) {
|
||||
goog.base(this, x, y);
|
||||
};
|
||||
goog.inherits(ol.Coordinate, goog.math.Vec2);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
ol.Coordinate.ZERO = new ol.Coordinate(0, 0);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Clone.
|
||||
*/
|
||||
ol.Coordinate.prototype.clone = function() {
|
||||
return new ol.Coordinate(this.x, this.y);
|
||||
};
|
||||
57
src/ol/coordinateformat.js
Normal file
57
src/ol/coordinateformat.js
Normal file
@@ -0,0 +1,57 @@
|
||||
goog.provide('ol.CoordinateFormat');
|
||||
goog.provide('ol.CoordinateFormatType');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function((ol.Coordinate|undefined)): string}
|
||||
*/
|
||||
ol.CoordinateFormatType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} precision Precision.
|
||||
* @return {ol.CoordinateFormatType} Coordinate format.
|
||||
*/
|
||||
ol.CoordinateFormat.createXY = function(precision) {
|
||||
return function(coordinate) {
|
||||
if (goog.isDef(coordinate)) {
|
||||
return coordinate.x.toFixed(precision) + ', ' +
|
||||
coordinate.y.toFixed(precision);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} degrees Degrees.
|
||||
* @param {string} hemispheres Hemispheres.
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.CoordinateFormat.degreesToHDMS_ = function(degrees, hemispheres) {
|
||||
var normalizedDegrees = goog.math.modulo(degrees + 180, 360) - 180;
|
||||
var x = Math.abs(Math.round(3600 * normalizedDegrees));
|
||||
return Math.floor(x / 3600) + '\u00b0 ' +
|
||||
Math.floor((x / 60) % 60) + '\u2032 ' +
|
||||
Math.floor(x % 60) + '\u2033 ' +
|
||||
hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} coordinate Coordinate.
|
||||
* @return {string} Coordinate format.
|
||||
*/
|
||||
ol.CoordinateFormat.hdms = function(coordinate) {
|
||||
if (goog.isDef(coordinate)) {
|
||||
return ol.CoordinateFormat.degreesToHDMS_(coordinate.y, 'NS') + ' ' +
|
||||
ol.CoordinateFormat.degreesToHDMS_(coordinate.x, 'EW');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
45
src/ol/coveragearea.js
Normal file
45
src/ol/coveragearea.js
Normal file
@@ -0,0 +1,45 @@
|
||||
goog.provide('ol.CoverageArea');
|
||||
|
||||
goog.require('ol.Extent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.CoverageArea = function(extent) {
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.extent = extent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
ol.CoverageArea.prototype.intersectsExtent = function(extent) {
|
||||
return this.extent.intersects(extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
ol.CoverageArea.prototype.intersectsExtentAndResolution = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TransformFunction} transformFn Transform.
|
||||
* @return {ol.CoverageArea} Transformed coverage area.
|
||||
*/
|
||||
ol.CoverageArea.prototype.transform = function(transformFn) {
|
||||
var extent = this.extent.transform(transformFn);
|
||||
return new ol.CoverageArea(extent);
|
||||
};
|
||||
153
src/ol/createmap.js
Normal file
153
src/ol/createmap.js
Normal file
@@ -0,0 +1,153 @@
|
||||
goog.provide('ol.RendererHint');
|
||||
goog.provide('ol.createMap');
|
||||
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapProperty');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.interaction.AltDragRotate');
|
||||
goog.require('ol.interaction.CenterConstraint');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
goog.require('ol.interaction.DblClickZoom');
|
||||
goog.require('ol.interaction.DragPan');
|
||||
goog.require('ol.interaction.KeyboardPan');
|
||||
goog.require('ol.interaction.KeyboardZoom');
|
||||
goog.require('ol.interaction.MouseWheelZoom');
|
||||
goog.require('ol.interaction.ResolutionConstraint');
|
||||
goog.require('ol.interaction.RotationConstraint');
|
||||
goog.require('ol.interaction.ShiftDragZoom');
|
||||
goog.require('ol.renderer.dom');
|
||||
goog.require('ol.renderer.dom.Map');
|
||||
goog.require('ol.renderer.webgl');
|
||||
goog.require('ol.renderer.webgl.Map');
|
||||
|
||||
|
||||
/**
|
||||
* @define {string} Default projection code.
|
||||
*/
|
||||
ol.DEFAULT_PROJECTION_CODE = 'EPSG:3857';
|
||||
|
||||
|
||||
/**
|
||||
* @define {string} Default user projection code.
|
||||
*/
|
||||
ol.DEFAULT_USER_PROJECTION_CODE = 'EPSG:4326';
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable DOM.
|
||||
*/
|
||||
ol.ENABLE_DOM = true;
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable WebGL.
|
||||
*/
|
||||
ol.ENABLE_WEBGL = true;
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.RendererHint = {
|
||||
DOM: 'dom',
|
||||
WEBGL: 'webgl'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.RendererHint>}
|
||||
*/
|
||||
ol.DEFAULT_RENDERER_HINT = [
|
||||
ol.RendererHint.WEBGL,
|
||||
ol.RendererHint.DOM
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} target Target.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
* @param {ol.RendererHint|Array.<ol.RendererHint>=} opt_rendererHints
|
||||
* Renderer hints.
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.createMap = function(target, opt_values, opt_rendererHints) {
|
||||
|
||||
var values = {};
|
||||
if (goog.isDef(opt_values)) {
|
||||
goog.object.extend(values, opt_values);
|
||||
}
|
||||
|
||||
// FIXME this should be a configuration option
|
||||
var centerConstraint = ol.interaction.CenterConstraint.snapToPixel;
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower(
|
||||
Math.exp(Math.log(2) / 8), ol.Projection.EPSG_3857_HALF_SIZE / 128);
|
||||
var rotationConstraint = ol.interaction.RotationConstraint.none;
|
||||
var constraints = new ol.interaction.Constraints(
|
||||
centerConstraint, resolutionConstraint, rotationConstraint);
|
||||
|
||||
if (!goog.object.containsKey(values, ol.MapProperty.INTERACTIONS)) {
|
||||
var interactions = new ol.Collection();
|
||||
interactions.push(new ol.interaction.AltDragRotate(constraints));
|
||||
interactions.push(new ol.interaction.DblClickZoom(constraints));
|
||||
interactions.push(new ol.interaction.DragPan(constraints));
|
||||
interactions.push(new ol.interaction.KeyboardPan(constraints, 16));
|
||||
interactions.push(new ol.interaction.KeyboardZoom(constraints));
|
||||
interactions.push(new ol.interaction.MouseWheelZoom(constraints));
|
||||
interactions.push(new ol.interaction.ShiftDragZoom(constraints));
|
||||
values[ol.MapProperty.INTERACTIONS] = interactions;
|
||||
}
|
||||
|
||||
if (!goog.object.containsKey(values, ol.MapProperty.LAYERS)) {
|
||||
values[ol.MapProperty.LAYERS] = new ol.Collection();
|
||||
}
|
||||
|
||||
if (!goog.object.containsKey(values, ol.MapProperty.PROJECTION)) {
|
||||
values[ol.MapProperty.PROJECTION] =
|
||||
ol.Projection.getFromCode(ol.DEFAULT_PROJECTION_CODE);
|
||||
}
|
||||
|
||||
if (!goog.object.containsKey(values, ol.MapProperty.USER_PROJECTION)) {
|
||||
values[ol.MapProperty.USER_PROJECTION] =
|
||||
ol.Projection.getFromCode(ol.DEFAULT_USER_PROJECTION_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.RendererHint>}
|
||||
*/
|
||||
var rendererHints;
|
||||
if (goog.isDef(opt_rendererHints)) {
|
||||
if (goog.isArray(opt_rendererHints)) {
|
||||
rendererHints = opt_rendererHints;
|
||||
} else {
|
||||
rendererHints = [opt_rendererHints];
|
||||
}
|
||||
} else {
|
||||
rendererHints = ol.DEFAULT_RENDERER_HINT;
|
||||
}
|
||||
|
||||
var i, rendererHint, rendererConstructor;
|
||||
for (i = 0; i < rendererHints.length; ++i) {
|
||||
rendererHint = rendererHints[i];
|
||||
if (rendererHint == ol.RendererHint.DOM) {
|
||||
if (ol.ENABLE_DOM && ol.renderer.dom.isSupported()) {
|
||||
rendererConstructor = ol.renderer.dom.Map;
|
||||
break;
|
||||
}
|
||||
} else if (rendererHint == ol.RendererHint.WEBGL) {
|
||||
if (ol.ENABLE_WEBGL && ol.renderer.webgl.isSupported()) {
|
||||
rendererConstructor = ol.renderer.webgl.Map;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (goog.isDef(rendererConstructor)) {
|
||||
return new ol.Map(target, rendererConstructor, values);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
59
src/ol/extent.js
Normal file
59
src/ol/extent.js
Normal file
@@ -0,0 +1,59 @@
|
||||
goog.provide('ol.Extent');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Rectangle');
|
||||
goog.require('ol.TransformFunction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Rectangle}
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
*/
|
||||
ol.Extent = function(minX, minY, maxX, maxY) {
|
||||
goog.base(this, minX, minY, maxX, maxY);
|
||||
};
|
||||
goog.inherits(ol.Extent, ol.Rectangle);
|
||||
|
||||
|
||||
/**
|
||||
* @param {...ol.Coordinate} var_args Coordinates.
|
||||
* @return {!ol.Extent} Bounding extent.
|
||||
*/
|
||||
ol.Extent.boundingExtent = function(var_args) {
|
||||
var coordinate0 = arguments[0];
|
||||
var extent = new ol.Extent(coordinate0.x, coordinate0.y,
|
||||
coordinate0.x, coordinate0.y);
|
||||
var i;
|
||||
for (i = 1; i < arguments.length; ++i) {
|
||||
var coordinate = arguments[i];
|
||||
extent.minX = Math.min(extent.minX, coordinate.x);
|
||||
extent.minY = Math.min(extent.minY, coordinate.y);
|
||||
extent.maxX = Math.max(extent.maxX, coordinate.x);
|
||||
extent.maxY = Math.max(extent.maxY, coordinate.y);
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.Extent.prototype.clone = function() {
|
||||
return new ol.Extent(this.minX, this.minY, this.maxX, this.maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TransformFunction} transformFn Transform function.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.Extent.prototype.transform = function(transformFn) {
|
||||
var min = transformFn(new ol.Coordinate(this.minX, this.minY));
|
||||
var max = transformFn(new ol.Coordinate(this.maxX, this.maxY));
|
||||
return new ol.Extent(min.x, min.y, max.x, max.y);
|
||||
};
|
||||
29
src/ol/extent_test.js
Normal file
29
src/ol/extent_test.js
Normal file
@@ -0,0 +1,29 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Projection');
|
||||
|
||||
|
||||
function testClone() {
|
||||
var extent = new ol.Extent(1, 2, 3, 4);
|
||||
var clonedExtent = extent.clone();
|
||||
assertTrue(clonedExtent instanceof ol.Extent);
|
||||
assertFalse(clonedExtent === extent);
|
||||
assertEquals(extent.minX, clonedExtent.minX);
|
||||
assertEquals(extent.minY, clonedExtent.minY);
|
||||
assertEquals(extent.maxX, clonedExtent.maxX);
|
||||
assertEquals(extent.maxY, clonedExtent.maxY);
|
||||
}
|
||||
|
||||
|
||||
function testTransform() {
|
||||
var transformFn =
|
||||
ol.Projection.getTransformFromCodes('EPSG:4326', 'EPSG:3857');
|
||||
var sourceExtent = new ol.Extent(-15, -30, 45, 60);
|
||||
var destinationExtent = sourceExtent.transform(transformFn);
|
||||
assertNotNullNorUndefined(destinationExtent);
|
||||
// FIXME check values with third-party tool
|
||||
assertRoughlyEquals(-1669792.3618991037, destinationExtent.minX, 1e-9);
|
||||
assertRoughlyEquals(-3503549.843504376, destinationExtent.minY, 1e-9);
|
||||
assertRoughlyEquals(5009377.085697311, destinationExtent.maxX, 1e-9);
|
||||
assertRoughlyEquals(8399737.889818361, destinationExtent.maxY, 1e-9);
|
||||
}
|
||||
60
src/ol/interaction/altdragrotate.js
Normal file
60
src/ol/interaction/altdragrotate.js
Normal file
@@ -0,0 +1,60 @@
|
||||
goog.provide('ol.interaction.AltDragRotate');
|
||||
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Drag');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.AltDragRotate = function(constraints) {
|
||||
|
||||
goog.base(this, constraints);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.startRotation_ = 0;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.AltDragRotate, ol.interaction.Drag);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.AltDragRotate.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
var map = mapBrowserEvent.map;
|
||||
var size = map.getSize();
|
||||
var theta = Math.atan2(
|
||||
size.height / 2 - browserEvent.offsetY,
|
||||
browserEvent.offsetX - size.width / 2);
|
||||
this.rotate(map, this.startRotation_, -theta);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.AltDragRotate.prototype.handleDragStart =
|
||||
function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
var map = mapBrowserEvent.map;
|
||||
if (browserEvent.isMouseActionButton() && browserEvent.altKey &&
|
||||
map.canRotate()) {
|
||||
var size = map.getSize();
|
||||
var theta = Math.atan2(
|
||||
size.height / 2 - browserEvent.offsetY,
|
||||
browserEvent.offsetX - size.width / 2);
|
||||
this.startRotation_ = (map.getRotation() || 0) + theta;
|
||||
browserEvent.preventDefault();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
47
src/ol/interaction/centerconstraint.js
Normal file
47
src/ol/interaction/centerconstraint.js
Normal file
@@ -0,0 +1,47 @@
|
||||
goog.provide('ol.interaction.CenterConstraint');
|
||||
goog.provide('ol.interaction.CenterConstraintType');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function((ol.Coordinate|undefined),
|
||||
* (number|undefined),
|
||||
* ol.Coordinate): (ol.Coordinate|undefined)}
|
||||
*/
|
||||
ol.interaction.CenterConstraintType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} center Center.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {ol.Coordinate} delta Delta.
|
||||
* @return {ol.Coordinate|undefined} Center.
|
||||
*/
|
||||
ol.interaction.CenterConstraint.none = function(center, resolution, delta) {
|
||||
if (goog.isDefAndNotNull(center) && goog.isDef(resolution)) {
|
||||
var x = center.x + delta.x;
|
||||
var y = center.y + delta.y;
|
||||
return new ol.Coordinate(x, y);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} center Center.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {ol.Coordinate} delta Delta.
|
||||
* @return {ol.Coordinate|undefined} Center.
|
||||
*/
|
||||
ol.interaction.CenterConstraint.snapToPixel =
|
||||
function(center, resolution, delta) {
|
||||
if (goog.isDefAndNotNull(center) && goog.isDef(resolution)) {
|
||||
var x = Math.floor((center.x + delta.x) / resolution + 0.5) * resolution;
|
||||
var y = Math.floor((center.y + delta.y) / resolution + 0.5) * resolution;
|
||||
return new ol.Coordinate(x, y);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
36
src/ol/interaction/constraints.js
Normal file
36
src/ol/interaction/constraints.js
Normal file
@@ -0,0 +1,36 @@
|
||||
goog.provide('ol.interaction.Constraints');
|
||||
|
||||
goog.require('ol.interaction.CenterConstraintType');
|
||||
goog.require('ol.interaction.ResolutionConstraintType');
|
||||
goog.require('ol.interaction.RotationConstraintType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.interaction.CenterConstraintType} centerConstraint
|
||||
* Center constraint.
|
||||
* @param {ol.interaction.ResolutionConstraintType} resolutionConstraint
|
||||
* Resolution constraint.
|
||||
* @param {ol.interaction.RotationConstraintType} rotationConstraint
|
||||
* Rotation constraint.
|
||||
*/
|
||||
ol.interaction.Constraints =
|
||||
function(centerConstraint, resolutionConstraint, rotationConstraint) {
|
||||
|
||||
/**
|
||||
* @type {ol.interaction.CenterConstraintType}
|
||||
*/
|
||||
this.center = centerConstraint;
|
||||
|
||||
/**
|
||||
* @type {ol.interaction.ResolutionConstraintType}
|
||||
*/
|
||||
this.resolution = resolutionConstraint;
|
||||
|
||||
/**
|
||||
* @type {ol.interaction.RotationConstraintType}
|
||||
*/
|
||||
this.rotation = rotationConstraint;
|
||||
|
||||
};
|
||||
36
src/ol/interaction/dblclickzoom.js
Normal file
36
src/ol/interaction/dblclickzoom.js
Normal file
@@ -0,0 +1,36 @@
|
||||
goog.provide('ol.interaction.DblClickZoom');
|
||||
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.Interaction');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.DblClickZoom = function(constraints) {
|
||||
goog.base(this, constraints);
|
||||
};
|
||||
goog.inherits(ol.interaction.DblClickZoom, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DblClickZoom.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (browserEvent.type == goog.events.EventType.DBLCLICK &&
|
||||
browserEvent.isMouseActionButton()) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var resolution = map.getResolution();
|
||||
var delta = mapBrowserEvent.browserEvent.shiftKey ? -1 : 1;
|
||||
var anchor = mapBrowserEvent.getCoordinate();
|
||||
this.zoom(map, resolution, delta, anchor);
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
};
|
||||
122
src/ol/interaction/drag.js
Normal file
122
src/ol/interaction/drag.js
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
goog.provide('ol.interaction.Drag');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Interaction');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.Drag = function(constraints) {
|
||||
|
||||
goog.base(this, constraints);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.dragging_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.startX = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.startY = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.offsetX = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.offsetY = 0;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.startCenter = null;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.startCoordinate = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Drag, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDrag = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDragEnd = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDragStart = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (this.dragging_) {
|
||||
if (mapBrowserEvent.type == goog.fx.Dragger.EventType.DRAG) {
|
||||
goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent);
|
||||
this.deltaX = browserEvent.clientX - this.startX;
|
||||
this.deltaY = browserEvent.clientY - this.startY;
|
||||
this.handleDrag(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type == goog.fx.Dragger.EventType.END) {
|
||||
goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent);
|
||||
this.deltaX = browserEvent.clientX - this.startX;
|
||||
this.deltaY = browserEvent.clientY - this.startY;
|
||||
this.handleDragEnd(mapBrowserEvent);
|
||||
this.dragging_ = false;
|
||||
}
|
||||
} else if (mapBrowserEvent.type == goog.fx.Dragger.EventType.START) {
|
||||
goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent);
|
||||
this.startX = browserEvent.clientX;
|
||||
this.startY = browserEvent.clientY;
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.startCenter = /** @type {!ol.Coordinate} */ map.getCenter();
|
||||
this.startCoordinate = /** @type {ol.Coordinate} */
|
||||
mapBrowserEvent.getCoordinate();
|
||||
if (this.handleDragStart(mapBrowserEvent)) {
|
||||
this.dragging_ = true;
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
48
src/ol/interaction/dragpan.js
Normal file
48
src/ol/interaction/dragpan.js
Normal file
@@ -0,0 +1,48 @@
|
||||
goog.provide('ol.interaction.DragPan');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
goog.require('ol.interaction.Drag');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.DragPan = function(constraints) {
|
||||
goog.base(this, constraints);
|
||||
};
|
||||
goog.inherits(ol.interaction.DragPan, ol.interaction.Drag);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var resolution = map.getResolution();
|
||||
var rotation = map.getRotation();
|
||||
var delta =
|
||||
new ol.Coordinate(-resolution * this.deltaX, resolution * this.deltaY);
|
||||
if (map.canRotate() && goog.isDef(rotation)) {
|
||||
delta.rotate(rotation);
|
||||
}
|
||||
this.pan(map, delta, this.startCenter);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (!browserEvent.shiftKey) {
|
||||
browserEvent.preventDefault();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
107
src/ol/interaction/interaction.js
Normal file
107
src/ol/interaction/interaction.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// FIXME factor out key precondition (shift et. al)
|
||||
|
||||
goog.provide('ol.Interaction');
|
||||
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.Interaction = function(constraints) {
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.interaction.Constraints}
|
||||
*/
|
||||
this.constraints = constraints;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.Interaction.prototype.fitExtent = function(map, extent) {
|
||||
var resolution = map.getResolutionForExtent(extent);
|
||||
resolution = this.constraints.resolution(resolution, 0);
|
||||
var center = extent.getCenter();
|
||||
center = this.constraints.center(center, resolution, ol.Coordinate.ZERO);
|
||||
map.withFrozenRendering(function() {
|
||||
map.setCenter(center);
|
||||
map.setResolution(resolution);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
*/
|
||||
ol.Interaction.prototype.handleMapBrowserEvent = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {ol.Coordinate} delta Delta.
|
||||
* @param {ol.Coordinate=} opt_anchor Anchor.
|
||||
*/
|
||||
ol.Interaction.prototype.pan = function(map, delta, opt_anchor) {
|
||||
var center = opt_anchor ? opt_anchor : map.getCenter();
|
||||
var resolution = map.getResolution();
|
||||
center = this.constraints.center(center, resolution, delta);
|
||||
map.setCenter(center);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {number|undefined} rotation Rotation.
|
||||
* @param {number} delta Delta.
|
||||
* @param {ol.Coordinate=} opt_anchor Anchor.
|
||||
*/
|
||||
ol.Interaction.prototype.rotate = function(map, rotation, delta, opt_anchor) {
|
||||
// FIXME handle rotation about anchor
|
||||
rotation = this.constraints.rotation(rotation, delta);
|
||||
map.setRotation(rotation);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
*/
|
||||
ol.Interaction.prototype.setResolution = function(map, resolution) {
|
||||
resolution = this.constraints.resolution(resolution, 0);
|
||||
map.setResolution(resolution);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {number} delta Delta.
|
||||
* @param {ol.Coordinate=} opt_anchor Anchor.
|
||||
*/
|
||||
ol.Interaction.prototype.zoom = function(map, resolution, delta, opt_anchor) {
|
||||
if (goog.isDefAndNotNull(opt_anchor)) {
|
||||
var anchor = opt_anchor;
|
||||
var mapCenter = /** @type {!ol.Coordinate} */ map.getCenter();
|
||||
var mapResolution = map.getResolution();
|
||||
resolution = this.constraints.resolution(resolution, delta);
|
||||
var x = anchor.x - resolution * (anchor.x - mapCenter.x) / mapResolution;
|
||||
var y = anchor.y - resolution * (anchor.y - mapCenter.y) / mapResolution;
|
||||
var center = new ol.Coordinate(x, y);
|
||||
center = this.constraints.center(center, resolution, ol.Coordinate.ZERO);
|
||||
map.withFrozenRendering(function() {
|
||||
map.setCenter(center);
|
||||
map.setResolution(resolution);
|
||||
});
|
||||
} else {
|
||||
resolution = this.constraints.resolution(resolution, delta);
|
||||
map.setResolution(resolution);
|
||||
}
|
||||
};
|
||||
53
src/ol/interaction/keyboard.js
Normal file
53
src/ol/interaction/keyboard.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// FIXME this class is ugly and should be removed
|
||||
|
||||
goog.provide('ol.interaction.Keyboard');
|
||||
|
||||
goog.require('ol.Interaction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
*/
|
||||
ol.interaction.Keyboard = function() {
|
||||
|
||||
goog.base(this, null);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, Function>}
|
||||
*/
|
||||
this.charCodeCallbacks_ = {};
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Keyboard, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @param {Function} callback Callback.
|
||||
*/
|
||||
ol.interaction.Keyboard.prototype.addCallback = function(s, callback) {
|
||||
var i;
|
||||
for (i = 0; i < s.length; ++i) {
|
||||
this.charCodeCallbacks_[s.charCodeAt(i)] = callback;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Keyboard.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
|
||||
var keyEvent = /** @type {goog.events.KeyEvent} */
|
||||
mapBrowserEvent.browserEvent;
|
||||
var callback = this.charCodeCallbacks_[keyEvent.charCode];
|
||||
if (callback) {
|
||||
callback();
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
62
src/ol/interaction/keyboardpan.js
Normal file
62
src/ol/interaction/keyboardpan.js
Normal file
@@ -0,0 +1,62 @@
|
||||
goog.provide('ol.interaction.KeyboardPan');
|
||||
|
||||
goog.require('goog.events.KeyCodes');
|
||||
goog.require('goog.events.KeyHandler.EventType');
|
||||
goog.require('ol.Interaction');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
* @param {number} pixelDelta Pixel delta.
|
||||
*/
|
||||
ol.interaction.KeyboardPan = function(constraints, pixelDelta) {
|
||||
|
||||
goog.base(this, constraints);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.pixelDelta_ = pixelDelta;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.KeyboardPan, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
|
||||
var keyEvent = /** @type {goog.events.KeyEvent} */
|
||||
mapBrowserEvent.browserEvent;
|
||||
var keyCode = keyEvent.keyCode;
|
||||
if (keyCode == goog.events.KeyCodes.DOWN ||
|
||||
keyCode == goog.events.KeyCodes.LEFT ||
|
||||
keyCode == goog.events.KeyCodes.RIGHT ||
|
||||
keyCode == goog.events.KeyCodes.UP) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var resolution = map.getResolution();
|
||||
var delta;
|
||||
var mapUnitsDelta = resolution * this.pixelDelta_;
|
||||
if (keyCode == goog.events.KeyCodes.DOWN) {
|
||||
delta = new ol.Coordinate(0, -mapUnitsDelta);
|
||||
} else if (keyCode == goog.events.KeyCodes.LEFT) {
|
||||
delta = new ol.Coordinate(-mapUnitsDelta, 0);
|
||||
} else if (keyCode == goog.events.KeyCodes.RIGHT) {
|
||||
delta = new ol.Coordinate(mapUnitsDelta, 0);
|
||||
} else {
|
||||
goog.asserts.assert(keyCode == goog.events.KeyCodes.UP);
|
||||
delta = new ol.Coordinate(0, mapUnitsDelta);
|
||||
}
|
||||
this.pan(map, delta);
|
||||
keyEvent.preventDefault();
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
39
src/ol/interaction/keyboardzoom.js
Normal file
39
src/ol/interaction/keyboardzoom.js
Normal file
@@ -0,0 +1,39 @@
|
||||
goog.provide('ol.interaction.KeyboardZoom');
|
||||
|
||||
goog.require('goog.events.KeyCodes');
|
||||
goog.require('goog.events.KeyHandler.EventType');
|
||||
goog.require('ol.Interaction');
|
||||
goog.require('ol.interaction.ResolutionConstraintType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.KeyboardZoom = function(constraints) {
|
||||
goog.base(this, constraints);
|
||||
};
|
||||
goog.inherits(ol.interaction.KeyboardZoom, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
|
||||
var keyEvent = /** @type {goog.events.KeyEvent} */
|
||||
mapBrowserEvent.browserEvent;
|
||||
var charCode = keyEvent.charCode;
|
||||
if (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0)) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var resolution = map.getResolution();
|
||||
var delta = charCode == '+'.charCodeAt(0) ? 1 : -1;
|
||||
this.zoom(map, resolution, delta);
|
||||
keyEvent.preventDefault();
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
41
src/ol/interaction/mousewheelzoom.js
Normal file
41
src/ol/interaction/mousewheelzoom.js
Normal file
@@ -0,0 +1,41 @@
|
||||
goog.provide('ol.interaction.MouseWheelZoom');
|
||||
|
||||
goog.require('goog.events.MouseWheelEvent');
|
||||
goog.require('goog.events.MouseWheelHandler.EventType');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Interaction}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.MouseWheelZoom = function(constraints) {
|
||||
goog.base(this, constraints);
|
||||
};
|
||||
goog.inherits(ol.interaction.MouseWheelZoom, ol.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (mapBrowserEvent.type ==
|
||||
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var mouseWheelEvent = /** @type {goog.events.MouseWheelEvent} */
|
||||
mapBrowserEvent.browserEvent;
|
||||
goog.asserts.assert(mouseWheelEvent instanceof goog.events.MouseWheelEvent);
|
||||
if (mouseWheelEvent.deltaY !== 0) {
|
||||
var delta = mouseWheelEvent.deltaY < 0 ? 1 : -1;
|
||||
var resolution = map.getResolution();
|
||||
var anchor = mapBrowserEvent.getCoordinate();
|
||||
this.zoom(map, resolution, delta, anchor);
|
||||
mapBrowserEvent.preventDefault();
|
||||
mouseWheelEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
73
src/ol/interaction/resolutionconstraint.js
Normal file
73
src/ol/interaction/resolutionconstraint.js
Normal file
@@ -0,0 +1,73 @@
|
||||
goog.provide('ol.interaction.ResolutionConstraint');
|
||||
goog.provide('ol.interaction.ResolutionConstraintType');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.array');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function((number|undefined), number): (number|undefined)}
|
||||
*/
|
||||
ol.interaction.ResolutionConstraintType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} power Power.
|
||||
* @param {number} maxResolution Maximum resolution.
|
||||
* @param {number=} opt_minResolution Minimum resolution.
|
||||
* @return {ol.interaction.ResolutionConstraintType} Zoom function.
|
||||
*/
|
||||
ol.interaction.ResolutionConstraint.createContinuous =
|
||||
function(power, maxResolution, opt_minResolution) {
|
||||
var minResolution = opt_minResolution || 0;
|
||||
return function(resolution, delta) {
|
||||
if (goog.isDef(resolution)) {
|
||||
resolution /= Math.pow(power, delta);
|
||||
return goog.math.clamp(resolution, minResolution, maxResolution);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} resolutions Resolutions.
|
||||
* @return {ol.interaction.ResolutionConstraintType} Zoom function.
|
||||
*/
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions =
|
||||
function(resolutions) {
|
||||
return function(resolution, delta) {
|
||||
if (goog.isDef(resolution)) {
|
||||
var z = ol.array.linearFindNearest(resolutions, resolution);
|
||||
z = goog.math.clamp(z + delta, 0, resolutions.length - 1);
|
||||
return resolutions[z];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} power Power.
|
||||
* @param {number} maxResolution Maximum resolution.
|
||||
* @param {number=} opt_maxLevel Maximum level.
|
||||
* @return {ol.interaction.ResolutionConstraintType} Zoom function.
|
||||
*/
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower =
|
||||
function(power, maxResolution, opt_maxLevel) {
|
||||
return function(resolution, delta) {
|
||||
if (goog.isDef(resolution)) {
|
||||
var oldLevel = Math.floor(
|
||||
Math.log(maxResolution / resolution) / Math.log(power) + 0.5);
|
||||
var newLevel = Math.max(oldLevel + delta, 0);
|
||||
if (goog.isDef(opt_maxLevel)) {
|
||||
newLevel = Math.min(newLevel, opt_maxLevel);
|
||||
}
|
||||
return maxResolution / Math.pow(power, newLevel);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
};
|
||||
159
src/ol/interaction/resolutionconstraint_test.js
Normal file
159
src/ol/interaction/resolutionconstraint_test.js
Normal file
@@ -0,0 +1,159 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.interaction.ResolutionConstraint');
|
||||
|
||||
|
||||
function testSnapToResolutionsZero() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(1000, resolutionConstraint(1000, 0));
|
||||
assertEquals(500, resolutionConstraint(500, 0));
|
||||
assertEquals(250, resolutionConstraint(250, 0));
|
||||
assertEquals(100, resolutionConstraint(100, 0));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToResolutionsZoomIn() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(500, resolutionConstraint(1000, 1));
|
||||
assertEquals(250, resolutionConstraint(500, 1));
|
||||
assertEquals(100, resolutionConstraint(250, 1));
|
||||
assertEquals(100, resolutionConstraint(100, 1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToResolutionsZoomOut() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(1000, resolutionConstraint(1000, -1));
|
||||
assertEquals(1000, resolutionConstraint(500, -1));
|
||||
assertEquals(500, resolutionConstraint(250, -1));
|
||||
assertEquals(250, resolutionConstraint(100, -1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToResolutionsNearestZero() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(1000, resolutionConstraint(1050, 0));
|
||||
assertEquals(1000, resolutionConstraint(950, 0));
|
||||
assertEquals(500, resolutionConstraint(550, 0));
|
||||
assertEquals(500, resolutionConstraint(400, 0));
|
||||
assertEquals(250, resolutionConstraint(300, 0));
|
||||
assertEquals(250, resolutionConstraint(200, 0));
|
||||
assertEquals(100, resolutionConstraint(150, 0));
|
||||
assertEquals(100, resolutionConstraint(50, 0));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToResolutionsNearestZoomIn() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(500, resolutionConstraint(1050, 1));
|
||||
assertEquals(500, resolutionConstraint(950, 1));
|
||||
assertEquals(250, resolutionConstraint(550, 1));
|
||||
assertEquals(250, resolutionConstraint(450, 1));
|
||||
assertEquals(100, resolutionConstraint(300, 1));
|
||||
assertEquals(100, resolutionConstraint(200, 1));
|
||||
assertEquals(100, resolutionConstraint(150, 1));
|
||||
assertEquals(100, resolutionConstraint(50, 1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToResolutionsNearestZoomOut() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToResolutions(
|
||||
[1000, 500, 250, 100]);
|
||||
assertEquals(1000, resolutionConstraint(1050, -1));
|
||||
assertEquals(1000, resolutionConstraint(950, -1));
|
||||
assertEquals(1000, resolutionConstraint(550, -1));
|
||||
assertEquals(1000, resolutionConstraint(450, -1));
|
||||
assertEquals(500, resolutionConstraint(300, -1));
|
||||
assertEquals(500, resolutionConstraint(200, -1));
|
||||
assertEquals(250, resolutionConstraint(150, -1));
|
||||
assertEquals(250, resolutionConstraint(50, -1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToPowerZero() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower(2, 1024, 10);
|
||||
assertEquals(1024, resolutionConstraint(1024, 0));
|
||||
assertEquals(512, resolutionConstraint(512, 0));
|
||||
assertEquals(256, resolutionConstraint(256, 0));
|
||||
assertEquals(128, resolutionConstraint(128, 0));
|
||||
assertEquals(64, resolutionConstraint(64, 0));
|
||||
assertEquals(32, resolutionConstraint(32, 0));
|
||||
assertEquals(16, resolutionConstraint(16, 0));
|
||||
assertEquals(8, resolutionConstraint(8, 0));
|
||||
assertEquals(4, resolutionConstraint(4, 0));
|
||||
assertEquals(2, resolutionConstraint(2, 0));
|
||||
assertEquals(1, resolutionConstraint(1, 0));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToPowerZoomIn() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower(2, 1024, 10);
|
||||
assertEquals(512, resolutionConstraint(1024, 1));
|
||||
assertEquals(256, resolutionConstraint(512, 1));
|
||||
assertEquals(128, resolutionConstraint(256, 1));
|
||||
assertEquals(64, resolutionConstraint(128, 1));
|
||||
assertEquals(32, resolutionConstraint(64, 1));
|
||||
assertEquals(16, resolutionConstraint(32, 1));
|
||||
assertEquals(8, resolutionConstraint(16, 1));
|
||||
assertEquals(4, resolutionConstraint(8, 1));
|
||||
assertEquals(2, resolutionConstraint(4, 1));
|
||||
assertEquals(1, resolutionConstraint(2, 1));
|
||||
assertEquals(1, resolutionConstraint(1, 1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToPowerZoomOut() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower(2, 1024, 10);
|
||||
assertEquals(1024, resolutionConstraint(1024, -1));
|
||||
assertEquals(1024, resolutionConstraint(512, -1));
|
||||
assertEquals(512, resolutionConstraint(256, -1));
|
||||
assertEquals(256, resolutionConstraint(128, -1));
|
||||
assertEquals(128, resolutionConstraint(64, -1));
|
||||
assertEquals(64, resolutionConstraint(32, -1));
|
||||
assertEquals(32, resolutionConstraint(16, -1));
|
||||
assertEquals(16, resolutionConstraint(8, -1));
|
||||
assertEquals(8, resolutionConstraint(4, -1));
|
||||
assertEquals(4, resolutionConstraint(2, -1));
|
||||
assertEquals(2, resolutionConstraint(1, -1));
|
||||
}
|
||||
|
||||
|
||||
function testSnapToPowerNearestZero() {
|
||||
var resolutionConstraint =
|
||||
ol.interaction.ResolutionConstraint.createSnapToPower(2, 1024, 10);
|
||||
assertEquals(1024, resolutionConstraint(1050, 0));
|
||||
assertEquals(1024, resolutionConstraint(9050, 0));
|
||||
assertEquals(512, resolutionConstraint(550, 0));
|
||||
assertEquals(512, resolutionConstraint(450, 0));
|
||||
assertEquals(256, resolutionConstraint(300, 0));
|
||||
assertEquals(256, resolutionConstraint(250, 0));
|
||||
assertEquals(128, resolutionConstraint(150, 0));
|
||||
assertEquals(128, resolutionConstraint(100, 0));
|
||||
assertEquals(64, resolutionConstraint(75, 0));
|
||||
assertEquals(64, resolutionConstraint(50, 0));
|
||||
assertEquals(32, resolutionConstraint(40, 0));
|
||||
assertEquals(32, resolutionConstraint(30, 0));
|
||||
assertEquals(16, resolutionConstraint(20, 0));
|
||||
assertEquals(16, resolutionConstraint(12, 0));
|
||||
assertEquals(8, resolutionConstraint(9, 0));
|
||||
assertEquals(8, resolutionConstraint(7, 0));
|
||||
assertEquals(4, resolutionConstraint(5, 0));
|
||||
assertEquals(4, resolutionConstraint(3.5, 0));
|
||||
assertEquals(2, resolutionConstraint(2.1, 0));
|
||||
assertEquals(2, resolutionConstraint(1.9, 0));
|
||||
assertEquals(1, resolutionConstraint(1.1, 0));
|
||||
assertEquals(1, resolutionConstraint(0.9, 0));
|
||||
}
|
||||
39
src/ol/interaction/rotationconstraint.js
Normal file
39
src/ol/interaction/rotationconstraint.js
Normal file
@@ -0,0 +1,39 @@
|
||||
goog.provide('ol.interaction.RotationConstraint');
|
||||
goog.provide('ol.interaction.RotationConstraintType');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function((number|undefined), number): (number|undefined)}
|
||||
*/
|
||||
ol.interaction.RotationConstraintType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number|undefined} rotation Rotation.
|
||||
* @param {number} delta Delta.
|
||||
* @return {number|undefined} Rotation.
|
||||
*/
|
||||
ol.interaction.RotationConstraint.none = function(rotation, delta) {
|
||||
if (goog.isDef(rotation)) {
|
||||
return rotation + delta;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} n N.
|
||||
* @return {ol.interaction.RotationConstraintType} Rotation constraint.
|
||||
*/
|
||||
ol.interaction.RotationConstraint.createSnapToN = function(n) {
|
||||
var theta = 2 * Math.PI / n;
|
||||
return function(rotation, delta) {
|
||||
if (goog.isDef(rotation)) {
|
||||
rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
|
||||
return rotation;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
};
|
||||
75
src/ol/interaction/shiftdragrotateandzoom.js
Normal file
75
src/ol/interaction/shiftdragrotateandzoom.js
Normal file
@@ -0,0 +1,75 @@
|
||||
goog.provide('ol.interaction.ShiftDragRotateAndZoom');
|
||||
|
||||
goog.require('goog.math.Vec2');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
goog.require('ol.interaction.Drag');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.ShiftDragRotateAndZoom = function(constraints) {
|
||||
|
||||
goog.base(this, constraints);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.startRatio_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.startRotation_ = 0;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.ShiftDragRotateAndZoom, ol.interaction.Drag);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.ShiftDragRotateAndZoom.prototype.handleDrag =
|
||||
function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
var map = mapBrowserEvent.map;
|
||||
var size = map.getSize();
|
||||
var delta = new goog.math.Vec2(
|
||||
browserEvent.offsetX - size.width / 2,
|
||||
size.height / 2 - browserEvent.offsetY);
|
||||
var theta = Math.atan2(delta.y, delta.x);
|
||||
// FIXME this should use map.withFrozenRendering but an assertion fails :-(
|
||||
this.rotate(map, this.startRotation_, -theta);
|
||||
var resolution = this.startRatio_ * delta.magnitude();
|
||||
this.setResolution(map, resolution);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.ShiftDragRotateAndZoom.prototype.handleDragStart =
|
||||
function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
var map = mapBrowserEvent.map;
|
||||
if (map.canRotate() && browserEvent.shiftKey) {
|
||||
var resolution = map.getResolution();
|
||||
var size = map.getSize();
|
||||
var delta = new goog.math.Vec2(
|
||||
browserEvent.offsetX - size.width / 2,
|
||||
size.height / 2 - browserEvent.offsetY);
|
||||
var theta = Math.atan2(delta.y, delta.x);
|
||||
this.startRotation_ = (map.getRotation() || 0) + theta;
|
||||
this.startRatio_ = resolution / delta.magnitude();
|
||||
browserEvent.preventDefault();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
65
src/ol/interaction/shiftdragzoom.js
Normal file
65
src/ol/interaction/shiftdragzoom.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// FIXME draw drag box
|
||||
|
||||
goog.provide('ol.interaction.ShiftDragZoom');
|
||||
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.interaction.Constraints');
|
||||
goog.require('ol.interaction.Drag');
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} Hysterisis pixels.
|
||||
*/
|
||||
ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS = 8;
|
||||
|
||||
|
||||
/**
|
||||
* @const {number}
|
||||
*/
|
||||
ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED =
|
||||
ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS *
|
||||
ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @param {ol.interaction.Constraints} constraints Constraints.
|
||||
*/
|
||||
ol.interaction.ShiftDragZoom = function(constraints) {
|
||||
goog.base(this, constraints);
|
||||
};
|
||||
goog.inherits(ol.interaction.ShiftDragZoom, ol.interaction.Drag);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.ShiftDragZoom.prototype.handleDragEnd =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.deltaX * this.deltaX + this.deltaY * this.deltaY >=
|
||||
ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var extent = ol.Extent.boundingExtent(
|
||||
this.startCoordinate,
|
||||
mapBrowserEvent.getCoordinate());
|
||||
this.fitExtent(map, extent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.ShiftDragZoom.prototype.handleDragStart =
|
||||
function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (browserEvent.isMouseActionButton() && browserEvent.shiftKey) {
|
||||
browserEvent.preventDefault();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
228
src/ol/layer.js
Normal file
228
src/ol/layer.js
Normal file
@@ -0,0 +1,228 @@
|
||||
goog.provide('ol.Layer');
|
||||
goog.provide('ol.LayerProperty');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.Store');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.LayerProperty = {
|
||||
BRIGHTNESS: 'brightness',
|
||||
CONTRAST: 'contrast',
|
||||
HUE: 'hue',
|
||||
OPACITY: 'opacity',
|
||||
SATURATION: 'saturation',
|
||||
VISIBLE: 'visible'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {ol.Store} store Store.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.Layer = function(store, opt_values) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Store}
|
||||
*/
|
||||
this.store_ = store;
|
||||
|
||||
this.setBrightness(0);
|
||||
this.setContrast(0);
|
||||
this.setHue(0);
|
||||
this.setOpacity(1);
|
||||
this.setSaturation(0);
|
||||
this.setVisible(true);
|
||||
|
||||
if (goog.isDef(opt_values)) {
|
||||
this.setValues(opt_values);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.Layer, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Brightness.
|
||||
*/
|
||||
ol.Layer.prototype.getBrightness = function() {
|
||||
return /** @type {number} */ this.get(ol.LayerProperty.BRIGHTNESS);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getBrightness',
|
||||
ol.Layer.prototype.getBrightness);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Contrast.
|
||||
*/
|
||||
ol.Layer.prototype.getContrast = function() {
|
||||
return /** @type {number} */ this.get(ol.LayerProperty.CONTRAST);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getContrast',
|
||||
ol.Layer.prototype.getContrast);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Hue.
|
||||
*/
|
||||
ol.Layer.prototype.getHue = function() {
|
||||
return /** @type {number} */ this.get(ol.LayerProperty.HUE);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getHue',
|
||||
ol.Layer.prototype.getHue);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Opacity.
|
||||
*/
|
||||
ol.Layer.prototype.getOpacity = function() {
|
||||
return /** @type {number} */ this.get(ol.LayerProperty.OPACITY);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getOpacity',
|
||||
ol.Layer.prototype.getOpacity);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Saturation.
|
||||
*/
|
||||
ol.Layer.prototype.getSaturation = function() {
|
||||
return /** @type {number} */ this.get(ol.LayerProperty.SATURATION);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getSaturation',
|
||||
ol.Layer.prototype.getSaturation);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Store} Store.
|
||||
*/
|
||||
ol.Layer.prototype.getStore = function() {
|
||||
return this.store_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Visible.
|
||||
*/
|
||||
ol.Layer.prototype.getVisible = function() {
|
||||
return /** @type {boolean} */ this.get(ol.LayerProperty.VISIBLE);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'getVisible',
|
||||
ol.Layer.prototype.getVisible);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is ready.
|
||||
*/
|
||||
ol.Layer.prototype.isReady = function() {
|
||||
return this.getStore().isReady();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} brightness Brightness.
|
||||
*/
|
||||
ol.Layer.prototype.setBrightness = function(brightness) {
|
||||
brightness = goog.math.clamp(brightness, -1, 1);
|
||||
if (brightness != this.getBrightness()) {
|
||||
this.set(ol.LayerProperty.BRIGHTNESS, brightness);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setBrightness',
|
||||
ol.Layer.prototype.setBrightness);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} contrast Contrast.
|
||||
*/
|
||||
ol.Layer.prototype.setContrast = function(contrast) {
|
||||
contrast = goog.math.clamp(contrast, -1, 1);
|
||||
if (contrast != this.getContrast()) {
|
||||
this.set(ol.LayerProperty.CONTRAST, contrast);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setContrast',
|
||||
ol.Layer.prototype.setContrast);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} hue Hue.
|
||||
*/
|
||||
ol.Layer.prototype.setHue = function(hue) {
|
||||
if (hue != this.getHue()) {
|
||||
this.set(ol.LayerProperty.HUE, hue);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setHue',
|
||||
ol.Layer.prototype.setHue);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} opacity Opacity.
|
||||
*/
|
||||
ol.Layer.prototype.setOpacity = function(opacity) {
|
||||
opacity = goog.math.clamp(opacity, 0, 1);
|
||||
if (opacity != this.getOpacity()) {
|
||||
this.set(ol.LayerProperty.OPACITY, opacity);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setOpacity',
|
||||
ol.Layer.prototype.setOpacity);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} saturation Saturation.
|
||||
*/
|
||||
ol.Layer.prototype.setSaturation = function(saturation) {
|
||||
saturation = goog.math.clamp(saturation, -1, 1);
|
||||
if (saturation != this.getSaturation()) {
|
||||
this.set(ol.LayerProperty.SATURATION, saturation);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setSaturation',
|
||||
ol.Layer.prototype.setSaturation);
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} visible Visible.
|
||||
*/
|
||||
ol.Layer.prototype.setVisible = function(visible) {
|
||||
visible = !!visible;
|
||||
if (visible != this.getVisible()) {
|
||||
this.set(ol.LayerProperty.VISIBLE, visible);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Layer.prototype,
|
||||
'setVisible',
|
||||
ol.Layer.prototype.setVisible);
|
||||
189
src/ol/layer/bingmaps.js
Normal file
189
src/ol/layer/bingmaps.js
Normal file
@@ -0,0 +1,189 @@
|
||||
goog.provide('ol.layer.BingMaps');
|
||||
goog.provide('ol.tilestore.BingMaps');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.net.Jsonp');
|
||||
goog.require('ol.TileCoverageArea');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.TileStore');
|
||||
goog.require('ol.tilegrid.XYZ');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.BingMapsStyle = {
|
||||
AERIAL: 'Aerial',
|
||||
AERIAL_WITH_LABELS: 'AerialWithLabels',
|
||||
ROAD: 'Road',
|
||||
ORDNANCE_SURVEY: 'OrdnanceSurvey',
|
||||
COLLINS_BART: 'CollinsBart'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileLayer}
|
||||
* @param {ol.BingMapsStyle} style Bing Maps style.
|
||||
* @param {string} key Key.
|
||||
* @param {string=} opt_culture Culture.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.BingMaps = function(style, key, opt_culture, opt_values) {
|
||||
var tileStore = new ol.tilestore.BingMaps(style, key, opt_culture,
|
||||
function(tileStore) {
|
||||
this.dispatchEvent(goog.events.EventType.LOAD);
|
||||
}, this);
|
||||
goog.base(this, tileStore, opt_values);
|
||||
};
|
||||
goog.inherits(ol.layer.BingMaps, ol.TileLayer);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileStore}
|
||||
* @param {ol.BingMapsStyle} style Bing Maps style.
|
||||
* @param {string} key Key.
|
||||
* @param {string=} opt_culture Culture.
|
||||
* @param {?function(ol.tilestore.BingMaps)=} opt_callback Callback.
|
||||
* @param {*=} opt_obj Object.
|
||||
*/
|
||||
ol.tilestore.BingMaps =
|
||||
function(style, key, opt_culture, opt_callback, opt_obj) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.culture_ = opt_culture || 'en-us';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ready_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?function(ol.tilestore.BingMaps)}
|
||||
*/
|
||||
this.callback_ = opt_callback || null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.object_ = opt_obj;
|
||||
|
||||
var uri = new goog.Uri(
|
||||
'http://dev.virtualearth.net/REST/v1/Imagery/Metadata/' + style);
|
||||
var jsonp = new goog.net.Jsonp(uri, 'jsonp');
|
||||
jsonp.send({
|
||||
'include': 'ImageryProviders',
|
||||
'key': key
|
||||
}, goog.bind(this.handleImageryMetadataResponse, this));
|
||||
|
||||
var projection = ol.Projection.getFromCode('EPSG:3857');
|
||||
var extent = projection.getExtent();
|
||||
|
||||
goog.base(
|
||||
this, projection, null, ol.TileUrlFunction.nullTileUrlFunction, extent);
|
||||
|
||||
};
|
||||
goog.inherits(ol.tilestore.BingMaps, ol.TileStore);
|
||||
|
||||
|
||||
/**
|
||||
* @param {BingMapsImageryMetadataResponse} response Response.
|
||||
*/
|
||||
ol.tilestore.BingMaps.prototype.handleImageryMetadataResponse =
|
||||
function(response) {
|
||||
|
||||
goog.asserts.assert(
|
||||
response.authenticationResultCode == 'ValidCredentials');
|
||||
goog.asserts.assert(response.statusCode == 200);
|
||||
goog.asserts.assert(response.statusDescription == 'OK');
|
||||
|
||||
var brandLogoUri = response.brandLogoUri;
|
||||
var copyright = response.copyright;
|
||||
goog.asserts.assert(response.resourceSets.length == 1);
|
||||
var resourceSet = response.resourceSets[0];
|
||||
goog.asserts.assert(resourceSet.resources.length == 1);
|
||||
var resource = resourceSet.resources[0];
|
||||
|
||||
var zoomMin = resource.zoomMin;
|
||||
var zoomMax = resource.zoomMax;
|
||||
var tileSize = new ol.Size(resource.imageWidth, resource.imageHeight);
|
||||
var tileGrid = new ol.tilegrid.XYZ(zoomMax, tileSize);
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
|
||||
function(tileCoord) {
|
||||
if (tileCoord.z < zoomMin || zoomMax < tileCoord.z) {
|
||||
return null;
|
||||
}
|
||||
var n = 1 << tileCoord.z;
|
||||
var y = -tileCoord.y - 1;
|
||||
if (y < 0 || n <= y) {
|
||||
return null;
|
||||
} else {
|
||||
var x = goog.math.modulo(tileCoord.x, n);
|
||||
return new ol.TileCoord(tileCoord.z, x, y);
|
||||
}
|
||||
},
|
||||
ol.TileUrlFunction.createFromTileUrlFunctions(
|
||||
goog.array.map(
|
||||
resource.imageUrlSubdomains,
|
||||
function(subdomain) {
|
||||
var imageUrl = resource.imageUrl
|
||||
.replace('{subdomain}', subdomain)
|
||||
.replace('{culture}', this.culture_);
|
||||
return function(tileCoord) {
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
return imageUrl.replace(
|
||||
'{quadkey}', tileCoord.quadKey());
|
||||
}
|
||||
};
|
||||
})));
|
||||
|
||||
var projection = ol.Projection.getFromCode('EPSG:4326');
|
||||
var attributions = goog.array.map(
|
||||
resource.imageryProviders,
|
||||
function(imageryProvider) {
|
||||
var html = imageryProvider.attribution;
|
||||
var coverageAreas = goog.array.map(
|
||||
imageryProvider.coverageAreas,
|
||||
function(coverageArea) {
|
||||
var bbox = coverageArea.bbox;
|
||||
var extent = new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]);
|
||||
var minZ = coverageArea.zoomMin;
|
||||
var maxZ = coverageArea.zoomMax;
|
||||
return new ol.TileCoverageArea(tileGrid, extent, minZ, maxZ);
|
||||
});
|
||||
return new ol.Attribution(html, coverageAreas, projection);
|
||||
});
|
||||
this.setAttributions(attributions);
|
||||
|
||||
this.ready_ = true;
|
||||
|
||||
if (!goog.isNull(this.callback_)) {
|
||||
this.callback_.call(this.object_, this);
|
||||
this.callback_ = null;
|
||||
this.object_ = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.tilestore.BingMaps.prototype.isReady = function() {
|
||||
return this.ready_;
|
||||
};
|
||||
62
src/ol/layer/mapquest.js
Normal file
62
src/ol/layer/mapquest.js
Normal file
@@ -0,0 +1,62 @@
|
||||
goog.provide('ol.layer.MapQuestOSM');
|
||||
goog.provide('ol.layer.MapQuestOpenAerial');
|
||||
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.layer.XYZ');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.layer.XYZ}
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.MapQuestOSM = function(opt_values) {
|
||||
|
||||
var tileUrlFunction = ol.TileUrlFunction.createFromTemplate(
|
||||
'http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg');
|
||||
|
||||
var attributions = [
|
||||
new ol.Attribution(
|
||||
'Tiles Courtesy of ' +
|
||||
'<a href="http://www.mapquest.com/" target="_blank">MapQuest</a> ' +
|
||||
'<img src="http://developer.mapquest.com/content/osm/mq_logo.png">'),
|
||||
new ol.Attribution(
|
||||
'Data © ' +
|
||||
'<a href="http://www.openstreetmap.org">OpenStreetMap</a> ' +
|
||||
'contributors, ' +
|
||||
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA</a>')
|
||||
];
|
||||
|
||||
goog.base(this, 18, tileUrlFunction, attributions);
|
||||
|
||||
};
|
||||
goog.inherits(ol.layer.MapQuestOSM, ol.layer.XYZ);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.layer.XYZ}
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.MapQuestOpenAerial = function(opt_values) {
|
||||
|
||||
var tileUrlFunction = ol.TileUrlFunction.createFromTemplate(
|
||||
'http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg');
|
||||
|
||||
var attributions = [
|
||||
new ol.Attribution(
|
||||
'Tiles Courtesy of ' +
|
||||
'<a href="http://www.mapquest.com/" target="_blank">MapQuest</a> ' +
|
||||
'<img src="http://developer.mapquest.com/content/osm/mq_logo.png">'),
|
||||
new ol.Attribution(
|
||||
'Portions Courtesy NASA/JPL-Caltech and ' +
|
||||
'U.S. Depart. of Agriculture, Farm Service Agency')
|
||||
];
|
||||
|
||||
goog.base(this, 18, tileUrlFunction, attributions);
|
||||
|
||||
};
|
||||
goog.inherits(ol.layer.MapQuestOpenAerial, ol.layer.XYZ);
|
||||
40
src/ol/layer/openstreetmap.js
Normal file
40
src/ol/layer/openstreetmap.js
Normal file
@@ -0,0 +1,40 @@
|
||||
goog.provide('ol.layer.OpenStreetMap');
|
||||
goog.provide('ol.store.OpenStreetMap');
|
||||
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.tilestore.XYZ');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileLayer}
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.OpenStreetMap = function(opt_values) {
|
||||
var tileStore = new ol.store.OpenStreetMap();
|
||||
goog.base(this, tileStore, opt_values);
|
||||
};
|
||||
goog.inherits(ol.layer.OpenStreetMap, ol.TileLayer);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.tilestore.XYZ}
|
||||
*/
|
||||
ol.store.OpenStreetMap = function() {
|
||||
|
||||
var tileUrlFunction = ol.TileUrlFunction.createFromTemplate(
|
||||
'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png');
|
||||
|
||||
var attribution = new ol.Attribution(
|
||||
'© <a href="http://www.openstreetmap.org">OpenStreetMap</a> ' +
|
||||
'contributors, ' +
|
||||
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA</a>');
|
||||
|
||||
goog.base(this, 18, tileUrlFunction, [attribution]);
|
||||
|
||||
};
|
||||
goog.inherits(ol.store.OpenStreetMap, ol.tilestore.XYZ);
|
||||
92
src/ol/layer/stamen.js
Normal file
92
src/ol/layer/stamen.js
Normal file
@@ -0,0 +1,92 @@
|
||||
// FIXME Configure minZoom when supported by TileGrid
|
||||
|
||||
goog.provide('ol.layer.Stamen');
|
||||
goog.provide('ol.store.Stamen');
|
||||
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.layer.XYZ');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.StamenProvider = {
|
||||
TERRAIN: 'terrain',
|
||||
TONER: 'toner',
|
||||
WATERCOLOR: 'watercolor'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.StamenFlavor = {
|
||||
TERRAIN_BACKGROUND: 'background',
|
||||
TERRAIN_LABELS: 'labels',
|
||||
TERRAIN_LINES: 'lines',
|
||||
TONER_2010: '2010',
|
||||
TONER_2011: '2011',
|
||||
TONER_2011_LABELS: '2011-labels',
|
||||
TONER_2011_LINES: '2011-lines',
|
||||
TONER_2011_LITE: '2011-lite',
|
||||
TONER_BACKGROUND: 'background',
|
||||
TONER_HYBRID: 'hybrid',
|
||||
TONER_LABELS: 'labels',
|
||||
TONER_LINES: 'lines',
|
||||
TONER_LITE: 'lite'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<ol.StamenProvider,
|
||||
* {type: string, minZoom: number, maxZoom: number}>}
|
||||
*/
|
||||
ol.StamenProviderConfig = {};
|
||||
ol.StamenProviderConfig[ol.StamenProvider.TERRAIN] = {
|
||||
type: 'jpg',
|
||||
minZoom: 4,
|
||||
maxZoom: 18
|
||||
};
|
||||
ol.StamenProviderConfig[ol.StamenProvider.TONER] = {
|
||||
type: 'png',
|
||||
minZoom: 0,
|
||||
maxZoom: 20
|
||||
};
|
||||
ol.StamenProviderConfig[ol.StamenProvider.WATERCOLOR] = {
|
||||
type: 'jpg',
|
||||
minZoom: 3,
|
||||
maxZoom: 16
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.layer.XYZ}
|
||||
* @param {ol.StamenProvider} provider Provider.
|
||||
* @param {ol.StamenFlavor=} opt_flavor Flavor.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.Stamen = function(provider, opt_flavor, opt_values) {
|
||||
|
||||
var config = ol.StamenProviderConfig[provider];
|
||||
|
||||
var layer = provider;
|
||||
if (goog.isDef(opt_flavor)) {
|
||||
layer += '-' + opt_flavor;
|
||||
}
|
||||
var tileUrlFunction = ol.TileUrlFunction.createFromTemplate(
|
||||
'http://{a-d}.tile.stamen.com/' + layer + '/{z}/{x}/{y}.' + config.type);
|
||||
|
||||
var attribution = new ol.Attribution(
|
||||
'Map tiles by <a href="http://stamen.com">Stamen Design</a>, ' +
|
||||
'under ' +
|
||||
'<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. ' +
|
||||
'Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, ' +
|
||||
'under ' +
|
||||
'<a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.');
|
||||
|
||||
goog.base(this, config.maxZoom, tileUrlFunction, [attribution]);
|
||||
|
||||
};
|
||||
goog.inherits(ol.layer.Stamen, ol.layer.XYZ);
|
||||
180
src/ol/layer/tilejson.js
Normal file
180
src/ol/layer/tilejson.js
Normal file
@@ -0,0 +1,180 @@
|
||||
// FIXME add some error checking
|
||||
// FIXME check order of async callbacks
|
||||
// FIXME use minzoom when supported by ol.TileGrid
|
||||
|
||||
/**
|
||||
* @see http://mapbox.com/developers/api/
|
||||
*/
|
||||
|
||||
goog.provide('ol.layer.TileJSON');
|
||||
goog.provide('ol.tilejson');
|
||||
goog.provide('ol.tilestore.TileJSON');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.net.jsloader');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.TileStore');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<TileJSON>}
|
||||
*/
|
||||
ol.tilejson.grids_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param {TileJSON} tileJSON Tile JSON.
|
||||
*/
|
||||
var grid = function(tileJSON) {
|
||||
ol.tilejson.grids_.push(tileJSON);
|
||||
};
|
||||
goog.exportSymbol('grid', grid);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileLayer}
|
||||
* @param {string} url URL.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.TileJSON = function(url, opt_values) {
|
||||
goog.asserts.assert(goog.string.endsWith(url, '.jsonp'));
|
||||
var tileStore = new ol.tilestore.TileJSON(url, function(tileStore) {
|
||||
this.dispatchEvent(goog.events.EventType.LOAD);
|
||||
}, this);
|
||||
goog.base(this, tileStore, opt_values);
|
||||
};
|
||||
goog.inherits(ol.layer.TileJSON, ol.TileLayer);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileStore}
|
||||
* @param {string} uri URI.
|
||||
* @param {?function(ol.tilestore.TileJSON)=} opt_callback Callback.
|
||||
* @param {*=} opt_obj Object.
|
||||
*/
|
||||
ol.tilestore.TileJSON = function(uri, opt_callback, opt_obj) {
|
||||
|
||||
var projection = ol.Projection.getFromCode('EPSG:3857');
|
||||
|
||||
goog.base(
|
||||
this, projection, null, ol.TileUrlFunction.nullTileUrlFunction, null);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?function(ol.tilestore.TileJSON)}
|
||||
*/
|
||||
this.callback_ = opt_callback || null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.object_ = opt_obj;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ready_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.async.Deferred}
|
||||
*/
|
||||
this.deferred_ = goog.net.jsloader.load(uri, {cleanupWhenDone: true});
|
||||
this.deferred_.addCallback(this.handleTileJSONResponse, this);
|
||||
|
||||
};
|
||||
goog.inherits(ol.tilestore.TileJSON, ol.TileStore);
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.tilestore.TileJSON.prototype.handleTileJSONResponse = function() {
|
||||
|
||||
var tileJSON = ol.tilejson.grids_.pop();
|
||||
|
||||
var epsg4326Projection = ol.Projection.getFromCode('EPSG:4326');
|
||||
|
||||
var epsg4326Extent, extent;
|
||||
if (goog.isDef(tileJSON.bounds)) {
|
||||
var bounds = tileJSON.bounds;
|
||||
epsg4326Extent = new ol.Extent(
|
||||
bounds[0], bounds[1], bounds[2], bounds[3]);
|
||||
extent = epsg4326Extent.transform(
|
||||
ol.Projection.getTransform(epsg4326Projection, this.getProjection()));
|
||||
this.setExtent(extent);
|
||||
} else {
|
||||
epsg4326Extent = null;
|
||||
extent = null;
|
||||
}
|
||||
|
||||
var scheme = goog.isDef(tileJSON.scheme) || 'xyz';
|
||||
if (goog.isDef(tileJSON.scheme)) {
|
||||
goog.asserts.assert(tileJSON.scheme == 'xyz');
|
||||
}
|
||||
var minzoom = tileJSON.minzoom || 0;
|
||||
goog.asserts.assert(minzoom === 0); // FIXME
|
||||
var maxzoom = tileJSON.maxzoom || 22;
|
||||
var tileGrid = new ol.tilegrid.XYZ(maxzoom);
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
|
||||
function(tileCoord) {
|
||||
if (tileCoord.z < minzoom || maxzoom < tileCoord.z) {
|
||||
return null;
|
||||
}
|
||||
var n = 1 << tileCoord.z;
|
||||
var y = -tileCoord.y - 1;
|
||||
if (y < 0 || n <= y) {
|
||||
return null;
|
||||
}
|
||||
var x = goog.math.modulo(tileCoord.x, n);
|
||||
if (!goog.isNull(extent)) {
|
||||
var tileExtent = tileGrid.getTileCoordExtent(
|
||||
new ol.TileCoord(tileCoord.z, x, tileCoord.y));
|
||||
if (!tileExtent.intersects(extent)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new ol.TileCoord(tileCoord.z, x, y);
|
||||
},
|
||||
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
|
||||
|
||||
if (goog.isDef(tileJSON.attribution)) {
|
||||
var coverageAreas = [
|
||||
new ol.TileCoverageArea(tileGrid, epsg4326Extent, minzoom, maxzoom)
|
||||
];
|
||||
var coverageAreaProjection = epsg4326Projection;
|
||||
this.setAttributions([
|
||||
new ol.Attribution(
|
||||
tileJSON.attribution, coverageAreas, coverageAreaProjection)
|
||||
]);
|
||||
}
|
||||
|
||||
this.ready_ = true;
|
||||
|
||||
if (!goog.isNull(this.callback_)) {
|
||||
this.callback_.call(this.object_, this);
|
||||
this.callback_ = null;
|
||||
this.object_ = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.tilestore.TileJSON.prototype.isReady = function() {
|
||||
return this.ready_;
|
||||
};
|
||||
118
src/ol/layer/xyz.js
Normal file
118
src/ol/layer/xyz.js
Normal file
@@ -0,0 +1,118 @@
|
||||
goog.provide('ol.layer.XYZ');
|
||||
goog.provide('ol.tilegrid.XYZ');
|
||||
goog.provide('ol.tilestore.XYZ');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileGrid');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.TileStore');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileGrid}
|
||||
* @param {number} maxZoom Maximum zoom.
|
||||
* @param {ol.Size=} opt_tileSize Tile size.
|
||||
*/
|
||||
ol.tilegrid.XYZ = function(maxZoom, opt_tileSize) {
|
||||
|
||||
var resolutions = new Array(maxZoom + 1);
|
||||
var z;
|
||||
for (z = 0; z <= maxZoom; ++z) {
|
||||
resolutions[z] = ol.Projection.EPSG_3857_HALF_SIZE / (128 << z);
|
||||
}
|
||||
|
||||
var extent = ol.Projection.EPSG_3857_EXTENT;
|
||||
var origin = new ol.Coordinate(
|
||||
-ol.Projection.EPSG_3857_HALF_SIZE, ol.Projection.EPSG_3857_HALF_SIZE);
|
||||
|
||||
goog.base(this, resolutions, extent, origin, opt_tileSize);
|
||||
|
||||
};
|
||||
goog.inherits(ol.tilegrid.XYZ, ol.TileGrid);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.tilegrid.XYZ.prototype.forEachTileCoordParentTileBounds =
|
||||
function(tileCoord, callback, opt_obj) {
|
||||
var x = tileCoord.x;
|
||||
var y = tileCoord.y;
|
||||
var z = tileCoord.z;
|
||||
var tileBounds;
|
||||
while (true) {
|
||||
z -= 1;
|
||||
if (z < 0) {
|
||||
break;
|
||||
}
|
||||
x = Math.floor(x / 2);
|
||||
y = Math.floor(y / 2);
|
||||
tileBounds = new ol.TileBounds(x, y, x, y);
|
||||
if (callback.call(opt_obj, z, tileBounds)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileLayer}
|
||||
* @param {number} maxZoom Maximum zoom.
|
||||
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
|
||||
* @param {Array.<ol.Attribution>=} opt_attributions Attributions.
|
||||
* @param {string=} opt_crossOrigin Cross origin.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.layer.XYZ = function(
|
||||
maxZoom, tileUrlFunction, opt_attributions, opt_crossOrigin, opt_values) {
|
||||
var tileStore = new ol.tilestore.XYZ(
|
||||
maxZoom, tileUrlFunction, opt_attributions, opt_crossOrigin);
|
||||
goog.base(this, tileStore, opt_values);
|
||||
};
|
||||
goog.inherits(ol.layer.XYZ, ol.TileLayer);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.TileStore}
|
||||
* @param {number} maxZoom Maximum zoom.
|
||||
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
|
||||
* @param {Array.<ol.Attribution>=} opt_attributions Attributions.
|
||||
* @param {string=} opt_crossOrigin Cross origin.
|
||||
*/
|
||||
ol.tilestore.XYZ =
|
||||
function(maxZoom, tileUrlFunction, opt_attributions, opt_crossOrigin) {
|
||||
|
||||
var projection = ol.Projection.getFromCode('EPSG:3857');
|
||||
var tileGrid = new ol.tilegrid.XYZ(maxZoom);
|
||||
var tileUrlFunction2 = ol.TileUrlFunction.withTileCoordTransform(
|
||||
function(tileCoord) {
|
||||
var n = 1 << tileCoord.z;
|
||||
var y = -tileCoord.y - 1;
|
||||
if (y < 0 || n <= y) {
|
||||
return null;
|
||||
} else {
|
||||
var x = goog.math.modulo(tileCoord.x, n);
|
||||
return new ol.TileCoord(tileCoord.z, x, y);
|
||||
}
|
||||
},
|
||||
tileUrlFunction);
|
||||
var extent = projection.getExtent();
|
||||
|
||||
goog.base(this, projection, tileGrid, tileUrlFunction2, extent,
|
||||
opt_attributions, opt_crossOrigin);
|
||||
|
||||
};
|
||||
goog.inherits(ol.tilestore.XYZ, ol.TileStore);
|
||||
129
src/ol/layer/xyz_test.js
Normal file
129
src/ol/layer/xyz_test.js
Normal file
@@ -0,0 +1,129 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.tilestore.XYZ');
|
||||
|
||||
|
||||
function testXYZ() {
|
||||
|
||||
var xyzTileStore = new ol.tilestore.XYZ(
|
||||
6, ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}'));
|
||||
var tileGrid = xyzTileStore.getTileGrid();
|
||||
|
||||
var coordinate = new ol.Coordinate(829330.2064098881, 5933916.615134273);
|
||||
var tileUrl;
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 0));
|
||||
assertEquals('0/0/0', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 1));
|
||||
assertEquals('1/1/0', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 2));
|
||||
assertEquals('2/2/1', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 3));
|
||||
assertEquals('3/4/2', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 4));
|
||||
assertEquals('4/8/5', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 5));
|
||||
assertEquals('5/16/11', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(
|
||||
tileGrid.getTileCoordForCoordAndZ(coordinate, 6));
|
||||
assertEquals('6/33/22', tileUrl);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testXYZWrapX() {
|
||||
|
||||
var xyzTileStore = new ol.tilestore.XYZ(
|
||||
6, ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}'));
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, -31, -23));
|
||||
assertEquals('6/33/22', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, 33, -23));
|
||||
assertEquals('6/33/22', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, 97, -23));
|
||||
assertEquals('6/33/22', tileUrl);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testXYZCropY() {
|
||||
|
||||
var xyzTileStore = new ol.tilestore.XYZ(
|
||||
6, ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}'));
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, 33, -87));
|
||||
assertUndefined(tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, 33, -23));
|
||||
assertEquals('6/33/22', tileUrl);
|
||||
|
||||
tileUrl = xyzTileStore.getTileCoordUrl(new ol.TileCoord(6, 33, 41));
|
||||
assertUndefined(tileUrl);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testXYZTileGridForEachTileCoordParentTileBounds() {
|
||||
|
||||
var xyzTileGrid = new ol.tilegrid.XYZ(6);
|
||||
|
||||
var tileCoord = new ol.TileCoord(5, 11, 21);
|
||||
var zs = [], tileBoundss = [];
|
||||
xyzTileGrid.forEachTileCoordParentTileBounds(
|
||||
tileCoord,
|
||||
function(z, tileBounds) {
|
||||
zs.push(z);
|
||||
tileBoundss.push(tileBounds);
|
||||
return false;
|
||||
});
|
||||
|
||||
assertEquals(5, zs.length);
|
||||
assertEquals(5, tileBoundss.length);
|
||||
|
||||
assertEquals(4, zs[0]);
|
||||
assertEquals(5, tileBoundss[0].minX);
|
||||
assertEquals(10, tileBoundss[0].minY);
|
||||
assertEquals(5, tileBoundss[0].maxX);
|
||||
assertEquals(10, tileBoundss[0].maxY);
|
||||
|
||||
assertEquals(3, zs[1]);
|
||||
assertEquals(2, tileBoundss[1].minX);
|
||||
assertEquals(5, tileBoundss[1].minY);
|
||||
assertEquals(2, tileBoundss[1].maxX);
|
||||
assertEquals(5, tileBoundss[1].maxY);
|
||||
|
||||
assertEquals(2, zs[2]);
|
||||
assertEquals(1, tileBoundss[2].minX);
|
||||
assertEquals(2, tileBoundss[2].minY);
|
||||
assertEquals(1, tileBoundss[2].maxX);
|
||||
assertEquals(2, tileBoundss[2].maxY);
|
||||
|
||||
assertEquals(1, zs[3]);
|
||||
assertEquals(0, tileBoundss[3].minX);
|
||||
assertEquals(1, tileBoundss[3].minY);
|
||||
assertEquals(0, tileBoundss[3].maxX);
|
||||
assertEquals(1, tileBoundss[3].maxY);
|
||||
|
||||
assertEquals(0, zs[4]);
|
||||
assertEquals(0, tileBoundss[4].minX);
|
||||
assertEquals(0, tileBoundss[4].minY);
|
||||
assertEquals(0, tileBoundss[4].maxX);
|
||||
assertEquals(0, tileBoundss[4].maxY);
|
||||
|
||||
}
|
||||
808
src/ol/map.js
Normal file
808
src/ol/map.js
Normal file
@@ -0,0 +1,808 @@
|
||||
// FIXME better map browser event types
|
||||
// FIXME recheck layer/map projection compatability when projection changes
|
||||
// FIXME layer renderers should skip when they can't reproject
|
||||
// FIXME add tilt and height?
|
||||
|
||||
goog.provide('ol.Map');
|
||||
goog.provide('ol.MapEventType');
|
||||
goog.provide('ol.MapProperty');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dispose');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.ViewportSizeMonitor');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.events.KeyHandler');
|
||||
goog.require('goog.events.KeyHandler.EventType');
|
||||
goog.require('goog.events.MouseWheelEvent');
|
||||
goog.require('goog.events.MouseWheelHandler');
|
||||
goog.require('goog.events.MouseWheelHandler.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.fx.DragEvent');
|
||||
goog.require('goog.fx.Dragger');
|
||||
goog.require('goog.fx.anim');
|
||||
goog.require('goog.fx.anim.Animated');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Color');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Interaction');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TransformFunction');
|
||||
goog.require('ol.renderer.Layer');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.MapEventType = {
|
||||
POST_RENDER: 'postrender'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.MapProperty = {
|
||||
BACKGROUND_COLOR: 'backgroundColor',
|
||||
CENTER: 'center',
|
||||
INTERACTIONS: 'interactions',
|
||||
LAYERS: 'layers',
|
||||
PROJECTION: 'projection',
|
||||
RESOLUTION: 'resolution',
|
||||
ROTATION: 'rotation',
|
||||
SIZE: 'size',
|
||||
USER_PROJECTION: 'userProjection'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.MapPaneZIndex = {
|
||||
VIEWPORT: 1000
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @implements {goog.fx.anim.Animated}
|
||||
* @param {Element} container Container.
|
||||
* @param {function(new: ol.renderer.Map, Element, ol.Map)} rendererConstructor
|
||||
* Renderer constructor.
|
||||
* @param {Object=} opt_values Values.
|
||||
* @param {goog.dom.ViewportSizeMonitor=} opt_viewportSizeMonitor
|
||||
* Viewport size monitor.
|
||||
*/
|
||||
ol.Map = function(
|
||||
container, rendererConstructor, opt_values, opt_viewportSizeMonitor) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* @protected
|
||||
* @type {goog.debug.Logger}
|
||||
*/
|
||||
this.logger = goog.debug.Logger.getLogger('ol.map.' + goog.getUid(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ol.TransformFunction}
|
||||
* @private
|
||||
*/
|
||||
this.userToMapTransform_ = ol.Projection.identityTransform;
|
||||
|
||||
/**
|
||||
* @type {ol.TransformFunction}
|
||||
* @private
|
||||
*/
|
||||
this.mapToUserTransform_ = ol.Projection.cloneTransform;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.animatedRenderer_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.animatingCount_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.freezeRenderingCount_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.dirty_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.container_ = container;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.viewport_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.viewport_.className = 'ol-viewport';
|
||||
this.viewport_.style.position = 'relative';
|
||||
this.viewport_.style.overflow = 'hidden';
|
||||
this.viewport_.style.width = '100%';
|
||||
this.viewport_.style.height = '100%';
|
||||
this.viewport_.style.zIndex = ol.MapPaneZIndex.VIEWPORT;
|
||||
goog.dom.appendChild(container, this.viewport_);
|
||||
|
||||
goog.events.listen(this.viewport_, [
|
||||
goog.events.EventType.DBLCLICK
|
||||
], this.handleBrowserEvent, false, this);
|
||||
|
||||
// FIXME we probably shouldn't listen on document...
|
||||
var keyHandler = new goog.events.KeyHandler(document);
|
||||
goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
|
||||
this.handleBrowserEvent, false, this);
|
||||
this.registerDisposable(keyHandler);
|
||||
|
||||
var mouseWheelHandler = new goog.events.MouseWheelHandler(this.viewport_);
|
||||
goog.events.listen(mouseWheelHandler,
|
||||
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
|
||||
this.handleBrowserEvent, false, this);
|
||||
this.registerDisposable(mouseWheelHandler);
|
||||
|
||||
var dragger = new goog.fx.Dragger(this.viewport_);
|
||||
dragger.defaultAction = function() {};
|
||||
goog.events.listen(dragger, [
|
||||
goog.fx.Dragger.EventType.START,
|
||||
goog.fx.Dragger.EventType.DRAG,
|
||||
goog.fx.Dragger.EventType.END
|
||||
], this.handleDraggerEvent, false, this);
|
||||
this.registerDisposable(dragger);
|
||||
|
||||
/**
|
||||
* @type {ol.renderer.Map}
|
||||
* @private
|
||||
*/
|
||||
this.renderer_ = new rendererConstructor(this.viewport_, this);
|
||||
this.registerDisposable(this.renderer_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.dom.ViewportSizeMonitor}
|
||||
*/
|
||||
this.viewportSizeMonitor_ =
|
||||
opt_viewportSizeMonitor || new goog.dom.ViewportSizeMonitor();
|
||||
|
||||
goog.events.listen(this.viewportSizeMonitor_, goog.events.EventType.RESIZE,
|
||||
this.handleBrowserWindowResize, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.MapProperty.PROJECTION),
|
||||
this.handleProjectionChanged, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.MapProperty.USER_PROJECTION),
|
||||
this.handleUserProjectionChanged, false, this);
|
||||
|
||||
if (goog.isDef(opt_values)) {
|
||||
this.setValues(opt_values);
|
||||
}
|
||||
|
||||
this.handleBrowserWindowResize();
|
||||
|
||||
};
|
||||
goog.inherits(ol.Map, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can rotate.
|
||||
*/
|
||||
ol.Map.prototype.canRotate = function() {
|
||||
return this.renderer_.canRotate();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.Map.prototype.fitExtent = function(extent) {
|
||||
this.withFrozenRendering(function() {
|
||||
this.setCenter(extent.getCenter());
|
||||
this.setResolution(this.getResolutionForExtent(extent));
|
||||
if (this.canRotate()) {
|
||||
this.setRotation(0);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} userExtent Extent in user projection.
|
||||
*/
|
||||
ol.Map.prototype.fitUserExtent = function(userExtent) {
|
||||
this.fitExtent(userExtent.transform(this.userToMapTransform_));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Freeze rendering.
|
||||
*/
|
||||
ol.Map.prototype.freezeRendering = function() {
|
||||
++this.freezeRenderingCount_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Color|undefined} Background color.
|
||||
*/
|
||||
ol.Map.prototype.getBackgroundColor = function() {
|
||||
return /** @type {ol.Color|undefined} */ (
|
||||
this.get(ol.MapProperty.BACKGROUND_COLOR));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getBackgroundColor',
|
||||
ol.Map.prototype.getBackgroundColor);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate|undefined} Center.
|
||||
*/
|
||||
ol.Map.prototype.getCenter = function() {
|
||||
return /** @type {ol.Coordinate} */ this.get(ol.MapProperty.CENTER);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getCenter',
|
||||
ol.Map.prototype.getCenter);
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Container.
|
||||
*/
|
||||
ol.Map.prototype.getContainer = function() {
|
||||
return this.container_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @return {ol.Coordinate|undefined} Coordinate.
|
||||
*/
|
||||
ol.Map.prototype.getCoordinateFromPixel = function(pixel) {
|
||||
if (this.isDef()) {
|
||||
return this.renderer_.getCoordinateFromPixel(pixel);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent|undefined} Extent.
|
||||
*/
|
||||
ol.Map.prototype.getExtent = function() {
|
||||
if (this.isDef()) {
|
||||
var center = this.getCenter();
|
||||
var resolution = this.getResolution();
|
||||
var size = this.getSize();
|
||||
var minX = center.x - resolution * size.width / 2;
|
||||
var minY = center.y - resolution * size.height / 2;
|
||||
var maxX = center.x + resolution * size.width / 2;
|
||||
var maxY = center.y + resolution * size.height / 2;
|
||||
return new ol.Extent(minX, minY, maxX, maxY);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Collection} Interactions.
|
||||
*/
|
||||
ol.Map.prototype.getInteractions = function() {
|
||||
return /** @type {ol.Collection} */ this.get(ol.MapProperty.INTERACTIONS);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getInteractions',
|
||||
ol.Map.prototype.getInteractions);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Collection} Layers.
|
||||
*/
|
||||
ol.Map.prototype.getLayers = function() {
|
||||
return /** @type {ol.Collection} */ (this.get(ol.MapProperty.LAYERS));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Pixel|undefined} Pixel.
|
||||
*/
|
||||
ol.Map.prototype.getPixelFromCoordinate = function(coordinate) {
|
||||
if (this.isDef()) {
|
||||
return this.renderer_.getPixelFromCoordinate(coordinate);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Projection|undefined} Projection.
|
||||
*/
|
||||
ol.Map.prototype.getProjection = function() {
|
||||
return /** @type {ol.Projection} */ this.get(ol.MapProperty.PROJECTION);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getProjection',
|
||||
ol.Map.prototype.getProjection);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} Resolution.
|
||||
*/
|
||||
ol.Map.prototype.getResolution = function() {
|
||||
return /** @type {number} */ this.get(ol.MapProperty.RESOLUTION);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getResolution',
|
||||
ol.Map.prototype.getResolution);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number|undefined} Resolution.
|
||||
*/
|
||||
ol.Map.prototype.getResolutionForExtent = function(extent) {
|
||||
var size = this.getSize();
|
||||
if (goog.isDef(size)) {
|
||||
var xResolution = (extent.maxX - extent.minX) / size.width;
|
||||
var yResolution = (extent.maxY - extent.minY) / size.height;
|
||||
return Math.max(xResolution, yResolution);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Rotated extent.
|
||||
*/
|
||||
ol.Map.prototype.getRotatedExtent = function() {
|
||||
goog.asserts.assert(this.isDef());
|
||||
var center = /** @type {!ol.Coordinate} */ this.getCenter();
|
||||
var resolution = this.getResolution();
|
||||
var rotation = this.getRotation() || 0;
|
||||
var size = this.getSize();
|
||||
var xScale = resolution * size.width / 2;
|
||||
var yScale = resolution * size.height / 2;
|
||||
var corners = [
|
||||
new ol.Coordinate(-xScale, -yScale),
|
||||
new ol.Coordinate(-xScale, yScale),
|
||||
new ol.Coordinate(xScale, -yScale),
|
||||
new ol.Coordinate(xScale, yScale)
|
||||
];
|
||||
goog.array.forEach(corners, function(corner) {
|
||||
corner.rotate(rotation);
|
||||
corner.add(center);
|
||||
});
|
||||
return ol.Extent.boundingExtent.apply(null, corners);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} Rotation.
|
||||
*/
|
||||
ol.Map.prototype.getRotation = function() {
|
||||
return /** @type {number|undefined} */ this.get(ol.MapProperty.ROTATION);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getRotation',
|
||||
ol.Map.prototype.getRotation);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Size|undefined} Size.
|
||||
*/
|
||||
ol.Map.prototype.getSize = function() {
|
||||
return /** @type {ol.Size|undefined} */ this.get(ol.MapProperty.SIZE);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getSize',
|
||||
ol.Map.prototype.getSize);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate|undefined} Center in user projection.
|
||||
*/
|
||||
ol.Map.prototype.getUserCenter = function() {
|
||||
var center = this.getCenter();
|
||||
if (goog.isDef(center)) {
|
||||
return this.mapToUserTransform_(center);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent|undefined} Extent in user projection.
|
||||
*/
|
||||
ol.Map.prototype.getUserExtent = function() {
|
||||
var extent = this.getExtent();
|
||||
if (goog.isDef(extent)) {
|
||||
return extent.transform(this.mapToUserTransform_);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @return {ol.Projection|undefined} Projection.
|
||||
*/
|
||||
ol.Map.prototype.getUserProjection = function() {
|
||||
return /** @type {ol.Projection} */ this.get(
|
||||
ol.MapProperty.USER_PROJECTION);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getUserProjection',
|
||||
ol.Map.prototype.getUserProjection);
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Viewport.
|
||||
*/
|
||||
ol.Map.prototype.getViewport = function() {
|
||||
return this.viewport_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {string=} opt_type Type.
|
||||
*/
|
||||
ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) {
|
||||
var type = opt_type || browserEvent.type;
|
||||
var mapBrowserEvent = new ol.MapBrowserEvent(type, this, browserEvent);
|
||||
var interactions = this.getInteractions();
|
||||
var interactionsArray = /** @type {Array.<ol.Interaction>} */
|
||||
interactions.getArray();
|
||||
goog.array.every(interactionsArray, function(interaction) {
|
||||
interaction.handleMapBrowserEvent(mapBrowserEvent);
|
||||
return !mapBrowserEvent.defaultPrevented;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.fx.DragEvent} dragEvent Drag event.
|
||||
*/
|
||||
ol.Map.prototype.handleDraggerEvent = function(dragEvent) {
|
||||
var browserEvent = dragEvent.browserEvent;
|
||||
this.handleBrowserEvent(browserEvent, dragEvent.type);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.Map.prototype.handleProjectionChanged = function() {
|
||||
this.recalculateTransforms_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.Map.prototype.handleUserProjectionChanged = function() {
|
||||
this.recalculateTransforms_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.Map.prototype.handleBrowserWindowResize = function() {
|
||||
var size = new ol.Size(this.container_.clientWidth,
|
||||
this.container_.clientHeight);
|
||||
this.setSize(size);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is animating.
|
||||
*/
|
||||
ol.Map.prototype.isAnimating = function() {
|
||||
return this.animatingCount_ > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is defined.
|
||||
*/
|
||||
ol.Map.prototype.isDef = function() {
|
||||
return goog.isDefAndNotNull(this.getCenter()) &&
|
||||
goog.isDef(this.getResolution()) &&
|
||||
goog.isDefAndNotNull(this.getSize());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.Map.prototype.onAnimationFrame = function() {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('onAnimationFrame');
|
||||
}
|
||||
this.renderFrame_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.recalculateTransforms_ = function() {
|
||||
var projection = this.getProjection();
|
||||
var userProjection = this.getUserProjection();
|
||||
if (goog.isDefAndNotNull(projection) &&
|
||||
goog.isDefAndNotNull(userProjection)) {
|
||||
this.mapToUserTransform_ = ol.Projection.getTransform(
|
||||
projection, userProjection);
|
||||
this.userToMapTransform_ = ol.Projection.getTransform(
|
||||
userProjection, projection);
|
||||
} else {
|
||||
this.mapToUserTransform_ = ol.Projection.cloneTransform;
|
||||
this.userToMapTransform_ = ol.Projection.identityTransform;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render.
|
||||
*/
|
||||
ol.Map.prototype.render = function() {
|
||||
if (this.animatingCount_ < 1) {
|
||||
if (this.freezeRenderingCount_ === 0) {
|
||||
this.renderFrame_();
|
||||
} else {
|
||||
this.dirty_ = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.renderFrame_ = function() {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('renderFrame_');
|
||||
}
|
||||
var animatedRenderer = this.renderer_.render();
|
||||
this.dirty_ = false;
|
||||
if (animatedRenderer != this.animatedRenderer_) {
|
||||
if (animatedRenderer) {
|
||||
this.startAnimating();
|
||||
} else {
|
||||
this.stopAnimating();
|
||||
}
|
||||
this.animatedRenderer_ = animatedRenderer;
|
||||
}
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('postrender');
|
||||
}
|
||||
this.dispatchEvent(ol.MapEventType.POST_RENDER);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} backgroundColor Background color.
|
||||
*/
|
||||
ol.Map.prototype.setBackgroundColor = function(backgroundColor) {
|
||||
this.set(ol.MapProperty.BACKGROUND_COLOR, backgroundColor);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setBackgroundColor',
|
||||
ol.Map.prototype.setBackgroundColor);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} center Center.
|
||||
*/
|
||||
ol.Map.prototype.setCenter = function(center) {
|
||||
this.set(ol.MapProperty.CENTER, center);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setCenter',
|
||||
ol.Map.prototype.setCenter);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Collection} interactions Interactions.
|
||||
*/
|
||||
ol.Map.prototype.setInteractions = function(interactions) {
|
||||
this.set(ol.MapProperty.INTERACTIONS, interactions);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setInteractions',
|
||||
ol.Map.prototype.setInteractions);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {ol.Collection} layers Layers.
|
||||
*/
|
||||
ol.Map.prototype.setLayers = function(layers) {
|
||||
this.set(ol.MapProperty.LAYERS, layers);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setLayers',
|
||||
ol.Map.prototype.setLayers);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {ol.Projection} projection Projection.
|
||||
*/
|
||||
ol.Map.prototype.setProjection = function(projection) {
|
||||
this.set(ol.MapProperty.PROJECTION, projection);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setProjection',
|
||||
ol.Map.prototype.setProjection);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
*/
|
||||
ol.Map.prototype.setResolution = function(resolution) {
|
||||
this.set(ol.MapProperty.RESOLUTION, resolution);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setResolution',
|
||||
ol.Map.prototype.setResolution);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {number|undefined} rotation Rotation.
|
||||
*/
|
||||
ol.Map.prototype.setRotation = function(rotation) {
|
||||
this.set(ol.MapProperty.ROTATION, rotation);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setRotation',
|
||||
ol.Map.prototype.setRotation);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Size} size Size.
|
||||
*/
|
||||
ol.Map.prototype.setSize = function(size) {
|
||||
var currentSize = this.getSize();
|
||||
if (!goog.isDef(currentSize) || !currentSize.equals(size)) {
|
||||
this.set(ol.MapProperty.SIZE, size);
|
||||
}
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setSize',
|
||||
ol.Map.prototype.setSize);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {ol.Coordinate} userCenter Center in user projection.
|
||||
*/
|
||||
ol.Map.prototype.setUserCenter = function(userCenter) {
|
||||
this.setCenter(this.userToMapTransform_(userCenter));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setUserCenter',
|
||||
ol.Map.prototype.setUserCenter);
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @param {ol.Projection} userProjection User projection.
|
||||
*/
|
||||
ol.Map.prototype.setUserProjection = function(userProjection) {
|
||||
this.set(ol.MapProperty.USER_PROJECTION, userProjection);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'setUserProjection',
|
||||
ol.Map.prototype.setUserProjection);
|
||||
|
||||
|
||||
/**
|
||||
* Start animating.
|
||||
*/
|
||||
ol.Map.prototype.startAnimating = function() {
|
||||
if (++this.animatingCount_ == 1) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('startAnimating');
|
||||
}
|
||||
goog.fx.anim.registerAnimation(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stop animating.
|
||||
*/
|
||||
ol.Map.prototype.stopAnimating = function() {
|
||||
goog.asserts.assert(this.animatingCount_ > 0);
|
||||
if (--this.animatingCount_ === 0) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('stopAnimating');
|
||||
}
|
||||
goog.fx.anim.unregisterAnimation(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unfreeze rendering.
|
||||
*/
|
||||
ol.Map.prototype.unfreezeRendering = function() {
|
||||
goog.asserts.assert(this.freezeRenderingCount_ > 0);
|
||||
if (--this.freezeRenderingCount_ === 0 &&
|
||||
this.animatingCount_ < 1 &&
|
||||
this.dirty_) {
|
||||
this.renderFrame_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(this: T)} f Function.
|
||||
* @param {T=} opt_obj Object.
|
||||
* @template T
|
||||
*/
|
||||
ol.Map.prototype.withFrozenRendering = function(f, opt_obj) {
|
||||
this.freezeRendering();
|
||||
try {
|
||||
f.call(opt_obj);
|
||||
} finally {
|
||||
this.unfreezeRendering();
|
||||
}
|
||||
};
|
||||
53
src/ol/mapbrowserevent.js
Normal file
53
src/ol/mapbrowserevent.js
Normal file
@@ -0,0 +1,53 @@
|
||||
goog.provide('ol.MapBrowserEvent');
|
||||
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.MapEvent');
|
||||
goog.require('ol.Pixel');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.MapEvent}
|
||||
* @param {string} type Event type.
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
*/
|
||||
ol.MapBrowserEvent = function(type, map, browserEvent) {
|
||||
|
||||
goog.base(this, type, map);
|
||||
|
||||
/**
|
||||
* @type {goog.events.BrowserEvent}
|
||||
*/
|
||||
this.browserEvent = browserEvent;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate|undefined}
|
||||
*/
|
||||
this.coordinate_ = undefined;
|
||||
|
||||
};
|
||||
goog.inherits(ol.MapBrowserEvent, ol.MapEvent);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate|undefined} Coordinate.
|
||||
*/
|
||||
ol.MapBrowserEvent.prototype.getCoordinate = function() {
|
||||
if (goog.isDef(this.coordinate_)) {
|
||||
return this.coordinate_;
|
||||
} else {
|
||||
var map = this.map;
|
||||
var browserEvent = this.browserEvent;
|
||||
var eventPosition = goog.style.getRelativePosition(
|
||||
browserEvent, map.getViewport());
|
||||
var pixel = new ol.Pixel(eventPosition.x, eventPosition.y);
|
||||
var coordinate = map.getCoordinateFromPixel(pixel);
|
||||
this.coordinate_ = coordinate;
|
||||
return coordinate;
|
||||
}
|
||||
};
|
||||
37
src/ol/mapevent.js
Normal file
37
src/ol/mapevent.js
Normal file
@@ -0,0 +1,37 @@
|
||||
goog.provide('ol.MapEvent');
|
||||
|
||||
goog.require('goog.events.Event');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @param {string} type Event type.
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.MapEvent = function(type, map) {
|
||||
|
||||
goog.base(this, type);
|
||||
|
||||
/**
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map = map;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.defaultPrevented = false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.MapEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* Prevents the default action.
|
||||
*/
|
||||
ol.MapEvent.prototype.preventDefault = function() {
|
||||
goog.base(this, 'preventDefault');
|
||||
this.defaultPrevented = true;
|
||||
};
|
||||
268
src/ol/object.js
Normal file
268
src/ol/object.js
Normal file
@@ -0,0 +1,268 @@
|
||||
|
||||
/**
|
||||
* @fileoverview An implementation of Google Maps' MVCObject.
|
||||
* @see https://developers.google.com/maps/articles/mvcfun
|
||||
* @see https://developers.google.com/maps/documentation/javascript/reference
|
||||
*/
|
||||
|
||||
goog.provide('ol.Object');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.ObjectProperty = {
|
||||
ACCESSORS: 'ol_accessors_',
|
||||
BINDINGS: 'ol_bindings_'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.Object = function(opt_values) {
|
||||
goog.base(this);
|
||||
if (goog.isDef(opt_values)) {
|
||||
this.setValues(opt_values);
|
||||
}
|
||||
};
|
||||
goog.inherits(ol.Object, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, string>}
|
||||
*/
|
||||
ol.Object.changedEventTypeCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, string>}
|
||||
*/
|
||||
ol.Object.getterNameCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, string>}
|
||||
*/
|
||||
ol.Object.setterNameCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} str String.
|
||||
* @return {string} Capitalized string.
|
||||
*/
|
||||
ol.Object.capitalize = function(str) {
|
||||
return str.substr(0, 1).toUpperCase() + str.substr(1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Object} obj Object.
|
||||
* @return {Object.<string, {target: ol.Object, key: string}>} Accessors.
|
||||
*/
|
||||
ol.Object.getAccessors = function(obj) {
|
||||
return obj[ol.ObjectProperty.ACCESSORS] ||
|
||||
(obj[ol.ObjectProperty.ACCESSORS] = {});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
* @return {string} Changed name.
|
||||
*/
|
||||
ol.Object.getChangedEventType = function(key) {
|
||||
return ol.Object.changedEventTypeCache_[key] ||
|
||||
(ol.Object.changedEventTypeCache_[key] = key.toLowerCase() + '_changed');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key String.
|
||||
* @return {string} Getter name.
|
||||
*/
|
||||
ol.Object.getGetterName = function(key) {
|
||||
return ol.Object.getterNameCache_[key] ||
|
||||
(ol.Object.getterNameCache_[key] = 'get' + ol.Object.capitalize(key));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Object} obj Object.
|
||||
* @return {Object.<string, ?number>} Listeners.
|
||||
*/
|
||||
ol.Object.getListeners = function(obj) {
|
||||
return obj[ol.ObjectProperty.BINDINGS] ||
|
||||
(obj[ol.ObjectProperty.BINDINGS] = {});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key String.
|
||||
* @return {string} Setter name.
|
||||
*/
|
||||
ol.Object.getSetterName = function(key) {
|
||||
return ol.Object.setterNameCache_[key] ||
|
||||
(ol.Object.setterNameCache_[key] = 'set' + ol.Object.capitalize(key));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
* @param {ol.Object} target Target.
|
||||
* @param {string=} opt_targetKey Target key.
|
||||
* @param {boolean=} opt_noNotify No notify.
|
||||
*/
|
||||
ol.Object.prototype.bindTo =
|
||||
function(key, target, opt_targetKey, opt_noNotify) {
|
||||
var targetKey = opt_targetKey || key;
|
||||
this.unbind(key);
|
||||
var eventType = ol.Object.getChangedEventType(targetKey);
|
||||
var listeners = ol.Object.getListeners(this);
|
||||
listeners[key] = goog.events.listen(target, eventType, function() {
|
||||
this.notifyInternal_(key);
|
||||
}, undefined, this);
|
||||
var accessors = ol.Object.getAccessors(this);
|
||||
accessors[key] = {target: target, key: targetKey};
|
||||
var noNotify = opt_noNotify || false;
|
||||
if (!noNotify) {
|
||||
this.notifyInternal_(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
*/
|
||||
ol.Object.prototype.changed = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
* @return {*} Value.
|
||||
*/
|
||||
ol.Object.prototype.get = function(key) {
|
||||
var accessors = ol.Object.getAccessors(this);
|
||||
if (goog.object.containsKey(accessors, key)) {
|
||||
var accessor = accessors[key];
|
||||
var target = accessor.target;
|
||||
var targetKey = accessor.key;
|
||||
var getterName = ol.Object.getGetterName(targetKey);
|
||||
if (target[getterName]) {
|
||||
return target[getterName]();
|
||||
} else {
|
||||
return target.get(targetKey);
|
||||
}
|
||||
} else {
|
||||
return this[key];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
*/
|
||||
ol.Object.prototype.notify = function(key) {
|
||||
var accessors = ol.Object.getAccessors(this);
|
||||
if (goog.object.containsKey(accessors, key)) {
|
||||
var accessor = accessors[key];
|
||||
var target = accessor.target;
|
||||
var targetKey = accessor.key;
|
||||
target.notify(targetKey);
|
||||
} else {
|
||||
this.notifyInternal_(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
* @private
|
||||
*/
|
||||
ol.Object.prototype.notifyInternal_ = function(key) {
|
||||
var eventType = ol.Object.getChangedEventType(key);
|
||||
this.dispatchEvent(eventType);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
* @param {*} value Value.
|
||||
*/
|
||||
ol.Object.prototype.set = function(key, value) {
|
||||
var accessors = ol.Object.getAccessors(this);
|
||||
if (goog.object.containsKey(accessors, key)) {
|
||||
var accessor = accessors[key];
|
||||
var target = accessor.target;
|
||||
var targetKey = accessor.key;
|
||||
var setterName = ol.Object.getSetterName(targetKey);
|
||||
if (target[setterName]) {
|
||||
target[setterName](value);
|
||||
} else {
|
||||
target.set(targetKey, value);
|
||||
}
|
||||
} else {
|
||||
this[key] = value;
|
||||
this.notifyInternal_(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, *>} options Options.
|
||||
*/
|
||||
ol.Object.prototype.setOptions = function(options) {
|
||||
goog.object.forEach(options, function(value, key) {
|
||||
var setterName = ol.Object.getSetterName(key);
|
||||
if (this[setterName]) {
|
||||
this[setterName](value);
|
||||
} else {
|
||||
this.set(key, value);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, *>} values Values.
|
||||
*/
|
||||
ol.Object.prototype.setValues = ol.Object.prototype.setOptions;
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} key Key.
|
||||
*/
|
||||
ol.Object.prototype.unbind = function(key) {
|
||||
var listeners = ol.Object.getListeners(this);
|
||||
var listener = listeners[key];
|
||||
if (listener) {
|
||||
delete listeners[key];
|
||||
goog.events.unlistenByKey(listener);
|
||||
var value = this.get(key);
|
||||
var accessors = ol.Object.getAccessors(this);
|
||||
delete accessors[key];
|
||||
this[key] = value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all bindings.
|
||||
*/
|
||||
ol.Object.prototype.unbindAll = function() {
|
||||
var listeners = ol.Object.getListeners(this);
|
||||
var keys = goog.object.getKeys(listeners);
|
||||
goog.array.forEach(keys, function(key) {
|
||||
this.unbind(key);
|
||||
}, this);
|
||||
};
|
||||
389
src/ol/object_test.js
Normal file
389
src/ol/object_test.js
Normal file
@@ -0,0 +1,389 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
function testModel() {
|
||||
var m = new ol.Object();
|
||||
assertNotNullNorUndefined(m);
|
||||
}
|
||||
|
||||
|
||||
function testGetUndefined() {
|
||||
var m = new ol.Object();
|
||||
assertUndefined(m.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testGetSetGet() {
|
||||
var m = new ol.Object();
|
||||
assertUndefined(m.get('k'));
|
||||
m.set('k', 1);
|
||||
assertEquals(1, m.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testSetValues() {
|
||||
var m = new ol.Object();
|
||||
m.setValues({
|
||||
k1: 1,
|
||||
k2: 2
|
||||
});
|
||||
assertEquals(1, m.get('k1'));
|
||||
assertEquals(2, m.get('k2'));
|
||||
}
|
||||
|
||||
|
||||
function testNotifyKeyEvent() {
|
||||
var m = new ol.Object();
|
||||
var eventDispatched = false;
|
||||
goog.events.listen(m, 'k_changed', function() {
|
||||
eventDispatched = true;
|
||||
});
|
||||
m.notify('k');
|
||||
assertTrue(eventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testBindSetNotifyKeyEvent() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
var callbackCalled = false;
|
||||
goog.events.listen(n, 'k_changed', function() {
|
||||
eventDispatched = true;
|
||||
});
|
||||
n.bindTo('k', m);
|
||||
m.set('k', 1);
|
||||
assertTrue(eventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testSetNotifyKeyEvent() {
|
||||
var m = new ol.Object();
|
||||
var eventDispatched = false;
|
||||
goog.events.listen(m, 'k_changed', function() {
|
||||
eventDispatched = true;
|
||||
});
|
||||
m.set('k', 1);
|
||||
assertTrue(eventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testSetBind() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
m.set('k', 1);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertUndefined(n.get('k'));
|
||||
n.bindTo('k', m);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(1, n.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testBindSet() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('k', m);
|
||||
m.set('k', 1);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(1, n.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testBindSetBackwards() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('k', m);
|
||||
n.set('k', 1);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(1, n.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testSetBindBackwards() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.set('k', 1);
|
||||
n.bindTo('k', m);
|
||||
assertUndefined(m.get('k'));
|
||||
assertUndefined(n.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testBindSetUnbind() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('k', m);
|
||||
n.set('k', 1);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(1, n.get('k'));
|
||||
n.unbind('k');
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(1, n.get('k'));
|
||||
n.set('k', 2);
|
||||
assertEquals(1, m.get('k'));
|
||||
assertEquals(2, n.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testUnbindAll() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('k', m);
|
||||
n.set('k', 1);
|
||||
assertEquals(m.get('k'), 1);
|
||||
assertEquals(n.get('k'), 1);
|
||||
n.unbindAll();
|
||||
assertEquals(m.get('k'), 1);
|
||||
assertEquals(n.get('k'), 1);
|
||||
n.set('k', 2);
|
||||
assertEquals(m.get('k'), 1);
|
||||
assertEquals(n.get('k'), 2);
|
||||
}
|
||||
|
||||
|
||||
function testBindNotify() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
m.bindTo('k', n);
|
||||
mEventDispatched = false;
|
||||
goog.events.listen(m, 'k_changed', function() {
|
||||
mEventDispatched = true;
|
||||
});
|
||||
nEventDispatched = false;
|
||||
goog.events.listen(n, 'k_changed', function() {
|
||||
nEventDispatched = true;
|
||||
});
|
||||
n.set('k', 1);
|
||||
assertTrue(mEventDispatched);
|
||||
assertTrue(nEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testBindBackwardsNotify() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('k', m);
|
||||
mEventDispatched = false;
|
||||
goog.events.listen(m, 'k_changed', function() {
|
||||
mEventDispatched = true;
|
||||
});
|
||||
nEventDispatched = false;
|
||||
goog.events.listen(n, 'k_changed', function() {
|
||||
nEventDispatched = true;
|
||||
});
|
||||
n.set('k', 1);
|
||||
assertTrue(mEventDispatched);
|
||||
assertTrue(nEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testBindRename() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
n.bindTo('kn', m, 'km');
|
||||
m.set('km', 1);
|
||||
assertEquals(m.get('km'), 1);
|
||||
assertEquals(n.get('kn'), 1);
|
||||
}
|
||||
|
||||
|
||||
function testBindRenameEvents() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
kmEventDispatched = false;
|
||||
goog.events.listen(m, 'km_changed', function() {
|
||||
kmEventDispatched = true;
|
||||
});
|
||||
knEventDispatched = false;
|
||||
goog.events.listen(n, 'kn_changed', function() {
|
||||
knEventDispatched = true;
|
||||
});
|
||||
n.bindTo('kn', m, 'km');
|
||||
m.set('km', 1);
|
||||
assertEquals(m.get('km'), 1);
|
||||
assertEquals(n.get('kn'), 1);
|
||||
assertTrue(kmEventDispatched);
|
||||
assertTrue(knEventDispatched);
|
||||
}
|
||||
|
||||
|
||||
function testTransitiveBindForwards() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
var o = new ol.Object();
|
||||
n.bindTo('kn', m, 'km');
|
||||
o.bindTo('ko', n, 'kn');
|
||||
m.set('km', 1);
|
||||
assertEquals(1, m.get('km'));
|
||||
assertEquals(1, n.get('kn'));
|
||||
assertEquals(1, o.get('ko'));
|
||||
}
|
||||
|
||||
|
||||
function testTransitiveBindBackwards() {
|
||||
var m = new ol.Object();
|
||||
var n = new ol.Object();
|
||||
var o = new ol.Object();
|
||||
n.bindTo('kn', m, 'km');
|
||||
o.bindTo('ko', n, 'kn');
|
||||
o.set('ko', 1);
|
||||
assertEquals(1, m.get('km'));
|
||||
assertEquals(1, n.get('kn'));
|
||||
assertEquals(1, o.get('ko'));
|
||||
}
|
||||
|
||||
|
||||
function testMrideyAccessors() {
|
||||
// http://blog.mridey.com/2010/03/maps-javascript-api-v3-more-about.html
|
||||
var a = new ol.Object();
|
||||
a.set('level', 2);
|
||||
assertEquals(2, a.get('level'));
|
||||
var b = new ol.Object();
|
||||
b.setValues({
|
||||
level: 2,
|
||||
index: 3,
|
||||
description: 'Hello world.'
|
||||
});
|
||||
assertEquals(3, b.get('index'));
|
||||
}
|
||||
|
||||
|
||||
function testMrideyBinding() {
|
||||
// http://blog.mridey.com/2010/03/maps-javascript-api-v3-more-about.html
|
||||
var a = new ol.Object();
|
||||
a.set('level', 2);
|
||||
var b = new ol.Object();
|
||||
b.bindTo('index', a, 'level');
|
||||
assertEquals(2, b.get('index'));
|
||||
a.set('level', 3);
|
||||
assertEquals(3, b.get('index'));
|
||||
b.set('index', 4);
|
||||
assertEquals(4, a.get('level'));
|
||||
var c = new ol.Object();
|
||||
c.bindTo('zoom', a, 'level');
|
||||
assertEquals(4, c.get('zoom'));
|
||||
b.unbind('index');
|
||||
assertEquals(4, b.get('index'));
|
||||
c.set('zoom', 5);
|
||||
assertEquals(5, a.get('level'));
|
||||
assertEquals(4, b.get('index'));
|
||||
}
|
||||
|
||||
|
||||
function testCircularBind() {
|
||||
var a = new ol.Object();
|
||||
var b = new ol.Object();
|
||||
a.bindTo('k', b);
|
||||
assertThrows(function() {
|
||||
b.bindTo('k', a);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testPriority() {
|
||||
var a = new ol.Object();
|
||||
var b = new ol.Object();
|
||||
a.set('k', 1);
|
||||
b.set('k', 2);
|
||||
a.bindTo('k', b);
|
||||
assertEquals(2, a.get('k'));
|
||||
assertEquals(2, b.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testPriorityUndefined() {
|
||||
var a = new ol.Object();
|
||||
var b = new ol.Object();
|
||||
a.set('k', 1);
|
||||
a.bindTo('k', b);
|
||||
assertUndefined(a.get('k'));
|
||||
assertUndefined(b.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testSetter() {
|
||||
var a = new ol.Object();
|
||||
var x;
|
||||
var setterCalled;
|
||||
a.setX = function(value) {
|
||||
this.x = value;
|
||||
setterCalled = true;
|
||||
};
|
||||
a.set('x', 1);
|
||||
assertEquals(1, a.get('x'));
|
||||
assertUndefined(setterCalled);
|
||||
}
|
||||
|
||||
|
||||
function testSetterBind() {
|
||||
var a = new ol.Object();
|
||||
var x;
|
||||
var setterCalled;
|
||||
a.setX = function(value) {
|
||||
this.x = value;
|
||||
setterCalled = true;
|
||||
};
|
||||
var b = new ol.Object();
|
||||
b.bindTo('x', a);
|
||||
b.set('x', 1);
|
||||
assertEquals(1, a.get('x'));
|
||||
assertEquals(1, b.get('x'));
|
||||
assertTrue(setterCalled);
|
||||
}
|
||||
|
||||
|
||||
function testGetter() {
|
||||
var a = new ol.Object();
|
||||
var getterCalled;
|
||||
a.getX = function() {
|
||||
getterCalled = true;
|
||||
return 1;
|
||||
};
|
||||
assertUndefined(a.get('x'));
|
||||
assertUndefined(getterCalled);
|
||||
}
|
||||
|
||||
|
||||
function testGetterBind() {
|
||||
var a = new ol.Object();
|
||||
var getterCalled;
|
||||
a.getX = function() {
|
||||
getterCalled = true;
|
||||
return 1;
|
||||
};
|
||||
var b = new ol.Object();
|
||||
b.bindTo('x', a);
|
||||
assertEquals(1, b.get('x'));
|
||||
assertTrue(getterCalled);
|
||||
}
|
||||
|
||||
|
||||
function testBindSelf() {
|
||||
var a = new ol.Object();
|
||||
assertThrows(function() {
|
||||
a.bindTo('k', a);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateWithOptions() {
|
||||
var obj = new ol.Object({k: 1});
|
||||
assertEquals(1, obj.get('k'));
|
||||
}
|
||||
|
||||
|
||||
function testEventTypeCaseSensitivity() {
|
||||
var obj = new ol.Object();
|
||||
var lowercaseEventDispatched = false;
|
||||
goog.events.listen(obj, 'k_changed', function() {
|
||||
lowercaseEventDispatched = true;
|
||||
});
|
||||
var uppercaseEventDispatched = false;
|
||||
goog.events.listen(obj, 'K_changed', function() {
|
||||
uppercaseEventDispatched = true;
|
||||
});
|
||||
obj.set('K', 1);
|
||||
assertTrue(lowercaseEventDispatched);
|
||||
assertFalse(uppercaseEventDispatched);
|
||||
}
|
||||
9
src/ol/ol.js
Normal file
9
src/ol/ol.js
Normal file
@@ -0,0 +1,9 @@
|
||||
goog.provide('ol');
|
||||
|
||||
goog.require('goog.debug.Logger');
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
var logger = goog.debug.Logger.getLogger('ol');
|
||||
logger.setLevel(goog.debug.Logger.Level.FINEST);
|
||||
}
|
||||
24
src/ol/pixel.js
Normal file
24
src/ol/pixel.js
Normal file
@@ -0,0 +1,24 @@
|
||||
goog.provide('ol.Pixel');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.math.Coordinate}
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
ol.Pixel = function(x, y) {
|
||||
goog.base(this, x, y);
|
||||
};
|
||||
goog.inherits(ol.Pixel, goog.math.Coordinate);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Pixel} Clone.
|
||||
*/
|
||||
ol.Pixel.prototype.clone = function() {
|
||||
return new ol.Pixel(this.x, this.y);
|
||||
};
|
||||
18
src/ol/pixelbounds.js
Normal file
18
src/ol/pixelbounds.js
Normal file
@@ -0,0 +1,18 @@
|
||||
goog.provide('ol.PixelBounds');
|
||||
|
||||
goog.require('ol.Rectangle');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Rectangle}
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
*/
|
||||
ol.PixelBounds = function(minX, minY, maxX, maxY) {
|
||||
goog.base(this, minX, minY, maxX, maxY);
|
||||
};
|
||||
goog.inherits(ol.PixelBounds, ol.Rectangle);
|
||||
500
src/ol/projection.js
Normal file
500
src/ol/projection.js
Normal file
@@ -0,0 +1,500 @@
|
||||
goog.provide('ol.Projection');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.TransformFunction');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Enable Proj4js.
|
||||
*/
|
||||
ol.ENABLE_PROJ4JS = true;
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.ProjectionUnits = {
|
||||
DEGREES: 'degrees',
|
||||
METERS: 'm'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string} code Code.
|
||||
* @param {ol.ProjectionUnits} units Units.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.Projection = function(code, units, extent) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.code_ = code;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.ProjectionUnits}
|
||||
*/
|
||||
this.units_ = units;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.extent_ = extent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Code.
|
||||
*/
|
||||
ol.Projection.prototype.getCode = function() {
|
||||
return this.code_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.Projection.prototype.getExtent = function() {
|
||||
return this.extent_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.ProjectionUnits} Units.
|
||||
*/
|
||||
ol.Projection.prototype.getUnits = function() {
|
||||
return this.units_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Projection}
|
||||
* @param {string} code Code.
|
||||
* @param {Proj4js.Proj} proj4jsProj Proj4js projection.
|
||||
*/
|
||||
ol.Proj4jsProjection = function(code, proj4jsProj) {
|
||||
|
||||
var units = /** @type {ol.ProjectionUnits} */ proj4jsProj.units;
|
||||
|
||||
goog.base(this, code, units, null);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Proj4js.Proj}
|
||||
*/
|
||||
this.proj4jsProj_ = proj4jsProj;
|
||||
|
||||
};
|
||||
goog.inherits(ol.Proj4jsProjection, ol.Projection);
|
||||
|
||||
|
||||
/**
|
||||
* @return {Proj4js.Proj} Proj4js projection.
|
||||
*/
|
||||
ol.Proj4jsProjection.prototype.getProj4jsProj = function() {
|
||||
return this.proj4jsProj_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.Proj4jsProjection>}
|
||||
*/
|
||||
ol.Projection.proj4jsProjections_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.Projection>}
|
||||
*/
|
||||
ol.Projection.projections_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, Object.<string, ol.TransformFunction>>}
|
||||
*/
|
||||
ol.Projection.transforms_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Projection>} projections Projections.
|
||||
* @private
|
||||
*/
|
||||
ol.Projection.addEquivalentProjections_ = function(projections) {
|
||||
ol.Projection.addProjections(projections);
|
||||
goog.array.forEach(projections, function(source) {
|
||||
goog.array.forEach(projections, function(destination) {
|
||||
ol.Projection.addTransform(
|
||||
source, destination, ol.Projection.cloneTransform);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Projection>} projections1 Projections.
|
||||
* @param {Array.<ol.Projection>} projections2 Projections.
|
||||
* @param {ol.TransformFunction} forwardTransform Forward transform.
|
||||
* @param {ol.TransformFunction} inverseTransform Inverse transform.
|
||||
* @private
|
||||
*/
|
||||
ol.Projection.addEquivalentTransforms_ =
|
||||
function(projections1, projections2, forwardTransform, inverseTransform) {
|
||||
goog.array.forEach(projections1, function(projection1) {
|
||||
goog.array.forEach(projections2, function(projection2) {
|
||||
ol.Projection.addTransform(projection1, projection2, forwardTransform);
|
||||
ol.Projection.addTransform(projection2, projection1, inverseTransform);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Proj4jsProjection} proj4jsProjection Proj4js projection.
|
||||
*/
|
||||
ol.Projection.addProj4jsProjection = function(proj4jsProjection) {
|
||||
var proj4jsProjections = ol.Projection.proj4jsProjections_;
|
||||
var code = proj4jsProjection.getCode();
|
||||
goog.asserts.assert(!goog.object.containsKey(proj4jsProjections, code));
|
||||
proj4jsProjections[code] = proj4jsProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Projection} projection Projection.
|
||||
*/
|
||||
ol.Projection.addProjection = function(projection) {
|
||||
var projections = ol.Projection.projections_;
|
||||
var code = projection.getCode();
|
||||
goog.asserts.assert(!goog.object.containsKey(projections, code));
|
||||
projections[code] = projection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Projection>} projections Projections.
|
||||
*/
|
||||
ol.Projection.addProjections = function(projections) {
|
||||
goog.array.forEach(projections, function(projection) {
|
||||
ol.Projection.addProjection(projection);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Projection} source Source.
|
||||
* @param {ol.Projection} destination Destination.
|
||||
* @param {ol.TransformFunction} transformFn Transform.
|
||||
*/
|
||||
ol.Projection.addTransform = function(source, destination, transformFn) {
|
||||
var projections = ol.Projection.projections_;
|
||||
var sourceCode = source.getCode();
|
||||
var destinationCode = destination.getCode();
|
||||
var transforms = ol.Projection.transforms_;
|
||||
if (!goog.object.containsKey(transforms, sourceCode)) {
|
||||
transforms[sourceCode] = {};
|
||||
}
|
||||
goog.asserts.assert(
|
||||
!goog.object.containsKey(transforms[sourceCode], destinationCode));
|
||||
transforms[sourceCode][destinationCode] = transformFn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} code Code.
|
||||
* @return {ol.Projection} Projection.
|
||||
*/
|
||||
ol.Projection.getFromCode = function(code) {
|
||||
var projection = ol.Projection.projections_[code];
|
||||
if (ol.Projection.isProj4jsSupported() && !goog.isDef(projection)) {
|
||||
projection = ol.Projection.getProj4jsProjectionFromCode_(code);
|
||||
}
|
||||
if (!goog.isDef(projection)) {
|
||||
goog.asserts.assert(goog.isDef(projection));
|
||||
projection = null;
|
||||
}
|
||||
return projection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} code Code.
|
||||
* @private
|
||||
* @return {ol.Proj4jsProjection} Proj4js projection.
|
||||
*/
|
||||
ol.Projection.getProj4jsProjectionFromCode_ = function(code) {
|
||||
var proj4jsProjections = ol.Projection.proj4jsProjections_;
|
||||
var proj4jsProjection = proj4jsProjections[code];
|
||||
if (!goog.isDef(proj4jsProjection)) {
|
||||
var proj4jsProj = new Proj4js.Proj(code);
|
||||
proj4jsProjection = new ol.Proj4jsProjection(code, proj4jsProj);
|
||||
proj4jsProjections[code] = proj4jsProjection;
|
||||
}
|
||||
return proj4jsProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Projection} projection1 Projection 1.
|
||||
* @param {ol.Projection} projection2 Projection 2.
|
||||
* @return {boolean} Equivalent.
|
||||
*/
|
||||
ol.Projection.equivalent = function(projection1, projection2) {
|
||||
if (projection1 === projection2) {
|
||||
return true;
|
||||
} else if (projection1.getUnits() != projection2.getUnits()) {
|
||||
return false;
|
||||
} else {
|
||||
var transformFn = ol.Projection.getTransform(projection1, projection2);
|
||||
return transformFn === ol.Projection.cloneTransform;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Projection} source Source.
|
||||
* @param {ol.Projection} destination Destination.
|
||||
* @return {ol.TransformFunction} Transform.
|
||||
*/
|
||||
ol.Projection.getTransform = function(source, destination) {
|
||||
var transforms = ol.Projection.transforms_;
|
||||
var sourceCode = source.getCode();
|
||||
var destinationCode = destination.getCode();
|
||||
var transform;
|
||||
if (goog.object.containsKey(transforms, sourceCode) &&
|
||||
goog.object.containsKey(transforms[sourceCode], destinationCode)) {
|
||||
transform = transforms[sourceCode][destinationCode];
|
||||
}
|
||||
if (ol.Projection.isProj4jsSupported() && !goog.isDef(transform)) {
|
||||
var proj4jsSource;
|
||||
if (source instanceof ol.Proj4jsProjection) {
|
||||
proj4jsSource = source;
|
||||
} else {
|
||||
proj4jsSource =
|
||||
ol.Projection.getProj4jsProjectionFromCode_(source.getCode());
|
||||
}
|
||||
var sourceProj4jsProj = proj4jsSource.getProj4jsProj();
|
||||
var proj4jsDestination;
|
||||
if (destination instanceof ol.Proj4jsProjection) {
|
||||
proj4jsDestination = destination;
|
||||
} else {
|
||||
proj4jsDestination =
|
||||
ol.Projection.getProj4jsProjectionFromCode_(source.getCode());
|
||||
}
|
||||
var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
|
||||
transform =
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
function(coordinate) {
|
||||
var proj4jsPoint = new Proj4js.Point(coordinate.x, coordinate.y);
|
||||
proj4jsPoint = Proj4js.transform(
|
||||
sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint);
|
||||
return new ol.Coordinate(proj4jsPoint.x, proj4jsPoint.y);
|
||||
};
|
||||
ol.Projection.addTransform(source, destination, transform);
|
||||
}
|
||||
if (!goog.isDef(transform)) {
|
||||
goog.asserts.assert(goog.isDef(transform));
|
||||
transform = ol.Projection.identityTransform;
|
||||
}
|
||||
return transform;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} sourceCode Source code.
|
||||
* @param {string} destinationCode Destination code.
|
||||
* @return {ol.TransformFunction} Transform.
|
||||
*/
|
||||
ol.Projection.getTransformFromCodes = function(sourceCode, destinationCode) {
|
||||
var source = ol.Projection.getFromCode(sourceCode);
|
||||
var destination = ol.Projection.getFromCode(destinationCode);
|
||||
return ol.Projection.getTransform(source, destination);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Has Proj4js.
|
||||
*/
|
||||
ol.Projection.isProj4jsSupported = function() {
|
||||
return ol.ENABLE_PROJ4JS && 'Proj4js' in goog.global;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.identityTransform = function(point) {
|
||||
return point;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.cloneTransform = function(point) {
|
||||
return point.clone();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @param {ol.Projection} source Source.
|
||||
* @param {ol.Projection} destination Destination.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.transform = function(point, source, destination) {
|
||||
var transformFn = ol.Projection.getTransform(source, destination);
|
||||
return transformFn(point);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @param {string} sourceCode Source code.
|
||||
* @param {string} destinationCode Destination code.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.transformWithCodes =
|
||||
function(point, sourceCode, destinationCode) {
|
||||
var transformFn = ol.Projection.getTransformFromCodes(
|
||||
sourceCode, destinationCode);
|
||||
return transformFn(point);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.Projection.EPSG_3857_RADIUS = 6378137;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.forwardSphericalMercator = function(point) {
|
||||
var x = ol.Projection.EPSG_3857_RADIUS * Math.PI * point.x / 180;
|
||||
var y = ol.Projection.EPSG_3857_RADIUS *
|
||||
Math.log(Math.tan(Math.PI * (point.y + 90) / 360));
|
||||
return new ol.Coordinate(x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @return {ol.Coordinate} Point.
|
||||
*/
|
||||
ol.Projection.inverseSphericalMercator = function(point) {
|
||||
var x = 180 * point.x / (ol.Projection.EPSG_3857_RADIUS * Math.PI);
|
||||
var y = 360 * Math.atan(
|
||||
Math.exp(point.y / ol.Projection.EPSG_3857_RADIUS)) / Math.PI - 90;
|
||||
return new ol.Coordinate(x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.Projection.EPSG_3857_HALF_SIZE = Math.PI * ol.Projection.EPSG_3857_RADIUS;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
ol.Projection.EPSG_3857_EXTENT = new ol.Extent(
|
||||
-ol.Projection.EPSG_3857_HALF_SIZE,
|
||||
-ol.Projection.EPSG_3857_HALF_SIZE,
|
||||
ol.Projection.EPSG_3857_HALF_SIZE,
|
||||
ol.Projection.EPSG_3857_HALF_SIZE);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.Projection.EPSG_3857_LIKE_CODES_ = [
|
||||
'EPSG:3857',
|
||||
'EPSG:102100',
|
||||
'EPSG:102113',
|
||||
'EPSG:900913'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<ol.Projection>}
|
||||
*/
|
||||
ol.Projection.EPSG_3857_LIKE_PROJECTIONS_ = goog.array.map(
|
||||
ol.Projection.EPSG_3857_LIKE_CODES_,
|
||||
function(code) {
|
||||
return new ol.Projection(
|
||||
code,
|
||||
ol.ProjectionUnits.METERS,
|
||||
ol.Projection.EPSG_3857_EXTENT);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
ol.Projection.EPSG_4326_EXTENT_ = new ol.Extent(-180, -90, 180, 90);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.Projection.EPSG_4326_LIKE_CODES_ = [
|
||||
'CRS:84',
|
||||
'EPSG:4326',
|
||||
'urn:ogc:def:crs:EPSG:6.6:4326'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<ol.Projection>}
|
||||
*/
|
||||
ol.Projection.EPSG_4326_LIKE_PROJECTIONS = goog.array.map(
|
||||
ol.Projection.EPSG_4326_LIKE_CODES_,
|
||||
function(code) {
|
||||
return new ol.Projection(
|
||||
code,
|
||||
ol.ProjectionUnits.DEGREES,
|
||||
ol.Projection.EPSG_4326_EXTENT_);
|
||||
});
|
||||
|
||||
|
||||
ol.Projection.addEquivalentProjections_(
|
||||
ol.Projection.EPSG_3857_LIKE_PROJECTIONS_);
|
||||
ol.Projection.addEquivalentProjections_(
|
||||
ol.Projection.EPSG_4326_LIKE_PROJECTIONS);
|
||||
ol.Projection.addEquivalentTransforms_(
|
||||
ol.Projection.EPSG_4326_LIKE_PROJECTIONS,
|
||||
ol.Projection.EPSG_3857_LIKE_PROJECTIONS_,
|
||||
ol.Projection.forwardSphericalMercator,
|
||||
ol.Projection.inverseSphericalMercator);
|
||||
87
src/ol/projection_test.js
Normal file
87
src/ol/projection_test.js
Normal file
@@ -0,0 +1,87 @@
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Projection');
|
||||
|
||||
|
||||
function _testAllEquivalent(codes) {
|
||||
var projections = goog.array.map(codes, ol.Projection.getFromCode);
|
||||
goog.array.forEach(projections, function(source) {
|
||||
goog.array.forEach(projections, function(destination) {
|
||||
assertTrue(ol.Projection.equivalent(source, destination));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testEpsg3857Equivalence() {
|
||||
_testAllEquivalent([
|
||||
'EPSG:3857',
|
||||
'EPSG:102100',
|
||||
'EPSG:102113',
|
||||
'EPSG:900913'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function testEpsg4326Equivalence() {
|
||||
_testAllEquivalent([
|
||||
'CRS:84',
|
||||
'urn:ogc:def:crs:EPSG:6.6:4326',
|
||||
'EPSG:4326'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function testIdentityTransform() {
|
||||
var epsg4326 = ol.Projection.getFromCode('EPSG:4326');
|
||||
var uniqueObject = {};
|
||||
var sourcePoint = new ol.Coordinate(uniqueObject, uniqueObject);
|
||||
var destinationPoint = ol.Projection.transform(
|
||||
sourcePoint, epsg4326, epsg4326);
|
||||
assertFalse(sourcePoint === destinationPoint);
|
||||
assertTrue(destinationPoint.x === sourcePoint.x);
|
||||
assertTrue(destinationPoint.y === sourcePoint.y);
|
||||
}
|
||||
|
||||
|
||||
function testForwardSphericalMercatorOrigin() {
|
||||
var point = ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(0, 0), 'EPSG:4326', 'EPSG:3857');
|
||||
assertNotNullNorUndefined(point);
|
||||
assertEquals(0, point.x);
|
||||
assertRoughlyEquals(0, point.y, 1e-9);
|
||||
}
|
||||
|
||||
|
||||
function testInverseSphericalMercatorOrigin() {
|
||||
var point = ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(0, 0), 'EPSG:3857', 'EPSG:4326');
|
||||
assertNotNullNorUndefined(point);
|
||||
assertEquals(0, point.x);
|
||||
assertEquals(0, point.y);
|
||||
}
|
||||
|
||||
|
||||
function testForwardSphericalMercatorAlastaira() {
|
||||
// http://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/
|
||||
var point = ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(-5.625, 52.4827802220782),
|
||||
'EPSG:4326',
|
||||
'EPSG:900913');
|
||||
assertNotNullNorUndefined(point);
|
||||
assertRoughlyEquals(-626172.13571216376, point.x, 1e-9);
|
||||
assertRoughlyEquals(6887893.4928337997, point.y, 1e-9);
|
||||
}
|
||||
|
||||
|
||||
function testInverseSphericalMercatorAlastaira() {
|
||||
// http://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/
|
||||
var point = ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(-626172.13571216376, 6887893.4928337997),
|
||||
'EPSG:900913',
|
||||
'EPSG:4326');
|
||||
assertNotNullNorUndefined(point);
|
||||
assertRoughlyEquals(-5.625, point.x, 1e-9);
|
||||
assertRoughlyEquals(52.4827802220782, point.y, 1e-9);
|
||||
}
|
||||
123
src/ol/rectangle.js
Normal file
123
src/ol/rectangle.js
Normal file
@@ -0,0 +1,123 @@
|
||||
goog.provide('ol.Rectangle');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Size');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
*/
|
||||
ol.Rectangle = function(minX, minY, maxX, maxY) {
|
||||
|
||||
goog.asserts.assert(minX <= maxX);
|
||||
goog.asserts.assert(minY <= maxY);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.minX = minX;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.minY = minY;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxX = maxX;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxY = maxY;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Rectangle} Clone.
|
||||
*/
|
||||
ol.Rectangle.prototype.clone = function() {
|
||||
return new ol.Rectangle(this.minX, this.minY, this.maxX, this.maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {boolean} Contains.
|
||||
*/
|
||||
ol.Rectangle.prototype.contains = function(coordinate) {
|
||||
return this.minX <= coordinate.x && coordinate.x <= this.maxX &&
|
||||
this.minY <= coordinate.y && coordinate.y <= this.maxY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Center.
|
||||
*/
|
||||
ol.Rectangle.prototype.getCenter = function() {
|
||||
return new ol.Coordinate(
|
||||
(this.minX + this.maxX) / 2, (this.minY + this.maxY) / 2);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Height.
|
||||
*/
|
||||
ol.Rectangle.prototype.getHeight = function() {
|
||||
return this.maxY - this.minY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Size} Size.
|
||||
*/
|
||||
ol.Rectangle.prototype.getSize = function() {
|
||||
return new ol.Size(this.getWidth(), this.getHeight());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Width.
|
||||
*/
|
||||
ol.Rectangle.prototype.getWidth = function() {
|
||||
return this.maxX - this.minX;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Rectangle} rectangle Rectangle.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
ol.Rectangle.prototype.intersects = function(rectangle) {
|
||||
return this.minX <= rectangle.maxX &&
|
||||
this.maxX >= rectangle.minX &&
|
||||
this.minY <= rectangle.maxY &&
|
||||
this.maxY >= rectangle.minY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.Rectangle.prototype.normalize = function(coordinate) {
|
||||
return new ol.Coordinate(
|
||||
(coordinate.x - this.minX) / this.getWidth(),
|
||||
(coordinate.y - this.minY) / this.getHeight());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.Rectangle.prototype.toString = function() {
|
||||
return '(' + [this.minX, this.minY, this.maxX, this.maxY].join(', ') + ')';
|
||||
};
|
||||
142
src/ol/rectangle_test.js
Normal file
142
src/ol/rectangle_test.js
Normal file
@@ -0,0 +1,142 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Rectangle');
|
||||
|
||||
|
||||
function testCenter() {
|
||||
var rectangle = new ol.Rectangle(1, 2, 3, 4);
|
||||
var center = rectangle.getCenter();
|
||||
assertEquals(2, center.x);
|
||||
assertEquals(3, center.y);
|
||||
}
|
||||
|
||||
|
||||
function testClone() {
|
||||
var rectangle = new ol.Rectangle(1, 2, 3, 4);
|
||||
var clonedRectangle = rectangle.clone();
|
||||
assertTrue(clonedRectangle instanceof ol.Rectangle);
|
||||
assertFalse(clonedRectangle === rectangle);
|
||||
assertEquals(rectangle.minX, clonedRectangle.minX);
|
||||
assertEquals(rectangle.minY, clonedRectangle.minY);
|
||||
assertEquals(rectangle.maxX, clonedRectangle.maxX);
|
||||
assertEquals(rectangle.maxY, clonedRectangle.maxY);
|
||||
}
|
||||
|
||||
|
||||
function testContainsPositive() {
|
||||
var rectangle = new ol.Rectangle(1, 2, 3, 4);
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(1, 2)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(1, 3)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(1, 4)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(2, 2)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(2, 3)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(2, 4)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(3, 2)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(3, 3)));
|
||||
assertTrue(rectangle.contains(new ol.Coordinate(3, 4)));
|
||||
}
|
||||
|
||||
|
||||
function testContainsNegative() {
|
||||
var rectangle = new ol.Rectangle(1, 2, 3, 4);
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(0, 1)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(0, 2)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(0, 3)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(0, 4)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(0, 5)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(1, 1)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(1, 5)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(2, 1)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(2, 5)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(3, 1)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(3, 5)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(4, 1)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(4, 2)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(4, 3)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(4, 4)));
|
||||
assertFalse(rectangle.contains(new ol.Coordinate(4, 5)));
|
||||
}
|
||||
|
||||
|
||||
function testIntersects() {
|
||||
|
||||
var rectangle1 = new ol.Rectangle(50, 50, 100, 100);
|
||||
|
||||
function assertIntersects(rectangle2) {
|
||||
assertTrue(rectangle1 + ' expected to intersect ' + rectangle2,
|
||||
rectangle1.intersects(rectangle2));
|
||||
}
|
||||
function assertNotIntersects(rectangle2) {
|
||||
assertFalse(rectangle1 + ' expected to not intersect ' + rectangle2,
|
||||
rectangle1.intersects(rectangle2));
|
||||
}
|
||||
|
||||
assertIntersects(rectangle1);
|
||||
assertIntersects(new ol.Rectangle(20, 20, 80, 80));
|
||||
assertIntersects(new ol.Rectangle(20, 50, 80, 100));
|
||||
assertIntersects(new ol.Rectangle(20, 80, 80, 120));
|
||||
assertIntersects(new ol.Rectangle(50, 20, 100, 80));
|
||||
assertIntersects(new ol.Rectangle(50, 80, 100, 120));
|
||||
assertIntersects(new ol.Rectangle(80, 20, 120, 80));
|
||||
assertIntersects(new ol.Rectangle(80, 50, 120, 100));
|
||||
assertIntersects(new ol.Rectangle(80, 80, 120, 120));
|
||||
assertIntersects(new ol.Rectangle(20, 20, 120, 120));
|
||||
assertIntersects(new ol.Rectangle(70, 70, 80, 80));
|
||||
assertNotIntersects(new ol.Rectangle(10, 10, 30, 30));
|
||||
assertNotIntersects(new ol.Rectangle(30, 10, 70, 30));
|
||||
assertNotIntersects(new ol.Rectangle(50, 10, 100, 30));
|
||||
assertNotIntersects(new ol.Rectangle(80, 10, 120, 30));
|
||||
assertNotIntersects(new ol.Rectangle(120, 10, 140, 30));
|
||||
assertNotIntersects(new ol.Rectangle(10, 30, 30, 70));
|
||||
assertNotIntersects(new ol.Rectangle(120, 30, 140, 70));
|
||||
assertNotIntersects(new ol.Rectangle(10, 50, 30, 100));
|
||||
assertNotIntersects(new ol.Rectangle(120, 50, 140, 100));
|
||||
assertNotIntersects(new ol.Rectangle(10, 80, 30, 120));
|
||||
assertNotIntersects(new ol.Rectangle(120, 80, 140, 120));
|
||||
assertNotIntersects(new ol.Rectangle(10, 120, 30, 140));
|
||||
assertNotIntersects(new ol.Rectangle(30, 120, 70, 140));
|
||||
assertNotIntersects(new ol.Rectangle(50, 120, 100, 140));
|
||||
assertNotIntersects(new ol.Rectangle(80, 120, 120, 140));
|
||||
assertNotIntersects(new ol.Rectangle(120, 120, 140, 140));
|
||||
}
|
||||
|
||||
|
||||
function testSize() {
|
||||
var rectangle = new ol.Rectangle(0, 1, 2, 4);
|
||||
var size = rectangle.getSize();
|
||||
assertEquals(2, size.width);
|
||||
assertEquals(3, size.height);
|
||||
}
|
||||
|
||||
|
||||
function testNormalize() {
|
||||
var rectangle = new ol.Rectangle(0, 1, 2, 3);
|
||||
var coordinate;
|
||||
|
||||
coordinate = rectangle.normalize(new ol.Coordinate(1, 2));
|
||||
assertEquals(0.5, coordinate.x);
|
||||
assertEquals(0.5, coordinate.y);
|
||||
|
||||
coordinate = rectangle.normalize(new ol.Coordinate(0, 3));
|
||||
assertEquals(0, coordinate.x);
|
||||
assertEquals(1, coordinate.y);
|
||||
|
||||
coordinate = rectangle.normalize(new ol.Coordinate(2, 1));
|
||||
assertEquals(1, coordinate.x);
|
||||
assertEquals(0, coordinate.y);
|
||||
|
||||
coordinate = rectangle.normalize(new ol.Coordinate(0, 0));
|
||||
assertEquals(0, coordinate.x);
|
||||
assertEquals(-0.5, coordinate.y);
|
||||
|
||||
coordinate = rectangle.normalize(new ol.Coordinate(-1, 1));
|
||||
assertEquals(-0.5, coordinate.x);
|
||||
assertEquals(0, coordinate.y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testToString() {
|
||||
var rectangle = new ol.Rectangle(0, 1, 2, 3);
|
||||
assertEquals('(0, 1, 2, 3)', rectangle.toString());
|
||||
}
|
||||
9
src/ol/renderer/dom/dom.js
Normal file
9
src/ol/renderer/dom/dom.js
Normal file
@@ -0,0 +1,9 @@
|
||||
goog.provide('ol.renderer.dom');
|
||||
|
||||
goog.require('goog.functions');
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is supported.
|
||||
*/
|
||||
ol.renderer.dom.isSupported = goog.functions.TRUE;
|
||||
85
src/ol/renderer/dom/layer.js
Normal file
85
src/ol/renderer/dom/layer.js
Normal file
@@ -0,0 +1,85 @@
|
||||
goog.provide('ol.renderer.dom.Layer');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.renderer.Layer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Layer}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @param {!Element} target Target.
|
||||
*/
|
||||
ol.renderer.dom.Layer = function(mapRenderer, layer, target) {
|
||||
goog.base(this, mapRenderer, layer);
|
||||
|
||||
/**
|
||||
* @type {!Element}
|
||||
* @protected
|
||||
*/
|
||||
this.target = target;
|
||||
|
||||
/**
|
||||
* Top left corner of the target in map coords.
|
||||
*
|
||||
* @type {ol.Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.origin = null;
|
||||
|
||||
this.handleLayerOpacityChange();
|
||||
this.handleLayerVisibleChange();
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.Layer, ol.renderer.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.renderer.Map} Map renderer.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.getMapRenderer = function() {
|
||||
return /** @type {ol.renderer.dom.Map} */ goog.base(this, 'getMapRenderer');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.handleLayerLoad = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.handleLayerOpacityChange = function() {
|
||||
goog.style.setOpacity(this.target, this.getLayer().getOpacity());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.handleLayerVisibleChange = function() {
|
||||
goog.style.showElement(this.target, this.getLayer().getVisible());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.render = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the top left corner of the target.
|
||||
*
|
||||
* @param {ol.Coordinate} origin Origin.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.setOrigin = function(origin) {
|
||||
this.origin = origin;
|
||||
};
|
||||
169
src/ol/renderer/dom/map.js
Normal file
169
src/ol/renderer/dom/map.js
Normal file
@@ -0,0 +1,169 @@
|
||||
goog.provide('ol.renderer.dom.Map');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.dom.TileLayer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Map}
|
||||
* @param {Element} container Container.
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.renderer.dom.Map = function(container, map) {
|
||||
|
||||
goog.base(this, container, map);
|
||||
|
||||
/**
|
||||
* @type {!Element}
|
||||
* @private
|
||||
*/
|
||||
this.layersPane_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.layersPane_.className = 'ol-layers-pane';
|
||||
this.layersPane_.style.position = 'absolute';
|
||||
goog.dom.appendChild(container, this.layersPane_);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
this.layerPanes_ = {};
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderedCenter_ = undefined;
|
||||
|
||||
/**
|
||||
* The pixel offset of the layers pane with respect to its container.
|
||||
*
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.layersPaneOffset_ = null;
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.Map, ol.renderer.Map);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
|
||||
|
||||
if (layer instanceof ol.TileLayer) {
|
||||
|
||||
var layerPane = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
layerPane.className = 'ol-layer';
|
||||
layerPane.style.position = 'absolute';
|
||||
goog.dom.appendChild(this.layersPane_, layerPane);
|
||||
|
||||
var layerRenderer = new ol.renderer.dom.TileLayer(this, layer, layerPane);
|
||||
|
||||
this.layerPanes_[goog.getUid(layerRenderer)] = layerPane;
|
||||
|
||||
return layerRenderer;
|
||||
|
||||
} else {
|
||||
goog.asserts.assert(false);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleCenterChanged = function() {
|
||||
goog.base(this, 'handleCenterChanged');
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
// FIXME: shiftLayersPane_ and resetLayersPane_ should be called
|
||||
// elsewhere as we may be frozen here
|
||||
if (goog.isDef(this.renderedCenter_)) {
|
||||
this.shiftLayersPane_();
|
||||
} else {
|
||||
this.resetLayersPane_();
|
||||
}
|
||||
map.render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleResolutionChanged = function() {
|
||||
goog.base(this, 'handleResolutionChanged');
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
// FIXME: resetLayersPane_ should be called
|
||||
// elsewhere as we may be frozen here
|
||||
this.resetLayersPane_();
|
||||
map.render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset the layers pane to its initial position.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.resetLayersPane_ = function() {
|
||||
var offset = new ol.Coordinate(0, 0);
|
||||
goog.style.setPosition(this.layersPane_, offset);
|
||||
|
||||
this.layersPaneOffset_ = offset;
|
||||
this.renderedCenter_ = this.map.getCenter();
|
||||
|
||||
this.setOrigin_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the origin for each layer renderer.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.setOrigin_ = function() {
|
||||
var center = this.map.getCenter();
|
||||
var resolution = this.map.getResolution();
|
||||
var targetSize = this.map.getSize();
|
||||
var targetWidth = targetSize.width;
|
||||
var targetHeight = targetSize.height;
|
||||
var origin = new ol.Coordinate(
|
||||
center.x - resolution * targetWidth / 2,
|
||||
center.y + resolution * targetHeight / 2);
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
layerRenderer.setOrigin(origin);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Move the layers pane.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.shiftLayersPane_ = function() {
|
||||
var center = this.map.getCenter();
|
||||
var oldCenter = this.renderedCenter_;
|
||||
var resolution = this.map.getResolution();
|
||||
var dx = Math.round((oldCenter.x - center.x) / resolution);
|
||||
var dy = Math.round((center.y - oldCenter.y) / resolution);
|
||||
if (!(dx === 0 && dy === 0)) {
|
||||
var offset = this.layersPaneOffset_;
|
||||
offset.x += Math.round((oldCenter.x - center.x) / resolution);
|
||||
offset.y += Math.round((center.y - oldCenter.y) / resolution);
|
||||
goog.style.setPosition(this.layersPane_, offset);
|
||||
this.renderedCenter_ = center;
|
||||
}
|
||||
};
|
||||
148
src/ol/renderer/dom/tilelayer.js
Normal file
148
src/ol/renderer/dom/tilelayer.js
Normal file
@@ -0,0 +1,148 @@
|
||||
goog.provide('ol.renderer.dom.TileLayer');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.renderer.dom.Layer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.dom.Layer}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.TileLayer} tileLayer Tile layer.
|
||||
* @param {!Element} target Target.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer, target) {
|
||||
goog.base(this, mapRenderer, tileLayer, target);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
this.renderedTiles_ = {};
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderedMapResolution_ = undefined;
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.TileLayer, ol.renderer.dom.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.TileLayer} Layer.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.getLayer = function() {
|
||||
return /** @type {ol.TileLayer} */ goog.base(this, 'getLayer');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the pixel offset between the tile origin and the container origin.
|
||||
* @private
|
||||
* @param {number} z Z.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {ol.Coordinate} Offset.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.getTileOffset_ = function(z, resolution) {
|
||||
var tileLayer = this.getLayer();
|
||||
var tileStore = tileLayer.getStore();
|
||||
var tileGrid = tileStore.getTileGrid();
|
||||
var tileOrigin = tileGrid.getOrigin(z);
|
||||
var offset = new ol.Coordinate(
|
||||
Math.round((this.origin.x - tileOrigin.x) / resolution),
|
||||
Math.round((tileOrigin.y - this.origin.y) / resolution));
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get rid of tiles outside the rendered extent.
|
||||
* @private
|
||||
* @param {ol.TileBounds} tileBounds Tile bounds.
|
||||
* @param {number} z Z.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.removeInvisibleTiles_ = function(
|
||||
tileBounds, z) {
|
||||
var key, tileCoord, prune, tile;
|
||||
for (key in this.renderedTiles_) {
|
||||
tileCoord = ol.TileCoord.createFromString(key);
|
||||
prune = z !== tileCoord.z ||
|
||||
tileCoord.x < tileBounds.minX ||
|
||||
tileCoord.x > tileBounds.maxX ||
|
||||
tileCoord.y < tileBounds.minY ||
|
||||
tileCoord.y > tileBounds.maxY;
|
||||
if (prune) {
|
||||
tile = this.renderedTiles_[key];
|
||||
delete this.renderedTiles_[key];
|
||||
goog.dom.removeNode(tile.getImage(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.render = function() {
|
||||
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
var mapExtent = /** @type {!ol.Extent} */ map.getExtent();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
|
||||
var tileLayer = this.getLayer();
|
||||
var tileStore = tileLayer.getStore();
|
||||
var tileGrid = tileStore.getTileGrid();
|
||||
|
||||
if (mapResolution != this.renderedMapResolution_) {
|
||||
this.renderedTiles_ = {};
|
||||
goog.dom.removeChildren(this.target);
|
||||
}
|
||||
|
||||
// z represents the "best" resolution
|
||||
var z = tileGrid.getZForResolution(mapResolution);
|
||||
|
||||
var tileBounds =
|
||||
tileGrid.getTileBoundsForExtentAndResolution(mapExtent, mapResolution);
|
||||
var tileOffset = this.getTileOffset_(z, mapResolution);
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
var key, tile, pixelBounds, img, newTiles = false;
|
||||
tileBounds.forEachTileCoord(z, function(tileCoord) {
|
||||
key = tileCoord.toString();
|
||||
tile = this.renderedTiles_[key];
|
||||
if (!goog.isDef(tile)) {
|
||||
tile = tileStore.getTile(tileCoord);
|
||||
if (goog.isNull(tile)) {
|
||||
} else {
|
||||
tile.load();
|
||||
this.renderedTiles_[key] = tile;
|
||||
pixelBounds = tileGrid.getPixelBoundsForTileCoordAndResolution(
|
||||
tileCoord, mapResolution);
|
||||
img = tile.getImage(this);
|
||||
img.style.position = 'absolute';
|
||||
img.style.left = (pixelBounds.minX - tileOffset.x) + 'px';
|
||||
img.style.top = (-pixelBounds.maxY - tileOffset.y) + 'px';
|
||||
img.style.width = pixelBounds.getWidth() + 'px';
|
||||
img.style.height = pixelBounds.getHeight() + 'px';
|
||||
goog.dom.appendChild(fragment, img);
|
||||
newTiles = true;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (newTiles) {
|
||||
goog.dom.appendChild(this.target, fragment);
|
||||
}
|
||||
|
||||
this.removeInvisibleTiles_(tileBounds, z);
|
||||
this.renderedMapResolution_ = mapResolution;
|
||||
};
|
||||
127
src/ol/renderer/layer.js
Normal file
127
src/ol/renderer/layer.js
Normal file
@@ -0,0 +1,127 @@
|
||||
goog.provide('ol.renderer.Layer');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.LayerProperty');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.Layer} layer Layer.
|
||||
*/
|
||||
ol.renderer.Layer = function(mapRenderer, layer) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.Map}
|
||||
*/
|
||||
this.mapRenderer_ = mapRenderer;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Layer}
|
||||
*/
|
||||
this.layer_ = layer;
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.BRIGHTNESS),
|
||||
this.handleLayerBrightnessChange, false, this);
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.CONTRAST),
|
||||
this.handleLayerContrastChange, false, this);
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.HUE),
|
||||
this.handleLayerHueChange, false, this);
|
||||
|
||||
goog.events.listen(this.layer_, goog.events.EventType.LOAD,
|
||||
this.handleLayerLoad, false, this);
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.OPACITY),
|
||||
this.handleLayerOpacityChange, false, this);
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.SATURATION),
|
||||
this.handleLayerSaturationChange, false, this);
|
||||
|
||||
goog.events.listen(this.layer_,
|
||||
ol.Object.getChangedEventType(ol.LayerProperty.VISIBLE),
|
||||
this.handleLayerVisibleChange, false, this);
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.Layer, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Layer} Layer.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.getLayer = function() {
|
||||
return this.layer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.getMap = function() {
|
||||
return this.mapRenderer_.getMap();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.renderer.Map} Map renderer.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.getMapRenderer = function() {
|
||||
return this.mapRenderer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerBrightnessChange = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerContrastChange = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerHueChange = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerLoad = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerOpacityChange = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerSaturationChange = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.handleLayerVisibleChange = goog.nullFunction;
|
||||
377
src/ol/renderer/map.js
Normal file
377
src/ol/renderer/map.js
Normal file
@@ -0,0 +1,377 @@
|
||||
goog.provide('ol.renderer.Map');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.fx.anim');
|
||||
goog.require('goog.fx.anim.Animated');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapProperty');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @param {Element} container Container.
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.renderer.Map = function(container, map) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.container_ = container;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map = map;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Object.<number, ol.renderer.Layer>}
|
||||
*/
|
||||
this.layerRenderers = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.layersListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.coordinateToPixelMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.pixelToCoordinateMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.matricesDirty_ = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.mapListenerKeys_ = [
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR),
|
||||
this.handleBackgroundColorChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.CENTER),
|
||||
this.handleCenterChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS),
|
||||
this.handleLayersChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION),
|
||||
this.handleResolutionChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.ROTATION),
|
||||
this.handleRotationChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
|
||||
this.handleSizeChanged, false, this)
|
||||
];
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.Map, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.addLayer = function(layer) {
|
||||
var layerRenderer = this.createLayerRenderer(layer);
|
||||
this.setLayerRenderer(layer, layerRenderer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can rotate.
|
||||
*/
|
||||
ol.renderer.Map.prototype.canRotate = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
* @return {ol.renderer.Layer} layerRenderer Layer renderer.
|
||||
*/
|
||||
ol.renderer.Map.prototype.createLayerRenderer = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.Map.prototype.disposeInternal = function() {
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
goog.dispose(layerRenderer);
|
||||
});
|
||||
goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
}
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(this: T, ol.Layer, ol.renderer.Layer, number)} f Function.
|
||||
* @param {T=} opt_obj Object.
|
||||
* @template T
|
||||
*/
|
||||
ol.renderer.Map.prototype.forEachReadyVisibleLayer = function(f, opt_obj) {
|
||||
var layers = this.map.getLayers();
|
||||
layers.forEach(function(layer, index) {
|
||||
if (layer.isReady() && layer.getVisible()) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
f.call(opt_obj, layer, layerRenderer, index);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getCoordinateFromPixel = function(pixel) {
|
||||
this.updateMatrices_();
|
||||
var vec3 = [pixel.x, pixel.y, 0];
|
||||
goog.vec.Mat4.multVec3(this.pixelToCoordinateMatrix_, vec3, vec3);
|
||||
return new ol.Coordinate(vec3[0], vec3[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
* @return {ol.renderer.Layer} Layer renderer.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getLayerRenderer = function(layer) {
|
||||
var key = goog.getUid(layer);
|
||||
var layerRenderer = this.layerRenderers[key];
|
||||
goog.asserts.assert(goog.isDef(layerRenderer));
|
||||
return layerRenderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getMap = function() {
|
||||
return this.map;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Pixel} Pixel.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getPixelFromCoordinate = function(coordinate) {
|
||||
this.updateMatrices_();
|
||||
var vec3 = [coordinate.x, coordinate.y, 0];
|
||||
goog.vec.Mat4.multVec3(this.coordinateToPixelMatrix_, vec3, vec3);
|
||||
return new ol.Pixel(vec3[0], vec3[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle background color changed.
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleBackgroundColorChanged = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleCenterChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersAdd = function(collectionEvent) {
|
||||
var layer = /** @type {ol.Layer} */ collectionEvent.elem;
|
||||
this.addLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersChanged = function() {
|
||||
var layerRenderers = goog.object.getValues(this.layerRenderers);
|
||||
goog.array.forEach(layerRenderers, function(layerRenderer) {
|
||||
this.removeLayerRenderer(layerRenderer);
|
||||
}, this);
|
||||
this.layerRenderers = {};
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
this.layersListenerKeys_ = null;
|
||||
}
|
||||
var layers = this.map.getLayers();
|
||||
if (goog.isDefAndNotNull(layers)) {
|
||||
layers.forEach(this.addLayer, this);
|
||||
this.layersListenerKeys_ = [
|
||||
goog.events.listen(layers, ol.CollectionEventType.ADD,
|
||||
this.handleLayersAdd, false, this),
|
||||
goog.events.listen(layers, ol.CollectionEventType.REMOVE,
|
||||
this.handleLayersRemove, false, this)
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) {
|
||||
var layer = /** @type {ol.Layer} */ collectionEvent.elem;
|
||||
this.removeLayer(layer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleResolutionChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleRotationChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleSizeChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.removeLayer = function(layer) {
|
||||
goog.dispose(this.removeLayerRenderer(layer));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @return {ol.renderer.Layer} Layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
var key = goog.getUid(layer);
|
||||
if (key in this.layerRenderers) {
|
||||
var layerRenderer = this.layerRenderers[key];
|
||||
delete this.layerRenderers[key];
|
||||
return layerRenderer;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Animating.
|
||||
*/
|
||||
ol.renderer.Map.prototype.render = function() {
|
||||
var animate = false;
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
if (layerRenderer.render()) {
|
||||
animate = true;
|
||||
}
|
||||
});
|
||||
return animate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Layer} layer Layer.
|
||||
* @param {ol.renderer.Layer} layerRenderer Layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) {
|
||||
var key = goog.getUid(layer);
|
||||
goog.asserts.assert(!(key in this.layerRenderers));
|
||||
this.layerRenderers[key] = layerRenderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.Map.prototype.updateMatrices_ = function() {
|
||||
|
||||
if (this.matricesDirty_) {
|
||||
|
||||
var map = this.map;
|
||||
var center = /** @type {!ol.Coordinate} */ map.getCenter();
|
||||
var resolution = /** @type {number} */ map.getResolution();
|
||||
var rotation = map.getRotation();
|
||||
var size = /** @type {!ol.Size} */ map.getSize();
|
||||
|
||||
goog.vec.Mat4.makeIdentity(this.coordinateToPixelMatrix_);
|
||||
goog.vec.Mat4.translate(this.coordinateToPixelMatrix_,
|
||||
size.width / 2,
|
||||
size.height / 2,
|
||||
0);
|
||||
goog.vec.Mat4.scale(this.coordinateToPixelMatrix_,
|
||||
1 / resolution,
|
||||
-1 / resolution,
|
||||
1);
|
||||
if (this.canRotate() && goog.isDef(rotation)) {
|
||||
goog.vec.Mat4.rotate(this.coordinateToPixelMatrix_,
|
||||
-rotation,
|
||||
0,
|
||||
0,
|
||||
1);
|
||||
}
|
||||
goog.vec.Mat4.translate(this.coordinateToPixelMatrix_,
|
||||
-center.x,
|
||||
-center.y,
|
||||
0);
|
||||
|
||||
var inverted = goog.vec.Mat4.invert(
|
||||
this.coordinateToPixelMatrix_, this.pixelToCoordinateMatrix_);
|
||||
goog.asserts.assert(inverted);
|
||||
|
||||
this.matricesDirty_ = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
116
src/ol/renderer/webgl/layer.js
Normal file
116
src/ol/renderer/webgl/layer.js
Normal file
@@ -0,0 +1,116 @@
|
||||
goog.provide('ol.renderer.webgl.Layer');
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.renderer.Layer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Layer}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.Layer} layer Layer.
|
||||
*/
|
||||
ol.renderer.webgl.Layer = function(mapRenderer, layer) {
|
||||
goog.base(this, mapRenderer, layer);
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.dispatchChangeEvent = function() {
|
||||
this.dispatchEvent(goog.events.EventType.CHANGE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.renderer.Map} MapRenderer.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getMapRenderer = function() {
|
||||
return /** @type {ol.renderer.webgl.Map} */ goog.base(
|
||||
this, 'getMapRenderer');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.vec.Mat4.AnyType} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getMatrix = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {WebGLTexture} Texture.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getTexture = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerBrightnessChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerContrastChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerHueChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerLoad = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerOpacityChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerVisibleChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle webglcontextlost.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Render.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.render = goog.abstractMethod;
|
||||
640
src/ol/renderer/webgl/map.js
Normal file
640
src/ol/renderer/webgl/map.js
Normal file
@@ -0,0 +1,640 @@
|
||||
// FIXME clear textureCache
|
||||
// FIXME defer texture loads until after render when animating
|
||||
// FIXME generational tile texture garbage collector newFrame/get
|
||||
// FIXME defer cleanup until post-render
|
||||
// FIXME check against gl.getParameter(webgl.MAX_TEXTURE_SIZE)
|
||||
|
||||
goog.provide('ol.renderer.webgl.Map');
|
||||
goog.provide('ol.renderer.webgl.map.shader');
|
||||
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dispose');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.webgl');
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.renderer.webgl.FragmentShader');
|
||||
goog.require('ol.renderer.webgl.TileLayer');
|
||||
goog.require('ol.renderer.webgl.VertexShader');
|
||||
goog.require('ol.webgl.WebGLContextEventType');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}}
|
||||
*/
|
||||
ol.renderer.webgl.TextureCacheEntry;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.FragmentShader}
|
||||
* @see https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/brightnesscontrast.js
|
||||
* @see https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/huesaturation.js
|
||||
*/
|
||||
ol.renderer.webgl.map.shader.Fragment = function() {
|
||||
goog.base(this, [
|
||||
'precision mediump float;',
|
||||
'',
|
||||
'uniform float uBrightness;',
|
||||
'uniform float uContrast;',
|
||||
'uniform float uHue;',
|
||||
'uniform float uOpacity;',
|
||||
'uniform mat4 uMatrix;',
|
||||
'uniform float uSaturation;',
|
||||
'uniform sampler2D uTexture;',
|
||||
'',
|
||||
'varying vec2 vTexCoord;',
|
||||
'',
|
||||
'void main(void) {',
|
||||
'',
|
||||
' vec4 texCoord = uMatrix * vec4(vTexCoord, 0., 1.);',
|
||||
' vec4 color = texture2D(uTexture, texCoord.st);',
|
||||
'',
|
||||
' if (uHue != 0.) {',
|
||||
' float angle = uHue * 3.14159265;',
|
||||
' float s = sin(angle), c = cos(angle);',
|
||||
' vec3 weights = (vec3(2. * c, -sqrt(3.) * s - c, sqrt(3.) * s - c)',
|
||||
' + 1.) / 3.;',
|
||||
' color.rgb = vec3(',
|
||||
' dot(color.rgb, weights.xyz),',
|
||||
' dot(color.rgb, weights.zxy),',
|
||||
' dot(color.rgb, weights.yzx)',
|
||||
' );',
|
||||
' }',
|
||||
'',
|
||||
' if (uSaturation != 0.) {',
|
||||
' float average = (color.r + color.g + color.b) / 3.;',
|
||||
' if (uSaturation > 0.) {',
|
||||
' color.rgb += (average - color.rgb)',
|
||||
' * (1. - 1. / (1. - uSaturation));',
|
||||
' } else {',
|
||||
' color.rgb += (average - color.rgb) * -uSaturation;',
|
||||
' }',
|
||||
' }',
|
||||
'',
|
||||
' color.rgb += uBrightness;',
|
||||
'',
|
||||
' if (uContrast != 0.) {',
|
||||
' if (uContrast > 0.) {',
|
||||
' color.rgb = (color.rgb - 0.5) / (1. - uContrast) + 0.5;',
|
||||
' } else {',
|
||||
' color.rgb = (color.rgb - 0.5) * (1. + uContrast) + 0.5;',
|
||||
' }',
|
||||
' }',
|
||||
'',
|
||||
' color.a = color.a * uOpacity;',
|
||||
'',
|
||||
' gl_FragColor = color;',
|
||||
'',
|
||||
'}'
|
||||
].join('\n'));
|
||||
};
|
||||
goog.inherits(
|
||||
ol.renderer.webgl.map.shader.Fragment, ol.renderer.webgl.FragmentShader);
|
||||
goog.addSingletonGetter(ol.renderer.webgl.map.shader.Fragment);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.VertexShader}
|
||||
*/
|
||||
ol.renderer.webgl.map.shader.Vertex = function() {
|
||||
goog.base(this, [
|
||||
'attribute vec2 aPosition;',
|
||||
'attribute vec2 aTexCoord;',
|
||||
'',
|
||||
'varying vec2 vTexCoord;',
|
||||
'',
|
||||
'void main(void) {',
|
||||
' gl_Position = vec4(aPosition, 0., 1.);',
|
||||
' vTexCoord = aTexCoord;',
|
||||
'}'
|
||||
].join('\n'));
|
||||
};
|
||||
goog.inherits(
|
||||
ol.renderer.webgl.map.shader.Vertex, ol.renderer.webgl.VertexShader);
|
||||
goog.addSingletonGetter(ol.renderer.webgl.map.shader.Vertex);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Map}
|
||||
* @param {Element} container Container.
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.renderer.webgl.Map = function(container, map) {
|
||||
|
||||
goog.base(this, container, map);
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.logger = goog.debug.Logger.getLogger(
|
||||
'ol.renderer.webgl.maprenderer.' + goog.getUid(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.canvas_ = goog.dom.createElement(goog.dom.TagName.CANVAS);
|
||||
this.canvas_.height = container.clientHeight;
|
||||
this.canvas_.width = container.clientWidth;
|
||||
goog.dom.appendChild(container, this.canvas_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLRenderingContext}
|
||||
*/
|
||||
this.gl_ = this.canvas_.getContext('experimental-webgl', {
|
||||
alpha: false,
|
||||
antialias: true,
|
||||
depth: false,
|
||||
preserveDrawingBuffer: false,
|
||||
stencil: false
|
||||
});
|
||||
goog.asserts.assert(!goog.isNull(this.gl_));
|
||||
|
||||
goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.LOST,
|
||||
this.handleWebGLContextLost, false, this);
|
||||
goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
|
||||
this.handleWebGLContextRestored, false, this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
this.clearColor_ = new ol.Color(1, 1, 1, 1);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{aPosition: number,
|
||||
* aTexCoord: number,
|
||||
* uBrightness: WebGLUniformLocation,
|
||||
* uContrast: WebGLUniformLocation,
|
||||
* uHue: WebGLUniformLocation,
|
||||
* uMatrix: WebGLUniformLocation,
|
||||
* uOpacity: WebGLUniformLocation,
|
||||
* uSaturation: WebGLUniformLocation,
|
||||
* uTexture: WebGLUniformLocation}|null}
|
||||
*/
|
||||
this.locations_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLBuffer}
|
||||
*/
|
||||
this.arrayBuffer_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, WebGLShader>}
|
||||
*/
|
||||
this.shaderCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLProgram>}
|
||||
*/
|
||||
this.programCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.renderer.webgl.TextureCacheEntry>}
|
||||
*/
|
||||
this.textureCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.FragmentShader}
|
||||
*/
|
||||
this.fragmentShader_ = ol.renderer.webgl.map.shader.Fragment.getInstance();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.VertexShader}
|
||||
*/
|
||||
this.vertexShader_ = ol.renderer.webgl.map.shader.Vertex.getInstance();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, null|number>}
|
||||
*/
|
||||
this.layerRendererChangeListenKeys_ = {};
|
||||
|
||||
this.initializeGL_();
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.Map, ol.renderer.Map);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.addLayer = function(layer) {
|
||||
goog.base(this, 'addLayer', layer);
|
||||
if (layer.getVisible()) {
|
||||
this.getMap().render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Image} image Image.
|
||||
* @param {number} magFilter Mag filter.
|
||||
* @param {number} minFilter Min filter.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.bindImageTexture =
|
||||
function(image, magFilter, minFilter) {
|
||||
var gl = this.getGL();
|
||||
var imageKey = image.src;
|
||||
var textureCacheEntry = this.textureCache_[imageKey];
|
||||
if (goog.isDef(textureCacheEntry)) {
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, textureCacheEntry.texture);
|
||||
if (textureCacheEntry.magFilter != magFilter) {
|
||||
gl.texParameteri(
|
||||
goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, magFilter);
|
||||
textureCacheEntry.magFilter = magFilter;
|
||||
}
|
||||
if (textureCacheEntry.minFilter != minFilter) {
|
||||
gl.texParameteri(
|
||||
goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, minFilter);
|
||||
textureCacheEntry.minFilter = minFilter;
|
||||
}
|
||||
} else {
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA, goog.webgl.RGBA,
|
||||
goog.webgl.UNSIGNED_BYTE, image);
|
||||
gl.texParameteri(
|
||||
goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, magFilter);
|
||||
gl.texParameteri(
|
||||
goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER, minFilter);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_S,
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_T,
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
this.textureCache_[imageKey] = {
|
||||
texture: texture,
|
||||
magFilter: magFilter,
|
||||
minFilter: minFilter
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.canRotate = goog.functions.TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) {
|
||||
var gl = this.getGL();
|
||||
if (layer instanceof ol.TileLayer) {
|
||||
return new ol.renderer.webgl.TileLayer(this, layer);
|
||||
} else {
|
||||
goog.asserts.assert(false);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.disposeInternal = function() {
|
||||
var gl = this.getGL();
|
||||
if (!gl.isContextLost()) {
|
||||
goog.object.forEach(this.programCache_, function(program) {
|
||||
gl.deleteProgram(program);
|
||||
});
|
||||
goog.object.forEach(this.shaderCache_, function(shader) {
|
||||
gl.deleteShader(shader);
|
||||
});
|
||||
goog.object.forEach(this.textureCache_, function(textureCacheEntry) {
|
||||
gl.deleteTexture(textureCacheEntry.texture);
|
||||
});
|
||||
}
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {WebGLRenderingContext} GL.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.getGL = function() {
|
||||
return this.gl_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.renderer.webgl.FragmentShader} fragmentShaderObject
|
||||
* Fragment shader.
|
||||
* @param {ol.renderer.webgl.VertexShader} vertexShaderObject Vertex shader.
|
||||
* @return {WebGLProgram} Program.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.getProgram = function(
|
||||
fragmentShaderObject, vertexShaderObject) {
|
||||
var programKey =
|
||||
goog.getUid(fragmentShaderObject) + '/' + goog.getUid(vertexShaderObject);
|
||||
if (programKey in this.programCache_) {
|
||||
return this.programCache_[programKey];
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
var program = gl.createProgram();
|
||||
gl.attachShader(program, this.getShader(fragmentShaderObject));
|
||||
gl.attachShader(program, this.getShader(vertexShaderObject));
|
||||
gl.linkProgram(program);
|
||||
if (goog.DEBUG) {
|
||||
if (!gl.getProgramParameter(program, goog.webgl.LINK_STATUS) &&
|
||||
!gl.isContextLost()) {
|
||||
this.logger.severe(gl.getProgramInfoLog(program));
|
||||
goog.asserts.assert(
|
||||
gl.getProgramParameter(program, goog.webgl.LINK_STATUS));
|
||||
}
|
||||
}
|
||||
this.programCache_[programKey] = program;
|
||||
return program;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.renderer.webgl.Shader} shaderObject Shader object.
|
||||
* @return {WebGLShader} Shader.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) {
|
||||
var shaderKey = goog.getUid(shaderObject);
|
||||
if (shaderKey in this.shaderCache_) {
|
||||
return this.shaderCache_[shaderKey];
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
var shader = gl.createShader(shaderObject.getType());
|
||||
gl.shaderSource(shader, shaderObject.getSource());
|
||||
gl.compileShader(shader);
|
||||
if (goog.DEBUG) {
|
||||
if (!gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS) &&
|
||||
!gl.isContextLost()) {
|
||||
this.logger.severe(gl.getShaderInfoLog(shader));
|
||||
goog.asserts.assert(
|
||||
gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS));
|
||||
}
|
||||
}
|
||||
this.shaderCache_[shaderKey] = shader;
|
||||
return shader;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() {
|
||||
var backgroundColor = this.getMap().getBackgroundColor();
|
||||
this.clearColor_ = new ol.Color(
|
||||
backgroundColor.r / 255,
|
||||
backgroundColor.g / 255,
|
||||
backgroundColor.b / 255,
|
||||
backgroundColor.a / 255);
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleCenterChanged = function() {
|
||||
goog.base(this, 'handleCenterChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleResolutionChanged = function() {
|
||||
goog.base(this, 'handleResolutionChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleRotationChanged = function() {
|
||||
goog.base(this, 'handleRotationChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleSizeChanged = function() {
|
||||
goog.base(this, 'handleSizeChanged');
|
||||
var size = this.getMap().getSize();
|
||||
if (!goog.isDef(size)) {
|
||||
return;
|
||||
}
|
||||
this.canvas_.width = size.width;
|
||||
this.canvas_.height = size.height;
|
||||
var gl = this.gl_;
|
||||
if (!goog.isNull(gl)) {
|
||||
gl.viewport(0, 0, size.width, size.height);
|
||||
this.getMap().render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('WebGLContextLost');
|
||||
}
|
||||
event.preventDefault();
|
||||
this.locations_ = null;
|
||||
this.arrayBuffer_ = null;
|
||||
this.shaderCache_ = {};
|
||||
this.programCache_ = {};
|
||||
this.textureCache_ = {};
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
layerRenderer.handleWebGLContextLost();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleWebGLContextRestored = function() {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('WebGLContextRestored');
|
||||
}
|
||||
this.initializeGL_();
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.initializeGL_ = function() {
|
||||
var gl = this.gl_;
|
||||
gl.activeTexture(goog.webgl.TEXTURE0);
|
||||
gl.blendFunc(goog.webgl.SRC_ALPHA, goog.webgl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.disable(goog.webgl.CULL_FACE);
|
||||
gl.disable(goog.webgl.DEPTH_TEST);
|
||||
gl.disable(goog.webgl.SCISSOR_TEST);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Image} image Image.
|
||||
* @return {boolean} Is image texture loaded.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.isImageTextureLoaded = function(image) {
|
||||
return image.src in this.textureCache_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.removeLayer = function(layer) {
|
||||
goog.base(this, 'removeLayer', layer);
|
||||
if (layer.getVisible()) {
|
||||
this.getMap().render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
var layerRenderer = goog.base(this, 'removeLayerRenderer', layer);
|
||||
if (!goog.isNull(layerRenderer)) {
|
||||
var layerKey = goog.getUid(layer);
|
||||
goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]);
|
||||
delete this.layerRendererChangeListenKeys_[layerKey];
|
||||
}
|
||||
return layerRenderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.render = function() {
|
||||
|
||||
if (!this.getMap().isDef()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = this.getMap().getSize();
|
||||
|
||||
var animate = goog.base(this, 'render');
|
||||
|
||||
var gl = this.getGL();
|
||||
|
||||
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null);
|
||||
|
||||
gl.clearColor(this.clearColor_.r, this.clearColor_.g, this.clearColor_.b,
|
||||
this.clearColor_.a);
|
||||
gl.clear(goog.webgl.COLOR_BUFFER_BIT);
|
||||
gl.enable(goog.webgl.BLEND);
|
||||
gl.viewport(0, 0, size.width, size.height);
|
||||
|
||||
var program = this.getProgram(this.fragmentShader_, this.vertexShader_);
|
||||
gl.useProgram(program);
|
||||
if (goog.isNull(this.locations_)) {
|
||||
this.locations_ = {
|
||||
aPosition: gl.getAttribLocation(program, 'aPosition'),
|
||||
aTexCoord: gl.getAttribLocation(program, 'aTexCoord'),
|
||||
uBrightness: gl.getUniformLocation(program, 'uBrightness'),
|
||||
uContrast: gl.getUniformLocation(program, 'uContrast'),
|
||||
uHue: gl.getUniformLocation(program, 'uHue'),
|
||||
uMatrix: gl.getUniformLocation(program, 'uMatrix'),
|
||||
uOpacity: gl.getUniformLocation(program, 'uOpacity'),
|
||||
uSaturation: gl.getUniformLocation(program, 'uSaturation'),
|
||||
uTexture: gl.getUniformLocation(program, 'uTexture')
|
||||
};
|
||||
}
|
||||
|
||||
if (goog.isNull(this.arrayBuffer_)) {
|
||||
var arrayBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer);
|
||||
gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([
|
||||
-1, -1, 0, 0,
|
||||
1, -1, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
1, 1, 1, 1
|
||||
]), goog.webgl.STATIC_DRAW);
|
||||
this.arrayBuffer_ = arrayBuffer;
|
||||
} else {
|
||||
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
|
||||
}
|
||||
|
||||
gl.enableVertexAttribArray(this.locations_.aPosition);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.aPosition, 2, goog.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(this.locations_.aTexCoord);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.aTexCoord, 2, goog.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(this.locations_.uTexture, 0);
|
||||
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
gl.uniformMatrix4fv(
|
||||
this.locations_.uMatrix, false, layerRenderer.getMatrix());
|
||||
gl.uniform1f(this.locations_.uBrightness, layer.getBrightness());
|
||||
gl.uniform1f(this.locations_.uContrast, layer.getContrast());
|
||||
gl.uniform1f(this.locations_.uHue, layer.getHue());
|
||||
gl.uniform1f(this.locations_.uOpacity, layer.getOpacity());
|
||||
gl.uniform1f(this.locations_.uSaturation, layer.getSaturation());
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, layerRenderer.getTexture());
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
|
||||
return animate;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.setLayerRenderer = function(
|
||||
layer, layerRenderer) {
|
||||
goog.base(this, 'setLayerRenderer', layer, layerRenderer);
|
||||
var layerKey = goog.getUid(layer);
|
||||
this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen(
|
||||
layerRenderer, goog.events.EventType.CHANGE,
|
||||
this.handleLayerRendererChange, false, this);
|
||||
};
|
||||
81
src/ol/renderer/webgl/shader.js
Normal file
81
src/ol/renderer/webgl/shader.js
Normal file
@@ -0,0 +1,81 @@
|
||||
goog.provide('ol.renderer.webgl.FragmentShader');
|
||||
goog.provide('ol.renderer.webgl.VertexShader');
|
||||
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.webgl');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string} source Source.
|
||||
*/
|
||||
ol.renderer.webgl.Shader = function(source) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.source_ = source;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Type.
|
||||
*/
|
||||
ol.renderer.webgl.Shader.prototype.getType = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Source.
|
||||
*/
|
||||
ol.renderer.webgl.Shader.prototype.getSource = function() {
|
||||
return this.source_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is animated?
|
||||
*/
|
||||
ol.renderer.webgl.Shader.prototype.isAnimated = goog.functions.FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
*/
|
||||
ol.renderer.webgl.FragmentShader = function(source) {
|
||||
goog.base(this, source);
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.FragmentShader, ol.renderer.webgl.Shader);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.FragmentShader.prototype.getType = function() {
|
||||
return goog.webgl.FRAGMENT_SHADER;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
*/
|
||||
ol.renderer.webgl.VertexShader = function(source) {
|
||||
goog.base(this, source);
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.VertexShader, ol.renderer.webgl.Shader);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VertexShader.prototype.getType = function() {
|
||||
return goog.webgl.VERTEX_SHADER;
|
||||
};
|
||||
496
src/ol/renderer/webgl/tilelayer.js
Normal file
496
src/ol/renderer/webgl/tilelayer.js
Normal file
@@ -0,0 +1,496 @@
|
||||
// FIXME large resolutions lead to too large framebuffers :-(
|
||||
// FIXME animated shaders! check in redraw
|
||||
|
||||
goog.provide('ol.renderer.webgl.TileLayer');
|
||||
goog.provide('ol.renderer.webgl.tilelayerrenderer');
|
||||
goog.provide('ol.renderer.webgl.tilelayerrenderer.shader.Fragment');
|
||||
goog.provide('ol.renderer.webgl.tilelayerrenderer.shader.Vertex');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('goog.vec.Vec4');
|
||||
goog.require('goog.webgl');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.MapEventType');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileLayer');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.renderer.webgl.FragmentShader');
|
||||
goog.require('ol.renderer.webgl.Layer');
|
||||
goog.require('ol.renderer.webgl.VertexShader');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.FragmentShader}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Fragment = function() {
|
||||
goog.base(this, [
|
||||
'precision mediump float;',
|
||||
'',
|
||||
'uniform sampler2D uTexture;',
|
||||
'',
|
||||
'varying vec2 vTexCoord;',
|
||||
'',
|
||||
'void main(void) {',
|
||||
' gl_FragColor = texture2D(uTexture, vTexCoord);',
|
||||
'}'
|
||||
].join('\n'));
|
||||
};
|
||||
goog.inherits(
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Fragment,
|
||||
ol.renderer.webgl.FragmentShader);
|
||||
goog.addSingletonGetter(ol.renderer.webgl.tilelayerrenderer.shader.Fragment);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.VertexShader}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Vertex = function() {
|
||||
goog.base(this, [
|
||||
'attribute vec2 aPosition;',
|
||||
'attribute vec2 aTexCoord;',
|
||||
'',
|
||||
'varying vec2 vTexCoord;',
|
||||
'',
|
||||
'uniform vec4 uTileOffset;',
|
||||
'',
|
||||
'void main(void) {',
|
||||
' gl_Position.xy = aPosition * uTileOffset.xy + uTileOffset.zw;',
|
||||
' gl_Position.z = 0.;',
|
||||
' gl_Position.w = 1.;',
|
||||
' vTexCoord = aTexCoord;',
|
||||
'}'
|
||||
].join('\n'));
|
||||
};
|
||||
goog.inherits(
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Vertex,
|
||||
ol.renderer.webgl.VertexShader);
|
||||
goog.addSingletonGetter(ol.renderer.webgl.tilelayerrenderer.shader.Vertex);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.TileLayer} tileLayer Tile layer.
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
goog.base(this, mapRenderer, tileLayer);
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.logger = goog.debug.Logger.getLogger(
|
||||
'ol.renderer.webgl.tilelayerrenderer.' + goog.getUid(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.FragmentShader}
|
||||
*/
|
||||
this.fragmentShader_ =
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Fragment.getInstance();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.VertexShader}
|
||||
*/
|
||||
this.vertexShader_ =
|
||||
ol.renderer.webgl.tilelayerrenderer.shader.Vertex.getInstance();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{aPosition: number,
|
||||
* aTexCoord: number,
|
||||
* uTileOffset: WebGLUniformLocation,
|
||||
* uTexture: WebGLUniformLocation}|null}
|
||||
*/
|
||||
this.locations_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLBuffer}
|
||||
*/
|
||||
this.arrayBuffer_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
this.texture_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLFramebuffer}
|
||||
*/
|
||||
this.framebuffer_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.framebufferDimension_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, number>}
|
||||
*/
|
||||
this.tileChangeListenerKeys_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.AnyType}
|
||||
*/
|
||||
this.matrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} framebufferDimension Framebuffer dimension.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.bindFramebuffer_ =
|
||||
function(framebufferDimension) {
|
||||
|
||||
var mapRenderer = this.getMapRenderer();
|
||||
var gl = mapRenderer.getGL();
|
||||
|
||||
if (!goog.isDef(this.framebufferDimension_) ||
|
||||
this.framebufferDimension_ != framebufferDimension) {
|
||||
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('re-sizing framebuffer');
|
||||
}
|
||||
|
||||
if (ol.renderer.webgl.FREE_RESOURCES_IMMEDIATELY) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('freeing WebGL resources');
|
||||
}
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(this.framebuffer_);
|
||||
gl.deleteTexture(this.texture_);
|
||||
}
|
||||
} else {
|
||||
var map = this.getMap();
|
||||
goog.events.listenOnce(
|
||||
map,
|
||||
ol.MapEventType.POST_RENDER,
|
||||
goog.partial(function(gl, framebuffer, texture) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('freeing WebGL resources on postrender');
|
||||
}
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}, gl, this.framebuffer_, this.texture_));
|
||||
}
|
||||
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA,
|
||||
framebufferDimension, framebufferDimension, 0, goog.webgl.RGBA,
|
||||
goog.webgl.UNSIGNED_BYTE, null);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER,
|
||||
goog.webgl.LINEAR);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER,
|
||||
goog.webgl.LINEAR);
|
||||
|
||||
var framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, framebuffer);
|
||||
gl.framebufferTexture2D(goog.webgl.FRAMEBUFFER,
|
||||
goog.webgl.COLOR_ATTACHMENT0, goog.webgl.TEXTURE_2D, texture, 0);
|
||||
|
||||
this.texture_ = texture;
|
||||
this.framebuffer_ = framebuffer;
|
||||
this.framebufferDimension_ = framebufferDimension;
|
||||
|
||||
} else {
|
||||
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, this.framebuffer_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
|
||||
var mapRenderer = this.getMapRenderer();
|
||||
var gl = mapRenderer.getGL();
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteBuffer(this.arrayBuffer_);
|
||||
gl.deleteFramebuffer(this.framebuffer_);
|
||||
gl.deleteTexture(this.texture_);
|
||||
}
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.TileLayer} Layer.
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.getLayer = function() {
|
||||
return /** @type {ol.TileLayer} */ goog.base(this, 'getLayer');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.getMatrix = function() {
|
||||
return this.matrix_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.getTexture = function() {
|
||||
return this.texture_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.handleTileChange = function() {
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
|
||||
this.locations_ = null;
|
||||
this.arrayBuffer_ = null;
|
||||
this.texture_ = null;
|
||||
this.framebuffer_ = null;
|
||||
this.framebufferDimension_ = undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.render = function() {
|
||||
|
||||
var animate = false;
|
||||
|
||||
var mapRenderer = this.getMapRenderer();
|
||||
var map = this.getMap();
|
||||
var gl = mapRenderer.getGL();
|
||||
|
||||
goog.asserts.assert(map.isDef());
|
||||
var mapCenter = map.getCenter();
|
||||
var mapExtent = map.getExtent();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
var mapRotatedExtent = map.getRotatedExtent();
|
||||
var mapRotation = map.getRotation();
|
||||
|
||||
var tileLayer = this.getLayer();
|
||||
var tileStore = tileLayer.getStore();
|
||||
var tileGrid = tileStore.getTileGrid();
|
||||
var z = tileGrid.getZForResolution(mapResolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
var tileBounds = tileGrid.getTileBoundsForExtentAndResolution(
|
||||
mapRotatedExtent, tileResolution);
|
||||
var tileBoundsSize = tileBounds.getSize();
|
||||
var tileSize = tileGrid.getTileSize();
|
||||
|
||||
var maxDimension = Math.max(
|
||||
tileBoundsSize.width * tileSize.width,
|
||||
tileBoundsSize.height * tileSize.height);
|
||||
var framebufferDimension =
|
||||
Math.pow(2, Math.ceil(Math.log(maxDimension) / Math.log(2)));
|
||||
var framebufferExtentSize = new ol.Size(
|
||||
tileResolution * framebufferDimension,
|
||||
tileResolution * framebufferDimension);
|
||||
var origin = tileGrid.getOrigin(z);
|
||||
var minX = origin.x + tileBounds.minX * tileSize.width * tileResolution;
|
||||
var minY = origin.y + tileBounds.minY * tileSize.height * tileResolution;
|
||||
var framebufferExtent = new ol.Extent(
|
||||
minX,
|
||||
minY,
|
||||
minX + framebufferExtentSize.width,
|
||||
minY + framebufferExtentSize.height);
|
||||
|
||||
this.bindFramebuffer_(framebufferDimension);
|
||||
gl.viewport(0, 0, framebufferDimension, framebufferDimension);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(goog.webgl.COLOR_BUFFER_BIT);
|
||||
gl.disable(goog.webgl.BLEND);
|
||||
|
||||
var program = mapRenderer.getProgram(
|
||||
this.fragmentShader_, this.vertexShader_);
|
||||
gl.useProgram(program);
|
||||
if (goog.isNull(this.locations_)) {
|
||||
this.locations_ = {
|
||||
aPosition: gl.getAttribLocation(program, 'aPosition'),
|
||||
aTexCoord: gl.getAttribLocation(program, 'aTexCoord'),
|
||||
uTileOffset: gl.getUniformLocation(program, 'uTileOffset'),
|
||||
uTexture: gl.getUniformLocation(program, 'uTexture')
|
||||
};
|
||||
}
|
||||
|
||||
if (goog.isNull(this.arrayBuffer_)) {
|
||||
var arrayBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, arrayBuffer);
|
||||
gl.bufferData(goog.webgl.ARRAY_BUFFER, new Float32Array([
|
||||
0, 0, 0, 1,
|
||||
1, 0, 1, 1,
|
||||
0, 1, 0, 0,
|
||||
1, 1, 1, 0
|
||||
]), goog.webgl.STATIC_DRAW);
|
||||
this.arrayBuffer_ = arrayBuffer;
|
||||
} else {
|
||||
gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.arrayBuffer_);
|
||||
}
|
||||
|
||||
gl.enableVertexAttribArray(this.locations_.aPosition);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.aPosition, 2, goog.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(this.locations_.aTexCoord);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.aTexCoord, 2, goog.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(this.locations_.uTexture, 0);
|
||||
|
||||
/**
|
||||
* @type {Object.<number, Object.<string, ol.TileCoord>>}
|
||||
*/
|
||||
var tilesToDrawByZ = {};
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.Tile>}
|
||||
*/
|
||||
var imagesToLoad = [];
|
||||
|
||||
tilesToDrawByZ[z] = {};
|
||||
tileBounds.forEachTileCoord(z, function(tileCoord) {
|
||||
|
||||
var tile = tileStore.getTile(tileCoord);
|
||||
|
||||
if (goog.isNull(tile)) {
|
||||
} else if (tile.getState() == ol.TileState.LOADED) {
|
||||
if (mapRenderer.isImageTextureLoaded(tile.getImage())) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
return;
|
||||
} else {
|
||||
imagesToLoad.push(tile.getImage());
|
||||
}
|
||||
} else {
|
||||
var tileKey = goog.getUid(tile);
|
||||
if (!(tileKey in this.tileChangeListenerKeys_)) {
|
||||
tile.load();
|
||||
// FIXME will need to handle aborts as well
|
||||
this.tileChangeListenerKeys_[tileKey] = goog.events.listen(tile,
|
||||
goog.events.EventType.CHANGE, this.handleTileChange, false, this);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME this could be more efficient about filling partial holes
|
||||
tileGrid.forEachTileCoordParentTileBounds(
|
||||
tileCoord,
|
||||
function(z, tileBounds) {
|
||||
var fullyCovered = true;
|
||||
tileBounds.forEachTileCoord(z, function(tileCoord) {
|
||||
var tileCoordKey = tileCoord.toString();
|
||||
if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) {
|
||||
return;
|
||||
}
|
||||
var tile = tileStore.getTile(tileCoord);
|
||||
if (!goog.isNull(tile) &&
|
||||
tile.getState() == ol.TileState.LOADED) {
|
||||
if (!tilesToDrawByZ[z]) {
|
||||
tilesToDrawByZ[z] = {};
|
||||
}
|
||||
tilesToDrawByZ[z][tileCoordKey] = tile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
});
|
||||
return fullyCovered;
|
||||
});
|
||||
|
||||
}, this);
|
||||
|
||||
var zs = goog.object.getKeys(tilesToDrawByZ);
|
||||
goog.array.sort(zs);
|
||||
var uTileOffset = goog.vec.Vec4.createFloat32();
|
||||
goog.array.forEach(zs, function(z) {
|
||||
goog.object.forEach(tilesToDrawByZ[z], function(tile) {
|
||||
var tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord);
|
||||
var sx = 2 * tileExtent.getWidth() / framebufferExtentSize.width;
|
||||
var sy = 2 * tileExtent.getHeight() / framebufferExtentSize.height;
|
||||
var tx = 2 * (tileExtent.minX - framebufferExtent.minX) /
|
||||
framebufferExtentSize.width - 1;
|
||||
var ty = 2 * (tileExtent.minY - framebufferExtent.minY) /
|
||||
framebufferExtentSize.height - 1;
|
||||
goog.vec.Vec4.setFromValues(uTileOffset, sx, sy, tx, ty);
|
||||
gl.uniform4fv(this.locations_.uTileOffset, uTileOffset);
|
||||
mapRenderer.bindImageTexture(
|
||||
tile.getImage(), goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
goog.vec.Mat4.makeIdentity(this.matrix_);
|
||||
goog.vec.Mat4.translate(this.matrix_,
|
||||
(mapCenter.x - framebufferExtent.minX) /
|
||||
(framebufferExtent.maxX - framebufferExtent.minX),
|
||||
(mapCenter.y - framebufferExtent.minY) /
|
||||
(framebufferExtent.maxY - framebufferExtent.minY),
|
||||
0);
|
||||
goog.vec.Mat4.scale(this.matrix_,
|
||||
(mapExtent.maxX - mapExtent.minX) /
|
||||
(framebufferExtent.maxX - framebufferExtent.minX),
|
||||
(mapExtent.maxY - mapExtent.minY) /
|
||||
(framebufferExtent.maxY - framebufferExtent.minY),
|
||||
1);
|
||||
if (goog.isDef(mapRotation)) {
|
||||
goog.vec.Mat4.rotate(this.matrix_,
|
||||
mapRotation,
|
||||
0,
|
||||
0,
|
||||
1);
|
||||
}
|
||||
goog.vec.Mat4.translate(this.matrix_,
|
||||
-0.5,
|
||||
-0.5,
|
||||
0);
|
||||
|
||||
if (!goog.array.isEmpty(imagesToLoad)) {
|
||||
goog.events.listenOnce(
|
||||
map,
|
||||
ol.MapEventType.POST_RENDER,
|
||||
goog.partial(function(mapRenderer, imagesToLoad) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('uploading textures');
|
||||
}
|
||||
goog.array.forEach(imagesToLoad, function(image) {
|
||||
mapRenderer.bindImageTexture(
|
||||
image, goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
});
|
||||
}, mapRenderer, imagesToLoad));
|
||||
animate = true;
|
||||
}
|
||||
|
||||
return animate;
|
||||
|
||||
};
|
||||
15
src/ol/renderer/webgl/webgl.js
Normal file
15
src/ol/renderer/webgl/webgl.js
Normal file
@@ -0,0 +1,15 @@
|
||||
goog.provide('ol.renderer.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Free resources immediately.
|
||||
*/
|
||||
ol.renderer.webgl.FREE_RESOURCES_IMMEDIATELY = false;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is supported.
|
||||
*/
|
||||
ol.renderer.webgl.isSupported = function() {
|
||||
return 'WebGLRenderingContext' in goog.global;
|
||||
};
|
||||
25
src/ol/size.js
Normal file
25
src/ol/size.js
Normal file
@@ -0,0 +1,25 @@
|
||||
goog.provide('ol.Size');
|
||||
|
||||
goog.require('goog.math.Size');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.math.Size}
|
||||
* @param {number} width Width.
|
||||
* @param {number} height Height.
|
||||
*/
|
||||
ol.Size = function(width, height) {
|
||||
goog.base(this, width, height);
|
||||
};
|
||||
goog.inherits(ol.Size, goog.math.Size);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Size} size Size.
|
||||
* @return {boolean} Equals.
|
||||
*/
|
||||
ol.Size.prototype.equals = function(size) {
|
||||
return this.width == size.width && this.height == size.height;
|
||||
};
|
||||
96
src/ol/store.js
Normal file
96
src/ol/store.js
Normal file
@@ -0,0 +1,96 @@
|
||||
goog.provide('ol.Store');
|
||||
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Projection');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.Projection} projection Projection.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @param {Array.<ol.Attribution>=} opt_attributions Attributions.
|
||||
*/
|
||||
ol.Store = function(projection, opt_extent, opt_attributions) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Projection}
|
||||
*/
|
||||
this.projection_ = projection;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.extent_ = opt_extent || projection.getExtent();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.Attribution>}
|
||||
*/
|
||||
this.attributions_ = opt_attributions || null;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.Attribution>} Attributions.
|
||||
*/
|
||||
ol.Store.prototype.getAttributions = function() {
|
||||
return this.attributions_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.Store.prototype.getExtent = function() {
|
||||
return this.extent_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Projection} Projection.
|
||||
*/
|
||||
ol.Store.prototype.getProjection = function() {
|
||||
return this.projection_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>|undefined} Resolutions.
|
||||
*/
|
||||
ol.Store.prototype.getResolutions = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is ready.
|
||||
*/
|
||||
ol.Store.prototype.isReady = goog.functions.TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Attribution>} attributions Attributions.
|
||||
*/
|
||||
ol.Store.prototype.setAttributions = function(attributions) {
|
||||
this.attributions_ = attributions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.Store.prototype.setExtent = function(extent) {
|
||||
this.extent_ = extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Projection} projection Projetion.
|
||||
*/
|
||||
ol.Store.prototype.setProjection = function(projection) {
|
||||
this.projection_ = projection;
|
||||
};
|
||||
160
src/ol/tile.js
Normal file
160
src/ol/tile.js
Normal file
@@ -0,0 +1,160 @@
|
||||
goog.provide('ol.Tile');
|
||||
goog.provide('ol.TileState');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.TileCoord');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.TileState = {
|
||||
IDLE: 0,
|
||||
LOADING: 1,
|
||||
LOADED: 2,
|
||||
ERROR: 3
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {string} src Source.
|
||||
* @param {?string} crossOrigin Cross origin.
|
||||
*/
|
||||
ol.Tile = function(tileCoord, src, crossOrigin) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {ol.TileCoord}
|
||||
*/
|
||||
this.tileCoord = tileCoord;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.src_ = src;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileState}
|
||||
*/
|
||||
this.state_ = ol.TileState.IDLE;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Image}
|
||||
*/
|
||||
this.image_ = new Image();
|
||||
if (!goog.isNull(crossOrigin)) {
|
||||
this.image_.crossOrigin = crossOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, Image>}
|
||||
*/
|
||||
this.imageByContext_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.imageListenerKeys_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.Tile, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.Tile.prototype.dispatchChangeEvent = function() {
|
||||
this.dispatchEvent(goog.events.EventType.CHANGE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object=} opt_context Object.
|
||||
* @return {Image} Image.
|
||||
*/
|
||||
ol.Tile.prototype.getImage = function(opt_context) {
|
||||
if (goog.isDef(opt_context)) {
|
||||
var image;
|
||||
var key = goog.getUid(opt_context);
|
||||
if (key in this.imageByContext_) {
|
||||
return this.imageByContext_[key];
|
||||
} else if (goog.object.isEmpty(this.imageByContext_)) {
|
||||
image = this.image_;
|
||||
} else {
|
||||
image = /** @type {Image} */ this.image_.cloneNode(false);
|
||||
}
|
||||
this.imageByContext_[key] = image;
|
||||
return image;
|
||||
} else {
|
||||
return this.image_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.TileState} State.
|
||||
*/
|
||||
ol.Tile.prototype.getState = function() {
|
||||
return this.state_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Tile.prototype.handleImageError_ = function() {
|
||||
this.state_ = ol.TileState.ERROR;
|
||||
this.unlistenImage_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Tile.prototype.handleImageLoad_ = function() {
|
||||
this.state_ = ol.TileState.LOADED;
|
||||
this.unlistenImage_();
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load.
|
||||
*/
|
||||
ol.Tile.prototype.load = function() {
|
||||
if (this.state_ == ol.TileState.IDLE) {
|
||||
this.state_ = ol.TileState.LOADING;
|
||||
goog.asserts.assert(goog.isNull(this.imageListenerKeys_));
|
||||
this.imageListenerKeys_ = [
|
||||
goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,
|
||||
this.handleImageError_, false, this),
|
||||
goog.events.listenOnce(this.image_, goog.events.EventType.LOAD,
|
||||
this.handleImageLoad_, false, this)
|
||||
];
|
||||
this.image_.src = this.src_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Tile.prototype.unlistenImage_ = function() {
|
||||
goog.asserts.assert(!goog.isNull(this.imageListenerKeys_));
|
||||
goog.array.forEach(this.imageListenerKeys_, goog.events.unlistenByKey);
|
||||
this.imageListenerKeys_ = null;
|
||||
};
|
||||
|
||||
113
src/ol/tilebounds.js
Normal file
113
src/ol/tilebounds.js
Normal file
@@ -0,0 +1,113 @@
|
||||
goog.provide('ol.TileBounds');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Rectangle');
|
||||
goog.require('ol.TileCoord');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Rectangle}
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
*/
|
||||
ol.TileBounds = function(minX, minY, maxX, maxY) {
|
||||
goog.base(this, minX, minY, maxX, maxY);
|
||||
};
|
||||
goog.inherits(ol.TileBounds, ol.Rectangle);
|
||||
|
||||
|
||||
/**
|
||||
* @param {...ol.TileCoord} var_args Tile coordinates.
|
||||
* @return {!ol.TileBounds} Bounding tile box.
|
||||
*/
|
||||
ol.TileBounds.boundingTileBounds = function(var_args) {
|
||||
var tileCoord0 = arguments[0];
|
||||
var tileBounds = new ol.TileBounds(tileCoord0.x, tileCoord0.y,
|
||||
tileCoord0.x, tileCoord0.y);
|
||||
var i;
|
||||
for (i = 1; i < arguments.length; ++i) {
|
||||
var tileCoord = arguments[i];
|
||||
goog.asserts.assert(tileCoord.z == tileCoord0.z);
|
||||
tileBounds.minX = Math.min(tileBounds.minX, tileCoord.x);
|
||||
tileBounds.minY = Math.min(tileBounds.minY, tileCoord.y);
|
||||
tileBounds.maxX = Math.max(tileBounds.maxX, tileCoord.x);
|
||||
tileBounds.maxY = Math.max(tileBounds.maxY, tileCoord.y);
|
||||
}
|
||||
return tileBounds;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.TileBounds} Clone.
|
||||
*/
|
||||
ol.TileBounds.prototype.clone = function() {
|
||||
return new ol.TileBounds(this.minX, this.minY, this.maxX, this.maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {boolean} Contains tile coordinate.
|
||||
*/
|
||||
ol.TileBounds.prototype.contains = function(tileCoord) {
|
||||
return this.minX <= tileCoord.x && tileCoord.x <= this.maxX &&
|
||||
this.minY <= tileCoord.y && tileCoord.y <= this.maxY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileBounds} tileBounds Tile bounds.
|
||||
* @return {boolean} Contains.
|
||||
*/
|
||||
ol.TileBounds.prototype.containsTileBounds = function(tileBounds) {
|
||||
return this.minX <= tileBounds.minX && tileBounds.maxX <= this.maxX &&
|
||||
this.minY <= tileBounds.minY && tileBounds.minY <= this.maxY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileBounds} tileBounds Tile bounds.
|
||||
* @return {boolean} Equals.
|
||||
*/
|
||||
ol.TileBounds.prototype.equals = function(tileBounds) {
|
||||
return this.minX == tileBounds.minX && tileBounds.maxX == this.maxX &&
|
||||
this.minY == tileBounds.minY && tileBounds.minY == this.minY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @param {function(this: T, ol.TileCoord)} f Callback.
|
||||
* @param {T=} opt_obj The object to be used for the value of 'this' within f.
|
||||
* @template T
|
||||
*/
|
||||
ol.TileBounds.prototype.forEachTileCoord = function(z, f, opt_obj) {
|
||||
var x, y;
|
||||
for (x = this.minX; x <= this.maxX; ++x) {
|
||||
for (y = this.minY; y <= this.maxY; ++y) {
|
||||
f.call(opt_obj, new ol.TileCoord(z, x, y));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {number} Height.
|
||||
*/
|
||||
ol.TileBounds.prototype.getHeight = function() {
|
||||
return this.maxY - this.minY + 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {number} Width.
|
||||
*/
|
||||
ol.TileBounds.prototype.getWidth = function() {
|
||||
return this.maxX - this.minX + 1;
|
||||
};
|
||||
102
src/ol/tilebounds_test.js
Normal file
102
src/ol/tilebounds_test.js
Normal file
@@ -0,0 +1,102 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.TileBounds');
|
||||
|
||||
|
||||
function testClone() {
|
||||
var tileBounds = new ol.TileBounds(1, 2, 3, 4);
|
||||
var clonedTileBounds = tileBounds.clone();
|
||||
assertTrue(clonedTileBounds instanceof ol.TileBounds);
|
||||
assertFalse(clonedTileBounds === tileBounds);
|
||||
assertEquals(tileBounds.minX, clonedTileBounds.minX);
|
||||
assertEquals(tileBounds.minY, clonedTileBounds.minY);
|
||||
assertEquals(tileBounds.maxX, clonedTileBounds.maxX);
|
||||
assertEquals(tileBounds.maxY, clonedTileBounds.maxY);
|
||||
}
|
||||
|
||||
|
||||
function testContains() {
|
||||
var tileBounds = new ol.TileBounds(1, 1, 3, 3);
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 0, 0)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 0, 1)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 0, 2)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 0, 3)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 0, 4)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 1, 0)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 1, 1)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 1, 2)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 1, 3)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 1, 4)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 2, 0)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 2, 1)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 2, 2)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 2, 3)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 2, 4)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 3, 0)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 3, 1)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 3, 2)));
|
||||
assertTrue(tileBounds.contains(new ol.TileCoord(0, 3, 3)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 3, 4)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 4, 0)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 4, 1)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 4, 2)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 4, 3)));
|
||||
assertFalse(tileBounds.contains(new ol.TileCoord(0, 4, 4)));
|
||||
}
|
||||
|
||||
|
||||
function testBoundingTileBounds() {
|
||||
var tileBounds = new ol.TileBounds.boundingTileBounds(
|
||||
new ol.TileCoord(3, 1, 3),
|
||||
new ol.TileCoord(3, 2, 0));
|
||||
assertEquals(1, tileBounds.minX);
|
||||
assertEquals(0, tileBounds.minY);
|
||||
assertEquals(2, tileBounds.maxX);
|
||||
assertEquals(3, tileBounds.maxY);
|
||||
}
|
||||
|
||||
|
||||
function testBoundingTileBoundsMixedZ() {
|
||||
assertThrows(function() {
|
||||
var tileBounds = new ol.TileBounds.boundingTileBounds(
|
||||
new ol.TileCoord(3, 1, 3),
|
||||
new ol.TileCoord(4, 2, 0));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testForEachTileCoord() {
|
||||
|
||||
var tileBounds = new ol.TileBounds(0, 2, 1, 3);
|
||||
|
||||
var tileCoords = [];
|
||||
tileBounds.forEachTileCoord(5, function(tileCoord) {
|
||||
tileCoords.push(tileCoord.clone());
|
||||
});
|
||||
|
||||
assertEquals(4, tileCoords.length);
|
||||
|
||||
assertEquals(5, tileCoords[0].z);
|
||||
assertEquals(0, tileCoords[0].x);
|
||||
assertEquals(2, tileCoords[0].y);
|
||||
|
||||
assertEquals(5, tileCoords[1].z);
|
||||
assertEquals(0, tileCoords[1].x);
|
||||
assertEquals(3, tileCoords[1].y);
|
||||
|
||||
assertEquals(5, tileCoords[2].z);
|
||||
assertEquals(1, tileCoords[2].x);
|
||||
assertEquals(2, tileCoords[2].y);
|
||||
|
||||
assertEquals(5, tileCoords[3].z);
|
||||
assertEquals(1, tileCoords[3].x);
|
||||
assertEquals(3, tileCoords[3].y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testSize() {
|
||||
var tileBounds = new ol.TileBounds(0, 1, 2, 4);
|
||||
var size = tileBounds.getSize();
|
||||
assertEquals(3, size.width);
|
||||
assertEquals(4, size.height);
|
||||
}
|
||||
122
src/ol/tilecoord.js
Normal file
122
src/ol/tilecoord.js
Normal file
@@ -0,0 +1,122 @@
|
||||
goog.provide('ol.TileCoord');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('ol.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.QuadKeyCharCode = {
|
||||
ZERO: '0'.charCodeAt(0),
|
||||
ONE: '1'.charCodeAt(0),
|
||||
TWO: '2'.charCodeAt(0),
|
||||
THREE: '3'.charCodeAt(0)
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Coordinate}
|
||||
* @param {number} z Z.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
ol.TileCoord = function(z, x, y) {
|
||||
|
||||
goog.base(this, x, y);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.z = z;
|
||||
|
||||
};
|
||||
goog.inherits(ol.TileCoord, ol.Coordinate);
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} quadKey Quad key.
|
||||
* @return {ol.TileCoord} Tile coordinate.
|
||||
*/
|
||||
ol.TileCoord.createFromQuadKey = function(quadKey) {
|
||||
var z = quadKey.length, x = 0, y = 0;
|
||||
var mask = 1 << (z - 1);
|
||||
var i;
|
||||
for (i = 0; i < z; ++i) {
|
||||
switch (quadKey.charCodeAt(i)) {
|
||||
case ol.QuadKeyCharCode.ONE:
|
||||
x += mask;
|
||||
break;
|
||||
case ol.QuadKeyCharCode.TWO:
|
||||
y += mask;
|
||||
break;
|
||||
case ol.QuadKeyCharCode.THREE:
|
||||
x += mask;
|
||||
y += mask;
|
||||
break;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
return new ol.TileCoord(z, x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} str String.
|
||||
* @return {ol.TileCoord} Tile coord.
|
||||
*/
|
||||
ol.TileCoord.createFromString = function(str) {
|
||||
var v = str.split('/');
|
||||
v = goog.array.map(v, function(e, i, a) {
|
||||
return parseInt(e, 10);
|
||||
});
|
||||
return new ol.TileCoord(v[0], v[1], v[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.TileCoord} Clone.
|
||||
*/
|
||||
ol.TileCoord.prototype.clone = function() {
|
||||
return new ol.TileCoord(this.z, this.x, this.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Hash.
|
||||
*/
|
||||
ol.TileCoord.prototype.hash = function() {
|
||||
return (this.x << this.z) + this.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Quad key.
|
||||
*/
|
||||
ol.TileCoord.prototype.quadKey = function() {
|
||||
var digits = new Array(this.z);
|
||||
var mask = 1 << (this.z - 1);
|
||||
var i, charCode;
|
||||
for (i = 0; i < this.z; ++i) {
|
||||
charCode = ol.QuadKeyCharCode.ZERO;
|
||||
if (this.x & mask) {
|
||||
charCode += 1;
|
||||
}
|
||||
if (this.y & mask) {
|
||||
charCode += 2;
|
||||
}
|
||||
digits[i] = String.fromCharCode(charCode);
|
||||
mask >>= 1;
|
||||
}
|
||||
return digits.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.TileCoord.prototype.toString = function() {
|
||||
return [this.z, this.x, this.y].join('/');
|
||||
};
|
||||
39
src/ol/tilecoord_test.js
Normal file
39
src/ol/tilecoord_test.js
Normal file
@@ -0,0 +1,39 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.TileCoord');
|
||||
|
||||
|
||||
function testConstructorOrderZXY() {
|
||||
var tc1 = new ol.TileCoord(1, 2, 3);
|
||||
assertEquals(1, tc1.z);
|
||||
assertEquals(2, tc1.x);
|
||||
assertEquals(3, tc1.y);
|
||||
}
|
||||
|
||||
|
||||
function testCreateFromQuadKey() {
|
||||
var tileCoord = ol.TileCoord.createFromQuadKey('213');
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(3, tileCoord.x);
|
||||
assertEquals(5, tileCoord.y);
|
||||
}
|
||||
|
||||
|
||||
function testCreateFromString() {
|
||||
var str = '1/2/3';
|
||||
var tc = ol.TileCoord.createFromString(str);
|
||||
assertEquals(1, tc.z);
|
||||
assertEquals(2, tc.x);
|
||||
assertEquals(3, tc.y);
|
||||
}
|
||||
|
||||
|
||||
function testQuadKey() {
|
||||
assertEquals('213', (new ol.TileCoord(3, 3, 5)).quadKey());
|
||||
}
|
||||
|
||||
|
||||
function testHash() {
|
||||
var tc1 = new ol.TileCoord(3, 2, 1);
|
||||
var tc2 = new ol.TileCoord(3, 1, 1);
|
||||
assertTrue(tc1.hash() != tc2.hash());
|
||||
}
|
||||
71
src/ol/tilecoveragearea.js
Normal file
71
src/ol/tilecoveragearea.js
Normal file
@@ -0,0 +1,71 @@
|
||||
goog.provide('ol.TileCoverageArea');
|
||||
|
||||
goog.require('ol.CoverageArea');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.TileGrid');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.CoverageArea}
|
||||
* @param {ol.TileGrid} tileGrid Tile grid.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} minZ Minimum Z.
|
||||
* @param {number} maxZ Maximum Z.
|
||||
*/
|
||||
ol.TileCoverageArea = function(tileGrid, extent, minZ, maxZ) {
|
||||
|
||||
goog.base(this, extent);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileGrid}
|
||||
*/
|
||||
this.tileGrid_ = tileGrid;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minZ_ = minZ;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxZ_ = maxZ;
|
||||
|
||||
};
|
||||
goog.inherits(ol.TileCoverageArea, ol.CoverageArea);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.TileCoverageArea.prototype.intersectsExtentAndResolution =
|
||||
function(extent, resolution) {
|
||||
var z = this.tileGrid_.getZForResolution(resolution);
|
||||
return this.intersectsExtentAndZ(extent, z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} z Z.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
ol.TileCoverageArea.prototype.intersectsExtentAndZ = function(extent, z) {
|
||||
return this.minZ_ <= z && z <= this.maxZ_ && this.intersectsExtent(extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TransformFunction} transformFn Transform.
|
||||
* @return {ol.TileCoverageArea} Transformed tile coverage area.
|
||||
*/
|
||||
ol.TileCoverageArea.prototype.transform = function(transformFn) {
|
||||
var extent = this.extent.transform(transformFn);
|
||||
return new ol.TileCoverageArea(
|
||||
this.tileGrid_, extent, this.minZ_, this.maxZ_);
|
||||
};
|
||||
311
src/ol/tilegrid.js
Normal file
311
src/ol/tilegrid.js
Normal file
@@ -0,0 +1,311 @@
|
||||
// FIXME cope with tile grids whose minium zoom is not zero
|
||||
|
||||
goog.provide('ol.TileGrid');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.PixelBounds');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileBounds');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.array');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {!Array.<number>} resolutions Resolutions.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Coordinate|!Array.<ol.Coordinate>} origin Origin.
|
||||
* @param {ol.Size=} opt_tileSize Tile size.
|
||||
*/
|
||||
ol.TileGrid = function(resolutions, extent, origin, opt_tileSize) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.resolutions_ = resolutions;
|
||||
goog.asserts.assert(goog.array.isSorted(resolutions, function(a, b) {
|
||||
return b - a;
|
||||
}, true));
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.numResolutions_ = this.resolutions_.length;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.extent_ = extent;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.origin_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.Coordinate>}
|
||||
*/
|
||||
this.origins_ = null;
|
||||
|
||||
if (origin instanceof ol.Coordinate) {
|
||||
this.origin_ = origin;
|
||||
} else if (goog.isArray(origin)) {
|
||||
goog.asserts.assert(origin.length == this.numResolutions_);
|
||||
this.origins_ = origin;
|
||||
} else {
|
||||
goog.asserts.assert(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Size}
|
||||
*/
|
||||
this.tileSize_ = opt_tileSize || new ol.Size(256, 256);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {function(this: T, number, ol.TileBounds): boolean} callback
|
||||
* Callback.
|
||||
* @param {T=} opt_obj Object.
|
||||
* @template T
|
||||
*/
|
||||
ol.TileGrid.prototype.forEachTileCoordParentTileBounds =
|
||||
function(tileCoord, callback, opt_obj) {
|
||||
var tileCoordExtent = this.getTileCoordExtent(tileCoord);
|
||||
var z = tileCoord.z - 1;
|
||||
while (z >= 0) {
|
||||
if (callback.call(
|
||||
opt_obj, z, this.getTileBoundsForExtentAndZ(tileCoordExtent, z))) {
|
||||
return;
|
||||
}
|
||||
--z;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.TileGrid.prototype.getExtent = function() {
|
||||
return this.extent_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @return {ol.Coordinate} Origin.
|
||||
*/
|
||||
ol.TileGrid.prototype.getOrigin = function(z) {
|
||||
if (!goog.isNull(this.origin_)) {
|
||||
return this.origin_;
|
||||
} else {
|
||||
goog.asserts.assert(!goog.isNull(this.origins_));
|
||||
goog.asserts.assert(0 <= z && z < this.origins_.length);
|
||||
return this.origins_[z];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {ol.PixelBounds} Pixel bounds.
|
||||
*/
|
||||
ol.TileGrid.prototype.getPixelBoundsForTileCoordAndResolution = function(
|
||||
tileCoord, resolution) {
|
||||
var scale = resolution / this.getResolution(tileCoord.z);
|
||||
var tileSize = this.getTileSize();
|
||||
tileSize = new ol.Size(tileSize.width / scale,
|
||||
tileSize.height / scale);
|
||||
var minX, maxX, minY, maxY;
|
||||
minX = Math.round(tileCoord.x * tileSize.width);
|
||||
maxX = Math.round((tileCoord.x + 1) * tileSize.width);
|
||||
minY = Math.round(tileCoord.y * tileSize.height);
|
||||
maxY = Math.round((tileCoord.y + 1) * tileSize.height);
|
||||
return new ol.PixelBounds(minX, minY, maxX, maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @return {number} Resolution.
|
||||
*/
|
||||
ol.TileGrid.prototype.getResolution = function(z) {
|
||||
goog.asserts.assert(0 <= z && z < this.numResolutions_);
|
||||
return this.resolutions_[z];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Resolutions.
|
||||
*/
|
||||
ol.TileGrid.prototype.getResolutions = function() {
|
||||
return this.resolutions_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @param {ol.TileBounds} tileBounds Tile bounds.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileBoundsExtent = function(z, tileBounds) {
|
||||
var origin = this.getOrigin(z);
|
||||
var resolution = this.getResolution(z);
|
||||
var tileSize = this.tileSize_;
|
||||
var minX = origin.x + tileBounds.minX * tileSize.width * resolution;
|
||||
var minY = origin.y + tileBounds.minY * tileSize.height * resolution;
|
||||
var maxX = origin.x + (tileBounds.maxX + 1) * tileSize.width * resolution;
|
||||
var maxY = origin.y + (tileBounds.maxY + 1) * tileSize.height * resolution;
|
||||
return new ol.Extent(minX, minY, maxX, maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {ol.TileBounds} Tile bounds.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileBoundsForExtentAndResolution = function(
|
||||
extent, resolution) {
|
||||
var min = this.getTileCoordForCoordAndResolution(
|
||||
new ol.Coordinate(extent.minX, extent.minY), resolution);
|
||||
var max = this.getTileCoordForCoordAndResolution(
|
||||
new ol.Coordinate(extent.maxX, extent.maxY), resolution);
|
||||
return new ol.TileBounds(min.x, min.y, max.x, max.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} z Z.
|
||||
* @return {ol.TileBounds} Tile bounds.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileBoundsForExtentAndZ = function(extent, z) {
|
||||
var resolution = this.getResolution(z);
|
||||
return this.getTileBoundsForExtentAndResolution(extent, resolution);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {ol.Coordinate} Tile center.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileCoordCenter = function(tileCoord) {
|
||||
var origin = this.getOrigin(tileCoord.z);
|
||||
var resolution = this.getResolution(tileCoord.z);
|
||||
var tileSize = this.tileSize_;
|
||||
var x = origin.x + (tileCoord.x + 0.5) * tileSize.width * resolution;
|
||||
var y = origin.y + (tileCoord.y + 0.5) * tileSize.height * resolution;
|
||||
return new ol.Coordinate(x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileCoordExtent = function(tileCoord) {
|
||||
var origin = this.getOrigin(tileCoord.z);
|
||||
var resolution = this.getResolution(tileCoord.z);
|
||||
var tileSize = this.tileSize_;
|
||||
var minX = origin.x + tileCoord.x * tileSize.width * resolution;
|
||||
var minY = origin.y + tileCoord.y * tileSize.height * resolution;
|
||||
var maxX = minX + tileSize.width * resolution;
|
||||
var maxY = minY + tileSize.height * resolution;
|
||||
return new ol.Extent(minX, minY, maxX, maxY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {ol.TileCoord} Tile coordinate.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileCoordForCoordAndResolution = function(
|
||||
coordinate, resolution) {
|
||||
var z = this.getZForResolution(resolution);
|
||||
var scale = resolution / this.getResolution(z);
|
||||
var origin = this.getOrigin(z);
|
||||
|
||||
var offsetFromOrigin = new ol.Coordinate(
|
||||
Math.floor((coordinate.x - origin.x) / resolution),
|
||||
Math.floor((coordinate.y - origin.y) / resolution));
|
||||
|
||||
var tileSize = this.getTileSize();
|
||||
tileSize = new ol.Size(tileSize.width / scale,
|
||||
tileSize.height / scale);
|
||||
|
||||
var x, y;
|
||||
x = Math.floor(offsetFromOrigin.x / tileSize.width);
|
||||
y = Math.floor(offsetFromOrigin.y / tileSize.height);
|
||||
|
||||
var tileCoord = new ol.TileCoord(z, x, y);
|
||||
var tileCoordPixelBounds = this.getPixelBoundsForTileCoordAndResolution(
|
||||
tileCoord, resolution);
|
||||
|
||||
// adjust x to allow for stretched tiles
|
||||
if (offsetFromOrigin.x < tileCoordPixelBounds.minX) {
|
||||
tileCoord.x -= 1;
|
||||
} else if (offsetFromOrigin.x >= tileCoordPixelBounds.maxX) {
|
||||
tileCoord.x += 1;
|
||||
}
|
||||
// adjust y to allow for stretched tiles
|
||||
if (offsetFromOrigin.y < tileCoordPixelBounds.minY) {
|
||||
tileCoord.y -= 1;
|
||||
} else if (offsetFromOrigin.y >= tileCoordPixelBounds.maxY) {
|
||||
tileCoord.y += 1;
|
||||
}
|
||||
|
||||
return tileCoord;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} z Z.
|
||||
* @return {ol.TileCoord} Tile coordinate.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileCoordForCoordAndZ = function(coordinate, z) {
|
||||
var resolution = this.getResolution(z);
|
||||
return this.getTileCoordForCoordAndResolution(coordinate, resolution);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {number} Tile resolution.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileCoordResolution = function(tileCoord) {
|
||||
goog.asserts.assert(0 <= tileCoord.z && tileCoord.z < this.numResolutions_);
|
||||
return this.resolutions_[tileCoord.z];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Size} Tile size.
|
||||
*/
|
||||
ol.TileGrid.prototype.getTileSize = function() {
|
||||
return this.tileSize_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {number} Z.
|
||||
*/
|
||||
ol.TileGrid.prototype.getZForResolution = function(resolution) {
|
||||
return ol.array.linearFindNearest(this.resolutions_, resolution);
|
||||
};
|
||||
465
src/ol/tilegrid_test.js
Normal file
465
src/ol/tilegrid_test.js
Normal file
@@ -0,0 +1,465 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileGrid');
|
||||
|
||||
|
||||
var extent;
|
||||
var resolutions;
|
||||
var origin;
|
||||
var origins;
|
||||
var tileSize;
|
||||
|
||||
|
||||
function setUp() {
|
||||
resolutions = [1000, 500, 250, 100];
|
||||
extent = new ol.Extent(0, 0, 100000, 100000);
|
||||
origin = new ol.Coordinate(0, 0);
|
||||
origins = [];
|
||||
tileSize = new ol.Size(100, 100);
|
||||
}
|
||||
|
||||
|
||||
function testCreateValid() {
|
||||
assertNotThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateDuplicateResolutions() {
|
||||
var resolutions = [100, 50, 50, 25, 10];
|
||||
assertThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateOutOfOrderResolutions() {
|
||||
var resolutions = [100, 25, 50, 10];
|
||||
assertThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateOrigins() {
|
||||
var resolutions = [100, 50, 25, 10];
|
||||
var origins = [origin, origin, origin, origin];
|
||||
assertNotThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origins, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateTooFewOrigins() {
|
||||
var resolutions = [100, 50, 25, 10];
|
||||
var origins = [origin, origin, origin];
|
||||
assertThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origins, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testCreateTooManyOrigins() {
|
||||
var resolutions = [100, 50, 25, 10];
|
||||
var origins = [origin, origin, origin, origin, origin];
|
||||
assertThrows(function() {
|
||||
return new ol.TileGrid(resolutions, extent, origins, tileSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testGetTileCoord() {
|
||||
|
||||
origin = new ol.Coordinate(0, 0);
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var tileCoord;
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(0, 0), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(0, 100000), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(10, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(100000, 0), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(10, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(100000, 100000), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(10, tileCoord.x);
|
||||
assertEquals(10, tileCoord.y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testGetTileCoordYSouth() {
|
||||
|
||||
origin = new ol.Coordinate(0, 100000);
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var tileCoord;
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(0, 0), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-10, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(0, 100000), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(100000, 0), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(10, tileCoord.x);
|
||||
assertEquals(-10, tileCoord.y);
|
||||
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndZ(
|
||||
new ol.Coordinate(100000, 100000), 3);
|
||||
assertEquals(3, tileCoord.z);
|
||||
assertEquals(10, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
}
|
||||
|
||||
function testGetTileCoordForCoordAndResolution() {
|
||||
|
||||
var tileSize = new ol.Size(256, 256);
|
||||
var tileGrid = new ol.TileGrid([10], extent, origin, tileSize);
|
||||
|
||||
var coordinate;
|
||||
var tileCoord;
|
||||
|
||||
// gets the first tile at the origin
|
||||
coordinate = new ol.Coordinate(0, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets one tile northwest of the origin
|
||||
coordinate = new ol.Coordinate(-1280, 1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(-1, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets one tile northeast of the origin
|
||||
coordinate = new ol.Coordinate(1280, 1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets one tile southeast of the origin
|
||||
coordinate = new ol.Coordinate(1280, -1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
|
||||
// gets one tile southwest of the origin
|
||||
coordinate = new ol.Coordinate(-1280, -1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(-1, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
|
||||
// gets the tile to the east when on the edge
|
||||
coordinate = new ol.Coordinate(2560, -1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(1, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
|
||||
// gets the tile to the north when on the edge
|
||||
coordinate = new ol.Coordinate(1280, -2560);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
|
||||
// pixels are top aligned to the origin
|
||||
coordinate = new ol.Coordinate(1280, -2559.999);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
|
||||
// pixels are left aligned to the origin
|
||||
coordinate = new ol.Coordinate(2559.999, -1280);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 10);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-1, tileCoord.y);
|
||||
}
|
||||
|
||||
function testGetTileCoordForCoordAndResolutionFractional() {
|
||||
|
||||
var tileSize = new ol.Size(256, 256);
|
||||
var tileGrid = new ol.TileGrid([1 / 3], extent, origin, tileSize);
|
||||
|
||||
var coordinate;
|
||||
var tileCoord;
|
||||
|
||||
// These tests render at a resolution of 1. Because the layer's
|
||||
// closest resolution is 1/3, the images are scaled by 1/3.
|
||||
// In this scenario, every third tile will be one pixel wider when
|
||||
// rendered (0,0 is normal; 1,0 is wider; 0,1 is taller; etc.)
|
||||
|
||||
// gets the first tile at the origin
|
||||
coordinate = new ol.Coordinate(0, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 1,0 tile at 256/3,0
|
||||
coordinate = new ol.Coordinate(256 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(1, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// still gets the 1,0 tile at 512/3,0 - wider tile
|
||||
coordinate = new ol.Coordinate(512 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(1, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 2,0 tile at 513/3,0
|
||||
coordinate = new ol.Coordinate(513 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(2, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 3,0 tile at 768/3,0
|
||||
coordinate = new ol.Coordinate(768 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(3, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 4,0 tile at 1024/3,0
|
||||
coordinate = new ol.Coordinate(1024 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(4, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// still gets the 4,0 tile at 1280/3,0 - wider tile
|
||||
coordinate = new ol.Coordinate(1280 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(4, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 5,0 tile at 1281/3,0
|
||||
coordinate = new ol.Coordinate(1281 / 3, 0);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(5, tileCoord.x);
|
||||
assertEquals(0, tileCoord.y);
|
||||
|
||||
// gets the 0,1 tile at 0,-256/3
|
||||
coordinate = new ol.Coordinate(0, -256 / 3);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-2, tileCoord.y);
|
||||
|
||||
// still gets the 0,1 tile at 0,-512/3 - taller tile
|
||||
coordinate = new ol.Coordinate(0, -512 / 3);
|
||||
tileCoord = tileGrid.getTileCoordForCoordAndResolution(
|
||||
coordinate, 1);
|
||||
assertEquals(0, tileCoord.z);
|
||||
assertEquals(0, tileCoord.x);
|
||||
assertEquals(-2, tileCoord.y);
|
||||
}
|
||||
|
||||
|
||||
function testGetTileCoordCenter() {
|
||||
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var center;
|
||||
|
||||
center = tileGrid.getTileCoordCenter(new ol.TileCoord(0, 0, 0));
|
||||
assertEquals(50000, center.x);
|
||||
assertEquals(50000, center.y);
|
||||
|
||||
center = tileGrid.getTileCoordCenter(new ol.TileCoord(3, 0, 0));
|
||||
assertEquals(5000, center.x);
|
||||
assertEquals(5000, center.y);
|
||||
|
||||
center = tileGrid.getTileCoordCenter(new ol.TileCoord(3, 9, 9));
|
||||
assertEquals(95000, center.x);
|
||||
assertEquals(95000, center.y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function testGetTileCoordExtent() {
|
||||
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var tileCoordExtent;
|
||||
|
||||
tileCoordExtent = tileGrid.getTileCoordExtent(new ol.TileCoord(0, 0, 0));
|
||||
assertEquals(0, tileCoordExtent.minX);
|
||||
assertEquals(0, tileCoordExtent.minY);
|
||||
assertEquals(100000, tileCoordExtent.maxX);
|
||||
assertEquals(100000, tileCoordExtent.maxY);
|
||||
|
||||
tileCoordExtent = tileGrid.getTileCoordExtent(new ol.TileCoord(3, 9, 0));
|
||||
assertEquals(90000, tileCoordExtent.minX);
|
||||
assertEquals(0, tileCoordExtent.minY);
|
||||
assertEquals(100000, tileCoordExtent.maxX);
|
||||
assertEquals(10000, tileCoordExtent.maxY);
|
||||
|
||||
tileCoordExtent = tileGrid.getTileCoordExtent(new ol.TileCoord(3, 0, 9));
|
||||
assertEquals(0, tileCoordExtent.minX);
|
||||
assertEquals(90000, tileCoordExtent.minY);
|
||||
assertEquals(10000, tileCoordExtent.maxX);
|
||||
assertEquals(100000, tileCoordExtent.maxY);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testGetExtentTileBounds() {
|
||||
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var e = new ol.Extent(45000, 5000, 55000, 15000);
|
||||
var tileBounds;
|
||||
|
||||
tileBounds = tileGrid.getTileBoundsForExtentAndZ(e, 0);
|
||||
assertEquals(0, tileBounds.minY);
|
||||
assertEquals(0, tileBounds.minX);
|
||||
assertEquals(0, tileBounds.maxX);
|
||||
assertEquals(0, tileBounds.maxY);
|
||||
|
||||
tileBounds = tileGrid.getTileBoundsForExtentAndZ(e, 1);
|
||||
assertEquals(0, tileBounds.minX);
|
||||
assertEquals(0, tileBounds.minY);
|
||||
assertEquals(1, tileBounds.maxX);
|
||||
assertEquals(0, tileBounds.maxY);
|
||||
|
||||
tileBounds = tileGrid.getTileBoundsForExtentAndZ(e, 2);
|
||||
assertEquals(1, tileBounds.minX);
|
||||
assertEquals(0, tileBounds.minY);
|
||||
assertEquals(2, tileBounds.maxX);
|
||||
assertEquals(0, tileBounds.maxY);
|
||||
|
||||
tileBounds = tileGrid.getTileBoundsForExtentAndZ(e, 3);
|
||||
assertEquals(4, tileBounds.minX);
|
||||
assertEquals(0, tileBounds.minY);
|
||||
assertEquals(5, tileBounds.maxX);
|
||||
assertEquals(1, tileBounds.maxY);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testForEachTileCoordParent() {
|
||||
|
||||
var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
var zs = [], tileBoundss = [];
|
||||
|
||||
tileGrid.forEachTileCoordParentTileBounds(
|
||||
new ol.TileCoord(3, 7, 3),
|
||||
function(z, tileBounds) {
|
||||
zs.push(z);
|
||||
tileBoundss.push(tileBounds);
|
||||
return false;
|
||||
});
|
||||
|
||||
assertEquals(3, zs.length);
|
||||
assertEquals(3, tileBoundss.length);
|
||||
|
||||
assertEquals(2, zs[0]);
|
||||
assertEquals(2, tileBoundss[0].minX);
|
||||
assertEquals(1, tileBoundss[0].minY);
|
||||
assertEquals(3, tileBoundss[0].maxX);
|
||||
assertEquals(1, tileBoundss[0].maxY);
|
||||
|
||||
assertEquals(1, zs[1]);
|
||||
assertEquals(1, tileBoundss[1].minX);
|
||||
assertEquals(0, tileBoundss[1].minY);
|
||||
assertEquals(1, tileBoundss[1].maxX);
|
||||
assertEquals(0, tileBoundss[1].maxY);
|
||||
|
||||
assertEquals(0, zs[2]);
|
||||
assertEquals(0, tileBoundss[2].minX);
|
||||
assertEquals(0, tileBoundss[2].minY);
|
||||
assertEquals(0, tileBoundss[2].maxX);
|
||||
assertEquals(0, tileBoundss[2].maxY);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testGetZForResolutionExact() {
|
||||
|
||||
var tileGrid =
|
||||
new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
|
||||
assertEquals(0, tileGrid.getZForResolution(1000));
|
||||
assertEquals(1, tileGrid.getZForResolution(500));
|
||||
assertEquals(2, tileGrid.getZForResolution(250));
|
||||
assertEquals(3, tileGrid.getZForResolution(100));
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testGetZForResolutionApproximate() {
|
||||
|
||||
var tileGrid =
|
||||
new ol.TileGrid(resolutions, extent, origin, tileSize);
|
||||
|
||||
assertEquals(0, tileGrid.getZForResolution(2000));
|
||||
assertEquals(0, tileGrid.getZForResolution(1000));
|
||||
assertEquals(0, tileGrid.getZForResolution(900));
|
||||
assertEquals(1, tileGrid.getZForResolution(750));
|
||||
assertEquals(1, tileGrid.getZForResolution(625));
|
||||
assertEquals(1, tileGrid.getZForResolution(500));
|
||||
assertEquals(1, tileGrid.getZForResolution(475));
|
||||
assertEquals(2, tileGrid.getZForResolution(375));
|
||||
assertEquals(2, tileGrid.getZForResolution(250));
|
||||
assertEquals(2, tileGrid.getZForResolution(200));
|
||||
assertEquals(3, tileGrid.getZForResolution(125));
|
||||
assertEquals(3, tileGrid.getZForResolution(100));
|
||||
assertEquals(3, tileGrid.getZForResolution(50));
|
||||
|
||||
}
|
||||
26
src/ol/tilelayer.js
Normal file
26
src/ol/tilelayer.js
Normal file
@@ -0,0 +1,26 @@
|
||||
goog.provide('ol.TileLayer');
|
||||
|
||||
goog.require('ol.Layer');
|
||||
goog.require('ol.TileStore');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Layer}
|
||||
* @param {ol.TileStore} tileStore Tile store.
|
||||
* @param {Object.<string, *>=} opt_values Values.
|
||||
*/
|
||||
ol.TileLayer = function(tileStore, opt_values) {
|
||||
goog.base(this, tileStore, opt_values);
|
||||
};
|
||||
goog.inherits(ol.TileLayer, ol.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.TileStore} Store.
|
||||
*/
|
||||
ol.TileLayer.prototype.getStore = function() {
|
||||
return /** @type {ol.TileStore} */ goog.base(this, 'getStore');
|
||||
};
|
||||
101
src/ol/tilestore.js
Normal file
101
src/ol/tilestore.js
Normal file
@@ -0,0 +1,101 @@
|
||||
goog.provide('ol.TileStore');
|
||||
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Store');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileGrid');
|
||||
goog.require('ol.TileUrlFunctionType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Store}
|
||||
* @param {ol.Projection} projection Projection.
|
||||
* @param {ol.TileGrid} tileGrid Tile grid.
|
||||
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @param {Array.<string>=} opt_attributions Attributions.
|
||||
* @param {?string=} opt_crossOrigin Cross origin.
|
||||
*/
|
||||
ol.TileStore = function(projection, tileGrid, tileUrlFunction, opt_extent,
|
||||
opt_attributions, opt_crossOrigin) {
|
||||
|
||||
goog.base(this, projection, opt_extent, opt_attributions);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.TileGrid}
|
||||
*/
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.TileUrlFunctionType}
|
||||
*/
|
||||
this.tileUrlFunction = tileUrlFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ = opt_crossOrigin || 'anonymous';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.Tile>}
|
||||
* FIXME will need to expire elements from this cache
|
||||
* FIXME see elemoine's work with goog.structs.LinkedMap
|
||||
*/
|
||||
this.tileCache_ = {};
|
||||
|
||||
};
|
||||
goog.inherits(ol.TileStore, ol.Store);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.TileStore.prototype.getResolutions = function() {
|
||||
return this.tileGrid.getResolutions();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {ol.Tile} Tile.
|
||||
*/
|
||||
ol.TileStore.prototype.getTile = function(tileCoord) {
|
||||
var key = tileCoord.toString();
|
||||
if (goog.object.containsKey(this.tileCache_, key)) {
|
||||
return this.tileCache_[key];
|
||||
} else {
|
||||
var tileUrl = this.getTileCoordUrl(tileCoord);
|
||||
var tile;
|
||||
if (goog.isDef(tileUrl)) {
|
||||
tile = new ol.Tile(tileCoord, tileUrl, this.crossOrigin_);
|
||||
} else {
|
||||
tile = null;
|
||||
}
|
||||
this.tileCache_[key] = tile;
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
ol.TileStore.prototype.getTileCoordUrl = function(tileCoord) {
|
||||
return this.tileUrlFunction(tileCoord);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.TileGrid} Tile grid.
|
||||
*/
|
||||
ol.TileStore.prototype.getTileGrid = function() {
|
||||
return this.tileGrid;
|
||||
};
|
||||
94
src/ol/tileurlfunction.js
Normal file
94
src/ol/tileurlfunction.js
Normal file
@@ -0,0 +1,94 @@
|
||||
goog.provide('ol.TileUrlFunction');
|
||||
goog.provide('ol.TileUrlFunctionType');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.TileCoord');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(ol.TileCoord): (string|undefined)}
|
||||
*/
|
||||
ol.TileUrlFunctionType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} template Template.
|
||||
* @return {ol.TileUrlFunctionType} Tile URL function.
|
||||
*/
|
||||
ol.TileUrlFunction.createFromTemplate = function(template) {
|
||||
var match =
|
||||
/\{(\d)-(\d)\}/.exec(template) || /\{([a-z])-([a-z])\}/.exec(template);
|
||||
if (match) {
|
||||
var templates = [];
|
||||
var startCharCode = match[1].charCodeAt(0);
|
||||
var stopCharCode = match[2].charCodeAt(0);
|
||||
var charCode;
|
||||
for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) {
|
||||
templates.push(template.replace(match[0], String.fromCharCode(charCode)));
|
||||
}
|
||||
return ol.TileUrlFunction.createFromTemplates(templates);
|
||||
} else {
|
||||
return function(tileCoord) {
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
return template.replace('{z}', tileCoord.z)
|
||||
.replace('{x}', tileCoord.x)
|
||||
.replace('{y}', tileCoord.y);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<string>} templates Templates.
|
||||
* @return {ol.TileUrlFunctionType} Tile URL function.
|
||||
*/
|
||||
ol.TileUrlFunction.createFromTemplates = function(templates) {
|
||||
return ol.TileUrlFunction.createFromTileUrlFunctions(
|
||||
goog.array.map(templates, ol.TileUrlFunction.createFromTemplate));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.TileUrlFunctionType>} tileUrlFunctions Tile URL Functions.
|
||||
* @return {ol.TileUrlFunctionType} Tile URL function.
|
||||
*/
|
||||
ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
|
||||
return function(tileCoord) {
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
var index = goog.math.modulo(tileCoord.hash(), tileUrlFunctions.length);
|
||||
return tileUrlFunctions[index](tileCoord);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord) {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(ol.TileCoord): ol.TileCoord} transformFn
|
||||
* Transform.function.
|
||||
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
|
||||
* @return {ol.TileUrlFunctionType} Tile URL function.
|
||||
*/
|
||||
ol.TileUrlFunction.withTileCoordTransform =
|
||||
function(transformFn, tileUrlFunction) {
|
||||
return function(tileCoord) {
|
||||
if (goog.isNull(tileCoord)) {
|
||||
return undefined;
|
||||
} else {
|
||||
return tileUrlFunction(transformFn(tileCoord));
|
||||
}
|
||||
};
|
||||
};
|
||||
33
src/ol/tileurlfunction_test.js
Normal file
33
src/ol/tileurlfunction_test.js
Normal file
@@ -0,0 +1,33 @@
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
|
||||
|
||||
function testCreateFromTemplate() {
|
||||
var tileUrl = ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}');
|
||||
assertEquals('3/2/1', tileUrl(new ol.TileCoord(3, 2, 1)));
|
||||
assertUndefined(tileUrl(null));
|
||||
}
|
||||
|
||||
|
||||
function testWithTileCoordTransform() {
|
||||
var tileUrl = ol.TileUrlFunction.withTileCoordTransform(
|
||||
function(tileCoord) {
|
||||
return new ol.TileCoord(tileCoord.z, tileCoord.x, -tileCoord.y);
|
||||
},
|
||||
ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}'));
|
||||
assertEquals('3/2/1', tileUrl(new ol.TileCoord(3, 2, -1)));
|
||||
assertUndefined(tileUrl(null));
|
||||
}
|
||||
|
||||
|
||||
function testCreateFromTileUrlFunctions() {
|
||||
var tileUrl = ol.TileUrlFunction.createFromTileUrlFunctions([
|
||||
ol.TileUrlFunction.createFromTemplate('a'),
|
||||
ol.TileUrlFunction.createFromTemplate('b')
|
||||
]);
|
||||
var tileUrl1 = tileUrl(new ol.TileCoord(1, 0, 0));
|
||||
var tileUrl2 = tileUrl(new ol.TileCoord(1, 0, 1));
|
||||
assertTrue(tileUrl1 != tileUrl2);
|
||||
assertUndefined(tileUrl(null));
|
||||
}
|
||||
9
src/ol/transformfunction.js
Normal file
9
src/ol/transformfunction.js
Normal file
@@ -0,0 +1,9 @@
|
||||
goog.provide('ol.TransformFunction');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(ol.Coordinate): ol.Coordinate}
|
||||
*/
|
||||
ol.TransformFunction;
|
||||
10
src/ol/webgl/webgl.js
Normal file
10
src/ol/webgl/webgl.js
Normal file
@@ -0,0 +1,10 @@
|
||||
goog.provide('ol.webgl.WebGLContextEventType');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.webgl.WebGLContextEventType = {
|
||||
LOST: 'webglcontextlost',
|
||||
RESTORED: 'webglcontextrestored'
|
||||
};
|
||||
Reference in New Issue
Block a user