Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
goog.provide('ol.animation');
|
||||
|
||||
goog.require('ol.PreRenderFunction');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.coordinate');
|
||||
goog.require('ol.easing');
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.animation.BounceOptions} options Bounce options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
* @api
|
||||
*/
|
||||
ol.animation.bounce = function(options) {
|
||||
var resolution = options.resolution;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.upAndDown;
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
*/
|
||||
function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = easing((frameState.time - start) / duration);
|
||||
var deltaResolution = resolution - frameState.viewState.resolution;
|
||||
frameState.animate = true;
|
||||
frameState.viewState.resolution += delta * deltaResolution;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.animation.PanOptions} options Pan options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
* @api
|
||||
*/
|
||||
ol.animation.pan = function(options) {
|
||||
var source = options.source;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var sourceX = source[0];
|
||||
var sourceY = source[1];
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.inAndOut;
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
*/
|
||||
function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = 1 - easing((frameState.time - start) / duration);
|
||||
var deltaX = sourceX - frameState.viewState.center[0];
|
||||
var deltaY = sourceY - frameState.viewState.center[1];
|
||||
frameState.animate = true;
|
||||
frameState.viewState.center[0] += delta * deltaX;
|
||||
frameState.viewState.center[1] += delta * deltaY;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.animation.RotateOptions} options Rotate options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
* @api
|
||||
*/
|
||||
ol.animation.rotate = function(options) {
|
||||
var sourceRotation = goog.isDef(options.rotation) ? options.rotation : 0;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.inAndOut;
|
||||
var anchor = goog.isDef(options.anchor) ?
|
||||
options.anchor : null;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
*/
|
||||
function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = 1 - easing((frameState.time - start) / duration);
|
||||
var deltaRotation =
|
||||
(sourceRotation - frameState.viewState.rotation) * delta;
|
||||
frameState.animate = true;
|
||||
frameState.viewState.rotation += deltaRotation;
|
||||
if (!goog.isNull(anchor)) {
|
||||
var center = frameState.viewState.center;
|
||||
ol.coordinate.sub(center, anchor);
|
||||
ol.coordinate.rotate(center, deltaRotation);
|
||||
ol.coordinate.add(center, anchor);
|
||||
}
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.animation.ZoomOptions} options Zoom options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
* @api
|
||||
*/
|
||||
ol.animation.zoom = function(options) {
|
||||
var sourceResolution = options.resolution;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.inAndOut;
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
*/
|
||||
function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = 1 - easing((frameState.time - start) / duration);
|
||||
var deltaResolution =
|
||||
sourceResolution - frameState.viewState.resolution;
|
||||
frameState.animate = true;
|
||||
frameState.viewState.resolution += delta * deltaResolution;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* The animation static methods are designed to be used with the
|
||||
* {@link ol.Map#beforeRender} method. For example:
|
||||
*
|
||||
* var map = new ol.Map({ ... });
|
||||
* var zoom = ol.animation.zoom({
|
||||
* resolution: map.getView().getResolution()
|
||||
* });
|
||||
* map.beforeRender(zoom);
|
||||
* map.getView().setResolution(map.getView().getResolution() * 2);
|
||||
*
|
||||
* @namespace ol.animation
|
||||
*/
|
||||
@@ -0,0 +1,104 @@
|
||||
goog.provide('ol.array');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* @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,
|
||||
/**
|
||||
* @param {number} a A.
|
||||
* @param {number} b B.
|
||||
* @return {number} b minus a.
|
||||
*/
|
||||
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.
|
||||
* @param {number} direction 0 means return the nearest, > 0
|
||||
* means return the largest nearest, < 0 means return the
|
||||
* smallest nearest.
|
||||
* @return {number} Index.
|
||||
*/
|
||||
ol.array.linearFindNearest = function(arr, target, direction) {
|
||||
var n = arr.length;
|
||||
if (arr[0] <= target) {
|
||||
return 0;
|
||||
} else if (target <= arr[n - 1]) {
|
||||
return n - 1;
|
||||
} else {
|
||||
var i;
|
||||
if (direction > 0) {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] < target) {
|
||||
return i - 1;
|
||||
}
|
||||
}
|
||||
} else if (direction < 0) {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] <= target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We should never get here, but the compiler complains
|
||||
// if it finds a path for which no number is returned.
|
||||
goog.asserts.fail();
|
||||
return n - 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<*>} arr Array.
|
||||
* @param {number} begin Begin index.
|
||||
* @param {number} end End index.
|
||||
*/
|
||||
ol.array.reverseSubArray = function(arr, begin, end) {
|
||||
goog.asserts.assert(begin >= 0);
|
||||
goog.asserts.assert(end < arr.length);
|
||||
while (begin < end) {
|
||||
var tmp = arr[begin];
|
||||
arr[begin] = arr[end];
|
||||
arr[end] = tmp;
|
||||
++begin;
|
||||
--end;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
goog.provide('ol.Attribution');
|
||||
|
||||
goog.require('ol.TileRange');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* An attribution for a layer source.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* source: new ol.source.OSM({
|
||||
* attributions: [
|
||||
* new ol.Attribution({
|
||||
* html: 'All maps © ' +
|
||||
* '<a href="http://www.opencyclemap.org/">OpenCycleMap</a>'
|
||||
* }),
|
||||
* ol.source.OSM.ATTRIBUTION
|
||||
* ],
|
||||
* ..
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.AttributionOptions} options Attribution options.
|
||||
* @struct
|
||||
* @api stable
|
||||
*/
|
||||
ol.Attribution = function(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.html_ = options.html;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, Array.<ol.TileRange>>}
|
||||
*/
|
||||
this.tileRanges_ = goog.isDef(options.tileRanges) ?
|
||||
options.tileRanges : null;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} HTML.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Attribution.prototype.getHTML = function() {
|
||||
return this.html_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, ol.TileRange>} tileRanges Tile ranges.
|
||||
* @return {boolean} Intersects any tile range.
|
||||
*/
|
||||
ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges) {
|
||||
if (goog.isNull(this.tileRanges_)) {
|
||||
return true;
|
||||
}
|
||||
var i, ii, tileRange, z;
|
||||
for (z in tileRanges) {
|
||||
if (!(z in this.tileRanges_)) {
|
||||
continue;
|
||||
}
|
||||
tileRange = tileRanges[z];
|
||||
for (i = 0, ii = this.tileRanges_[z].length; i < ii; ++i) {
|
||||
if (this.tileRanges_[z][i].intersects(tileRange)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
// FIXME Test on Internet Explorer with VBArray
|
||||
|
||||
goog.provide('ol.binary.Buffer');
|
||||
goog.provide('ol.binary.IReader');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.userAgent');
|
||||
goog.require('ol.has');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ArrayBuffer|string} data Data.
|
||||
*/
|
||||
ol.binary.Buffer = function(data) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ArrayBuffer|string}
|
||||
*/
|
||||
this.data_ = data;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.binary.IReader} Reader.
|
||||
*/
|
||||
ol.binary.Buffer.prototype.getReader = function() {
|
||||
var data = this.data_;
|
||||
if (ol.has.ARRAY_BUFFER) {
|
||||
var arrayBuffer;
|
||||
if (data instanceof ArrayBuffer) {
|
||||
arrayBuffer = data;
|
||||
} else if (goog.isString(data)) {
|
||||
// FIXME check what happens with Unicode
|
||||
arrayBuffer = new ArrayBuffer(data.length);
|
||||
var uint8View = new Uint8Array(arrayBuffer);
|
||||
var i, ii;
|
||||
for (i = 0, ii = data.length; i < ii; ++i) {
|
||||
uint8View[i] = data.charCodeAt(i);
|
||||
}
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
return new ol.binary.ArrayBufferReader(arrayBuffer);
|
||||
} else {
|
||||
goog.asserts.assert(goog.isString(data));
|
||||
goog.asserts.assert(
|
||||
goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10.0'));
|
||||
return new ol.binary.ArrayReader(new VBArray(data).toArray());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
ol.binary.IReader = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} At EOF.
|
||||
*/
|
||||
ol.binary.IReader.prototype.atEOF = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Byte.
|
||||
*/
|
||||
ol.binary.IReader.prototype.readByte = function() {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ArrayBuffer} arrayBuffer Array buffer.
|
||||
* @implements {ol.binary.IReader}
|
||||
*/
|
||||
ol.binary.ArrayBufferReader = function(arrayBuffer) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Uint8Array}
|
||||
*/
|
||||
this.uint8View_ = new Uint8Array(arrayBuffer);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.length_ = this.uint8View_.length;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.offset_ = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.binary.ArrayBufferReader.prototype.atEOF = function() {
|
||||
return this.offset_ == this.length_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.binary.ArrayBufferReader.prototype.readByte = function() {
|
||||
if (this.offset_ < this.length_) {
|
||||
return this.uint8View_[this.offset_++];
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {ol.binary.IReader}
|
||||
* @param {Array.<number>} array Array.
|
||||
*/
|
||||
ol.binary.ArrayReader = function(array) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.array_ = array;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.length_ = array.length;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.offset_ = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.binary.ArrayReader.prototype.atEOF = function() {
|
||||
return this.offset_ == this.length_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.binary.ArrayReader.prototype.readByte = function() {
|
||||
if (this.offset_ < this.length_) {
|
||||
return this.array_[this.offset_++];
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
goog.provide('ol.CanvasFunctionType');
|
||||
|
||||
|
||||
/**
|
||||
* A function returning the canvas element (`{HTMLCanvasElement}`)
|
||||
* used by the source as an image. The arguments passed to the function are:
|
||||
* {@link ol.Extent} the image extent, `{number}` the image resolution,
|
||||
* `{number}` the device pixel ratio, {@link ol.Size} the image size, and
|
||||
* {@link ol.proj.Projection} the image projection. The canvas returned by
|
||||
* this function is cached by the source. The this keyword inside the function
|
||||
* references the {@link ol.source.ImageCanvas}.
|
||||
*
|
||||
* @typedef {function(this:ol.source.ImageCanvas, ol.Extent, number,
|
||||
* number, ol.Size, ol.proj.Projection): HTMLCanvasElement}
|
||||
* @api
|
||||
*/
|
||||
ol.CanvasFunctionType;
|
||||
@@ -0,0 +1,42 @@
|
||||
goog.provide('ol.CenterConstraint');
|
||||
goog.provide('ol.CenterConstraintType');
|
||||
|
||||
goog.require('goog.math');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function((ol.Coordinate|undefined)): (ol.Coordinate|undefined)}
|
||||
*/
|
||||
ol.CenterConstraintType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.CenterConstraintType}
|
||||
*/
|
||||
ol.CenterConstraint.createExtent = function(extent) {
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} center Center.
|
||||
* @return {ol.Coordinate|undefined} Center.
|
||||
*/
|
||||
function(center) {
|
||||
if (goog.isDef(center)) {
|
||||
return [
|
||||
goog.math.clamp(center[0], extent[0], extent[2]),
|
||||
goog.math.clamp(center[1], extent[1], extent[3])
|
||||
];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} center Center.
|
||||
* @return {ol.Coordinate|undefined} Center.
|
||||
*/
|
||||
ol.CenterConstraint.none = function(center) {
|
||||
return center;
|
||||
};
|
||||
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* 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.events.Event');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.CollectionEventType = {
|
||||
/**
|
||||
* Triggered when an item is added to the collection.
|
||||
* @event ol.CollectionEvent#add
|
||||
* @api stable
|
||||
*/
|
||||
ADD: 'add',
|
||||
/**
|
||||
* Triggered when an item is removed from the collection.
|
||||
* @event ol.CollectionEvent#remove
|
||||
* @api stable
|
||||
*/
|
||||
REMOVE: 'remove'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted by {@link ol.Collection} instances are instances of this
|
||||
* type.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @implements {oli.CollectionEvent}
|
||||
* @param {ol.CollectionEventType} type Type.
|
||||
* @param {*=} opt_element Element.
|
||||
* @param {Object=} opt_target Target.
|
||||
*/
|
||||
ol.CollectionEvent = function(type, opt_element, opt_target) {
|
||||
|
||||
goog.base(this, type, opt_target);
|
||||
|
||||
/**
|
||||
* The element that is added to or removed from the collection.
|
||||
* @type {*}
|
||||
* @api stable
|
||||
*/
|
||||
this.element = opt_element;
|
||||
|
||||
};
|
||||
goog.inherits(ol.CollectionEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.CollectionProperty = {
|
||||
LENGTH: 'length'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* An expanded version of standard JS Array, adding convenience methods for
|
||||
* manipulation. Add and remove changes to the Collection trigger a Collection
|
||||
* event. Note that this does not cover changes to the objects _within_ the
|
||||
* Collection; they trigger events on the appropriate object, not on the
|
||||
* Collection as a whole.
|
||||
*
|
||||
* Because a Collection is itself an {@link ol.Object}, it can be bound to any
|
||||
* other Object or Collection such that a change in one will automatically be
|
||||
* reflected in the other.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires ol.CollectionEvent
|
||||
* @param {Array.<T>=} opt_array Array.
|
||||
* @template T
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection = function(opt_array) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<T>}
|
||||
*/
|
||||
this.array_ = goog.isDef(opt_array) ? opt_array : [];
|
||||
|
||||
this.updateLength_();
|
||||
|
||||
};
|
||||
goog.inherits(ol.Collection, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* Remove all elements from the collection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.clear = function() {
|
||||
while (this.getLength() > 0) {
|
||||
this.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<T>} arr Array.
|
||||
* @return {ol.Collection.<T>} This collection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.extend = function(arr) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = arr.length; i < ii; ++i) {
|
||||
this.push(arr[i]);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over each element, calling the provided callback.
|
||||
* @param {function(this: S, T, number, Array.<T>): *} f The function to call
|
||||
* for every element. This function takes 3 arguments (the element, the
|
||||
* index and the array). The return value is ignored.
|
||||
* @param {S=} opt_this The object to use as `this` in `f`.
|
||||
* @template S
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.forEach = function(f, opt_this) {
|
||||
goog.array.forEach(this.array_, f, opt_this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a reference to the underlying Array object. Warning: if the array
|
||||
* is mutated, no events will be dispatched by the collection, and the
|
||||
* collection's "length" property won't be in sync with the actual length
|
||||
* of the array.
|
||||
* @return {Array.<T>} Array.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.getArray = function() {
|
||||
return this.array_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @return {T} Element.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.item = function(index) {
|
||||
return this.array_[index];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the length of this collection.
|
||||
* @return {number} The length of the array.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.getLength = function() {
|
||||
return /** @type {number} */ (this.get(ol.CollectionProperty.LENGTH));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Insert an element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @param {T} elem Element.
|
||||
* @api stable
|
||||
*/
|
||||
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, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the last element of the collection and return it.
|
||||
* Return `undefined` if the collection is empty.
|
||||
* @return {T|undefined} Element.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.pop = function() {
|
||||
return this.removeAt(this.getLength() - 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Insert the provided element at the end of the collection.
|
||||
* @param {T} elem Element.
|
||||
* @return {number} Length.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.push = function(elem) {
|
||||
var n = this.array_.length;
|
||||
this.insertAt(n, elem);
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of elem from the collection.
|
||||
* @param {T} elem Element.
|
||||
* @return {T|undefined} The removed element or undefined if elem was not found.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.remove = function(elem) {
|
||||
var arr = this.array_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = arr.length; i < ii; ++i) {
|
||||
if (arr[i] === elem) {
|
||||
return this.removeAt(i);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the element at the provided index and return it.
|
||||
* Return `undefined` if the collection does not contain this index.
|
||||
* @param {number} index Index.
|
||||
* @return {T|undefined} Value.
|
||||
* @api stable
|
||||
*/
|
||||
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, this));
|
||||
return prev;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @param {T} elem Element.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Collection.prototype.setAt = function(index, elem) {
|
||||
var n = this.getLength();
|
||||
if (index < n) {
|
||||
var prev = this.array_[index];
|
||||
this.array_[index] = elem;
|
||||
this.dispatchEvent(
|
||||
new ol.CollectionEvent(ol.CollectionEventType.REMOVE, prev, this));
|
||||
this.dispatchEvent(
|
||||
new ol.CollectionEvent(ol.CollectionEventType.ADD, elem, 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);
|
||||
};
|
||||
@@ -0,0 +1,332 @@
|
||||
// We can't use goog.color or goog.color.alpha because they interally use a hex
|
||||
// string representation that encodes each channel in a single byte. This
|
||||
// causes occasional loss of precision and rounding errors, especially in the
|
||||
// alpha channel.
|
||||
|
||||
goog.provide('ol.color');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.color');
|
||||
goog.require('goog.color.names');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol');
|
||||
|
||||
|
||||
/**
|
||||
* A color represented as a short array [red, green, blue, alpha].
|
||||
* red, green, and blue should be integers in the range 0..255 inclusive.
|
||||
* alpha should be a float in the range 0..1 inclusive.
|
||||
* @typedef {Array.<number>}
|
||||
* @api
|
||||
*/
|
||||
ol.Color;
|
||||
|
||||
|
||||
/**
|
||||
* This RegExp matches # followed by 3 or 6 hex digits.
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.color.hexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @see goog.color.rgbColorRe_
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.color.rgbColorRe_ =
|
||||
/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @see goog.color.alpha.rgbaColorRe_
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.color.rgbaColorRe_ =
|
||||
/^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} dst Destination.
|
||||
* @param {ol.Color} src Source.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.blend = function(dst, src, opt_color) {
|
||||
// http://en.wikipedia.org/wiki/Alpha_compositing
|
||||
// FIXME do we need to scale by 255?
|
||||
var out = goog.isDef(opt_color) ? opt_color : [];
|
||||
var dstA = dst[3];
|
||||
var srcA = dst[3];
|
||||
if (dstA == 1) {
|
||||
out[0] = (src[0] * srcA + dst[0] * (1 - srcA) + 0.5) | 0;
|
||||
out[1] = (src[1] * srcA + dst[1] * (1 - srcA) + 0.5) | 0;
|
||||
out[2] = (src[2] * srcA + dst[2] * (1 - srcA) + 0.5) | 0;
|
||||
out[4] = 1;
|
||||
} else if (srcA === 0) {
|
||||
out[0] = dst[0];
|
||||
out[1] = dst[1];
|
||||
out[2] = dst[2];
|
||||
out[3] = dstA;
|
||||
} else {
|
||||
var outA = srcA + dstA * (1 - srcA);
|
||||
if (outA === 0) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
} else {
|
||||
out[0] = ((src[0] * srcA + dst[0] * dstA * (1 - srcA)) / outA + 0.5) | 0;
|
||||
out[1] = ((src[1] * srcA + dst[1] * dstA * (1 - srcA)) / outA + 0.5) | 0;
|
||||
out[2] = ((src[2] * srcA + dst[2] * dstA * (1 - srcA)) / outA + 0.5) | 0;
|
||||
out[3] = outA;
|
||||
}
|
||||
}
|
||||
goog.asserts.assert(ol.color.isValid(out));
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the color as an array. This function maintains a cache of calculated
|
||||
* arrays which means the result should not be modified.
|
||||
* @param {ol.Color|string} color Color.
|
||||
* @return {ol.Color} Color.
|
||||
* @api
|
||||
*/
|
||||
ol.color.asArray = function(color) {
|
||||
if (goog.isArray(color)) {
|
||||
return color;
|
||||
} else {
|
||||
goog.asserts.assert(goog.isString(color));
|
||||
return ol.color.fromString(color);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the color as an rgba string.
|
||||
* @param {ol.Color|string} color Color.
|
||||
* @return {string} Rgba string.
|
||||
* @api
|
||||
*/
|
||||
ol.color.asString = function(color) {
|
||||
if (goog.isString(color)) {
|
||||
return color;
|
||||
} else {
|
||||
goog.asserts.assert(goog.isArray(color));
|
||||
return ol.color.toString(color);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color1 Color1.
|
||||
* @param {ol.Color} color2 Color2.
|
||||
* @return {boolean} Equals.
|
||||
*/
|
||||
ol.color.equals = function(color1, color2) {
|
||||
return color1 === color2 || (
|
||||
color1[0] == color2[0] && color1[1] == color2[1] &&
|
||||
color1[2] == color2[2] && color1[3] == color2[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.fromString = (
|
||||
/**
|
||||
* @return {function(string): ol.Color}
|
||||
*/
|
||||
function() {
|
||||
|
||||
// We maintain a small cache of parsed strings. To provide cheap LRU-like
|
||||
// semantics, whenever the cache grows too large we simply delete an
|
||||
// arbitrary 25% of the entries.
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
var MAX_CACHE_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* @type {Object.<string, ol.Color>}
|
||||
*/
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
var cacheSize = 0;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
function(s) {
|
||||
var color;
|
||||
if (cache.hasOwnProperty(s)) {
|
||||
color = cache[s];
|
||||
} else {
|
||||
if (cacheSize >= MAX_CACHE_SIZE) {
|
||||
var i = 0;
|
||||
var key;
|
||||
for (key in cache) {
|
||||
if ((i++ & 3) === 0) {
|
||||
delete cache[key];
|
||||
--cacheSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
color = ol.color.fromStringInternal_(s);
|
||||
cache[s] = color;
|
||||
++cacheSize;
|
||||
}
|
||||
return color;
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @private
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.fromStringInternal_ = function(s) {
|
||||
|
||||
var isHex = false;
|
||||
if (ol.ENABLE_NAMED_COLORS && goog.color.names.hasOwnProperty(s)) {
|
||||
// goog.color.names does not have a type declaration, so add a typecast
|
||||
s = /** @type {string} */ (goog.color.names[s]);
|
||||
isHex = true;
|
||||
}
|
||||
|
||||
var r, g, b, a, color, match;
|
||||
if (isHex || (match = ol.color.hexColorRe_.exec(s))) { // hex
|
||||
var n = s.length - 1; // number of hex digits
|
||||
goog.asserts.assert(n == 3 || n == 6);
|
||||
var d = n == 3 ? 1 : 2; // number of digits per channel
|
||||
r = parseInt(s.substr(1 + 0 * d, d), 16);
|
||||
g = parseInt(s.substr(1 + 1 * d, d), 16);
|
||||
b = parseInt(s.substr(1 + 2 * d, d), 16);
|
||||
if (d == 1) {
|
||||
r = (r << 4) + r;
|
||||
g = (g << 4) + g;
|
||||
b = (b << 4) + b;
|
||||
}
|
||||
a = 1;
|
||||
color = [r, g, b, a];
|
||||
goog.asserts.assert(ol.color.isValid(color));
|
||||
return color;
|
||||
} else if ((match = ol.color.rgbaColorRe_.exec(s))) { // rgba()
|
||||
r = Number(match[1]);
|
||||
g = Number(match[2]);
|
||||
b = Number(match[3]);
|
||||
a = Number(match[4]);
|
||||
color = [r, g, b, a];
|
||||
return ol.color.normalize(color, color);
|
||||
} else if ((match = ol.color.rgbColorRe_.exec(s))) { // rgb()
|
||||
r = Number(match[1]);
|
||||
g = Number(match[2]);
|
||||
b = Number(match[3]);
|
||||
color = [r, g, b, 1];
|
||||
return ol.color.normalize(color, color);
|
||||
} else {
|
||||
goog.asserts.fail(s + ' is not a valid color');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @return {boolean} Is valid.
|
||||
*/
|
||||
ol.color.isValid = function(color) {
|
||||
return 0 <= color[0] && color[0] < 256 &&
|
||||
0 <= color[1] && color[1] < 256 &&
|
||||
0 <= color[2] && color[2] < 256 &&
|
||||
0 <= color[3] && color[3] <= 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Clamped color.
|
||||
*/
|
||||
ol.color.normalize = function(color, opt_color) {
|
||||
var result = goog.isDef(opt_color) ? opt_color : [];
|
||||
result[0] = goog.math.clamp((color[0] + 0.5) | 0, 0, 255);
|
||||
result[1] = goog.math.clamp((color[1] + 0.5) | 0, 0, 255);
|
||||
result[2] = goog.math.clamp((color[2] + 0.5) | 0, 0, 255);
|
||||
result[3] = goog.math.clamp(color[3], 0, 1);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.color.toString = function(color) {
|
||||
var r = color[0];
|
||||
if (r != (r | 0)) {
|
||||
r = (r + 0.5) | 0;
|
||||
}
|
||||
var g = color[1];
|
||||
if (g != (g | 0)) {
|
||||
g = (g + 0.5) | 0;
|
||||
}
|
||||
var b = color[2];
|
||||
if (b != (b | 0)) {
|
||||
b = (b + 0.5) | 0;
|
||||
}
|
||||
var a = color[3];
|
||||
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!ol.Color} color Color.
|
||||
* @param {goog.vec.Mat4.Number} transform Transform.
|
||||
* @param {!ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Transformed color.
|
||||
*/
|
||||
ol.color.transform = function(color, transform, opt_color) {
|
||||
var result = goog.isDef(opt_color) ? opt_color : [];
|
||||
result = goog.vec.Mat4.multVec3(transform, color, result);
|
||||
goog.asserts.assert(goog.isArray(result));
|
||||
result[3] = color[3];
|
||||
return ol.color.normalize(result, result);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color|string} color1 Color2.
|
||||
* @param {ol.Color|string} color2 Color2.
|
||||
* @return {boolean} Equals.
|
||||
*/
|
||||
ol.color.stringOrColorEquals = function(color1, color2) {
|
||||
if (color1 === color2 || color1 == color2) {
|
||||
return true;
|
||||
}
|
||||
if (goog.isString(color1)) {
|
||||
color1 = ol.color.fromString(color1);
|
||||
}
|
||||
if (goog.isString(color2)) {
|
||||
color2 = ol.color.fromString(color2);
|
||||
}
|
||||
return ol.color.equals(color1, color2);
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Colors can be defined as a {@link ol.Color} array, or as strings in
|
||||
* `rgb(r,g,b)` or `rgba(r,g,b,a)` format, or in hex `#rrggbb` or `#rgb` format.
|
||||
* Color names, like 'red', 'blue' or 'green', may also be used with the
|
||||
* Canvas renderer.
|
||||
*
|
||||
* @namespace ol.color
|
||||
*/
|
||||
@@ -0,0 +1,205 @@
|
||||
goog.provide('ol.color.Matrix');
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
ol.color.Matrix = function() {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.colorMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.brightness_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.brightnessMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.contrast_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.contrastMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.hue_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.hueMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.saturation_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.saturationMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Brightness value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeBrightness = function(matrix, value) {
|
||||
goog.vec.Mat4.makeTranslate(matrix, value, value, value);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Contrast value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeContrast = function(matrix, value) {
|
||||
goog.vec.Mat4.makeScale(matrix, value, value, value);
|
||||
var translateValue = (-0.5 * value + 0.5);
|
||||
goog.vec.Mat4.setColumnValues(matrix, 3,
|
||||
translateValue, translateValue, translateValue, 1);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Hue value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeHue = function(matrix, value) {
|
||||
var cosHue = Math.cos(value);
|
||||
var sinHue = Math.sin(value);
|
||||
var v00 = 0.213 + cosHue * 0.787 - sinHue * 0.213;
|
||||
var v01 = 0.715 - cosHue * 0.715 - sinHue * 0.715;
|
||||
var v02 = 0.072 - cosHue * 0.072 + sinHue * 0.928;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - cosHue * 0.213 + sinHue * 0.143;
|
||||
var v11 = 0.715 + cosHue * 0.285 + sinHue * 0.140;
|
||||
var v12 = 0.072 - cosHue * 0.072 - sinHue * 0.283;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - cosHue * 0.213 - sinHue * 0.787;
|
||||
var v21 = 0.715 - cosHue * 0.715 + sinHue * 0.715;
|
||||
var v22 = 0.072 + cosHue * 0.928 + sinHue * 0.072;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Saturation value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeSaturation = function(matrix, value) {
|
||||
var v00 = 0.213 + 0.787 * value;
|
||||
var v01 = 0.715 - 0.715 * value;
|
||||
var v02 = 0.072 - 0.072 * value;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - 0.213 * value;
|
||||
var v11 = 0.715 + 0.285 * value;
|
||||
var v12 = 0.072 - 0.072 * value;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - 0.213 * value;
|
||||
var v21 = 0.715 - 0.715 * value;
|
||||
var v22 = 0.072 + 0.928 * value;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number|undefined} brightness Brightness.
|
||||
* @param {number|undefined} contrast Contrast.
|
||||
* @param {number|undefined} hue Hue.
|
||||
* @param {number|undefined} saturation Saturation.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.prototype.getMatrix = function(
|
||||
brightness, contrast, hue, saturation) {
|
||||
var colorMatrixDirty = false;
|
||||
if (goog.isDef(brightness) && brightness !== this.brightness_) {
|
||||
ol.color.Matrix.makeBrightness(this.brightnessMatrix_, brightness);
|
||||
this.brightness_ = brightness;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(contrast) && contrast !== this.contrast_) {
|
||||
ol.color.Matrix.makeContrast(this.contrastMatrix_, contrast);
|
||||
this.contrast_ = contrast;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(hue) && hue !== this.hue_) {
|
||||
ol.color.Matrix.makeHue(this.hueMatrix_, hue);
|
||||
this.hue_ = hue;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(saturation) && saturation !== this.saturation_) {
|
||||
ol.color.Matrix.makeSaturation(this.saturationMatrix_, saturation);
|
||||
this.saturation_ = saturation;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (colorMatrixDirty) {
|
||||
var colorMatrix = this.colorMatrix_;
|
||||
goog.vec.Mat4.makeIdentity(colorMatrix);
|
||||
if (goog.isDef(contrast)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.contrastMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(brightness)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.brightnessMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(saturation)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.saturationMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(hue)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.hueMatrix_, colorMatrix);
|
||||
}
|
||||
}
|
||||
return this.colorMatrix_;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
goog.provide('ol.Constraints');
|
||||
|
||||
goog.require('ol.CenterConstraintType');
|
||||
goog.require('ol.ResolutionConstraintType');
|
||||
goog.require('ol.RotationConstraintType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.CenterConstraintType} centerConstraint Center constraint.
|
||||
* @param {ol.ResolutionConstraintType} resolutionConstraint
|
||||
* Resolution constraint.
|
||||
* @param {ol.RotationConstraintType} rotationConstraint
|
||||
* Rotation constraint.
|
||||
*/
|
||||
ol.Constraints =
|
||||
function(centerConstraint, resolutionConstraint, rotationConstraint) {
|
||||
|
||||
/**
|
||||
* @type {ol.CenterConstraintType}
|
||||
*/
|
||||
this.center = centerConstraint;
|
||||
|
||||
/**
|
||||
* @type {ol.ResolutionConstraintType}
|
||||
*/
|
||||
this.resolution = resolutionConstraint;
|
||||
|
||||
/**
|
||||
* @type {ol.RotationConstraintType}
|
||||
*/
|
||||
this.rotation = rotationConstraint;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.control
|
||||
*/
|
||||
@@ -0,0 +1,397 @@
|
||||
// FIXME handle date line wrap
|
||||
|
||||
goog.provide('ol.control.Attribution');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Control to show all the attributions associated with the layer sources
|
||||
* in the map. This control is one of the default controls included in maps.
|
||||
* By default it will show in the bottom right portion of the map, but this can
|
||||
* be changed by using a css selector for `.ol-attribution`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.AttributionOptions=} opt_options Attribution options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Attribution = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.ulElement_ = goog.dom.createElement(goog.dom.TagName.UL);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.logoLi_ = goog.dom.createElement(goog.dom.TagName.LI);
|
||||
|
||||
goog.dom.appendChild(this.ulElement_, this.logoLi_);
|
||||
goog.style.setElementShown(this.logoLi_, false);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsed_ = goog.isDef(options.collapsed) ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ = goog.isDef(options.collapsible) ?
|
||||
options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-attribution';
|
||||
|
||||
var tipLabel = goog.isDef(options.tipLabel) ?
|
||||
options.tipLabel : 'Attributions';
|
||||
|
||||
var collapseLabel = goog.isDef(options.collapseLabel) ?
|
||||
options.collapseLabel : '\u00BB';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.collapseLabel_ = /** @type {Node} */ (goog.isString(collapseLabel) ?
|
||||
goog.dom.createDom(goog.dom.TagName.SPAN, {}, collapseLabel) :
|
||||
collapseLabel);
|
||||
|
||||
var label = goog.isDef(options.label) ? options.label : 'i';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.label_ = /** @type {Node} */ (goog.isString(label) ?
|
||||
goog.dom.createDom(goog.dom.TagName.SPAN, {}, label) :
|
||||
label);
|
||||
|
||||
var activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'type': 'button',
|
||||
'title': tipLabel
|
||||
}, activeLabel);
|
||||
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ol-collapsed' : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
cssClasses, this.ulElement_, button);
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.Attribution.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
render: render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, Element>}
|
||||
*/
|
||||
this.attributionElements_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, boolean>}
|
||||
*/
|
||||
this.attributionElementRenderedVisible_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, Element>}
|
||||
*/
|
||||
this.logoElements_ = {};
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Attribution, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
* @return {Array.<Object.<string, ol.Attribution>>} Attributions.
|
||||
*/
|
||||
ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
|
||||
var i, ii, j, jj, tileRanges, source, sourceAttribution,
|
||||
sourceAttributionKey, sourceAttributions, sourceKey;
|
||||
var layerStatesArray = frameState.layerStatesArray;
|
||||
/** @type {Object.<string, ol.Attribution>} */
|
||||
var attributions = goog.object.clone(frameState.attributions);
|
||||
/** @type {Object.<string, ol.Attribution>} */
|
||||
var hiddenAttributions = {};
|
||||
for (i = 0, ii = layerStatesArray.length; i < ii; i++) {
|
||||
source = layerStatesArray[i].layer.getSource();
|
||||
if (goog.isNull(source)) {
|
||||
continue;
|
||||
}
|
||||
sourceKey = goog.getUid(source).toString();
|
||||
sourceAttributions = source.getAttributions();
|
||||
if (goog.isNull(sourceAttributions)) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0, jj = sourceAttributions.length; j < jj; j++) {
|
||||
sourceAttribution = sourceAttributions[j];
|
||||
sourceAttributionKey = goog.getUid(sourceAttribution).toString();
|
||||
if (sourceAttributionKey in attributions) {
|
||||
continue;
|
||||
}
|
||||
tileRanges = frameState.usedTiles[sourceKey];
|
||||
if (goog.isDef(tileRanges) &&
|
||||
sourceAttribution.intersectsAnyTileRange(tileRanges)) {
|
||||
if (sourceAttributionKey in hiddenAttributions) {
|
||||
delete hiddenAttributions[sourceAttributionKey];
|
||||
}
|
||||
attributions[sourceAttributionKey] = sourceAttribution;
|
||||
}
|
||||
else {
|
||||
hiddenAttributions[sourceAttributionKey] = sourceAttribution;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [attributions, hiddenAttributions];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.Attribution}
|
||||
* @api
|
||||
*/
|
||||
ol.control.Attribution.render = function(mapEvent) {
|
||||
this.updateElement_(mapEvent.frameState);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
*/
|
||||
ol.control.Attribution.prototype.updateElement_ = function(frameState) {
|
||||
|
||||
if (goog.isNull(frameState)) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.setElementShown(this.element, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var attributions = this.getSourceAttributions(frameState);
|
||||
/** @type {Object.<string, ol.Attribution>} */
|
||||
var visibleAttributions = attributions[0];
|
||||
/** @type {Object.<string, ol.Attribution>} */
|
||||
var hiddenAttributions = attributions[1];
|
||||
|
||||
var attributionElement, attributionKey;
|
||||
for (attributionKey in this.attributionElements_) {
|
||||
if (attributionKey in visibleAttributions) {
|
||||
if (!this.attributionElementRenderedVisible_[attributionKey]) {
|
||||
goog.style.setElementShown(
|
||||
this.attributionElements_[attributionKey], true);
|
||||
this.attributionElementRenderedVisible_[attributionKey] = true;
|
||||
}
|
||||
delete visibleAttributions[attributionKey];
|
||||
}
|
||||
else if (attributionKey in hiddenAttributions) {
|
||||
if (this.attributionElementRenderedVisible_[attributionKey]) {
|
||||
goog.style.setElementShown(
|
||||
this.attributionElements_[attributionKey], false);
|
||||
delete this.attributionElementRenderedVisible_[attributionKey];
|
||||
}
|
||||
delete hiddenAttributions[attributionKey];
|
||||
}
|
||||
else {
|
||||
goog.dom.removeNode(this.attributionElements_[attributionKey]);
|
||||
delete this.attributionElements_[attributionKey];
|
||||
delete this.attributionElementRenderedVisible_[attributionKey];
|
||||
}
|
||||
}
|
||||
for (attributionKey in visibleAttributions) {
|
||||
attributionElement = goog.dom.createElement(goog.dom.TagName.LI);
|
||||
attributionElement.innerHTML =
|
||||
visibleAttributions[attributionKey].getHTML();
|
||||
goog.dom.appendChild(this.ulElement_, attributionElement);
|
||||
this.attributionElements_[attributionKey] = attributionElement;
|
||||
this.attributionElementRenderedVisible_[attributionKey] = true;
|
||||
}
|
||||
for (attributionKey in hiddenAttributions) {
|
||||
attributionElement = goog.dom.createElement(goog.dom.TagName.LI);
|
||||
attributionElement.innerHTML =
|
||||
hiddenAttributions[attributionKey].getHTML();
|
||||
goog.style.setElementShown(attributionElement, false);
|
||||
goog.dom.appendChild(this.ulElement_, attributionElement);
|
||||
this.attributionElements_[attributionKey] = attributionElement;
|
||||
}
|
||||
|
||||
var renderVisible =
|
||||
!goog.object.isEmpty(this.attributionElementRenderedVisible_) ||
|
||||
!goog.object.isEmpty(frameState.logos);
|
||||
if (this.renderedVisible_ != renderVisible) {
|
||||
goog.style.setElementShown(this.element, renderVisible);
|
||||
this.renderedVisible_ = renderVisible;
|
||||
}
|
||||
if (renderVisible &&
|
||||
goog.object.isEmpty(this.attributionElementRenderedVisible_)) {
|
||||
goog.dom.classlist.add(this.element, 'ol-logo-only');
|
||||
} else {
|
||||
goog.dom.classlist.remove(this.element, 'ol-logo-only');
|
||||
}
|
||||
|
||||
this.insertLogos_(frameState);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?olx.FrameState} frameState Frame state.
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.insertLogos_ = function(frameState) {
|
||||
|
||||
var logo;
|
||||
var logos = frameState.logos;
|
||||
var logoElements = this.logoElements_;
|
||||
|
||||
for (logo in logoElements) {
|
||||
if (!(logo in logos)) {
|
||||
goog.dom.removeNode(logoElements[logo]);
|
||||
delete logoElements[logo];
|
||||
}
|
||||
}
|
||||
|
||||
var image, logoElement, logoKey;
|
||||
for (logoKey in logos) {
|
||||
if (!(logoKey in logoElements)) {
|
||||
image = new Image();
|
||||
image.src = logoKey;
|
||||
var logoValue = logos[logoKey];
|
||||
if (logoValue === '') {
|
||||
logoElement = image;
|
||||
} else {
|
||||
logoElement = goog.dom.createDom(goog.dom.TagName.A, {
|
||||
'href': logoValue
|
||||
});
|
||||
logoElement.appendChild(image);
|
||||
}
|
||||
goog.dom.appendChild(this.logoLi_, logoElement);
|
||||
logoElements[logoKey] = logoElement;
|
||||
}
|
||||
}
|
||||
|
||||
goog.style.setElementShown(this.logoLi_, !goog.object.isEmpty(logos));
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.Attribution.prototype.handleToggle_ = function() {
|
||||
goog.dom.classlist.toggle(this.element, 'ol-collapsed');
|
||||
if (this.collapsed_) {
|
||||
goog.dom.replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
goog.dom.replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Attribution.prototype.getCollapsible = function() {
|
||||
return this.collapsible_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
goog.dom.classlist.toggle(this.element, 'ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Attribution.prototype.setCollapsed = function(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the widget is collapsed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Attribution.prototype.getCollapsed = function() {
|
||||
return this.collapsed_;
|
||||
};
|
||||
@@ -0,0 +1,140 @@
|
||||
goog.provide('ol.control.Control');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('ol.MapEventType');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control is a visible widget with a DOM element in a fixed position on the
|
||||
* screen. They can involve user input (buttons), or be informational only;
|
||||
* the position is determined using CSS. By default these are placed in the
|
||||
* container with CSS class name `ol-overlaycontainer-stopevent`, but can use
|
||||
* any outside DOM element.
|
||||
*
|
||||
* This is the base class for controls. You can use it for simple custom
|
||||
* controls by creating the element with listeners, creating an instance:
|
||||
* ```js
|
||||
* var myControl = new ol.control.Control({element: myElement});
|
||||
* ```
|
||||
* and then adding this to the map.
|
||||
*
|
||||
* The main advantage of having this as a control rather than a simple separate
|
||||
* DOM element is that preventing propagation is handled for you. Controls
|
||||
* will also be `ol.Object`s in a `ol.Collection`, so you can use their
|
||||
* methods.
|
||||
*
|
||||
* You can also extend this base for your own control class. See
|
||||
* examples/custom-controls for an example of how to do this.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @implements {oli.control.Control}
|
||||
* @param {olx.control.ControlOptions} options Control options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Control = function(options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Element}
|
||||
*/
|
||||
this.element = goog.isDef(options.element) ? options.element : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.target_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array.<?number>}
|
||||
*/
|
||||
this.listenerKeys = [];
|
||||
|
||||
/**
|
||||
* @type {function(ol.MapEvent)}
|
||||
*/
|
||||
this.render = goog.isDef(options.render) ? options.render : goog.nullFunction;
|
||||
|
||||
if (goog.isDef(options.target)) {
|
||||
this.setTarget(options.target);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Control, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.control.Control.prototype.disposeInternal = function() {
|
||||
goog.dom.removeNode(this.element);
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the map associated with this control.
|
||||
* @return {ol.Map} Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Control.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Control.prototype.setMap = function(map) {
|
||||
if (!goog.isNull(this.map_)) {
|
||||
goog.dom.removeNode(this.element);
|
||||
}
|
||||
if (!goog.array.isEmpty(this.listenerKeys)) {
|
||||
goog.array.forEach(this.listenerKeys, goog.events.unlistenByKey);
|
||||
this.listenerKeys.length = 0;
|
||||
}
|
||||
this.map_ = map;
|
||||
if (!goog.isNull(this.map_)) {
|
||||
var target = !goog.isNull(this.target_) ?
|
||||
this.target_ : map.getOverlayContainerStopEvent();
|
||||
goog.dom.appendChild(target, this.element);
|
||||
if (this.render !== goog.nullFunction) {
|
||||
this.listenerKeys.push(goog.events.listen(map,
|
||||
ol.MapEventType.POSTRENDER, this.render, false, this));
|
||||
}
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function is used to set a target element for the control. It has no
|
||||
* effect if it is called after the control has been added to the map (i.e.
|
||||
* after `setMap` is called on the control). If no `target` is set in the
|
||||
* options passed to the control constructor and if `setTarget` is not called
|
||||
* then the control is added to the map's overlay container.
|
||||
* @param {Element|string} target Target.
|
||||
* @api
|
||||
*/
|
||||
ol.control.Control.prototype.setTarget = function(target) {
|
||||
this.target_ = goog.dom.getElement(target);
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
goog.provide('ol.control');
|
||||
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.control.Attribution');
|
||||
goog.require('ol.control.Rotate');
|
||||
goog.require('ol.control.Zoom');
|
||||
|
||||
|
||||
/**
|
||||
* Set of controls included in maps by default. Unless configured otherwise,
|
||||
* this returns a collection containing an instance of each of the following
|
||||
* controls:
|
||||
* * {@link ol.control.Zoom}
|
||||
* * {@link ol.control.Rotate}
|
||||
* * {@link ol.control.Attribution}
|
||||
*
|
||||
* @param {olx.control.DefaultsOptions=} opt_options Defaults options.
|
||||
* @return {ol.Collection.<ol.control.Control>} Controls.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.defaults = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
var controls = new ol.Collection();
|
||||
|
||||
var zoomControl = goog.isDef(options.zoom) ?
|
||||
options.zoom : true;
|
||||
if (zoomControl) {
|
||||
controls.push(new ol.control.Zoom(options.zoomOptions));
|
||||
}
|
||||
|
||||
var rotateControl = goog.isDef(options.rotate) ?
|
||||
options.rotate : true;
|
||||
if (rotateControl) {
|
||||
controls.push(new ol.control.Rotate(options.rotateOptions));
|
||||
}
|
||||
|
||||
var attributionControl = goog.isDef(options.attribution) ?
|
||||
options.attribution : true;
|
||||
if (attributionControl) {
|
||||
controls.push(new ol.control.Attribution(options.attributionOptions));
|
||||
}
|
||||
|
||||
return controls;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,150 @@
|
||||
goog.provide('ol.control.FullScreen');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.fullscreen');
|
||||
goog.require('goog.dom.fullscreen.EventType');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Provides a button that when clicked fills up the full screen with the map.
|
||||
* When in full screen mode, a close button is shown to exit full screen mode.
|
||||
* The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
|
||||
* toggle the map in full screen mode.
|
||||
*
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.FullScreenOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.FullScreen = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.cssClassName_ = goog.isDef(options.className) ?
|
||||
options.className : 'ol-full-screen';
|
||||
|
||||
var label = goog.isDef(options.label) ? options.label : '\u2194';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.labelNode_ = /** @type {Node} */ (goog.isString(label) ?
|
||||
goog.dom.createTextNode(label) : label);
|
||||
|
||||
var labelActive = goog.isDef(options.labelActive) ?
|
||||
options.labelActive : '\u00d7';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.labelActiveNode_ = /** @type {Node} */ (goog.isString(labelActive) ?
|
||||
goog.dom.createTextNode(labelActive) : labelActive);
|
||||
|
||||
var tipLabel = goog.isDef(options.tipLabel) ?
|
||||
options.tipLabel : 'Toggle full-screen';
|
||||
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'class': this.cssClassName_ + '-' + goog.dom.fullscreen.isFullScreen(),
|
||||
'type': 'button',
|
||||
'title': tipLabel
|
||||
}, this.labelNode_);
|
||||
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
goog.events.listen(goog.global.document,
|
||||
goog.dom.fullscreen.EventType.CHANGE,
|
||||
this.handleFullScreenChange_, false, this);
|
||||
|
||||
var cssClasses = this.cssClassName_ + ' ' + ol.css.CLASS_UNSELECTABLE +
|
||||
' ' + ol.css.CLASS_CONTROL + ' ' +
|
||||
(!goog.dom.fullscreen.isSupported() ? ol.css.CLASS_UNSUPPORTED : '');
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button);
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = goog.isDef(options.keys) ? options.keys : false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.FullScreen, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.FullScreen.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleFullScreen_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.FullScreen.prototype.handleFullScreen_ = function() {
|
||||
if (!goog.dom.fullscreen.isSupported()) {
|
||||
return;
|
||||
}
|
||||
var map = this.getMap();
|
||||
if (goog.isNull(map)) {
|
||||
return;
|
||||
}
|
||||
if (goog.dom.fullscreen.isFullScreen()) {
|
||||
goog.dom.fullscreen.exitFullScreen();
|
||||
} else {
|
||||
var target = map.getTarget();
|
||||
goog.asserts.assert(goog.isDefAndNotNull(target));
|
||||
var element = goog.dom.getElement(target);
|
||||
goog.asserts.assert(goog.isDefAndNotNull(element));
|
||||
if (this.keys_) {
|
||||
goog.dom.fullscreen.requestFullScreenWithKeys(element);
|
||||
} else {
|
||||
goog.dom.fullscreen.requestFullScreen(element);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
|
||||
var map = this.getMap();
|
||||
if (goog.dom.fullscreen.isFullScreen()) {
|
||||
goog.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
} else {
|
||||
goog.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
}
|
||||
if (!goog.isNull(map)) {
|
||||
map.updateSize();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,265 @@
|
||||
// FIXME should listen on appropriate pane, once it is defined
|
||||
|
||||
goog.provide('ol.control.MousePosition');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.CoordinateFormatType');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.TransformFunction');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.proj.Projection');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.control.MousePositionProperty = {
|
||||
PROJECTION: 'projection',
|
||||
COORDINATE_FORMAT: 'coordinateFormat'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control to show the 2D coordinates of the mouse cursor. By default, these
|
||||
* are in the view projection, but can be in any supported projection.
|
||||
* By default the control is shown in the top right corner of the map, but this
|
||||
* can be changed by using the css selector `.ol-mouse-position`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.MousePositionOptions=} opt_options Mouse position
|
||||
* options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-mouse-position';
|
||||
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, className);
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.MousePosition.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
render: render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
goog.events.listen(this,
|
||||
ol.Object.getChangeEventType(ol.control.MousePositionProperty.PROJECTION),
|
||||
this.handleProjectionChanged_, false, this);
|
||||
|
||||
if (goog.isDef(options.coordinateFormat)) {
|
||||
this.setCoordinateFormat(options.coordinateFormat);
|
||||
}
|
||||
if (goog.isDef(options.projection)) {
|
||||
this.setProjection(ol.proj.get(options.projection));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.undefinedHTML_ = goog.isDef(options.undefinedHTML) ?
|
||||
options.undefinedHTML : '';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = element.innerHTML;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.proj.Projection}
|
||||
*/
|
||||
this.mapProjection_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?ol.TransformFunction}
|
||||
*/
|
||||
this.transform_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Pixel}
|
||||
*/
|
||||
this.lastMouseMovePixel_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.MousePosition, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.MousePosition}
|
||||
* @api
|
||||
*/
|
||||
ol.control.MousePosition.render = function(mapEvent) {
|
||||
var frameState = mapEvent.frameState;
|
||||
if (goog.isNull(frameState)) {
|
||||
this.mapProjection_ = null;
|
||||
} else {
|
||||
if (this.mapProjection_ != frameState.viewState.projection) {
|
||||
this.mapProjection_ = frameState.viewState.projection;
|
||||
this.transform_ = null;
|
||||
}
|
||||
}
|
||||
this.updateHTML_(this.lastMouseMovePixel_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleProjectionChanged_ = function() {
|
||||
this.transform_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.CoordinateFormatType|undefined} The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition.prototype.getCoordinateFormat = function() {
|
||||
return /** @type {ol.CoordinateFormatType|undefined} */ (
|
||||
this.get(ol.control.MousePositionProperty.COORDINATE_FORMAT));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.MousePosition.prototype,
|
||||
'getCoordinateFormat',
|
||||
ol.control.MousePosition.prototype.getCoordinateFormat);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.proj.Projection|undefined} The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition.prototype.getProjection = function() {
|
||||
return /** @type {ol.proj.Projection|undefined} */ (
|
||||
this.get(ol.control.MousePositionProperty.PROJECTION));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.MousePosition.prototype,
|
||||
'getProjection',
|
||||
ol.control.MousePosition.prototype.getProjection);
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleMouseMove = function(browserEvent) {
|
||||
var map = this.getMap();
|
||||
this.lastMouseMovePixel_ = map.getEventPixel(browserEvent.getBrowserEvent());
|
||||
this.updateHTML_(this.lastMouseMovePixel_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @protected
|
||||
*/
|
||||
ol.control.MousePosition.prototype.handleMouseOut = function(browserEvent) {
|
||||
this.updateHTML_(null);
|
||||
this.lastMouseMovePixel_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition.prototype.setMap = function(map) {
|
||||
goog.base(this, 'setMap', map);
|
||||
if (!goog.isNull(map)) {
|
||||
var viewport = map.getViewport();
|
||||
this.listenerKeys.push(
|
||||
goog.events.listen(viewport, goog.events.EventType.MOUSEMOVE,
|
||||
this.handleMouseMove, false, this),
|
||||
goog.events.listen(viewport, goog.events.EventType.MOUSEOUT,
|
||||
this.handleMouseOut, false, this)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CoordinateFormatType} format The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition.prototype.setCoordinateFormat = function(format) {
|
||||
this.set(ol.control.MousePositionProperty.COORDINATE_FORMAT, format);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.MousePosition.prototype,
|
||||
'setCoordinateFormat',
|
||||
ol.control.MousePosition.prototype.setCoordinateFormat);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.proj.Projection} projection The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.MousePosition.prototype.setProjection = function(projection) {
|
||||
this.set(ol.control.MousePositionProperty.PROJECTION, projection);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.MousePosition.prototype,
|
||||
'setProjection',
|
||||
ol.control.MousePosition.prototype.setProjection);
|
||||
|
||||
|
||||
/**
|
||||
* @param {?ol.Pixel} pixel Pixel.
|
||||
* @private
|
||||
*/
|
||||
ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
|
||||
var html = this.undefinedHTML_;
|
||||
if (!goog.isNull(pixel) && !goog.isNull(this.mapProjection_)) {
|
||||
if (goog.isNull(this.transform_)) {
|
||||
var projection = this.getProjection();
|
||||
if (goog.isDef(projection)) {
|
||||
this.transform_ = ol.proj.getTransformFromProjections(
|
||||
this.mapProjection_, projection);
|
||||
} else {
|
||||
this.transform_ = ol.proj.identityTransform;
|
||||
}
|
||||
}
|
||||
var map = this.getMap();
|
||||
var coordinate = map.getCoordinateFromPixel(pixel);
|
||||
if (!goog.isNull(coordinate)) {
|
||||
this.transform_(coordinate, coordinate);
|
||||
var coordinateFormat = this.getCoordinateFormat();
|
||||
if (goog.isDef(coordinateFormat)) {
|
||||
html = coordinateFormat(coordinate);
|
||||
} else {
|
||||
html = coordinate.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!goog.isDef(this.renderedHTML_) || html != this.renderedHTML_) {
|
||||
this.element.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,497 @@
|
||||
goog.provide('ol.control.OverviewMap');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.math.Size');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapEventType');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.Overlay');
|
||||
goog.require('ol.OverlayPositioning');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.coordinate');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.extent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new control with a map acting as an overview map for an other
|
||||
* defined map.
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.OverviewMapOptions=} opt_options OverviewMap options.
|
||||
* @api
|
||||
*/
|
||||
ol.control.OverviewMap = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.collapsed_ = goog.isDef(options.collapsed) ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ = goog.isDef(options.collapsible) ?
|
||||
options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-overviewmap';
|
||||
|
||||
var tipLabel = goog.isDef(options.tipLabel) ?
|
||||
options.tipLabel : 'Overview map';
|
||||
|
||||
var collapseLabel = goog.isDef(options.collapseLabel) ?
|
||||
options.collapseLabel : '\u00AB';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.collapseLabel_ = /** @type {Node} */ (goog.isString(collapseLabel) ?
|
||||
goog.dom.createDom(goog.dom.TagName.SPAN, {}, collapseLabel) :
|
||||
collapseLabel);
|
||||
|
||||
var label = goog.isDef(options.label) ? options.label : '\u00BB';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Node}
|
||||
*/
|
||||
this.label_ = /** @type {Node} */ (goog.isString(label) ?
|
||||
goog.dom.createDom(goog.dom.TagName.SPAN, {}, label) :
|
||||
label);
|
||||
|
||||
var activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'type': 'button',
|
||||
'title': tipLabel
|
||||
}, activeLabel);
|
||||
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var ovmapDiv = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-overviewmap-map');
|
||||
|
||||
/**
|
||||
* @type {ol.Map}
|
||||
* @private
|
||||
*/
|
||||
this.ovmap_ = new ol.Map({
|
||||
controls: new ol.Collection(),
|
||||
interactions: new ol.Collection(),
|
||||
target: ovmapDiv
|
||||
});
|
||||
var ovmap = this.ovmap_;
|
||||
|
||||
if (goog.isDef(options.layers)) {
|
||||
options.layers.forEach(
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
*/
|
||||
function(layer) {
|
||||
ovmap.addLayer(layer);
|
||||
}, this);
|
||||
}
|
||||
|
||||
var box = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-overviewmap-box');
|
||||
|
||||
/**
|
||||
* @type {ol.Overlay}
|
||||
* @private
|
||||
*/
|
||||
this.boxOverlay_ = new ol.Overlay({
|
||||
position: [0, 0],
|
||||
positioning: ol.OverlayPositioning.BOTTOM_LEFT,
|
||||
element: box
|
||||
});
|
||||
this.ovmap_.addOverlay(this.boxOverlay_);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ol-collapsed' : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
cssClasses, ovmapDiv, button);
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.OverviewMap.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
render: render,
|
||||
target: options.target
|
||||
});
|
||||
};
|
||||
goog.inherits(ol.control.OverviewMap, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.setMap = function(map) {
|
||||
var currentMap = this.getMap();
|
||||
|
||||
if (goog.isNull(map) && !goog.isNull(currentMap)) {
|
||||
goog.events.unlisten(
|
||||
currentMap, ol.Object.getChangeEventType(ol.MapProperty.VIEW),
|
||||
this.handleViewChanged_, false, this);
|
||||
}
|
||||
|
||||
goog.base(this, 'setMap', map);
|
||||
|
||||
if (!goog.isNull(map)) {
|
||||
|
||||
// if no layers were set for the overviewmap map, then bind with
|
||||
// those in the main map
|
||||
if (this.ovmap_.getLayers().getLength() === 0) {
|
||||
this.ovmap_.bindTo(ol.MapProperty.LAYERGROUP, map);
|
||||
}
|
||||
|
||||
// bind current map view, or any new one
|
||||
this.bindView_();
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangeEventType(ol.MapProperty.VIEW),
|
||||
this.handleViewChanged_, false, this);
|
||||
|
||||
this.ovmap_.updateSize();
|
||||
this.resetExtent_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Bind some actions to the main map view.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.bindView_ = function() {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
|
||||
// if the map does not have a view, we can't act upon it
|
||||
if (goog.isNull(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME - the overviewmap view rotation currently follows the one used
|
||||
// by the main map view. We could support box rotation instead. The choice
|
||||
// between the 2 modes would be made in a single option
|
||||
this.ovmap_.getView().bindTo(ol.ViewProperty.ROTATION, view);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.OverviewMap}
|
||||
* @api
|
||||
*/
|
||||
ol.control.OverviewMap.render = function(mapEvent) {
|
||||
this.validateExtent_();
|
||||
this.updateBox_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called on main map view changed.
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.handleViewChanged_ = function(event) {
|
||||
this.bindView_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset the overview map extent if the box size (width or
|
||||
* height) is less than the size of the overview map size times minRatio
|
||||
* or is greater than the size of the overview size times maxRatio.
|
||||
*
|
||||
* If the map extent was not reset, the box size can fits in the defined
|
||||
* ratio sizes. This method then checks if is contained inside the overview
|
||||
* map current extent. If not, recenter the overview map to the current
|
||||
* main map center location.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.validateExtent_ = function() {
|
||||
var map = this.getMap();
|
||||
var ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mapSize = map.getSize();
|
||||
goog.asserts.assertArray(mapSize);
|
||||
|
||||
var view = map.getView();
|
||||
goog.asserts.assert(goog.isDef(view));
|
||||
var extent = view.calculateExtent(mapSize);
|
||||
|
||||
var ovmapSize = ovmap.getSize();
|
||||
goog.asserts.assertArray(ovmapSize);
|
||||
|
||||
var ovview = ovmap.getView();
|
||||
goog.asserts.assert(goog.isDef(ovview));
|
||||
var ovextent = ovview.calculateExtent(ovmapSize);
|
||||
|
||||
var topLeftPixel =
|
||||
ovmap.getPixelFromCoordinate(ol.extent.getTopLeft(extent));
|
||||
var bottomRightPixel =
|
||||
ovmap.getPixelFromCoordinate(ol.extent.getBottomRight(extent));
|
||||
var boxSize = new goog.math.Size(
|
||||
Math.abs(topLeftPixel[0] - bottomRightPixel[0]),
|
||||
Math.abs(topLeftPixel[1] - bottomRightPixel[1]));
|
||||
|
||||
var ovmapWidth = ovmapSize[0];
|
||||
var ovmapHeight = ovmapSize[1];
|
||||
|
||||
if (boxSize.width < ovmapWidth * ol.OVERVIEWMAP_MIN_RATIO ||
|
||||
boxSize.height < ovmapHeight * ol.OVERVIEWMAP_MIN_RATIO ||
|
||||
boxSize.width > ovmapWidth * ol.OVERVIEWMAP_MAX_RATIO ||
|
||||
boxSize.height > ovmapHeight * ol.OVERVIEWMAP_MAX_RATIO) {
|
||||
this.resetExtent_();
|
||||
} else if (!ol.extent.containsExtent(ovextent, extent)) {
|
||||
this.recenter_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset the overview map extent to half calculated min and max ratio times
|
||||
* the extent of the main map.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.resetExtent_ = function() {
|
||||
if (ol.OVERVIEWMAP_MAX_RATIO === 0 || ol.OVERVIEWMAP_MIN_RATIO === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = this.getMap();
|
||||
var ovmap = this.ovmap_;
|
||||
|
||||
var mapSize = map.getSize();
|
||||
goog.asserts.assertArray(mapSize);
|
||||
|
||||
var view = map.getView();
|
||||
goog.asserts.assert(goog.isDef(view));
|
||||
var extent = view.calculateExtent(mapSize);
|
||||
|
||||
var ovmapSize = ovmap.getSize();
|
||||
goog.asserts.assertArray(ovmapSize);
|
||||
|
||||
var ovview = ovmap.getView();
|
||||
goog.asserts.assert(goog.isDef(ovview));
|
||||
|
||||
// get how many times the current map overview could hold different
|
||||
// box sizes using the min and max ratio, pick the step in the middle used
|
||||
// to calculate the extent from the main map to set it to the overview map,
|
||||
var steps = Math.log(
|
||||
ol.OVERVIEWMAP_MAX_RATIO / ol.OVERVIEWMAP_MIN_RATIO) / Math.LN2;
|
||||
var ratio = 1 / (Math.pow(2, steps / 2) * ol.OVERVIEWMAP_MIN_RATIO);
|
||||
ol.extent.scaleFromCenter(extent, ratio);
|
||||
ovview.fitExtent(extent, ovmapSize);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the center of the overview map to the map center without changing its
|
||||
* resolution.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.recenter_ = function() {
|
||||
var map = this.getMap();
|
||||
var ovmap = this.ovmap_;
|
||||
|
||||
var view = map.getView();
|
||||
goog.asserts.assert(goog.isDef(view));
|
||||
|
||||
var ovview = ovmap.getView();
|
||||
goog.asserts.assert(goog.isDef(ovview));
|
||||
|
||||
ovview.setCenter(view.getCenter());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the box using the main map extent
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.updateBox_ = function() {
|
||||
var map = this.getMap();
|
||||
var ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mapSize = map.getSize();
|
||||
goog.asserts.assertArray(mapSize);
|
||||
|
||||
var view = map.getView();
|
||||
goog.asserts.assert(goog.isDef(view));
|
||||
|
||||
var ovview = ovmap.getView();
|
||||
goog.asserts.assert(goog.isDef(ovview));
|
||||
|
||||
var ovmapSize = ovmap.getSize();
|
||||
goog.asserts.assertArray(ovmapSize);
|
||||
|
||||
var rotation = view.getRotation();
|
||||
goog.asserts.assert(goog.isDef(rotation));
|
||||
|
||||
var overlay = this.boxOverlay_;
|
||||
var box = this.boxOverlay_.getElement();
|
||||
var extent = view.calculateExtent(mapSize);
|
||||
var ovresolution = ovview.getResolution();
|
||||
var bottomLeft = ol.extent.getBottomLeft(extent);
|
||||
var topRight = ol.extent.getTopRight(extent);
|
||||
|
||||
// set position using bottom left coordinates
|
||||
var rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft);
|
||||
overlay.setPosition(rotateBottomLeft);
|
||||
|
||||
// set box size calculated from map extent size and overview map resolution
|
||||
if (goog.isDefAndNotNull(box)) {
|
||||
var boxWidth = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution);
|
||||
var boxHeight = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution);
|
||||
goog.style.setBorderBoxSize(box, new goog.math.Size(
|
||||
boxWidth, boxHeight));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} rotation Target rotation.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Coordinate|undefined} Coordinate for rotation and center anchor.
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.calculateCoordinateRotate_ = function(
|
||||
rotation, coordinate) {
|
||||
var coordinateRotate;
|
||||
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
goog.asserts.assert(goog.isDef(view));
|
||||
|
||||
var currentCenter = view.getCenter();
|
||||
|
||||
if (goog.isDef(currentCenter)) {
|
||||
coordinateRotate = [
|
||||
coordinate[0] - currentCenter[0],
|
||||
coordinate[1] - currentCenter[1]
|
||||
];
|
||||
ol.coordinate.rotate(coordinateRotate, rotation);
|
||||
ol.coordinate.add(coordinateRotate, currentCenter);
|
||||
}
|
||||
return coordinateRotate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.handleToggle_ = function() {
|
||||
goog.dom.classlist.toggle(this.element, 'ol-collapsed');
|
||||
if (this.collapsed_) {
|
||||
goog.dom.replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
goog.dom.replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
|
||||
// manage overview map if it had not been rendered before and control
|
||||
// is expanded
|
||||
var ovmap = this.ovmap_;
|
||||
if (!this.collapsed_ && !ovmap.isRendered()) {
|
||||
ovmap.updateSize();
|
||||
this.resetExtent_();
|
||||
goog.events.listenOnce(ovmap, ol.MapEventType.POSTRENDER,
|
||||
function(event) {
|
||||
this.updateBox_();
|
||||
},
|
||||
false, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.getCollapsible = function() {
|
||||
return this.collapsible_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.setCollapsible = function(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
goog.dom.classlist.toggle(this.element, 'ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.setCollapsed = function(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the widget is collapsed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.OverviewMap.prototype.getCollapsed = function() {
|
||||
return this.collapsed_;
|
||||
};
|
||||
@@ -0,0 +1,172 @@
|
||||
goog.provide('ol.control.Rotate');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.animation');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.easing');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A button control to reset rotation to 0.
|
||||
* To style this control use css selector `.ol-rotate`. A `.ol-hidden` css
|
||||
* selector is added to the button when the rotation is 0.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.RotateOptions=} opt_options Rotate options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Rotate = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-rotate';
|
||||
|
||||
var label = goog.isDef(options.label) ?
|
||||
options.label : '\u21E7';
|
||||
|
||||
/**
|
||||
* @type {Node}
|
||||
* @private
|
||||
*/
|
||||
this.label_ = null;
|
||||
|
||||
if (goog.isString(label)) {
|
||||
this.label_ = goog.dom.createDom(goog.dom.TagName.SPAN,
|
||||
'ol-compass', label);
|
||||
} else {
|
||||
this.label_ = label;
|
||||
goog.dom.classlist.add(this.label_, 'ol-compass');
|
||||
}
|
||||
|
||||
var tipLabel = goog.isDef(options.tipLabel) ?
|
||||
options.tipLabel : 'Reset rotation';
|
||||
|
||||
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'class': className + '-reset',
|
||||
'type' : 'button',
|
||||
'title': tipLabel
|
||||
}, this.label_);
|
||||
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
ol.control.Rotate.prototype.handleClick_, false, this);
|
||||
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL;
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button);
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.Rotate.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
render: render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = goog.isDef(options.duration) ? options.duration : 250;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.autoHide_ = goog.isDef(options.autoHide) ? options.autoHide : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.rotation_ = undefined;
|
||||
|
||||
if (this.autoHide_) {
|
||||
goog.dom.classlist.add(this.element, ol.css.CLASS_HIDDEN);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Rotate, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.Rotate.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.resetNorth_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.Rotate.prototype.resetNorth_ = function() {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
if (goog.isNull(view)) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
var currentRotation = view.getRotation();
|
||||
while (currentRotation < -Math.PI) {
|
||||
currentRotation += 2 * Math.PI;
|
||||
}
|
||||
while (currentRotation > Math.PI) {
|
||||
currentRotation -= 2 * Math.PI;
|
||||
}
|
||||
if (goog.isDef(currentRotation)) {
|
||||
if (this.duration_ > 0) {
|
||||
map.beforeRender(ol.animation.rotate({
|
||||
rotation: currentRotation,
|
||||
duration: this.duration_,
|
||||
easing: ol.easing.easeOut
|
||||
}));
|
||||
}
|
||||
view.setRotation(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.Rotate}
|
||||
* @api
|
||||
*/
|
||||
ol.control.Rotate.render = function(mapEvent) {
|
||||
var frameState = mapEvent.frameState;
|
||||
if (goog.isNull(frameState)) {
|
||||
return;
|
||||
}
|
||||
var rotation = frameState.viewState.rotation;
|
||||
if (rotation != this.rotation_) {
|
||||
var transform = 'rotate(' + goog.math.toDegrees(rotation) + 'deg)';
|
||||
if (this.autoHide_) {
|
||||
goog.dom.classlist.enable(
|
||||
this.element, ol.css.CLASS_HIDDEN, rotation === 0);
|
||||
}
|
||||
this.label_.style.msTransform = transform;
|
||||
this.label_.style.webkitTransform = transform;
|
||||
this.label_.style.transform = transform;
|
||||
}
|
||||
this.rotation_ = rotation;
|
||||
};
|
||||
@@ -0,0 +1,343 @@
|
||||
goog.provide('ol.control.ScaleLine');
|
||||
goog.provide('ol.control.ScaleLineProperty');
|
||||
goog.provide('ol.control.ScaleLineUnits');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.TransformFunction');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.proj.METERS_PER_UNIT');
|
||||
goog.require('ol.proj.Units');
|
||||
goog.require('ol.sphere.NORMAL');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.control.ScaleLineProperty = {
|
||||
UNITS: 'units'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Units for the scale line. Supported values are `'degrees'`, `'imperial'`,
|
||||
* `'nautical'`, `'metric'`, `'us'`.
|
||||
* @enum {string}
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ScaleLineUnits = {
|
||||
DEGREES: 'degrees',
|
||||
IMPERIAL: 'imperial',
|
||||
NAUTICAL: 'nautical',
|
||||
METRIC: 'metric',
|
||||
US: 'us'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control displaying rough x-axis distances, calculated for the center of the
|
||||
* viewport.
|
||||
* No scale line will be shown when the x-axis distance cannot be calculated in
|
||||
* the view projection (e.g. at or beyond the poles in EPSG:4326).
|
||||
* By default the scale line will show in the bottom left portion of the map,
|
||||
* but this can be changed by using the css selector `.ol-scale-line`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.ScaleLineOptions=} opt_options Scale line options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ScaleLine = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-scale-line';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
className + '-inner');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.element_ = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
className + ' ' + ol.css.CLASS_UNSELECTABLE, this.innerElement_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?olx.ViewState}
|
||||
*/
|
||||
this.viewState_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.renderedWidth_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = '';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?ol.TransformFunction}
|
||||
*/
|
||||
this.toEPSG4326_ = null;
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.ScaleLine.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: this.element_,
|
||||
render: render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangeEventType(ol.control.ScaleLineProperty.UNITS),
|
||||
this.handleUnitsChanged_, false, this);
|
||||
|
||||
this.setUnits(/** @type {ol.control.ScaleLineUnits} */ (options.units) ||
|
||||
ol.control.ScaleLineUnits.METRIC);
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.ScaleLine, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5];
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.control.ScaleLineUnits|undefined} The units to use in the scale
|
||||
* line.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ScaleLine.prototype.getUnits = function() {
|
||||
return /** @type {ol.control.ScaleLineUnits|undefined} */ (
|
||||
this.get(ol.control.ScaleLineProperty.UNITS));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.ScaleLine.prototype,
|
||||
'getUnits',
|
||||
ol.control.ScaleLine.prototype.getUnits);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.ScaleLine}
|
||||
* @api
|
||||
*/
|
||||
ol.control.ScaleLine.render = function(mapEvent) {
|
||||
var frameState = mapEvent.frameState;
|
||||
if (goog.isNull(frameState)) {
|
||||
this.viewState_ = null;
|
||||
} else {
|
||||
this.viewState_ = frameState.viewState;
|
||||
}
|
||||
this.updateElement_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.ScaleLine.prototype.handleUnitsChanged_ = function() {
|
||||
this.updateElement_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.control.ScaleLineUnits} units The units to use in the scale line.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ScaleLine.prototype.setUnits = function(units) {
|
||||
this.set(ol.control.ScaleLineProperty.UNITS, units);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.control.ScaleLine.prototype,
|
||||
'setUnits',
|
||||
ol.control.ScaleLine.prototype.setUnits);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.ScaleLine.prototype.updateElement_ = function() {
|
||||
var viewState = this.viewState_;
|
||||
|
||||
if (goog.isNull(viewState)) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.setElementShown(this.element_, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var center = viewState.center;
|
||||
var projection = viewState.projection;
|
||||
var pointResolution =
|
||||
projection.getPointResolution(viewState.resolution, center);
|
||||
var projectionUnits = projection.getUnits();
|
||||
|
||||
var cosLatitude;
|
||||
var units = this.getUnits();
|
||||
if (projectionUnits == ol.proj.Units.DEGREES &&
|
||||
(units == ol.control.ScaleLineUnits.METRIC ||
|
||||
units == ol.control.ScaleLineUnits.IMPERIAL ||
|
||||
units == ol.control.ScaleLineUnits.US ||
|
||||
units == ol.control.ScaleLineUnits.NAUTICAL)) {
|
||||
|
||||
// Convert pointResolution from degrees to meters
|
||||
this.toEPSG4326_ = null;
|
||||
cosLatitude = Math.cos(goog.math.toRadians(center[1]));
|
||||
pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
|
||||
projectionUnits = ol.proj.Units.METERS;
|
||||
|
||||
} else if (projectionUnits != ol.proj.Units.DEGREES &&
|
||||
units == ol.control.ScaleLineUnits.DEGREES) {
|
||||
|
||||
// Convert pointResolution from other units to degrees
|
||||
if (goog.isNull(this.toEPSG4326_)) {
|
||||
this.toEPSG4326_ = ol.proj.getTransformFromProjections(
|
||||
projection, ol.proj.get('EPSG:4326'));
|
||||
}
|
||||
cosLatitude = Math.cos(goog.math.toRadians(this.toEPSG4326_(center)[1]));
|
||||
var radius = ol.sphere.NORMAL.radius;
|
||||
goog.asserts.assert(goog.isDef(ol.proj.METERS_PER_UNIT[projectionUnits]));
|
||||
radius /= ol.proj.METERS_PER_UNIT[projectionUnits];
|
||||
pointResolution *= 180 / (Math.PI * cosLatitude * radius);
|
||||
projectionUnits = ol.proj.Units.DEGREES;
|
||||
|
||||
} else {
|
||||
this.toEPSG4326_ = null;
|
||||
}
|
||||
|
||||
goog.asserts.assert(
|
||||
((units == ol.control.ScaleLineUnits.METRIC ||
|
||||
units == ol.control.ScaleLineUnits.IMPERIAL ||
|
||||
units == ol.control.ScaleLineUnits.US ||
|
||||
units == ol.control.ScaleLineUnits.NAUTICAL) &&
|
||||
projectionUnits == ol.proj.Units.METERS) ||
|
||||
(units == ol.control.ScaleLineUnits.DEGREES &&
|
||||
projectionUnits == ol.proj.Units.DEGREES));
|
||||
|
||||
var nominalCount = this.minWidth_ * pointResolution;
|
||||
var suffix = '';
|
||||
if (units == ol.control.ScaleLineUnits.DEGREES) {
|
||||
if (nominalCount < 1 / 60) {
|
||||
suffix = '\u2033'; // seconds
|
||||
pointResolution *= 3600;
|
||||
} else if (nominalCount < 1) {
|
||||
suffix = '\u2032'; // minutes
|
||||
pointResolution *= 60;
|
||||
} else {
|
||||
suffix = '\u00b0'; // degrees
|
||||
}
|
||||
} else if (units == ol.control.ScaleLineUnits.IMPERIAL) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution /= 0.0254;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.3048;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.344;
|
||||
}
|
||||
} else if (units == ol.control.ScaleLineUnits.NAUTICAL) {
|
||||
pointResolution /= 1852;
|
||||
suffix = 'nm';
|
||||
} else if (units == ol.control.ScaleLineUnits.METRIC) {
|
||||
if (nominalCount < 1) {
|
||||
suffix = 'mm';
|
||||
pointResolution *= 1000;
|
||||
} else if (nominalCount < 1000) {
|
||||
suffix = 'm';
|
||||
} else {
|
||||
suffix = 'km';
|
||||
pointResolution /= 1000;
|
||||
}
|
||||
} else if (units == ol.control.ScaleLineUnits.US) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution *= 39.37;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.30480061;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.3472;
|
||||
}
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
}
|
||||
|
||||
var i = 3 * Math.floor(
|
||||
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
|
||||
var count, width;
|
||||
while (true) {
|
||||
count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] *
|
||||
Math.pow(10, Math.floor(i / 3));
|
||||
width = Math.round(count / pointResolution);
|
||||
if (isNaN(width)) {
|
||||
goog.style.setElementShown(this.element_, false);
|
||||
this.renderedVisible_ = false;
|
||||
return;
|
||||
} else if (width >= this.minWidth_) {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
var html = count + ' ' + suffix;
|
||||
if (this.renderedHTML_ != html) {
|
||||
this.innerElement_.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
|
||||
if (this.renderedWidth_ != width) {
|
||||
this.innerElement_.style.width = width + 'px';
|
||||
this.renderedWidth_ = width;
|
||||
}
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
goog.style.setElementShown(this.element_, true);
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
goog.provide('ol.control.Zoom');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.animation');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.easing');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control with 2 buttons, one for zoom in and one for zoom out.
|
||||
* This control is one of the default controls of a map. To style this control
|
||||
* use css selectors `.ol-zoom-in` and `.ol-zoom-out`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.ZoomOptions=} opt_options Zoom options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.Zoom = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
var className = goog.isDef(options.className) ? options.className : 'ol-zoom';
|
||||
|
||||
var delta = goog.isDef(options.delta) ? options.delta : 1;
|
||||
|
||||
var zoomInLabel = goog.isDef(options.zoomInLabel) ?
|
||||
options.zoomInLabel : '+';
|
||||
var zoomOutLabel = goog.isDef(options.zoomOutLabel) ?
|
||||
options.zoomOutLabel : '\u2212';
|
||||
|
||||
var zoomInTipLabel = goog.isDef(options.zoomInTipLabel) ?
|
||||
options.zoomInTipLabel : 'Zoom in';
|
||||
var zoomOutTipLabel = goog.isDef(options.zoomOutTipLabel) ?
|
||||
options.zoomOutTipLabel : 'Zoom out';
|
||||
|
||||
var inElement = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'class': className + '-in',
|
||||
'type' : 'button',
|
||||
'title': zoomInTipLabel
|
||||
}, zoomInLabel);
|
||||
|
||||
goog.events.listen(inElement,
|
||||
goog.events.EventType.CLICK, goog.partial(
|
||||
ol.control.Zoom.prototype.handleClick_, delta), false, this);
|
||||
|
||||
goog.events.listen(inElement, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var outElement = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'class': className + '-out',
|
||||
'type' : 'button',
|
||||
'title': zoomOutTipLabel
|
||||
}, zoomOutLabel);
|
||||
|
||||
goog.events.listen(outElement,
|
||||
goog.events.EventType.CLICK, goog.partial(
|
||||
ol.control.Zoom.prototype.handleClick_, -delta), false, this);
|
||||
|
||||
goog.events.listen(outElement, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL;
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, inElement,
|
||||
outElement);
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = goog.isDef(options.duration) ? options.duration : 250;
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Zoom, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.Zoom.prototype.handleClick_ = function(delta, event) {
|
||||
event.preventDefault();
|
||||
this.zoomByDelta_(delta);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @private
|
||||
*/
|
||||
ol.control.Zoom.prototype.zoomByDelta_ = function(delta) {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
if (goog.isNull(view)) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
var currentResolution = view.getResolution();
|
||||
if (goog.isDef(currentResolution)) {
|
||||
if (this.duration_ > 0) {
|
||||
map.beforeRender(ol.animation.zoom({
|
||||
resolution: currentResolution,
|
||||
duration: this.duration_,
|
||||
easing: ol.easing.easeOut
|
||||
}));
|
||||
}
|
||||
var newResolution = view.constrainResolution(currentResolution, delta);
|
||||
view.setResolution(newResolution);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,327 @@
|
||||
// FIXME should possibly show tooltip when dragging?
|
||||
|
||||
goog.provide('ol.control.ZoomSlider');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
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.fx.DragDropEvent');
|
||||
goog.require('goog.fx.Dragger');
|
||||
goog.require('goog.fx.Dragger.EventType');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Rect');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.animation');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.easing');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A slider type of control for zooming.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* map.addControl(new ol.control.ZoomSlider());
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.ZoomSliderOptions=} opt_options Zoom slider options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ZoomSlider = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.currentResolution_ = undefined;
|
||||
|
||||
/**
|
||||
* The direction of the slider. Will be determined from actual display of the
|
||||
* container and defaults to ol.control.ZoomSlider.direction.VERTICAL.
|
||||
*
|
||||
* @type {ol.control.ZoomSlider.direction}
|
||||
* @private
|
||||
*/
|
||||
this.direction_ = ol.control.ZoomSlider.direction.VERTICAL;
|
||||
|
||||
/**
|
||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||
* is called.
|
||||
* @type {ol.Size}
|
||||
* @private
|
||||
*/
|
||||
this.thumbSize_ = null;
|
||||
|
||||
/**
|
||||
* Whether the slider is initialized.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.sliderInitialized_ = false;
|
||||
|
||||
var className = goog.isDef(options.className) ?
|
||||
options.className : 'ol-zoomslider';
|
||||
var thumbElement = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
[className + '-thumb', ol.css.CLASS_UNSELECTABLE]);
|
||||
var containerElement = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
[className, ol.css.CLASS_UNSELECTABLE, ol.css.CLASS_CONTROL],
|
||||
thumbElement);
|
||||
|
||||
/**
|
||||
* @type {goog.fx.Dragger}
|
||||
* @private
|
||||
*/
|
||||
this.dragger_ = new goog.fx.Dragger(thumbElement);
|
||||
this.registerDisposable(this.dragger_);
|
||||
|
||||
goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
|
||||
this.handleDraggerStart_, false, this);
|
||||
goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
|
||||
this.handleDraggerDrag_, false, this);
|
||||
goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
|
||||
this.handleDraggerEnd_, false, this);
|
||||
|
||||
goog.events.listen(containerElement, goog.events.EventType.CLICK,
|
||||
this.handleContainerClick_, false, this);
|
||||
goog.events.listen(thumbElement, goog.events.EventType.CLICK,
|
||||
goog.events.Event.stopPropagation);
|
||||
|
||||
var render = goog.isDef(options.render) ?
|
||||
options.render : ol.control.ZoomSlider.render;
|
||||
|
||||
goog.base(this, {
|
||||
element: containerElement,
|
||||
render: render
|
||||
});
|
||||
};
|
||||
goog.inherits(ol.control.ZoomSlider, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* The enum for available directions.
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.control.ZoomSlider.direction = {
|
||||
VERTICAL: 0,
|
||||
HORIZONTAL: 1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.setMap = function(map) {
|
||||
goog.base(this, 'setMap', map);
|
||||
if (!goog.isNull(map)) {
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the slider element. This will determine and set this controls
|
||||
* direction_ and also constrain the dragging of the thumb to always be within
|
||||
* the bounds of the container.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.initSlider_ = function() {
|
||||
var container = this.element;
|
||||
var containerSize = goog.style.getSize(container);
|
||||
|
||||
var thumb = goog.dom.getFirstElementChild(container);
|
||||
var thumbMargins = goog.style.getMarginBox(thumb);
|
||||
var thumbBorderBoxSize = goog.style.getBorderBoxSize(thumb);
|
||||
var thumbWidth = thumbBorderBoxSize.width +
|
||||
thumbMargins.right + thumbMargins.left;
|
||||
var thumbHeight = thumbBorderBoxSize.height +
|
||||
thumbMargins.top + thumbMargins.bottom;
|
||||
this.thumbSize_ = [thumbWidth, thumbHeight];
|
||||
|
||||
var width = containerSize.width - thumbWidth;
|
||||
var height = containerSize.height - thumbHeight;
|
||||
|
||||
var limits;
|
||||
if (containerSize.width > containerSize.height) {
|
||||
this.direction_ = ol.control.ZoomSlider.direction.HORIZONTAL;
|
||||
limits = new goog.math.Rect(0, 0, width, 0);
|
||||
} else {
|
||||
this.direction_ = ol.control.ZoomSlider.direction.VERTICAL;
|
||||
limits = new goog.math.Rect(0, 0, 0, height);
|
||||
}
|
||||
this.dragger_.setLimits(limits);
|
||||
this.sliderInitialized_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapEvent} mapEvent Map event.
|
||||
* @this {ol.control.ZoomSlider}
|
||||
* @api
|
||||
*/
|
||||
ol.control.ZoomSlider.render = function(mapEvent) {
|
||||
if (goog.isNull(mapEvent.frameState)) {
|
||||
return;
|
||||
}
|
||||
goog.asserts.assert(goog.isDefAndNotNull(mapEvent.frameState.viewState));
|
||||
if (!this.sliderInitialized_) {
|
||||
this.initSlider_();
|
||||
}
|
||||
var res = mapEvent.frameState.viewState.resolution;
|
||||
if (res !== this.currentResolution_) {
|
||||
this.currentResolution_ = res;
|
||||
this.setThumbPosition_(res);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent The browser event to handle.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleContainerClick_ = function(browserEvent) {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
var currentResolution = view.getResolution();
|
||||
goog.asserts.assert(goog.isDef(currentResolution));
|
||||
map.beforeRender(ol.animation.zoom({
|
||||
resolution: currentResolution,
|
||||
duration: ol.ZOOMSLIDER_ANIMATION_DURATION,
|
||||
easing: ol.easing.easeOut
|
||||
}));
|
||||
var relativePosition = this.getRelativePosition_(
|
||||
browserEvent.offsetX - this.thumbSize_[0] / 2,
|
||||
browserEvent.offsetY - this.thumbSize_[1] / 2);
|
||||
var resolution = this.getResolutionForPosition_(relativePosition);
|
||||
view.setResolution(view.constrainResolution(resolution));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger start events.
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerStart_ = function(event) {
|
||||
this.getMap().getView().setHint(ol.ViewHint.INTERACTING, 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
|
||||
var relativePosition = this.getRelativePosition_(event.left, event.top);
|
||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||
this.getMap().getView().setResolution(this.currentResolution_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger end events.
|
||||
* @param {goog.fx.DragDropEvent} event The dragdropevent.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
goog.asserts.assert(goog.isDef(this.currentResolution_));
|
||||
map.beforeRender(ol.animation.zoom({
|
||||
resolution: this.currentResolution_,
|
||||
duration: ol.ZOOMSLIDER_ANIMATION_DURATION,
|
||||
easing: ol.easing.easeOut
|
||||
}));
|
||||
var resolution = view.constrainResolution(this.currentResolution_);
|
||||
view.setResolution(resolution);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Positions the thumb inside its container according to the given resolution.
|
||||
*
|
||||
* @param {number} res The res.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.setThumbPosition_ = function(res) {
|
||||
var position = this.getPositionForResolution_(res);
|
||||
var dragger = this.dragger_;
|
||||
var thumb = goog.dom.getFirstElementChild(this.element);
|
||||
|
||||
if (this.direction_ == ol.control.ZoomSlider.direction.HORIZONTAL) {
|
||||
var left = dragger.limits.left + dragger.limits.width * position;
|
||||
goog.style.setPosition(thumb, left);
|
||||
} else {
|
||||
var top = dragger.limits.top + dragger.limits.height * position;
|
||||
goog.style.setPosition(thumb, dragger.limits.left, top);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the relative position of the thumb given x and y offsets. The
|
||||
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
||||
* in pixel units within the dragger limits.
|
||||
*
|
||||
* @param {number} x Pixel position relative to the left of the slider.
|
||||
* @param {number} y Pixel position relative to the top of the slider.
|
||||
* @return {number} The relative position of the thumb.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
|
||||
var draggerLimits = this.dragger_.limits;
|
||||
var amount;
|
||||
if (this.direction_ === ol.control.ZoomSlider.direction.HORIZONTAL) {
|
||||
amount = (x - draggerLimits.left) / draggerLimits.width;
|
||||
} else {
|
||||
amount = (y - draggerLimits.top) / draggerLimits.height;
|
||||
}
|
||||
return goog.math.clamp(amount, 0, 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the corresponding resolution of the thumb given its relative
|
||||
* position (where 0 is the minimum and 1 is the maximum).
|
||||
*
|
||||
* @param {number} position The relative position of the thumb.
|
||||
* @return {number} The corresponding resolution.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.getResolutionForPosition_ = function(position) {
|
||||
var fn = this.getMap().getView().getResolutionForValueFunction();
|
||||
return fn(1 - position);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines the relative position of the slider for the given resolution. A
|
||||
* relative position of 0 corresponds to the minimum view resolution. A
|
||||
* relative position of 1 corresponds to the maximum view resolution.
|
||||
*
|
||||
* @param {number} res The resolution.
|
||||
* @return {number} The relative position value (between 0 and 1).
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.getPositionForResolution_ = function(res) {
|
||||
var fn = this.getMap().getView().getValueForResolutionFunction();
|
||||
return 1 - fn(res);
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
goog.provide('ol.control.ZoomToExtent');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A button control which, when pressed, changes the map view to a specific
|
||||
* extent. To style this control use the css selector `.ol-zoom-extent`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {olx.control.ZoomToExtentOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.control.ZoomToExtent = function(opt_options) {
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
* @private
|
||||
*/
|
||||
this.extent_ = goog.isDef(options.extent) ? options.extent : null;
|
||||
|
||||
var className = goog.isDef(options.className) ? options.className :
|
||||
'ol-zoom-extent';
|
||||
|
||||
var label = goog.isDef(options.label) ? options.label : 'E';
|
||||
var tipLabel = goog.isDef(options.tipLabel) ?
|
||||
options.tipLabel : 'Fit to extent';
|
||||
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
|
||||
'type': 'button',
|
||||
'title': tipLabel
|
||||
}, label);
|
||||
|
||||
goog.events.listen(button, goog.events.EventType.CLICK,
|
||||
this.handleClick_, false, this);
|
||||
|
||||
goog.events.listen(button, [
|
||||
goog.events.EventType.MOUSEOUT,
|
||||
goog.events.EventType.FOCUSOUT
|
||||
], function() {
|
||||
this.blur();
|
||||
}, false);
|
||||
|
||||
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
|
||||
ol.css.CLASS_CONTROL;
|
||||
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button);
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
};
|
||||
goog.inherits(ol.control.ZoomToExtent, ol.control.Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomToExtent.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleZoomToExtent_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
|
||||
var map = this.getMap();
|
||||
var view = map.getView();
|
||||
var extent = goog.isNull(this.extent_) ?
|
||||
view.getProjection().getExtent() : this.extent_;
|
||||
var size = map.getSize();
|
||||
goog.asserts.assert(goog.isDef(size));
|
||||
view.fitExtent(extent, size);
|
||||
};
|
||||
@@ -0,0 +1,349 @@
|
||||
goog.provide('ol.Coordinate');
|
||||
goog.provide('ol.CoordinateFormatType');
|
||||
goog.provide('ol.coordinate');
|
||||
|
||||
goog.require('goog.math');
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes a {@link ol.Coordinate} and transforms it into a
|
||||
* `{string}`.
|
||||
*
|
||||
* @typedef {function((ol.Coordinate|undefined)): string}
|
||||
* @api stable
|
||||
*/
|
||||
ol.CoordinateFormatType;
|
||||
|
||||
|
||||
/**
|
||||
* An array of numbers representing an xy coordinate. Example: `[16, 48]`.
|
||||
* @typedef {Array.<number>} ol.Coordinate
|
||||
* @api stable
|
||||
*/
|
||||
ol.Coordinate;
|
||||
|
||||
|
||||
/**
|
||||
* Add `delta` to `coordinate`. `coordinate` is modified in place and returned
|
||||
* by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* ol.coordinate.add(coord, [-2, 4]);
|
||||
* // coord is now [5.85, 51.983333]
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.Coordinate} delta Delta.
|
||||
* @return {ol.Coordinate} The input coordinate adjusted by the given delta.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.add = function(coordinate, delta) {
|
||||
coordinate[0] += delta[0];
|
||||
coordinate[1] += delta[1];
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the point closest to the passed coordinate on the passed segment.
|
||||
* This is the foot of the perpendicular of the coordinate to the segment when
|
||||
* the foot is on the segment, or the closest segment coordinate when the foot
|
||||
* is outside the segment.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate The coordinate.
|
||||
* @param {Array.<ol.Coordinate>} segment The two coordinates of the segment.
|
||||
* @return {ol.Coordinate} The foot of the perpendicular of the coordinate to
|
||||
* the segment.
|
||||
*/
|
||||
ol.coordinate.closestOnSegment = function(coordinate, segment) {
|
||||
var x0 = coordinate[0];
|
||||
var y0 = coordinate[1];
|
||||
var start = segment[0];
|
||||
var end = segment[1];
|
||||
var x1 = start[0];
|
||||
var y1 = start[1];
|
||||
var x2 = end[0];
|
||||
var y2 = end[1];
|
||||
var dx = x2 - x1;
|
||||
var dy = y2 - y1;
|
||||
var along = (dx === 0 && dy === 0) ? 0 :
|
||||
((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0);
|
||||
var x, y;
|
||||
if (along <= 0) {
|
||||
x = x1;
|
||||
y = y1;
|
||||
} else if (along >= 1) {
|
||||
x = x2;
|
||||
y = y2;
|
||||
} else {
|
||||
x = x1 + along * dx;
|
||||
y = y1 + along * dy;
|
||||
}
|
||||
return [x, y];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link ol.CoordinateFormatType} function that can be used to format
|
||||
* a {ol.Coordinate} to a string.
|
||||
*
|
||||
* Example without specifying the fractional digits:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var stringifyFunc = ol.coordinate.createStringXY();
|
||||
* var out = stringifyFunc(coord);
|
||||
* // out is now '8, 48'
|
||||
*
|
||||
* Example with explicitly specifying 2 fractional digits:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var stringifyFunc = ol.coordinate.createStringXY(2);
|
||||
* var out = stringifyFunc(coord);
|
||||
* // out is now '7.85, 47.98'
|
||||
*
|
||||
* @param {number=} opt_fractionDigits The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {ol.CoordinateFormatType} Coordinate format.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.createStringXY = function(opt_fractionDigits) {
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} coordinate Coordinate.
|
||||
* @return {string} String XY.
|
||||
*/
|
||||
function(coordinate) {
|
||||
return ol.coordinate.toStringXY(coordinate, opt_fractionDigits);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} degrees Degrees.
|
||||
* @param {string} hemispheres Hemispheres.
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.coordinate.degreesToStringHDMS_ = 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);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Transforms the given {@link ol.Coordinate} to a string using the given string
|
||||
* template. The strings `{x}` and `{y}` in the template will be replaced with
|
||||
* the first and second coordinate values respectively.
|
||||
*
|
||||
* Example without specifying the fractional digits:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var template = 'Coordinate is ({x}|{y}).';
|
||||
* var out = ol.coordinate.format(coord, template);
|
||||
* // out is now 'Coordinate is (8|48).'
|
||||
*
|
||||
* Example explicitly specifying the fractional digits:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var template = 'Coordinate is ({x}|{y}).';
|
||||
* var out = ol.coordinate.format(coord, template, 2);
|
||||
* // out is now 'Coordinate is (7.85|47.98).'
|
||||
*
|
||||
* @param {ol.Coordinate|undefined} coordinate Coordinate.
|
||||
* @param {string} template A template string with `{x}` and `{y}` placeholders
|
||||
* that will be replaced by first and second coordinate values.
|
||||
* @param {number=} opt_fractionDigits The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} Formatted coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.format = function(coordinate, template, opt_fractionDigits) {
|
||||
if (goog.isDef(coordinate)) {
|
||||
return template
|
||||
.replace('{x}', coordinate[0].toFixed(opt_fractionDigits))
|
||||
.replace('{y}', coordinate[1].toFixed(opt_fractionDigits));
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate1 First coordinate.
|
||||
* @param {ol.Coordinate} coordinate2 Second coordinate.
|
||||
* @return {boolean} Whether the passed coordinates are equal.
|
||||
*/
|
||||
ol.coordinate.equals = function(coordinate1, coordinate2) {
|
||||
var equals = true;
|
||||
for (var i = coordinate1.length - 1; i >= 0; --i) {
|
||||
if (coordinate1[i] != coordinate2[i]) {
|
||||
equals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equals;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rotate `coordinate` by `angle`. `coordinate` is modified in place and
|
||||
* returned by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var rotateRadians = Math.PI / 2; // 90 degrees
|
||||
* ol.coordinate.rotate(coord, rotateRadians);
|
||||
* // coord is now [-47.983333, 7.85]
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} angle Angle in radian.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.rotate = function(coordinate, angle) {
|
||||
var cosAngle = Math.cos(angle);
|
||||
var sinAngle = Math.sin(angle);
|
||||
var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
|
||||
var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
|
||||
coordinate[0] = x;
|
||||
coordinate[1] = y;
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
|
||||
* by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var scale = 1.2;
|
||||
* ol.coordinate.scale(coord, scale);
|
||||
* // coord is now [9.42, 57.5799996]
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} scale Scale factor.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.coordinate.scale = function(coordinate, scale) {
|
||||
coordinate[0] *= scale;
|
||||
coordinate[1] *= scale;
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subtract `delta` to `coordinate`. `coordinate` is modified in place and
|
||||
* returned by the function.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.Coordinate} delta Delta.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.coordinate.sub = function(coordinate, delta) {
|
||||
coordinate[0] -= delta[0];
|
||||
coordinate[1] -= delta[1];
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coord1 First coordinate.
|
||||
* @param {ol.Coordinate} coord2 Second coordinate.
|
||||
* @return {number} Squared distance between coord1 and coord2.
|
||||
*/
|
||||
ol.coordinate.squaredDistance = function(coord1, coord2) {
|
||||
var dx = coord1[0] - coord2[0];
|
||||
var dy = coord1[1] - coord2[1];
|
||||
return dx * dx + dy * dy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the squared distance from a coordinate to a line segment.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate of the point.
|
||||
* @param {Array.<ol.Coordinate>} segment Line segment (2 coordinates).
|
||||
* @return {number} Squared distance from the point to the line segment.
|
||||
*/
|
||||
ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
|
||||
return ol.coordinate.squaredDistance(coordinate,
|
||||
ol.coordinate.closestOnSegment(coordinate, segment));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Example:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = ol.coordinate.toStringHDMS(coord);
|
||||
* // out is now '47° 59′ 0″ N 7° 51′ 0″ E'
|
||||
*
|
||||
* @param {ol.Coordinate|undefined} coordinate Coordinate.
|
||||
* @return {string} Hemisphere, degrees, minutes and seconds.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.toStringHDMS = function(coordinate) {
|
||||
if (goog.isDef(coordinate)) {
|
||||
return ol.coordinate.degreesToStringHDMS_(coordinate[1], 'NS') + ' ' +
|
||||
ol.coordinate.degreesToStringHDMS_(coordinate[0], 'EW');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Example without specifying fractional digits:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = ol.coordinate.toStringXY(coord);
|
||||
* // out is now '8, 48'
|
||||
*
|
||||
* Example explicitly specifying 1 fractional digit:
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = ol.coordinate.toStringXY(coord, 1);
|
||||
* // out is now '7.8, 48.0'
|
||||
*
|
||||
* @param {ol.Coordinate|undefined} coordinate Coordinate.
|
||||
* @param {number=} opt_fractionDigits The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} XY.
|
||||
* @api stable
|
||||
*/
|
||||
ol.coordinate.toStringXY = function(coordinate, opt_fractionDigits) {
|
||||
return ol.coordinate.format(coordinate, '{x}, {y}', opt_fractionDigits);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an ol.Coordinate from an Array and take into account axis order.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* var northCoord = ol.coordinate.fromProjectedArray([1, 2], 'n');
|
||||
* // northCoord is now [2, 1]
|
||||
*
|
||||
* var eastCoord = ol.coordinate.fromProjectedArray([1, 2], 'e');
|
||||
* // eastCoord is now [1, 2]
|
||||
*
|
||||
* @param {Array} array The array with coordinates.
|
||||
* @param {string} axis the axis info.
|
||||
* @return {ol.Coordinate} The coordinate created.
|
||||
*/
|
||||
ol.coordinate.fromProjectedArray = function(array, axis) {
|
||||
var firstAxis = axis.charAt(0);
|
||||
if (firstAxis === 'n' || firstAxis === 's') {
|
||||
return [array[1], array[0]];
|
||||
} else {
|
||||
return array;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.coordinate
|
||||
*/
|
||||
@@ -0,0 +1,37 @@
|
||||
goog.provide('ol.css');
|
||||
|
||||
|
||||
/**
|
||||
* The CSS class for hidden feature.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.css.CLASS_HIDDEN = 'ol-hidden';
|
||||
|
||||
|
||||
/**
|
||||
* The CSS class that we'll give the DOM elements to have them unselectable.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.css.CLASS_UNSELECTABLE = 'ol-unselectable';
|
||||
|
||||
|
||||
/**
|
||||
* The CSS class for unsupported feature.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.css.CLASS_UNSUPPORTED = 'ol-unsupported';
|
||||
|
||||
|
||||
/**
|
||||
* The CSS class for controls.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.css.CLASS_CONTROL = 'ol-control';
|
||||
@@ -0,0 +1,250 @@
|
||||
goog.provide('ol.DeviceOrientation');
|
||||
goog.provide('ol.DeviceOrientationProperty');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.has');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.DeviceOrientationProperty = {
|
||||
ALPHA: 'alpha',
|
||||
BETA: 'beta',
|
||||
GAMMA: 'gamma',
|
||||
HEADING: 'heading',
|
||||
TRACKING: 'tracking'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The ol.DeviceOrientation class provides access to DeviceOrientation
|
||||
* information and events, see the [HTML 5 DeviceOrientation Specification](
|
||||
* http://www.w3.org/TR/orientation-event/) for more details.
|
||||
*
|
||||
* Many new computers, and especially mobile phones
|
||||
* and tablets, provide hardware support for device orientation. Web
|
||||
* developers targeting mobile devices will be especially interested in this
|
||||
* class.
|
||||
*
|
||||
* Device orientation data are relative to a common starting point. For mobile
|
||||
* devices, the starting point is to lay your phone face up on a table with the
|
||||
* top of the phone pointing north. This represents the zero state. All
|
||||
* angles are then relative to this state. For computers, it is the same except
|
||||
* the screen is open at 90 degrees.
|
||||
*
|
||||
* Device orientation is reported as three angles - `alpha`, `beta`, and
|
||||
* `gamma` - relative to the starting position along the three planar axes X, Y
|
||||
* and Z. The X axis runs from the left edge to the right edge through the
|
||||
* middle of the device. Similarly, the Y axis runs from the bottom to the top
|
||||
* of the device through the middle. The Z axis runs from the back to the front
|
||||
* through the middle. In the starting position, the X axis points to the
|
||||
* right, the Y axis points away from you and the Z axis points straight up
|
||||
* from the device lying flat.
|
||||
*
|
||||
* The three angles representing the device orientation are relative to the
|
||||
* three axes. `alpha` indicates how much the device has been rotated around the
|
||||
* Z axis, which is commonly interpreted as the compass heading (see note
|
||||
* below). `beta` indicates how much the device has been rotated around the X
|
||||
* axis, or how much it is tilted from front to back. `gamma` indicates how
|
||||
* much the device has been rotated around the Y axis, or how much it is tilted
|
||||
* from left to right.
|
||||
*
|
||||
* For most browsers, the `alpha` value returns the compass heading so if the
|
||||
* device points north, it will be 0. With Safari on iOS, the 0 value of
|
||||
* `alpha` is calculated from when device orientation was first requested.
|
||||
* ol.DeviceOrientation provides the `heading` property which normalizes this
|
||||
* behavior across all browsers for you.
|
||||
*
|
||||
* It is important to note that the HTML 5 DeviceOrientation specification
|
||||
* indicates that `alpha`, `beta` and `gamma` are in degrees while the
|
||||
* equivalent properties in ol.DeviceOrientation are in radians for consistency
|
||||
* with all other uses of angles throughout OpenLayers.
|
||||
*
|
||||
* @see http://www.w3.org/TR/orientation-event/
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the device orientation changes.
|
||||
* @param {olx.DeviceOrientationOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation = function(opt_options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.listenerKey_ = null;
|
||||
|
||||
goog.events.listen(this,
|
||||
ol.Object.getChangeEventType(ol.DeviceOrientationProperty.TRACKING),
|
||||
this.handleTrackingChanged_, false, this);
|
||||
|
||||
this.setTracking(goog.isDef(options.tracking) ? options.tracking : false);
|
||||
|
||||
};
|
||||
goog.inherits(ol.DeviceOrientation, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.disposeInternal = function() {
|
||||
this.setTracking(false);
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent Event.
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.orientationChange_ = function(browserEvent) {
|
||||
var event = /** @type {DeviceOrientationEvent} */
|
||||
(browserEvent.getBrowserEvent());
|
||||
if (goog.isDefAndNotNull(event.alpha)) {
|
||||
var alpha = goog.math.toRadians(event.alpha);
|
||||
this.set(ol.DeviceOrientationProperty.ALPHA, alpha);
|
||||
// event.absolute is undefined in iOS.
|
||||
if (goog.isBoolean(event.absolute) && event.absolute) {
|
||||
this.set(ol.DeviceOrientationProperty.HEADING, alpha);
|
||||
} else if (goog.isDefAndNotNull(event.webkitCompassHeading) &&
|
||||
goog.isDefAndNotNull(event.webkitCompassAccuracy) &&
|
||||
event.webkitCompassAccuracy != -1) {
|
||||
var heading = goog.math.toRadians(event.webkitCompassHeading);
|
||||
this.set(ol.DeviceOrientationProperty.HEADING, heading);
|
||||
}
|
||||
}
|
||||
if (goog.isDefAndNotNull(event.beta)) {
|
||||
this.set(ol.DeviceOrientationProperty.BETA,
|
||||
goog.math.toRadians(event.beta));
|
||||
}
|
||||
if (goog.isDefAndNotNull(event.gamma)) {
|
||||
this.set(ol.DeviceOrientationProperty.GAMMA,
|
||||
goog.math.toRadians(event.gamma));
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} The euler angle in radians of the device from the
|
||||
* standard Z axis.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.getAlpha = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.DeviceOrientationProperty.ALPHA));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'getAlpha',
|
||||
ol.DeviceOrientation.prototype.getAlpha);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} The euler angle in radians of the device from the
|
||||
* planar X axis.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.getBeta = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.DeviceOrientationProperty.BETA));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'getBeta',
|
||||
ol.DeviceOrientation.prototype.getBeta);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} The euler angle in radians of the device from the
|
||||
* planar Y axis.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.getGamma = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.DeviceOrientationProperty.GAMMA));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'getGamma',
|
||||
ol.DeviceOrientation.prototype.getGamma);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|undefined} The heading of the device relative to north, in
|
||||
* radians, normalizing for different browser behavior.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.getHeading = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.DeviceOrientationProperty.HEADING));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'getHeading',
|
||||
ol.DeviceOrientation.prototype.getHeading);
|
||||
|
||||
|
||||
/**
|
||||
* Are we tracking the device's orientation?
|
||||
* @return {boolean} The status of tracking changes to alpha, beta and gamma.
|
||||
* If true, changes are tracked and reported immediately.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.getTracking = function() {
|
||||
return /** @type {boolean} */ (
|
||||
this.get(ol.DeviceOrientationProperty.TRACKING));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'getTracking',
|
||||
ol.DeviceOrientation.prototype.getTracking);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.handleTrackingChanged_ = function() {
|
||||
if (ol.has.DEVICE_ORIENTATION) {
|
||||
var tracking = this.getTracking();
|
||||
if (tracking && goog.isNull(this.listenerKey_)) {
|
||||
this.listenerKey_ = goog.events.listen(goog.global, 'deviceorientation',
|
||||
this.orientationChange_, false, this);
|
||||
} else if (!tracking && !goog.isNull(this.listenerKey_)) {
|
||||
goog.events.unlistenByKey(this.listenerKey_);
|
||||
this.listenerKey_ = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable tracking of DeviceOrientation events.
|
||||
* @param {boolean} tracking The status of tracking changes to alpha, beta and
|
||||
* gamma. If true, changes are tracked and reported immediately.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.DeviceOrientation.prototype.setTracking = function(tracking) {
|
||||
this.set(ol.DeviceOrientationProperty.TRACKING, tracking);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.DeviceOrientation.prototype,
|
||||
'setTracking',
|
||||
ol.DeviceOrientation.prototype.setTracking);
|
||||
@@ -0,0 +1,332 @@
|
||||
// FIXME add tests for browser features (Modernizr?)
|
||||
|
||||
goog.provide('ol.dom');
|
||||
goog.provide('ol.dom.BrowserFeature');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.userAgent');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol');
|
||||
|
||||
|
||||
/**
|
||||
* Create an html canvas element and returns its 2d context.
|
||||
* @param {number=} opt_width Canvas width.
|
||||
* @param {number=} opt_height Canvas height.
|
||||
* @return {CanvasRenderingContext2D}
|
||||
*/
|
||||
ol.dom.createCanvasContext2D = function(opt_width, opt_height) {
|
||||
var canvas = goog.dom.createElement(goog.dom.TagName.CANVAS);
|
||||
if (goog.isDef(opt_width)) {
|
||||
canvas.width = opt_width;
|
||||
}
|
||||
if (goog.isDef(opt_height)) {
|
||||
canvas.height = opt_height;
|
||||
}
|
||||
return canvas.getContext('2d');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {boolean}
|
||||
*/
|
||||
ol.dom.BrowserFeature = {
|
||||
USE_MS_MATRIX_TRANSFORM: ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE,
|
||||
USE_MS_ALPHA_FILTER: ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detect 2d transform.
|
||||
* Adapted from http://stackoverflow.com/q/5661671/130442
|
||||
* http://caniuse.com/#feat=transforms2d
|
||||
* @return {boolean}
|
||||
*/
|
||||
ol.dom.canUseCssTransform = (function() {
|
||||
var canUseCssTransform;
|
||||
return function() {
|
||||
if (!goog.isDef(canUseCssTransform)) {
|
||||
goog.asserts.assert(!goog.isNull(document.body));
|
||||
if (!goog.global.getComputedStyle) {
|
||||
// this browser is ancient
|
||||
canUseCssTransform = false;
|
||||
} else {
|
||||
var el = goog.dom.createElement(goog.dom.TagName.P),
|
||||
has2d,
|
||||
transforms = {
|
||||
'webkitTransform': '-webkit-transform',
|
||||
'OTransform': '-o-transform',
|
||||
'msTransform': '-ms-transform',
|
||||
'MozTransform': '-moz-transform',
|
||||
'transform': 'transform'
|
||||
};
|
||||
goog.dom.appendChild(document.body, el);
|
||||
for (var t in transforms) {
|
||||
if (t in el.style) {
|
||||
el.style[t] = 'translate(1px,1px)';
|
||||
has2d = goog.global.getComputedStyle(el).getPropertyValue(
|
||||
transforms[t]);
|
||||
}
|
||||
}
|
||||
goog.dom.removeNode(el);
|
||||
|
||||
canUseCssTransform = (has2d && has2d !== 'none');
|
||||
}
|
||||
}
|
||||
return canUseCssTransform;
|
||||
};
|
||||
}());
|
||||
|
||||
|
||||
/**
|
||||
* Detect 3d transform.
|
||||
* Adapted from http://stackoverflow.com/q/5661671/130442
|
||||
* http://caniuse.com/#feat=transforms3d
|
||||
* @return {boolean}
|
||||
*/
|
||||
ol.dom.canUseCssTransform3D = (function() {
|
||||
var canUseCssTransform3D;
|
||||
return function() {
|
||||
if (!goog.isDef(canUseCssTransform3D)) {
|
||||
goog.asserts.assert(!goog.isNull(document.body));
|
||||
if (!goog.global.getComputedStyle) {
|
||||
// this browser is ancient
|
||||
canUseCssTransform3D = false;
|
||||
} else {
|
||||
var el = goog.dom.createElement(goog.dom.TagName.P),
|
||||
has3d,
|
||||
transforms = {
|
||||
'webkitTransform': '-webkit-transform',
|
||||
'OTransform': '-o-transform',
|
||||
'msTransform': '-ms-transform',
|
||||
'MozTransform': '-moz-transform',
|
||||
'transform': 'transform'
|
||||
};
|
||||
goog.dom.appendChild(document.body, el);
|
||||
for (var t in transforms) {
|
||||
if (t in el.style) {
|
||||
el.style[t] = 'translate3d(1px,1px,1px)';
|
||||
has3d = goog.global.getComputedStyle(el).getPropertyValue(
|
||||
transforms[t]);
|
||||
}
|
||||
}
|
||||
goog.dom.removeNode(el);
|
||||
|
||||
canUseCssTransform3D = (has3d && has3d !== 'none');
|
||||
}
|
||||
}
|
||||
return canUseCssTransform3D;
|
||||
};
|
||||
}());
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} element Element.
|
||||
* @param {string} value Value.
|
||||
*/
|
||||
ol.dom.setTransform = function(element, value) {
|
||||
var style = element.style;
|
||||
style.WebkitTransform = value;
|
||||
style.MozTransform = value;
|
||||
style.OTransform = value;
|
||||
style.msTransform = value;
|
||||
style.transform = value;
|
||||
|
||||
// IE 9+ seems to assume transform-origin: 100% 100%; for some unknown reason
|
||||
if (goog.userAgent.IE && !ol.IS_LEGACY_IE) {
|
||||
element.style.transformOrigin = '0 0';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the opacity of an element, in an IE-compatible way
|
||||
* @param {!Element} element Element
|
||||
* @param {number} value Opacity, [0..1]
|
||||
*/
|
||||
ol.dom.setOpacity = function(element, value) {
|
||||
if (ol.dom.BrowserFeature.USE_MS_ALPHA_FILTER) {
|
||||
/** @type {string} */
|
||||
var filter = element.currentStyle.filter;
|
||||
|
||||
/** @type {RegExp} */
|
||||
var regex;
|
||||
|
||||
/** @type {string} */
|
||||
var alpha;
|
||||
|
||||
if (goog.userAgent.VERSION == '8.0') {
|
||||
regex = /progid:DXImageTransform\.Microsoft\.Alpha\(.*?\)/i;
|
||||
alpha = 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' +
|
||||
(value * 100) + ')';
|
||||
} else {
|
||||
regex = /alpha\(.*?\)/i;
|
||||
alpha = 'alpha(opacity=' + (value * 100) + ')';
|
||||
}
|
||||
|
||||
var newFilter = filter.replace(regex, alpha);
|
||||
if (newFilter === filter) {
|
||||
// no replace was made? just append the new alpha filter instead
|
||||
newFilter += ' ' + alpha;
|
||||
}
|
||||
|
||||
element.style.filter = newFilter;
|
||||
|
||||
// Fix to apply filter to absolutely-positioned children element
|
||||
if (element.currentStyle.zIndex === 'auto') {
|
||||
element.style.zIndex = 0;
|
||||
}
|
||||
} else {
|
||||
element.style.opacity = value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the IE matrix transform without replacing other filters
|
||||
* @private
|
||||
* @param {!Element} element Element
|
||||
* @param {string} value The new progid string
|
||||
*/
|
||||
ol.dom.setIEMatrix_ = function(element, value) {
|
||||
var filter = element.currentStyle.filter;
|
||||
var newFilter =
|
||||
filter.replace(/progid:DXImageTransform.Microsoft.Matrix\(.*?\)/i, value);
|
||||
|
||||
if (newFilter === filter) {
|
||||
newFilter = ' ' + value;
|
||||
}
|
||||
|
||||
element.style.filter = newFilter;
|
||||
|
||||
// Fix to apply filter to absolutely-positioned children element
|
||||
if (element.currentStyle.zIndex === 'auto') {
|
||||
element.style.zIndex = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Element} element Element.
|
||||
* @param {goog.vec.Mat4.Number} transform Matrix.
|
||||
* @param {number=} opt_precision Precision.
|
||||
* @param {Element=} opt_translationElement Required for IE7-8
|
||||
*/
|
||||
ol.dom.transformElement2D =
|
||||
function(element, transform, opt_precision, opt_translationElement) {
|
||||
// using matrix() causes gaps in Chrome and Firefox on Mac OS X, so prefer
|
||||
// matrix3d()
|
||||
var i;
|
||||
if (ol.dom.canUseCssTransform3D()) {
|
||||
var value3D;
|
||||
|
||||
if (goog.isDef(opt_precision)) {
|
||||
/** @type {Array.<string>} */
|
||||
var strings3D = new Array(16);
|
||||
for (i = 0; i < 16; ++i) {
|
||||
strings3D[i] = transform[i].toFixed(opt_precision);
|
||||
}
|
||||
value3D = strings3D.join(',');
|
||||
} else {
|
||||
value3D = transform.join(',');
|
||||
}
|
||||
ol.dom.setTransform(element, 'matrix3d(' + value3D + ')');
|
||||
} else if (ol.dom.canUseCssTransform()) {
|
||||
/** @type {Array.<number>} */
|
||||
var transform2D = [
|
||||
goog.vec.Mat4.getElement(transform, 0, 0),
|
||||
goog.vec.Mat4.getElement(transform, 1, 0),
|
||||
goog.vec.Mat4.getElement(transform, 0, 1),
|
||||
goog.vec.Mat4.getElement(transform, 1, 1),
|
||||
goog.vec.Mat4.getElement(transform, 0, 3),
|
||||
goog.vec.Mat4.getElement(transform, 1, 3)
|
||||
];
|
||||
var value2D;
|
||||
if (goog.isDef(opt_precision)) {
|
||||
/** @type {Array.<string>} */
|
||||
var strings2D = new Array(6);
|
||||
for (i = 0; i < 6; ++i) {
|
||||
strings2D[i] = transform2D[i].toFixed(opt_precision);
|
||||
}
|
||||
value2D = strings2D.join(',');
|
||||
} else {
|
||||
value2D = transform2D.join(',');
|
||||
}
|
||||
ol.dom.setTransform(element, 'matrix(' + value2D + ')');
|
||||
} else if (ol.dom.BrowserFeature.USE_MS_MATRIX_TRANSFORM) {
|
||||
var m11 = goog.vec.Mat4.getElement(transform, 0, 0),
|
||||
m12 = goog.vec.Mat4.getElement(transform, 0, 1),
|
||||
m21 = goog.vec.Mat4.getElement(transform, 1, 0),
|
||||
m22 = goog.vec.Mat4.getElement(transform, 1, 1),
|
||||
dx = goog.vec.Mat4.getElement(transform, 0, 3),
|
||||
dy = goog.vec.Mat4.getElement(transform, 1, 3);
|
||||
|
||||
// See: http://msdn.microsoft.com/en-us/library/ms533014(v=vs.85).aspx
|
||||
// and: http://extremelysatisfactorytotalitarianism.com/blog/?p=1002
|
||||
// @TODO: fix terrible IE bbox rotation issue.
|
||||
var s = 'progid:DXImageTransform.Microsoft.Matrix(';
|
||||
s += 'sizingMethod="auto expand"';
|
||||
s += ',M11=' + m11.toFixed(opt_precision || 20);
|
||||
s += ',M12=' + m12.toFixed(opt_precision || 20);
|
||||
s += ',M21=' + m21.toFixed(opt_precision || 20);
|
||||
s += ',M22=' + m22.toFixed(opt_precision || 20);
|
||||
s += ')';
|
||||
ol.dom.setIEMatrix_(element, s);
|
||||
|
||||
// scale = m11 = m22 = target resolution [m/px] / current res [m/px]
|
||||
// dx = (viewport width [px] / 2) * scale
|
||||
// + (layer.x [m] - view.x [m]) / target resolution [m / px]
|
||||
// except that we're positioning the child element relative to the
|
||||
// viewport, not the map.
|
||||
// dividing by the scale factor isn't the exact correction, but it's
|
||||
// close enough that you can barely tell unless you're looking for it
|
||||
dx /= m11;
|
||||
dy /= m22;
|
||||
|
||||
opt_translationElement.style.left = Math.round(dx) + 'px';
|
||||
opt_translationElement.style.top = Math.round(dy) + 'px';
|
||||
} else {
|
||||
element.style.left =
|
||||
Math.round(goog.vec.Mat4.getElement(transform, 0, 3)) + 'px';
|
||||
element.style.top =
|
||||
Math.round(goog.vec.Mat4.getElement(transform, 1, 3)) + 'px';
|
||||
|
||||
// TODO: Add scaling here. This isn't quite as simple as multiplying
|
||||
// width/height, because that only changes the container size, not the
|
||||
// content size.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the current computed width for the given element including margin,
|
||||
* padding and border.
|
||||
* Equivalent to jQuery's `$(el).outerWidth(true)`.
|
||||
* @param {!Element} element Element.
|
||||
* @return {number}
|
||||
*/
|
||||
ol.dom.outerWidth = function(element) {
|
||||
var width = element.offsetWidth;
|
||||
var style = element.currentStyle || window.getComputedStyle(element);
|
||||
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
|
||||
|
||||
return width;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the current computed height for the given element including margin,
|
||||
* padding and border.
|
||||
* Equivalent to jQuery's `$(el).outerHeight(true)`.
|
||||
* @param {!Element} element Element.
|
||||
* @return {number}
|
||||
*/
|
||||
ol.dom.outerHeight = function(element) {
|
||||
var height = element.offsetHeight;
|
||||
var style = element.currentStyle || window.getComputedStyle(element);
|
||||
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
|
||||
|
||||
return height;
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
goog.provide('ol.dom.Input');
|
||||
goog.provide('ol.dom.InputProperty');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.dom.InputProperty = {
|
||||
VALUE: 'value',
|
||||
CHECKED: 'checked'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Helper class for binding HTML input to an {@link ol.Object}.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* // bind a checkbox with id 'visible' to a layer's visibility
|
||||
* var visible = new ol.dom.Input(document.getElementById('visible'));
|
||||
* visible.bindTo('checked', layer, 'visible');
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {Element} target Target element.
|
||||
* @api
|
||||
*/
|
||||
ol.dom.Input = function(target) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
this.target_ = /** @type {HTMLInputElement} */ (target);
|
||||
|
||||
goog.events.listen(this.target_,
|
||||
[goog.events.EventType.CHANGE, goog.events.EventType.INPUT],
|
||||
this.handleInputChanged_, false, this);
|
||||
|
||||
goog.events.listen(this,
|
||||
ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE),
|
||||
this.handleValueChanged_, false, this);
|
||||
goog.events.listen(this,
|
||||
ol.Object.getChangeEventType(ol.dom.InputProperty.CHECKED),
|
||||
this.handleCheckedChanged_, false, this);
|
||||
};
|
||||
goog.inherits(ol.dom.Input, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* If the input is a checkbox, return whether or not the checkbox is checked.
|
||||
* @return {boolean|undefined} The checked state of the Input.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.dom.Input.prototype.getChecked = function() {
|
||||
return /** @type {boolean} */ (this.get(ol.dom.InputProperty.CHECKED));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.dom.Input.prototype,
|
||||
'getChecked',
|
||||
ol.dom.Input.prototype.getChecked);
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the input.
|
||||
* @return {string|undefined} The value of the Input.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.dom.Input.prototype.getValue = function() {
|
||||
return /** @type {string} */ (this.get(ol.dom.InputProperty.VALUE));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.dom.Input.prototype,
|
||||
'getValue',
|
||||
ol.dom.Input.prototype.getValue);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of the input.
|
||||
* @param {string} value The value of the Input.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.dom.Input.prototype.setValue = function(value) {
|
||||
this.set(ol.dom.InputProperty.VALUE, value);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.dom.Input.prototype,
|
||||
'setValue',
|
||||
ol.dom.Input.prototype.setValue);
|
||||
|
||||
|
||||
/**
|
||||
* Set whether or not a checkbox is checked.
|
||||
* @param {boolean} checked The checked state of the Input.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol.dom.Input.prototype.setChecked = function(checked) {
|
||||
this.set(ol.dom.InputProperty.CHECKED, checked);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.dom.Input.prototype,
|
||||
'setChecked',
|
||||
ol.dom.Input.prototype.setChecked);
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.dom.Input.prototype.handleInputChanged_ = function(browserEvent) {
|
||||
goog.asserts.assert(browserEvent.currentTarget == this.target_);
|
||||
var target = this.target_;
|
||||
if (target.type === 'checkbox' || target.type === 'radio') {
|
||||
this.setChecked(target.checked);
|
||||
} else {
|
||||
this.setValue(target.value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Change event.
|
||||
* @private
|
||||
*/
|
||||
ol.dom.Input.prototype.handleCheckedChanged_ = function(event) {
|
||||
this.target_.checked = /** @type {boolean} */ (this.getChecked());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Change event.
|
||||
* @private
|
||||
*/
|
||||
ol.dom.Input.prototype.handleValueChanged_ = function(event) {
|
||||
this.target_.value = /** @type {string} */ (this.getValue());
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
goog.provide('ol.easing');
|
||||
|
||||
goog.require('goog.fx.easing');
|
||||
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
ol.easing.easeIn = goog.fx.easing.easeIn;
|
||||
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
ol.easing.easeOut = goog.fx.easing.easeOut;
|
||||
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
ol.easing.inAndOut = goog.fx.easing.inAndOut;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
ol.easing.linear = function(t) {
|
||||
return t;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
ol.easing.upAndDown = function(t) {
|
||||
if (t < 0.5) {
|
||||
return ol.easing.inAndOut(2 * t);
|
||||
} else {
|
||||
return 1 - ol.easing.inAndOut(2 * (t - 0.5));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Easing functions for {@link ol.animation}.
|
||||
* @namespace ol.easing
|
||||
*/
|
||||
@@ -0,0 +1,185 @@
|
||||
goog.provide('ol.Ellipsoid');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} a Major radius.
|
||||
* @param {number} flattening Flattening.
|
||||
*/
|
||||
ol.Ellipsoid = function(a, flattening) {
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.a = a;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.flattening = flattening;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.b = this.a * (1 - this.flattening);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.eSquared = 2 * flattening - flattening * flattening;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.e = Math.sqrt(this.eSquared);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} c1 Coordinate 1.
|
||||
* @param {ol.Coordinate} c2 Coordinate 1.
|
||||
* @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence.
|
||||
* @param {number=} opt_maxIterations Maximum iterations.
|
||||
* @return {{distance: number, initialBearing: number, finalBearing: number}}
|
||||
* Vincenty.
|
||||
*/
|
||||
ol.Ellipsoid.prototype.vincenty =
|
||||
function(c1, c2, opt_minDeltaLambda, opt_maxIterations) {
|
||||
var minDeltaLambda = goog.isDef(opt_minDeltaLambda) ?
|
||||
opt_minDeltaLambda : 1e-12;
|
||||
var maxIterations = goog.isDef(opt_maxIterations) ?
|
||||
opt_maxIterations : 100;
|
||||
var f = this.flattening;
|
||||
var lat1 = goog.math.toRadians(c1[1]);
|
||||
var lat2 = goog.math.toRadians(c2[1]);
|
||||
var deltaLon = goog.math.toRadians(c2[0] - c1[0]);
|
||||
var U1 = Math.atan((1 - f) * Math.tan(lat1));
|
||||
var cosU1 = Math.cos(U1);
|
||||
var sinU1 = Math.sin(U1);
|
||||
var U2 = Math.atan((1 - f) * Math.tan(lat2));
|
||||
var cosU2 = Math.cos(U2);
|
||||
var sinU2 = Math.sin(U2);
|
||||
var lambda = deltaLon;
|
||||
var cosSquaredAlpha, sinAlpha;
|
||||
var cosLambda, deltaLambda = Infinity, sinLambda;
|
||||
var cos2SigmaM, cosSigma, sigma, sinSigma;
|
||||
var i;
|
||||
for (i = maxIterations; i > 0; --i) {
|
||||
cosLambda = Math.cos(lambda);
|
||||
sinLambda = Math.sin(lambda);
|
||||
var x = cosU2 * sinLambda;
|
||||
var y = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
|
||||
sinSigma = Math.sqrt(x * x + y * y);
|
||||
if (sinSigma === 0) {
|
||||
return {
|
||||
distance: 0,
|
||||
initialBearing: 0,
|
||||
finalBearing: 0
|
||||
};
|
||||
}
|
||||
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
|
||||
sigma = Math.atan2(sinSigma, cosSigma);
|
||||
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
|
||||
cosSquaredAlpha = 1 - sinAlpha * sinAlpha;
|
||||
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSquaredAlpha;
|
||||
if (isNaN(cos2SigmaM)) {
|
||||
cos2SigmaM = 0;
|
||||
}
|
||||
var C = f / 16 * cosSquaredAlpha * (4 + f * (4 - 3 * cosSquaredAlpha));
|
||||
var lambdaPrime = deltaLon + (1 - C) * f * sinAlpha * (sigma +
|
||||
C * sinSigma * (cos2SigmaM +
|
||||
C * cosSigma * (2 * cos2SigmaM * cos2SigmaM - 1)));
|
||||
deltaLambda = Math.abs(lambdaPrime - lambda);
|
||||
lambda = lambdaPrime;
|
||||
if (deltaLambda < minDeltaLambda) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i === 0) {
|
||||
return {
|
||||
distance: NaN,
|
||||
finalBearing: NaN,
|
||||
initialBearing: NaN
|
||||
};
|
||||
}
|
||||
var aSquared = this.a * this.a;
|
||||
var bSquared = this.b * this.b;
|
||||
var uSquared = cosSquaredAlpha * (aSquared - bSquared) / bSquared;
|
||||
var A = 1 + uSquared / 16384 *
|
||||
(4096 + uSquared * (uSquared * (320 - 175 * uSquared) - 768));
|
||||
var B = uSquared / 1024 *
|
||||
(256 + uSquared * (uSquared * (74 - 47 * uSquared) - 128));
|
||||
var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 *
|
||||
(cosSigma * (2 * cos2SigmaM * cos2SigmaM - 1) -
|
||||
B / 6 * cos2SigmaM * (4 * sinSigma * sinSigma - 3) *
|
||||
(4 * cos2SigmaM * cos2SigmaM - 3)));
|
||||
cosLambda = Math.cos(lambda);
|
||||
sinLambda = Math.sin(lambda);
|
||||
var alpha1 = Math.atan2(cosU2 * sinLambda,
|
||||
cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
|
||||
var alpha2 = Math.atan2(cosU1 * sinLambda,
|
||||
cosU1 * sinU2 * cosLambda - sinU1 * cosU2);
|
||||
return {
|
||||
distance: this.b * A * (sigma - deltaSigma),
|
||||
initialBearing: goog.math.toDegrees(alpha1),
|
||||
finalBearing: goog.math.toDegrees(alpha2)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from c1 to c2 using Vincenty.
|
||||
*
|
||||
* @param {ol.Coordinate} c1 Coordinate 1.
|
||||
* @param {ol.Coordinate} c2 Coordinate 1.
|
||||
* @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence.
|
||||
* @param {number=} opt_maxIterations Maximum iterations.
|
||||
* @return {number} Vincenty distance.
|
||||
*/
|
||||
ol.Ellipsoid.prototype.vincentyDistance =
|
||||
function(c1, c2, opt_minDeltaLambda, opt_maxIterations) {
|
||||
var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations);
|
||||
return vincenty.distance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the final bearing from c1 to c2 using Vincenty.
|
||||
*
|
||||
* @param {ol.Coordinate} c1 Coordinate 1.
|
||||
* @param {ol.Coordinate} c2 Coordinate 1.
|
||||
* @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence.
|
||||
* @param {number=} opt_maxIterations Maximum iterations.
|
||||
* @return {number} Initial bearing.
|
||||
*/
|
||||
ol.Ellipsoid.prototype.vincentyFinalBearing =
|
||||
function(c1, c2, opt_minDeltaLambda, opt_maxIterations) {
|
||||
var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations);
|
||||
return vincenty.finalBearing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the initial bearing from c1 to c2 using Vincenty.
|
||||
*
|
||||
* @param {ol.Coordinate} c1 Coordinate 1.
|
||||
* @param {ol.Coordinate} c2 Coordinate 1.
|
||||
* @param {number=} opt_minDeltaLambda Minimum delta lambda for convergence.
|
||||
* @param {number=} opt_maxIterations Maximum iterations.
|
||||
* @return {number} Initial bearing.
|
||||
*/
|
||||
ol.Ellipsoid.prototype.vincentyInitialBearing =
|
||||
function(c1, c2, opt_minDeltaLambda, opt_maxIterations) {
|
||||
var vincenty = this.vincenty(c1, c2, opt_minDeltaLambda, opt_maxIterations);
|
||||
return vincenty.initialBearing;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
goog.provide('ol.ellipsoid.WGS84');
|
||||
|
||||
goog.require('ol.Ellipsoid');
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Ellipsoid}
|
||||
*/
|
||||
ol.ellipsoid.WGS84 = new ol.Ellipsoid(6378137, 1 / 298.257223563);
|
||||
@@ -0,0 +1,168 @@
|
||||
goog.provide('ol.events.ConditionType');
|
||||
goog.provide('ol.events.condition');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.MapBrowserPointerEvent');
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes an {@link ol.MapBrowserEvent} and returns a
|
||||
* `{boolean}`. If the condition is met, true should be returned.
|
||||
*
|
||||
* @typedef {function(ol.MapBrowserEvent): boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.ConditionType;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the alt key is pressed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.altKeyOnly = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
return (
|
||||
browserEvent.altKey &&
|
||||
!browserEvent.platformModifierKey &&
|
||||
!browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the alt and shift keys are pressed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.altShiftKeysOnly = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
return (
|
||||
browserEvent.altKey &&
|
||||
!browserEvent.platformModifierKey &&
|
||||
browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always true.
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True.
|
||||
* @function
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.always = goog.functions.TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `click` event.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.click = function(mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.CLICK;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always false.
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} False.
|
||||
* @function
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.never = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the browser event is a `pointermove` event.
|
||||
* @api
|
||||
*/
|
||||
ol.events.condition.pointerMove = function(mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == 'pointermove';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `singleclick` event.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.singleClick = function(mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.SINGLECLICK;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True only if there no modifier keys are pressed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.noModifierKeys = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
return (
|
||||
!browserEvent.altKey &&
|
||||
!browserEvent.platformModifierKey &&
|
||||
!browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the platform modifier key is pressed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.platformModifierKeyOnly = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
return (
|
||||
!browserEvent.altKey &&
|
||||
browserEvent.platformModifierKey &&
|
||||
!browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the shift key is pressed.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.shiftKeyOnly = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
return (
|
||||
!browserEvent.altKey &&
|
||||
!browserEvent.platformModifierKey &&
|
||||
browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True only if the target element is not editable.
|
||||
* @api
|
||||
*/
|
||||
ol.events.condition.targetNotEditable = function(mapBrowserEvent) {
|
||||
var target = mapBrowserEvent.browserEvent.target;
|
||||
goog.asserts.assertInstanceof(target, Element);
|
||||
var tagName = target.tagName;
|
||||
return (
|
||||
tagName !== goog.dom.TagName.INPUT &&
|
||||
tagName !== goog.dom.TagName.SELECT &&
|
||||
tagName !== goog.dom.TagName.TEXTAREA);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a mouse device.
|
||||
* @api stable
|
||||
*/
|
||||
ol.events.condition.mouseOnly = function(mapBrowserEvent) {
|
||||
goog.asserts.assertInstanceof(mapBrowserEvent, ol.MapBrowserPointerEvent);
|
||||
/* pointerId must be 1 for mouse devices,
|
||||
* see: http://www.w3.org/Submission/pointer-events/#pointerevent-interface
|
||||
*/
|
||||
return mapBrowserEvent.pointerEvent.pointerId == 1;
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Applications do not normally create event instances. They register (and
|
||||
* unregister) event listener functions, which, when called by the library as
|
||||
* the result of an event being dispatched, are passed event instances as their
|
||||
* first argument. Listeners can be registered and unregistered on all objects
|
||||
* descending from {@link ol.Observable}. All event instances have a `target`
|
||||
* property, which corresponds to the object on which the event was dispatched.
|
||||
* By default, `this` within the listener also refers to the target, though
|
||||
* this can be configured in the listener registration function.
|
||||
* Some classes have their own event type, which return additional
|
||||
* properties; see the specific event class page for details.
|
||||
*
|
||||
* @namespace ol.events
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace ol.events.condition
|
||||
*/
|
||||
@@ -0,0 +1,890 @@
|
||||
goog.provide('ol.Extent');
|
||||
goog.provide('ol.extent');
|
||||
goog.provide('ol.extent.Corner');
|
||||
goog.provide('ol.extent.Relationship');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TransformFunction');
|
||||
|
||||
|
||||
/**
|
||||
* An array of numbers representing an extent: `[minx, miny, maxx, maxy]`.
|
||||
* @typedef {Array.<number>}
|
||||
* @api stable
|
||||
*/
|
||||
ol.Extent;
|
||||
|
||||
|
||||
/**
|
||||
* Extent corner.
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.extent.Corner = {
|
||||
BOTTOM_LEFT: 'bottom-left',
|
||||
BOTTOM_RIGHT: 'bottom-right',
|
||||
TOP_LEFT: 'top-left',
|
||||
TOP_RIGHT: 'top-right'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Relationship to an extent.
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.extent.Relationship = {
|
||||
UNKNOWN: 0,
|
||||
INTERSECTING: 1,
|
||||
ABOVE: 2,
|
||||
RIGHT: 4,
|
||||
BELOW: 8,
|
||||
LEFT: 16
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Builds an extent that includes all given coordinates.
|
||||
*
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @return {ol.Extent} Bounding extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.boundingExtent = function(coordinates) {
|
||||
var extent = ol.extent.createEmpty();
|
||||
for (var i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
ol.extent.extendCoordinate(extent, coordinates[i]);
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} xs Xs.
|
||||
* @param {Array.<number>} ys Ys.
|
||||
* @param {ol.Extent=} opt_extent Destination extent.
|
||||
* @private
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
|
||||
goog.asserts.assert(xs.length > 0);
|
||||
goog.asserts.assert(ys.length > 0);
|
||||
var minX = Math.min.apply(null, xs);
|
||||
var minY = Math.min.apply(null, ys);
|
||||
var maxX = Math.max.apply(null, xs);
|
||||
var maxY = Math.max.apply(null, ys);
|
||||
return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return extent increased by the provided value.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} value The amount by which the extent should be buffered.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.buffer = function(extent, value, opt_extent) {
|
||||
if (goog.isDef(opt_extent)) {
|
||||
opt_extent[0] = extent[0] - value;
|
||||
opt_extent[1] = extent[1] - value;
|
||||
opt_extent[2] = extent[2] + value;
|
||||
opt_extent[3] = extent[3] + value;
|
||||
return opt_extent;
|
||||
} else {
|
||||
return [
|
||||
extent[0] - value,
|
||||
extent[1] - value,
|
||||
extent[2] + value,
|
||||
extent[3] + value
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a clone of an extent.
|
||||
*
|
||||
* @param {ol.Extent} extent Extent to clone.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} The clone.
|
||||
*/
|
||||
ol.extent.clone = function(extent, opt_extent) {
|
||||
if (goog.isDef(opt_extent)) {
|
||||
opt_extent[0] = extent[0];
|
||||
opt_extent[1] = extent[1];
|
||||
opt_extent[2] = extent[2];
|
||||
opt_extent[3] = extent[3];
|
||||
return opt_extent;
|
||||
} else {
|
||||
return extent.slice();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {number} Closest squared distance.
|
||||
*/
|
||||
ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
|
||||
var dx, dy;
|
||||
if (x < extent[0]) {
|
||||
dx = extent[0] - x;
|
||||
} else if (extent[2] < x) {
|
||||
dx = x - extent[2];
|
||||
} else {
|
||||
dx = 0;
|
||||
}
|
||||
if (y < extent[1]) {
|
||||
dy = extent[1] - y;
|
||||
} else if (extent[3] < y) {
|
||||
dy = y - extent[3];
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
return dx * dx + dy * dy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the passed coordinate is contained or on the edge of the extent.
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {boolean} Contains.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.containsCoordinate = function(extent, coordinate) {
|
||||
return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if `extent2` is contained by or on the edge of `extent1`.
|
||||
*
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {boolean} Contains.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.containsExtent = function(extent1, extent2) {
|
||||
return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
|
||||
extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the passed coordinate is contained or on the edge of the extent.
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} x X coordinate.
|
||||
* @param {number} y Y coordinate.
|
||||
* @return {boolean} Contains.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.containsXY = function(extent, x, y) {
|
||||
return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the relationship between a coordinate and extent.
|
||||
* @param {ol.Extent} extent The extent.
|
||||
* @param {ol.Coordinate} coordinate The coordinate.
|
||||
* @return {number} The relationship (bitwise compare with
|
||||
* ol.extent.Relationship).
|
||||
*/
|
||||
ol.extent.coordinateRelationship = function(extent, coordinate) {
|
||||
var minX = extent[0];
|
||||
var minY = extent[1];
|
||||
var maxX = extent[2];
|
||||
var maxY = extent[3];
|
||||
var x = coordinate[0];
|
||||
var y = coordinate[1];
|
||||
var relationship = ol.extent.Relationship.UNKNOWN;
|
||||
if (x < minX) {
|
||||
relationship = relationship | ol.extent.Relationship.LEFT;
|
||||
} else if (x > maxX) {
|
||||
relationship = relationship | ol.extent.Relationship.RIGHT;
|
||||
}
|
||||
if (y < minY) {
|
||||
relationship = relationship | ol.extent.Relationship.BELOW;
|
||||
} else if (y > maxY) {
|
||||
relationship = relationship | ol.extent.Relationship.ABOVE;
|
||||
}
|
||||
if (relationship === ol.extent.Relationship.UNKNOWN) {
|
||||
relationship = ol.extent.Relationship.INTERSECTING;
|
||||
}
|
||||
return relationship;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Extent} Empty extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.createEmpty = function() {
|
||||
return [Infinity, Infinity, -Infinity, -Infinity];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
* @param {ol.Extent=} opt_extent Destination extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
|
||||
if (goog.isDef(opt_extent)) {
|
||||
opt_extent[0] = minX;
|
||||
opt_extent[1] = minY;
|
||||
opt_extent[2] = maxX;
|
||||
opt_extent[3] = maxY;
|
||||
return opt_extent;
|
||||
} else {
|
||||
return [minX, minY, maxX, maxY];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdateEmpty = function(opt_extent) {
|
||||
return ol.extent.createOrUpdate(
|
||||
Infinity, Infinity, -Infinity, -Infinity, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
|
||||
var x = coordinate[0];
|
||||
var y = coordinate[1];
|
||||
return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
|
||||
var extent = ol.extent.createOrUpdateEmpty(opt_extent);
|
||||
return ol.extent.extendCoordinates(extent, coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdateFromFlatCoordinates =
|
||||
function(flatCoordinates, offset, end, stride, opt_extent) {
|
||||
var extent = ol.extent.createOrUpdateEmpty(opt_extent);
|
||||
return ol.extent.extendFlatCoordinates(
|
||||
extent, flatCoordinates, offset, end, stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<ol.Coordinate>>} rings Rings.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
|
||||
var extent = ol.extent.createOrUpdateEmpty(opt_extent);
|
||||
return ol.extent.extendRings(extent, rings);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Empties extent in place.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.empty = function(extent) {
|
||||
extent[0] = extent[1] = Infinity;
|
||||
extent[2] = extent[3] = -Infinity;
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {boolean} Equals.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.equals = function(extent1, extent2) {
|
||||
return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
|
||||
extent1[1] == extent2[1] && extent1[3] == extent2[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {ol.Extent} Extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.extend = function(extent1, extent2) {
|
||||
if (extent2[0] < extent1[0]) {
|
||||
extent1[0] = extent2[0];
|
||||
}
|
||||
if (extent2[2] > extent1[2]) {
|
||||
extent1[2] = extent2[2];
|
||||
}
|
||||
if (extent2[1] < extent1[1]) {
|
||||
extent1[1] = extent2[1];
|
||||
}
|
||||
if (extent2[3] > extent1[3]) {
|
||||
extent1[3] = extent2[3];
|
||||
}
|
||||
return extent1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
*/
|
||||
ol.extent.extendCoordinate = function(extent, coordinate) {
|
||||
if (coordinate[0] < extent[0]) {
|
||||
extent[0] = coordinate[0];
|
||||
}
|
||||
if (coordinate[0] > extent[2]) {
|
||||
extent[2] = coordinate[0];
|
||||
}
|
||||
if (coordinate[1] < extent[1]) {
|
||||
extent[1] = coordinate[1];
|
||||
}
|
||||
if (coordinate[1] > extent[3]) {
|
||||
extent[3] = coordinate[1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.extendCoordinates = function(extent, coordinates) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
ol.extent.extendCoordinate(extent, coordinates[i]);
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.extendFlatCoordinates =
|
||||
function(extent, flatCoordinates, offset, end, stride) {
|
||||
for (; offset < end; offset += stride) {
|
||||
ol.extent.extendXY(
|
||||
extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} rings Rings.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.extendRings = function(extent, rings) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = rings.length; i < ii; ++i) {
|
||||
ol.extent.extendCoordinates(extent, rings[i]);
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
ol.extent.extendXY = function(extent, x, y) {
|
||||
extent[0] = Math.min(extent[0], x);
|
||||
extent[1] = Math.min(extent[1], y);
|
||||
extent[2] = Math.max(extent[2], x);
|
||||
extent[3] = Math.max(extent[3], y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function calls `callback` for each corner of the extent. If the
|
||||
* callback returns a truthy value the function returns that value
|
||||
* immediately. Otherwise the function returns `false`.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {function(this:T, ol.Coordinate): S} callback Callback.
|
||||
* @param {T=} opt_this Value to use as `this` when executing `callback`.
|
||||
* @return {S|boolean} Value.
|
||||
* @template S, T
|
||||
*/
|
||||
ol.extent.forEachCorner = function(extent, callback, opt_this) {
|
||||
var val;
|
||||
val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getBottomRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getTopRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getTopLeft(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number} Area.
|
||||
*/
|
||||
ol.extent.getArea = function(extent) {
|
||||
var area = 0;
|
||||
if (!ol.extent.isEmpty(extent)) {
|
||||
area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
|
||||
}
|
||||
return area;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Coordinate} Bottom left coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getBottomLeft = function(extent) {
|
||||
return [extent[0], extent[1]];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Coordinate} Bottom right coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getBottomRight = function(extent) {
|
||||
return [extent[2], extent[1]];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Coordinate} Center.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getCenter = function(extent) {
|
||||
return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a corner coordinate of an extent.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.extent.Corner} corner Corner.
|
||||
* @return {ol.Coordinate} Corner coordinate.
|
||||
*/
|
||||
ol.extent.getCorner = function(extent, corner) {
|
||||
var coordinate;
|
||||
if (corner === ol.extent.Corner.BOTTOM_LEFT) {
|
||||
coordinate = ol.extent.getBottomLeft(extent);
|
||||
} else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
|
||||
coordinate = ol.extent.getBottomRight(extent);
|
||||
} else if (corner === ol.extent.Corner.TOP_LEFT) {
|
||||
coordinate = ol.extent.getTopLeft(extent);
|
||||
} else if (corner === ol.extent.Corner.TOP_RIGHT) {
|
||||
coordinate = ol.extent.getTopRight(extent);
|
||||
} else {
|
||||
goog.asserts.fail('Invalid corner: %s', corner);
|
||||
}
|
||||
goog.asserts.assert(goog.isDef(coordinate));
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {number} Enlarged area.
|
||||
*/
|
||||
ol.extent.getEnlargedArea = function(extent1, extent2) {
|
||||
var minX = Math.min(extent1[0], extent2[0]);
|
||||
var minY = Math.min(extent1[1], extent2[1]);
|
||||
var maxX = Math.max(extent1[2], extent2[2]);
|
||||
var maxY = Math.max(extent1[3], extent2[3]);
|
||||
return (maxX - minX) * (maxY - minY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {ol.Extent=} opt_extent Destination extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.getForViewAndSize =
|
||||
function(center, resolution, rotation, size, opt_extent) {
|
||||
var dx = resolution * size[0] / 2;
|
||||
var dy = resolution * size[1] / 2;
|
||||
var cosRotation = Math.cos(rotation);
|
||||
var sinRotation = Math.sin(rotation);
|
||||
/** @type {Array.<number>} */
|
||||
var xs = [-dx, -dx, dx, dx];
|
||||
/** @type {Array.<number>} */
|
||||
var ys = [-dy, dy, -dy, dy];
|
||||
var i, x, y;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x = xs[i];
|
||||
y = ys[i];
|
||||
xs[i] = center[0] + x * cosRotation - y * sinRotation;
|
||||
ys[i] = center[1] + x * sinRotation + y * cosRotation;
|
||||
}
|
||||
return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number} Height.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getHeight = function(extent) {
|
||||
return extent[3] - extent[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {number} Intersection area.
|
||||
*/
|
||||
ol.extent.getIntersectionArea = function(extent1, extent2) {
|
||||
var intersection = ol.extent.getIntersection(extent1, extent2);
|
||||
return ol.extent.getArea(intersection);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the intersection of two extents.
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
|
||||
* @return {ol.Extent} Intersecting extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
|
||||
var intersection = goog.isDef(opt_extent) ?
|
||||
opt_extent : ol.extent.createEmpty();
|
||||
if (ol.extent.intersects(extent1, extent2)) {
|
||||
if (extent1[0] > extent2[0]) {
|
||||
intersection[0] = extent1[0];
|
||||
} else {
|
||||
intersection[0] = extent2[0];
|
||||
}
|
||||
if (extent1[1] > extent2[1]) {
|
||||
intersection[1] = extent1[1];
|
||||
} else {
|
||||
intersection[1] = extent2[1];
|
||||
}
|
||||
if (extent1[2] < extent2[2]) {
|
||||
intersection[2] = extent1[2];
|
||||
} else {
|
||||
intersection[2] = extent2[2];
|
||||
}
|
||||
if (extent1[3] < extent2[3]) {
|
||||
intersection[3] = extent1[3];
|
||||
} else {
|
||||
intersection[3] = extent2[3];
|
||||
}
|
||||
}
|
||||
return intersection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number} Margin.
|
||||
*/
|
||||
ol.extent.getMargin = function(extent) {
|
||||
return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Size} Size.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getSize = function(extent) {
|
||||
return [extent[2] - extent[0], extent[3] - extent[1]];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Coordinate} Top left coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getTopLeft = function(extent) {
|
||||
return [extent[0], extent[3]];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {ol.Coordinate} Top right coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getTopRight = function(extent) {
|
||||
return [extent[2], extent[3]];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number} Width.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.getWidth = function(extent) {
|
||||
return extent[2] - extent[0];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent.
|
||||
* @return {boolean} Intersects.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.intersects = function(extent1, extent2) {
|
||||
return extent1[0] <= extent2[2] &&
|
||||
extent1[2] >= extent2[0] &&
|
||||
extent1[1] <= extent2[3] &&
|
||||
extent1[3] >= extent2[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} Is empty.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.isEmpty = function(extent) {
|
||||
return extent[2] < extent[0] || extent[3] < extent[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} Is infinite.
|
||||
*/
|
||||
ol.extent.isInfinite = function(extent) {
|
||||
return extent[0] == -Infinity || extent[1] == -Infinity ||
|
||||
extent[2] == Infinity || extent[3] == Infinity;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.extent.normalize = function(extent, coordinate) {
|
||||
return [
|
||||
(coordinate[0] - extent[0]) / (extent[2] - extent[0]),
|
||||
(coordinate[1] - extent[1]) / (extent[3] - extent[1])
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.extent.returnOrUpdate = function(extent, opt_extent) {
|
||||
if (goog.isDef(opt_extent)) {
|
||||
opt_extent[0] = extent[0];
|
||||
opt_extent[1] = extent[1];
|
||||
opt_extent[2] = extent[2];
|
||||
opt_extent[3] = extent[3];
|
||||
return opt_extent;
|
||||
} else {
|
||||
return extent;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} value Value.
|
||||
*/
|
||||
ol.extent.scaleFromCenter = function(extent, value) {
|
||||
var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
|
||||
var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
|
||||
extent[0] -= deltaX;
|
||||
extent[2] += deltaX;
|
||||
extent[1] -= deltaY;
|
||||
extent[3] += deltaY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the segment between two coordinates intersects (crosses,
|
||||
* touches, or is contained by) the provided extent.
|
||||
* @param {ol.Extent} extent The extent.
|
||||
* @param {ol.Coordinate} start Segment start coordinate.
|
||||
* @param {ol.Coordinate} end Segment end coordinate.
|
||||
* @return {boolean} The segment intersects the extent.
|
||||
*/
|
||||
ol.extent.intersectsSegment = function(extent, start, end) {
|
||||
var intersects = false;
|
||||
var startRel = ol.extent.coordinateRelationship(extent, start);
|
||||
var endRel = ol.extent.coordinateRelationship(extent, end);
|
||||
if (startRel === ol.extent.Relationship.INTERSECTING ||
|
||||
endRel === ol.extent.Relationship.INTERSECTING) {
|
||||
intersects = true;
|
||||
} else {
|
||||
var minX = extent[0];
|
||||
var minY = extent[1];
|
||||
var maxX = extent[2];
|
||||
var maxY = extent[3];
|
||||
var startX = start[0];
|
||||
var startY = start[1];
|
||||
var endX = end[0];
|
||||
var endY = end[1];
|
||||
var slope = (endY - startY) / (endX - startX);
|
||||
var x, y;
|
||||
if (!!(endRel & ol.extent.Relationship.ABOVE) &&
|
||||
!(startRel & ol.extent.Relationship.ABOVE)) {
|
||||
// potentially intersects top
|
||||
x = endX - ((endY - maxY) / slope);
|
||||
intersects = x >= minX && x <= maxX;
|
||||
} else if (!!(endRel & ol.extent.Relationship.RIGHT) &&
|
||||
!(startRel & ol.extent.Relationship.RIGHT)) {
|
||||
// potentially intersects right
|
||||
y = endY - ((endX - maxX) * slope);
|
||||
intersects = y >= minY && y <= maxY;
|
||||
} else if (!!(endRel & ol.extent.Relationship.BELOW) &&
|
||||
!(startRel & ol.extent.Relationship.BELOW)) {
|
||||
// potentially intersects bottom
|
||||
x = endX - ((endY - minY) / slope);
|
||||
intersects = x >= minX && x <= maxX;
|
||||
} else if (!!(endRel & ol.extent.Relationship.LEFT) &&
|
||||
!(startRel & ol.extent.Relationship.LEFT)) {
|
||||
// potentially intersects left
|
||||
y = endY - ((endX - minX) * slope);
|
||||
intersects = y >= minY && y <= maxY;
|
||||
}
|
||||
|
||||
}
|
||||
return intersects;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
* @return {boolean} Touches.
|
||||
*/
|
||||
ol.extent.touches = function(extent1, extent2) {
|
||||
var intersects = ol.extent.intersects(extent1, extent2);
|
||||
return intersects &&
|
||||
(extent1[0] == extent2[2] || extent1[2] == extent2[0] ||
|
||||
extent1[1] == extent2[3] || extent1[3] == extent2[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply a transform function to the extent.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.TransformFunction} transformFn Transform function. Called with
|
||||
* [minX, minY, maxX, maxY] extent coordinates.
|
||||
* @param {ol.Extent=} opt_extent Destination extent.
|
||||
* @return {ol.Extent} Extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
|
||||
var coordinates = [
|
||||
extent[0], extent[1],
|
||||
extent[0], extent[3],
|
||||
extent[2], extent[1],
|
||||
extent[2], extent[3]
|
||||
];
|
||||
transformFn(coordinates, coordinates, 2);
|
||||
var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
|
||||
var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
|
||||
return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply a 2d transform to an extent.
|
||||
* @param {ol.Extent} extent Input extent.
|
||||
* @param {goog.vec.Mat4.Number} transform The transform matrix.
|
||||
* @param {ol.Extent=} opt_extent Optional extent for return values.
|
||||
* @return {ol.Extent} The transformed extent.
|
||||
*/
|
||||
ol.extent.transform2D = function(extent, transform, opt_extent) {
|
||||
var dest = goog.isDef(opt_extent) ? opt_extent : [];
|
||||
var m00 = goog.vec.Mat4.getElement(transform, 0, 0);
|
||||
var m10 = goog.vec.Mat4.getElement(transform, 1, 0);
|
||||
var m01 = goog.vec.Mat4.getElement(transform, 0, 1);
|
||||
var m11 = goog.vec.Mat4.getElement(transform, 1, 1);
|
||||
var m03 = goog.vec.Mat4.getElement(transform, 0, 3);
|
||||
var m13 = goog.vec.Mat4.getElement(transform, 1, 3);
|
||||
var xi = [0, 2, 0, 2];
|
||||
var yi = [1, 1, 3, 3];
|
||||
var xs = [];
|
||||
var ys = [];
|
||||
var i, x, y;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x = extent[xi[i]];
|
||||
y = extent[yi[i]];
|
||||
xs[i] = m00 * x + m01 * y + m03;
|
||||
ys[i] = m10 * x + m11 * y + m13;
|
||||
}
|
||||
dest[0] = Math.min.apply(null, xs);
|
||||
dest[1] = Math.min.apply(null, ys);
|
||||
dest[2] = Math.max.apply(null, xs);
|
||||
dest[3] = Math.max.apply(null, ys);
|
||||
return dest;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.extent
|
||||
*/
|
||||
@@ -0,0 +1,329 @@
|
||||
goog.provide('ol.Feature');
|
||||
goog.provide('ol.feature');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A vector object for geographic features with a geometry and other
|
||||
* attribute properties, similar to the features in vector file formats like
|
||||
* GeoJSON.
|
||||
*
|
||||
* Features can be styled individually with `setStyle`; otherwise they use the
|
||||
* style of their vector layer or feature overlay.
|
||||
*
|
||||
* Note that attribute properties are set as {@link ol.Object} properties on
|
||||
* the feature object, so they are observable, and have get/set accessors.
|
||||
*
|
||||
* Typically, a feature has a single geometry property. You can set the
|
||||
* geometry using the `setGeometry` method and get it with `getGeometry`.
|
||||
* It is possible to store more than one geometry on a feature using attribute
|
||||
* properties. By default, the geometry used for rendering is identified by
|
||||
* the property name `geometry`. If you want to use another geometry property
|
||||
* for rendering, use the `setGeometryName` method to change the attribute
|
||||
* property associated with the geometry for the feature. For example:
|
||||
*
|
||||
* ```js
|
||||
* var feature = new ol.Feature({
|
||||
* geometry: new ol.geom.Polygon(polyCoords),
|
||||
* labelPoint: new ol.geom.Point(labelCoords),
|
||||
* name: 'My Polygon'
|
||||
* });
|
||||
*
|
||||
* // get the polygon geometry
|
||||
* var poly = feature.getGeometry();
|
||||
*
|
||||
* // Render the feature as a point using the coordinates from labelPoint
|
||||
* feature.setGeometryName('labelPoint');
|
||||
*
|
||||
* // get the point geometry
|
||||
* var point = feature.getGeometry();
|
||||
* ```
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the id, the geometry or the style of the
|
||||
* feature changes.
|
||||
* @param {ol.geom.Geometry|Object.<string, *>=} opt_geometryOrProperties
|
||||
* You may pass a Geometry object directly, or an object literal
|
||||
* containing properties. If you pass an object literal, you may
|
||||
* include a Geometry associated with a `geometry` key.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature = function(opt_geometryOrProperties) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|string|undefined}
|
||||
*/
|
||||
this.id_ = undefined;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.geometryName_ = 'geometry';
|
||||
|
||||
/**
|
||||
* User provided style.
|
||||
* @private
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|
|
||||
* ol.feature.FeatureStyleFunction}
|
||||
*/
|
||||
this.style_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.feature.FeatureStyleFunction|undefined}
|
||||
*/
|
||||
this.styleFunction_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.geometryChangeKey_ = null;
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangeEventType(this.geometryName_),
|
||||
this.handleGeometryChanged_, false, this);
|
||||
|
||||
if (goog.isDef(opt_geometryOrProperties)) {
|
||||
if (opt_geometryOrProperties instanceof ol.geom.Geometry ||
|
||||
goog.isNull(opt_geometryOrProperties)) {
|
||||
var geometry = /** @type {ol.geom.Geometry} */ (opt_geometryOrProperties);
|
||||
this.setGeometry(geometry);
|
||||
} else {
|
||||
goog.asserts.assert(goog.isObject(opt_geometryOrProperties));
|
||||
var properties = /** @type {Object.<string, *>} */
|
||||
(opt_geometryOrProperties);
|
||||
this.setProperties(properties);
|
||||
}
|
||||
}
|
||||
};
|
||||
goog.inherits(ol.Feature, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* Clone this feature. If the original feature has a geometry it
|
||||
* is also cloned. The feature id is not set in the clone.
|
||||
* @return {ol.Feature} The clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.clone = function() {
|
||||
var clone = new ol.Feature(this.getProperties());
|
||||
clone.setGeometryName(this.getGeometryName());
|
||||
var geometry = this.getGeometry();
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
clone.setGeometry(geometry.clone());
|
||||
}
|
||||
var style = this.getStyle();
|
||||
if (!goog.isNull(style)) {
|
||||
clone.setStyle(style);
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.geom.Geometry|undefined} Returns the Geometry associated
|
||||
* with this feature using the current geometry name property. By
|
||||
* default, this is `geometry` but it may be changed by calling
|
||||
* `setGeometryName`.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.getGeometry = function() {
|
||||
return /** @type {ol.geom.Geometry|undefined} */ (
|
||||
this.get(this.geometryName_));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Feature.prototype,
|
||||
'getGeometry',
|
||||
ol.Feature.prototype.getGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number|string|undefined} Id.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.getId = function() {
|
||||
return this.id_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Get the property name associated with the geometry for
|
||||
* this feature. By default, this is `geometry` but it may be changed by
|
||||
* calling `setGeometryName`.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.getGeometryName = function() {
|
||||
return this.geometryName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.style.Style|Array.<ol.style.Style>|
|
||||
* ol.feature.FeatureStyleFunction} Return the style as set by `setStyle`
|
||||
* in the same format that it was provided in. If `setStyle` has not been
|
||||
* called, or if it was called with `null`, then `getStyle()` will return
|
||||
* `null`.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.getStyle = function() {
|
||||
return this.style_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.feature.FeatureStyleFunction|undefined} Return a function
|
||||
* representing the current style of this feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.getStyleFunction = function() {
|
||||
return this.styleFunction_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Feature.prototype.handleGeometryChange_ = function() {
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Feature.prototype.handleGeometryChanged_ = function() {
|
||||
if (!goog.isNull(this.geometryChangeKey_)) {
|
||||
goog.events.unlistenByKey(this.geometryChangeKey_);
|
||||
this.geometryChangeKey_ = null;
|
||||
}
|
||||
var geometry = this.getGeometry();
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
this.geometryChangeKey_ = goog.events.listen(geometry,
|
||||
goog.events.EventType.CHANGE, this.handleGeometryChange_, false, this);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry|undefined} geometry Set the geometry for this
|
||||
* feature. This will update the property associated with the current
|
||||
* geometry property name. By default, this is `geometry` but it can be
|
||||
* changed by calling `setGeometryName`.
|
||||
* @api stable
|
||||
* @observable
|
||||
*/
|
||||
ol.Feature.prototype.setGeometry = function(geometry) {
|
||||
this.set(this.geometryName_, geometry);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Feature.prototype,
|
||||
'setGeometry',
|
||||
ol.Feature.prototype.setGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* Set the style for the feature. This can be a single style object, an array
|
||||
* of styles, or a function that takes a resolution and returns an array of
|
||||
* styles. If it is `null` the feature has no style (a `null` style).
|
||||
* @param {ol.style.Style|Array.<ol.style.Style>|
|
||||
* ol.feature.FeatureStyleFunction} style Style for this feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.setStyle = function(style) {
|
||||
this.style_ = style;
|
||||
this.styleFunction_ = goog.isNull(style) ?
|
||||
undefined : ol.feature.createFeatureStyleFunction(style);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number|string|undefined} id Set a unique id for this feature.
|
||||
* The id may be used to retrieve a feature from a vector source with the
|
||||
* {@link ol.source.Vector#getFeatureById} method.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.setId = function(id) {
|
||||
this.id_ = id;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} name Set the property name from which this feature's
|
||||
* geometry will be fetched when calling `getGeometry`.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Feature.prototype.setGeometryName = function(name) {
|
||||
goog.events.unlisten(
|
||||
this, ol.Object.getChangeEventType(this.geometryName_),
|
||||
this.handleGeometryChanged_, false, this);
|
||||
this.geometryName_ = name;
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangeEventType(this.geometryName_),
|
||||
this.handleGeometryChanged_, false, this);
|
||||
this.handleGeometryChanged_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes a `{number}` representing the view's resolution. It
|
||||
* returns an Array of {@link ol.style.Style}. This way individual features
|
||||
* can be styled. The this keyword inside the function references the
|
||||
* {@link ol.Feature} to be styled.
|
||||
*
|
||||
* @typedef {function(this: ol.Feature, number): Array.<ol.style.Style>}
|
||||
* @api stable
|
||||
*/
|
||||
ol.feature.FeatureStyleFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Convert the provided object into a feature style function. Functions passed
|
||||
* through unchanged. Arrays of ol.style.Style or single style objects wrapped
|
||||
* in a new feature style function.
|
||||
* @param {ol.feature.FeatureStyleFunction|!Array.<ol.style.Style>|
|
||||
* !ol.style.Style} obj A feature style function, a single style, or an
|
||||
* array of styles.
|
||||
* @return {ol.feature.FeatureStyleFunction} A style function.
|
||||
*/
|
||||
ol.feature.createFeatureStyleFunction = function(obj) {
|
||||
/**
|
||||
* @type {ol.feature.FeatureStyleFunction}
|
||||
*/
|
||||
var styleFunction;
|
||||
|
||||
if (goog.isFunction(obj)) {
|
||||
styleFunction = /** @type {ol.feature.FeatureStyleFunction} */ (obj);
|
||||
} else {
|
||||
/**
|
||||
* @type {Array.<ol.style.Style>}
|
||||
*/
|
||||
var styles;
|
||||
if (goog.isArray(obj)) {
|
||||
styles = obj;
|
||||
} else {
|
||||
goog.asserts.assertInstanceof(obj, ol.style.Style);
|
||||
styles = [obj];
|
||||
}
|
||||
styleFunction = goog.functions.constant(styles);
|
||||
}
|
||||
return styleFunction;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.feature
|
||||
*/
|
||||
@@ -0,0 +1,316 @@
|
||||
goog.provide('ol.FeatureOverlay');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.CollectionEventType');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A mechanism for changing the style of a small number of features on a
|
||||
* temporary basis, for example highlighting. This is necessary with the Canvas
|
||||
* renderer, where, unlike in SVG, features cannot be individually referenced.
|
||||
* See examples/vector-layers for an example: create a FeatureOverlay with a
|
||||
* different style, copy the feature(s) you want rendered in this different
|
||||
* style into it, and then remove them again when you're finished.
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.FeatureOverlayOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Collection.<ol.Feature>}
|
||||
*/
|
||||
this.features_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<goog.events.Key>}
|
||||
*/
|
||||
this.featuresListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, goog.events.Key>}
|
||||
*/
|
||||
this.featureChangeListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.postComposeListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
|
||||
*/
|
||||
this.style_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.StyleFunction|undefined}
|
||||
*/
|
||||
this.styleFunction_ = undefined;
|
||||
|
||||
this.setStyle(goog.isDef(options.style) ?
|
||||
options.style : ol.style.defaultStyleFunction);
|
||||
|
||||
if (goog.isDef(options.features)) {
|
||||
if (goog.isArray(options.features)) {
|
||||
this.setFeatures(new ol.Collection(options.features.slice()));
|
||||
} else {
|
||||
goog.asserts.assertInstanceof(options.features, ol.Collection);
|
||||
this.setFeatures(options.features);
|
||||
}
|
||||
} else {
|
||||
this.setFeatures(new ol.Collection());
|
||||
}
|
||||
|
||||
if (goog.isDef(options.map)) {
|
||||
this.setMap(options.map);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.addFeature = function(feature) {
|
||||
this.features_.push(feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Collection.<ol.Feature>} Features collection.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getFeatures = function() {
|
||||
return this.features_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {?ol.Map} The map with which this feature overlay is associated.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeatureChange_ = function() {
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeaturesAdd_ = function(collectionEvent) {
|
||||
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_));
|
||||
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
|
||||
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
|
||||
goog.events.listen(feature, goog.events.EventType.CHANGE,
|
||||
this.handleFeatureChange_, false, this);
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleFeaturesRemove_ = function(collectionEvent) {
|
||||
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_));
|
||||
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
|
||||
var key = goog.getUid(feature).toString();
|
||||
goog.events.unlistenByKey(this.featureChangeListenerKeys_[key]);
|
||||
delete this.featureChangeListenerKeys_[key];
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle changes in image style state.
|
||||
* @param {goog.events.Event} event Image style change event.
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleImageChange_ = function(event) {
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.render.Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) {
|
||||
if (goog.isNull(this.features_)) {
|
||||
return;
|
||||
}
|
||||
var styleFunction = this.styleFunction_;
|
||||
if (!goog.isDef(styleFunction)) {
|
||||
styleFunction = ol.style.defaultStyleFunction;
|
||||
}
|
||||
var replayGroup = /** @type {ol.render.IReplayGroup} */
|
||||
(event.replayGroup);
|
||||
goog.asserts.assert(goog.isDef(replayGroup));
|
||||
var frameState = event.frameState;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var squaredTolerance = ol.renderer.vector.getSquaredTolerance(resolution,
|
||||
pixelRatio);
|
||||
var i, ii, styles, featureStyleFunction;
|
||||
this.features_.forEach(function(feature) {
|
||||
featureStyleFunction = feature.getStyleFunction();
|
||||
styles = goog.isDef(featureStyleFunction) ?
|
||||
featureStyleFunction.call(feature, resolution) :
|
||||
styleFunction(feature, resolution);
|
||||
|
||||
if (!goog.isDefAndNotNull(styles)) {
|
||||
return;
|
||||
}
|
||||
ii = styles.length;
|
||||
for (i = 0; i < ii; ++i) {
|
||||
ol.renderer.vector.renderFeature(replayGroup, feature, styles[i],
|
||||
squaredTolerance, this.handleImageChange_, this);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.removeFeature = function(feature) {
|
||||
this.features_.remove(feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.render_ = function() {
|
||||
if (!goog.isNull(this.map_)) {
|
||||
this.map_.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Collection.<ol.Feature>} features Features collection.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setFeatures = function(features) {
|
||||
if (!goog.isNull(this.featuresListenerKeys_)) {
|
||||
goog.array.forEach(this.featuresListenerKeys_, goog.events.unlistenByKey);
|
||||
this.featuresListenerKeys_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.featureChangeListenerKeys_)) {
|
||||
goog.array.forEach(
|
||||
goog.object.getValues(this.featureChangeListenerKeys_),
|
||||
goog.events.unlistenByKey);
|
||||
this.featureChangeListenerKeys_ = null;
|
||||
}
|
||||
this.features_ = features;
|
||||
if (!goog.isNull(features)) {
|
||||
this.featuresListenerKeys_ = [
|
||||
goog.events.listen(features, ol.CollectionEventType.ADD,
|
||||
this.handleFeaturesAdd_, false, this),
|
||||
goog.events.listen(features, ol.CollectionEventType.REMOVE,
|
||||
this.handleFeaturesRemove_, false, this)
|
||||
];
|
||||
this.featureChangeListenerKeys_ = {};
|
||||
features.forEach(function(feature) {
|
||||
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
|
||||
goog.events.listen(feature, goog.events.EventType.CHANGE,
|
||||
this.handleFeatureChange_, false, this);
|
||||
}, this);
|
||||
}
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setMap = function(map) {
|
||||
if (!goog.isNull(this.postComposeListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.postComposeListenerKey_);
|
||||
this.postComposeListenerKey_ = null;
|
||||
}
|
||||
this.render_();
|
||||
this.map_ = map;
|
||||
if (!goog.isNull(map)) {
|
||||
this.postComposeListenerKey_ = goog.events.listen(
|
||||
map, ol.render.EventType.POSTCOMPOSE, this.handleMapPostCompose_, false,
|
||||
this);
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the style for features. This can be a single style object, an array
|
||||
* of styles, or a function that takes a feature and resolution and returns
|
||||
* an array of styles.
|
||||
* @param {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction} style
|
||||
* Overlay style.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.setStyle = function(style) {
|
||||
this.style_ = style;
|
||||
this.styleFunction_ = ol.style.createStyleFunction(style);
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the style for features. This returns whatever was passed to the `style`
|
||||
* option at construction or to the `setStyle` method.
|
||||
* @return {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
|
||||
* Overlay style.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getStyle = function() {
|
||||
return this.style_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the style function.
|
||||
* @return {ol.style.StyleFunction|undefined} Style function.
|
||||
* @api
|
||||
*/
|
||||
ol.FeatureOverlay.prototype.getStyleFunction = function() {
|
||||
return this.styleFunction_;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.format
|
||||
*/
|
||||
@@ -0,0 +1,111 @@
|
||||
goog.provide('ol.format.BinaryFeature');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.binary.Buffer');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.FormatType');
|
||||
goog.require('ol.has');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.format.Feature}
|
||||
*/
|
||||
ol.format.BinaryFeature = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.BinaryFeature, ol.format.Feature);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @private
|
||||
* @return {ol.binary.Buffer} Buffer.
|
||||
*/
|
||||
ol.format.BinaryFeature.getBuffer_ = function(source) {
|
||||
if (ol.has.ARRAY_BUFFER && source instanceof ArrayBuffer) {
|
||||
return new ol.binary.Buffer(source);
|
||||
} else if (goog.isString(source)) {
|
||||
return new ol.binary.Buffer(source);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.getType = function() {
|
||||
return ol.format.FormatType.BINARY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readFeature = function(source) {
|
||||
return this.readFeatureFromBuffer(ol.format.BinaryFeature.getBuffer_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readFeatures = function(source) {
|
||||
return this.readFeaturesFromBuffer(
|
||||
ol.format.BinaryFeature.getBuffer_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.binary.Buffer} buffer Buffer.
|
||||
* @protected
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readFeatureFromBuffer = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.binary.Buffer} buffer Buffer.
|
||||
* @protected
|
||||
* @return {Array.<ol.Feature>} Feature.
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readFeaturesFromBuffer = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readGeometry = function(source) {
|
||||
return this.readGeometryFromBuffer(
|
||||
ol.format.BinaryFeature.getBuffer_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.binary.Buffer} buffer Buffer.
|
||||
* @protected
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readGeometryFromBuffer = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readProjection = function(source) {
|
||||
return this.readProjectionFromBuffer(
|
||||
ol.format.BinaryFeature.getBuffer_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.binary.Buffer} buffer Buffer.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.BinaryFeature.prototype.readProjectionFromBuffer =
|
||||
goog.abstractMethod;
|
||||
@@ -0,0 +1,184 @@
|
||||
goog.provide('ol.format.Feature');
|
||||
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for feature formats.
|
||||
* {ol.format.Feature} subclasses provide the ability to decode and encode
|
||||
* {@link ol.Feature} objects from a variety of commonly used geospatial
|
||||
* file formats. See the documentation for each format for more details.
|
||||
*
|
||||
* @constructor
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Feature = function() {
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.proj.Projection}
|
||||
*/
|
||||
this.defaultDataProjection = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<string>} Extensions.
|
||||
*/
|
||||
ol.format.Feature.prototype.getExtensions = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Adds the data projection to the read options.
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @return {olx.format.ReadOptions|undefined} Options.
|
||||
* @protected
|
||||
*/
|
||||
ol.format.Feature.prototype.getReadOptions = function(source, opt_options) {
|
||||
var options;
|
||||
if (goog.isDef(opt_options)) {
|
||||
options = {
|
||||
dataProjection: goog.isDef(opt_options.dataProjection) ?
|
||||
opt_options.dataProjection : this.readProjection(source),
|
||||
featureProjection: opt_options.featureProjection
|
||||
};
|
||||
}
|
||||
return this.adaptOptions(options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the `defaultDataProjection` on the options, if no `dataProjection`
|
||||
* is set.
|
||||
* @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options
|
||||
* Options.
|
||||
* @protected
|
||||
* @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined}
|
||||
* Updated options.
|
||||
*/
|
||||
ol.format.Feature.prototype.adaptOptions = function(options) {
|
||||
var updatedOptions;
|
||||
if (goog.isDef(options)) {
|
||||
updatedOptions = {
|
||||
featureProjection: options.featureProjection,
|
||||
dataProjection: goog.isDefAndNotNull(options.dataProjection) ?
|
||||
options.dataProjection : this.defaultDataProjection
|
||||
};
|
||||
}
|
||||
return updatedOptions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.format.FormatType} Format.
|
||||
*/
|
||||
ol.format.Feature.prototype.getType = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Read a single feature from a source.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.Feature.prototype.readFeature = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a source.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.Feature.prototype.readFeatures = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Read a single geometry from a source.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.Feature.prototype.readGeometry = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a source.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.Feature.prototype.readProjection = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Encode a feature in this format.
|
||||
*
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
ol.format.Feature.prototype.writeFeature = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features in this format.
|
||||
*
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
ol.format.Feature.prototype.writeFeatures = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Write a single geometry in this format.
|
||||
*
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
ol.format.Feature.prototype.writeGeometry = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
|
||||
* @param {boolean} write Set to true for writing, false for reading.
|
||||
* @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options
|
||||
* Options.
|
||||
* @return {ol.geom.Geometry|ol.Extent} Transformed geometry.
|
||||
* @protected
|
||||
*/
|
||||
ol.format.Feature.transformWithOptions = function(
|
||||
geometry, write, opt_options) {
|
||||
var featureProjection = goog.isDef(opt_options) ?
|
||||
ol.proj.get(opt_options.featureProjection) : null;
|
||||
var dataProjection = goog.isDef(opt_options) ?
|
||||
ol.proj.get(opt_options.dataProjection) : null;
|
||||
if (!goog.isNull(featureProjection) && !goog.isNull(dataProjection) &&
|
||||
!ol.proj.equivalent(featureProjection, dataProjection)) {
|
||||
if (geometry instanceof ol.geom.Geometry) {
|
||||
return (write ? geometry.clone() : geometry).transform(
|
||||
write ? featureProjection : dataProjection,
|
||||
write ? dataProjection : featureProjection);
|
||||
} else {
|
||||
// FIXME this is necessary because ol.format.GML treats extents
|
||||
// as geometries
|
||||
return ol.proj.transformExtent(
|
||||
write ? geometry.slice() : geometry,
|
||||
write ? featureProjection : dataProjection,
|
||||
write ? dataProjection : featureProjection);
|
||||
}
|
||||
} else {
|
||||
return geometry;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
goog.provide('ol.format.FormatType');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.format.FormatType = {
|
||||
BINARY: 'binary',
|
||||
JSON: 'json',
|
||||
TEXT: 'text',
|
||||
XML: 'xml'
|
||||
};
|
||||
@@ -0,0 +1,585 @@
|
||||
// FIXME coordinate order
|
||||
// FIXME reprojection
|
||||
|
||||
goog.provide('ol.format.GeoJSON');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.JSONFeature');
|
||||
goog.require('ol.geom.GeometryCollection');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GeoJSON format.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.JSONFeature}
|
||||
* @param {olx.format.GeoJSONOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get(
|
||||
goog.isDefAndNotNull(options.defaultDataProjection) ?
|
||||
options.defaultDataProjection : 'EPSG:4326');
|
||||
|
||||
|
||||
/**
|
||||
* Name of the geometry attribute for features.
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.geometryName_ = options.geometryName;
|
||||
|
||||
};
|
||||
goog.inherits(ol.format.GeoJSON, ol.format.JSONFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GeoJSON.EXTENSIONS_ = ['.geojson'];
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry|GeoJSONGeometryCollection} object Object.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @private
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.readGeometry_ = function(object, opt_options) {
|
||||
if (goog.isNull(object)) {
|
||||
return null;
|
||||
}
|
||||
var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type];
|
||||
goog.asserts.assert(goog.isDef(geometryReader));
|
||||
return /** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(
|
||||
geometryReader(object), false, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometryCollection} object Object.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @private
|
||||
* @return {ol.geom.GeometryCollection} Geometry collection.
|
||||
*/
|
||||
ol.format.GeoJSON.readGeometryCollectionGeometry_ = function(
|
||||
object, opt_options) {
|
||||
goog.asserts.assert(object.type == 'GeometryCollection');
|
||||
var geometries = goog.array.map(object.geometries,
|
||||
/**
|
||||
* @param {GeoJSONGeometry} geometry Geometry.
|
||||
* @return {ol.geom.Geometry} geometry Geometry.
|
||||
*/
|
||||
function(geometry) {
|
||||
return ol.format.GeoJSON.readGeometry_(geometry, opt_options);
|
||||
});
|
||||
return new ol.geom.GeometryCollection(geometries);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.Point} Point.
|
||||
*/
|
||||
ol.format.GeoJSON.readPointGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'Point');
|
||||
return new ol.geom.Point(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.LineString} LineString.
|
||||
*/
|
||||
ol.format.GeoJSON.readLineStringGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'LineString');
|
||||
return new ol.geom.LineString(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.MultiLineString} MultiLineString.
|
||||
*/
|
||||
ol.format.GeoJSON.readMultiLineStringGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'MultiLineString');
|
||||
return new ol.geom.MultiLineString(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.MultiPoint} MultiPoint.
|
||||
*/
|
||||
ol.format.GeoJSON.readMultiPointGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'MultiPoint');
|
||||
return new ol.geom.MultiPoint(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.MultiPolygon} MultiPolygon.
|
||||
*/
|
||||
ol.format.GeoJSON.readMultiPolygonGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'MultiPolygon');
|
||||
return new ol.geom.MultiPolygon(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @private
|
||||
* @return {ol.geom.Polygon} Polygon.
|
||||
*/
|
||||
ol.format.GeoJSON.readPolygonGeometry_ = function(object) {
|
||||
goog.asserts.assert(object.type == 'Polygon');
|
||||
return new ol.geom.Polygon(object.coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) {
|
||||
var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()];
|
||||
goog.asserts.assert(goog.isDef(geometryWriter));
|
||||
return geometryWriter(/** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, true, opt_options)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometryCollection} Empty GeoJSON geometry collection.
|
||||
*/
|
||||
ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_ = function(geometry) {
|
||||
return /** @type {GeoJSONGeometryCollection} */ ({
|
||||
'type': 'GeometryCollection',
|
||||
'geometries': []
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
|
||||
*/
|
||||
ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
|
||||
geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.GeometryCollection);
|
||||
var geometries = goog.array.map(
|
||||
geometry.getGeometriesArray(), function(geometry) {
|
||||
return ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
|
||||
});
|
||||
return /** @type {GeoJSONGeometryCollection} */ ({
|
||||
'type': 'GeometryCollection',
|
||||
'geometries': geometries
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'LineString',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString);
|
||||
goog.asserts.assert(
|
||||
geometry.getType() == ol.geom.GeometryType.MULTI_LINE_STRING);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiLineString',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPoint);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPoint',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPolygon);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPolygon',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writePointGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Point',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writePolygonGeometry_ = function(geometry) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Polygon);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Polygon',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<string, function(GeoJSONObject): ol.geom.Geometry>}
|
||||
*/
|
||||
ol.format.GeoJSON.GEOMETRY_READERS_ = {
|
||||
'Point': ol.format.GeoJSON.readPointGeometry_,
|
||||
'LineString': ol.format.GeoJSON.readLineStringGeometry_,
|
||||
'Polygon': ol.format.GeoJSON.readPolygonGeometry_,
|
||||
'MultiPoint': ol.format.GeoJSON.readMultiPointGeometry_,
|
||||
'MultiLineString': ol.format.GeoJSON.readMultiLineStringGeometry_,
|
||||
'MultiPolygon': ol.format.GeoJSON.readMultiPolygonGeometry_,
|
||||
'GeometryCollection': ol.format.GeoJSON.readGeometryCollectionGeometry_
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<string, function(ol.geom.Geometry): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
|
||||
*/
|
||||
ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
|
||||
'Point': ol.format.GeoJSON.writePointGeometry_,
|
||||
'LineString': ol.format.GeoJSON.writeLineStringGeometry_,
|
||||
'Polygon': ol.format.GeoJSON.writePolygonGeometry_,
|
||||
'MultiPoint': ol.format.GeoJSON.writeMultiPointGeometry_,
|
||||
'MultiLineString': ol.format.GeoJSON.writeMultiLineStringGeometry_,
|
||||
'MultiPolygon': ol.format.GeoJSON.writeMultiPolygonGeometry_,
|
||||
'GeometryCollection': ol.format.GeoJSON.writeGeometryCollectionGeometry_,
|
||||
'Circle': ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.getExtensions = function() {
|
||||
return ol.format.GeoJSON.EXTENSIONS_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read a feature from a GeoJSON Feature source. Only works for Feature,
|
||||
* use `readFeatures` to read FeatureCollection source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readFeature;
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a GeoJSON source. Works with both Feature and
|
||||
* FeatureCollection sources.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readFeatureFromObject = function(
|
||||
object, opt_options) {
|
||||
var geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
|
||||
goog.asserts.assert(geoJSONFeature.type == 'Feature');
|
||||
var geometry = ol.format.GeoJSON.readGeometry_(geoJSONFeature.geometry,
|
||||
opt_options);
|
||||
var feature = new ol.Feature();
|
||||
if (goog.isDef(this.geometryName_)) {
|
||||
feature.setGeometryName(this.geometryName_);
|
||||
}
|
||||
feature.setGeometry(geometry);
|
||||
if (goog.isDef(geoJSONFeature.id)) {
|
||||
feature.setId(geoJSONFeature.id);
|
||||
}
|
||||
if (goog.isDef(geoJSONFeature.properties)) {
|
||||
feature.setProperties(geoJSONFeature.properties);
|
||||
}
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readFeaturesFromObject = function(
|
||||
object, opt_options) {
|
||||
var geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
||||
if (geoJSONObject.type == 'Feature') {
|
||||
return [this.readFeatureFromObject(object, opt_options)];
|
||||
} else if (geoJSONObject.type == 'FeatureCollection') {
|
||||
var geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */
|
||||
(object);
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
var geoJSONFeatures = geoJSONFeatureCollection.features;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
|
||||
features.push(this.readFeatureFromObject(geoJSONFeatures[i],
|
||||
opt_options));
|
||||
}
|
||||
return features;
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read a geometry from a GeoJSON source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readGeometryFromObject = function(
|
||||
object, opt_options) {
|
||||
return ol.format.GeoJSON.readGeometry_(
|
||||
/** @type {GeoJSONGeometry} */ (object), opt_options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a GeoJSON source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readProjection;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.readProjectionFromObject = function(object) {
|
||||
var geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
||||
var crs = geoJSONObject.crs;
|
||||
if (goog.isDefAndNotNull(crs)) {
|
||||
if (crs.type == 'name') {
|
||||
return ol.proj.get(crs.properties.name);
|
||||
} else if (crs.type == 'EPSG') {
|
||||
// 'EPSG' is not part of the GeoJSON specification, but is generated by
|
||||
// GeoServer.
|
||||
// TODO: remove this when http://jira.codehaus.org/browse/GEOS-5996
|
||||
// is fixed and widely deployed.
|
||||
return ol.proj.get('EPSG:' + crs.properties.code);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return this.defaultDataProjection;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a feature as a GeoJSON Feature string.
|
||||
*
|
||||
* @function
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} GeoJSON.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeFeature;
|
||||
|
||||
|
||||
/**
|
||||
* Encode a feature as a GeoJSON Feature object.
|
||||
*
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @api
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeFeatureObject = function(
|
||||
feature, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
var object = {
|
||||
'type': 'Feature'
|
||||
};
|
||||
var id = feature.getId();
|
||||
if (goog.isDefAndNotNull(id)) {
|
||||
object['id'] = id;
|
||||
}
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
object['geometry'] =
|
||||
ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
|
||||
}
|
||||
var properties = feature.getProperties();
|
||||
goog.object.remove(properties, feature.getGeometryName());
|
||||
if (!goog.object.isEmpty(properties)) {
|
||||
object['properties'] = properties;
|
||||
} else {
|
||||
object['properties'] = null;
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features as GeoJSON.
|
||||
*
|
||||
* @function
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} GeoJSON.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features as a GeoJSON object.
|
||||
*
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {Object} GeoJSON Object.
|
||||
* @api
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeFeaturesObject =
|
||||
function(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
var objects = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = features.length; i < ii; ++i) {
|
||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||
}
|
||||
return /** @type {GeoJSONFeatureCollection} */ ({
|
||||
'type': 'FeatureCollection',
|
||||
'features': objects
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a geometry as a GeoJSON string.
|
||||
*
|
||||
* @function
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} GeoJSON.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* Encode a geometry as a GeoJSON object.
|
||||
*
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
|
||||
* @api
|
||||
*/
|
||||
ol.format.GeoJSON.prototype.writeGeometryObject = function(geometry,
|
||||
opt_options) {
|
||||
return ol.format.GeoJSON.writeGeometry_(geometry,
|
||||
this.adaptOptions(opt_options));
|
||||
};
|
||||
@@ -0,0 +1,216 @@
|
||||
goog.provide('ol.format.GML2');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.format.GML');
|
||||
goog.require('ol.format.GMLBase');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GML format,
|
||||
* version 2.1.2.
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.format.GMLOptions=} opt_options Optional configuration object.
|
||||
* @extends {ol.format.GMLBase}
|
||||
* @api
|
||||
*/
|
||||
ol.format.GML2 = function(opt_options) {
|
||||
var options = /** @type {olx.format.GMLOptions} */
|
||||
(goog.isDef(opt_options) ? opt_options : {});
|
||||
|
||||
goog.base(this, options);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.schemaLocation = goog.isDef(options.schemaLocation) ?
|
||||
options.schemaLocation : ol.format.GML2.schemaLocation_;
|
||||
|
||||
};
|
||||
goog.inherits(ol.format.GML2, ol.format.GMLBase);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.schemaLocation_ = ol.format.GMLBase.GMLNS +
|
||||
' http://schemas.opengis.net/gml/2.1.2/feature.xsd';
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Array.<number>|undefined} Flat coordinates.
|
||||
*/
|
||||
ol.format.GML2.prototype.readFlatCoordinates_ = function(node, objectStack) {
|
||||
var s = ol.xml.getAllTextContent(node, false).replace(/^\s*|\s*$/g, '');
|
||||
var context = objectStack[0];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var containerSrs = context['srsName'];
|
||||
var containerDimension = node.parentNode.getAttribute('srsDimension');
|
||||
var axisOrientation = 'enu';
|
||||
if (!goog.isNull(containerSrs)) {
|
||||
var proj = ol.proj.get(containerSrs);
|
||||
axisOrientation = proj.getAxisOrientation();
|
||||
}
|
||||
var coords = s.split(/[\s,]+/);
|
||||
// The "dimension" attribute is from the GML 3.0.1 spec.
|
||||
var dim = 2;
|
||||
if (!goog.isNull(node.getAttribute('srsDimension'))) {
|
||||
dim = ol.format.XSD.readNonNegativeIntegerString(
|
||||
node.getAttribute('srsDimension'));
|
||||
} else if (!goog.isNull(node.getAttribute('dimension'))) {
|
||||
dim = ol.format.XSD.readNonNegativeIntegerString(
|
||||
node.getAttribute('dimension'));
|
||||
} else if (!goog.isNull(containerDimension)) {
|
||||
dim = ol.format.XSD.readNonNegativeIntegerString(containerDimension);
|
||||
}
|
||||
var x, y, z;
|
||||
var flatCoordinates = [];
|
||||
for (var i = 0, ii = coords.length; i < ii; i += dim) {
|
||||
x = parseFloat(coords[i]);
|
||||
y = parseFloat(coords[i + 1]);
|
||||
z = (dim === 3) ? parseFloat(coords[i + 2]) : 0;
|
||||
if (axisOrientation.substr(0, 2) === 'en') {
|
||||
flatCoordinates.push(x, y, z);
|
||||
} else {
|
||||
flatCoordinates.push(y, x, z);
|
||||
}
|
||||
}
|
||||
return flatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Extent|undefined} Envelope.
|
||||
*/
|
||||
ol.format.GML2.prototype.readBox_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Box');
|
||||
var flatCoordinates = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<number>} */ ([null]),
|
||||
this.BOX_PARSERS_, node, objectStack, this);
|
||||
return ol.extent.createOrUpdate(flatCoordinates[1][0],
|
||||
flatCoordinates[1][1], flatCoordinates[1][3],
|
||||
flatCoordinates[1][4]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.innerBoundaryIsParser_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'innerBoundaryIs');
|
||||
var flatLinearRing = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<number>|undefined} */ (undefined),
|
||||
this.RING_PARSERS, node, objectStack, this);
|
||||
if (goog.isDef(flatLinearRing)) {
|
||||
var flatLinearRings = /** @type {Array.<Array.<number>>} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
goog.asserts.assert(goog.isArray(flatLinearRings));
|
||||
goog.asserts.assert(flatLinearRings.length > 0);
|
||||
flatLinearRings.push(flatLinearRing);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.outerBoundaryIsParser_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'outerBoundaryIs');
|
||||
var flatLinearRing = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<number>|undefined} */ (undefined),
|
||||
this.RING_PARSERS, node, objectStack, this);
|
||||
if (goog.isDef(flatLinearRing)) {
|
||||
var flatLinearRings = /** @type {Array.<Array.<number>>} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
goog.asserts.assert(goog.isArray(flatLinearRings));
|
||||
goog.asserts.assert(flatLinearRings.length > 0);
|
||||
flatLinearRings[0] = flatLinearRing;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'coordinates': ol.xml.makeReplacer(
|
||||
ol.format.GML2.prototype.readFlatCoordinates_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'innerBoundaryIs': ol.format.GML2.prototype.innerBoundaryIsParser_,
|
||||
'outerBoundaryIs': ol.format.GML2.prototype.outerBoundaryIsParser_
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.BOX_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'coordinates': ol.xml.makeArrayPusher(
|
||||
ol.format.GML2.prototype.readFlatCoordinates_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GML2.prototype.GEOMETRY_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'Point': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPoint),
|
||||
'MultiPoint': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readMultiPoint),
|
||||
'LineString': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readLineString),
|
||||
'MultiLineString': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readMultiLineString),
|
||||
'LinearRing' : ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readLinearRing),
|
||||
'Polygon': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPolygon),
|
||||
'MultiPolygon': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readMultiPolygon),
|
||||
'Box': ol.xml.makeReplacer(ol.format.GML2.prototype.readBox_)
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,599 @@
|
||||
// FIXME Envelopes should not be treated as geometries! readEnvelope_ is part
|
||||
// of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect
|
||||
// envelopes/extents, only geometries!
|
||||
goog.provide('ol.format.GMLBase');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Feature base format for reading and writing data in the GML format.
|
||||
* This class cannot be instantiate, it contains only base content that
|
||||
* is shared with versioned format classes ol.format.GML2 and
|
||||
* ol.format.GML3.
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.format.GMLOptions=} opt_options
|
||||
* Optional configuration object.
|
||||
* @extends {ol.format.XMLFeature}
|
||||
* @api
|
||||
*/
|
||||
ol.format.GMLBase = function(opt_options) {
|
||||
var options = /** @type {olx.format.GMLOptions} */
|
||||
(goog.isDef(opt_options) ? opt_options : {});
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<string>|string|undefined}
|
||||
*/
|
||||
this.featureType = options.featureType;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Object.<string, string>|string|undefined}
|
||||
*/
|
||||
this.featureNS = options.featureNS;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {string}
|
||||
*/
|
||||
this.srsName = options.srsName;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {string}
|
||||
*/
|
||||
this.schemaLocation = '';
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, Object>>}
|
||||
*/
|
||||
this.FEATURE_COLLECTION_PARSERS = {};
|
||||
this.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS] = {
|
||||
'featureMember': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readFeaturesInternal),
|
||||
'featureMembers': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readFeaturesInternal)
|
||||
};
|
||||
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.GMLBase, ol.format.XMLFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.GMLBase.GMLNS = 'http://www.opengis.net/gml';
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
var localName = ol.xml.getLocalName(node);
|
||||
var features;
|
||||
if (localName == 'FeatureCollection') {
|
||||
features = ol.xml.pushParseAndPop(null,
|
||||
this.FEATURE_COLLECTION_PARSERS, node,
|
||||
objectStack, this);
|
||||
} else if (localName == 'featureMembers' || localName == 'featureMember') {
|
||||
var context = objectStack[0];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var featureType = context['featureType'];
|
||||
var featureNS = context['featureNS'];
|
||||
var i, ii, prefix = 'p', defaultPrefix = 'p0';
|
||||
if (!goog.isDef(featureType) && goog.isDefAndNotNull(node.childNodes)) {
|
||||
featureType = [], featureNS = {};
|
||||
for (i = 0, ii = node.childNodes.length; i < ii; ++i) {
|
||||
var child = node.childNodes[i];
|
||||
if (child.nodeType === 1) {
|
||||
var ft = child.nodeName.split(':').pop();
|
||||
if (goog.array.indexOf(featureType, ft) === -1) {
|
||||
var key;
|
||||
if (!goog.object.contains(featureNS, child.namespaceURI)) {
|
||||
key = prefix + goog.object.getCount(featureNS);
|
||||
featureNS[key] = child.namespaceURI;
|
||||
} else {
|
||||
key = goog.object.findKey(featureNS, function(value) {
|
||||
return value === child.namespaceURI;
|
||||
});
|
||||
}
|
||||
featureType.push(key + ':' + ft);
|
||||
}
|
||||
}
|
||||
}
|
||||
context['featureType'] = featureType;
|
||||
context['featureNS'] = featureNS;
|
||||
}
|
||||
if (goog.isString(featureNS)) {
|
||||
var ns = featureNS;
|
||||
featureNS = {};
|
||||
featureNS[defaultPrefix] = ns;
|
||||
}
|
||||
var parsersNS = {};
|
||||
var featureTypes = goog.isArray(featureType) ? featureType : [featureType];
|
||||
for (var p in featureNS) {
|
||||
var parsers = {};
|
||||
for (i = 0, ii = featureTypes.length; i < ii; ++i) {
|
||||
var featurePrefix = featureTypes[i].indexOf(':') === -1 ?
|
||||
defaultPrefix : featureTypes[i].split(':')[0];
|
||||
if (featurePrefix === p) {
|
||||
parsers[featureTypes[i].split(':').pop()] =
|
||||
(localName == 'featureMembers') ?
|
||||
ol.xml.makeArrayPusher(this.readFeatureElement, this) :
|
||||
ol.xml.makeReplacer(this.readFeatureElement, this);
|
||||
}
|
||||
}
|
||||
parsersNS[featureNS[p]] = parsers;
|
||||
}
|
||||
features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack);
|
||||
}
|
||||
if (!goog.isDef(features)) {
|
||||
features = [];
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.Geometry|undefined} Geometry.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readGeometryElement = function(node, objectStack) {
|
||||
var context = objectStack[0];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
context['srsName'] = node.firstElementChild.getAttribute('srsName');
|
||||
var geometry = ol.xml.pushParseAndPop(/** @type {ol.geom.Geometry} */(null),
|
||||
this.GEOMETRY_PARSERS_, node, objectStack, this);
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
return /** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, false, context));
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) {
|
||||
var n;
|
||||
var fid = node.getAttribute('fid') ||
|
||||
ol.xml.getAttributeNS(node, ol.format.GMLBase.GMLNS, 'id');
|
||||
var values = {}, geometryName;
|
||||
for (n = node.firstElementChild; !goog.isNull(n);
|
||||
n = n.nextElementSibling) {
|
||||
var localName = ol.xml.getLocalName(n);
|
||||
// Assume attribute elements have one child node and that the child
|
||||
// is a text node. Otherwise assume it is a geometry node.
|
||||
if (n.childNodes.length === 0 ||
|
||||
(n.childNodes.length === 1 &&
|
||||
n.firstChild.nodeType === 3)) {
|
||||
var value = ol.xml.getAllTextContent(n, false);
|
||||
if (goog.string.isEmpty(value)) {
|
||||
value = undefined;
|
||||
}
|
||||
values[localName] = value;
|
||||
} else {
|
||||
// boundedBy is an extent and must not be considered as a geometry
|
||||
if (localName !== 'boundedBy') {
|
||||
geometryName = localName;
|
||||
}
|
||||
values[localName] = this.readGeometryElement(n, objectStack);
|
||||
}
|
||||
}
|
||||
var feature = new ol.Feature(values);
|
||||
if (goog.isDef(geometryName)) {
|
||||
feature.setGeometryName(geometryName);
|
||||
}
|
||||
if (fid) {
|
||||
feature.setId(fid);
|
||||
}
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.Point|undefined} Point.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readPoint = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Point');
|
||||
var flatCoordinates =
|
||||
this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||
if (goog.isDefAndNotNull(flatCoordinates)) {
|
||||
var point = new ol.geom.Point(null);
|
||||
goog.asserts.assert(flatCoordinates.length == 3);
|
||||
point.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
|
||||
return point;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.MultiPoint|undefined} MultiPoint.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readMultiPoint = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'MultiPoint');
|
||||
var coordinates = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<Array.<number>>} */ ([]),
|
||||
this.MULTIPOINT_PARSERS_, node, objectStack, this);
|
||||
if (goog.isDef(coordinates)) {
|
||||
return new ol.geom.MultiPoint(coordinates);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.MultiLineString|undefined} MultiLineString.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readMultiLineString = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'MultiLineString');
|
||||
var lineStrings = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<ol.geom.LineString>} */ ([]),
|
||||
this.MULTILINESTRING_PARSERS_, node, objectStack, this);
|
||||
if (goog.isDef(lineStrings)) {
|
||||
var multiLineString = new ol.geom.MultiLineString(null);
|
||||
multiLineString.setLineStrings(lineStrings);
|
||||
return multiLineString;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.MultiPolygon|undefined} MultiPolygon.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readMultiPolygon = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'MultiPolygon');
|
||||
var polygons = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<ol.geom.Polygon>} */ ([]),
|
||||
this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
|
||||
if (goog.isDef(polygons)) {
|
||||
var multiPolygon = new ol.geom.MultiPolygon(null);
|
||||
multiPolygon.setPolygons(polygons);
|
||||
return multiPolygon;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.pointMemberParser_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'pointMember' ||
|
||||
node.localName == 'pointMembers');
|
||||
ol.xml.parseNode(this.POINTMEMBER_PARSERS_,
|
||||
node, objectStack, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.lineStringMemberParser_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'lineStringMember' ||
|
||||
node.localName == 'lineStringMembers');
|
||||
ol.xml.parseNode(this.LINESTRINGMEMBER_PARSERS_,
|
||||
node, objectStack, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.polygonMemberParser_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'polygonMember' ||
|
||||
node.localName == 'polygonMembers');
|
||||
ol.xml.parseNode(this.POLYGONMEMBER_PARSERS_, node,
|
||||
objectStack, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.LineString|undefined} LineString.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readLineString = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'LineString');
|
||||
var flatCoordinates =
|
||||
this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||
if (goog.isDefAndNotNull(flatCoordinates)) {
|
||||
var lineString = new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
|
||||
return lineString;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Array.<number>|undefined} LinearRing flat coordinates.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'LinearRing');
|
||||
var ring = ol.xml.pushParseAndPop(/** @type {Array.<number>} */(null),
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
|
||||
objectStack, this);
|
||||
if (goog.isDefAndNotNull(ring)) {
|
||||
return ring;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.LinearRing|undefined} LinearRing.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readLinearRing = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'LinearRing');
|
||||
var flatCoordinates =
|
||||
this.readFlatCoordinatesFromNode_(node, objectStack);
|
||||
if (goog.isDef(flatCoordinates)) {
|
||||
var ring = new ol.geom.LinearRing(null);
|
||||
ring.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
|
||||
return ring;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.geom.Polygon|undefined} Polygon.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readPolygon = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Polygon');
|
||||
var flatLinearRings = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<Array.<number>>} */ ([null]),
|
||||
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
|
||||
if (goog.isDef(flatLinearRings) &&
|
||||
!goog.isNull(flatLinearRings[0])) {
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
var flatCoordinates = flatLinearRings[0];
|
||||
var ends = [flatCoordinates.length];
|
||||
var i, ii;
|
||||
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
|
||||
goog.array.extend(flatCoordinates, flatLinearRings[i]);
|
||||
ends.push(flatCoordinates.length);
|
||||
}
|
||||
polygon.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XYZ, flatCoordinates, ends);
|
||||
return polygon;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return /** @type {Array.<number>} */ (ol.xml.pushParseAndPop(
|
||||
null,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
|
||||
objectStack, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.MULTIPOINT_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'pointMember': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.pointMemberParser_),
|
||||
'pointMembers': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.pointMemberParser_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.MULTILINESTRING_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'lineStringMember': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.lineStringMemberParser_),
|
||||
'lineStringMembers': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.lineStringMemberParser_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.MULTIPOLYGON_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'polygonMember': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.polygonMemberParser_),
|
||||
'polygonMembers': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.polygonMemberParser_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.POINTMEMBER_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'Point': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.LINESTRINGMEMBER_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'LineString': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.readLineString)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GMLBase.prototype.POLYGONMEMBER_PARSERS_ = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'Polygon': ol.xml.makeArrayPusher(
|
||||
ol.format.GMLBase.prototype.readPolygon)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
ol.format.GMLBase.prototype.RING_PARSERS = Object({
|
||||
'http://www.opengis.net/gml' : {
|
||||
'LinearRing': ol.xml.makeReplacer(
|
||||
ol.format.GMLBase.prototype.readFlatLinearRing_)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readGeometryFromNode =
|
||||
function(node, opt_options) {
|
||||
var geometry = this.readGeometryElement(node,
|
||||
[this.getReadOptions(node, goog.isDef(opt_options) ? opt_options : {})]);
|
||||
return goog.isDef(geometry) ? geometry : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a GML FeatureCollection.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readFeaturesFromNode =
|
||||
function(node, opt_options) {
|
||||
var options = {
|
||||
featureType: this.featureType,
|
||||
featureNS: this.featureNS
|
||||
};
|
||||
if (goog.isDef(opt_options)) {
|
||||
goog.object.extend(options, this.getReadOptions(node, opt_options));
|
||||
}
|
||||
return this.readFeaturesInternal(node, [options]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GMLBase.prototype.readProjectionFromNode = function(node) {
|
||||
return ol.proj.get(goog.isDef(this.srsName_) ? this.srsName_ :
|
||||
node.firstElementChild.getAttribute('srsName'));
|
||||
};
|
||||
@@ -0,0 +1,876 @@
|
||||
goog.provide('ol.format.GPX');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GPX format.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.XMLFeature}
|
||||
* @param {olx.format.GPXOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GPX = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @type {function(ol.Feature, Node)|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.readExtensions_ = options.readExtensions;
|
||||
};
|
||||
goog.inherits(ol.format.GPX, ol.format.XMLFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.format.GPX.NAMESPACE_URIS_ = [
|
||||
null,
|
||||
'http://www.topografix.com/GPX/1/0',
|
||||
'http://www.topografix.com/GPX/1/1'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {Node} node Node.
|
||||
* @param {Object} values Values.
|
||||
* @private
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.format.GPX.appendCoordinate_ = function(flatCoordinates, node, values) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
flatCoordinates.push(
|
||||
parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat')));
|
||||
if (goog.object.containsKey(values, 'ele')) {
|
||||
flatCoordinates.push(
|
||||
/** @type {number} */ (values['ele']));
|
||||
goog.object.remove(values, 'ele');
|
||||
} else {
|
||||
flatCoordinates.push(0);
|
||||
}
|
||||
if (goog.object.containsKey(values, 'time')) {
|
||||
flatCoordinates.push(
|
||||
/** @type {number} */ (values['time']));
|
||||
goog.object.remove(values, 'time');
|
||||
} else {
|
||||
flatCoordinates.push(0);
|
||||
}
|
||||
return flatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.parseLink_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'link');
|
||||
var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
var href = node.getAttribute('href');
|
||||
if (!goog.isNull(href)) {
|
||||
values['link'] = href;
|
||||
}
|
||||
ol.xml.parseNode(ol.format.GPX.LINK_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.parseExtensions_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'extensions');
|
||||
var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values['extensionsNode_'] = node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.parseRtePt_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'rtept');
|
||||
var values = ol.xml.pushParseAndPop(
|
||||
{}, ol.format.GPX.RTEPT_PARSERS_, node, objectStack);
|
||||
if (goog.isDef(values)) {
|
||||
var rteValues = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
var flatCoordinates = /** @type {Array.<number>} */
|
||||
(rteValues['flatCoordinates']);
|
||||
ol.format.GPX.appendCoordinate_(flatCoordinates, node, values);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.parseTrkPt_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'trkpt');
|
||||
var values = ol.xml.pushParseAndPop(
|
||||
{}, ol.format.GPX.TRKPT_PARSERS_, node, objectStack);
|
||||
if (goog.isDef(values)) {
|
||||
var trkValues = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
var flatCoordinates = /** @type {Array.<number>} */
|
||||
(trkValues['flatCoordinates']);
|
||||
ol.format.GPX.appendCoordinate_(flatCoordinates, node, values);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.parseTrkSeg_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'trkseg');
|
||||
var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
ol.xml.parseNode(ol.format.GPX.TRKSEG_PARSERS_, node, objectStack);
|
||||
var flatCoordinates = /** @type {Array.<number>} */
|
||||
(values['flatCoordinates']);
|
||||
var ends = /** @type {Array.<number>} */ (values['ends']);
|
||||
ends.push(flatCoordinates.length);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Feature|undefined} Track.
|
||||
*/
|
||||
ol.format.GPX.readRte_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'rte');
|
||||
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
|
||||
var values = ol.xml.pushParseAndPop({
|
||||
'flatCoordinates': []
|
||||
}, ol.format.GPX.RTE_PARSERS_, node, objectStack);
|
||||
if (!goog.isDef(values)) {
|
||||
return undefined;
|
||||
}
|
||||
var flatCoordinates = /** @type {Array.<number>} */
|
||||
(values['flatCoordinates']);
|
||||
goog.object.remove(values, 'flatCoordinates');
|
||||
var geometry = new ol.geom.LineString(null);
|
||||
geometry.setFlatCoordinates(ol.geom.GeometryLayout.XYZM, flatCoordinates);
|
||||
ol.format.Feature.transformWithOptions(geometry, false, options);
|
||||
var feature = new ol.Feature(geometry);
|
||||
feature.setProperties(values);
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Feature|undefined} Track.
|
||||
*/
|
||||
ol.format.GPX.readTrk_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'trk');
|
||||
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
|
||||
var values = ol.xml.pushParseAndPop({
|
||||
'flatCoordinates': [],
|
||||
'ends': []
|
||||
}, ol.format.GPX.TRK_PARSERS_, node, objectStack);
|
||||
if (!goog.isDef(values)) {
|
||||
return undefined;
|
||||
}
|
||||
var flatCoordinates = /** @type {Array.<number>} */
|
||||
(values['flatCoordinates']);
|
||||
goog.object.remove(values, 'flatCoordinates');
|
||||
var ends = /** @type {Array.<number>} */ (values['ends']);
|
||||
goog.object.remove(values, 'ends');
|
||||
var geometry = new ol.geom.MultiLineString(null);
|
||||
geometry.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XYZM, flatCoordinates, ends);
|
||||
ol.format.Feature.transformWithOptions(geometry, false, options);
|
||||
var feature = new ol.Feature(geometry);
|
||||
feature.setProperties(values);
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Feature|undefined} Waypoint.
|
||||
*/
|
||||
ol.format.GPX.readWpt_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'wpt');
|
||||
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
|
||||
var values = ol.xml.pushParseAndPop(
|
||||
{}, ol.format.GPX.WPT_PARSERS_, node, objectStack);
|
||||
if (!goog.isDef(values)) {
|
||||
return undefined;
|
||||
}
|
||||
var coordinates = ol.format.GPX.appendCoordinate_([], node, values);
|
||||
var geometry = new ol.geom.Point(
|
||||
coordinates, ol.geom.GeometryLayout.XYZM);
|
||||
ol.format.Feature.transformWithOptions(geometry, false, options);
|
||||
var feature = new ol.Feature(geometry);
|
||||
feature.setProperties(values);
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, function(Node, Array.<*>): (ol.Feature|undefined)>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.FEATURE_READER_ = {
|
||||
'rte': ol.format.GPX.readRte_,
|
||||
'trk': ol.format.GPX.readTrk_,
|
||||
'wpt': ol.format.GPX.readWpt_
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.GPX_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'rte': ol.xml.makeArrayPusher(ol.format.GPX.readRte_),
|
||||
'trk': ol.xml.makeArrayPusher(ol.format.GPX.readTrk_),
|
||||
'wpt': ol.xml.makeArrayPusher(ol.format.GPX.readWpt_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.LINK_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'text':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readString, 'linkText'),
|
||||
'type':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readString, 'linkType')
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.RTE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'link': ol.format.GPX.parseLink_,
|
||||
'number':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
|
||||
'extensions': ol.format.GPX.parseExtensions_,
|
||||
'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'rtept': ol.format.GPX.parseRtePt_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.RTEPT_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRK_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'link': ol.format.GPX.parseLink_,
|
||||
'number':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
|
||||
'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'extensions': ol.format.GPX.parseExtensions_,
|
||||
'trkseg': ol.format.GPX.parseTrkSeg_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRKSEG_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'trkpt': ol.format.GPX.parseTrkPt_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRKPT_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.WPT_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime),
|
||||
'magvar': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'geoidheight': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'link': ol.format.GPX.parseLink_,
|
||||
'sym': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'fix': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'sat': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'hdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'vdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'pdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'ageofdgpsdata':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
|
||||
'dgpsid':
|
||||
ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
|
||||
'extensions': ol.format.GPX.parseExtensions_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Feature>} features
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.prototype.handleReadExtensions_ = function(features) {
|
||||
if (goog.isNull(features)) {
|
||||
features = [];
|
||||
}
|
||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||
var feature = features[i];
|
||||
if (goog.isDef(this.readExtensions_)) {
|
||||
var extensionsNode = feature.get('extensionsNode_') || null;
|
||||
this.readExtensions_(feature, extensionsNode);
|
||||
}
|
||||
feature.set('extensionsNode_', undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the first feature from a GPX source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GPX.prototype.readFeature;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GPX.prototype.readFeatureFromNode = function(node, opt_options) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
if (!goog.array.contains(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) {
|
||||
return null;
|
||||
}
|
||||
var featureReader = ol.format.GPX.FEATURE_READER_[node.localName];
|
||||
if (!goog.isDef(featureReader)) {
|
||||
return null;
|
||||
}
|
||||
var feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
|
||||
if (!goog.isDef(feature)) {
|
||||
return null;
|
||||
}
|
||||
this.handleReadExtensions_([feature]);
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a GPX source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GPX.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.GPX.prototype.readFeaturesFromNode = function(node, opt_options) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
if (!goog.array.contains(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) {
|
||||
return [];
|
||||
}
|
||||
if (node.localName == 'gpx') {
|
||||
var features = ol.xml.pushParseAndPop(
|
||||
/** @type {Array.<ol.Feature>} */ ([]), ol.format.GPX.GPX_PARSERS_,
|
||||
node, [this.getReadOptions(node, opt_options)]);
|
||||
if (goog.isDef(features)) {
|
||||
this.handleReadExtensions_(features);
|
||||
return features;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a GPX source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GPX.prototype.readProjection;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {string} value Value for the link's `href` attribute.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeLink_ = function(node, value, objectStack) {
|
||||
node.setAttribute('href', value);
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var properties = context['properties'];
|
||||
var link = [
|
||||
properties['linkText'],
|
||||
properties['linkType']
|
||||
];
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: node}),
|
||||
ol.format.GPX.LINK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
|
||||
link, objectStack, ol.format.GPX.LINK_SEQUENCE_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var parentNode = context.node;
|
||||
goog.asserts.assert(ol.xml.isNode(parentNode));
|
||||
var namespaceURI = parentNode.namespaceURI;
|
||||
var properties = context['properties'];
|
||||
//FIXME Projection handling
|
||||
ol.xml.setAttributeNS(node, null, 'lat', coordinate[1]);
|
||||
ol.xml.setAttributeNS(node, null, 'lon', coordinate[0]);
|
||||
var geometryLayout = context['geometryLayout'];
|
||||
/* jshint -W086 */
|
||||
switch (geometryLayout) {
|
||||
case ol.geom.GeometryLayout.XYZM:
|
||||
if (coordinate[3] !== 0) {
|
||||
properties['time'] = coordinate[3];
|
||||
}
|
||||
case ol.geom.GeometryLayout.XYZ:
|
||||
if (coordinate[2] !== 0) {
|
||||
properties['ele'] = coordinate[2];
|
||||
}
|
||||
break;
|
||||
case ol.geom.GeometryLayout.XYM:
|
||||
if (coordinate[2] !== 0) {
|
||||
properties['time'] = coordinate[2];
|
||||
}
|
||||
}
|
||||
/* jshint +W086 */
|
||||
var orderedKeys = ol.format.GPX.WPT_TYPE_SEQUENCE_[namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
|
||||
({node: node, 'properties': properties}),
|
||||
ol.format.GPX.WPT_TYPE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeRte_ = function(node, feature, objectStack) {
|
||||
var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
|
||||
var properties = feature.getProperties();
|
||||
var context = {node: node, 'properties': properties};
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDef(geometry)) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
|
||||
geometry = /** @type {ol.geom.LineString} */
|
||||
(ol.format.Feature.transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = geometry.getLayout();
|
||||
properties['rtept'] = geometry.getCoordinates();
|
||||
}
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.GPX.RTE_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
|
||||
ol.format.GPX.RTE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeTrk_ = function(node, feature, objectStack) {
|
||||
var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
|
||||
var properties = feature.getProperties();
|
||||
var context = {node: node, 'properties': properties};
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDef(geometry)) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString);
|
||||
geometry = /** @type {ol.geom.MultiLineString} */
|
||||
(ol.format.Feature.transformWithOptions(geometry, true, options));
|
||||
properties['trkseg'] = geometry.getLineStrings();
|
||||
}
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.GPX.TRK_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
|
||||
ol.format.GPX.TRK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.geom.LineString} lineString LineString.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeTrkSeg_ = function(node, lineString, objectStack) {
|
||||
var context = {node: node, 'geometryLayout': lineString.getLayout(),
|
||||
'properties': {}};
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ (context),
|
||||
ol.format.GPX.TRKSEG_SERIALIZERS_, ol.format.GPX.TRKSEG_NODE_FACTORY_,
|
||||
lineString.getCoordinates(), objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.writeWpt_ = function(node, feature, objectStack) {
|
||||
var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
context['properties'] = feature.getProperties();
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDef(geometry)) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
|
||||
geometry = /** @type {ol.geom.Point} */
|
||||
(ol.format.Feature.transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = geometry.getLayout();
|
||||
ol.format.GPX.writeWptType_(node, geometry.getCoordinates(), objectStack);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.LINK_SEQUENCE_ = ['text', 'type'];
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.LINK_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'text': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.RTE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, [
|
||||
'name', 'cmt', 'desc', 'src', 'link', 'number', 'type', 'rtept'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.RTE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
|
||||
'number': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeNonNegativeIntegerTextNode),
|
||||
'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'rtept': ol.xml.makeArraySerializer(ol.xml.makeChildAppender(
|
||||
ol.format.GPX.writeWptType_))
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRK_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, [
|
||||
'name', 'cmt', 'desc', 'src', 'link', 'number', 'type', 'trkseg'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRK_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
|
||||
'number': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeNonNegativeIntegerTextNode),
|
||||
'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'trkseg': ol.xml.makeArraySerializer(ol.xml.makeChildAppender(
|
||||
ol.format.GPX.writeTrkSeg_))
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRKSEG_NODE_FACTORY_ = ol.xml.makeSimpleNodeFactory('trkpt');
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.TRKSEG_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'trkpt': ol.xml.makeChildAppender(ol.format.GPX.writeWptType_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.WPT_TYPE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, [
|
||||
'ele', 'time', 'magvar', 'geoidheight', 'name', 'cmt', 'desc', 'src',
|
||||
'link', 'sym', 'type', 'fix', 'sat', 'hdop', 'vdop', 'pdop',
|
||||
'ageofdgpsdata', 'dgpsid'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.WPT_TYPE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'ele': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'time': ol.xml.makeChildAppender(ol.format.XSD.writeDateTimeTextNode),
|
||||
'magvar': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'geoidheight': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeDecimalTextNode),
|
||||
'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
|
||||
'sym': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'fix': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'sat': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeNonNegativeIntegerTextNode),
|
||||
'hdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'vdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'pdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'ageofdgpsdata': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeDecimalTextNode),
|
||||
'dgpsid': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeNonNegativeIntegerTextNode)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_ = {
|
||||
'Point': 'wpt',
|
||||
'LineString': 'rte',
|
||||
'MultiLineString': 'trk'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @param {string=} opt_nodeName Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.GPX_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
|
||||
goog.asserts.assertInstanceof(value, ol.Feature);
|
||||
var geometry = value.getGeometry();
|
||||
if (goog.isDef(geometry)) {
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
goog.asserts.assert(ol.xml.isNode(parentNode));
|
||||
return ol.xml.createElementNS(parentNode.namespaceURI,
|
||||
ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_[geometry.getType()]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.GPX.NAMESPACE_URIS_, {
|
||||
'rte': ol.xml.makeChildAppender(ol.format.GPX.writeRte_),
|
||||
'trk': ol.xml.makeChildAppender(ol.format.GPX.writeTrk_),
|
||||
'wpt': ol.xml.makeChildAppender(ol.format.GPX.writeWpt_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features in the GPX format.
|
||||
*
|
||||
* @function
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.GPX.prototype.writeFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features in the GPX format as an XML node.
|
||||
*
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Options.
|
||||
* @return {Node} Node.
|
||||
* @api
|
||||
*/
|
||||
ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
//FIXME Serialize metadata
|
||||
var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
|
||||
|
||||
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */
|
||||
({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_,
|
||||
ol.format.GPX.GPX_NODE_FACTORY_, features, [opt_options]);
|
||||
return gpx;
|
||||
};
|
||||
@@ -0,0 +1,220 @@
|
||||
goog.provide('ol.format.IGC');
|
||||
goog.provide('ol.format.IGCZ');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.string.newlines');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.TextFeature');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
/**
|
||||
* IGC altitude/z. One of 'barometric', 'gps', 'none'.
|
||||
* @enum {string}
|
||||
* @api
|
||||
*/
|
||||
ol.format.IGCZ = {
|
||||
BAROMETRIC: 'barometric',
|
||||
GPS: 'gps',
|
||||
NONE: 'none'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for `*.igc` flight recording files.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.TextFeature}
|
||||
* @param {olx.format.IGCOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.format.IGC = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.format.IGCZ}
|
||||
*/
|
||||
this.altitudeMode_ = goog.isDef(options.altitudeMode) ?
|
||||
options.altitudeMode : ol.format.IGCZ.NONE;
|
||||
|
||||
};
|
||||
goog.inherits(ol.format.IGC, ol.format.TextFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.IGC.EXTENSIONS_ = ['.igc'];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.format.IGC.B_RECORD_RE_ =
|
||||
/^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.format.IGC.H_RECORD_RE_ = /^H.([A-Z]{3}).*?:(.*)/;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
ol.format.IGC.HFDTE_RECORD_RE_ = /^HFDTE(\d{2})(\d{2})(\d{2})/;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.IGC.prototype.getExtensions = function() {
|
||||
return ol.format.IGC.EXTENSIONS_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the feature from the IGC source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @api
|
||||
*/
|
||||
ol.format.IGC.prototype.readFeature;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) {
|
||||
var altitudeMode = this.altitudeMode_;
|
||||
var lines = goog.string.newlines.splitLines(text);
|
||||
/** @type {Object.<string, string>} */
|
||||
var properties = {};
|
||||
var flatCoordinates = [];
|
||||
var year = 2000;
|
||||
var month = 0;
|
||||
var day = 1;
|
||||
var i, ii;
|
||||
for (i = 0, ii = lines.length; i < ii; ++i) {
|
||||
var line = lines[i];
|
||||
var m;
|
||||
if (line.charAt(0) == 'B') {
|
||||
m = ol.format.IGC.B_RECORD_RE_.exec(line);
|
||||
if (m) {
|
||||
var hour = parseInt(m[1], 10);
|
||||
var minute = parseInt(m[2], 10);
|
||||
var second = parseInt(m[3], 10);
|
||||
var y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000;
|
||||
if (m[6] == 'S') {
|
||||
y = -y;
|
||||
}
|
||||
var x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000;
|
||||
if (m[9] == 'W') {
|
||||
x = -x;
|
||||
}
|
||||
flatCoordinates.push(x, y);
|
||||
if (altitudeMode != ol.format.IGCZ.NONE) {
|
||||
var z;
|
||||
if (altitudeMode == ol.format.IGCZ.GPS) {
|
||||
z = parseInt(m[11], 10);
|
||||
} else if (altitudeMode == ol.format.IGCZ.BAROMETRIC) {
|
||||
z = parseInt(m[12], 10);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
z = 0;
|
||||
}
|
||||
flatCoordinates.push(z);
|
||||
}
|
||||
var dateTime = Date.UTC(year, month, day, hour, minute, second);
|
||||
flatCoordinates.push(dateTime / 1000);
|
||||
}
|
||||
} else if (line.charAt(0) == 'H') {
|
||||
m = ol.format.IGC.HFDTE_RECORD_RE_.exec(line);
|
||||
if (m) {
|
||||
day = parseInt(m[1], 10);
|
||||
month = parseInt(m[2], 10) - 1;
|
||||
year = 2000 + parseInt(m[3], 10);
|
||||
} else {
|
||||
m = ol.format.IGC.H_RECORD_RE_.exec(line);
|
||||
if (m) {
|
||||
properties[m[1]] = goog.string.trim(m[2]);
|
||||
m = ol.format.IGC.HFDTE_RECORD_RE_.exec(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flatCoordinates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var lineString = new ol.geom.LineString(null);
|
||||
var layout = altitudeMode == ol.format.IGCZ.NONE ?
|
||||
ol.geom.GeometryLayout.XYM : ol.geom.GeometryLayout.XYZM;
|
||||
lineString.setFlatCoordinates(layout, flatCoordinates);
|
||||
var feature = new ol.Feature(ol.format.Feature.transformWithOptions(
|
||||
lineString, false, opt_options));
|
||||
feature.setProperties(properties);
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the feature from the source. As IGC sources contain a single
|
||||
* feature, this will return the feature in an array.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api
|
||||
*/
|
||||
ol.format.IGC.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.IGC.prototype.readFeaturesFromText = function(text, opt_options) {
|
||||
var feature = this.readFeatureFromText(text, opt_options);
|
||||
if (!goog.isNull(feature)) {
|
||||
return [feature];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from the IGC source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api
|
||||
*/
|
||||
ol.format.IGC.prototype.readProjection;
|
||||
@@ -0,0 +1,168 @@
|
||||
goog.provide('ol.format.JSONFeature');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.json');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.FormatType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for JSON feature formats.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.Feature}
|
||||
*/
|
||||
ol.format.JSONFeature = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.JSONFeature, ol.format.Feature);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @private
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.getObject_ = function(source) {
|
||||
if (goog.isObject(source)) {
|
||||
return source;
|
||||
} else if (goog.isString(source)) {
|
||||
var object = goog.json.parse(source);
|
||||
return goog.isDef(object) ? object : null;
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.getType = function() {
|
||||
return ol.format.FormatType.JSON;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) {
|
||||
return this.readFeatureFromObject(
|
||||
this.getObject_(source), this.getReadOptions(source, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readFeatures = function(source, opt_options) {
|
||||
return this.readFeaturesFromObject(
|
||||
this.getObject_(source), this.getReadOptions(source, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readFeatureFromObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readFeaturesFromObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readGeometry = function(source, opt_options) {
|
||||
return this.readGeometryFromObject(
|
||||
this.getObject_(source), this.getReadOptions(source, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readGeometryFromObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readProjection = function(source) {
|
||||
return this.readProjectionFromObject(this.getObject_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @protected
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.readProjectionFromObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) {
|
||||
return goog.json.serialize(this.writeFeatureObject(feature, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeFeatureObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeFeatures = function(
|
||||
features, opt_options) {
|
||||
return goog.json.serialize(this.writeFeaturesObject(features, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeFeaturesObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeGeometry = function(
|
||||
geometry, opt_options) {
|
||||
return goog.json.serialize(this.writeGeometryObject(geometry, opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
ol.format.JSONFeature.prototype.writeGeometryObject = goog.abstractMethod;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,236 @@
|
||||
// FIXME add typedef for stack state objects
|
||||
goog.provide('ol.format.OSMXML');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading data in the
|
||||
* [OSMXML format](http://wiki.openstreetmap.org/wiki/OSM_XML).
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.XMLFeature}
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.OSMXML = function() {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get('EPSG:4326');
|
||||
};
|
||||
goog.inherits(ol.format.OSMXML, ol.format.XMLFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.EXTENSIONS_ = ['.osm'];
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.OSMXML.prototype.getExtensions = function() {
|
||||
return ol.format.OSMXML.EXTENSIONS_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.readNode_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'node');
|
||||
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
|
||||
var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
var id = node.getAttribute('id');
|
||||
var coordinates = /** @type {Array.<number>} */ ([
|
||||
parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat'))
|
||||
]);
|
||||
state.nodes[id] = coordinates;
|
||||
|
||||
var values = ol.xml.pushParseAndPop({
|
||||
tags: {}
|
||||
}, ol.format.OSMXML.NODE_PARSERS_, node, objectStack);
|
||||
if (!goog.object.isEmpty(values.tags)) {
|
||||
var geometry = new ol.geom.Point(coordinates);
|
||||
ol.format.Feature.transformWithOptions(geometry, false, options);
|
||||
var feature = new ol.Feature(geometry);
|
||||
feature.setId(id);
|
||||
feature.setProperties(values.tags);
|
||||
state.features.push(feature);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.readWay_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'way');
|
||||
var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
|
||||
var id = node.getAttribute('id');
|
||||
var values = ol.xml.pushParseAndPop({
|
||||
ndrefs: [],
|
||||
tags: {}
|
||||
}, ol.format.OSMXML.WAY_PARSERS_, node, objectStack);
|
||||
var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
var flatCoordinates = /** @type {Array.<number>} */ ([]);
|
||||
for (var i = 0, ii = values.ndrefs.length; i < ii; i++) {
|
||||
var point = state.nodes[values.ndrefs[i]];
|
||||
goog.array.extend(flatCoordinates, point);
|
||||
}
|
||||
var geometry;
|
||||
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
|
||||
// closed way
|
||||
geometry = new ol.geom.Polygon(null);
|
||||
geometry.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates,
|
||||
[flatCoordinates.length]);
|
||||
} else {
|
||||
geometry = new ol.geom.LineString(null);
|
||||
geometry.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
|
||||
}
|
||||
ol.format.Feature.transformWithOptions(geometry, false, options);
|
||||
var feature = new ol.Feature(geometry);
|
||||
feature.setId(id);
|
||||
feature.setProperties(values.tags);
|
||||
state.features.push(feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Feature|undefined} Track.
|
||||
*/
|
||||
ol.format.OSMXML.readNd_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'nd');
|
||||
var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values.ndrefs.push(node.getAttribute('ref'));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {ol.Feature|undefined} Track.
|
||||
*/
|
||||
ol.format.OSMXML.readTag_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'tag');
|
||||
var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values.tags[node.getAttribute('k')] = node.getAttribute('v');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.format.OSMXML.NAMESPACE_URIS_ = [
|
||||
null
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.WAY_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OSMXML.NAMESPACE_URIS_, {
|
||||
'nd': ol.format.OSMXML.readNd_,
|
||||
'tag': ol.format.OSMXML.readTag_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OSMXML.NAMESPACE_URIS_, {
|
||||
'node': ol.format.OSMXML.readNode_,
|
||||
'way': ol.format.OSMXML.readWay_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OSMXML.NODE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OSMXML.NAMESPACE_URIS_, {
|
||||
'tag': ol.format.OSMXML.readTag_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from an OSM source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.OSMXML.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
var options = this.getReadOptions(node, opt_options);
|
||||
if (node.localName == 'osm') {
|
||||
var state = ol.xml.pushParseAndPop({
|
||||
nodes: {},
|
||||
features: []
|
||||
}, ol.format.OSMXML.PARSERS_, node, [options]);
|
||||
if (goog.isDef(state.features)) {
|
||||
return state.features;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from an OSM source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.OSMXML.prototype.readProjection;
|
||||
@@ -0,0 +1,461 @@
|
||||
goog.provide('ol.format.OWS');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('ol.format.XLink');
|
||||
goog.require('ol.format.XML');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.format.XML}
|
||||
*/
|
||||
ol.format.OWS = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.OWS, ol.format.XML);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {Object} OWS object.
|
||||
*/
|
||||
ol.format.OWS.prototype.readFromDocument = function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readFromNode(n);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {Object} OWS object.
|
||||
*/
|
||||
ol.format.OWS.prototype.readFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
var owsObject = ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.PARSERS_, node, []);
|
||||
return goog.isDef(owsObject) ? owsObject : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readAddress_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Address');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.ADDRESS_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readAllowedValues_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'AllowedValues');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.ALLOWED_VALUES_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readConstraint_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Constraint');
|
||||
var name = node.getAttribute('name');
|
||||
if (!goog.isDef(name)) {
|
||||
return undefined;
|
||||
}
|
||||
return ol.xml.pushParseAndPop({'name': name},
|
||||
ol.format.OWS.CONSTRAINT_PARSERS_, node,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readContactInfo_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ContactInfo');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.CONTACT_INFO_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readDcp_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'DCP');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.DCP_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readGet_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Get');
|
||||
var href = ol.format.XLink.readHref(node);
|
||||
if (!goog.isDef(href)) {
|
||||
return undefined;
|
||||
}
|
||||
return ol.xml.pushParseAndPop({'href': href},
|
||||
ol.format.OWS.REQUEST_METHOD_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readHttp_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'HTTP');
|
||||
return ol.xml.pushParseAndPop({}, ol.format.OWS.HTTP_PARSERS_,
|
||||
node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readOperation_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Operation');
|
||||
var name = node.getAttribute('name');
|
||||
var value = ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.OPERATION_PARSERS_, node, objectStack);
|
||||
if (!goog.isDef(value)) {
|
||||
return undefined;
|
||||
}
|
||||
var object = /** @type {Object} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
goog.asserts.assert(goog.isObject(object));
|
||||
object[name] = value;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readOperationsMetadata_ = function(node,
|
||||
objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'OperationsMetadata');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.OPERATIONS_METADATA_PARSERS_, node,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readPhone_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Phone');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.OWS.PHONE_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readServiceIdentification_ = function(node,
|
||||
objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ServiceIdentification');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_, node,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readServiceContact_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ServiceContact');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.OWS.SERVICE_CONTACT_PARSERS_, node,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
ol.format.OWS.readServiceProvider_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ServiceProvider');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.OWS.SERVICE_PROVIDER_PARSERS_, node,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {string|undefined}
|
||||
*/
|
||||
ol.format.OWS.readValue_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Value');
|
||||
return ol.format.XSD.readString(node);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.NAMESPACE_URIS_ = [
|
||||
null,
|
||||
'http://www.opengis.net/ows/1.1'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'ServiceIdentification': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readServiceIdentification_),
|
||||
'ServiceProvider': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readServiceProvider_),
|
||||
'OperationsMetadata': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readOperationsMetadata_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.ADDRESS_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'DeliveryPoint': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'City': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'AdministrativeArea': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'PostalCode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Country': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'ElectronicMailAddress': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.ALLOWED_VALUES_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Value': ol.xml.makeObjectPropertyPusher(ol.format.OWS.readValue_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.CONSTRAINT_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'AllowedValues': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readAllowedValues_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.CONTACT_INFO_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Phone': ol.xml.makeObjectPropertySetter(ol.format.OWS.readPhone_),
|
||||
'Address': ol.xml.makeObjectPropertySetter(ol.format.OWS.readAddress_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.DCP_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'HTTP': ol.xml.makeObjectPropertySetter(ol.format.OWS.readHttp_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.HTTP_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Get': ol.xml.makeObjectPropertyPusher(ol.format.OWS.readGet_),
|
||||
'Post': undefined // TODO
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.OPERATION_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'DCP': ol.xml.makeObjectPropertySetter(ol.format.OWS.readDcp_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.OPERATIONS_METADATA_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Operation': ol.format.OWS.readOperation_
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.PHONE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Voice': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Facsimile': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.REQUEST_METHOD_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Constraint': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.OWS.readConstraint_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.SERVICE_CONTACT_PARSERS_ =
|
||||
ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'IndividualName': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'PositionName': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'ContactInfo': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readContactInfo_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_ =
|
||||
ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'ServiceTypeVersion': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'ServiceType': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.OWS.SERVICE_PROVIDER_PARSERS_ =
|
||||
ol.xml.makeParsersNS(
|
||||
ol.format.OWS.NAMESPACE_URIS_, {
|
||||
'ProviderName': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'ProviderSite': ol.xml.makeObjectPropertySetter(ol.format.XLink.readHref),
|
||||
'ServiceContact': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.OWS.readServiceContact_)
|
||||
});
|
||||
@@ -0,0 +1,393 @@
|
||||
goog.provide('ol.format.Polyline');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.TextFeature');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.flat.flip');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the Encoded
|
||||
* Polyline Algorithm Format.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.TextFeature}
|
||||
* @param {olx.format.PolylineOptions=} opt_options
|
||||
* Optional configuration object.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.factor_ = goog.isDef(options.factor) ? options.factor : 1e5;
|
||||
};
|
||||
goog.inherits(ol.format.Polyline, ol.format.TextFeature);
|
||||
|
||||
|
||||
/**
|
||||
* Encode a list of n-dimensional points and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array.<number>} numbers A list of n-dimensional points.
|
||||
* @param {number} stride The number of dimension of the points in the list.
|
||||
* @param {number=} opt_factor The factor by which the numbers will be
|
||||
* multiplied. The remaining decimal places will get rounded away.
|
||||
* Default is `1e5`.
|
||||
* @return {string} The encoded string.
|
||||
* @api
|
||||
*/
|
||||
ol.format.Polyline.encodeDeltas = function(numbers, stride, opt_factor) {
|
||||
var factor = goog.isDef(opt_factor) ? opt_factor : 1e5;
|
||||
var d;
|
||||
|
||||
var lastNumbers = new Array(stride);
|
||||
for (d = 0; d < stride; ++d) {
|
||||
lastNumbers[d] = 0;
|
||||
}
|
||||
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii;) {
|
||||
for (d = 0; d < stride; ++d, ++i) {
|
||||
var num = numbers[i];
|
||||
var delta = num - lastNumbers[d];
|
||||
lastNumbers[d] = num;
|
||||
|
||||
numbers[i] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
return ol.format.Polyline.encodeFloats(numbers, factor);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode a list of n-dimensional points from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @param {number} stride The number of dimension of the points in the
|
||||
* encoded string.
|
||||
* @param {number=} opt_factor The factor by which the resulting numbers will
|
||||
* be divided. Default is `1e5`.
|
||||
* @return {Array.<number>} A list of n-dimensional points.
|
||||
* @api
|
||||
*/
|
||||
ol.format.Polyline.decodeDeltas = function(encoded, stride, opt_factor) {
|
||||
var factor = goog.isDef(opt_factor) ? opt_factor : 1e5;
|
||||
var d;
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var lastNumbers = new Array(stride);
|
||||
for (d = 0; d < stride; ++d) {
|
||||
lastNumbers[d] = 0;
|
||||
}
|
||||
|
||||
var numbers = ol.format.Polyline.decodeFloats(encoded, factor);
|
||||
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii;) {
|
||||
for (d = 0; d < stride; ++d, ++i) {
|
||||
lastNumbers[d] += numbers[i];
|
||||
|
||||
numbers[i] = lastNumbers[d];
|
||||
}
|
||||
}
|
||||
|
||||
return numbers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a list of floating point numbers and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array.<number>} numbers A list of floating point numbers.
|
||||
* @param {number=} opt_factor The factor by which the numbers will be
|
||||
* multiplied. The remaining decimal places will get rounded away.
|
||||
* Default is `1e5`.
|
||||
* @return {string} The encoded string.
|
||||
* @api
|
||||
*/
|
||||
ol.format.Polyline.encodeFloats = function(numbers, opt_factor) {
|
||||
var factor = goog.isDef(opt_factor) ? opt_factor : 1e5;
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
numbers[i] = Math.round(numbers[i] * factor);
|
||||
}
|
||||
|
||||
return ol.format.Polyline.encodeSignedIntegers(numbers);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode a list of floating point numbers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @param {number=} opt_factor The factor by which the result will be divided.
|
||||
* Default is `1e5`.
|
||||
* @return {Array.<number>} A list of floating point numbers.
|
||||
* @api
|
||||
*/
|
||||
ol.format.Polyline.decodeFloats = function(encoded, opt_factor) {
|
||||
var factor = goog.isDef(opt_factor) ? opt_factor : 1e5;
|
||||
var numbers = ol.format.Polyline.decodeSignedIntegers(encoded);
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
numbers[i] /= factor;
|
||||
}
|
||||
return numbers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a list of signed integers and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array.<number>} numbers A list of signed integers.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
ol.format.Polyline.encodeSignedIntegers = function(numbers) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
var num = numbers[i];
|
||||
numbers[i] = (num < 0) ? ~(num << 1) : (num << 1);
|
||||
}
|
||||
return ol.format.Polyline.encodeUnsignedIntegers(numbers);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode a list of signed integers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @return {Array.<number>} A list of signed integers.
|
||||
*/
|
||||
ol.format.Polyline.decodeSignedIntegers = function(encoded) {
|
||||
var numbers = ol.format.Polyline.decodeUnsignedIntegers(encoded);
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
var num = numbers[i];
|
||||
numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
|
||||
}
|
||||
return numbers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a list of unsigned integers and return an encoded string
|
||||
*
|
||||
* @param {Array.<number>} numbers A list of unsigned integers.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
ol.format.Polyline.encodeUnsignedIntegers = function(numbers) {
|
||||
var encoded = '';
|
||||
var i, ii;
|
||||
for (i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
encoded += ol.format.Polyline.encodeUnsignedInteger(numbers[i]);
|
||||
}
|
||||
return encoded;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode a list of unsigned integers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @return {Array.<number>} A list of unsigned integers.
|
||||
*/
|
||||
ol.format.Polyline.decodeUnsignedIntegers = function(encoded) {
|
||||
var numbers = [];
|
||||
var current = 0;
|
||||
var shift = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = encoded.length; i < ii; ++i) {
|
||||
var b = encoded.charCodeAt(i) - 63;
|
||||
current |= (b & 0x1f) << shift;
|
||||
if (b < 0x20) {
|
||||
numbers.push(current);
|
||||
current = 0;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 5;
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode one single unsigned integer and return an encoded string
|
||||
*
|
||||
* @param {number} num Unsigned integer that should be encoded.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
ol.format.Polyline.encodeUnsignedInteger = function(num) {
|
||||
var value, encoded = '';
|
||||
while (num >= 0x20) {
|
||||
value = (0x20 | (num & 0x1f)) + 63;
|
||||
encoded += String.fromCharCode(value);
|
||||
num >>= 5;
|
||||
}
|
||||
value = num + 63;
|
||||
encoded += String.fromCharCode(value);
|
||||
return encoded;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the feature from the Polyline source. The coordinates are assumed to be
|
||||
* in two dimensions and in latitude, longitude order.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline.prototype.readFeature;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.readFeatureFromText = function(text, opt_options) {
|
||||
var geometry = this.readGeometryFromText(text, opt_options);
|
||||
return new ol.Feature(geometry);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the feature from the source. As Polyline sources contain a single
|
||||
* feature, this will return the feature in an array.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.readFeaturesFromText =
|
||||
function(text, opt_options) {
|
||||
var feature = this.readFeatureFromText(text, opt_options);
|
||||
return [feature];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the geometry from the source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline.prototype.readGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.readGeometryFromText =
|
||||
function(text, opt_options) {
|
||||
var flatCoordinates = ol.format.Polyline.decodeDeltas(text, 2, this.factor_);
|
||||
ol.geom.flat.flip.flipXY(
|
||||
flatCoordinates, 0, flatCoordinates.length, 2, flatCoordinates);
|
||||
var coordinates = ol.geom.flat.inflate.coordinates(
|
||||
flatCoordinates, 0, flatCoordinates.length, 2);
|
||||
|
||||
return /** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(
|
||||
new ol.geom.LineString(coordinates), false,
|
||||
this.adaptOptions(opt_options)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a Polyline source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline.prototype.readProjection;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.writeFeatureText = function(feature, opt_options) {
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDefAndNotNull(geometry)) {
|
||||
return this.writeGeometryText(geometry, opt_options);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.writeFeaturesText =
|
||||
function(features, opt_options) {
|
||||
goog.asserts.assert(features.length == 1);
|
||||
return this.writeFeatureText(features[0], opt_options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write a single geometry in Polyline format.
|
||||
*
|
||||
* @function
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} Geometry.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.Polyline.prototype.writeGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.Polyline.prototype.writeGeometryText =
|
||||
function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
|
||||
geometry = /** @type {ol.geom.LineString} */
|
||||
(ol.format.Feature.transformWithOptions(
|
||||
geometry, true, this.adaptOptions(opt_options)));
|
||||
var flatCoordinates = geometry.getFlatCoordinates();
|
||||
var stride = geometry.getStride();
|
||||
ol.geom.flat.flip.flipXY(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
||||
return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_);
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
goog.provide('ol.format.TextFeature');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.FormatType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for text feature formats.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.Feature}
|
||||
*/
|
||||
ol.format.TextFeature = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.TextFeature, ol.format.Feature);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @private
|
||||
* @return {string} Text.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.getText_ = function(source) {
|
||||
if (goog.isString(source)) {
|
||||
return source;
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.getType = function() {
|
||||
return ol.format.FormatType.TEXT;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readFeature = function(source, opt_options) {
|
||||
return this.readFeatureFromText(
|
||||
this.getText_(source), this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readFeatureFromText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readFeatures = function(source, opt_options) {
|
||||
return this.readFeaturesFromText(
|
||||
this.getText_(source), this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readFeaturesFromText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readGeometry = function(source, opt_options) {
|
||||
return this.readGeometryFromText(
|
||||
this.getText_(source), this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @protected
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readGeometryFromText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readProjection = function(source) {
|
||||
return this.readProjectionFromText(this.getText_(source));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @protected
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.readProjectionFromText = function(text) {
|
||||
return this.defaultDataProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeFeature = function(feature, opt_options) {
|
||||
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeFeatureText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeFeatures = function(
|
||||
features, opt_options) {
|
||||
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeFeaturesText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeGeometry = function(
|
||||
geometry, opt_options) {
|
||||
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
ol.format.TextFeature.prototype.writeGeometryText = goog.abstractMethod;
|
||||
@@ -0,0 +1,409 @@
|
||||
goog.provide('ol.format.TopoJSON');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.JSONFeature');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the TopoJSON format.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.JSONFeature}
|
||||
* @param {olx.format.TopoJSONOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.TopoJSON = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.defaultDataProjection = ol.proj.get(
|
||||
goog.isDefAndNotNull(options.defaultDataProjection) ?
|
||||
options.defaultDataProjection : 'EPSG:4326');
|
||||
|
||||
};
|
||||
goog.inherits(ol.format.TopoJSON, ol.format.JSONFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.EXTENSIONS_ = ['.topojson'];
|
||||
|
||||
|
||||
/**
|
||||
* Concatenate arcs into a coordinate array.
|
||||
* @param {Array.<number>} indices Indices of arcs to concatenate. Negative
|
||||
* values indicate arcs need to be reversed.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs (already
|
||||
* transformed).
|
||||
* @return {Array.<ol.Coordinate>} Coordinates array.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.concatenateArcs_ = function(indices, arcs) {
|
||||
/** @type {Array.<ol.Coordinate>} */
|
||||
var coordinates = [];
|
||||
var index, arc;
|
||||
var i, ii;
|
||||
var j, jj;
|
||||
for (i = 0, ii = indices.length; i < ii; ++i) {
|
||||
index = indices[i];
|
||||
if (i > 0) {
|
||||
// splicing together arcs, discard last point
|
||||
coordinates.pop();
|
||||
}
|
||||
if (index >= 0) {
|
||||
// forward arc
|
||||
arc = arcs[index];
|
||||
} else {
|
||||
// reverse arc
|
||||
arc = arcs[~index].slice().reverse();
|
||||
}
|
||||
coordinates.push.apply(coordinates, arc);
|
||||
}
|
||||
// provide fresh copies of coordinate arrays
|
||||
for (j = 0, jj = coordinates.length; j < jj; ++j) {
|
||||
coordinates[j] = coordinates[j].slice();
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a point from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @return {ol.geom.Point} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readPointGeometry_ = function(object, scale, translate) {
|
||||
var coordinates = object.coordinates;
|
||||
if (!goog.isNull(scale) && !goog.isNull(translate)) {
|
||||
ol.format.TopoJSON.transformVertex_(coordinates, scale, translate);
|
||||
}
|
||||
return new ol.geom.Point(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a multi-point from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @return {ol.geom.MultiPoint} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readMultiPointGeometry_ = function(object, scale,
|
||||
translate) {
|
||||
var coordinates = object.coordinates;
|
||||
var i, ii;
|
||||
if (!goog.isNull(scale) && !goog.isNull(translate)) {
|
||||
for (i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
ol.format.TopoJSON.transformVertex_(coordinates[i], scale, translate);
|
||||
}
|
||||
}
|
||||
return new ol.geom.MultiPoint(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a linestring from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @return {ol.geom.LineString} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readLineStringGeometry_ = function(object, arcs) {
|
||||
var coordinates = ol.format.TopoJSON.concatenateArcs_(object.arcs, arcs);
|
||||
return new ol.geom.LineString(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a multi-linestring from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @return {ol.geom.MultiLineString} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readMultiLineStringGeometry_ = function(object, arcs) {
|
||||
var coordinates = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = object.arcs.length; i < ii; ++i) {
|
||||
coordinates[i] = ol.format.TopoJSON.concatenateArcs_(object.arcs[i], arcs);
|
||||
}
|
||||
return new ol.geom.MultiLineString(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a polygon from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @return {ol.geom.Polygon} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readPolygonGeometry_ = function(object, arcs) {
|
||||
var coordinates = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = object.arcs.length; i < ii; ++i) {
|
||||
coordinates[i] = ol.format.TopoJSON.concatenateArcs_(object.arcs[i], arcs);
|
||||
}
|
||||
return new ol.geom.Polygon(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a multi-polygon from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @return {ol.geom.MultiPolygon} Geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readMultiPolygonGeometry_ = function(object, arcs) {
|
||||
var coordinates = [];
|
||||
var polyArray, ringCoords, j, jj;
|
||||
var i, ii;
|
||||
for (i = 0, ii = object.arcs.length; i < ii; ++i) {
|
||||
// for each polygon
|
||||
polyArray = object.arcs[i];
|
||||
ringCoords = [];
|
||||
for (j = 0, jj = polyArray.length; j < jj; ++j) {
|
||||
// for each ring
|
||||
ringCoords[j] = ol.format.TopoJSON.concatenateArcs_(polyArray[j], arcs);
|
||||
}
|
||||
coordinates[i] = ringCoords;
|
||||
}
|
||||
return new ol.geom.MultiPolygon(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TopoJSON.prototype.getExtensions = function() {
|
||||
return ol.format.TopoJSON.EXTENSIONS_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create features from a TopoJSON GeometryCollection object.
|
||||
*
|
||||
* @param {TopoJSONGeometryCollection} collection TopoJSON Geometry
|
||||
* object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Array of features.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readFeaturesFromGeometryCollection_ = function(
|
||||
collection, arcs, scale, translate, opt_options) {
|
||||
var geometries = collection.geometries;
|
||||
var features = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
features[i] = ol.format.TopoJSON.readFeatureFromGeometry_(
|
||||
geometries[i], arcs, scale, translate, opt_options);
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a feature from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON geometry object.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs,
|
||||
scale, translate, opt_options) {
|
||||
var geometry;
|
||||
var type = object.type;
|
||||
var geometryReader = ol.format.TopoJSON.GEOMETRY_READERS_[type];
|
||||
goog.asserts.assert(goog.isDef(geometryReader));
|
||||
if ((type === 'Point') || (type === 'MultiPoint')) {
|
||||
geometry = geometryReader(object, scale, translate);
|
||||
} else {
|
||||
geometry = geometryReader(object, arcs);
|
||||
}
|
||||
var feature = new ol.Feature();
|
||||
feature.setGeometry(/** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, false, opt_options)));
|
||||
if (goog.isDef(object.id)) {
|
||||
feature.setId(object.id);
|
||||
}
|
||||
if (goog.isDef(object.properties)) {
|
||||
feature.setProperties(object.properties);
|
||||
}
|
||||
return feature;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a TopoJSON source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.TopoJSON.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.TopoJSON.prototype.readFeaturesFromObject = function(
|
||||
object, opt_options) {
|
||||
if (object.type == 'Topology') {
|
||||
var topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
|
||||
var transform, scale = null, translate = null;
|
||||
if (goog.isDef(topoJSONTopology.transform)) {
|
||||
transform = /** @type {TopoJSONTransform} */
|
||||
(topoJSONTopology.transform);
|
||||
scale = transform.scale;
|
||||
translate = transform.translate;
|
||||
}
|
||||
var arcs = topoJSONTopology.arcs;
|
||||
if (goog.isDef(transform)) {
|
||||
ol.format.TopoJSON.transformArcs_(arcs, scale, translate);
|
||||
}
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
var topoJSONFeatures = goog.object.getValues(topoJSONTopology.objects);
|
||||
var i, ii;
|
||||
var feature;
|
||||
for (i = 0, ii = topoJSONFeatures.length; i < ii; ++i) {
|
||||
if (topoJSONFeatures[i].type === 'GeometryCollection') {
|
||||
feature = /** @type {TopoJSONGeometryCollection} */
|
||||
(topoJSONFeatures[i]);
|
||||
features.push.apply(features,
|
||||
ol.format.TopoJSON.readFeaturesFromGeometryCollection_(
|
||||
feature, arcs, scale, translate, opt_options));
|
||||
} else {
|
||||
feature = /** @type {TopoJSONGeometry} */
|
||||
(topoJSONFeatures[i]);
|
||||
features.push(ol.format.TopoJSON.readFeatureFromGeometry_(
|
||||
feature, arcs, scale, translate, opt_options));
|
||||
}
|
||||
}
|
||||
return features;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply a linear transform to array of arcs. The provided array of arcs is
|
||||
* modified in place.
|
||||
*
|
||||
* @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.transformArcs_ = function(arcs, scale, translate) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = arcs.length; i < ii; ++i) {
|
||||
ol.format.TopoJSON.transformArc_(arcs[i], scale, translate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply a linear transform to an arc. The provided arc is modified in place.
|
||||
*
|
||||
* @param {Array.<ol.Coordinate>} arc Arc.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.transformArc_ = function(arc, scale, translate) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var vertex;
|
||||
var i, ii;
|
||||
for (i = 0, ii = arc.length; i < ii; ++i) {
|
||||
vertex = arc[i];
|
||||
x += vertex[0];
|
||||
y += vertex[1];
|
||||
vertex[0] = x;
|
||||
vertex[1] = y;
|
||||
ol.format.TopoJSON.transformVertex_(vertex, scale, translate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply a linear transform to a vertex. The provided vertex is modified in
|
||||
* place.
|
||||
*
|
||||
* @param {ol.Coordinate} vertex Vertex.
|
||||
* @param {Array.<number>} scale Scale for each dimension.
|
||||
* @param {Array.<number>} translate Translation for each dimension.
|
||||
* @private
|
||||
*/
|
||||
ol.format.TopoJSON.transformVertex_ = function(vertex, scale, translate) {
|
||||
vertex[0] = vertex[0] * scale[0] + translate[0];
|
||||
vertex[1] = vertex[1] * scale[1] + translate[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a TopoJSON source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} object Source.
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.TopoJSON.prototype.readProjection = function(object) {
|
||||
return this.defaultDataProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<string, function(TopoJSONGeometry, Array, ...Array): ol.geom.Geometry>}
|
||||
*/
|
||||
ol.format.TopoJSON.GEOMETRY_READERS_ = {
|
||||
'Point': ol.format.TopoJSON.readPointGeometry_,
|
||||
'LineString': ol.format.TopoJSON.readLineStringGeometry_,
|
||||
'Polygon': ol.format.TopoJSON.readPolygonGeometry_,
|
||||
'MultiPoint': ol.format.TopoJSON.readMultiPointGeometry_,
|
||||
'MultiLineString': ol.format.TopoJSON.readMultiLineStringGeometry_,
|
||||
'MultiPolygon': ol.format.TopoJSON.readMultiPolygonGeometry_
|
||||
};
|
||||
@@ -0,0 +1,770 @@
|
||||
goog.provide('ol.format.WFS');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.format.GML3');
|
||||
goog.require('ol.format.GMLBase');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the WFS format.
|
||||
* By default, supports WFS version 1.1.0. You can pass a GML format
|
||||
* as option if you want to read a WFS that contains GML2 (WFS 1.0.0).
|
||||
* Also see {@link ol.format.GMLBase} which is used by this format.
|
||||
*
|
||||
* @constructor
|
||||
* @param {olx.format.WFSOptions=} opt_options
|
||||
* Optional configuration object.
|
||||
* @extends {ol.format.XMLFeature}
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS = function(opt_options) {
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<string>|string|undefined}
|
||||
*/
|
||||
this.featureType_ = options.featureType;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, string>|string|undefined}
|
||||
*/
|
||||
this.featureNS_ = options.featureNS;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.format.GMLBase}
|
||||
*/
|
||||
this.gmlFormat_ = goog.isDef(options.gmlFormat) ?
|
||||
options.gmlFormat : new ol.format.GML3();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.schemaLocation_ = goog.isDef(options.schemaLocation) ?
|
||||
options.schemaLocation : ol.format.WFS.SCHEMA_LOCATION;
|
||||
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.WFS, ol.format.XMLFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.WFS.FEATURE_PREFIX = 'feature';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.WFS.XMLNS = 'http://www.w3.org/2000/xmlns/';
|
||||
|
||||
|
||||
/**
|
||||
* Number of features; bounds/extent.
|
||||
* @typedef {{numberOfFeatures: number,
|
||||
* bounds: ol.Extent}}
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.FeatureCollectionMetadata;
|
||||
|
||||
|
||||
/**
|
||||
* Total deleted; total inserted; total updated; array of insert ids.
|
||||
* @typedef {{totalDeleted: number,
|
||||
* totalInserted: number,
|
||||
* totalUpdated: number,
|
||||
* insertIds: Array.<string>}}
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.TransactionResponse;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.WFS.SCHEMA_LOCATION = 'http://www.opengis.net/wfs ' +
|
||||
'http://schemas.opengis.net/wfs/1.1.0/wfs.xsd';
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a WFS FeatureCollection.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
|
||||
var context = {
|
||||
'featureType': this.featureType_,
|
||||
'featureNS': this.featureNS_
|
||||
};
|
||||
goog.object.extend(context, this.getReadOptions(node,
|
||||
goog.isDef(opt_options) ? opt_options : {}));
|
||||
var objectStack = [context];
|
||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS][
|
||||
'featureMember'] =
|
||||
ol.xml.makeArrayPusher(ol.format.GMLBase.prototype.readFeaturesInternal);
|
||||
var features = ol.xml.pushParseAndPop([],
|
||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
||||
objectStack, this.gmlFormat_);
|
||||
if (!goog.isDef(features)) {
|
||||
features = [];
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.readTransactionResponse = function(source) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readTransactionResponseFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readTransactionResponseFromNode(/** @type {Node} */ (source));
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readTransactionResponseFromDocument(doc);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
|
||||
* FeatureCollection metadata.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.readFeatureCollectionMetadata = function(source) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readFeatureCollectionMetadataFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readFeatureCollectionMetadataFromNode(
|
||||
/** @type {Node} */ (source));
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readFeatureCollectionMetadataFromDocument(doc);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
|
||||
* FeatureCollection metadata.
|
||||
*/
|
||||
ol.format.WFS.prototype.readFeatureCollectionMetadataFromDocument =
|
||||
function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readFeatureCollectionMetadataFromNode(n);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.FEATURE_COLLECTION_PARSERS_ = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'boundedBy': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.GMLBase.prototype.readGeometryElement, 'bounds')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {ol.format.WFS.FeatureCollectionMetadata|undefined}
|
||||
* FeatureCollection metadata.
|
||||
*/
|
||||
ol.format.WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'FeatureCollection');
|
||||
var result = {};
|
||||
var value = ol.format.XSD.readNonNegativeIntegerString(
|
||||
node.getAttribute('numberOfFeatures'));
|
||||
result['numberOfFeatures'] = value;
|
||||
return ol.xml.pushParseAndPop(
|
||||
/** @type {ol.format.WFS.FeatureCollectionMetadata} */ (result),
|
||||
ol.format.WFS.FEATURE_COLLECTION_PARSERS_, node, [], this.gmlFormat_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.TRANSACTION_SUMMARY_PARSERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'totalInserted': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'totalUpdated': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'totalDeleted': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Transaction Summary.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.readTransactionSummary_ = function(node, objectStack) {
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WFS.TRANSACTION_SUMMARY_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.OGC_FID_PARSERS_ = {
|
||||
'http://www.opengis.net/ogc': {
|
||||
'FeatureId': ol.xml.makeArrayPusher(function(node, objectStack) {
|
||||
return node.getAttribute('fid');
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.fidParser_ = function(node, objectStack) {
|
||||
ol.xml.parseNode(ol.format.WFS.OGC_FID_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.INSERT_RESULTS_PARSERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'Feature': ol.format.WFS.fidParser_
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Array.<string>|undefined} Insert results.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.readInsertResults_ = function(node, objectStack) {
|
||||
return ol.xml.pushParseAndPop(
|
||||
[], ol.format.WFS.INSERT_RESULTS_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'TransactionSummary': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WFS.readTransactionSummary_, 'transactionSummary'),
|
||||
'InsertResults': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WFS.readInsertResults_, 'insertIds')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
|
||||
*/
|
||||
ol.format.WFS.prototype.readTransactionResponseFromDocument = function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readTransactionResponseFromNode(n);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {ol.format.WFS.TransactionResponse|undefined} Transaction response.
|
||||
*/
|
||||
ol.format.WFS.prototype.readTransactionResponseFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'TransactionResponse');
|
||||
return ol.xml.pushParseAndPop(
|
||||
/** @type {ol.format.WFS.TransactionResponse} */({}),
|
||||
ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_, node, []);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.QUERY_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'PropertyName': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeFeature_ = function(node, feature, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var featureType = context['featureType'];
|
||||
var featureNS = context['featureNS'];
|
||||
var child = ol.xml.createElementNS(featureNS, featureType);
|
||||
node.appendChild(child);
|
||||
ol.format.GML3.prototype.writeFeatureElement(child, feature, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {number|string} fid Feature identifier.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeOgcFidFilter_ = function(node, fid, objectStack) {
|
||||
var filter = ol.xml.createElementNS('http://www.opengis.net/ogc', 'Filter');
|
||||
var child = ol.xml.createElementNS('http://www.opengis.net/ogc', 'FeatureId');
|
||||
filter.appendChild(child);
|
||||
child.setAttribute('fid', fid);
|
||||
node.appendChild(filter);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeDelete_ = function(node, feature, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var featureType = context['featureType'];
|
||||
var featurePrefix = context['featurePrefix'];
|
||||
featurePrefix = goog.isDef(featurePrefix) ? featurePrefix :
|
||||
ol.format.WFS.FEATURE_PREFIX;
|
||||
var featureNS = context['featureNS'];
|
||||
node.setAttribute('typeName', featurePrefix + ':' + featureType);
|
||||
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
|
||||
featureNS);
|
||||
var fid = feature.getId();
|
||||
if (goog.isDef(fid)) {
|
||||
ol.format.WFS.writeOgcFidFilter_(node, fid, objectStack);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeUpdate_ = function(node, feature, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var featureType = context['featureType'];
|
||||
var featurePrefix = context['featurePrefix'];
|
||||
featurePrefix = goog.isDef(featurePrefix) ? featurePrefix :
|
||||
ol.format.WFS.FEATURE_PREFIX;
|
||||
var featureNS = context['featureNS'];
|
||||
node.setAttribute('typeName', featurePrefix + ':' + featureType);
|
||||
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
|
||||
featureNS);
|
||||
var fid = feature.getId();
|
||||
if (goog.isDef(fid)) {
|
||||
var keys = feature.getKeys();
|
||||
var values = [];
|
||||
for (var i = 0, ii = keys.length; i < ii; i++) {
|
||||
var value = feature.get(keys[i]);
|
||||
if (goog.isDef(value)) {
|
||||
values.push({name: keys[i], value: value});
|
||||
}
|
||||
}
|
||||
ol.xml.pushSerializeAndPop({node: node, srsName:
|
||||
context['srsName']},
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Property'), values,
|
||||
objectStack);
|
||||
ol.format.WFS.writeOgcFidFilter_(node, fid, objectStack);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Object} pair Property name and value.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeProperty_ = function(node, pair, objectStack) {
|
||||
var name = ol.xml.createElementNS('http://www.opengis.net/wfs', 'Name');
|
||||
node.appendChild(name);
|
||||
ol.format.XSD.writeStringTextNode(name, pair.name);
|
||||
if (goog.isDefAndNotNull(pair.value)) {
|
||||
var value = ol.xml.createElementNS('http://www.opengis.net/wfs', 'Value');
|
||||
node.appendChild(value);
|
||||
if (pair.value instanceof ol.geom.Geometry) {
|
||||
ol.format.GML3.prototype.writeGeometryElement(value,
|
||||
pair.value, objectStack);
|
||||
} else {
|
||||
ol.format.XSD.writeStringTextNode(value, pair.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {{vendorId: string, safeToIgnore: boolean, value: string}}
|
||||
* nativeElement The native element.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeNative_ = function(node, nativeElement, objectStack) {
|
||||
if (goog.isDef(nativeElement.vendorId)) {
|
||||
node.setAttribute('vendorId', nativeElement.vendorId);
|
||||
}
|
||||
if (goog.isDef(nativeElement.safeToIgnore)) {
|
||||
node.setAttribute('safeToIgnore', nativeElement.safeToIgnore);
|
||||
}
|
||||
if (goog.isDef(nativeElement.value)) {
|
||||
ol.format.XSD.writeStringTextNode(node, nativeElement.value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'Insert': ol.xml.makeChildAppender(ol.format.WFS.writeFeature_),
|
||||
'Update': ol.xml.makeChildAppender(ol.format.WFS.writeUpdate_),
|
||||
'Delete': ol.xml.makeChildAppender(ol.format.WFS.writeDelete_),
|
||||
'Property': ol.xml.makeChildAppender(ol.format.WFS.writeProperty_),
|
||||
'Native': ol.xml.makeChildAppender(ol.format.WFS.writeNative_)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {string} featureType Feature type.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeQuery_ = function(node, featureType, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var featurePrefix = context['featurePrefix'];
|
||||
var featureNS = context['featureNS'];
|
||||
var propertyNames = context['propertyNames'];
|
||||
var srsName = context['srsName'];
|
||||
var prefix = goog.isDef(featurePrefix) ? featurePrefix + ':' : '';
|
||||
node.setAttribute('typeName', prefix + featureType);
|
||||
if (goog.isDef(srsName)) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
if (goog.isDef(featureNS)) {
|
||||
ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
|
||||
featureNS);
|
||||
}
|
||||
var item = goog.object.clone(context);
|
||||
item.node = node;
|
||||
ol.xml.pushSerializeAndPop(item,
|
||||
ol.format.WFS.QUERY_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('PropertyName'), propertyNames,
|
||||
objectStack);
|
||||
var bbox = context['bbox'];
|
||||
if (goog.isDef(bbox)) {
|
||||
var child = ol.xml.createElementNS('http://www.opengis.net/ogc', 'Filter');
|
||||
ol.format.WFS.writeOgcBBOX_(child, bbox, objectStack);
|
||||
node.appendChild(child);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {string} value PropertyName value.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeOgcPropertyName_ = function(node, value, objectStack) {
|
||||
var property = ol.xml.createElementNS('http://www.opengis.net/ogc',
|
||||
'PropertyName');
|
||||
ol.format.XSD.writeStringTextNode(property, value);
|
||||
node.appendChild(property);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Extent} bbox Bounding box.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeOgcBBOX_ = function(node, bbox, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var geometryName = context['geometryName'];
|
||||
var bboxNode = ol.xml.createElementNS('http://www.opengis.net/ogc', 'BBOX');
|
||||
node.appendChild(bboxNode);
|
||||
ol.format.WFS.writeOgcPropertyName_(bboxNode, geometryName, objectStack);
|
||||
ol.format.GML3.prototype.writeGeometryElement(bboxNode, bbox, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.GETFEATURE_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/wfs': {
|
||||
'Query': ol.xml.makeChildAppender(
|
||||
ol.format.WFS.writeQuery_)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<{string}>} featureTypes Feature types.
|
||||
* @param {Array.<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WFS.writeGetFeature_ = function(node, featureTypes, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
var item = goog.object.clone(context);
|
||||
item.node = node;
|
||||
ol.xml.pushSerializeAndPop(item,
|
||||
ol.format.WFS.GETFEATURE_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Query'), featureTypes,
|
||||
objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.format.WFSWriteGetFeatureOptions} options Options.
|
||||
* @return {Node} Result.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.writeGetFeature = function(options) {
|
||||
var node = ol.xml.createElementNS('http://www.opengis.net/wfs',
|
||||
'GetFeature');
|
||||
node.setAttribute('service', 'WFS');
|
||||
node.setAttribute('version', '1.1.0');
|
||||
if (goog.isDef(options)) {
|
||||
if (goog.isDef(options.handle)) {
|
||||
node.setAttribute('handle', options.handle);
|
||||
}
|
||||
if (goog.isDef(options.outputFormat)) {
|
||||
node.setAttribute('outputFormat', options.outputFormat);
|
||||
}
|
||||
if (goog.isDef(options.maxFeatures)) {
|
||||
node.setAttribute('maxFeatures', options.maxFeatures);
|
||||
}
|
||||
if (goog.isDef(options.resultType)) {
|
||||
node.setAttribute('resultType', options.resultType);
|
||||
}
|
||||
if (goog.isDef(options.startIndex)) {
|
||||
node.setAttribute('startIndex', options.startIndex);
|
||||
}
|
||||
if (goog.isDef(options.count)) {
|
||||
node.setAttribute('count', options.count);
|
||||
}
|
||||
}
|
||||
ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation', this.schemaLocation_);
|
||||
var context = {
|
||||
node: node,
|
||||
srsName: options.srsName,
|
||||
featureNS: goog.isDef(options.featureNS) ?
|
||||
options.featureNS : this.featureNS_,
|
||||
featurePrefix: options.featurePrefix,
|
||||
geometryName: options.geometryName,
|
||||
bbox: options.bbox,
|
||||
propertyNames: goog.isDef(options.propertyNames) ?
|
||||
options.propertyNames : []
|
||||
};
|
||||
goog.asserts.assert(goog.isArray(options.featureTypes));
|
||||
ol.format.WFS.writeGetFeature_(node, options.featureTypes, [context]);
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Feature>} inserts The features to insert.
|
||||
* @param {Array.<ol.Feature>} updates The features to update.
|
||||
* @param {Array.<ol.Feature>} deletes The features to delete.
|
||||
* @param {olx.format.WFSWriteTransactionOptions} options Write options.
|
||||
* @return {Node} Result.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.writeTransaction = function(inserts, updates, deletes,
|
||||
options) {
|
||||
var objectStack = [];
|
||||
var node = ol.xml.createElementNS('http://www.opengis.net/wfs',
|
||||
'Transaction');
|
||||
node.setAttribute('service', 'WFS');
|
||||
node.setAttribute('version', '1.1.0');
|
||||
var baseObj, obj;
|
||||
if (goog.isDef(options)) {
|
||||
baseObj = goog.isDef(options.gmlOptions) ? options.gmlOptions : {};
|
||||
if (goog.isDef(options.handle)) {
|
||||
node.setAttribute('handle', options.handle);
|
||||
}
|
||||
}
|
||||
ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation', this.schemaLocation_);
|
||||
if (goog.isDefAndNotNull(inserts)) {
|
||||
obj = {node: node, featureNS: options.featureNS,
|
||||
featureType: options.featureType, featurePrefix: options.featurePrefix};
|
||||
goog.object.extend(obj, baseObj);
|
||||
ol.xml.pushSerializeAndPop(obj,
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Insert'), inserts,
|
||||
objectStack);
|
||||
}
|
||||
if (goog.isDefAndNotNull(updates)) {
|
||||
obj = {node: node, featureNS: options.featureNS,
|
||||
featureType: options.featureType, featurePrefix: options.featurePrefix};
|
||||
goog.object.extend(obj, baseObj);
|
||||
ol.xml.pushSerializeAndPop(obj,
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Update'), updates,
|
||||
objectStack);
|
||||
}
|
||||
if (goog.isDefAndNotNull(deletes)) {
|
||||
ol.xml.pushSerializeAndPop({node: node, featureNS: options.featureNS,
|
||||
featureType: options.featureType, featurePrefix: options.featurePrefix},
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Delete'), deletes,
|
||||
objectStack);
|
||||
}
|
||||
if (goog.isDef(options.nativeElements)) {
|
||||
ol.xml.pushSerializeAndPop({node: node, featureNS: options.featureNS,
|
||||
featureType: options.featureType, featurePrefix: options.featurePrefix},
|
||||
ol.format.WFS.TRANSACTION_SERIALIZERS_,
|
||||
ol.xml.makeSimpleNodeFactory('Native'), options.nativeElements,
|
||||
objectStack);
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the projection from a WFS source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @return {?ol.proj.Projection} Projection.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WFS.prototype.readProjection;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WFS.prototype.readProjectionFromDocument = function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readProjectionFromNode(n);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WFS.prototype.readProjectionFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'FeatureCollection');
|
||||
|
||||
if (goog.isDefAndNotNull(node.firstElementChild) &&
|
||||
goog.isDefAndNotNull(node.firstElementChild.firstElementChild)) {
|
||||
node = node.firstElementChild.firstElementChild;
|
||||
for (var n = node.firstElementChild; !goog.isNull(n);
|
||||
n = n.nextElementSibling) {
|
||||
if (!(n.childNodes.length === 0 ||
|
||||
(n.childNodes.length === 1 &&
|
||||
n.firstChild.nodeType === 3))) {
|
||||
var objectStack = [{}];
|
||||
this.gmlFormat_.readGeometryElement(n, objectStack);
|
||||
return ol.proj.get(objectStack.pop().srsName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,852 @@
|
||||
goog.provide('ol.format.WKT');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.TextFeature');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.GeometryCollection');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.format.TextFeature}
|
||||
* @param {olx.format.WKTOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Split GeometryCollection into multiple features.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.splitCollection_ = goog.isDef(options.splitCollection) ?
|
||||
options.splitCollection : false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.format.WKT, ol.format.TextFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.WKT.EMPTY = 'EMPTY';
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Point} geom Point geometry.
|
||||
* @return {string} Coordinates part of Point as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodePointGeometry_ = function(geom) {
|
||||
var coordinates = geom.getCoordinates();
|
||||
if (goog.array.isEmpty(coordinates)) {
|
||||
return '';
|
||||
}
|
||||
return coordinates[0] + ' ' + coordinates[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.MultiPoint} geom MultiPoint geometry.
|
||||
* @return {string} Coordinates part of MultiPoint as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodeMultiPointGeometry_ = function(geom) {
|
||||
var array = [];
|
||||
var components = geom.getPoints();
|
||||
for (var i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + ol.format.WKT.encodePointGeometry_(components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryCollection} geom GeometryCollection geometry.
|
||||
* @return {string} Coordinates part of GeometryCollection as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodeGeometryCollectionGeometry_ = function(geom) {
|
||||
var array = [];
|
||||
var geoms = geom.getGeometries();
|
||||
for (var i = 0, ii = geoms.length; i < ii; ++i) {
|
||||
array.push(ol.format.WKT.encode_(geoms[i]));
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.LineString|ol.geom.LinearRing} geom LineString geometry.
|
||||
* @return {string} Coordinates part of LineString as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodeLineStringGeometry_ = function(geom) {
|
||||
var coordinates = geom.getCoordinates();
|
||||
var array = [];
|
||||
for (var i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
array.push(coordinates[i][0] + ' ' + coordinates[i][1]);
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.MultiLineString} geom MultiLineString geometry.
|
||||
* @return {string} Coordinates part of MultiLineString as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodeMultiLineStringGeometry_ = function(geom) {
|
||||
var array = [];
|
||||
var components = geom.getLineStrings();
|
||||
for (var i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
|
||||
components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Polygon} geom Polygon geometry.
|
||||
* @return {string} Coordinates part of Polygon as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodePolygonGeometry_ = function(geom) {
|
||||
var array = [];
|
||||
var rings = geom.getLinearRings();
|
||||
for (var i = 0, ii = rings.length; i < ii; ++i) {
|
||||
array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
|
||||
rings[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.MultiPolygon} geom MultiPolygon geometry.
|
||||
* @return {string} Coordinates part of MultiPolygon as WKT.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encodeMultiPolygonGeometry_ = function(geom) {
|
||||
var array = [];
|
||||
var components = geom.getPolygons();
|
||||
for (var i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + ol.format.WKT.encodePolygonGeometry_(
|
||||
components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a geometry as WKT.
|
||||
* @param {ol.geom.Geometry} geom The geometry to encode.
|
||||
* @return {string} WKT string for the geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.encode_ = function(geom) {
|
||||
var type = geom.getType();
|
||||
var geometryEncoder = ol.format.WKT.GeometryEncoder_[type];
|
||||
goog.asserts.assert(goog.isDef(geometryEncoder));
|
||||
var enc = geometryEncoder(geom);
|
||||
type = type.toUpperCase();
|
||||
if (enc.length === 0) {
|
||||
return type + ' ' + ol.format.WKT.EMPTY;
|
||||
}
|
||||
return type + '(' + enc + ')';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, function(ol.geom.Geometry): string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.GeometryEncoder_ = {
|
||||
'Point': ol.format.WKT.encodePointGeometry_,
|
||||
'LineString': ol.format.WKT.encodeLineStringGeometry_,
|
||||
'Polygon': ol.format.WKT.encodePolygonGeometry_,
|
||||
'MultiPoint': ol.format.WKT.encodeMultiPointGeometry_,
|
||||
'MultiLineString': ol.format.WKT.encodeMultiLineStringGeometry_,
|
||||
'MultiPolygon': ol.format.WKT.encodeMultiPolygonGeometry_,
|
||||
'GeometryCollection': ol.format.WKT.encodeGeometryCollectionGeometry_
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse a WKT string.
|
||||
* @param {string} wkt WKT string.
|
||||
* @return {ol.geom.Geometry|ol.geom.GeometryCollection|undefined}
|
||||
* The geometry created.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.prototype.parse_ = function(wkt) {
|
||||
var lexer = new ol.format.WKT.Lexer(wkt);
|
||||
var parser = new ol.format.WKT.Parser(lexer);
|
||||
return parser.parse();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read a feature from a WKT source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.Feature} Feature.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.readFeature;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.readFeatureFromText = function(text, opt_options) {
|
||||
var geom = this.readGeometryFromText(text, opt_options);
|
||||
if (goog.isDef(geom)) {
|
||||
var feature = new ol.Feature();
|
||||
feature.setGeometry(geom);
|
||||
return feature;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a WKT source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.readFeaturesFromText = function(text, opt_options) {
|
||||
var geometries = [];
|
||||
var geometry = this.readGeometryFromText(text, opt_options);
|
||||
if (this.splitCollection_ &&
|
||||
geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
|
||||
geometries = (/** @type {ol.geom.GeometryCollection} */ (geometry))
|
||||
.getGeometriesArray();
|
||||
} else {
|
||||
geometries = [geometry];
|
||||
}
|
||||
var feature, features = [];
|
||||
for (var i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
feature = new ol.Feature();
|
||||
feature.setGeometry(geometries[i]);
|
||||
features.push(feature);
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read a single geometry from a WKT source.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Read options.
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.readGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.readGeometryFromText = function(text, opt_options) {
|
||||
var geometry = this.parse_(text);
|
||||
if (goog.isDef(geometry)) {
|
||||
return /** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, false, opt_options));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode a feature as a WKT string.
|
||||
*
|
||||
* @function
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} WKT string.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.writeFeature;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.writeFeatureText = function(feature, opt_options) {
|
||||
var geometry = feature.getGeometry();
|
||||
if (goog.isDef(geometry)) {
|
||||
return this.writeGeometryText(geometry, opt_options);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features as a WKT string.
|
||||
*
|
||||
* @function
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @return {string} WKT string.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.writeFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.writeFeaturesText = function(features, opt_options) {
|
||||
if (features.length == 1) {
|
||||
return this.writeFeatureText(features[0], opt_options);
|
||||
}
|
||||
var geometries = [];
|
||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||
geometries.push(features[i].getGeometry());
|
||||
}
|
||||
var collection = new ol.geom.GeometryCollection(geometries);
|
||||
return this.writeGeometryText(collection, opt_options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write a single geometry as a WKT string.
|
||||
*
|
||||
* @function
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @return {string} WKT string.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WKT.prototype.writeGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WKT.prototype.writeGeometryText = function(geometry, opt_options) {
|
||||
return ol.format.WKT.encode_(/** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, true, opt_options)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{type: number, value: (number|string|undefined), position: number}}
|
||||
*/
|
||||
ol.format.WKT.Token;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.format.WKT.TokenType = {
|
||||
TEXT: 1,
|
||||
LEFT_PAREN: 2,
|
||||
RIGHT_PAREN: 3,
|
||||
NUMBER: 4,
|
||||
COMMA: 5,
|
||||
EOF: 6
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class to tokenize a WKT string.
|
||||
* @param {string} wkt WKT string.
|
||||
* @constructor
|
||||
* @protected
|
||||
*/
|
||||
ol.format.WKT.Lexer = function(wkt) {
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.wkt = wkt;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.index_ = -1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @return {boolean} Whether the character is alphabetic.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.isAlpha_ = function(c) {
|
||||
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @param {boolean=} opt_decimal Whether the string number
|
||||
* contains a dot, i.e. is a decimal number.
|
||||
* @return {boolean} Whether the character is numeric.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.isNumeric_ = function(c, opt_decimal) {
|
||||
var decimal = goog.isDef(opt_decimal) ? opt_decimal : false;
|
||||
return c >= '0' && c <= '9' || c == '.' && !decimal;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @return {boolean} Whether the character is whitespace.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.isWhiteSpace_ = function(c) {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Next string character.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.nextChar_ = function() {
|
||||
return this.wkt.charAt(++this.index_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fetch and return the next token.
|
||||
* @return {!ol.format.WKT.Token} Next string token.
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.nextToken = function() {
|
||||
var c = this.nextChar_();
|
||||
var token = {position: this.index_, value: c};
|
||||
|
||||
if (c == '(') {
|
||||
token.type = ol.format.WKT.TokenType.LEFT_PAREN;
|
||||
} else if (c == ',') {
|
||||
token.type = ol.format.WKT.TokenType.COMMA;
|
||||
} else if (c == ')') {
|
||||
token.type = ol.format.WKT.TokenType.RIGHT_PAREN;
|
||||
} else if (this.isNumeric_(c) || c == '-') {
|
||||
token.type = ol.format.WKT.TokenType.NUMBER;
|
||||
token.value = this.readNumber_();
|
||||
} else if (this.isAlpha_(c)) {
|
||||
token.type = ol.format.WKT.TokenType.TEXT;
|
||||
token.value = this.readText_();
|
||||
} else if (this.isWhiteSpace_(c)) {
|
||||
return this.nextToken();
|
||||
} else if (c === '') {
|
||||
token.type = ol.format.WKT.TokenType.EOF;
|
||||
} else {
|
||||
throw new Error('Unexpected character: ' + c);
|
||||
}
|
||||
|
||||
return token;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Numeric token value.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.readNumber_ = function() {
|
||||
var c, index = this.index_;
|
||||
var decimal = false;
|
||||
do {
|
||||
if (c == '.') {
|
||||
decimal = true;
|
||||
}
|
||||
c = this.nextChar_();
|
||||
} while (this.isNumeric_(c, decimal));
|
||||
return parseFloat(this.wkt.substring(index, this.index_--));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} String token value.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Lexer.prototype.readText_ = function() {
|
||||
var c, index = this.index_;
|
||||
do {
|
||||
c = this.nextChar_();
|
||||
} while (this.isAlpha_(c));
|
||||
return this.wkt.substring(index, this.index_--).toUpperCase();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class to parse the tokens from the WKT string.
|
||||
* @param {ol.format.WKT.Lexer} lexer
|
||||
* @constructor
|
||||
* @protected
|
||||
*/
|
||||
ol.format.WKT.Parser = function(lexer) {
|
||||
|
||||
/**
|
||||
* @type {ol.format.WKT.Lexer}
|
||||
* @private
|
||||
*/
|
||||
this.lexer_ = lexer;
|
||||
|
||||
/**
|
||||
* @type {ol.format.WKT.Token}
|
||||
* @private
|
||||
*/
|
||||
this.token_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.dimension_ = 2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the next token form the lexer and replace the active token.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.consume_ = function() {
|
||||
this.token_ = this.lexer_.nextToken();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* If the given type matches the current token, consume it.
|
||||
* @param {ol.format.WKT.TokenType.<number>} type Token type.
|
||||
* @return {boolean} Whether the token matches the given type.
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.match = function(type) {
|
||||
var isMatch = this.token_.type == type;
|
||||
if (isMatch) {
|
||||
this.consume_();
|
||||
}
|
||||
return isMatch;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Try to parse the tokens provided by the lexer.
|
||||
* @return {ol.geom.Geometry|ol.geom.GeometryCollection} The geometry.
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parse = function() {
|
||||
this.consume_();
|
||||
var geometry = this.parseGeometry_();
|
||||
goog.asserts.assert(this.token_.type == ol.format.WKT.TokenType.EOF);
|
||||
return geometry;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!(ol.geom.Geometry|ol.geom.GeometryCollection)} The geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseGeometry_ = function() {
|
||||
var token = this.token_;
|
||||
if (this.match(ol.format.WKT.TokenType.TEXT)) {
|
||||
var geomType = token.value;
|
||||
if (geomType == ol.geom.GeometryType.GEOMETRY_COLLECTION.toUpperCase()) {
|
||||
var geometries = this.parseGeometryCollectionText_();
|
||||
return new ol.geom.GeometryCollection(geometries);
|
||||
} else {
|
||||
var parser = ol.format.WKT.Parser.GeometryParser_[geomType];
|
||||
var ctor = ol.format.WKT.Parser.GeometryConstructor_[geomType];
|
||||
if (!goog.isDef(parser) || !goog.isDef(ctor)) {
|
||||
throw new Error('Invalid geometry type: ' + geomType);
|
||||
}
|
||||
var coordinates = parser.call(this);
|
||||
return new ctor(coordinates);
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<ol.geom.Geometry>} A collection of geometries.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseGeometryCollectionText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var geometries = [];
|
||||
do {
|
||||
geometries.push(this.parseGeometry_());
|
||||
} while (this.match(ol.format.WKT.TokenType.COMMA));
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return geometries;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} All values in a point.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePointText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates = this.parsePoint_();
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return null;
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} All points in a linestring.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseLineStringText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates = this.parsePointList_();
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} All points in a polygon.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePolygonText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates = this.parseLineStringTextList_();
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} All points in a multipoint.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseMultiPointText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates;
|
||||
if (this.token_.type == ol.format.WKT.TokenType.LEFT_PAREN) {
|
||||
coordinates = this.parsePointTextList_();
|
||||
} else {
|
||||
coordinates = this.parsePointList_();
|
||||
}
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} All linestring points
|
||||
* in a multilinestring.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseMultiLineStringText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates = this.parseLineStringTextList_();
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} All polygon points in a multipolygon.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseMultiPolygonText_ = function() {
|
||||
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
|
||||
var coordinates = this.parsePolygonTextList_();
|
||||
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
} else if (this.isEmptyGeometry_()) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<number>} A point.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePoint_ = function() {
|
||||
var coordinates = [];
|
||||
for (var i = 0; i < this.dimension_; ++i) {
|
||||
var token = this.token_;
|
||||
if (this.match(ol.format.WKT.TokenType.NUMBER)) {
|
||||
coordinates.push(token.value);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (coordinates.length == this.dimension_) {
|
||||
return coordinates;
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePointList_ = function() {
|
||||
var coordinates = [this.parsePoint_()];
|
||||
while (this.match(ol.format.WKT.TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePoint_());
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePointTextList_ = function() {
|
||||
var coordinates = [this.parsePointText_()];
|
||||
while (this.match(ol.format.WKT.TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePointText_());
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parseLineStringTextList_ = function() {
|
||||
var coordinates = [this.parseLineStringText_()];
|
||||
while (this.match(ol.format.WKT.TokenType.COMMA)) {
|
||||
coordinates.push(this.parseLineStringText_());
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.parsePolygonTextList_ = function() {
|
||||
var coordinates = [this.parsePolygonText_()];
|
||||
while (this.match(ol.format.WKT.TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePolygonText_());
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the token implies an empty geometry.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.isEmptyGeometry_ = function() {
|
||||
var isEmpty = this.token_.type == ol.format.WKT.TokenType.TEXT &&
|
||||
this.token_.value == ol.format.WKT.EMPTY;
|
||||
if (isEmpty) {
|
||||
this.consume_();
|
||||
}
|
||||
return isEmpty;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an error message for an unexpected token error.
|
||||
* @return {string} Error message.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.prototype.formatErrorMessage_ = function() {
|
||||
return 'Unexpected `' + this.token_.value + '` at position ' +
|
||||
this.token_.position + ' in `' + this.lexer_.wkt + '`';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {function (new:ol.geom.Geometry, Array, ol.geom.GeometryLayout.<string>=)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.GeometryConstructor_ = {
|
||||
'POINT': ol.geom.Point,
|
||||
'LINESTRING': ol.geom.LineString,
|
||||
'POLYGON': ol.geom.Polygon,
|
||||
'MULTIPOINT': ol.geom.MultiPoint,
|
||||
'MULTILINESTRING': ol.geom.MultiLineString,
|
||||
'MULTIPOLYGON': ol.geom.MultiPolygon
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {(function(): Array)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WKT.Parser.GeometryParser_ = {
|
||||
'POINT': ol.format.WKT.Parser.prototype.parsePointText_,
|
||||
'LINESTRING': ol.format.WKT.Parser.prototype.parseLineStringText_,
|
||||
'POLYGON': ol.format.WKT.Parser.prototype.parsePolygonText_,
|
||||
'MULTIPOINT': ol.format.WKT.Parser.prototype.parseMultiPointText_,
|
||||
'MULTILINESTRING': ol.format.WKT.Parser.prototype.parseMultiLineStringText_,
|
||||
'MULTIPOLYGON': ol.format.WKT.Parser.prototype.parseMultiPolygonText_
|
||||
};
|
||||
@@ -0,0 +1,832 @@
|
||||
goog.provide('ol.format.WMSCapabilities');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.format.XLink');
|
||||
goog.require('ol.format.XML');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMS capabilities data
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.XML}
|
||||
* @api
|
||||
*/
|
||||
ol.format.WMSCapabilities = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.version = undefined;
|
||||
};
|
||||
goog.inherits(ol.format.WMSCapabilities, ol.format.XML);
|
||||
|
||||
|
||||
/**
|
||||
* Read a WMS capabilities document.
|
||||
*
|
||||
* @function
|
||||
* @param {Document|Node|string} source The XML source.
|
||||
* @return {Object} An object representing the WMS capabilities.
|
||||
* @api
|
||||
*/
|
||||
ol.format.WMSCapabilities.prototype.read;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {Object} WMS Capability object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.prototype.readFromDocument = function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readFromNode(n);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {Object} WMS Capability object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.prototype.readFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'WMS_Capabilities' ||
|
||||
node.localName == 'WMT_MS_Capabilities');
|
||||
this.version = goog.string.trim(node.getAttribute('version'));
|
||||
goog.asserts.assertString(this.version);
|
||||
var wmsCapabilityObject = ol.xml.pushParseAndPop({
|
||||
'version': this.version
|
||||
}, ol.format.WMSCapabilities.PARSERS_, node, []);
|
||||
return goog.isDef(wmsCapabilityObject) ? wmsCapabilityObject : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Attribution object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readAttribution_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Attribution');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object} Bounding box object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readBoundingBox_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'BoundingBox');
|
||||
|
||||
var extent = [
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('minx')),
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('miny')),
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('maxx')),
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('maxy'))
|
||||
];
|
||||
|
||||
var resolutions = [
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('resx')),
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('resy'))
|
||||
];
|
||||
|
||||
return {
|
||||
'crs': node.getAttribute('CRS'),
|
||||
'extent': extent,
|
||||
'res': resolutions
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {ol.Extent|undefined} Bounding box object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readEXGeographicBoundingBox_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'EX_GeographicBoundingBox');
|
||||
var geographicBoundingBox = ol.xml.pushParseAndPop(
|
||||
{},
|
||||
ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_,
|
||||
node, objectStack);
|
||||
if (!goog.isDef(geographicBoundingBox)) {
|
||||
return undefined;
|
||||
}
|
||||
var westBoundLongitude = /** @type {number|undefined} */
|
||||
(geographicBoundingBox['westBoundLongitude']);
|
||||
var southBoundLatitude = /** @type {number|undefined} */
|
||||
(geographicBoundingBox['southBoundLatitude']);
|
||||
var eastBoundLongitude = /** @type {number|undefined} */
|
||||
(geographicBoundingBox['eastBoundLongitude']);
|
||||
var northBoundLatitude = /** @type {number|undefined} */
|
||||
(geographicBoundingBox['northBoundLatitude']);
|
||||
if (!goog.isDef(westBoundLongitude) || !goog.isDef(southBoundLatitude) ||
|
||||
!goog.isDef(eastBoundLongitude) || !goog.isDef(northBoundLatitude)) {
|
||||
return undefined;
|
||||
}
|
||||
return [
|
||||
westBoundLongitude, southBoundLatitude,
|
||||
eastBoundLongitude, northBoundLatitude
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Capability object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readCapability_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Capability');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.CAPABILITY_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Service object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readService_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Service');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.SERVICE_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Contact information object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readContactInformation_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ContactInformation');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_,
|
||||
node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Contact person object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readContactPersonPrimary_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ContactPersonPrimary');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_,
|
||||
node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Contact address object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readContactAddress_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'ContactAddress');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_,
|
||||
node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Array.<string>|undefined} Format array.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readException_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Exception');
|
||||
return ol.xml.pushParseAndPop(
|
||||
[], ol.format.WMSCapabilities.EXCEPTION_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
* @return {Object|undefined} Layer object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readCapabilityLayer_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Layer');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Layer object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readLayer_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Layer');
|
||||
var parentLayerObject = /** @type {Object.<string,*>} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
|
||||
var layerObject = /** @type {Object.<string,*>} */ (ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack));
|
||||
|
||||
if (!goog.isDef(layerObject)) {
|
||||
return undefined;
|
||||
}
|
||||
var queryable =
|
||||
ol.format.XSD.readBooleanString(node.getAttribute('queryable'));
|
||||
if (!goog.isDef(queryable)) {
|
||||
queryable = parentLayerObject['queryable'];
|
||||
}
|
||||
layerObject['queryable'] = goog.isDef(queryable) ? queryable : false;
|
||||
|
||||
var cascaded = ol.format.XSD.readNonNegativeIntegerString(
|
||||
node.getAttribute('cascaded'));
|
||||
if (!goog.isDef(cascaded)) {
|
||||
cascaded = parentLayerObject['cascaded'];
|
||||
}
|
||||
layerObject['cascaded'] = cascaded;
|
||||
|
||||
var opaque = ol.format.XSD.readBooleanString(node.getAttribute('opaque'));
|
||||
if (!goog.isDef(opaque)) {
|
||||
opaque = parentLayerObject['opaque'];
|
||||
}
|
||||
layerObject['opaque'] = goog.isDef(opaque) ? opaque : false;
|
||||
|
||||
var noSubsets =
|
||||
ol.format.XSD.readBooleanString(node.getAttribute('noSubsets'));
|
||||
if (!goog.isDef(noSubsets)) {
|
||||
noSubsets = parentLayerObject['noSubsets'];
|
||||
}
|
||||
layerObject['noSubsets'] = goog.isDef(noSubsets) ? noSubsets : false;
|
||||
|
||||
var fixedWidth =
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('fixedWidth'));
|
||||
if (!goog.isDef(fixedWidth)) {
|
||||
fixedWidth = parentLayerObject['fixedWidth'];
|
||||
}
|
||||
layerObject['fixedWidth'] = fixedWidth;
|
||||
|
||||
var fixedHeight =
|
||||
ol.format.XSD.readDecimalString(node.getAttribute('fixedHeight'));
|
||||
if (!goog.isDef(fixedHeight)) {
|
||||
fixedHeight = parentLayerObject['fixedHeight'];
|
||||
}
|
||||
layerObject['fixedHeight'] = fixedHeight;
|
||||
|
||||
// See 7.2.4.8
|
||||
var addKeys = ['Style', 'CRS', 'AuthorityURL'];
|
||||
goog.array.forEach(addKeys, function(key) {
|
||||
var parentValue = parentLayerObject[key];
|
||||
if (goog.isDef(parentValue)) {
|
||||
var childValue = goog.object.setIfUndefined(layerObject, key, []);
|
||||
childValue = childValue.concat(parentValue);
|
||||
layerObject[key] = childValue;
|
||||
}
|
||||
});
|
||||
|
||||
var replaceKeys = ['EX_GeographicBoundingBox', 'BoundingBox', 'Dimension',
|
||||
'Attribution', 'MinScaleDenominator', 'MaxScaleDenominator'];
|
||||
goog.array.forEach(replaceKeys, function(key) {
|
||||
var childValue = layerObject[key];
|
||||
if (!goog.isDef(childValue)) {
|
||||
var parentValue = parentLayerObject[key];
|
||||
layerObject[key] = parentValue;
|
||||
}
|
||||
});
|
||||
|
||||
return layerObject;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object} Dimension object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readDimension_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Dimension');
|
||||
var dimensionObject = {
|
||||
'name': node.getAttribute('name'),
|
||||
'units': node.getAttribute('units'),
|
||||
'unitSymbol': node.getAttribute('unitSymbol'),
|
||||
'default': node.getAttribute('default'),
|
||||
'multipleValues': ol.format.XSD.readBooleanString(
|
||||
node.getAttribute('multipleValues')),
|
||||
'nearestValue': ol.format.XSD.readBooleanString(
|
||||
node.getAttribute('nearestValue')),
|
||||
'current': ol.format.XSD.readBooleanString(node.getAttribute('current')),
|
||||
'values': ol.format.XSD.readString(node)
|
||||
};
|
||||
return dimensionObject;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Online resource object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_,
|
||||
node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Request object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readRequest_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Request');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.REQUEST_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} DCP type object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readDCPType_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'DCPType');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.DCPTYPE_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} HTTP object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readHTTP_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'HTTP');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.HTTP_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Operation type object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readOperationType_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Online resource object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readSizedFormatOnlineresource_ =
|
||||
function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
var formatOnlineresource =
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
|
||||
if (goog.isDef(formatOnlineresource)) {
|
||||
var size = [
|
||||
ol.format.XSD.readNonNegativeIntegerString(node.getAttribute('width')),
|
||||
ol.format.XSD.readNonNegativeIntegerString(node.getAttribute('height'))
|
||||
];
|
||||
formatOnlineresource['size'] = size;
|
||||
return formatOnlineresource;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Authority URL object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readAuthorityURL_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'AuthorityURL');
|
||||
var authorityObject =
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
|
||||
if (goog.isDef(authorityObject)) {
|
||||
authorityObject['name'] = node.getAttribute('name');
|
||||
return authorityObject;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Metadata URL object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readMetadataURL_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'MetadataURL');
|
||||
var metadataObject =
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
|
||||
if (goog.isDef(metadataObject)) {
|
||||
metadataObject['type'] = node.getAttribute('type');
|
||||
return metadataObject;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Style object.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readStyle_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Style');
|
||||
return ol.xml.pushParseAndPop(
|
||||
{}, ol.format.WMSCapabilities.STYLE_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Array.<string>|undefined} Keyword list.
|
||||
*/
|
||||
ol.format.WMSCapabilities.readKeywordList_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'KeywordList');
|
||||
return ol.xml.pushParseAndPop(
|
||||
[], ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_ = [
|
||||
null,
|
||||
'http://www.opengis.net/wms'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Service': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readService_),
|
||||
'Capability': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readCapability_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.CAPABILITY_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Request': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readRequest_),
|
||||
'Exception': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readException_),
|
||||
'Layer': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readCapabilityLayer_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.SERVICE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'KeywordList': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readKeywordList_),
|
||||
'OnlineResource': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XLink.readHref),
|
||||
'ContactInformation': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readContactInformation_),
|
||||
'Fees': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'AccessConstraints': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'LayerLimit': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'MaxWidth': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'MaxHeight': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'ContactPersonPrimary': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readContactPersonPrimary_),
|
||||
'ContactPosition': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'ContactAddress': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readContactAddress_),
|
||||
'ContactVoiceTelephone': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'ContactFacsimileTelephone': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'ContactElectronicMailAddress': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'ContactPerson': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'ContactOrganization': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'AddressType': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Address': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'City': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'StateOrProvince': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'PostCode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Country': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.EXCEPTION_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Format': ol.xml.makeArrayPusher(ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.LAYER_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'KeywordList': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readKeywordList_),
|
||||
'CRS': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
|
||||
'EX_GeographicBoundingBox': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readEXGeographicBoundingBox_),
|
||||
'BoundingBox': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readBoundingBox_),
|
||||
'Dimension': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readDimension_),
|
||||
'Attribution': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readAttribution_),
|
||||
'AuthorityURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readAuthorityURL_),
|
||||
'Identifier': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
|
||||
'MetadataURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readMetadataURL_),
|
||||
'DataURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_),
|
||||
'FeatureListURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_),
|
||||
'Style': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readStyle_),
|
||||
'MinScaleDenominator': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'MaxScaleDenominator': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'Layer': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readLayer_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'OnlineResource': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XLink.readHref),
|
||||
'LogoURL': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readSizedFormatOnlineresource_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_ =
|
||||
ol.xml.makeParsersNS(ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'westBoundLongitude': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'eastBoundLongitude': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'southBoundLatitude': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'northBoundLatitude': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.REQUEST_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'GetCapabilities': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readOperationType_),
|
||||
'GetMap': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readOperationType_),
|
||||
'GetFeatureInfo': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readOperationType_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Format': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
|
||||
'DCPType': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readDCPType_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.DCPTYPE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'HTTP': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readHTTP_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.HTTP_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Get': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_),
|
||||
'Post': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.STYLE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'LegendURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMSCapabilities.readSizedFormatOnlineresource_),
|
||||
'StyleSheetURL': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_),
|
||||
'StyleURL': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMSCapabilities.readFormatOnlineresource_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Format': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
|
||||
'OnlineResource': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XLink.readHref)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMSCapabilities.NAMESPACE_URIS_, {
|
||||
'Keyword': ol.xml.makeArrayPusher(ol.format.XSD.readString)
|
||||
});
|
||||
@@ -0,0 +1,145 @@
|
||||
goog.provide('ol.format.WMSGetFeatureInfo');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.format.GML');
|
||||
goog.require('ol.format.GML2');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMSGetFeatureInfo format. It uses
|
||||
* {@link ol.format.GML2} to read features.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.XMLFeature}
|
||||
* @api
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo = function() {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver';
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.format.GML2}
|
||||
*/
|
||||
this.gmlFormat_ = new ol.format.GML2();
|
||||
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.WMSGetFeatureInfo, ol.format.XMLFeature);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo.featureIdentifier_ = '_feature';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo.layerIdentifier_ = '_layer';
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo.prototype.readFeatures_ =
|
||||
function(node, objectStack) {
|
||||
|
||||
node.namespaceURI = this.featureNS_;
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
var localName = ol.xml.getLocalName(node);
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
if (node.childNodes.length === 0) {
|
||||
return features;
|
||||
}
|
||||
if (localName == 'msGMLOutput') {
|
||||
goog.array.forEach(node.childNodes, function(layer) {
|
||||
if (layer.nodeType !== goog.dom.NodeType.ELEMENT) {
|
||||
return;
|
||||
}
|
||||
var context = objectStack[0];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
|
||||
goog.asserts.assert(layer.localName.indexOf(
|
||||
ol.format.WMSGetFeatureInfo.layerIdentifier_) >= 0);
|
||||
|
||||
var featureType = goog.string.remove(layer.localName,
|
||||
ol.format.WMSGetFeatureInfo.layerIdentifier_) +
|
||||
ol.format.WMSGetFeatureInfo.featureIdentifier_;
|
||||
|
||||
context['featureType'] = featureType;
|
||||
context['featureNS'] = this.featureNS_;
|
||||
|
||||
var parsers = {};
|
||||
parsers[featureType] = ol.xml.makeArrayPusher(
|
||||
this.gmlFormat_.readFeatureElement, this.gmlFormat_);
|
||||
var parsersNS = ol.xml.makeParsersNS(
|
||||
[context['featureNS'], null], parsers);
|
||||
layer.namespaceURI = this.featureNS_;
|
||||
var layerFeatures = ol.xml.pushParseAndPop(
|
||||
[], parsersNS, layer, objectStack, this.gmlFormat_);
|
||||
if (goog.isDef(layerFeatures)) {
|
||||
goog.array.extend(features, layerFeatures);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
if (localName == 'FeatureCollection') {
|
||||
var gmlFeatures = ol.xml.pushParseAndPop([],
|
||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
|
||||
[{}], this.gmlFormat_);
|
||||
if (goog.isDef(gmlFeatures)) {
|
||||
features = gmlFeatures;
|
||||
}
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read all features from a WMSGetFeatureInfo response.
|
||||
*
|
||||
* @function
|
||||
* @param {ArrayBuffer|Document|Node|Object|string} source Source.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo.prototype.readFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.WMSGetFeatureInfo.prototype.readFeaturesFromNode =
|
||||
function(node, opt_options) {
|
||||
var options = {
|
||||
'featureType': this.featureType,
|
||||
'featureNS': this.featureNS
|
||||
};
|
||||
if (goog.isDef(opt_options)) {
|
||||
goog.object.extend(options, this.getReadOptions(node, opt_options));
|
||||
}
|
||||
return this.readFeatures_(node, [options]);
|
||||
};
|
||||
@@ -0,0 +1,400 @@
|
||||
goog.provide('ol.format.WMTSCapabilities');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.format.OWS');
|
||||
goog.require('ol.format.XLink');
|
||||
goog.require('ol.format.XML');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMTS capabilities data.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.XML}
|
||||
* @api
|
||||
*/
|
||||
ol.format.WMTSCapabilities = function() {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {ol.format.OWS}
|
||||
* @private
|
||||
*/
|
||||
this.owsParser_ = new ol.format.OWS();
|
||||
};
|
||||
goog.inherits(ol.format.WMTSCapabilities, ol.format.XML);
|
||||
|
||||
|
||||
/**
|
||||
* Read a WMTS capabilities document.
|
||||
*
|
||||
* @function
|
||||
* @param {Document|Node|string} source The XML source.
|
||||
* @return {Object} An object representing the WMTS capabilities.
|
||||
* @api
|
||||
*/
|
||||
ol.format.WMTSCapabilities.prototype.read;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {Object} WMTS Capability object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.prototype.readFromDocument = function(doc) {
|
||||
goog.asserts.assert(doc.nodeType == goog.dom.NodeType.DOCUMENT);
|
||||
for (var n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return this.readFromNode(n);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {Object} WMTS Capability object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.prototype.readFromNode = function(node) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Capabilities');
|
||||
this.version = goog.string.trim(node.getAttribute('version'));
|
||||
goog.asserts.assertString(this.version);
|
||||
var WMTSCapabilityObject = this.owsParser_.readFromNode(node);
|
||||
if (!goog.isDef(WMTSCapabilityObject)) {
|
||||
return null;
|
||||
}
|
||||
goog.object.set(WMTSCapabilityObject, 'version', this.version);
|
||||
WMTSCapabilityObject = ol.xml.pushParseAndPop(WMTSCapabilityObject,
|
||||
ol.format.WMTSCapabilities.PARSERS_, node, []);
|
||||
return goog.isDef(WMTSCapabilityObject) ? WMTSCapabilityObject : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Attribution object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readContents_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Contents');
|
||||
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.CONTENTS_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Layers object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readLayer_ = function(node, objectStack) {
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
goog.asserts.assert(node.localName == 'Layer');
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.LAYER_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Tile Matrix Set object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readTileMatrixSet_ = function(node, objectStack) {
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.TMS_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Style object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readStyle_ = function(node, objectStack) {
|
||||
var style = ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.STYLE_PARSERS_, node, objectStack);
|
||||
if (!goog.isDef(style)) {
|
||||
return undefined;
|
||||
}
|
||||
var isDefault = node.getAttribute('isDefault') === 'true';
|
||||
style['isDefault'] = isDefault;
|
||||
return style;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Tile Matrix Set Link object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readTileMatrixSetLink_ = function(node,
|
||||
objectStack) {
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Resource URL object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readResourceUrl_ = function(node, objectStack) {
|
||||
var format = node.getAttribute('format');
|
||||
var template = node.getAttribute('template');
|
||||
var resourceType = node.getAttribute('resourceType');
|
||||
var resource = {};
|
||||
if (goog.isDef(format)) {
|
||||
resource['format'] = format;
|
||||
}
|
||||
if (goog.isDef(template)) {
|
||||
resource['template'] = template;
|
||||
}
|
||||
if (goog.isDef(resourceType)) {
|
||||
resource['resourceType'] = resourceType;
|
||||
}
|
||||
return resource;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} WGS84 BBox object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readWgs84BoundingBox_ = function(node, objectStack) {
|
||||
var coordinates = ol.xml.pushParseAndPop([],
|
||||
ol.format.WMTSCapabilities.WGS84_BBOX_READERS_, node, objectStack);
|
||||
if (coordinates.length != 2) {
|
||||
return undefined;
|
||||
}
|
||||
return ol.extent.boundingExtent(coordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Legend object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readLegendUrl_ = function(node, objectStack) {
|
||||
var legend = {};
|
||||
legend['format'] = node.getAttribute('format');
|
||||
legend['href'] = ol.format.XLink.readHref(node);
|
||||
return legend;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Coordinates object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readCoordinates_ = function(node, objectStack) {
|
||||
var coordinates = ol.format.XSD.readString(node).split(' ');
|
||||
if (!goog.isDef(coordinates) || coordinates.length != 2) {
|
||||
return undefined;
|
||||
}
|
||||
var x = +coordinates[0];
|
||||
var y = +coordinates[1];
|
||||
if (isNaN(x) || isNaN(y)) {
|
||||
return undefined;
|
||||
}
|
||||
return [x, y];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} TileMatrix object.
|
||||
*/
|
||||
ol.format.WMTSCapabilities.readTileMatrix_ = function(node, objectStack) {
|
||||
return ol.xml.pushParseAndPop({},
|
||||
ol.format.WMTSCapabilities.TM_PARSERS_, node, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_ = [
|
||||
null,
|
||||
'http://www.opengis.net/wmts/1.0'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_ = [
|
||||
null,
|
||||
'http://www.opengis.net/ows/1.1'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'Contents': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMTSCapabilities.readContents_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.CONTENTS_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'Layer': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readLayer_),
|
||||
'TileMatrixSet': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readTileMatrixSet_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.LAYER_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'Style': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readStyle_),
|
||||
'Format': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.XSD.readString),
|
||||
'TileMatrixSetLink': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readTileMatrixSetLink_),
|
||||
'ResourceURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readResourceUrl_)
|
||||
}, ol.xml.makeParsersNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
|
||||
'Title': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'Abstract': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'WGS84BoundingBox': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMTSCapabilities.readWgs84BoundingBox_),
|
||||
'Identifier': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
}));
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.STYLE_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'LegendURL': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readLegendUrl_)
|
||||
}, ol.xml.makeParsersNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
|
||||
'Title': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'Identifier': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
}));
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'TileMatrixSet': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.WGS84_BBOX_READERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
|
||||
'LowerCorner': ol.xml.makeArrayPusher(
|
||||
ol.format.WMTSCapabilities.readCoordinates_),
|
||||
'UpperCorner': ol.xml.makeArrayPusher(
|
||||
ol.format.WMTSCapabilities.readCoordinates_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.TMS_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'WellKnownScaleSet': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'TileMatrix': ol.xml.makeObjectPropertyPusher(
|
||||
ol.format.WMTSCapabilities.readTileMatrix_)
|
||||
}, ol.xml.makeParsersNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
|
||||
'SupportedCRS': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString),
|
||||
'Identifier': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
}));
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Parser>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.WMTSCapabilities.TM_PARSERS_ = ol.xml.makeParsersNS(
|
||||
ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
|
||||
'TopLeftCorner': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.WMTSCapabilities.readCoordinates_),
|
||||
'ScaleDenominator': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readDecimal),
|
||||
'TileWidth': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'TileHeight': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'MatrixWidth': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger),
|
||||
'MatrixHeight': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readNonNegativeInteger)
|
||||
}, ol.xml.makeParsersNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
|
||||
'Identifier': ol.xml.makeObjectPropertySetter(
|
||||
ol.format.XSD.readString)
|
||||
}));
|
||||
@@ -0,0 +1,17 @@
|
||||
goog.provide('ol.format.XLink');
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.XLink.NAMESPACE_URI = 'http://www.w3.org/1999/xlink';
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {boolean|undefined} Boolean.
|
||||
*/
|
||||
ol.format.XLink.readHref = function(node) {
|
||||
return node.getAttributeNS(ol.format.XLink.NAMESPACE_URI, 'href');
|
||||
};
|
||||
@@ -0,0 +1,255 @@
|
||||
goog.provide('ol.format.XMLFeature');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.dom.xml');
|
||||
goog.require('ol.format.Feature');
|
||||
goog.require('ol.format.FormatType');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for XML feature formats.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.format.Feature}
|
||||
*/
|
||||
ol.format.XMLFeature = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.format.XMLFeature, ol.format.Feature);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.getType = function() {
|
||||
return ol.format.FormatType.XML;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeature = function(source, opt_options) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readFeatureFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readFeatureFromDocument(doc, opt_options);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeatureFromDocument = function(
|
||||
doc, opt_options) {
|
||||
var features = this.readFeaturesFromDocument(doc, opt_options);
|
||||
if (features.length > 0) {
|
||||
return features[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @return {ol.Feature} Feature.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeatureFromNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeatures = function(source, opt_options) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readFeaturesFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readFeaturesFromDocument(doc, opt_options);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @protected
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeaturesFromDocument = function(
|
||||
doc, opt_options) {
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
var n;
|
||||
for (n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
|
||||
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
goog.array.extend(features, this.readFeaturesFromNode(n, opt_options));
|
||||
}
|
||||
}
|
||||
return features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @protected
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readFeaturesFromNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readGeometry = function(source, opt_options) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readGeometryFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readGeometryFromDocument(doc, opt_options);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @protected
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readGeometryFromDocument = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {olx.format.ReadOptions=} opt_options Options.
|
||||
* @protected
|
||||
* @return {ol.geom.Geometry} Geometry.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readGeometryFromNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readProjection = function(source) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readProjectionFromNode(/** @type {Node} */ (source));
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readProjectionFromDocument(doc);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @protected
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readProjectionFromDocument = function(doc) {
|
||||
return this.defaultDataProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @protected
|
||||
* @return {ol.proj.Projection} Projection.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.readProjectionFromNode = function(node) {
|
||||
return this.defaultDataProjection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) {
|
||||
var node = this.writeFeatureNode(feature, opt_options);
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return goog.dom.xml.serialize(/** @type {Element} */(node));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {olx.format.WriteOptions=} opt_options Options.
|
||||
* @protected
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeFeatureNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) {
|
||||
var node = this.writeFeaturesNode(features, opt_options);
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return goog.dom.xml.serialize(/** @type {Element} */(node));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {olx.format.WriteOptions=} opt_options Options.
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeFeaturesNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) {
|
||||
var node = this.writeGeometryNode(geometry, opt_options);
|
||||
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
|
||||
return goog.dom.xml.serialize(/** @type {Element} */(node));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Options.
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
ol.format.XMLFeature.prototype.writeGeometryNode = goog.abstractMethod;
|
||||
@@ -0,0 +1,48 @@
|
||||
goog.provide('ol.format.XML');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Generic format for reading non-feature XML data
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
ol.format.XML = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document|Node|string} source Source.
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.format.XML.prototype.read = function(source) {
|
||||
if (ol.xml.isDocument(source)) {
|
||||
return this.readFromDocument(/** @type {Document} */ (source));
|
||||
} else if (ol.xml.isNode(source)) {
|
||||
return this.readFromNode(/** @type {Node} */ (source));
|
||||
} else if (goog.isString(source)) {
|
||||
var doc = ol.xml.parse(source);
|
||||
return this.readFromDocument(doc);
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.format.XML.prototype.readFromDocument = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.format.XML.prototype.readFromNode = goog.abstractMethod;
|
||||
@@ -0,0 +1,183 @@
|
||||
goog.provide('ol.format.XSD');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.format.XSD.NAMESPACE_URI = 'http://www.w3.org/2001/XMLSchema';
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {boolean|undefined} Boolean.
|
||||
*/
|
||||
ol.format.XSD.readBoolean = function(node) {
|
||||
var s = ol.xml.getAllTextContent(node, false);
|
||||
return ol.format.XSD.readBooleanString(s);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} string String.
|
||||
* @return {boolean|undefined} Boolean.
|
||||
*/
|
||||
ol.format.XSD.readBooleanString = function(string) {
|
||||
var m = /^\s*(true|1)|(false|0)\s*$/.exec(string);
|
||||
if (m) {
|
||||
return goog.isDef(m[1]) || false;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {number|undefined} DateTime in seconds.
|
||||
*/
|
||||
ol.format.XSD.readDateTime = function(node) {
|
||||
var s = ol.xml.getAllTextContent(node, false);
|
||||
var re =
|
||||
/^\s*(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(Z|(?:([+\-])(\d{2})(?::(\d{2}))?))\s*$/;
|
||||
var m = re.exec(s);
|
||||
if (m) {
|
||||
var year = parseInt(m[1], 10);
|
||||
var month = parseInt(m[2], 10) - 1;
|
||||
var day = parseInt(m[3], 10);
|
||||
var hour = parseInt(m[4], 10);
|
||||
var minute = parseInt(m[5], 10);
|
||||
var second = parseInt(m[6], 10);
|
||||
var dateTime = Date.UTC(year, month, day, hour, minute, second) / 1000;
|
||||
if (m[7] != 'Z') {
|
||||
var sign = m[8] == '-' ? -1 : 1;
|
||||
dateTime += sign * 60 * parseInt(m[9], 10);
|
||||
if (goog.isDef(m[10])) {
|
||||
dateTime += sign * 60 * 60 * parseInt(m[10], 10);
|
||||
}
|
||||
}
|
||||
return dateTime;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {number|undefined} Decimal.
|
||||
*/
|
||||
ol.format.XSD.readDecimal = function(node) {
|
||||
var s = ol.xml.getAllTextContent(node, false);
|
||||
return ol.format.XSD.readDecimalString(s);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} string String.
|
||||
* @return {number|undefined} Decimal.
|
||||
*/
|
||||
ol.format.XSD.readDecimalString = function(string) {
|
||||
// FIXME check spec
|
||||
var m = /^\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)\s*$/i.exec(string);
|
||||
if (m) {
|
||||
return parseFloat(m[1]);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {number|undefined} Non negative integer.
|
||||
*/
|
||||
ol.format.XSD.readNonNegativeInteger = function(node) {
|
||||
var s = ol.xml.getAllTextContent(node, false);
|
||||
return ol.format.XSD.readNonNegativeIntegerString(s);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} string String.
|
||||
* @return {number|undefined} Non negative integer.
|
||||
*/
|
||||
ol.format.XSD.readNonNegativeIntegerString = function(string) {
|
||||
var m = /^\s*(\d+)\s*$/.exec(string);
|
||||
if (m) {
|
||||
return parseInt(m[1], 10);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @return {string|undefined} String.
|
||||
*/
|
||||
ol.format.XSD.readString = function(node) {
|
||||
var s = ol.xml.getAllTextContent(node, false);
|
||||
return goog.string.trim(s);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the boolean to.
|
||||
* @param {boolean} bool Boolean.
|
||||
*/
|
||||
ol.format.XSD.writeBooleanTextNode = function(node, bool) {
|
||||
ol.format.XSD.writeStringTextNode(node, (bool) ? '1' : '0');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the dateTime to.
|
||||
* @param {number} dateTime DateTime in seconds.
|
||||
*/
|
||||
ol.format.XSD.writeDateTimeTextNode = function(node, dateTime) {
|
||||
var date = new Date(dateTime * 1000);
|
||||
var string = date.getUTCFullYear() + '-' +
|
||||
goog.string.padNumber(date.getUTCMonth() + 1, 2) + '-' +
|
||||
goog.string.padNumber(date.getUTCDate(), 2) + 'T' +
|
||||
goog.string.padNumber(date.getUTCHours(), 2) + ':' +
|
||||
goog.string.padNumber(date.getUTCMinutes(), 2) + ':' +
|
||||
goog.string.padNumber(date.getUTCSeconds(), 2) + 'Z';
|
||||
node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the decimal to.
|
||||
* @param {number} decimal Decimal.
|
||||
*/
|
||||
ol.format.XSD.writeDecimalTextNode = function(node, decimal) {
|
||||
var string = decimal.toPrecision();
|
||||
node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the decimal to.
|
||||
* @param {number} nonNegativeInteger Non negative integer.
|
||||
*/
|
||||
ol.format.XSD.writeNonNegativeIntegerTextNode =
|
||||
function(node, nonNegativeInteger) {
|
||||
goog.asserts.assert(nonNegativeInteger >= 0);
|
||||
goog.asserts.assert(nonNegativeInteger == (nonNegativeInteger | 0));
|
||||
var string = nonNegativeInteger.toString();
|
||||
node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the string to.
|
||||
* @param {string} string String.
|
||||
*/
|
||||
ol.format.XSD.writeStringTextNode = function(node, string) {
|
||||
node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
// FIXME factor out common code between usedTiles and wantedTiles
|
||||
|
||||
goog.provide('ol.PostRenderFunction');
|
||||
goog.provide('ol.PreRenderFunction');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(ol.Map, ?olx.FrameState): boolean}
|
||||
*/
|
||||
ol.PostRenderFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Function to perform manipulations before rendering. This function is called
|
||||
* with the {@link ol.Map} as first and an optional {@link olx.FrameState} as
|
||||
* second argument. Return `true` to keep this function for the next frame,
|
||||
* `false` to remove it.
|
||||
* @typedef {function(ol.Map, ?olx.FrameState): boolean}
|
||||
* @api
|
||||
*/
|
||||
ol.PreRenderFunction;
|
||||
@@ -0,0 +1,406 @@
|
||||
// FIXME handle geolocation not supported
|
||||
|
||||
goog.provide('ol.Geolocation');
|
||||
goog.provide('ol.GeolocationProperty');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.has');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.sphere.WGS84');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.GeolocationProperty = {
|
||||
ACCURACY: 'accuracy',
|
||||
ACCURACY_GEOMETRY: 'accuracyGeometry',
|
||||
ALTITUDE: 'altitude',
|
||||
ALTITUDE_ACCURACY: 'altitudeAccuracy',
|
||||
HEADING: 'heading',
|
||||
POSITION: 'position',
|
||||
PROJECTION: 'projection',
|
||||
SPEED: 'speed',
|
||||
TRACKING: 'tracking',
|
||||
TRACKING_OPTIONS: 'trackingOptions'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Helper class for providing HTML5 Geolocation capabilities.
|
||||
* The [Geolocation API](http://www.w3.org/TR/geolocation-API/)
|
||||
* is used to locate a user's position.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var geolocation = new ol.Geolocation({
|
||||
* // take the projection to use from the map's view
|
||||
* projection: view.getProjection()
|
||||
* });
|
||||
* // listen to changes in position
|
||||
* geolocation.on('change', function(evt) {
|
||||
* window.console.log(geolocation.getPosition());
|
||||
* });
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @fires change Triggered when the position changes.
|
||||
* @param {olx.GeolocationOptions=} opt_options Options.
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation = function(opt_options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* The unprojected (EPSG:4326) device position.
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.position_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TransformFunction}
|
||||
*/
|
||||
this.transform_ = ol.proj.identityTransform;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.watchId_ = undefined;
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangeEventType(ol.GeolocationProperty.PROJECTION),
|
||||
this.handleProjectionChanged_, false, this);
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangeEventType(ol.GeolocationProperty.TRACKING),
|
||||
this.handleTrackingChanged_, false, this);
|
||||
|
||||
if (goog.isDef(options.projection)) {
|
||||
this.setProjection(ol.proj.get(options.projection));
|
||||
}
|
||||
if (goog.isDef(options.trackingOptions)) {
|
||||
this.setTrackingOptions(options.trackingOptions);
|
||||
}
|
||||
|
||||
this.setTracking(goog.isDef(options.tracking) ? options.tracking : false);
|
||||
|
||||
};
|
||||
goog.inherits(ol.Geolocation, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.Geolocation.prototype.disposeInternal = function() {
|
||||
this.setTracking(false);
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Geolocation.prototype.handleProjectionChanged_ = function() {
|
||||
var projection = this.getProjection();
|
||||
if (goog.isDefAndNotNull(projection)) {
|
||||
this.transform_ = ol.proj.getTransformFromProjections(
|
||||
ol.proj.get('EPSG:4326'), projection);
|
||||
if (!goog.isNull(this.position_)) {
|
||||
this.set(
|
||||
ol.GeolocationProperty.POSITION, this.transform_(this.position_));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Geolocation.prototype.handleTrackingChanged_ = function() {
|
||||
if (ol.has.GEOLOCATION) {
|
||||
var tracking = this.getTracking();
|
||||
if (tracking && !goog.isDef(this.watchId_)) {
|
||||
this.watchId_ = goog.global.navigator.geolocation.watchPosition(
|
||||
goog.bind(this.positionChange_, this),
|
||||
goog.bind(this.positionError_, this),
|
||||
this.getTrackingOptions());
|
||||
} else if (!tracking && goog.isDef(this.watchId_)) {
|
||||
goog.global.navigator.geolocation.clearWatch(this.watchId_);
|
||||
this.watchId_ = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {GeolocationPosition} position position event.
|
||||
*/
|
||||
ol.Geolocation.prototype.positionChange_ = function(position) {
|
||||
var coords = position.coords;
|
||||
this.set(ol.GeolocationProperty.ACCURACY, coords.accuracy);
|
||||
this.set(ol.GeolocationProperty.ALTITUDE,
|
||||
goog.isNull(coords.altitude) ? undefined : coords.altitude);
|
||||
this.set(ol.GeolocationProperty.ALTITUDE_ACCURACY,
|
||||
goog.isNull(coords.altitudeAccuracy) ?
|
||||
undefined : coords.altitudeAccuracy);
|
||||
this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ?
|
||||
undefined : goog.math.toRadians(coords.heading));
|
||||
if (goog.isNull(this.position_)) {
|
||||
this.position_ = [coords.longitude, coords.latitude];
|
||||
} else {
|
||||
this.position_[0] = coords.longitude;
|
||||
this.position_[1] = coords.latitude;
|
||||
}
|
||||
var projectedPosition = this.transform_(this.position_);
|
||||
this.set(ol.GeolocationProperty.POSITION, projectedPosition);
|
||||
this.set(ol.GeolocationProperty.SPEED,
|
||||
goog.isNull(coords.speed) ? undefined : coords.speed);
|
||||
var geometry = ol.geom.Polygon.circular(
|
||||
ol.sphere.WGS84, this.position_, coords.accuracy);
|
||||
geometry.applyTransform(this.transform_);
|
||||
this.set(ol.GeolocationProperty.ACCURACY_GEOMETRY, geometry);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {GeolocationPositionError} error error object.
|
||||
*/
|
||||
ol.Geolocation.prototype.positionError_ = function(error) {
|
||||
error.type = goog.events.EventType.ERROR;
|
||||
this.setTracking(false);
|
||||
this.dispatchEvent(error);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the accuracy of the position in meters.
|
||||
* @return {number|undefined} The accuracy of the position measurement in
|
||||
* meters.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getAccuracy = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.ACCURACY));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getAccuracy',
|
||||
ol.Geolocation.prototype.getAccuracy);
|
||||
|
||||
|
||||
/**
|
||||
* Get a geometry of the position accuracy.
|
||||
* @return {?ol.geom.Geometry} A geometry of the position accuracy.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getAccuracyGeometry = function() {
|
||||
return /** @type {?ol.geom.Geometry} */ (
|
||||
this.get(ol.GeolocationProperty.ACCURACY_GEOMETRY) || null);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getAccuracyGeometry',
|
||||
ol.Geolocation.prototype.getAccuracyGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* Get the altitude associated with the position.
|
||||
* @return {number|undefined} The altitude of the position in meters above mean
|
||||
* sea level.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getAltitude = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.ALTITUDE));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getAltitude',
|
||||
ol.Geolocation.prototype.getAltitude);
|
||||
|
||||
|
||||
/**
|
||||
* Get the altitude accuracy of the position.
|
||||
* @return {number|undefined} The accuracy of the altitude measurement in
|
||||
* meters.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getAltitudeAccuracy = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.ALTITUDE_ACCURACY));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getAltitudeAccuracy',
|
||||
ol.Geolocation.prototype.getAltitudeAccuracy);
|
||||
|
||||
|
||||
/**
|
||||
* Get the heading as radians clockwise from North.
|
||||
* @return {number|undefined} The heading of the device in radians from north.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getHeading = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.HEADING));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getHeading',
|
||||
ol.Geolocation.prototype.getHeading);
|
||||
|
||||
|
||||
/**
|
||||
* Get the position of the device.
|
||||
* @return {ol.Coordinate|undefined} The current position of the device reported
|
||||
* in the current projection.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getPosition = function() {
|
||||
return /** @type {ol.Coordinate|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.POSITION));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getPosition',
|
||||
ol.Geolocation.prototype.getPosition);
|
||||
|
||||
|
||||
/**
|
||||
* Get the projection associated with the position.
|
||||
* @return {ol.proj.Projection|undefined} The projection the position is
|
||||
* reported in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getProjection = function() {
|
||||
return /** @type {ol.proj.Projection|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.PROJECTION));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getProjection',
|
||||
ol.Geolocation.prototype.getProjection);
|
||||
|
||||
|
||||
/**
|
||||
* Get the speed in meters per second.
|
||||
* @return {number|undefined} The instantaneous speed of the device in meters
|
||||
* per second.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getSpeed = function() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.SPEED));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getSpeed',
|
||||
ol.Geolocation.prototype.getSpeed);
|
||||
|
||||
|
||||
/**
|
||||
* Are we tracking the user's position?
|
||||
* @return {boolean} Whether to track the device's position.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getTracking = function() {
|
||||
return /** @type {boolean} */ (
|
||||
this.get(ol.GeolocationProperty.TRACKING));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getTracking',
|
||||
ol.Geolocation.prototype.getTracking);
|
||||
|
||||
|
||||
/**
|
||||
* Get the tracking options.
|
||||
* @see http://www.w3.org/TR/geolocation-API/#position-options
|
||||
* @return {GeolocationPositionOptions|undefined} PositionOptions as defined by
|
||||
* the HTML5 Geolocation spec at
|
||||
* {@link http://www.w3.org/TR/geolocation-API/#position_options_interface}
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.getTrackingOptions = function() {
|
||||
return /** @type {GeolocationPositionOptions|undefined} */ (
|
||||
this.get(ol.GeolocationProperty.TRACKING_OPTIONS));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'getTrackingOptions',
|
||||
ol.Geolocation.prototype.getTrackingOptions);
|
||||
|
||||
|
||||
/**
|
||||
* Set the projection to use for transforming the coordinates.
|
||||
* @param {ol.proj.Projection} projection The projection the position is
|
||||
* reported in.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.setProjection = function(projection) {
|
||||
this.set(ol.GeolocationProperty.PROJECTION, projection);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'setProjection',
|
||||
ol.Geolocation.prototype.setProjection);
|
||||
|
||||
|
||||
/**
|
||||
* Enable/disable tracking.
|
||||
* @param {boolean} tracking Whether to track the device's position.
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.setTracking = function(tracking) {
|
||||
this.set(ol.GeolocationProperty.TRACKING, tracking);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'setTracking',
|
||||
ol.Geolocation.prototype.setTracking);
|
||||
|
||||
|
||||
/**
|
||||
* Set the tracking options.
|
||||
* @see http://www.w3.org/TR/geolocation-API/#position-options
|
||||
* @param {GeolocationPositionOptions} options PositionOptions as defined by the
|
||||
* HTML5 Geolocation spec at
|
||||
* {@link http://www.w3.org/TR/geolocation-API/#position_options_interface}
|
||||
* @observable
|
||||
* @api stable
|
||||
*/
|
||||
ol.Geolocation.prototype.setTrackingOptions = function(options) {
|
||||
this.set(ol.GeolocationProperty.TRACKING_OPTIONS, options);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Geolocation.prototype,
|
||||
'setTrackingOptions',
|
||||
ol.Geolocation.prototype.setTrackingOptions);
|
||||
@@ -0,0 +1,230 @@
|
||||
goog.provide('ol.geom.Circle');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Circle geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number=} opt_radius Radius.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle = function(center, opt_radius, opt_layout) {
|
||||
goog.base(this);
|
||||
var radius = goog.isDef(opt_radius) ? opt_radius : 0;
|
||||
this.setCenterAndRadius(center, radius,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
};
|
||||
goog.inherits(ol.geom.Circle, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.Circle} Clone.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.clone = function() {
|
||||
var circle = new ol.geom.Circle(null);
|
||||
circle.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||
return circle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Circle.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var dx = x - flatCoordinates[0];
|
||||
var dy = y - flatCoordinates[1];
|
||||
var squaredDistance = dx * dx + dy * dy;
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
var i;
|
||||
if (squaredDistance === 0) {
|
||||
for (i = 0; i < this.stride; ++i) {
|
||||
closestPoint[i] = flatCoordinates[i];
|
||||
}
|
||||
} else {
|
||||
var delta = this.getRadius() / Math.sqrt(squaredDistance);
|
||||
closestPoint[0] = flatCoordinates[0] + delta * dx;
|
||||
closestPoint[1] = flatCoordinates[1] + delta * dy;
|
||||
for (i = 2; i < this.stride; ++i) {
|
||||
closestPoint[i] = flatCoordinates[i];
|
||||
}
|
||||
}
|
||||
closestPoint.length = this.stride;
|
||||
return squaredDistance;
|
||||
} else {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Circle.prototype.containsXY = function(x, y) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var dx = x - flatCoordinates[0];
|
||||
var dy = y - flatCoordinates[1];
|
||||
return dx * dx + dy * dy <= this.getRadiusSquared_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Center.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.getCenter = function() {
|
||||
return this.flatCoordinates.slice(0, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Circle.prototype.computeExtent = function(extent) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var radius = flatCoordinates[this.stride] - flatCoordinates[0];
|
||||
return ol.extent.createOrUpdate(
|
||||
flatCoordinates[0] - radius, flatCoordinates[1] - radius,
|
||||
flatCoordinates[0] + radius, flatCoordinates[1] + radius,
|
||||
extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Radius.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.getRadius = function() {
|
||||
return Math.sqrt(this.getRadiusSquared_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {number} Radius squared.
|
||||
*/
|
||||
ol.geom.Circle.prototype.getRadiusSquared_ = function() {
|
||||
var dx = this.flatCoordinates[this.stride] - this.flatCoordinates[0];
|
||||
var dy = this.flatCoordinates[this.stride + 1] - this.flatCoordinates[1];
|
||||
return dx * dx + dy * dy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.CIRCLE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.setCenter = function(center) {
|
||||
var stride = this.stride;
|
||||
goog.asserts.assert(center.length == stride);
|
||||
var radius = this.flatCoordinates[stride] - this.flatCoordinates[0];
|
||||
var flatCoordinates = center.slice();
|
||||
flatCoordinates[stride] = flatCoordinates[0] + radius;
|
||||
var i;
|
||||
for (i = 1; i < stride; ++i) {
|
||||
flatCoordinates[stride + i] = center[i];
|
||||
}
|
||||
this.setFlatCoordinates(this.layout, flatCoordinates);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} radius Radius.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.setCenterAndRadius =
|
||||
function(center, radius, opt_layout) {
|
||||
if (goog.isNull(center)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||
} else {
|
||||
this.setLayout(opt_layout, center, 0);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
/** @type {Array.<number>} */
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var offset = ol.geom.flat.deflate.coordinate(
|
||||
flatCoordinates, 0, center, this.stride);
|
||||
flatCoordinates[offset++] = flatCoordinates[0] + radius;
|
||||
var i, ii;
|
||||
for (i = 1, ii = this.stride; i < ii; ++i) {
|
||||
flatCoordinates[offset++] = flatCoordinates[i];
|
||||
}
|
||||
flatCoordinates.length = offset;
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
ol.geom.Circle.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates) {
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The radius is in the units of the projection.
|
||||
* @param {number} radius Radius.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Circle.prototype.setRadius = function(radius) {
|
||||
goog.asserts.assert(!goog.isNull(this.flatCoordinates));
|
||||
this.flatCoordinates[this.stride] = this.flatCoordinates[0] + radius;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Transform each coordinate of the circle from one coordinate reference system
|
||||
* to another. The geometry is modified in place.
|
||||
* If you do not want the geometry modified in place, first clone() it and
|
||||
* then use this function on the clone.
|
||||
*
|
||||
* Internally a circle is currently represented by two points: the center of
|
||||
* the circle `[cx, cy]`, and the point to the right of the circle
|
||||
* `[cx + r, cy]`. This `transform` function just transforms these two points.
|
||||
* So the resulting geometry is also a circle, and that circle does not
|
||||
* correspond to the shape that would be obtained by transforming every point
|
||||
* of the original circle.
|
||||
*
|
||||
* @param {ol.proj.ProjectionLike} source The current projection. Can be a
|
||||
* string identifier or a {@link ol.proj.Projection} object.
|
||||
* @param {ol.proj.ProjectionLike} destination The desired projection. Can be a
|
||||
* string identifier or a {@link ol.proj.Projection} object.
|
||||
* @return {ol.geom.Circle} This geometry. Note that original geometry is
|
||||
* modified in place.
|
||||
* @function
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Circle.prototype.transform;
|
||||
@@ -0,0 +1,64 @@
|
||||
goog.provide('ol.geom.flat.area');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} Area.
|
||||
*/
|
||||
ol.geom.flat.area.linearRing = function(flatCoordinates, offset, end, stride) {
|
||||
var twiceArea = 0;
|
||||
var x1 = flatCoordinates[end - stride];
|
||||
var y1 = flatCoordinates[end - stride + 1];
|
||||
for (; offset < end; offset += stride) {
|
||||
var x2 = flatCoordinates[offset];
|
||||
var y2 = flatCoordinates[offset + 1];
|
||||
twiceArea += y1 * x2 - x1 * y2;
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
return twiceArea / 2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} Area.
|
||||
*/
|
||||
ol.geom.flat.area.linearRings =
|
||||
function(flatCoordinates, offset, ends, stride) {
|
||||
var area = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
area += ol.geom.flat.area.linearRing(flatCoordinates, offset, end, stride);
|
||||
offset = end;
|
||||
}
|
||||
return area;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} Area.
|
||||
*/
|
||||
ol.geom.flat.area.linearRingss =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
var area = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
area +=
|
||||
ol.geom.flat.area.linearRings(flatCoordinates, offset, ends, stride);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return area;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
goog.provide('ol.geom.flat.center');
|
||||
|
||||
goog.require('ol.extent');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @return {Array.<number>} Flat centers.
|
||||
*/
|
||||
ol.geom.flat.center.linearRingss =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
var flatCenters = [];
|
||||
var i, ii;
|
||||
var extent = ol.extent.createEmpty();
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
extent = ol.extent.createOrUpdateFromFlatCoordinates(
|
||||
flatCoordinates, offset, ends[0], stride);
|
||||
flatCenters.push((extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return flatCenters;
|
||||
};
|
||||
@@ -0,0 +1,260 @@
|
||||
goog.provide('ol.geom.flat.closest');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.math');
|
||||
|
||||
|
||||
/**
|
||||
* Returns the point on the 2D line segment flatCoordinates[offset1] to
|
||||
* flatCoordinates[offset2] that is closest to the point (x, y). Extra
|
||||
* dimensions are linearly interpolated.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset1 Offset 1.
|
||||
* @param {number} offset2 Offset 2.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @param {Array.<number>} closestPoint Closest point.
|
||||
*/
|
||||
ol.geom.flat.closest.point =
|
||||
function(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) {
|
||||
var x1 = flatCoordinates[offset1];
|
||||
var y1 = flatCoordinates[offset1 + 1];
|
||||
var dx = flatCoordinates[offset2] - x1;
|
||||
var dy = flatCoordinates[offset2 + 1] - y1;
|
||||
var i, offset;
|
||||
if (dx === 0 && dy === 0) {
|
||||
offset = offset1;
|
||||
} else {
|
||||
var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
|
||||
if (t > 1) {
|
||||
offset = offset2;
|
||||
} else if (t > 0) {
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = goog.math.lerp(flatCoordinates[offset1 + i],
|
||||
flatCoordinates[offset2 + i], t);
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
return;
|
||||
} else {
|
||||
offset = offset1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = flatCoordinates[offset + i];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the squared of the largest distance between any pair of consecutive
|
||||
* coordinates.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxSquaredDelta Max squared delta.
|
||||
* @return {number} Max squared delta.
|
||||
*/
|
||||
ol.geom.flat.closest.getMaxSquaredDelta =
|
||||
function(flatCoordinates, offset, end, stride, maxSquaredDelta) {
|
||||
var x1 = flatCoordinates[offset];
|
||||
var y1 = flatCoordinates[offset + 1];
|
||||
for (offset += stride; offset < end; offset += stride) {
|
||||
var x2 = flatCoordinates[offset];
|
||||
var y2 = flatCoordinates[offset + 1];
|
||||
var squaredDelta = ol.math.squaredDistance(x1, y1, x2, y2);
|
||||
if (squaredDelta > maxSquaredDelta) {
|
||||
maxSquaredDelta = squaredDelta;
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
return maxSquaredDelta;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxSquaredDelta Max squared delta.
|
||||
* @return {number} Max squared delta.
|
||||
*/
|
||||
ol.geom.flat.closest.getsMaxSquaredDelta =
|
||||
function(flatCoordinates, offset, ends, stride, maxSquaredDelta) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
maxSquaredDelta = ol.geom.flat.closest.getMaxSquaredDelta(
|
||||
flatCoordinates, offset, end, stride, maxSquaredDelta);
|
||||
offset = end;
|
||||
}
|
||||
return maxSquaredDelta;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxSquaredDelta Max squared delta.
|
||||
* @return {number} Max squared delta.
|
||||
*/
|
||||
ol.geom.flat.closest.getssMaxSquaredDelta =
|
||||
function(flatCoordinates, offset, endss, stride, maxSquaredDelta) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
maxSquaredDelta = ol.geom.flat.closest.getsMaxSquaredDelta(
|
||||
flatCoordinates, offset, ends, stride, maxSquaredDelta);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return maxSquaredDelta;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxDelta Max delta.
|
||||
* @param {boolean} isRing Is ring.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @param {Array.<number>} closestPoint Closest point.
|
||||
* @param {number} minSquaredDistance Minimum squared distance.
|
||||
* @param {Array.<number>=} opt_tmpPoint Temporary point object.
|
||||
* @return {number} Minimum squared distance.
|
||||
*/
|
||||
ol.geom.flat.closest.getClosestPoint = function(flatCoordinates, offset, end,
|
||||
stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
|
||||
opt_tmpPoint) {
|
||||
if (offset == end) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
var i, squaredDistance;
|
||||
if (maxDelta === 0) {
|
||||
// All points are identical, so just test the first point.
|
||||
squaredDistance = ol.math.squaredDistance(
|
||||
x, y, flatCoordinates[offset], flatCoordinates[offset + 1]);
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = flatCoordinates[offset + i];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
return squaredDistance;
|
||||
} else {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
}
|
||||
goog.asserts.assert(maxDelta > 0);
|
||||
var tmpPoint = goog.isDef(opt_tmpPoint) ? opt_tmpPoint : [NaN, NaN];
|
||||
var index = offset + stride;
|
||||
while (index < end) {
|
||||
ol.geom.flat.closest.point(
|
||||
flatCoordinates, index - stride, index, stride, x, y, tmpPoint);
|
||||
squaredDistance = ol.math.squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
minSquaredDistance = squaredDistance;
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = tmpPoint[i];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
index += stride;
|
||||
} else {
|
||||
// Skip ahead multiple points, because we know that all the skipped
|
||||
// points cannot be any closer than the closest point we have found so
|
||||
// far. We know this because we know how close the current point is, how
|
||||
// close the closest point we have found so far is, and the maximum
|
||||
// distance between consecutive points. For example, if we're currently
|
||||
// at distance 10, the best we've found so far is 3, and that the maximum
|
||||
// distance between consecutive points is 2, then we'll need to skip at
|
||||
// least (10 - 3) / 2 == 3 (rounded down) points to have any chance of
|
||||
// finding a closer point. We use Math.max(..., 1) to ensure that we
|
||||
// always advance at least one point, to avoid an infinite loop.
|
||||
index += stride * Math.max(
|
||||
((Math.sqrt(squaredDistance) -
|
||||
Math.sqrt(minSquaredDistance)) / maxDelta) | 0, 1);
|
||||
}
|
||||
}
|
||||
if (isRing) {
|
||||
// Check the closing segment.
|
||||
ol.geom.flat.closest.point(
|
||||
flatCoordinates, end - stride, offset, stride, x, y, tmpPoint);
|
||||
squaredDistance = ol.math.squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
minSquaredDistance = squaredDistance;
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = tmpPoint[i];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
}
|
||||
}
|
||||
return minSquaredDistance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxDelta Max delta.
|
||||
* @param {boolean} isRing Is ring.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @param {Array.<number>} closestPoint Closest point.
|
||||
* @param {number} minSquaredDistance Minimum squared distance.
|
||||
* @param {Array.<number>=} opt_tmpPoint Temporary point object.
|
||||
* @return {number} Minimum squared distance.
|
||||
*/
|
||||
ol.geom.flat.closest.getsClosestPoint = function(flatCoordinates, offset, ends,
|
||||
stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
|
||||
opt_tmpPoint) {
|
||||
var tmpPoint = goog.isDef(opt_tmpPoint) ? opt_tmpPoint : [NaN, NaN];
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
minSquaredDistance = ol.geom.flat.closest.getClosestPoint(
|
||||
flatCoordinates, offset, end, stride,
|
||||
maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);
|
||||
offset = end;
|
||||
}
|
||||
return minSquaredDistance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} maxDelta Max delta.
|
||||
* @param {boolean} isRing Is ring.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @param {Array.<number>} closestPoint Closest point.
|
||||
* @param {number} minSquaredDistance Minimum squared distance.
|
||||
* @param {Array.<number>=} opt_tmpPoint Temporary point object.
|
||||
* @return {number} Minimum squared distance.
|
||||
*/
|
||||
ol.geom.flat.closest.getssClosestPoint = function(flatCoordinates, offset,
|
||||
endss, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
|
||||
opt_tmpPoint) {
|
||||
var tmpPoint = goog.isDef(opt_tmpPoint) ? opt_tmpPoint : [NaN, NaN];
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
minSquaredDistance = ol.geom.flat.closest.getsClosestPoint(
|
||||
flatCoordinates, offset, ends, stride,
|
||||
maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return minSquaredDistance;
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
goog.provide('ol.geom.flat.contains');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} Contains extent.
|
||||
*/
|
||||
ol.geom.flat.contains.linearRingContainsExtent =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
var outside = ol.extent.forEachCorner(extent,
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
*/
|
||||
function(coordinate) {
|
||||
return !ol.geom.flat.contains.linearRingContainsXY(flatCoordinates,
|
||||
offset, end, stride, coordinate[0], coordinate[1]);
|
||||
});
|
||||
return !outside;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
ol.geom.flat.contains.linearRingContainsXY =
|
||||
function(flatCoordinates, offset, end, stride, x, y) {
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
var contains = false;
|
||||
var x1 = flatCoordinates[end - stride];
|
||||
var y1 = flatCoordinates[end - stride + 1];
|
||||
for (; offset < end; offset += stride) {
|
||||
var x2 = flatCoordinates[offset];
|
||||
var y2 = flatCoordinates[offset + 1];
|
||||
var intersect = ((y1 > y) != (y2 > y)) &&
|
||||
(x < (x2 - x1) * (y - y1) / (y2 - y1) + x1);
|
||||
if (intersect) {
|
||||
contains = !contains;
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
return contains;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
ol.geom.flat.contains.linearRingsContainsXY =
|
||||
function(flatCoordinates, offset, ends, stride, x, y) {
|
||||
goog.asserts.assert(ends.length > 0);
|
||||
if (ends.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (!ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, ends[0], stride, x, y)) {
|
||||
return false;
|
||||
}
|
||||
var i, ii;
|
||||
for (i = 1, ii = ends.length; i < ii; ++i) {
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, ends[i - 1], ends[i], stride, x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
ol.geom.flat.contains.linearRingssContainsXY =
|
||||
function(flatCoordinates, offset, endss, stride, x, y) {
|
||||
goog.asserts.assert(endss.length > 0);
|
||||
if (endss.length === 0) {
|
||||
return false;
|
||||
}
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
if (ol.geom.flat.contains.linearRingsContainsXY(
|
||||
flatCoordinates, offset, ends, stride, x, y)) {
|
||||
return true;
|
||||
}
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
goog.provide('ol.geom.flat.deflate');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} offset Offset.
|
||||
*/
|
||||
ol.geom.flat.deflate.coordinate =
|
||||
function(flatCoordinates, offset, coordinate, stride) {
|
||||
goog.asserts.assert(coordinate.length == stride);
|
||||
var i, ii;
|
||||
for (i = 0, ii = coordinate.length; i < ii; ++i) {
|
||||
flatCoordinates[offset++] = coordinate[i];
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} offset Offset.
|
||||
*/
|
||||
ol.geom.flat.deflate.coordinates =
|
||||
function(flatCoordinates, offset, coordinates, stride) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
var coordinate = coordinates[i];
|
||||
goog.asserts.assert(coordinate.length == stride);
|
||||
var j;
|
||||
for (j = 0; j < stride; ++j) {
|
||||
flatCoordinates[offset++] = coordinate[j];
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinatess Coordinatess.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<number>=} opt_ends Ends.
|
||||
* @return {Array.<number>} Ends.
|
||||
*/
|
||||
ol.geom.flat.deflate.coordinatess =
|
||||
function(flatCoordinates, offset, coordinatess, stride, opt_ends) {
|
||||
var ends = goog.isDef(opt_ends) ? opt_ends : [];
|
||||
var i = 0;
|
||||
var j, jj;
|
||||
for (j = 0, jj = coordinatess.length; j < jj; ++j) {
|
||||
var end = ol.geom.flat.deflate.coordinates(
|
||||
flatCoordinates, offset, coordinatess[j], stride);
|
||||
ends[i++] = end;
|
||||
offset = end;
|
||||
}
|
||||
ends.length = i;
|
||||
return ends;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinatesss Coordinatesss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<Array.<number>>=} opt_endss Endss.
|
||||
* @return {Array.<Array.<number>>} Endss.
|
||||
*/
|
||||
ol.geom.flat.deflate.coordinatesss =
|
||||
function(flatCoordinates, offset, coordinatesss, stride, opt_endss) {
|
||||
var endss = goog.isDef(opt_endss) ? opt_endss : [];
|
||||
var i = 0;
|
||||
var j, jj;
|
||||
for (j = 0, jj = coordinatesss.length; j < jj; ++j) {
|
||||
var ends = ol.geom.flat.deflate.coordinatess(
|
||||
flatCoordinates, offset, coordinatesss[j], stride, endss[i]);
|
||||
endss[i++] = ends;
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
endss.length = i;
|
||||
return endss;
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
goog.provide('ol.geom.flat.flip');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @param {number=} opt_destOffset Destination offset.
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.flat.flip.flipXY =
|
||||
function(flatCoordinates, offset, end, stride, opt_dest, opt_destOffset) {
|
||||
var dest, destOffset;
|
||||
if (goog.isDef(opt_dest)) {
|
||||
dest = opt_dest;
|
||||
destOffset = goog.isDef(opt_destOffset) ? opt_destOffset : 0;
|
||||
} else {
|
||||
goog.asserts.assert(!goog.isDef(opt_destOffset));
|
||||
dest = [];
|
||||
destOffset = 0;
|
||||
}
|
||||
var j, k;
|
||||
for (j = offset; j < end; ) {
|
||||
var x = flatCoordinates[j++];
|
||||
dest[destOffset++] = flatCoordinates[j++];
|
||||
dest[destOffset++] = x;
|
||||
for (k = 2; k < stride; ++k) {
|
||||
dest[destOffset++] = flatCoordinates[j++];
|
||||
}
|
||||
}
|
||||
dest.length = destOffset;
|
||||
return dest;
|
||||
};
|
||||
@@ -0,0 +1,180 @@
|
||||
goog.provide('ol.geom.flat.geodesic');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.TransformFunction');
|
||||
goog.require('ol.math');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {function(number): ol.Coordinate} interpolate Interpolate function.
|
||||
* @param {ol.TransformFunction} transform Transform from longitude/latitude to
|
||||
* projected coordinates.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.flat.geodesic.line_ =
|
||||
function(interpolate, transform, squaredTolerance) {
|
||||
// FIXME reduce garbage generation
|
||||
// FIXME optimize stack operations
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var flatCoordinates = [];
|
||||
|
||||
var geoA = interpolate(0);
|
||||
var geoB = interpolate(1);
|
||||
|
||||
var a = transform(geoA);
|
||||
var b = transform(geoB);
|
||||
|
||||
/** @type {Array.<ol.Coordinate>} */
|
||||
var geoStack = [geoB, geoA];
|
||||
/** @type {Array.<ol.Coordinate>} */
|
||||
var stack = [b, a];
|
||||
/** @type {Array.<number>} */
|
||||
var fractionStack = [1, 0];
|
||||
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var fractions = {};
|
||||
|
||||
var maxIterations = 1e5;
|
||||
var geoM, m, fracA, fracB, fracM, key;
|
||||
|
||||
while (--maxIterations > 0 && fractionStack.length > 0) {
|
||||
// Pop the a coordinate off the stack
|
||||
fracA = fractionStack.pop();
|
||||
geoA = geoStack.pop();
|
||||
a = stack.pop();
|
||||
// Add the a coordinate if it has not been added yet
|
||||
key = fracA.toString();
|
||||
if (!goog.object.containsKey(fractions, key)) {
|
||||
flatCoordinates.push(a[0], a[1]);
|
||||
fractions[key] = true;
|
||||
}
|
||||
// Pop the b coordinate off the stack
|
||||
fracB = fractionStack.pop();
|
||||
geoB = geoStack.pop();
|
||||
b = stack.pop();
|
||||
// Find the m point between the a and b coordinates
|
||||
fracM = (fracA + fracB) / 2;
|
||||
geoM = interpolate(fracM);
|
||||
m = transform(geoM);
|
||||
if (ol.math.squaredSegmentDistance(m[0], m[1], a[0], a[1],
|
||||
b[0], b[1]) < squaredTolerance) {
|
||||
// If the m point is sufficiently close to the straight line, then we
|
||||
// discard it. Just use the b coordinate and move on to the next line
|
||||
// segment.
|
||||
flatCoordinates.push(b[0], b[1]);
|
||||
key = fracB.toString();
|
||||
goog.asserts.assert(!goog.object.containsKey(fractions, key));
|
||||
fractions[key] = true;
|
||||
} else {
|
||||
// Otherwise, we need to subdivide the current line segment. Split it
|
||||
// into two and push the two line segments onto the stack.
|
||||
fractionStack.push(fracB, fracM, fracM, fracA);
|
||||
stack.push(b, m, m, a);
|
||||
geoStack.push(geoB, geoM, geoM, geoA);
|
||||
}
|
||||
}
|
||||
goog.asserts.assert(maxIterations > 0);
|
||||
|
||||
return flatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a great-circle arcs between two lat/lon points.
|
||||
* @param {number} lon1 Longitude 1 in degrees.
|
||||
* @param {number} lat1 Latitude 1 in degrees.
|
||||
* @param {number} lon2 Longitude 2 in degrees.
|
||||
* @param {number} lat2 Latitude 2 in degrees.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.flat.geodesic.greatCircleArc = function(
|
||||
lon1, lat1, lon2, lat2, projection, squaredTolerance) {
|
||||
|
||||
var geoProjection = ol.proj.get('EPSG:4326');
|
||||
|
||||
var cosLat1 = Math.cos(goog.math.toRadians(lat1));
|
||||
var sinLat1 = Math.sin(goog.math.toRadians(lat1));
|
||||
var cosLat2 = Math.cos(goog.math.toRadians(lat2));
|
||||
var sinLat2 = Math.sin(goog.math.toRadians(lat2));
|
||||
var cosDeltaLon = Math.cos(goog.math.toRadians(lon2 - lon1));
|
||||
var sinDeltaLon = Math.sin(goog.math.toRadians(lon2 - lon1));
|
||||
var d = sinLat1 * sinLat2 + cosLat1 * cosLat2 * cosDeltaLon;
|
||||
|
||||
return ol.geom.flat.geodesic.line_(
|
||||
/**
|
||||
* @param {number} frac Fraction.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
function(frac) {
|
||||
if (1 <= d) {
|
||||
return [lon2, lat2];
|
||||
}
|
||||
var D = frac * Math.acos(d);
|
||||
var cosD = Math.cos(D);
|
||||
var sinD = Math.sin(D);
|
||||
var y = sinDeltaLon * cosLat2;
|
||||
var x = cosLat1 * sinLat2 - sinLat1 * cosLat2 * cosDeltaLon;
|
||||
var theta = Math.atan2(y, x);
|
||||
var lat = Math.asin(sinLat1 * cosD + cosLat1 * sinD * Math.cos(theta));
|
||||
var lon = goog.math.toRadians(lon1) +
|
||||
Math.atan2(Math.sin(theta) * sinD * cosLat1,
|
||||
cosD - sinLat1 * Math.sin(lat));
|
||||
return [goog.math.toDegrees(lon), goog.math.toDegrees(lat)];
|
||||
}, ol.proj.getTransform(geoProjection, projection), squaredTolerance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a meridian (line at constant longitude).
|
||||
* @param {number} lon Longitude.
|
||||
* @param {number} lat1 Latitude 1.
|
||||
* @param {number} lat2 Latitude 2.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.flat.geodesic.meridian =
|
||||
function(lon, lat1, lat2, projection, squaredTolerance) {
|
||||
var epsg4326Projection = ol.proj.get('EPSG:4326');
|
||||
return ol.geom.flat.geodesic.line_(
|
||||
/**
|
||||
* @param {number} frac Fraction.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
function(frac) {
|
||||
return [lon, lat1 + ((lat2 - lat1) * frac)];
|
||||
},
|
||||
ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a parallel (line at constant latitude).
|
||||
* @param {number} lat Latitude.
|
||||
* @param {number} lon1 Longitude 1.
|
||||
* @param {number} lon2 Longitude 2.
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.flat.geodesic.parallel =
|
||||
function(lat, lon1, lon2, projection, squaredTolerance) {
|
||||
var epsg4326Projection = ol.proj.get('EPSG:4326');
|
||||
return ol.geom.flat.geodesic.line_(
|
||||
/**
|
||||
* @param {number} frac Fraction.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
function(frac) {
|
||||
return [lon1 + ((lon2 - lon1) * frac), lat];
|
||||
},
|
||||
ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
goog.provide('ol.geom.flat.inflate');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<ol.Coordinate>=} opt_coordinates Coordinates.
|
||||
* @return {Array.<ol.Coordinate>} Coordinates.
|
||||
*/
|
||||
ol.geom.flat.inflate.coordinates =
|
||||
function(flatCoordinates, offset, end, stride, opt_coordinates) {
|
||||
var coordinates = goog.isDef(opt_coordinates) ? opt_coordinates : [];
|
||||
var i = 0;
|
||||
var j;
|
||||
for (j = offset; j < end; j += stride) {
|
||||
coordinates[i++] = flatCoordinates.slice(j, j + stride);
|
||||
}
|
||||
coordinates.length = i;
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<Array.<ol.Coordinate>>=} opt_coordinatess Coordinatess.
|
||||
* @return {Array.<Array.<ol.Coordinate>>} Coordinatess.
|
||||
*/
|
||||
ol.geom.flat.inflate.coordinatess =
|
||||
function(flatCoordinates, offset, ends, stride, opt_coordinatess) {
|
||||
var coordinatess = goog.isDef(opt_coordinatess) ? opt_coordinatess : [];
|
||||
var i = 0;
|
||||
var j, jj;
|
||||
for (j = 0, jj = ends.length; j < jj; ++j) {
|
||||
var end = ends[j];
|
||||
coordinatess[i++] = ol.geom.flat.inflate.coordinates(
|
||||
flatCoordinates, offset, end, stride, coordinatess[i]);
|
||||
offset = end;
|
||||
}
|
||||
coordinatess.length = i;
|
||||
return coordinatess;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<Array.<Array.<ol.Coordinate>>>=} opt_coordinatesss
|
||||
* Coordinatesss.
|
||||
* @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinatesss.
|
||||
*/
|
||||
ol.geom.flat.inflate.coordinatesss =
|
||||
function(flatCoordinates, offset, endss, stride, opt_coordinatesss) {
|
||||
var coordinatesss = goog.isDef(opt_coordinatesss) ? opt_coordinatesss : [];
|
||||
var i = 0;
|
||||
var j, jj;
|
||||
for (j = 0, jj = endss.length; j < jj; ++j) {
|
||||
var ends = endss[j];
|
||||
coordinatesss[i++] = ol.geom.flat.inflate.coordinatess(
|
||||
flatCoordinates, offset, ends, stride, coordinatesss[i]);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
coordinatesss.length = i;
|
||||
return coordinatesss;
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
goog.provide('ol.geom.flat.interiorpoint');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.geom.flat.contains');
|
||||
|
||||
|
||||
/**
|
||||
* Calculates a point that is likely to lie in the interior of the linear rings.
|
||||
* Inspired by JTS's com.vividsolutions.jts.geom.Geometry#getInteriorPoint.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<number>} flatCenters Flat centers.
|
||||
* @param {number} flatCentersOffset Flat center offset.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @return {Array.<number>} Destination.
|
||||
*/
|
||||
ol.geom.flat.interiorpoint.linearRings = function(flatCoordinates, offset,
|
||||
ends, stride, flatCenters, flatCentersOffset, opt_dest) {
|
||||
var i, ii, x, x1, x2, y1, y2;
|
||||
var y = flatCenters[flatCentersOffset + 1];
|
||||
/** @type {Array.<number>} */
|
||||
var intersections = [];
|
||||
// Calculate intersections with the horizontal line
|
||||
var end = ends[0];
|
||||
x1 = flatCoordinates[end - stride];
|
||||
y1 = flatCoordinates[end - stride + 1];
|
||||
for (i = offset; i < end; i += stride) {
|
||||
x2 = flatCoordinates[i];
|
||||
y2 = flatCoordinates[i + 1];
|
||||
if ((y <= y1 && y2 <= y) || (y1 <= y && y <= y2)) {
|
||||
x = (y - y1) / (y2 - y1) * (x2 - x1) + x1;
|
||||
intersections.push(x);
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
// Find the longest segment of the horizontal line that has its center point
|
||||
// inside the linear ring.
|
||||
var pointX = NaN;
|
||||
var maxSegmentLength = -Infinity;
|
||||
intersections.sort();
|
||||
x1 = intersections[0];
|
||||
for (i = 1, ii = intersections.length; i < ii; ++i) {
|
||||
x2 = intersections[i];
|
||||
var segmentLength = Math.abs(x2 - x1);
|
||||
if (segmentLength > maxSegmentLength) {
|
||||
x = (x1 + x2) / 2;
|
||||
if (ol.geom.flat.contains.linearRingsContainsXY(
|
||||
flatCoordinates, offset, ends, stride, x, y)) {
|
||||
pointX = x;
|
||||
maxSegmentLength = segmentLength;
|
||||
}
|
||||
}
|
||||
x1 = x2;
|
||||
}
|
||||
if (isNaN(pointX)) {
|
||||
// There is no horizontal line that has its center point inside the linear
|
||||
// ring. Use the center of the the linear ring's extent.
|
||||
pointX = flatCenters[flatCentersOffset];
|
||||
}
|
||||
if (goog.isDef(opt_dest)) {
|
||||
opt_dest.push(pointX, y);
|
||||
return opt_dest;
|
||||
} else {
|
||||
return [pointX, y];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Array.<number>} flatCenters Flat centers.
|
||||
* @return {Array.<number>} Interior points.
|
||||
*/
|
||||
ol.geom.flat.interiorpoint.linearRingss =
|
||||
function(flatCoordinates, offset, endss, stride, flatCenters) {
|
||||
goog.asserts.assert(2 * endss.length == flatCenters.length);
|
||||
var interiorPoints = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
interiorPoints = ol.geom.flat.interiorpoint.linearRings(flatCoordinates,
|
||||
offset, ends, stride, flatCenters, 2 * i, interiorPoints);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return interiorPoints;
|
||||
};
|
||||
@@ -0,0 +1,190 @@
|
||||
goog.provide('ol.geom.flat.interpolate');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.math');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} fraction Fraction.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @return {Array.<number>} Destination.
|
||||
*/
|
||||
ol.geom.flat.interpolate.lineString =
|
||||
function(flatCoordinates, offset, end, stride, fraction, opt_dest) {
|
||||
// FIXME interpolate extra dimensions
|
||||
goog.asserts.assert(0 <= fraction && fraction <= 1);
|
||||
var pointX = NaN;
|
||||
var pointY = NaN;
|
||||
var n = (end - offset) / stride;
|
||||
if (n === 0) {
|
||||
goog.asserts.fail();
|
||||
} else if (n == 1) {
|
||||
pointX = flatCoordinates[offset];
|
||||
pointY = flatCoordinates[offset + 1];
|
||||
} else if (n == 2) {
|
||||
pointX = (1 - fraction) * flatCoordinates[offset] +
|
||||
fraction * flatCoordinates[offset + stride];
|
||||
pointY = (1 - fraction) * flatCoordinates[offset + 1] +
|
||||
fraction * flatCoordinates[offset + stride + 1];
|
||||
} else {
|
||||
var x1 = flatCoordinates[offset];
|
||||
var y1 = flatCoordinates[offset + 1];
|
||||
var length = 0;
|
||||
var cumulativeLengths = [0];
|
||||
var i;
|
||||
for (i = offset + stride; i < end; i += stride) {
|
||||
var x2 = flatCoordinates[i];
|
||||
var y2 = flatCoordinates[i + 1];
|
||||
length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
cumulativeLengths.push(length);
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
var target = fraction * length;
|
||||
var index = goog.array.binarySearch(cumulativeLengths, target);
|
||||
if (index < 0) {
|
||||
var t = (target - cumulativeLengths[-index - 2]) /
|
||||
(cumulativeLengths[-index - 1] - cumulativeLengths[-index - 2]);
|
||||
var o = offset + (-index - 2) * stride;
|
||||
pointX = goog.math.lerp(
|
||||
flatCoordinates[o], flatCoordinates[o + stride], t);
|
||||
pointY = goog.math.lerp(
|
||||
flatCoordinates[o + 1], flatCoordinates[o + stride + 1], t);
|
||||
} else {
|
||||
pointX = flatCoordinates[offset + index * stride];
|
||||
pointY = flatCoordinates[offset + index * stride + 1];
|
||||
}
|
||||
}
|
||||
if (goog.isDefAndNotNull(opt_dest)) {
|
||||
opt_dest[0] = pointX;
|
||||
opt_dest[1] = pointY;
|
||||
return opt_dest;
|
||||
} else {
|
||||
return [pointX, pointY];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} m M.
|
||||
* @param {boolean} extrapolate Extrapolate.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.geom.flat.lineStringCoordinateAtM =
|
||||
function(flatCoordinates, offset, end, stride, m, extrapolate) {
|
||||
if (end == offset) {
|
||||
return null;
|
||||
}
|
||||
var coordinate;
|
||||
if (m < flatCoordinates[offset + stride - 1]) {
|
||||
if (extrapolate) {
|
||||
coordinate = flatCoordinates.slice(offset, offset + stride);
|
||||
coordinate[stride - 1] = m;
|
||||
return coordinate;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (flatCoordinates[end - 1] < m) {
|
||||
if (extrapolate) {
|
||||
coordinate = flatCoordinates.slice(end - stride, end);
|
||||
coordinate[stride - 1] = m;
|
||||
return coordinate;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// FIXME use O(1) search
|
||||
if (m == flatCoordinates[offset + stride - 1]) {
|
||||
return flatCoordinates.slice(offset, offset + stride);
|
||||
}
|
||||
var lo = offset / stride;
|
||||
var hi = end / stride;
|
||||
while (lo < hi) {
|
||||
var mid = (lo + hi) >> 1;
|
||||
if (m < flatCoordinates[(mid + 1) * stride - 1]) {
|
||||
hi = mid;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
var m0 = flatCoordinates[lo * stride - 1];
|
||||
if (m == m0) {
|
||||
return flatCoordinates.slice((lo - 1) * stride, (lo - 1) * stride + stride);
|
||||
}
|
||||
var m1 = flatCoordinates[(lo + 1) * stride - 1];
|
||||
goog.asserts.assert(m0 < m);
|
||||
goog.asserts.assert(m <= m1);
|
||||
var t = (m - m0) / (m1 - m0);
|
||||
coordinate = [];
|
||||
var i;
|
||||
for (i = 0; i < stride - 1; ++i) {
|
||||
coordinate.push(goog.math.lerp(flatCoordinates[(lo - 1) * stride + i],
|
||||
flatCoordinates[lo * stride + i], t));
|
||||
}
|
||||
coordinate.push(m);
|
||||
goog.asserts.assert(coordinate.length == stride);
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} m M.
|
||||
* @param {boolean} extrapolate Extrapolate.
|
||||
* @param {boolean} interpolate Interpolate.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.geom.flat.lineStringsCoordinateAtM = function(
|
||||
flatCoordinates, offset, ends, stride, m, extrapolate, interpolate) {
|
||||
if (interpolate) {
|
||||
return ol.geom.flat.lineStringCoordinateAtM(
|
||||
flatCoordinates, offset, ends[ends.length - 1], stride, m, extrapolate);
|
||||
}
|
||||
var coordinate;
|
||||
if (m < flatCoordinates[stride - 1]) {
|
||||
if (extrapolate) {
|
||||
coordinate = flatCoordinates.slice(0, stride);
|
||||
coordinate[stride - 1] = m;
|
||||
return coordinate;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (flatCoordinates[flatCoordinates.length - 1] < m) {
|
||||
if (extrapolate) {
|
||||
coordinate = flatCoordinates.slice(flatCoordinates.length - stride);
|
||||
coordinate[stride - 1] = m;
|
||||
return coordinate;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
if (offset == end) {
|
||||
continue;
|
||||
}
|
||||
if (m < flatCoordinates[offset + stride - 1]) {
|
||||
return null;
|
||||
} else if (m <= flatCoordinates[end - 1]) {
|
||||
return ol.geom.flat.lineStringCoordinateAtM(
|
||||
flatCoordinates, offset, end, stride, m, false);
|
||||
}
|
||||
offset = end;
|
||||
}
|
||||
goog.asserts.fail();
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
goog.provide('ol.geom.flat.intersectsextent');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.segments');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.lineString =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
var coordinatesExtent = ol.extent.extendFlatCoordinates(
|
||||
ol.extent.createEmpty(), flatCoordinates, offset, end, stride);
|
||||
if (!ol.extent.intersects(extent, coordinatesExtent)) {
|
||||
return false;
|
||||
}
|
||||
if (ol.extent.containsExtent(extent, coordinatesExtent)) {
|
||||
return true;
|
||||
}
|
||||
if (coordinatesExtent[0] >= extent[0] &&
|
||||
coordinatesExtent[2] <= extent[2]) {
|
||||
return true;
|
||||
}
|
||||
if (coordinatesExtent[1] >= extent[1] &&
|
||||
coordinatesExtent[3] <= extent[3]) {
|
||||
return true;
|
||||
}
|
||||
return ol.geom.flat.segments.forEach(flatCoordinates, offset, end, stride,
|
||||
/**
|
||||
* @param {ol.Coordinate} point1 Start point.
|
||||
* @param {ol.Coordinate} point2 End point.
|
||||
* @return {boolean} `true` if the segment and the extent intersect,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
function(point1, point2) {
|
||||
return ol.extent.intersectsSegment(extent, point1, point2);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.lineStrings =
|
||||
function(flatCoordinates, offset, ends, stride, extent) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
if (ol.geom.flat.intersectsextent.lineString(
|
||||
flatCoordinates, offset, ends[i], stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
offset = ends[i];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRing =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
if (ol.geom.flat.intersectsextent.lineString(
|
||||
flatCoordinates, offset, end, stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[0], extent[1])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[0], extent[3])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[2], extent[1])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[2], extent[3])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRings =
|
||||
function(flatCoordinates, offset, ends, stride, extent) {
|
||||
goog.asserts.assert(ends.length > 0);
|
||||
if (!ol.geom.flat.intersectsextent.linearRing(
|
||||
flatCoordinates, offset, ends[0], stride, extent)) {
|
||||
return false;
|
||||
}
|
||||
if (ends.length === 1) {
|
||||
return true;
|
||||
}
|
||||
var i, ii;
|
||||
for (i = 1, ii = ends.length; i < ii; ++i) {
|
||||
if (ol.geom.flat.contains.linearRingContainsExtent(
|
||||
flatCoordinates, ends[i - 1], ends[i], stride, extent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRingss =
|
||||
function(flatCoordinates, offset, endss, stride, extent) {
|
||||
goog.asserts.assert(endss.length > 0);
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
if (ol.geom.flat.intersectsextent.linearRings(
|
||||
flatCoordinates, offset, ends, stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
goog.provide('ol.geom.flat.length');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} Length.
|
||||
*/
|
||||
ol.geom.flat.length.lineString =
|
||||
function(flatCoordinates, offset, end, stride) {
|
||||
var x1 = flatCoordinates[offset];
|
||||
var y1 = flatCoordinates[offset + 1];
|
||||
var length = 0;
|
||||
var i;
|
||||
for (i = offset + stride; i < end; i += stride) {
|
||||
var x2 = flatCoordinates[i];
|
||||
var y2 = flatCoordinates[i + 1];
|
||||
length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
return length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} Perimeter.
|
||||
*/
|
||||
ol.geom.flat.length.linearRing =
|
||||
function(flatCoordinates, offset, end, stride) {
|
||||
var perimeter =
|
||||
ol.geom.flat.length.lineString(flatCoordinates, offset, end, stride);
|
||||
var dx = flatCoordinates[end - stride] - flatCoordinates[offset];
|
||||
var dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];
|
||||
perimeter += Math.sqrt(dx * dx + dy * dy);
|
||||
return perimeter;
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
goog.provide('ol.geom.flat.orient');
|
||||
|
||||
goog.require('ol.geom.flat.reverse');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} Is clockwise.
|
||||
*/
|
||||
ol.geom.flat.orient.linearRingIsClockwise =
|
||||
function(flatCoordinates, offset, end, stride) {
|
||||
// http://tinyurl.com/clockwise-method
|
||||
// https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
|
||||
var edge = 0;
|
||||
var x1 = flatCoordinates[end - stride];
|
||||
var y1 = flatCoordinates[end - stride + 1];
|
||||
for (; offset < end; offset += stride) {
|
||||
var x2 = flatCoordinates[offset];
|
||||
var y2 = flatCoordinates[offset + 1];
|
||||
edge += (x2 - x1) * (y2 + y1);
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
return edge > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} `true` if all rings are correctly oriented, `false`
|
||||
* otherwise.
|
||||
*/
|
||||
ol.geom.flat.orient.linearRingsAreOriented =
|
||||
function(flatCoordinates, offset, ends, stride) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
|
||||
flatCoordinates, offset, end, stride);
|
||||
if (i === 0 ? !isClockwise : isClockwise) {
|
||||
return false;
|
||||
}
|
||||
offset = end;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} `true` if all rings are correctly oriented, `false`
|
||||
* otherwise.
|
||||
*/
|
||||
ol.geom.flat.linearRingssAreOriented =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
if (!ol.geom.flat.orient.linearRingsAreOriented(
|
||||
flatCoordinates, offset, endss[i], stride)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} End.
|
||||
*/
|
||||
ol.geom.flat.orient.orientLinearRings =
|
||||
function(flatCoordinates, offset, ends, stride) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
|
||||
flatCoordinates, offset, end, stride);
|
||||
var reverse = i === 0 ? !isClockwise : isClockwise;
|
||||
if (reverse) {
|
||||
ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
|
||||
}
|
||||
offset = end;
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @return {number} End.
|
||||
*/
|
||||
ol.geom.flat.orient.orientLinearRingss =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
offset = ol.geom.flat.orient.orientLinearRings(
|
||||
flatCoordinates, offset, endss[i], stride);
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
goog.provide('ol.geom.flat.reverse');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
*/
|
||||
ol.geom.flat.reverse.coordinates =
|
||||
function(flatCoordinates, offset, end, stride) {
|
||||
while (offset < end - stride) {
|
||||
var i;
|
||||
for (i = 0; i < stride; ++i) {
|
||||
var tmp = flatCoordinates[offset + i];
|
||||
flatCoordinates[offset + i] = flatCoordinates[end - stride + i];
|
||||
flatCoordinates[end - stride + i] = tmp;
|
||||
}
|
||||
offset += stride;
|
||||
end -= stride;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
goog.provide('ol.geom.flat.segments');
|
||||
|
||||
|
||||
/**
|
||||
* This function calls `callback` for each segment of the flat coordinates
|
||||
* array. If the callback returns a truthy value the function returns that
|
||||
* value immediately. Otherwise the function returns `false`.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
|
||||
* called for each segment.
|
||||
* @param {S=} opt_this The object to be used as the value of 'this'
|
||||
* within callback.
|
||||
* @return {T|boolean} Value.
|
||||
* @template T,S
|
||||
*/
|
||||
ol.geom.flat.segments.forEach =
|
||||
function(flatCoordinates, offset, end, stride, callback, opt_this) {
|
||||
var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];
|
||||
var point2 = [];
|
||||
var ret;
|
||||
for (; (offset + stride) < end; offset += stride) {
|
||||
point2[0] = flatCoordinates[offset + stride];
|
||||
point2[1] = flatCoordinates[offset + stride + 1];
|
||||
ret = callback.call(opt_this, point1, point2);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
point1[0] = point2[0];
|
||||
point1[1] = point2[1];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,400 @@
|
||||
// Based on simplify-js https://github.com/mourner/simplify-js
|
||||
// Copyright (c) 2012, Vladimir Agafonkin
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.geom.flat.simplify');
|
||||
|
||||
goog.require('ol.math');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {boolean} highQuality Highest quality.
|
||||
* @param {Array.<number>=} opt_simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @return {Array.<number>} Simplified line string.
|
||||
*/
|
||||
ol.geom.flat.simplify.lineString = function(flatCoordinates, offset, end,
|
||||
stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) {
|
||||
var simplifiedFlatCoordinates = goog.isDef(opt_simplifiedFlatCoordinates) ?
|
||||
opt_simplifiedFlatCoordinates : [];
|
||||
if (!highQuality) {
|
||||
end = ol.geom.flat.simplify.radialDistance(flatCoordinates, offset, end,
|
||||
stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, 0);
|
||||
flatCoordinates = simplifiedFlatCoordinates;
|
||||
offset = 0;
|
||||
stride = 2;
|
||||
}
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
|
||||
flatCoordinates, offset, end, stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, 0);
|
||||
return simplifiedFlatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.douglasPeucker = function(flatCoordinates, offset, end,
|
||||
stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
|
||||
var n = (end - offset) / stride;
|
||||
if (n < 3) {
|
||||
for (; offset < end; offset += stride) {
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] =
|
||||
flatCoordinates[offset];
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] =
|
||||
flatCoordinates[offset + 1];
|
||||
}
|
||||
return simplifiedOffset;
|
||||
}
|
||||
/** @type {Array.<number>} */
|
||||
var markers = new Array(n);
|
||||
markers[0] = 1;
|
||||
markers[n - 1] = 1;
|
||||
/** @type {Array.<number>} */
|
||||
var stack = [offset, end - stride];
|
||||
var index = 0;
|
||||
var i;
|
||||
while (stack.length > 0) {
|
||||
var last = stack.pop();
|
||||
var first = stack.pop();
|
||||
var maxSquaredDistance = 0;
|
||||
var x1 = flatCoordinates[first];
|
||||
var y1 = flatCoordinates[first + 1];
|
||||
var x2 = flatCoordinates[last];
|
||||
var y2 = flatCoordinates[last + 1];
|
||||
for (i = first + stride; i < last; i += stride) {
|
||||
var x = flatCoordinates[i];
|
||||
var y = flatCoordinates[i + 1];
|
||||
var squaredDistance = ol.math.squaredSegmentDistance(
|
||||
x, y, x1, y1, x2, y2);
|
||||
if (squaredDistance > maxSquaredDistance) {
|
||||
index = i;
|
||||
maxSquaredDistance = squaredDistance;
|
||||
}
|
||||
}
|
||||
if (maxSquaredDistance > squaredTolerance) {
|
||||
markers[(index - offset) / stride] = 1;
|
||||
if (first + stride < index) {
|
||||
stack.push(first, index);
|
||||
}
|
||||
if (index + stride < last) {
|
||||
stack.push(index, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (markers[i]) {
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] =
|
||||
flatCoordinates[offset + i * stride];
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] =
|
||||
flatCoordinates[offset + i * stride + 1];
|
||||
}
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @param {Array.<number>} simplifiedEnds Simplified ends.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.douglasPeuckers = function(flatCoordinates, offset,
|
||||
ends, stride, squaredTolerance, simplifiedFlatCoordinates,
|
||||
simplifiedOffset, simplifiedEnds) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
simplifiedOffset = ol.geom.flat.simplify.douglasPeucker(
|
||||
flatCoordinates, offset, end, stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset);
|
||||
simplifiedEnds.push(simplifiedOffset);
|
||||
offset = end;
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.douglasPeuckerss = function(
|
||||
flatCoordinates, offset, endss, stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
var simplifiedEnds = [];
|
||||
simplifiedOffset = ol.geom.flat.simplify.douglasPeuckers(
|
||||
flatCoordinates, offset, ends, stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
|
||||
simplifiedEndss.push(simplifiedEnds);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.radialDistance = function(flatCoordinates, offset, end,
|
||||
stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
|
||||
if (end <= offset + stride) {
|
||||
// zero or one point, no simplification possible, so copy and return
|
||||
for (; offset < end; offset += stride) {
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] =
|
||||
flatCoordinates[offset + 1];
|
||||
}
|
||||
return simplifiedOffset;
|
||||
}
|
||||
var x1 = flatCoordinates[offset];
|
||||
var y1 = flatCoordinates[offset + 1];
|
||||
// copy first point
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x1;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y1;
|
||||
var x2 = x1;
|
||||
var y2 = y1;
|
||||
for (offset += stride; offset < end; offset += stride) {
|
||||
x2 = flatCoordinates[offset];
|
||||
y2 = flatCoordinates[offset + 1];
|
||||
if (ol.math.squaredDistance(x1, y1, x2, y2) > squaredTolerance) {
|
||||
// copy point at offset
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x2;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y2;
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
}
|
||||
if (x2 != x1 || y2 != y1) {
|
||||
// copy last point
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x2;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y2;
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} value Value.
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @return {number} Rounded value.
|
||||
*/
|
||||
ol.geom.flat.simplify.snap = function(value, tolerance) {
|
||||
return tolerance * Math.round(value / tolerance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Simplifies a line string using an algorithm designed by Tim Schaub.
|
||||
* Coordinates are snapped to the nearest value in a virtual grid and
|
||||
* consecutive duplicate coordinates are discarded. This effectively preserves
|
||||
* topology as the simplification of any subsection of a line string is
|
||||
* independent of the rest of the line string. This means that, for examples,
|
||||
* the common edge between two polygons will be simplified to the same line
|
||||
* string independently in both polygons. This implementation uses a single
|
||||
* pass over the coordinates and eliminates intermediate collinear points.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.quantize = function(flatCoordinates, offset, end, stride,
|
||||
tolerance, simplifiedFlatCoordinates, simplifiedOffset) {
|
||||
// do nothing if the line is empty
|
||||
if (offset == end) {
|
||||
return simplifiedOffset;
|
||||
}
|
||||
// snap the first coordinate (P1)
|
||||
var x1 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
|
||||
var y1 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
|
||||
offset += stride;
|
||||
// add the first coordinate to the output
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x1;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y1;
|
||||
// find the next coordinate that does not snap to the same value as the first
|
||||
// coordinate (P2)
|
||||
var x2, y2;
|
||||
do {
|
||||
x2 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
|
||||
y2 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
|
||||
offset += stride;
|
||||
if (offset == end) {
|
||||
// all coordinates snap to the same value, the line collapses to a point
|
||||
// push the last snapped value anyway to ensure that the output contains
|
||||
// at least two points
|
||||
// FIXME should we really return at least two points anyway?
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x2;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y2;
|
||||
return simplifiedOffset;
|
||||
}
|
||||
} while (x2 == x1 && y2 == y1);
|
||||
while (offset < end) {
|
||||
var x3, y3;
|
||||
// snap the next coordinate (P3)
|
||||
x3 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
|
||||
y3 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
|
||||
offset += stride;
|
||||
// skip P3 if it is equal to P2
|
||||
if (x3 == x2 && y3 == y2) {
|
||||
continue;
|
||||
}
|
||||
// calculate the delta between P1 and P2
|
||||
var dx1 = x2 - x1;
|
||||
var dy1 = y2 - y1;
|
||||
// calculate the delta between P3 and P1
|
||||
var dx2 = x3 - x1;
|
||||
var dy2 = y3 - y1;
|
||||
// if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from
|
||||
// P1 in the same direction then P2 is on the straight line between P1 and
|
||||
// P3
|
||||
if ((dx1 * dy2 == dy1 * dx2) &&
|
||||
((dx1 < 0 && dx2 < dx1) || dx1 == dx2 || (dx1 > 0 && dx2 > dx1)) &&
|
||||
((dy1 < 0 && dy2 < dy1) || dy1 == dy2 || (dy1 > 0 && dy2 > dy1))) {
|
||||
// discard P2 and set P2 = P3
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
continue;
|
||||
}
|
||||
// either P1, P2, and P3 are not colinear, or they are colinear but P3 is
|
||||
// between P3 and P1 or on the opposite half of the line to P2. add P2,
|
||||
// and continue with P1 = P2 and P2 = P3
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x2;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y2;
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
}
|
||||
// add the last point (P2)
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = x2;
|
||||
simplifiedFlatCoordinates[simplifiedOffset++] = y2;
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @param {Array.<number>} simplifiedEnds Simplified ends.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.quantizes = function(
|
||||
flatCoordinates, offset, ends, stride,
|
||||
tolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
simplifiedOffset = ol.geom.flat.simplify.quantize(
|
||||
flatCoordinates, offset, end, stride,
|
||||
tolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset);
|
||||
simplifiedEnds.push(simplifiedOffset);
|
||||
offset = end;
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
|
||||
* coordinates.
|
||||
* @param {number} simplifiedOffset Simplified offset.
|
||||
* @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
|
||||
* @return {number} Simplified offset.
|
||||
*/
|
||||
ol.geom.flat.simplify.quantizess = function(
|
||||
flatCoordinates, offset, endss, stride,
|
||||
tolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
var simplifiedEnds = [];
|
||||
simplifiedOffset = ol.geom.flat.simplify.quantizes(
|
||||
flatCoordinates, offset, ends, stride,
|
||||
tolerance,
|
||||
simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
|
||||
simplifiedEndss.push(simplifiedEnds);
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return simplifiedOffset;
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
goog.provide('ol.geom.flat.transform');
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {goog.vec.Mat4.Number} transform Transform.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @return {Array.<number>} Transformed coordinates.
|
||||
*/
|
||||
ol.geom.flat.transform.transform2D =
|
||||
function(flatCoordinates, offset, end, stride, transform, opt_dest) {
|
||||
var m00 = goog.vec.Mat4.getElement(transform, 0, 0);
|
||||
var m10 = goog.vec.Mat4.getElement(transform, 1, 0);
|
||||
var m01 = goog.vec.Mat4.getElement(transform, 0, 1);
|
||||
var m11 = goog.vec.Mat4.getElement(transform, 1, 1);
|
||||
var m03 = goog.vec.Mat4.getElement(transform, 0, 3);
|
||||
var m13 = goog.vec.Mat4.getElement(transform, 1, 3);
|
||||
var dest = goog.isDef(opt_dest) ? opt_dest : [];
|
||||
var i = 0;
|
||||
var j;
|
||||
for (j = offset; j < end; j += stride) {
|
||||
var x = flatCoordinates[j];
|
||||
var y = flatCoordinates[j + 1];
|
||||
dest[i++] = m00 * x + m01 * y + m03;
|
||||
dest[i++] = m10 * x + m11 * y + m13;
|
||||
}
|
||||
if (goog.isDef(opt_dest) && dest.length != i) {
|
||||
dest.length = i;
|
||||
}
|
||||
return dest;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {number} deltaX Delta X.
|
||||
* @param {number} deltaY Delta Y.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @return {Array.<number>} Transformed coordinates.
|
||||
*/
|
||||
ol.geom.flat.transform.translate =
|
||||
function(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) {
|
||||
var dest = goog.isDef(opt_dest) ? opt_dest : [];
|
||||
var i = 0;
|
||||
var j, k;
|
||||
for (j = offset; j < end; j += stride) {
|
||||
dest[i++] = flatCoordinates[j] + deltaX;
|
||||
dest[i++] = flatCoordinates[j + 1] + deltaY;
|
||||
for (k = j + 2; k < j + stride; ++k) {
|
||||
dest[i++] = flatCoordinates[k];
|
||||
}
|
||||
}
|
||||
if (goog.isDef(opt_dest) && dest.length != i) {
|
||||
dest.length = i;
|
||||
}
|
||||
return dest;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @namespace ol.geom
|
||||
*/
|
||||
@@ -0,0 +1,238 @@
|
||||
goog.provide('ol.geom.Geometry');
|
||||
goog.provide('ol.geom.GeometryType');
|
||||
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Observable');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.proj');
|
||||
|
||||
|
||||
/**
|
||||
* The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
|
||||
* `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
|
||||
* `'GeometryCollection'`, `'Circle'`.
|
||||
* @enum {string}
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryType = {
|
||||
POINT: 'Point',
|
||||
LINE_STRING: 'LineString',
|
||||
LINEAR_RING: 'LinearRing',
|
||||
POLYGON: 'Polygon',
|
||||
MULTI_POINT: 'MultiPoint',
|
||||
MULTI_LINE_STRING: 'MultiLineString',
|
||||
MULTI_POLYGON: 'MultiPolygon',
|
||||
GEOMETRY_COLLECTION: 'GeometryCollection',
|
||||
CIRCLE: 'Circle'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
|
||||
* or measure ('M') coordinate is available. Supported values are `'XY'`,
|
||||
* `'XYZ'`, `'XYM'`, `'XYZM'`.
|
||||
* @enum {string}
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryLayout = {
|
||||
XY: 'XY',
|
||||
XYZ: 'XYZ',
|
||||
XYM: 'XYM',
|
||||
XYZM: 'XYZM'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for vector geometries.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Observable}
|
||||
* @fires change Triggered when the geometry changes.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.extent_ = ol.extent.createEmpty();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.extentRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Object.<string, ol.geom.Geometry>}
|
||||
*/
|
||||
this.simplifiedGeometryCache = {};
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
this.simplifiedGeometryRevision = 0;
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.Geometry, ol.Observable);
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @function
|
||||
* @return {!ol.geom.Geometry} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.clone = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @param {ol.Coordinate} closestPoint Closest point.
|
||||
* @param {number} minSquaredDistance Minimum squared distance.
|
||||
* @return {number} Minimum squared distance.
|
||||
*/
|
||||
ol.geom.Geometry.prototype.closestPointXY = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} point Point.
|
||||
* @param {ol.Coordinate=} opt_closestPoint Closest point.
|
||||
* @return {ol.Coordinate} Closest point.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
|
||||
var closestPoint = goog.isDef(opt_closestPoint) ?
|
||||
opt_closestPoint : [NaN, NaN];
|
||||
this.closestPointXY(point[0], point[1], closestPoint, Infinity);
|
||||
return closestPoint;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {boolean} Contains coordinate.
|
||||
*/
|
||||
ol.geom.Geometry.prototype.containsCoordinate = function(coordinate) {
|
||||
return this.containsXY(coordinate[0], coordinate[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @protected
|
||||
* @return {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.geom.Geometry.prototype.computeExtent = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
ol.geom.Geometry.prototype.containsXY = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* Get the extent of the geometry.
|
||||
* @param {ol.Extent=} opt_extent Extent.
|
||||
* @return {ol.Extent} extent Extent.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
|
||||
if (this.extentRevision_ != this.getRevision()) {
|
||||
this.extent_ = this.computeExtent(this.extent_);
|
||||
this.extentRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.extent.returnOrUpdate(this.extent_, opt_extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a simplified version of this geometry using the Douglas Peucker
|
||||
* algorithm.
|
||||
* @see http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
|
||||
* @function
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {ol.geom.Geometry} Simplified geometry.
|
||||
*/
|
||||
ol.geom.Geometry.prototype.getSimplifiedGeometry = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Get the type of this geometry.
|
||||
* @function
|
||||
* @return {ol.geom.GeometryType} Geometry type.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.getType = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Apply a transform function to each coordinate of the geometry.
|
||||
* The geometry is modified in place.
|
||||
* If you do not want the geometry modified in place, first clone() it and
|
||||
* then use this function on the clone.
|
||||
* @function
|
||||
* @param {ol.TransformFunction} transformFn Transform.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Test if the geometry and the passed extent intersect.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} `true` if the geometry and the extent intersect.
|
||||
* @function
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Translate the geometry.
|
||||
* @param {number} deltaX Delta X.
|
||||
* @param {number} deltaY Delta Y.
|
||||
* @function
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Geometry.prototype.translate = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Transform each coordinate of the geometry from one coordinate reference
|
||||
* system to another. The geometry is modified in place.
|
||||
* For example, a line will be transformed to a line and a circle to a circle.
|
||||
* If you do not want the geometry modified in place, first clone() it and
|
||||
* then use this function on the clone.
|
||||
*
|
||||
* @param {ol.proj.ProjectionLike} source The current projection. Can be a
|
||||
* string identifier or a {@link ol.proj.Projection} object.
|
||||
* @param {ol.proj.ProjectionLike} destination The desired projection. Can be a
|
||||
* string identifier or a {@link ol.proj.Projection} object.
|
||||
* @return {ol.geom.Geometry} This geometry. Note that original geometry is
|
||||
* modified in place.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Geometry.prototype.transform = function(source, destination) {
|
||||
this.applyTransform(ol.proj.getTransform(source, destination));
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,294 @@
|
||||
goog.provide('ol.geom.GeometryCollection');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* An array of {@link ol.geom.Geometry} objects.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.Geometry}
|
||||
* @param {Array.<ol.geom.Geometry>=} opt_geometries Geometries.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection = function(opt_geometries) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.geom.Geometry>}
|
||||
*/
|
||||
this.geometries_ = goog.isDef(opt_geometries) ? opt_geometries : null;
|
||||
|
||||
this.listenGeometriesChange_();
|
||||
};
|
||||
goog.inherits(ol.geom.GeometryCollection, ol.geom.Geometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
|
||||
* @private
|
||||
* @return {Array.<ol.geom.Geometry>} Cloned geometries.
|
||||
*/
|
||||
ol.geom.GeometryCollection.cloneGeometries_ = function(geometries) {
|
||||
var clonedGeometries = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
clonedGeometries.push(geometries[i].clone());
|
||||
}
|
||||
return clonedGeometries;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.unlistenGeometriesChange_ = function() {
|
||||
var i, ii;
|
||||
if (goog.isNull(this.geometries_)) {
|
||||
return;
|
||||
}
|
||||
for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
|
||||
goog.events.unlisten(
|
||||
this.geometries_[i], goog.events.EventType.CHANGE,
|
||||
this.changed, false, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.listenGeometriesChange_ = function() {
|
||||
var i, ii;
|
||||
if (goog.isNull(this.geometries_)) {
|
||||
return;
|
||||
}
|
||||
for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
|
||||
goog.events.listen(
|
||||
this.geometries_[i], goog.events.EventType.CHANGE,
|
||||
this.changed, false, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.GeometryCollection} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.clone = function() {
|
||||
var geometryCollection = new ol.geom.GeometryCollection(null);
|
||||
geometryCollection.setGeometries(this.geometries_);
|
||||
return geometryCollection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
minSquaredDistance = geometries[i].closestPointXY(
|
||||
x, y, closestPoint, minSquaredDistance);
|
||||
}
|
||||
return minSquaredDistance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.containsXY = function(x, y) {
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
if (geometries[i].containsXY(x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.computeExtent = function(extent) {
|
||||
ol.extent.createOrUpdateEmpty(extent);
|
||||
var geometries = this.geometries_;
|
||||
for (var i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
ol.extent.extend(extent, geometries[i].getExtent());
|
||||
}
|
||||
return extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.Geometry>} Geometries.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.getGeometries = function() {
|
||||
return ol.geom.GeometryCollection.cloneGeometries_(this.geometries_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.Geometry>} Geometries.
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.getGeometriesArray = function() {
|
||||
return this.geometries_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.getSimplifiedGeometry =
|
||||
function(squaredTolerance) {
|
||||
if (this.simplifiedGeometryRevision != this.getRevision()) {
|
||||
goog.object.clear(this.simplifiedGeometryCache);
|
||||
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
|
||||
this.simplifiedGeometryRevision = this.getRevision();
|
||||
}
|
||||
if (squaredTolerance < 0 ||
|
||||
(this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
|
||||
squaredTolerance < this.simplifiedGeometryMaxMinSquaredTolerance)) {
|
||||
return this;
|
||||
}
|
||||
var key = squaredTolerance.toString();
|
||||
if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
|
||||
return this.simplifiedGeometryCache[key];
|
||||
} else {
|
||||
var simplifiedGeometries = [];
|
||||
var geometries = this.geometries_;
|
||||
var simplified = false;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
var geometry = geometries[i];
|
||||
var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
|
||||
simplifiedGeometries.push(simplifiedGeometry);
|
||||
if (simplifiedGeometry !== geometry) {
|
||||
simplified = true;
|
||||
}
|
||||
}
|
||||
if (simplified) {
|
||||
var simplifiedGeometryCollection = new ol.geom.GeometryCollection(null);
|
||||
simplifiedGeometryCollection.setGeometriesArray(simplifiedGeometries);
|
||||
this.simplifiedGeometryCache[key] = simplifiedGeometryCollection;
|
||||
return simplifiedGeometryCollection;
|
||||
} else {
|
||||
this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.GEOMETRY_COLLECTION;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.intersectsExtent = function(extent) {
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
if (geometries[i].intersectsExtent(extent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is empty.
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.isEmpty = function() {
|
||||
return goog.array.isEmpty(this.geometries_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.setGeometries = function(geometries) {
|
||||
this.setGeometriesArray(
|
||||
ol.geom.GeometryCollection.cloneGeometries_(geometries));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.setGeometriesArray = function(geometries) {
|
||||
this.unlistenGeometriesChange_();
|
||||
this.geometries_ = geometries;
|
||||
this.listenGeometriesChange_();
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.applyTransform = function(transformFn) {
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
geometries[i].applyTransform(transformFn);
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translate the geometry.
|
||||
* @param {number} deltaX Delta X.
|
||||
* @param {number} deltaY Delta Y.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.translate = function(deltaX, deltaY) {
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
geometries[i].translate(deltaX, deltaY);
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.disposeInternal = function() {
|
||||
this.unlistenGeometriesChange_();
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
goog.provide('ol.geom.LinearRing');
|
||||
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.area');
|
||||
goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Linear ring geometry. Only used as part of polygon; cannot be rendered
|
||||
* on its own.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing = function(coordinates, opt_layout) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDelta_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.LinearRing, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.LinearRing} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.clone = function() {
|
||||
var linearRing = new ol.geom.LinearRing(null);
|
||||
linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||
return linearRing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
if (this.maxDeltaRevision_ != this.getRevision()) {
|
||||
this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
|
||||
this.maxDeltaRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.geom.flat.closest.getClosestPoint(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Area (on projected plane).
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.getArea = function() {
|
||||
return ol.geom.flat.area.linearRing(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.Coordinate>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinates(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
var simplifiedFlatCoordinates = [];
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
squaredTolerance, simplifiedFlatCoordinates, 0);
|
||||
var simplifiedLinearRing = new ol.geom.LinearRing(null);
|
||||
simplifiedLinearRing.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
|
||||
return simplifiedLinearRing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.LINEAR_RING;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.setCoordinates =
|
||||
function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 1);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
|
||||
this.flatCoordinates, 0, coordinates, this.stride);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
ol.geom.LinearRing.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates) {
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.changed();
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
goog.provide('ol.geom.LineString');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interpolate');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.length');
|
||||
goog.require('ol.geom.flat.segments');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Linestring geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString = function(coordinates, opt_layout) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.flatMidpoint_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.flatMidpointRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDelta_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.LineString, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.appendCoordinate = function(coordinate) {
|
||||
goog.asserts.assert(coordinate.length == this.stride);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = coordinate.slice();
|
||||
} else {
|
||||
goog.array.extend(this.flatCoordinates, coordinate);
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.LineString} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.clone = function() {
|
||||
var lineString = new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||
return lineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.LineString.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
if (this.maxDeltaRevision_ != this.getRevision()) {
|
||||
this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
|
||||
this.maxDeltaRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.geom.flat.closest.getClosestPoint(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over each segment, calling the provided callback.
|
||||
* If the callback returns a truthy value the function returns that
|
||||
* value immediately. Otherwise the function returns `false`.
|
||||
*
|
||||
* @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
|
||||
* called for each segment.
|
||||
* @param {S=} opt_this The object to be used as the value of 'this'
|
||||
* within callback.
|
||||
* @return {T|boolean} Value.
|
||||
* @template T,S
|
||||
* @api
|
||||
*/
|
||||
ol.geom.LineString.prototype.forEachSegment = function(callback, opt_this) {
|
||||
return ol.geom.flat.segments.forEach(this.flatCoordinates, 0,
|
||||
this.flatCoordinates.length, this.stride, callback, opt_this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the coordinate at `m` using linear interpolation, or `null` if no
|
||||
* such coordinate exists.
|
||||
*
|
||||
* `opt_extrapolate` controls extrapolation beyond the range of Ms in the
|
||||
* MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
|
||||
* M will return the first coordinate and Ms greater than the last M will
|
||||
* return the last coordinate.
|
||||
*
|
||||
* @param {number} m M.
|
||||
* @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
|
||||
if (this.layout != ol.geom.GeometryLayout.XYM &&
|
||||
this.layout != ol.geom.GeometryLayout.XYZM) {
|
||||
return null;
|
||||
}
|
||||
var extrapolate = goog.isDef(opt_extrapolate) ? opt_extrapolate : false;
|
||||
return ol.geom.flat.lineStringCoordinateAtM(this.flatCoordinates, 0,
|
||||
this.flatCoordinates.length, this.stride, m, extrapolate);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.Coordinate>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinates(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Length (on projected plane).
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.getLength = function() {
|
||||
return ol.geom.flat.length.lineString(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Flat midpoint.
|
||||
*/
|
||||
ol.geom.LineString.prototype.getFlatMidpoint = function() {
|
||||
if (this.flatMidpointRevision_ != this.getRevision()) {
|
||||
this.flatMidpoint_ = ol.geom.flat.interpolate.lineString(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
0.5, this.flatMidpoint_);
|
||||
this.flatMidpointRevision_ = this.getRevision();
|
||||
}
|
||||
return this.flatMidpoint_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.LineString.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
var simplifiedFlatCoordinates = [];
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
squaredTolerance, simplifiedFlatCoordinates, 0);
|
||||
var simplifiedLineString = new ol.geom.LineString(null);
|
||||
simplifiedLineString.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
|
||||
return simplifiedLineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.LINE_STRING;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.LineString.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.lineString(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.LineString.prototype.setCoordinates =
|
||||
function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 1);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
|
||||
this.flatCoordinates, 0, coordinates, this.stride);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
ol.geom.LineString.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates) {
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.changed();
|
||||
};
|
||||
@@ -0,0 +1,320 @@
|
||||
goog.provide('ol.geom.MultiLineString');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interpolate');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Multi-linestring geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString = function(coordinates, opt_layout) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.ends_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDelta_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.MultiLineString, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.LineString} lineString LineString.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.appendLineString = function(lineString) {
|
||||
goog.asserts.assert(lineString.getLayout() == this.layout);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = lineString.getFlatCoordinates().slice();
|
||||
} else {
|
||||
goog.array.extend(
|
||||
this.flatCoordinates, lineString.getFlatCoordinates().slice());
|
||||
}
|
||||
this.ends_.push(this.flatCoordinates.length);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.MultiLineString} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.clone = function() {
|
||||
var multiLineString = new ol.geom.MultiLineString(null);
|
||||
multiLineString.setFlatCoordinates(
|
||||
this.layout, this.flatCoordinates.slice(), this.ends_.slice());
|
||||
return multiLineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
if (this.maxDeltaRevision_ != this.getRevision()) {
|
||||
this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride, 0));
|
||||
this.maxDeltaRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.geom.flat.closest.getsClosestPoint(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride,
|
||||
this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the coordinate at `m` using linear interpolation, or `null` if no
|
||||
* such coordinate exists.
|
||||
*
|
||||
* `opt_extrapolate` controls extrapolation beyond the range of Ms in the
|
||||
* MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
|
||||
* M will return the first coordinate and Ms greater than the last M will
|
||||
* return the last coordinate.
|
||||
*
|
||||
* `opt_interpolate` controls interpolation between consecutive LineStrings
|
||||
* within the MultiLineString. If `opt_interpolate` is `true` the coordinates
|
||||
* will be linearly interpolated between the last coordinate of one LineString
|
||||
* and the first coordinate of the next LineString. If `opt_interpolate` is
|
||||
* `false` then the function will return `null` for Ms falling between
|
||||
* LineStrings.
|
||||
*
|
||||
* @param {number} m M.
|
||||
* @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
|
||||
* @param {boolean=} opt_interpolate Interpolate. Default is `false`.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getCoordinateAtM =
|
||||
function(m, opt_extrapolate, opt_interpolate) {
|
||||
if ((this.layout != ol.geom.GeometryLayout.XYM &&
|
||||
this.layout != ol.geom.GeometryLayout.XYZM) ||
|
||||
this.flatCoordinates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var extrapolate = goog.isDef(opt_extrapolate) ? opt_extrapolate : false;
|
||||
var interpolate = goog.isDef(opt_interpolate) ? opt_interpolate : false;
|
||||
return ol.geom.flat.lineStringsCoordinateAtM(this.flatCoordinates, 0,
|
||||
this.ends_, this.stride, m, extrapolate, interpolate);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<Array.<ol.Coordinate>>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinatess(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Ends.
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getEnds = function() {
|
||||
return this.ends_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @return {ol.geom.LineString} LineString.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getLineString = function(index) {
|
||||
goog.asserts.assert(0 <= index && index < this.ends_.length);
|
||||
if (index < 0 || this.ends_.length <= index) {
|
||||
return null;
|
||||
}
|
||||
var lineString = new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
|
||||
index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
|
||||
return lineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.LineString>} LineStrings.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getLineStrings = function() {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var ends = this.ends_;
|
||||
var layout = this.layout;
|
||||
/** @type {Array.<ol.geom.LineString>} */
|
||||
var lineStrings = [];
|
||||
var offset = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var lineString = new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
|
||||
lineStrings.push(lineString);
|
||||
offset = end;
|
||||
}
|
||||
return lineStrings;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Flat midpoints.
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
|
||||
var midpoints = [];
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var offset = 0;
|
||||
var ends = this.ends_;
|
||||
var stride = this.stride;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var midpoint = ol.geom.flat.interpolate.lineString(
|
||||
flatCoordinates, offset, end, stride, 0.5);
|
||||
goog.array.extend(midpoints, midpoint);
|
||||
offset = end;
|
||||
}
|
||||
return midpoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
var simplifiedFlatCoordinates = [];
|
||||
var simplifiedEnds = [];
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeuckers(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance,
|
||||
simplifiedFlatCoordinates, 0, simplifiedEnds);
|
||||
var simplifiedMultiLineString = new ol.geom.MultiLineString(null);
|
||||
simplifiedMultiLineString.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
|
||||
return simplifiedMultiLineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.MULTI_LINE_STRING;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.lineStrings(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.setCoordinates =
|
||||
function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 2);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
var ends = ol.geom.flat.deflate.coordinatess(
|
||||
this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
|
||||
this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates, ends) {
|
||||
if (goog.isNull(flatCoordinates)) {
|
||||
goog.asserts.assert(!goog.isNull(ends) && ends.length === 0);
|
||||
} else if (ends.length === 0) {
|
||||
goog.asserts.assert(flatCoordinates.length === 0);
|
||||
} else {
|
||||
goog.asserts.assert(flatCoordinates.length == ends[ends.length - 1]);
|
||||
}
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.ends_ = ends;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom.LineString>} lineStrings LineStrings.
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
|
||||
var layout = ol.geom.GeometryLayout.XY;
|
||||
var flatCoordinates = [];
|
||||
var ends = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = lineStrings.length; i < ii; ++i) {
|
||||
var lineString = lineStrings[i];
|
||||
if (i === 0) {
|
||||
layout = lineString.getLayout();
|
||||
} else {
|
||||
// FIXME better handle the case of non-matching layouts
|
||||
goog.asserts.assert(lineString.getLayout() == layout);
|
||||
}
|
||||
goog.array.extend(flatCoordinates, lineString.getFlatCoordinates());
|
||||
ends.push(flatCoordinates.length);
|
||||
}
|
||||
this.setFlatCoordinates(layout, flatCoordinates, ends);
|
||||
};
|
||||
@@ -0,0 +1,193 @@
|
||||
goog.provide('ol.geom.MultiPoint');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.math');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Multi-point geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint = function(coordinates, opt_layout) {
|
||||
goog.base(this);
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
};
|
||||
goog.inherits(ol.geom.MultiPoint, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Point} point Point.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.appendPoint = function(point) {
|
||||
goog.asserts.assert(point.getLayout() == this.layout);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = point.getFlatCoordinates().slice();
|
||||
} else {
|
||||
goog.array.extend(this.flatCoordinates, point.getFlatCoordinates());
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.MultiPoint} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.clone = function() {
|
||||
var multiPoint = new ol.geom.MultiPoint(null);
|
||||
multiPoint.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||
return multiPoint;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var stride = this.stride;
|
||||
var i, ii, j;
|
||||
for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
|
||||
var squaredDistance = ol.math.squaredDistance(
|
||||
x, y, flatCoordinates[i], flatCoordinates[i + 1]);
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
minSquaredDistance = squaredDistance;
|
||||
for (j = 0; j < stride; ++j) {
|
||||
closestPoint[j] = flatCoordinates[i + j];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
}
|
||||
}
|
||||
return minSquaredDistance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.Coordinate>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinates(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @return {ol.geom.Point} Point.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.getPoint = function(index) {
|
||||
var n = goog.isNull(this.flatCoordinates) ?
|
||||
0 : this.flatCoordinates.length / this.stride;
|
||||
goog.asserts.assert(0 <= index && index < n);
|
||||
if (index < 0 || n <= index) {
|
||||
return null;
|
||||
}
|
||||
var point = new ol.geom.Point(null);
|
||||
point.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
|
||||
index * this.stride, (index + 1) * this.stride));
|
||||
return point;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.Point>} Points.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.getPoints = function() {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var layout = this.layout;
|
||||
var stride = this.stride;
|
||||
/** @type {Array.<ol.geom.Point>} */
|
||||
var points = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
|
||||
var point = new ol.geom.Point(null);
|
||||
point.setFlatCoordinates(layout, flatCoordinates.slice(i, i + stride));
|
||||
points.push(point);
|
||||
}
|
||||
return points;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.MULTI_POINT;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var stride = this.stride;
|
||||
var i, ii, x, y;
|
||||
for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
|
||||
x = flatCoordinates[i];
|
||||
y = flatCoordinates[i + 1];
|
||||
if (ol.extent.containsXY(extent, x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.setCoordinates =
|
||||
function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 1);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
|
||||
this.flatCoordinates, 0, coordinates, this.stride);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates) {
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.changed();
|
||||
};
|
||||
@@ -0,0 +1,404 @@
|
||||
goog.provide('ol.geom.MultiPolygon');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.area');
|
||||
goog.require('ol.geom.flat.center');
|
||||
goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interiorpoint');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.orient');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Multi-polygon geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon = function(coordinates, opt_layout) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {Array.<Array.<number>>}
|
||||
* @private
|
||||
*/
|
||||
this.endss_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.flatInteriorPointsRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.flatInteriorPoints_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDelta_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.orientedRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.orientedFlatCoordinates_ = null;
|
||||
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.MultiPolygon, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Polygon} polygon Polygon.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
|
||||
goog.asserts.assert(polygon.getLayout() == this.layout);
|
||||
/** @type {Array.<number>} */
|
||||
var ends;
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = polygon.getFlatCoordinates().slice();
|
||||
ends = polygon.getEnds().slice();
|
||||
this.endss_.push();
|
||||
} else {
|
||||
var offset = this.flatCoordinates.length;
|
||||
goog.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
|
||||
ends = polygon.getEnds().slice();
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
ends[i] += offset;
|
||||
}
|
||||
}
|
||||
this.endss_.push(ends);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.MultiPolygon} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.clone = function() {
|
||||
var multiPolygon = new ol.geom.MultiPolygon(null);
|
||||
multiPolygon.setFlatCoordinates(
|
||||
this.layout, this.flatCoordinates.slice(), this.endss_.slice());
|
||||
return multiPolygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
if (this.maxDeltaRevision_ != this.getRevision()) {
|
||||
this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getssMaxSquaredDelta(
|
||||
this.flatCoordinates, 0, this.endss_, this.stride, 0));
|
||||
this.maxDeltaRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.geom.flat.closest.getssClosestPoint(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
|
||||
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.containsXY = function(x, y) {
|
||||
return ol.geom.flat.contains.linearRingssContainsXY(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Area (on projected plane).
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getArea = function() {
|
||||
return ol.geom.flat.area.linearRingss(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinatesss(
|
||||
this.flatCoordinates, 0, this.endss_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<Array.<number>>} Endss.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getEndss = function() {
|
||||
return this.endss_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Flat interior points.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getFlatInteriorPoints = function() {
|
||||
if (this.flatInteriorPointsRevision_ != this.getRevision()) {
|
||||
var flatCenters = ol.geom.flat.center.linearRingss(
|
||||
this.flatCoordinates, 0, this.endss_, this.stride);
|
||||
this.flatInteriorPoints_ = ol.geom.flat.interiorpoint.linearRingss(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
|
||||
flatCenters);
|
||||
this.flatInteriorPointsRevision_ = this.getRevision();
|
||||
}
|
||||
return this.flatInteriorPoints_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.geom.MultiPoint} Interior points.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
|
||||
var interiorPoints = new ol.geom.MultiPoint(null);
|
||||
interiorPoints.setFlatCoordinates(ol.geom.GeometryLayout.XY,
|
||||
this.getFlatInteriorPoints().slice());
|
||||
return interiorPoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Oriented flat coordinates.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
|
||||
if (this.orientedRevision_ != this.getRevision()) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
if (ol.geom.flat.linearRingssAreOriented(
|
||||
flatCoordinates, 0, this.endss_, this.stride)) {
|
||||
this.orientedFlatCoordinates_ = flatCoordinates;
|
||||
} else {
|
||||
this.orientedFlatCoordinates_ = flatCoordinates.slice();
|
||||
this.orientedFlatCoordinates_.length =
|
||||
ol.geom.flat.orient.orientLinearRingss(
|
||||
this.orientedFlatCoordinates_, 0, this.endss_, this.stride);
|
||||
}
|
||||
this.orientedRevision_ = this.getRevision();
|
||||
}
|
||||
return this.orientedFlatCoordinates_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
var simplifiedFlatCoordinates = [];
|
||||
var simplifiedEndss = [];
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
|
||||
this.flatCoordinates, 0, this.endss_, this.stride,
|
||||
Math.sqrt(squaredTolerance),
|
||||
simplifiedFlatCoordinates, 0, simplifiedEndss);
|
||||
var simplifiedMultiPolygon = new ol.geom.MultiPolygon(null);
|
||||
simplifiedMultiPolygon.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEndss);
|
||||
return simplifiedMultiPolygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @return {ol.geom.Polygon} Polygon.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getPolygon = function(index) {
|
||||
goog.asserts.assert(0 <= index && index < this.endss_.length);
|
||||
if (index < 0 || this.endss_.length <= index) {
|
||||
return null;
|
||||
}
|
||||
var offset;
|
||||
if (index === 0) {
|
||||
offset = 0;
|
||||
} else {
|
||||
var prevEnds = this.endss_[index - 1];
|
||||
offset = prevEnds[prevEnds.length - 1];
|
||||
}
|
||||
var ends = this.endss_[index].slice();
|
||||
var end = ends[ends.length - 1];
|
||||
if (offset !== 0) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
ends[i] -= offset;
|
||||
}
|
||||
}
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
polygon.setFlatCoordinates(
|
||||
this.layout, this.flatCoordinates.slice(offset, end), ends);
|
||||
return polygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.Polygon>} Polygons.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getPolygons = function() {
|
||||
var layout = this.layout;
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var endss = this.endss_;
|
||||
var polygons = [];
|
||||
var offset = 0;
|
||||
var i, ii, j, jj;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i].slice();
|
||||
var end = ends[ends.length - 1];
|
||||
if (offset !== 0) {
|
||||
for (j = 0, jj = ends.length; j < jj; ++j) {
|
||||
ends[j] -= offset;
|
||||
}
|
||||
}
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
polygon.setFlatCoordinates(
|
||||
layout, flatCoordinates.slice(offset, end), ends);
|
||||
polygons.push(polygon);
|
||||
offset = end;
|
||||
}
|
||||
return polygons;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.MULTI_POLYGON;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.linearRingss(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.setCoordinates =
|
||||
function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 3);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
var endss = ol.geom.flat.deflate.coordinatesss(
|
||||
this.flatCoordinates, 0, coordinates, this.stride, this.endss_);
|
||||
if (endss.length === 0) {
|
||||
this.flatCoordinates.length = 0;
|
||||
} else {
|
||||
var lastEnds = endss[endss.length - 1];
|
||||
this.flatCoordinates.length = lastEnds.length === 0 ?
|
||||
0 : lastEnds[lastEnds.length - 1];
|
||||
}
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates, endss) {
|
||||
goog.asserts.assert(!goog.isNull(endss));
|
||||
if (goog.isNull(flatCoordinates) || flatCoordinates.length === 0) {
|
||||
goog.asserts.assert(endss.length === 0);
|
||||
} else {
|
||||
goog.asserts.assert(endss.length > 0);
|
||||
var ends = endss[endss.length - 1];
|
||||
goog.asserts.assert(flatCoordinates.length == ends[ends.length - 1]);
|
||||
}
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.endss_ = endss;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.geom.Polygon>} polygons Polygons.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
|
||||
var layout = ol.geom.GeometryLayout.XY;
|
||||
var flatCoordinates = [];
|
||||
var endss = [];
|
||||
var i, ii, ends;
|
||||
for (i = 0, ii = polygons.length; i < ii; ++i) {
|
||||
var polygon = polygons[i];
|
||||
if (i === 0) {
|
||||
layout = polygon.getLayout();
|
||||
} else {
|
||||
// FIXME better handle the case of non-matching layouts
|
||||
goog.asserts.assert(polygon.getLayout() == layout);
|
||||
}
|
||||
var offset = flatCoordinates.length;
|
||||
ends = polygon.getEnds();
|
||||
var j, jj;
|
||||
for (j = 0, jj = ends.length; j < jj; ++j) {
|
||||
ends[j] += offset;
|
||||
}
|
||||
goog.array.extend(flatCoordinates, polygon.getFlatCoordinates());
|
||||
endss.push(ends);
|
||||
}
|
||||
this.setFlatCoordinates(layout, flatCoordinates, endss);
|
||||
};
|
||||
@@ -0,0 +1,126 @@
|
||||
goog.provide('ol.geom.Point');
|
||||
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.math');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Point geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {ol.Coordinate} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Point = function(coordinates, opt_layout) {
|
||||
goog.base(this);
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
};
|
||||
goog.inherits(ol.geom.Point, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.Point} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Point.prototype.clone = function() {
|
||||
var point = new ol.geom.Point(null);
|
||||
point.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||
return point;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Point.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var squaredDistance = ol.math.squaredDistance(
|
||||
x, y, flatCoordinates[0], flatCoordinates[1]);
|
||||
if (squaredDistance < minSquaredDistance) {
|
||||
var stride = this.stride;
|
||||
var i;
|
||||
for (i = 0; i < stride; ++i) {
|
||||
closestPoint[i] = flatCoordinates[i];
|
||||
}
|
||||
closestPoint.length = stride;
|
||||
return squaredDistance;
|
||||
} else {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Point.prototype.getCoordinates = function() {
|
||||
return goog.isNull(this.flatCoordinates) ? [] : this.flatCoordinates.slice();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Point.prototype.computeExtent = function(extent) {
|
||||
return ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Point.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.POINT;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Point.prototype.intersectsExtent = function(extent) {
|
||||
return ol.extent.containsXY(extent,
|
||||
this.flatCoordinates[0], this.flatCoordinates[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Point.prototype.setCoordinates = function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 0);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
this.flatCoordinates.length = ol.geom.flat.deflate.coordinate(
|
||||
this.flatCoordinates, 0, coordinates, this.stride);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
ol.geom.Point.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.changed();
|
||||
};
|
||||
@@ -0,0 +1,395 @@
|
||||
goog.provide('ol.geom.Polygon');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.SimpleGeometry');
|
||||
goog.require('ol.geom.flat.area');
|
||||
goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interiorpoint');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.orient');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Polygon geometry.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.SimpleGeometry}
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon = function(coordinates, opt_layout) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.ends_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.flatInteriorPointRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.flatInteriorPoint_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDelta_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.orientedRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.orientedFlatCoordinates_ = null;
|
||||
|
||||
this.setCoordinates(coordinates,
|
||||
/** @type {ol.geom.GeometryLayout|undefined} */ (opt_layout));
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.Polygon, ol.geom.SimpleGeometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.LinearRing} linearRing Linear ring.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) {
|
||||
goog.asserts.assert(linearRing.getLayout() == this.layout);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = linearRing.getFlatCoordinates().slice();
|
||||
} else {
|
||||
goog.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
|
||||
}
|
||||
this.ends_.push(this.flatCoordinates.length);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a complete copy of the geometry.
|
||||
* @return {!ol.geom.Polygon} Clone.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.clone = function() {
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
polygon.setFlatCoordinates(
|
||||
this.layout, this.flatCoordinates.slice(), this.ends_.slice());
|
||||
return polygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Polygon.prototype.closestPointXY =
|
||||
function(x, y, closestPoint, minSquaredDistance) {
|
||||
if (minSquaredDistance <
|
||||
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
|
||||
return minSquaredDistance;
|
||||
}
|
||||
if (this.maxDeltaRevision_ != this.getRevision()) {
|
||||
this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride, 0));
|
||||
this.maxDeltaRevision_ = this.getRevision();
|
||||
}
|
||||
return ol.geom.flat.closest.getsClosestPoint(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride,
|
||||
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Polygon.prototype.containsXY = function(x, y) {
|
||||
return ol.geom.flat.contains.linearRingsContainsXY(
|
||||
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Area (on projected plane).
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getArea = function() {
|
||||
return ol.geom.flat.area.linearRings(
|
||||
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<Array.<ol.Coordinate>>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getCoordinates = function() {
|
||||
return ol.geom.flat.inflate.coordinatess(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Ends.
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getEnds = function() {
|
||||
return this.ends_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Interior point.
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getFlatInteriorPoint = function() {
|
||||
if (this.flatInteriorPointRevision_ != this.getRevision()) {
|
||||
var flatCenter = ol.extent.getCenter(this.getExtent());
|
||||
this.flatInteriorPoint_ = ol.geom.flat.interiorpoint.linearRings(
|
||||
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride,
|
||||
flatCenter, 0);
|
||||
this.flatInteriorPointRevision_ = this.getRevision();
|
||||
}
|
||||
return this.flatInteriorPoint_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.geom.Point} Interior point.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getInteriorPoint = function() {
|
||||
return new ol.geom.Point(this.getFlatInteriorPoint());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of rings of the polygon, this includes the exterior
|
||||
* ring and any interior rings.
|
||||
*
|
||||
* @return {number} Number of rings.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getLinearRingCount = function() {
|
||||
return this.ends_.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the Nth linear ring of the polygon geometry. Return `null` if the
|
||||
* given index is out of range.
|
||||
* The exterior linear ring is available at index `0` and the interior rings
|
||||
* at index `1` and beyond.
|
||||
*
|
||||
* @param {number} index Index.
|
||||
* @return {ol.geom.LinearRing} Linear ring.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getLinearRing = function(index) {
|
||||
goog.asserts.assert(0 <= index && index < this.ends_.length);
|
||||
if (index < 0 || this.ends_.length <= index) {
|
||||
return null;
|
||||
}
|
||||
var linearRing = new ol.geom.LinearRing(null);
|
||||
linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
|
||||
index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
|
||||
return linearRing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.LinearRing>} Linear rings.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getLinearRings = function() {
|
||||
var layout = this.layout;
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var ends = this.ends_;
|
||||
var linearRings = [];
|
||||
var offset = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var linearRing = new ol.geom.LinearRing(null);
|
||||
linearRing.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
|
||||
linearRings.push(linearRing);
|
||||
offset = end;
|
||||
}
|
||||
return linearRings;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Oriented flat coordinates.
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() {
|
||||
if (this.orientedRevision_ != this.getRevision()) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
if (ol.geom.flat.orient.linearRingsAreOriented(
|
||||
flatCoordinates, 0, this.ends_, this.stride)) {
|
||||
this.orientedFlatCoordinates_ = flatCoordinates;
|
||||
} else {
|
||||
this.orientedFlatCoordinates_ = flatCoordinates.slice();
|
||||
this.orientedFlatCoordinates_.length =
|
||||
ol.geom.flat.orient.orientLinearRings(
|
||||
this.orientedFlatCoordinates_, 0, this.ends_, this.stride);
|
||||
}
|
||||
this.orientedRevision_ = this.getRevision();
|
||||
}
|
||||
return this.orientedFlatCoordinates_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
var simplifiedFlatCoordinates = [];
|
||||
var simplifiedEnds = [];
|
||||
simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizes(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride,
|
||||
Math.sqrt(squaredTolerance),
|
||||
simplifiedFlatCoordinates, 0, simplifiedEnds);
|
||||
var simplifiedPolygon = new ol.geom.Polygon(null);
|
||||
simplifiedPolygon.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
|
||||
return simplifiedPolygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.POLYGON;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Polygon.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.linearRings(
|
||||
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
|
||||
if (goog.isNull(coordinates)) {
|
||||
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
|
||||
} else {
|
||||
this.setLayout(opt_layout, coordinates, 2);
|
||||
if (goog.isNull(this.flatCoordinates)) {
|
||||
this.flatCoordinates = [];
|
||||
}
|
||||
var ends = ol.geom.flat.deflate.coordinatess(
|
||||
this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
|
||||
this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
*/
|
||||
ol.geom.Polygon.prototype.setFlatCoordinates =
|
||||
function(layout, flatCoordinates, ends) {
|
||||
if (goog.isNull(flatCoordinates)) {
|
||||
goog.asserts.assert(!goog.isNull(ends) && ends.length === 0);
|
||||
} else if (ends.length === 0) {
|
||||
goog.asserts.assert(flatCoordinates.length === 0);
|
||||
} else {
|
||||
goog.asserts.assert(flatCoordinates.length == ends[ends.length - 1]);
|
||||
}
|
||||
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||
this.ends_ = ends;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an approximation of a circle on the surface of a sphere.
|
||||
* @param {ol.Sphere} sphere The sphere.
|
||||
* @param {ol.Coordinate} center Center (`[lon, lat]` in degrees).
|
||||
* @param {number} radius The great-circle distance from the center to
|
||||
* the polygon vertices.
|
||||
* @param {number=} opt_n Optional number of vertices for the resulting
|
||||
* polygon. Default is `32`.
|
||||
* @return {ol.geom.Polygon} The "circular" polygon.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.circular = function(sphere, center, radius, opt_n) {
|
||||
var n = goog.isDef(opt_n) ? opt_n : 32;
|
||||
/** @type {Array.<number>} */
|
||||
var flatCoordinates = [];
|
||||
var i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
goog.array.extend(
|
||||
flatCoordinates, sphere.offset(center, radius, 2 * Math.PI * i / n));
|
||||
}
|
||||
flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
polygon.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
|
||||
return polygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a polygon from an extent. The layout used is `XY`.
|
||||
* @param {ol.Extent} extent The extent.
|
||||
* @return {ol.geom.Polygon} The polygon.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Polygon.fromExtent = function(extent) {
|
||||
var minX = extent[0];
|
||||
var minY = extent[1];
|
||||
var maxX = extent[2];
|
||||
var maxY = extent[3];
|
||||
var flatCoordinates =
|
||||
[minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY];
|
||||
var polygon = new ol.geom.Polygon(null);
|
||||
polygon.setFlatCoordinates(
|
||||
ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
|
||||
return polygon;
|
||||
};
|
||||
@@ -0,0 +1,287 @@
|
||||
goog.provide('ol.geom.SimpleGeometry');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.flat.transform');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; only used for creating subclasses; do not instantiate
|
||||
* in apps, as cannot be rendered.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.geom.Geometry}
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.SimpleGeometry = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.geom.GeometryLayout}
|
||||
*/
|
||||
this.layout = ol.geom.GeometryLayout.XY;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
this.stride = 2;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.flatCoordinates = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} stride Stride.
|
||||
* @private
|
||||
* @return {ol.geom.GeometryLayout} layout Layout.
|
||||
*/
|
||||
ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
|
||||
if (stride == 2) {
|
||||
return ol.geom.GeometryLayout.XY;
|
||||
} else if (stride == 3) {
|
||||
return ol.geom.GeometryLayout.XYZ;
|
||||
} else if (stride == 4) {
|
||||
return ol.geom.GeometryLayout.XYZM;
|
||||
} else {
|
||||
goog.asserts.fail('unsupported stride: ' + stride);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @private
|
||||
* @return {number} Stride.
|
||||
*/
|
||||
ol.geom.SimpleGeometry.getStrideForLayout_ = function(layout) {
|
||||
if (layout == ol.geom.GeometryLayout.XY) {
|
||||
return 2;
|
||||
} else if (layout == ol.geom.GeometryLayout.XYZ) {
|
||||
return 3;
|
||||
} else if (layout == ol.geom.GeometryLayout.XYM) {
|
||||
return 3;
|
||||
} else if (layout == ol.geom.GeometryLayout.XYZM) {
|
||||
return 4;
|
||||
} else {
|
||||
goog.asserts.fail('unsupported layout: ' + layout);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.containsXY = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.computeExtent = function(extent) {
|
||||
return ol.extent.createOrUpdateFromFlatCoordinates(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} First coordinate.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getFirstCoordinate = function() {
|
||||
return this.flatCoordinates.slice(0, this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Flat coordinates.
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
|
||||
return this.flatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Last point.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getLastCoordinate = function() {
|
||||
return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.geom.GeometryLayout} Layout.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getLayout = function() {
|
||||
return this.layout;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry =
|
||||
function(squaredTolerance) {
|
||||
if (this.simplifiedGeometryRevision != this.getRevision()) {
|
||||
goog.object.clear(this.simplifiedGeometryCache);
|
||||
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
|
||||
this.simplifiedGeometryRevision = this.getRevision();
|
||||
}
|
||||
// If squaredTolerance is negative or if we know that simplification will not
|
||||
// have any effect then just return this.
|
||||
if (squaredTolerance < 0 ||
|
||||
(this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
|
||||
squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
|
||||
return this;
|
||||
}
|
||||
var key = squaredTolerance.toString();
|
||||
if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
|
||||
return this.simplifiedGeometryCache[key];
|
||||
} else {
|
||||
var simplifiedGeometry =
|
||||
this.getSimplifiedGeometryInternal(squaredTolerance);
|
||||
var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
|
||||
if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
|
||||
this.simplifiedGeometryCache[key] = simplifiedGeometry;
|
||||
return simplifiedGeometry;
|
||||
} else {
|
||||
// Simplification did not actually remove any coordinates. We now know
|
||||
// that any calls to getSimplifiedGeometry with a squaredTolerance less
|
||||
// than or equal to the current squaredTolerance will also not have any
|
||||
// effect. This allows us to short circuit simplification (saving CPU
|
||||
// cycles) and prevents the cache of simplified geometries from filling
|
||||
// up with useless identical copies of this geometry (saving memory).
|
||||
this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {ol.geom.SimpleGeometry} Simplified geometry.
|
||||
* @protected
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal =
|
||||
function(squaredTolerance) {
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Stride.
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.getStride = function() {
|
||||
return this.stride;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @protected
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal =
|
||||
function(layout, flatCoordinates) {
|
||||
this.stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
|
||||
this.layout = layout;
|
||||
this.flatCoordinates = flatCoordinates;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryLayout|undefined} layout Layout.
|
||||
* @param {Array} coordinates Coordinates.
|
||||
* @param {number} nesting Nesting.
|
||||
* @protected
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.setLayout =
|
||||
function(layout, coordinates, nesting) {
|
||||
/** @type {number} */
|
||||
var stride;
|
||||
if (goog.isDef(layout)) {
|
||||
stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
|
||||
} else {
|
||||
var i;
|
||||
for (i = 0; i < nesting; ++i) {
|
||||
if (coordinates.length === 0) {
|
||||
this.layout = ol.geom.GeometryLayout.XY;
|
||||
this.stride = 2;
|
||||
return;
|
||||
} else {
|
||||
coordinates = /** @type {Array} */ (coordinates[0]);
|
||||
}
|
||||
}
|
||||
stride = (/** @type {Array} */ (coordinates)).length;
|
||||
layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
|
||||
}
|
||||
this.layout = layout;
|
||||
this.stride = stride;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.applyTransform = function(transformFn) {
|
||||
if (!goog.isNull(this.flatCoordinates)) {
|
||||
transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translate the geometry.
|
||||
* @param {number} deltaX Delta X.
|
||||
* @param {number} deltaY Delta Y.
|
||||
* @api
|
||||
*/
|
||||
ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
|
||||
var flatCoordinates = this.getFlatCoordinates();
|
||||
if (!goog.isNull(flatCoordinates)) {
|
||||
var stride = this.getStride();
|
||||
ol.geom.flat.transform.translate(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride,
|
||||
deltaX, deltaY, flatCoordinates);
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
|
||||
* @param {goog.vec.Mat4.Number} transform Transform.
|
||||
* @param {Array.<number>=} opt_dest Destination.
|
||||
* @return {Array.<number>} Transformed flat coordinates.
|
||||
*/
|
||||
ol.geom.transformSimpleGeometry2D =
|
||||
function(simpleGeometry, transform, opt_dest) {
|
||||
var flatCoordinates = simpleGeometry.getFlatCoordinates();
|
||||
if (goog.isNull(flatCoordinates)) {
|
||||
return null;
|
||||
} else {
|
||||
var stride = simpleGeometry.getStride();
|
||||
return ol.geom.flat.transform.transform2D(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride,
|
||||
transform, opt_dest);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,435 @@
|
||||
goog.provide('ol.Graticule');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.math');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.flat.geodesic');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.render.EventType');
|
||||
goog.require('ol.style.Stroke');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {olx.GraticuleOptions=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
ol.Graticule = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {ol.Map}
|
||||
* @private
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @type {ol.proj.Projection}
|
||||
* @private
|
||||
*/
|
||||
this.projection_ = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxLat_ = Infinity;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxLon_ = Infinity;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.minLat_ = -Infinity;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.minLon_ = -Infinity;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.targetSize_ = goog.isDef(options.targetSize) ?
|
||||
options.targetSize : 100;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxLines_ = goog.isDef(options.maxLines) ? options.maxLines : 100;
|
||||
goog.asserts.assert(this.maxLines_ > 0);
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.geom.LineString>}
|
||||
* @private
|
||||
*/
|
||||
this.meridians_ = [];
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.geom.LineString>}
|
||||
* @private
|
||||
*/
|
||||
this.parallels_ = [];
|
||||
|
||||
/**
|
||||
* @type {ol.style.Stroke}
|
||||
* @private
|
||||
*/
|
||||
this.strokeStyle_ = goog.isDef(options.strokeStyle) ?
|
||||
options.strokeStyle : ol.Graticule.DEFAULT_STROKE_STYLE_;
|
||||
|
||||
/**
|
||||
* @type {ol.TransformFunction|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.fromLonLatTransform_ = undefined;
|
||||
|
||||
/**
|
||||
* @type {ol.TransformFunction|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.toLonLatTransform_ = undefined;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.projectionCenterLonLat_ = null;
|
||||
|
||||
this.setMap(goog.isDef(options.map) ? options.map : null);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.style.Stroke}
|
||||
* @private
|
||||
* @const
|
||||
*/
|
||||
ol.Graticule.DEFAULT_STROKE_STYLE_ = new ol.style.Stroke({
|
||||
color: 'rgba(0,0,0,0.2)'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* TODO can be configurable
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.intervals_ = [90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05,
|
||||
0.01, 0.005, 0.002, 0.001];
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} lon Longitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} index Index.
|
||||
* @return {number} Index.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.addMeridian_ =
|
||||
function(lon, squaredTolerance, extent, index) {
|
||||
var lineString = this.getMeridian_(lon, squaredTolerance, index);
|
||||
if (ol.extent.intersects(lineString.getExtent(), extent)) {
|
||||
this.meridians_[index++] = lineString;
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} lat Latitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} index Index.
|
||||
* @return {number} Index.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.addParallel_ =
|
||||
function(lat, squaredTolerance, extent, index) {
|
||||
var lineString = this.getParallel_(lat, squaredTolerance, index);
|
||||
if (ol.extent.intersects(lineString.getExtent(), extent)) {
|
||||
this.parallels_[index++] = lineString;
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.createGraticule_ =
|
||||
function(extent, center, resolution, squaredTolerance) {
|
||||
|
||||
var interval = this.getInterval_(resolution);
|
||||
if (interval == -1) {
|
||||
this.meridians_.length = this.parallels_.length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var centerLonLat = this.toLonLatTransform_(center);
|
||||
var centerLon = centerLonLat[0];
|
||||
var centerLat = centerLonLat[1];
|
||||
var maxLines = this.maxLines_;
|
||||
var cnt, idx, lat, lon;
|
||||
|
||||
// Create meridians
|
||||
|
||||
centerLon = Math.floor(centerLon / interval) * interval;
|
||||
lon = goog.math.clamp(centerLon, this.minLon_, this.maxLon_);
|
||||
|
||||
idx = this.addMeridian_(lon, squaredTolerance, extent, 0);
|
||||
|
||||
cnt = 0;
|
||||
while (lon != this.minLon_ && cnt++ < maxLines) {
|
||||
lon = Math.max(lon - interval, this.minLon_);
|
||||
idx = this.addMeridian_(lon, squaredTolerance, extent, idx);
|
||||
}
|
||||
|
||||
lon = goog.math.clamp(centerLon, this.minLon_, this.maxLon_);
|
||||
|
||||
cnt = 0;
|
||||
while (lon != this.maxLon_ && cnt++ < maxLines) {
|
||||
lon = Math.min(lon + interval, this.maxLon_);
|
||||
idx = this.addMeridian_(lon, squaredTolerance, extent, idx);
|
||||
}
|
||||
|
||||
this.meridians_.length = idx;
|
||||
|
||||
// Create parallels
|
||||
|
||||
centerLat = Math.floor(centerLat / interval) * interval;
|
||||
lat = goog.math.clamp(centerLat, this.minLat_, this.maxLat_);
|
||||
|
||||
idx = this.addParallel_(lat, squaredTolerance, extent, 0);
|
||||
|
||||
cnt = 0;
|
||||
while (lat != this.minLat_ && cnt++ < maxLines) {
|
||||
lat = Math.max(lat - interval, this.minLat_);
|
||||
idx = this.addParallel_(lat, squaredTolerance, extent, idx);
|
||||
}
|
||||
|
||||
lat = goog.math.clamp(centerLat, this.minLat_, this.maxLat_);
|
||||
|
||||
cnt = 0;
|
||||
while (lat != this.maxLat_ && cnt++ < maxLines) {
|
||||
lat = Math.min(lat + interval, this.maxLat_);
|
||||
idx = this.addParallel_(lat, squaredTolerance, extent, idx);
|
||||
}
|
||||
|
||||
this.parallels_.length = idx;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {number} The interval in degrees.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.getInterval_ = function(resolution) {
|
||||
var centerLon = this.projectionCenterLonLat_[0];
|
||||
var centerLat = this.projectionCenterLonLat_[1];
|
||||
var interval = -1;
|
||||
var i, ii, delta, dist;
|
||||
var target = Math.pow(this.targetSize_ * resolution, 2);
|
||||
/** @type {Array.<number>} **/
|
||||
var p1 = [];
|
||||
/** @type {Array.<number>} **/
|
||||
var p2 = [];
|
||||
for (i = 0, ii = ol.Graticule.intervals_.length; i < ii; ++i) {
|
||||
delta = ol.Graticule.intervals_[i] / 2;
|
||||
p1[0] = centerLon - delta;
|
||||
p1[1] = centerLat - delta;
|
||||
p2[0] = centerLon + delta;
|
||||
p2[1] = centerLat + delta;
|
||||
this.fromLonLatTransform_(p1, p1);
|
||||
this.fromLonLatTransform_(p2, p2);
|
||||
dist = Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2);
|
||||
if (dist <= target) {
|
||||
break;
|
||||
}
|
||||
interval = ol.Graticule.intervals_[i];
|
||||
}
|
||||
return interval;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} The map.
|
||||
* @api
|
||||
*/
|
||||
ol.Graticule.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} lon Longitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {ol.geom.LineString} The meridian line string.
|
||||
* @param {number} index Index.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.getMeridian_ = function(lon, squaredTolerance, index) {
|
||||
goog.asserts.assert(lon >= this.minLon_);
|
||||
goog.asserts.assert(lon <= this.maxLon_);
|
||||
var flatCoordinates = ol.geom.flat.geodesic.meridian(lon,
|
||||
this.minLat_, this.maxLat_, this.projection_, squaredTolerance);
|
||||
goog.asserts.assert(flatCoordinates.length > 0);
|
||||
var lineString = goog.isDef(this.meridians_[index]) ?
|
||||
this.meridians_[index] : new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
|
||||
return lineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.LineString>} The meridians.
|
||||
* @api
|
||||
*/
|
||||
ol.Graticule.prototype.getMeridians = function() {
|
||||
return this.meridians_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} lat Latitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {ol.geom.LineString} The parallel line string.
|
||||
* @param {number} index Index.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.getParallel_ = function(lat, squaredTolerance, index) {
|
||||
goog.asserts.assert(lat >= this.minLat_);
|
||||
goog.asserts.assert(lat <= this.maxLat_);
|
||||
var flatCoordinates = ol.geom.flat.geodesic.parallel(lat,
|
||||
this.minLon_, this.maxLon_, this.projection_, squaredTolerance);
|
||||
goog.asserts.assert(flatCoordinates.length > 0);
|
||||
var lineString = goog.isDef(this.parallels_[index]) ?
|
||||
this.parallels_[index] : new ol.geom.LineString(null);
|
||||
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
|
||||
return lineString;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.geom.LineString>} The parallels.
|
||||
* @api
|
||||
*/
|
||||
ol.Graticule.prototype.getParallels = function() {
|
||||
return this.parallels_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.render.Event} e Event.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.handlePostCompose_ = function(e) {
|
||||
var vectorContext = e.vectorContext;
|
||||
var frameState = e.frameState;
|
||||
var extent = frameState.extent;
|
||||
var viewState = frameState.viewState;
|
||||
var center = viewState.center;
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var squaredTolerance =
|
||||
resolution * resolution / (4 * pixelRatio * pixelRatio);
|
||||
|
||||
var updateProjectionInfo = goog.isNull(this.projection_) ||
|
||||
!ol.proj.equivalent(this.projection_, projection);
|
||||
|
||||
if (updateProjectionInfo) {
|
||||
this.updateProjectionInfo_(projection);
|
||||
}
|
||||
|
||||
this.createGraticule_(extent, center, resolution, squaredTolerance);
|
||||
|
||||
// Draw the lines
|
||||
vectorContext.setFillStrokeStyle(null, this.strokeStyle_);
|
||||
var i, l, line;
|
||||
for (i = 0, l = this.meridians_.length; i < l; ++i) {
|
||||
line = this.meridians_[i];
|
||||
vectorContext.drawLineStringGeometry(line, null);
|
||||
}
|
||||
for (i = 0, l = this.parallels_.length; i < l; ++i) {
|
||||
line = this.parallels_[i];
|
||||
vectorContext.drawLineStringGeometry(line, null);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.proj.Projection} projection Projection.
|
||||
* @private
|
||||
*/
|
||||
ol.Graticule.prototype.updateProjectionInfo_ = function(projection) {
|
||||
goog.asserts.assert(!goog.isNull(projection));
|
||||
|
||||
var extent = projection.getExtent();
|
||||
var worldExtent = projection.getWorldExtent();
|
||||
var maxLat = worldExtent[3];
|
||||
var maxLon = worldExtent[2];
|
||||
var minLat = worldExtent[1];
|
||||
var minLon = worldExtent[0];
|
||||
|
||||
goog.asserts.assert(!goog.isNull(extent));
|
||||
goog.asserts.assert(goog.isDef(maxLat));
|
||||
goog.asserts.assert(goog.isDef(maxLon));
|
||||
goog.asserts.assert(goog.isDef(minLat));
|
||||
goog.asserts.assert(goog.isDef(minLon));
|
||||
|
||||
this.maxLat_ = maxLat;
|
||||
this.maxLon_ = maxLon;
|
||||
this.minLat_ = minLat;
|
||||
this.minLon_ = minLon;
|
||||
|
||||
var epsg4326Projection = ol.proj.get('EPSG:4326');
|
||||
|
||||
this.fromLonLatTransform_ = ol.proj.getTransform(
|
||||
epsg4326Projection, projection);
|
||||
|
||||
this.toLonLatTransform_ = ol.proj.getTransform(
|
||||
projection, epsg4326Projection);
|
||||
|
||||
this.projectionCenterLonLat_ = this.toLonLatTransform_(
|
||||
ol.extent.getCenter(extent));
|
||||
|
||||
this.projection_ = projection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @api
|
||||
*/
|
||||
ol.Graticule.prototype.setMap = function(map) {
|
||||
if (!goog.isNull(this.map_)) {
|
||||
this.map_.un(ol.render.EventType.POSTCOMPOSE,
|
||||
this.handlePostCompose_, this);
|
||||
this.map_.render();
|
||||
}
|
||||
if (!goog.isNull(map)) {
|
||||
map.on(ol.render.EventType.POSTCOMPOSE,
|
||||
this.handlePostCompose_, this);
|
||||
map.render();
|
||||
}
|
||||
this.map_ = map;
|
||||
};
|
||||
@@ -0,0 +1,150 @@
|
||||
goog.provide('ol.has');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('ol');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* The ratio between physical pixels and device-independent pixels
|
||||
* (dips) on the device (`window.devicePixelRatio`).
|
||||
* @const
|
||||
* @type {number}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.DEVICE_PIXEL_RATIO = goog.global.devicePixelRatio || 1;
|
||||
|
||||
|
||||
/**
|
||||
* True if the browser supports ArrayBuffers.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.has.ARRAY_BUFFER = 'ArrayBuffer' in goog.global;
|
||||
|
||||
|
||||
/**
|
||||
* True if the browser's Canvas implementation implements {get,set}LineDash.
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.has.CANVAS_LINE_DASH = false;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports Canvas.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.CANVAS = ol.ENABLE_CANVAS && (
|
||||
/**
|
||||
* @return {boolean} Canvas supported.
|
||||
*/
|
||||
function() {
|
||||
if (!('HTMLCanvasElement' in goog.global)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
var context = ol.dom.createCanvasContext2D();
|
||||
if (goog.isNull(context)) {
|
||||
return false;
|
||||
} else {
|
||||
if (goog.isDef(context.setLineDash)) {
|
||||
ol.has.CANVAS_LINE_DASH = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if DeviceOrientation is supported in the user's browser.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.DEVICE_ORIENTATION = 'DeviceOrientationEvent' in goog.global;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports DOM.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.has.DOM = ol.ENABLE_DOM;
|
||||
|
||||
|
||||
/**
|
||||
* Is HTML5 geolocation supported in the current browser?
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.GEOLOCATION = 'geolocation' in goog.global.navigator;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports touch events.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.TOUCH = ol.ASSUME_TOUCH || 'ontouchstart' in goog.global;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports pointer events.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.has.POINTER = 'PointerEvent' in goog.global;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports ms pointer events (IE 10).
|
||||
* @const
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.has.MSPOINTER = !!(goog.global.navigator.msPointerEnabled);
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports WebGL.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol.has.WEBGL;
|
||||
|
||||
|
||||
(function() {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
var hasWebGL = false;
|
||||
var textureSize;
|
||||
var /** @type {Array.<string>} */ extensions = [];
|
||||
|
||||
if ('WebGLRenderingContext' in goog.global) {
|
||||
try {
|
||||
var canvas = /** @type {HTMLCanvasElement} */
|
||||
(goog.dom.createElement(goog.dom.TagName.CANVAS));
|
||||
var gl = ol.webgl.getContext(canvas, {
|
||||
failIfMajorPerformanceCaveat: true
|
||||
});
|
||||
if (!goog.isNull(gl)) {
|
||||
hasWebGL = true;
|
||||
textureSize = /** @type {number} */
|
||||
(gl.getParameter(gl.MAX_TEXTURE_SIZE));
|
||||
extensions = gl.getSupportedExtensions();
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
ol.has.WEBGL = hasWebGL;
|
||||
ol.WEBGL_EXTENSIONS = extensions;
|
||||
ol.WEBGL_MAX_TEXTURE_SIZE = textureSize;
|
||||
}
|
||||
})();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user