--- /srv/reproducible-results/rbuild-debian/r-b-build.unXvPqxv/b1/openlayers_2.13.1+ds2-10_amd64.changes
+++ /srv/reproducible-results/rbuild-debian/r-b-build.unXvPqxv/b2/openlayers_2.13.1+ds2-10_amd64.changes
├── Files
│ @@ -1,2 +1,2 @@
│
│ - 2c336306eaba9a29f846b73cd6e694e2 708360 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb
│ + 9e03fc7cf236545d46cdaa71cc8ce128 715916 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb
├── libjs-openlayers_2.13.1+ds2-10_all.deb
│ ├── file list
│ │ @@ -1,3 +1,3 @@
│ │ -rw-r--r-- 0 0 0 4 2023-01-14 13:27:41.000000 debian-binary
│ │ -rw-r--r-- 0 0 0 3680 2023-01-14 13:27:41.000000 control.tar.xz
│ │ --rw-r--r-- 0 0 0 704488 2023-01-14 13:27:41.000000 data.tar.xz
│ │ +-rw-r--r-- 0 0 0 712044 2023-01-14 13:27:41.000000 data.tar.xz
│ ├── control.tar.xz
│ │ ├── control.tar
│ │ │ ├── ./md5sums
│ │ │ │ ├── ./md5sums
│ │ │ │ │┄ Files differ
│ ├── data.tar.xz
│ │ ├── data.tar
│ │ │ ├── ./usr/share/javascript/openlayers/OpenLayers.js
│ │ │ │ ├── js-beautify {}
│ │ │ │ │ @@ -136,14 +136,647 @@
│ │ │ │ │ * (code)
│ │ │ │ │ *
│ │ │ │ │ * (end code)
│ │ │ │ │ */
│ │ │ │ │ ImgPath: ''
│ │ │ │ │ };
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ + OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/SingleFile.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constructor: OpenLayers.Class
│ │ │ │ │ + * Base class used to construct all other classes. Includes support for
│ │ │ │ │ + * multiple inheritance.
│ │ │ │ │ + *
│ │ │ │ │ + * This constructor is new in OpenLayers 2.5. At OpenLayers 3.0, the old
│ │ │ │ │ + * syntax for creating classes and dealing with inheritance
│ │ │ │ │ + * will be removed.
│ │ │ │ │ + *
│ │ │ │ │ + * To create a new OpenLayers-style class, use the following syntax:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * var MyClass = OpenLayers.Class(prototype);
│ │ │ │ │ + * (end)
│ │ │ │ │ + *
│ │ │ │ │ + * To create a new OpenLayers-style class with multiple inheritance, use the
│ │ │ │ │ + * following syntax:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * var MyClass = OpenLayers.Class(Class1, Class2, prototype);
│ │ │ │ │ + * (end)
│ │ │ │ │ + *
│ │ │ │ │ + * Note that instanceof reflection will only reveal Class1 as superclass.
│ │ │ │ │ + *
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Class = function() {
│ │ │ │ │ + var len = arguments.length;
│ │ │ │ │ + var P = arguments[0];
│ │ │ │ │ + var F = arguments[len - 1];
│ │ │ │ │ +
│ │ │ │ │ + var C = typeof F.initialize == "function" ?
│ │ │ │ │ + F.initialize :
│ │ │ │ │ + function() {
│ │ │ │ │ + P.prototype.initialize.apply(this, arguments);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + if (len > 1) {
│ │ │ │ │ + var newArgs = [C, P].concat(
│ │ │ │ │ + Array.prototype.slice.call(arguments).slice(1, len - 1), F);
│ │ │ │ │ + OpenLayers.inherit.apply(null, newArgs);
│ │ │ │ │ + } else {
│ │ │ │ │ + C.prototype = F;
│ │ │ │ │ + }
│ │ │ │ │ + return C;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Function: OpenLayers.inherit
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * C - {Object} the class that inherits
│ │ │ │ │ + * P - {Object} the superclass to inherit from
│ │ │ │ │ + *
│ │ │ │ │ + * In addition to the mandatory C and P parameters, an arbitrary number of
│ │ │ │ │ + * objects can be passed, which will extend C.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.inherit = function(C, P) {
│ │ │ │ │ + var F = function() {};
│ │ │ │ │ + F.prototype = P.prototype;
│ │ │ │ │ + C.prototype = new F;
│ │ │ │ │ + var i, l, o;
│ │ │ │ │ + for (i = 2, l = arguments.length; i < l; i++) {
│ │ │ │ │ + o = arguments[i];
│ │ │ │ │ + if (typeof o === "function") {
│ │ │ │ │ + o = o.prototype;
│ │ │ │ │ + }
│ │ │ │ │ + OpenLayers.Util.extend(C.prototype, o);
│ │ │ │ │ + }
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIFunction: extend
│ │ │ │ │ + * Copy all properties of a source object to a destination object. Modifies
│ │ │ │ │ + * the passed in destination object. Any properties on the source object
│ │ │ │ │ + * that are set to undefined will not be (re)set on the destination object.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * destination - {Object} The object that will be modified
│ │ │ │ │ + * source - {Object} The object with properties to be set on the destination
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} The destination object.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Util = OpenLayers.Util || {};
│ │ │ │ │ +OpenLayers.Util.extend = function(destination, source) {
│ │ │ │ │ + destination = destination || {};
│ │ │ │ │ + if (source) {
│ │ │ │ │ + for (var property in source) {
│ │ │ │ │ + var value = source[property];
│ │ │ │ │ + if (value !== undefined) {
│ │ │ │ │ + destination[property] = value;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * IE doesn't include the toString property when iterating over an object's
│ │ │ │ │ + * properties with the for(property in object) syntax. Explicitly check if
│ │ │ │ │ + * the source has its own toString property.
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ + /*
│ │ │ │ │ + * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
│ │ │ │ │ + * prototype object" when calling hawOwnProperty if the source object
│ │ │ │ │ + * is an instance of window.Event.
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ + var sourceIsEvt = typeof window.Event == "function" &&
│ │ │ │ │ + source instanceof window.Event;
│ │ │ │ │ +
│ │ │ │ │ + if (!sourceIsEvt &&
│ │ │ │ │ + source.hasOwnProperty && source.hasOwnProperty("toString")) {
│ │ │ │ │ + destination.toString = source.toString;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return destination;
│ │ │ │ │ +};
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Geometry.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Geometry
│ │ │ │ │ + * A Geometry is a description of a geographic object. Create an instance of
│ │ │ │ │ + * this class with the constructor. This is a base class,
│ │ │ │ │ + * typical geometry types are described by subclasses of this class.
│ │ │ │ │ + *
│ │ │ │ │ + * Note that if you use the method, you must
│ │ │ │ │ + * explicitly include the OpenLayers.Format.WKT in your build.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String} A unique identifier for this geometry.
│ │ │ │ │ + */
│ │ │ │ │ + id: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: parent
│ │ │ │ │ + * {}This is set when a Geometry is added as component
│ │ │ │ │ + * of another geometry
│ │ │ │ │ + */
│ │ │ │ │ + parent: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: bounds
│ │ │ │ │ + * {} The bounds of this geometry
│ │ │ │ │ + */
│ │ │ │ │ + bounds: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry
│ │ │ │ │ + * Creates a geometry object.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function() {
│ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroy
│ │ │ │ │ + * Destroy this geometry.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + this.id = null;
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: clone
│ │ │ │ │ + * Create a clone of this geometry. Does not set any non-standard
│ │ │ │ │ + * properties of the cloned geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An exact clone of this geometry.
│ │ │ │ │ + */
│ │ │ │ │ + clone: function() {
│ │ │ │ │ + return new OpenLayers.Geometry();
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: setBounds
│ │ │ │ │ + * Set the bounds for this Geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * bounds - {}
│ │ │ │ │ + */
│ │ │ │ │ + setBounds: function(bounds) {
│ │ │ │ │ + if (bounds) {
│ │ │ │ │ + this.bounds = bounds.clone();
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: clearBounds
│ │ │ │ │ + * Nullify this components bounds and that of its parent as well.
│ │ │ │ │ + */
│ │ │ │ │ + clearBounds: function() {
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ + if (this.parent) {
│ │ │ │ │ + this.parent.clearBounds();
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: extendBounds
│ │ │ │ │ + * Extend the existing bounds to include the new bounds.
│ │ │ │ │ + * If geometry's bounds is not yet set, then set a new Bounds.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * newBounds - {}
│ │ │ │ │ + */
│ │ │ │ │ + extendBounds: function(newBounds) {
│ │ │ │ │ + var bounds = this.getBounds();
│ │ │ │ │ + if (!bounds) {
│ │ │ │ │ + this.setBounds(newBounds);
│ │ │ │ │ + } else {
│ │ │ │ │ + this.bounds.extend(newBounds);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getBounds
│ │ │ │ │ + * Get the bounds for this Geometry. If bounds is not set, it
│ │ │ │ │ + * is calculated again, this makes queries faster.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │ + getBounds: function() {
│ │ │ │ │ + if (this.bounds == null) {
│ │ │ │ │ + this.calculateBounds();
│ │ │ │ │ + }
│ │ │ │ │ + return this.bounds;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: calculateBounds
│ │ │ │ │ + * Recalculate the bounds for the geometry.
│ │ │ │ │ + */
│ │ │ │ │ + calculateBounds: function() {
│ │ │ │ │ + //
│ │ │ │ │ + // This should be overridden by subclasses.
│ │ │ │ │ + //
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: distanceTo
│ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane).
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Optional properties for configuring the distance
│ │ │ │ │ + * calculation.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options depend on the specific geometry type.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Number | Object} The distance between this geometry and the target.
│ │ │ │ │ + * If details is true, the return will be an object with distance,
│ │ │ │ │ + * x0, y0, x1, and x2 properties. The x0 and y0 properties represent
│ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1
│ │ │ │ │ + * properties represent the coordinates of the closest point on the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ + */
│ │ │ │ │ + distanceTo: function(geometry, options) {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getVertices
│ │ │ │ │ + * Return a list of all points in this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are
│ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not
│ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will
│ │ │ │ │ + * be returned.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} A list of all vertices in the geometry.
│ │ │ │ │ + */
│ │ │ │ │ + getVertices: function(nodes) {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: atPoint
│ │ │ │ │ + * Note - This is only an approximation based on the bounds of the
│ │ │ │ │ + * geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * lonlat - {|Object} OpenLayers.LonLat or an
│ │ │ │ │ + * object with a 'lon' and 'lat' properties.
│ │ │ │ │ + * toleranceLon - {float} Optional tolerance in Geometric Coords
│ │ │ │ │ + * toleranceLat - {float} Optional tolerance in Geographic Coords
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Whether or not the geometry is at the specified location
│ │ │ │ │ + */
│ │ │ │ │ + atPoint: function(lonlat, toleranceLon, toleranceLat) {
│ │ │ │ │ + var atPoint = false;
│ │ │ │ │ + var bounds = this.getBounds();
│ │ │ │ │ + if ((bounds != null) && (lonlat != null)) {
│ │ │ │ │ +
│ │ │ │ │ + var dX = (toleranceLon != null) ? toleranceLon : 0;
│ │ │ │ │ + var dY = (toleranceLat != null) ? toleranceLat : 0;
│ │ │ │ │ +
│ │ │ │ │ + var toleranceBounds =
│ │ │ │ │ + new OpenLayers.Bounds(this.bounds.left - dX,
│ │ │ │ │ + this.bounds.bottom - dY,
│ │ │ │ │ + this.bounds.right + dX,
│ │ │ │ │ + this.bounds.top + dY);
│ │ │ │ │ +
│ │ │ │ │ + atPoint = toleranceBounds.containsLonLat(lonlat);
│ │ │ │ │ + }
│ │ │ │ │ + return atPoint;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: getLength
│ │ │ │ │ + * Calculate the length of this geometry. This method is defined in
│ │ │ │ │ + * subclasses.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The length of the collection by summing its parts
│ │ │ │ │ + */
│ │ │ │ │ + getLength: function() {
│ │ │ │ │ + //to be overridden by geometries that actually have a length
│ │ │ │ │ + //
│ │ │ │ │ + return 0.0;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: getArea
│ │ │ │ │ + * Calculate the area of this geometry. This method is defined in subclasses.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The area of the collection by summing its parts
│ │ │ │ │ + */
│ │ │ │ │ + getArea: function() {
│ │ │ │ │ + //to be overridden by geometries that actually have an area
│ │ │ │ │ + //
│ │ │ │ │ + return 0.0;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getCentroid
│ │ │ │ │ + * Calculate the centroid of this geometry. This method is defined in subclasses.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} The centroid of the collection
│ │ │ │ │ + */
│ │ │ │ │ + getCentroid: function() {
│ │ │ │ │ + return null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: toString
│ │ │ │ │ + * Returns a text representation of the geometry. If the WKT format is
│ │ │ │ │ + * included in a build, this will be the Well-Known Text
│ │ │ │ │ + * representation.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} String representation of this geometry.
│ │ │ │ │ + */
│ │ │ │ │ + toString: function() {
│ │ │ │ │ + var string;
│ │ │ │ │ + if (OpenLayers.Format && OpenLayers.Format.WKT) {
│ │ │ │ │ + string = OpenLayers.Format.WKT.prototype.write(
│ │ │ │ │ + new OpenLayers.Feature.Vector(this)
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + string = Object.prototype.toString.call(this);
│ │ │ │ │ + }
│ │ │ │ │ + return string;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Function: OpenLayers.Geometry.fromWKT
│ │ │ │ │ + * Generate a geometry given a Well-Known Text string. For this method to
│ │ │ │ │ + * work, you must include the OpenLayers.Format.WKT in your build
│ │ │ │ │ + * explicitly.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * wkt - {String} A string representing the geometry in Well-Known Text.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} A geometry of the appropriate class.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.fromWKT = function(wkt) {
│ │ │ │ │ + var geom;
│ │ │ │ │ + if (OpenLayers.Format && OpenLayers.Format.WKT) {
│ │ │ │ │ + var format = OpenLayers.Geometry.fromWKT.format;
│ │ │ │ │ + if (!format) {
│ │ │ │ │ + format = new OpenLayers.Format.WKT();
│ │ │ │ │ + OpenLayers.Geometry.fromWKT.format = format;
│ │ │ │ │ + }
│ │ │ │ │ + var result = format.read(wkt);
│ │ │ │ │ + if (result instanceof OpenLayers.Feature.Vector) {
│ │ │ │ │ + geom = result.geometry;
│ │ │ │ │ + } else if (OpenLayers.Util.isArray(result)) {
│ │ │ │ │ + var len = result.length;
│ │ │ │ │ + var components = new Array(len);
│ │ │ │ │ + for (var i = 0; i < len; ++i) {
│ │ │ │ │ + components[i] = result[i].geometry;
│ │ │ │ │ + }
│ │ │ │ │ + geom = new OpenLayers.Geometry.Collection(components);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return geom;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Method: OpenLayers.Geometry.segmentsIntersect
│ │ │ │ │ + * Determine whether two line segments intersect. Optionally calculates
│ │ │ │ │ + * and returns the intersection point. This function is optimized for
│ │ │ │ │ + * cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those
│ │ │ │ │ + * obvious cases where there is no intersection, the function should
│ │ │ │ │ + * not be called.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * seg1 - {Object} Object representing a segment with properties x1, y1, x2,
│ │ │ │ │ + * and y2. The start point is represented by x1 and y1. The end point
│ │ │ │ │ + * is represented by x2 and y2. Start and end are ordered so that x1 < x2.
│ │ │ │ │ + * seg2 - {Object} Object representing a segment with properties x1, y1, x2,
│ │ │ │ │ + * and y2. The start point is represented by x1 and y1. The end point
│ │ │ │ │ + * is represented by x2 and y2. Start and end are ordered so that x1 < x2.
│ │ │ │ │ + * options - {Object} Optional properties for calculating the intersection.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * point - {Boolean} Return the intersection point. If false, the actual
│ │ │ │ │ + * intersection point will not be calculated. If true and the segments
│ │ │ │ │ + * intersect, the intersection point will be returned. If true and
│ │ │ │ │ + * the segments do not intersect, false will be returned. If true and
│ │ │ │ │ + * the segments are coincident, true will be returned.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, if the segments are
│ │ │ │ │ + * within the tolerance distance, this will be considered an intersection.
│ │ │ │ │ + * In addition, if the point option is true and the calculated intersection
│ │ │ │ │ + * is within the tolerance distance of an end point, the endpoint will be
│ │ │ │ │ + * returned instead of the calculated intersection. Further, if the
│ │ │ │ │ + * intersection is within the tolerance of endpoints on both segments, or
│ │ │ │ │ + * if two segment endpoints are within the tolerance distance of eachother
│ │ │ │ │ + * (but no intersection is otherwise calculated), an endpoint on the
│ │ │ │ │ + * first segment provided will be returned.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean | } The two segments intersect.
│ │ │ │ │ + * If the point argument is true, the return will be the intersection
│ │ │ │ │ + * point or false if none exists. If point is true and the segments
│ │ │ │ │ + * are coincident, return will be true (and the instersection is equal
│ │ │ │ │ + * to the shorter segment).
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {
│ │ │ │ │ + var point = options && options.point;
│ │ │ │ │ + var tolerance = options && options.tolerance;
│ │ │ │ │ + var intersection = false;
│ │ │ │ │ + var x11_21 = seg1.x1 - seg2.x1;
│ │ │ │ │ + var y11_21 = seg1.y1 - seg2.y1;
│ │ │ │ │ + var x12_11 = seg1.x2 - seg1.x1;
│ │ │ │ │ + var y12_11 = seg1.y2 - seg1.y1;
│ │ │ │ │ + var y22_21 = seg2.y2 - seg2.y1;
│ │ │ │ │ + var x22_21 = seg2.x2 - seg2.x1;
│ │ │ │ │ + var d = (y22_21 * x12_11) - (x22_21 * y12_11);
│ │ │ │ │ + var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);
│ │ │ │ │ + var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);
│ │ │ │ │ + if (d == 0) {
│ │ │ │ │ + // parallel
│ │ │ │ │ + if (n1 == 0 && n2 == 0) {
│ │ │ │ │ + // coincident
│ │ │ │ │ + intersection = true;
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + var along1 = n1 / d;
│ │ │ │ │ + var along2 = n2 / d;
│ │ │ │ │ + if (along1 >= 0 && along1 <= 1 && along2 >= 0 && along2 <= 1) {
│ │ │ │ │ + // intersect
│ │ │ │ │ + if (!point) {
│ │ │ │ │ + intersection = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + // calculate the intersection point
│ │ │ │ │ + var x = seg1.x1 + (along1 * x12_11);
│ │ │ │ │ + var y = seg1.y1 + (along1 * y12_11);
│ │ │ │ │ + intersection = new OpenLayers.Geometry.Point(x, y);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (tolerance) {
│ │ │ │ │ + var dist;
│ │ │ │ │ + if (intersection) {
│ │ │ │ │ + if (point) {
│ │ │ │ │ + var segs = [seg1, seg2];
│ │ │ │ │ + var seg, x, y;
│ │ │ │ │ + // check segment endpoints for proximity to intersection
│ │ │ │ │ + // set intersection to first endpoint within the tolerance
│ │ │ │ │ + outer: for (var i = 0; i < 2; ++i) {
│ │ │ │ │ + seg = segs[i];
│ │ │ │ │ + for (var j = 1; j < 3; ++j) {
│ │ │ │ │ + x = seg["x" + j];
│ │ │ │ │ + y = seg["y" + j];
│ │ │ │ │ + dist = Math.sqrt(
│ │ │ │ │ + Math.pow(x - intersection.x, 2) +
│ │ │ │ │ + Math.pow(y - intersection.y, 2)
│ │ │ │ │ + );
│ │ │ │ │ + if (dist < tolerance) {
│ │ │ │ │ + intersection.x = x;
│ │ │ │ │ + intersection.y = y;
│ │ │ │ │ + break outer;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + // no calculated intersection, but segments could be within
│ │ │ │ │ + // the tolerance of one another
│ │ │ │ │ + var segs = [seg1, seg2];
│ │ │ │ │ + var source, target, x, y, p, result;
│ │ │ │ │ + // check segment endpoints for proximity to intersection
│ │ │ │ │ + // set intersection to first endpoint within the tolerance
│ │ │ │ │ + outer: for (var i = 0; i < 2; ++i) {
│ │ │ │ │ + source = segs[i];
│ │ │ │ │ + target = segs[(i + 1) % 2];
│ │ │ │ │ + for (var j = 1; j < 3; ++j) {
│ │ │ │ │ + p = {
│ │ │ │ │ + x: source["x" + j],
│ │ │ │ │ + y: source["y" + j]
│ │ │ │ │ + };
│ │ │ │ │ + result = OpenLayers.Geometry.distanceToSegment(p, target);
│ │ │ │ │ + if (result.distance < tolerance) {
│ │ │ │ │ + if (point) {
│ │ │ │ │ + intersection = new OpenLayers.Geometry.Point(p.x, p.y);
│ │ │ │ │ + } else {
│ │ │ │ │ + intersection = true;
│ │ │ │ │ + }
│ │ │ │ │ + break outer;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return intersection;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Function: OpenLayers.Geometry.distanceToSegment
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {Object} An object with x and y properties representing the
│ │ │ │ │ + * point coordinates.
│ │ │ │ │ + * segment - {Object} An object with x1, y1, x2, and y2 properties
│ │ │ │ │ + * representing endpoint coordinates.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} An object with distance, along, x, and y properties. The distance
│ │ │ │ │ + * will be the shortest distance between the input point and segment.
│ │ │ │ │ + * The x and y properties represent the coordinates along the segment
│ │ │ │ │ + * where the shortest distance meets the segment. The along attribute
│ │ │ │ │ + * describes how far between the two segment points the given point is.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.distanceToSegment = function(point, segment) {
│ │ │ │ │ + var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment);
│ │ │ │ │ + result.distance = Math.sqrt(result.distance);
│ │ │ │ │ + return result;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Function: OpenLayers.Geometry.distanceSquaredToSegment
│ │ │ │ │ + *
│ │ │ │ │ + * Usually the distanceToSegment function should be used. This variant however
│ │ │ │ │ + * can be used for comparisons where the exact distance is not important.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {Object} An object with x and y properties representing the
│ │ │ │ │ + * point coordinates.
│ │ │ │ │ + * segment - {Object} An object with x1, y1, x2, and y2 properties
│ │ │ │ │ + * representing endpoint coordinates.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} An object with squared distance, along, x, and y properties.
│ │ │ │ │ + * The distance will be the shortest distance between the input point and
│ │ │ │ │ + * segment. The x and y properties represent the coordinates along the
│ │ │ │ │ + * segment where the shortest distance meets the segment. The along
│ │ │ │ │ + * attribute describes how far between the two segment points the given
│ │ │ │ │ + * point is.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) {
│ │ │ │ │ + var x0 = point.x;
│ │ │ │ │ + var y0 = point.y;
│ │ │ │ │ + var x1 = segment.x1;
│ │ │ │ │ + var y1 = segment.y1;
│ │ │ │ │ + var x2 = segment.x2;
│ │ │ │ │ + var y2 = segment.y2;
│ │ │ │ │ + var dx = x2 - x1;
│ │ │ │ │ + var dy = y2 - y1;
│ │ │ │ │ + var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
│ │ │ │ │ + (Math.pow(dx, 2) + Math.pow(dy, 2));
│ │ │ │ │ + var x, y;
│ │ │ │ │ + if (along <= 0.0) {
│ │ │ │ │ + x = x1;
│ │ │ │ │ + y = y1;
│ │ │ │ │ + } else if (along >= 1.0) {
│ │ │ │ │ + x = x2;
│ │ │ │ │ + y = y2;
│ │ │ │ │ + } else {
│ │ │ │ │ + x = x1 + along * dx;
│ │ │ │ │ + y = y1 + along * dy;
│ │ │ │ │ + }
│ │ │ │ │ + return {
│ │ │ │ │ + distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2),
│ │ │ │ │ + x: x,
│ │ │ │ │ + y: y,
│ │ │ │ │ + along: along
│ │ │ │ │ + };
│ │ │ │ │ +};
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ OpenLayers/BaseTypes.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │ @@ -603,141 +1236,14 @@
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ return selected;
│ │ │ │ │ }
│ │ │ │ │
│ │ │ │ │ };
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/SingleFile.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constructor: OpenLayers.Class
│ │ │ │ │ - * Base class used to construct all other classes. Includes support for
│ │ │ │ │ - * multiple inheritance.
│ │ │ │ │ - *
│ │ │ │ │ - * This constructor is new in OpenLayers 2.5. At OpenLayers 3.0, the old
│ │ │ │ │ - * syntax for creating classes and dealing with inheritance
│ │ │ │ │ - * will be removed.
│ │ │ │ │ - *
│ │ │ │ │ - * To create a new OpenLayers-style class, use the following syntax:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * var MyClass = OpenLayers.Class(prototype);
│ │ │ │ │ - * (end)
│ │ │ │ │ - *
│ │ │ │ │ - * To create a new OpenLayers-style class with multiple inheritance, use the
│ │ │ │ │ - * following syntax:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * var MyClass = OpenLayers.Class(Class1, Class2, prototype);
│ │ │ │ │ - * (end)
│ │ │ │ │ - *
│ │ │ │ │ - * Note that instanceof reflection will only reveal Class1 as superclass.
│ │ │ │ │ - *
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Class = function() {
│ │ │ │ │ - var len = arguments.length;
│ │ │ │ │ - var P = arguments[0];
│ │ │ │ │ - var F = arguments[len - 1];
│ │ │ │ │ -
│ │ │ │ │ - var C = typeof F.initialize == "function" ?
│ │ │ │ │ - F.initialize :
│ │ │ │ │ - function() {
│ │ │ │ │ - P.prototype.initialize.apply(this, arguments);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - if (len > 1) {
│ │ │ │ │ - var newArgs = [C, P].concat(
│ │ │ │ │ - Array.prototype.slice.call(arguments).slice(1, len - 1), F);
│ │ │ │ │ - OpenLayers.inherit.apply(null, newArgs);
│ │ │ │ │ - } else {
│ │ │ │ │ - C.prototype = F;
│ │ │ │ │ - }
│ │ │ │ │ - return C;
│ │ │ │ │ -};
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Function: OpenLayers.inherit
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * C - {Object} the class that inherits
│ │ │ │ │ - * P - {Object} the superclass to inherit from
│ │ │ │ │ - *
│ │ │ │ │ - * In addition to the mandatory C and P parameters, an arbitrary number of
│ │ │ │ │ - * objects can be passed, which will extend C.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.inherit = function(C, P) {
│ │ │ │ │ - var F = function() {};
│ │ │ │ │ - F.prototype = P.prototype;
│ │ │ │ │ - C.prototype = new F;
│ │ │ │ │ - var i, l, o;
│ │ │ │ │ - for (i = 2, l = arguments.length; i < l; i++) {
│ │ │ │ │ - o = arguments[i];
│ │ │ │ │ - if (typeof o === "function") {
│ │ │ │ │ - o = o.prototype;
│ │ │ │ │ - }
│ │ │ │ │ - OpenLayers.Util.extend(C.prototype, o);
│ │ │ │ │ - }
│ │ │ │ │ -};
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * APIFunction: extend
│ │ │ │ │ - * Copy all properties of a source object to a destination object. Modifies
│ │ │ │ │ - * the passed in destination object. Any properties on the source object
│ │ │ │ │ - * that are set to undefined will not be (re)set on the destination object.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * destination - {Object} The object that will be modified
│ │ │ │ │ - * source - {Object} The object with properties to be set on the destination
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Object} The destination object.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Util = OpenLayers.Util || {};
│ │ │ │ │ -OpenLayers.Util.extend = function(destination, source) {
│ │ │ │ │ - destination = destination || {};
│ │ │ │ │ - if (source) {
│ │ │ │ │ - for (var property in source) {
│ │ │ │ │ - var value = source[property];
│ │ │ │ │ - if (value !== undefined) {
│ │ │ │ │ - destination[property] = value;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * IE doesn't include the toString property when iterating over an object's
│ │ │ │ │ - * properties with the for(property in object) syntax. Explicitly check if
│ │ │ │ │ - * the source has its own toString property.
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ - /*
│ │ │ │ │ - * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
│ │ │ │ │ - * prototype object" when calling hawOwnProperty if the source object
│ │ │ │ │ - * is an instance of window.Event.
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ - var sourceIsEvt = typeof window.Event == "function" &&
│ │ │ │ │ - source instanceof window.Event;
│ │ │ │ │ -
│ │ │ │ │ - if (!sourceIsEvt &&
│ │ │ │ │ - source.hasOwnProperty && source.hasOwnProperty("toString")) {
│ │ │ │ │ - destination.toString = source.toString;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - return destination;
│ │ │ │ │ -};
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ OpenLayers/BaseTypes/Bounds.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │ @@ -4426,1644 +4932,14 @@
│ │ │ │ │ } else {
│ │ │ │ │ str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N");
│ │ │ │ │ }
│ │ │ │ │ return str;
│ │ │ │ │ };
│ │ │ │ │
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Events.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/Util.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Event
│ │ │ │ │ - * Utility functions for event handling.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Event = {
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: observers
│ │ │ │ │ - * {Object} A hashtable cache of the event observers. Keyed by
│ │ │ │ │ - * element._eventCacheID
│ │ │ │ │ - */
│ │ │ │ │ - observers: false,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_SPACE
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_SPACE: 32,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_BACKSPACE
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_BACKSPACE: 8,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_TAB
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_TAB: 9,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_RETURN
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_RETURN: 13,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_ESC
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_ESC: 27,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_LEFT
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_LEFT: 37,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_UP
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_UP: 38,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_RIGHT
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_RIGHT: 39,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_DOWN
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_DOWN: 40,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: KEY_DELETE
│ │ │ │ │ - * {int}
│ │ │ │ │ - */
│ │ │ │ │ - KEY_DELETE: 46,
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: element
│ │ │ │ │ - * Cross browser event element detection.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {DOMElement} The element that caused the event
│ │ │ │ │ - */
│ │ │ │ │ - element: function(event) {
│ │ │ │ │ - return event.target || event.srcElement;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: isSingleTouch
│ │ │ │ │ - * Determine whether event was caused by a single touch
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - isSingleTouch: function(event) {
│ │ │ │ │ - return event.touches && event.touches.length == 1;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: isMultiTouch
│ │ │ │ │ - * Determine whether event was caused by a multi touch
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - isMultiTouch: function(event) {
│ │ │ │ │ - return event.touches && event.touches.length > 1;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: isLeftClick
│ │ │ │ │ - * Determine whether event was caused by a left click.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - isLeftClick: function(event) {
│ │ │ │ │ - return (((event.which) && (event.which == 1)) ||
│ │ │ │ │ - ((event.button) && (event.button == 1)));
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: isRightClick
│ │ │ │ │ - * Determine whether event was caused by a right mouse click.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - isRightClick: function(event) {
│ │ │ │ │ - return (((event.which) && (event.which == 3)) ||
│ │ │ │ │ - ((event.button) && (event.button == 2)));
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: stop
│ │ │ │ │ - * Stops an event from propagating.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - * allowDefault - {Boolean} If true, we stop the event chain but
│ │ │ │ │ - * still allow the default browser behaviour (text selection,
│ │ │ │ │ - * radio-button clicking, etc). Default is false.
│ │ │ │ │ - */
│ │ │ │ │ - stop: function(event, allowDefault) {
│ │ │ │ │ -
│ │ │ │ │ - if (!allowDefault) {
│ │ │ │ │ - OpenLayers.Event.preventDefault(event);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (event.stopPropagation) {
│ │ │ │ │ - event.stopPropagation();
│ │ │ │ │ - } else {
│ │ │ │ │ - event.cancelBubble = true;
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: preventDefault
│ │ │ │ │ - * Cancels the event if it is cancelable, without stopping further
│ │ │ │ │ - * propagation of the event.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - */
│ │ │ │ │ - preventDefault: function(event) {
│ │ │ │ │ - if (event.preventDefault) {
│ │ │ │ │ - event.preventDefault();
│ │ │ │ │ - } else {
│ │ │ │ │ - event.returnValue = false;
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: findElement
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * event - {Event}
│ │ │ │ │ - * tagName - {String}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {DOMElement} The first node with the given tagName, starting from the
│ │ │ │ │ - * node the event was triggered on and traversing the DOM upwards
│ │ │ │ │ - */
│ │ │ │ │ - findElement: function(event, tagName) {
│ │ │ │ │ - var element = OpenLayers.Event.element(event);
│ │ │ │ │ - while (element.parentNode && (!element.tagName ||
│ │ │ │ │ - (element.tagName.toUpperCase() != tagName.toUpperCase()))) {
│ │ │ │ │ - element = element.parentNode;
│ │ │ │ │ - }
│ │ │ │ │ - return element;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: observe
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * elementParam - {DOMElement || String}
│ │ │ │ │ - * name - {String}
│ │ │ │ │ - * observer - {function}
│ │ │ │ │ - * useCapture - {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - observe: function(elementParam, name, observer, useCapture) {
│ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam);
│ │ │ │ │ - useCapture = useCapture || false;
│ │ │ │ │ -
│ │ │ │ │ - if (name == 'keypress' &&
│ │ │ │ │ - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||
│ │ │ │ │ - element.attachEvent)) {
│ │ │ │ │ - name = 'keydown';
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - //if observers cache has not yet been created, create it
│ │ │ │ │ - if (!this.observers) {
│ │ │ │ │ - this.observers = {};
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - //if not already assigned, make a new unique cache ID
│ │ │ │ │ - if (!element._eventCacheID) {
│ │ │ │ │ - var idPrefix = "eventCacheID_";
│ │ │ │ │ - if (element.id) {
│ │ │ │ │ - idPrefix = element.id + "_" + idPrefix;
│ │ │ │ │ - }
│ │ │ │ │ - element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - var cacheID = element._eventCacheID;
│ │ │ │ │ -
│ │ │ │ │ - //if there is not yet a hash entry for this element, add one
│ │ │ │ │ - if (!this.observers[cacheID]) {
│ │ │ │ │ - this.observers[cacheID] = [];
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - //add a new observer to this element's list
│ │ │ │ │ - this.observers[cacheID].push({
│ │ │ │ │ - 'element': element,
│ │ │ │ │ - 'name': name,
│ │ │ │ │ - 'observer': observer,
│ │ │ │ │ - 'useCapture': useCapture
│ │ │ │ │ - });
│ │ │ │ │ -
│ │ │ │ │ - //add the actual browser event listener
│ │ │ │ │ - if (element.addEventListener) {
│ │ │ │ │ - element.addEventListener(name, observer, useCapture);
│ │ │ │ │ - } else if (element.attachEvent) {
│ │ │ │ │ - element.attachEvent('on' + name, observer);
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: stopObservingElement
│ │ │ │ │ - * Given the id of an element to stop observing, cycle through the
│ │ │ │ │ - * element's cached observers, calling stopObserving on each one,
│ │ │ │ │ - * skipping those entries which can no longer be removed.
│ │ │ │ │ - *
│ │ │ │ │ - * parameters:
│ │ │ │ │ - * elementParam - {DOMElement || String}
│ │ │ │ │ - */
│ │ │ │ │ - stopObservingElement: function(elementParam) {
│ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam);
│ │ │ │ │ - var cacheID = element._eventCacheID;
│ │ │ │ │ -
│ │ │ │ │ - this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: _removeElementObservers
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * elementObservers - {Array(Object)} Array of (element, name,
│ │ │ │ │ - * observer, usecapture) objects,
│ │ │ │ │ - * taken directly from hashtable
│ │ │ │ │ - */
│ │ │ │ │ - _removeElementObservers: function(elementObservers) {
│ │ │ │ │ - if (elementObservers) {
│ │ │ │ │ - for (var i = elementObservers.length - 1; i >= 0; i--) {
│ │ │ │ │ - var entry = elementObservers[i];
│ │ │ │ │ - OpenLayers.Event.stopObserving.apply(this, [
│ │ │ │ │ - entry.element, entry.name, entry.observer, entry.useCapture
│ │ │ │ │ - ]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: stopObserving
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * elementParam - {DOMElement || String}
│ │ │ │ │ - * name - {String}
│ │ │ │ │ - * observer - {function}
│ │ │ │ │ - * useCapture - {Boolean}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} Whether or not the event observer was removed
│ │ │ │ │ - */
│ │ │ │ │ - stopObserving: function(elementParam, name, observer, useCapture) {
│ │ │ │ │ - useCapture = useCapture || false;
│ │ │ │ │ -
│ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam);
│ │ │ │ │ - var cacheID = element._eventCacheID;
│ │ │ │ │ -
│ │ │ │ │ - if (name == 'keypress') {
│ │ │ │ │ - if (navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||
│ │ │ │ │ - element.detachEvent) {
│ │ │ │ │ - name = 'keydown';
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // find element's entry in this.observers cache and remove it
│ │ │ │ │ - var foundEntry = false;
│ │ │ │ │ - var elementObservers = OpenLayers.Event.observers[cacheID];
│ │ │ │ │ - if (elementObservers) {
│ │ │ │ │ -
│ │ │ │ │ - // find the specific event type in the element's list
│ │ │ │ │ - var i = 0;
│ │ │ │ │ - while (!foundEntry && i < elementObservers.length) {
│ │ │ │ │ - var cacheEntry = elementObservers[i];
│ │ │ │ │ -
│ │ │ │ │ - if ((cacheEntry.name == name) &&
│ │ │ │ │ - (cacheEntry.observer == observer) &&
│ │ │ │ │ - (cacheEntry.useCapture == useCapture)) {
│ │ │ │ │ -
│ │ │ │ │ - elementObservers.splice(i, 1);
│ │ │ │ │ - if (elementObservers.length == 0) {
│ │ │ │ │ - delete OpenLayers.Event.observers[cacheID];
│ │ │ │ │ - }
│ │ │ │ │ - foundEntry = true;
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - i++;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - //actually remove the event listener from browser
│ │ │ │ │ - if (foundEntry) {
│ │ │ │ │ - if (element.removeEventListener) {
│ │ │ │ │ - element.removeEventListener(name, observer, useCapture);
│ │ │ │ │ - } else if (element && element.detachEvent) {
│ │ │ │ │ - element.detachEvent('on' + name, observer);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - return foundEntry;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: unloadCache
│ │ │ │ │ - * Cycle through all the element entries in the events cache and call
│ │ │ │ │ - * stopObservingElement on each.
│ │ │ │ │ - */
│ │ │ │ │ - unloadCache: function() {
│ │ │ │ │ - // check for OpenLayers.Event before checking for observers, because
│ │ │ │ │ - // OpenLayers.Event may be undefined in IE if no map instance was
│ │ │ │ │ - // created
│ │ │ │ │ - if (OpenLayers.Event && OpenLayers.Event.observers) {
│ │ │ │ │ - for (var cacheID in OpenLayers.Event.observers) {
│ │ │ │ │ - var elementObservers = OpenLayers.Event.observers[cacheID];
│ │ │ │ │ - OpenLayers.Event._removeElementObservers.apply(this,
│ │ │ │ │ - [elementObservers]);
│ │ │ │ │ - }
│ │ │ │ │ - OpenLayers.Event.observers = false;
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Event"
│ │ │ │ │ -};
│ │ │ │ │ -
│ │ │ │ │ -/* prevent memory leaks in IE */
│ │ │ │ │ -OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Class: OpenLayers.Events
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Events = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: BROWSER_EVENTS
│ │ │ │ │ - * {Array(String)} supported events
│ │ │ │ │ - */
│ │ │ │ │ - BROWSER_EVENTS: [
│ │ │ │ │ - "mouseover", "mouseout",
│ │ │ │ │ - "mousedown", "mouseup", "mousemove",
│ │ │ │ │ - "click", "dblclick", "rightclick", "dblrightclick",
│ │ │ │ │ - "resize", "focus", "blur",
│ │ │ │ │ - "touchstart", "touchmove", "touchend",
│ │ │ │ │ - "keydown"
│ │ │ │ │ - ],
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: listeners
│ │ │ │ │ - * {Object} Hashtable of Array(Function): events listener functions
│ │ │ │ │ - */
│ │ │ │ │ - listeners: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: object
│ │ │ │ │ - * {Object} the code object issuing application events
│ │ │ │ │ - */
│ │ │ │ │ - object: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: element
│ │ │ │ │ - * {DOMElement} the DOM element receiving browser events
│ │ │ │ │ - */
│ │ │ │ │ - element: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: eventHandler
│ │ │ │ │ - * {Function} bound event handler attached to elements
│ │ │ │ │ - */
│ │ │ │ │ - eventHandler: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: fallThrough
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - fallThrough: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: includeXY
│ │ │ │ │ - * {Boolean} Should the .xy property automatically be created for browser
│ │ │ │ │ - * mouse events? In general, this should be false. If it is true, then
│ │ │ │ │ - * mouse events will automatically generate a '.xy' property on the
│ │ │ │ │ - * event object that is passed. (Prior to OpenLayers 2.7, this was true
│ │ │ │ │ - * by default.) Otherwise, you can call the getMousePosition on the
│ │ │ │ │ - * relevant events handler on the object available via the 'evt.object'
│ │ │ │ │ - * property of the evt object. So, for most events, you can call:
│ │ │ │ │ - * function named(evt) {
│ │ │ │ │ - * this.xy = this.object.events.getMousePosition(evt)
│ │ │ │ │ - * }
│ │ │ │ │ - *
│ │ │ │ │ - * This option typically defaults to false for performance reasons:
│ │ │ │ │ - * when creating an events object whose primary purpose is to manage
│ │ │ │ │ - * relatively positioned mouse events within a div, it may make
│ │ │ │ │ - * sense to set it to true.
│ │ │ │ │ - *
│ │ │ │ │ - * This option is also used to control whether the events object caches
│ │ │ │ │ - * offsets. If this is false, it will not: the reason for this is that
│ │ │ │ │ - * it is only expected to be called many times if the includeXY property
│ │ │ │ │ - * is set to true. If you set this to true, you are expected to clear
│ │ │ │ │ - * the offset cache manually (using this.clearMouseCache()) if:
│ │ │ │ │ - * the border of the element changes
│ │ │ │ │ - * the location of the element in the page changes
│ │ │ │ │ - */
│ │ │ │ │ - includeXY: false,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: extensions
│ │ │ │ │ - * {Object} Event extensions registered with this instance. Keys are
│ │ │ │ │ - * event types, values are {OpenLayers.Events.*} extension instances or
│ │ │ │ │ - * {Boolean} for events that an instantiated extension provides in
│ │ │ │ │ - * addition to the one it was created for.
│ │ │ │ │ - *
│ │ │ │ │ - * Extensions create an event in addition to browser events, which usually
│ │ │ │ │ - * fires when a sequence of browser events is completed. Extensions are
│ │ │ │ │ - * automatically instantiated when a listener is registered for an event
│ │ │ │ │ - * provided by an extension.
│ │ │ │ │ - *
│ │ │ │ │ - * Extensions are created in the namespace using
│ │ │ │ │ - * , and named after the event they provide.
│ │ │ │ │ - * The constructor receives the target instance as
│ │ │ │ │ - * argument. Extensions that need to capture browser events before they
│ │ │ │ │ - * propagate can register their listeners events using , with
│ │ │ │ │ - * {extension: true} as 4th argument.
│ │ │ │ │ - *
│ │ │ │ │ - * If an extension creates more than one event, an alias for each event
│ │ │ │ │ - * type should be created and reference the same class. The constructor
│ │ │ │ │ - * should set a reference in the target's extensions registry to itself.
│ │ │ │ │ - *
│ │ │ │ │ - * Below is a minimal extension that provides the "foostart" and "fooend"
│ │ │ │ │ - * event types, which replace the native "click" event type if clicked on
│ │ │ │ │ - * an element with the css class "foo":
│ │ │ │ │ - *
│ │ │ │ │ - * (code)
│ │ │ │ │ - * OpenLayers.Events.foostart = OpenLayers.Class({
│ │ │ │ │ - * initialize: function(target) {
│ │ │ │ │ - * this.target = target;
│ │ │ │ │ - * this.target.register("click", this, this.doStuff, {extension: true});
│ │ │ │ │ - * // only required if extension provides more than one event type
│ │ │ │ │ - * this.target.extensions["foostart"] = true;
│ │ │ │ │ - * this.target.extensions["fooend"] = true;
│ │ │ │ │ - * },
│ │ │ │ │ - * destroy: function() {
│ │ │ │ │ - * var target = this.target;
│ │ │ │ │ - * target.unregister("click", this, this.doStuff);
│ │ │ │ │ - * delete this.target;
│ │ │ │ │ - * // only required if extension provides more than one event type
│ │ │ │ │ - * delete target.extensions["foostart"];
│ │ │ │ │ - * delete target.extensions["fooend"];
│ │ │ │ │ - * },
│ │ │ │ │ - * doStuff: function(evt) {
│ │ │ │ │ - * var propagate = true;
│ │ │ │ │ - * if (OpenLayers.Event.element(evt).className === "foo") {
│ │ │ │ │ - * propagate = false;
│ │ │ │ │ - * var target = this.target;
│ │ │ │ │ - * target.triggerEvent("foostart");
│ │ │ │ │ - * window.setTimeout(function() {
│ │ │ │ │ - * target.triggerEvent("fooend");
│ │ │ │ │ - * }, 1000);
│ │ │ │ │ - * }
│ │ │ │ │ - * return propagate;
│ │ │ │ │ - * }
│ │ │ │ │ - * });
│ │ │ │ │ - * // only required if extension provides more than one event type
│ │ │ │ │ - * OpenLayers.Events.fooend = OpenLayers.Events.foostart;
│ │ │ │ │ - * (end)
│ │ │ │ │ - *
│ │ │ │ │ - */
│ │ │ │ │ - extensions: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: extensionCount
│ │ │ │ │ - * {Object} Keys are event types (like in ), values are the
│ │ │ │ │ - * number of extension listeners for each event type.
│ │ │ │ │ - */
│ │ │ │ │ - extensionCount: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: clearMouseListener
│ │ │ │ │ - * A version of that is bound to this instance so that
│ │ │ │ │ - * it can be used with and
│ │ │ │ │ - * .
│ │ │ │ │ - */
│ │ │ │ │ - clearMouseListener: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Events
│ │ │ │ │ - * Construct an OpenLayers.Events object.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * object - {Object} The js object to which this Events object is being added
│ │ │ │ │ - * element - {DOMElement} A dom element to respond to browser events
│ │ │ │ │ - * eventTypes - {Array(String)} Deprecated. Array of custom application
│ │ │ │ │ - * events. A listener may be registered for any named event, regardless
│ │ │ │ │ - * of the values provided here.
│ │ │ │ │ - * fallThrough - {Boolean} Allow events to fall through after these have
│ │ │ │ │ - * been handled?
│ │ │ │ │ - * options - {Object} Options for the events object.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(object, element, eventTypes, fallThrough, options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.object = object;
│ │ │ │ │ - this.fallThrough = fallThrough;
│ │ │ │ │ - this.listeners = {};
│ │ │ │ │ - this.extensions = {};
│ │ │ │ │ - this.extensionCount = {};
│ │ │ │ │ - this._msTouches = [];
│ │ │ │ │ -
│ │ │ │ │ - // if a dom element is specified, add a listeners list
│ │ │ │ │ - // for browser events on the element and register them
│ │ │ │ │ - if (element != null) {
│ │ │ │ │ - this.attachToElement(element);
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - for (var e in this.extensions) {
│ │ │ │ │ - if (typeof this.extensions[e] !== "boolean") {
│ │ │ │ │ - this.extensions[e].destroy();
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - this.extensions = null;
│ │ │ │ │ - if (this.element) {
│ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.element);
│ │ │ │ │ - if (this.element.hasScrollEvent) {
│ │ │ │ │ - OpenLayers.Event.stopObserving(
│ │ │ │ │ - window, "scroll", this.clearMouseListener
│ │ │ │ │ - );
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - this.element = null;
│ │ │ │ │ -
│ │ │ │ │ - this.listeners = null;
│ │ │ │ │ - this.object = null;
│ │ │ │ │ - this.fallThrough = null;
│ │ │ │ │ - this.eventHandler = null;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: addEventType
│ │ │ │ │ - * Deprecated. Any event can be triggered without adding it first.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * eventName - {String}
│ │ │ │ │ - */
│ │ │ │ │ - addEventType: function(eventName) {},
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: attachToElement
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * element - {HTMLDOMElement} a DOM element to attach browser events to
│ │ │ │ │ - */
│ │ │ │ │ - attachToElement: function(element) {
│ │ │ │ │ - if (this.element) {
│ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.element);
│ │ │ │ │ - } else {
│ │ │ │ │ - // keep a bound copy of handleBrowserEvent() so that we can
│ │ │ │ │ - // pass the same function to both Event.observe() and .stopObserving()
│ │ │ │ │ - this.eventHandler = OpenLayers.Function.bindAsEventListener(
│ │ │ │ │ - this.handleBrowserEvent, this
│ │ │ │ │ - );
│ │ │ │ │ -
│ │ │ │ │ - // to be used with observe and stopObserving
│ │ │ │ │ - this.clearMouseListener = OpenLayers.Function.bind(
│ │ │ │ │ - this.clearMouseCache, this
│ │ │ │ │ - );
│ │ │ │ │ - }
│ │ │ │ │ - this.element = element;
│ │ │ │ │ - var msTouch = !!window.navigator.msMaxTouchPoints;
│ │ │ │ │ - var type;
│ │ │ │ │ - for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {
│ │ │ │ │ - type = this.BROWSER_EVENTS[i];
│ │ │ │ │ - // register the event cross-browser
│ │ │ │ │ - OpenLayers.Event.observe(element, type, this.eventHandler);
│ │ │ │ │ - if (msTouch && type.indexOf('touch') === 0) {
│ │ │ │ │ - this.addMsTouchListener(element, type, this.eventHandler);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - // disable dragstart in IE so that mousedown/move/up works normally
│ │ │ │ │ - OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: on
│ │ │ │ │ - * Convenience method for registering listeners with a common scope.
│ │ │ │ │ - * Internally, this method calls as shown in the examples
│ │ │ │ │ - * below.
│ │ │ │ │ - *
│ │ │ │ │ - * Example use:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * // register a single listener for the "loadstart" event
│ │ │ │ │ - * events.on({"loadstart": loadStartListener});
│ │ │ │ │ - *
│ │ │ │ │ - * // this is equivalent to the following
│ │ │ │ │ - * events.register("loadstart", undefined, loadStartListener);
│ │ │ │ │ - *
│ │ │ │ │ - * // register multiple listeners to be called with the same `this` object
│ │ │ │ │ - * events.on({
│ │ │ │ │ - * "loadstart": loadStartListener,
│ │ │ │ │ - * "loadend": loadEndListener,
│ │ │ │ │ - * scope: object
│ │ │ │ │ - * });
│ │ │ │ │ - *
│ │ │ │ │ - * // this is equivalent to the following
│ │ │ │ │ - * events.register("loadstart", object, loadStartListener);
│ │ │ │ │ - * events.register("loadend", object, loadEndListener);
│ │ │ │ │ - * (end)
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * object - {Object}
│ │ │ │ │ - */
│ │ │ │ │ - on: function(object) {
│ │ │ │ │ - for (var type in object) {
│ │ │ │ │ - if (type != "scope" && object.hasOwnProperty(type)) {
│ │ │ │ │ - this.register(type, object.scope, object[type]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: register
│ │ │ │ │ - * Register an event on the events object.
│ │ │ │ │ - *
│ │ │ │ │ - * When the event is triggered, the 'func' function will be called, in the
│ │ │ │ │ - * context of 'obj'. Imagine we were to register an event, specifying an
│ │ │ │ │ - * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the
│ │ │ │ │ - * context in the callback function will be our Bounds object. This means
│ │ │ │ │ - * that within our callback function, we can access the properties and
│ │ │ │ │ - * methods of the Bounds object through the "this" variable. So our
│ │ │ │ │ - * callback could execute something like:
│ │ │ │ │ - * : leftStr = "Left: " + this.left;
│ │ │ │ │ - *
│ │ │ │ │ - * or
│ │ │ │ │ - *
│ │ │ │ │ - * : centerStr = "Center: " + this.getCenterLonLat();
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * type - {String} Name of the event to register
│ │ │ │ │ - * obj - {Object} The object to bind the context to for the callback#.
│ │ │ │ │ - * If no object is specified, default is the Events's 'object' property.
│ │ │ │ │ - * func - {Function} The callback function. If no callback is
│ │ │ │ │ - * specified, this function does nothing.
│ │ │ │ │ - * priority - {Boolean|Object} If true, adds the new listener to the
│ │ │ │ │ - * *front* of the events queue instead of to the end.
│ │ │ │ │ - *
│ │ │ │ │ - * Valid options for priority:
│ │ │ │ │ - * extension - {Boolean} If true, then the event will be registered as
│ │ │ │ │ - * extension event. Extension events are handled before all other
│ │ │ │ │ - * events.
│ │ │ │ │ - */
│ │ │ │ │ - register: function(type, obj, func, priority) {
│ │ │ │ │ - if (type in OpenLayers.Events && !this.extensions[type]) {
│ │ │ │ │ - this.extensions[type] = new OpenLayers.Events[type](this);
│ │ │ │ │ - }
│ │ │ │ │ - if (func != null) {
│ │ │ │ │ - if (obj == null) {
│ │ │ │ │ - obj = this.object;
│ │ │ │ │ - }
│ │ │ │ │ - var listeners = this.listeners[type];
│ │ │ │ │ - if (!listeners) {
│ │ │ │ │ - listeners = [];
│ │ │ │ │ - this.listeners[type] = listeners;
│ │ │ │ │ - this.extensionCount[type] = 0;
│ │ │ │ │ - }
│ │ │ │ │ - var listener = {
│ │ │ │ │ - obj: obj,
│ │ │ │ │ - func: func
│ │ │ │ │ - };
│ │ │ │ │ - if (priority) {
│ │ │ │ │ - listeners.splice(this.extensionCount[type], 0, listener);
│ │ │ │ │ - if (typeof priority === "object" && priority.extension) {
│ │ │ │ │ - this.extensionCount[type]++;
│ │ │ │ │ - }
│ │ │ │ │ - } else {
│ │ │ │ │ - listeners.push(listener);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: registerPriority
│ │ │ │ │ - * Same as register() but adds the new listener to the *front* of the
│ │ │ │ │ - * events queue instead of to the end.
│ │ │ │ │ - *
│ │ │ │ │ - * TODO: get rid of this in 3.0 - Decide whether listeners should be
│ │ │ │ │ - * called in the order they were registered or in reverse order.
│ │ │ │ │ - *
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * type - {String} Name of the event to register
│ │ │ │ │ - * obj - {Object} The object to bind the context to for the callback#.
│ │ │ │ │ - * If no object is specified, default is the Events's
│ │ │ │ │ - * 'object' property.
│ │ │ │ │ - * func - {Function} The callback function. If no callback is
│ │ │ │ │ - * specified, this function does nothing.
│ │ │ │ │ - */
│ │ │ │ │ - registerPriority: function(type, obj, func) {
│ │ │ │ │ - this.register(type, obj, func, true);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: un
│ │ │ │ │ - * Convenience method for unregistering listeners with a common scope.
│ │ │ │ │ - * Internally, this method calls as shown in the examples
│ │ │ │ │ - * below.
│ │ │ │ │ - *
│ │ │ │ │ - * Example use:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * // unregister a single listener for the "loadstart" event
│ │ │ │ │ - * events.un({"loadstart": loadStartListener});
│ │ │ │ │ - *
│ │ │ │ │ - * // this is equivalent to the following
│ │ │ │ │ - * events.unregister("loadstart", undefined, loadStartListener);
│ │ │ │ │ - *
│ │ │ │ │ - * // unregister multiple listeners with the same `this` object
│ │ │ │ │ - * events.un({
│ │ │ │ │ - * "loadstart": loadStartListener,
│ │ │ │ │ - * "loadend": loadEndListener,
│ │ │ │ │ - * scope: object
│ │ │ │ │ - * });
│ │ │ │ │ - *
│ │ │ │ │ - * // this is equivalent to the following
│ │ │ │ │ - * events.unregister("loadstart", object, loadStartListener);
│ │ │ │ │ - * events.unregister("loadend", object, loadEndListener);
│ │ │ │ │ - * (end)
│ │ │ │ │ - */
│ │ │ │ │ - un: function(object) {
│ │ │ │ │ - for (var type in object) {
│ │ │ │ │ - if (type != "scope" && object.hasOwnProperty(type)) {
│ │ │ │ │ - this.unregister(type, object.scope, object[type]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: unregister
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * type - {String}
│ │ │ │ │ - * obj - {Object} If none specified, defaults to this.object
│ │ │ │ │ - * func - {Function}
│ │ │ │ │ - */
│ │ │ │ │ - unregister: function(type, obj, func) {
│ │ │ │ │ - if (obj == null) {
│ │ │ │ │ - obj = this.object;
│ │ │ │ │ - }
│ │ │ │ │ - var listeners = this.listeners[type];
│ │ │ │ │ - if (listeners != null) {
│ │ │ │ │ - for (var i = 0, len = listeners.length; i < len; i++) {
│ │ │ │ │ - if (listeners[i].obj == obj && listeners[i].func == func) {
│ │ │ │ │ - listeners.splice(i, 1);
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: remove
│ │ │ │ │ - * Remove all listeners for a given event type. If type is not registered,
│ │ │ │ │ - * does nothing.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * type - {String}
│ │ │ │ │ - */
│ │ │ │ │ - remove: function(type) {
│ │ │ │ │ - if (this.listeners[type] != null) {
│ │ │ │ │ - this.listeners[type] = [];
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: triggerEvent
│ │ │ │ │ - * Trigger a specified registered event.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * type - {String}
│ │ │ │ │ - * evt - {Event || Object} will be passed to the listeners.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} The last listener return. If a listener returns false, the
│ │ │ │ │ - * chain of listeners will stop getting called.
│ │ │ │ │ - */
│ │ │ │ │ - triggerEvent: function(type, evt) {
│ │ │ │ │ - var listeners = this.listeners[type];
│ │ │ │ │ -
│ │ │ │ │ - // fast path
│ │ │ │ │ - if (!listeners || listeners.length == 0) {
│ │ │ │ │ - return undefined;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // prep evt object with object & div references
│ │ │ │ │ - if (evt == null) {
│ │ │ │ │ - evt = {};
│ │ │ │ │ - }
│ │ │ │ │ - evt.object = this.object;
│ │ │ │ │ - evt.element = this.element;
│ │ │ │ │ - if (!evt.type) {
│ │ │ │ │ - evt.type = type;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // execute all callbacks registered for specified type
│ │ │ │ │ - // get a clone of the listeners array to
│ │ │ │ │ - // allow for splicing during callbacks
│ │ │ │ │ - listeners = listeners.slice();
│ │ │ │ │ - var continueChain;
│ │ │ │ │ - for (var i = 0, len = listeners.length; i < len; i++) {
│ │ │ │ │ - var callback = listeners[i];
│ │ │ │ │ - // bind the context to callback.obj
│ │ │ │ │ - continueChain = callback.func.apply(callback.obj, [evt]);
│ │ │ │ │ -
│ │ │ │ │ - if ((continueChain != undefined) && (continueChain == false)) {
│ │ │ │ │ - // if callback returns false, execute no more callbacks.
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - // don't fall through to other DOM elements
│ │ │ │ │ - if (!this.fallThrough) {
│ │ │ │ │ - OpenLayers.Event.stop(evt, true);
│ │ │ │ │ - }
│ │ │ │ │ - return continueChain;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: handleBrowserEvent
│ │ │ │ │ - * Basically just a wrapper to the triggerEvent() function, but takes
│ │ │ │ │ - * care to set a property 'xy' on the event with the current mouse
│ │ │ │ │ - * position.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * evt - {Event}
│ │ │ │ │ - */
│ │ │ │ │ - handleBrowserEvent: function(evt) {
│ │ │ │ │ - var type = evt.type,
│ │ │ │ │ - listeners = this.listeners[type];
│ │ │ │ │ - if (!listeners || listeners.length == 0) {
│ │ │ │ │ - // noone's listening, bail out
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ - // add clientX & clientY to all events - corresponds to average x, y
│ │ │ │ │ - var touches = evt.touches;
│ │ │ │ │ - if (touches && touches[0]) {
│ │ │ │ │ - var x = 0;
│ │ │ │ │ - var y = 0;
│ │ │ │ │ - var num = touches.length;
│ │ │ │ │ - var touch;
│ │ │ │ │ - for (var i = 0; i < num; ++i) {
│ │ │ │ │ - touch = this.getTouchClientXY(touches[i]);
│ │ │ │ │ - x += touch.clientX;
│ │ │ │ │ - y += touch.clientY;
│ │ │ │ │ - }
│ │ │ │ │ - evt.clientX = x / num;
│ │ │ │ │ - evt.clientY = y / num;
│ │ │ │ │ - }
│ │ │ │ │ - if (this.includeXY) {
│ │ │ │ │ - evt.xy = this.getMousePosition(evt);
│ │ │ │ │ - }
│ │ │ │ │ - this.triggerEvent(type, evt);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: getTouchClientXY
│ │ │ │ │ - * WebKit has a few bugs for clientX/clientY. This method detects them
│ │ │ │ │ - * and calculate the correct values.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * evt - {Touch} a Touch object from a TouchEvent
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Object} An object with only clientX and clientY properties with the
│ │ │ │ │ - * calculated values.
│ │ │ │ │ - */
│ │ │ │ │ - getTouchClientXY: function(evt) {
│ │ │ │ │ - // olMochWin is to override window, used for testing
│ │ │ │ │ - var win = window.olMockWin || window,
│ │ │ │ │ - winPageX = win.pageXOffset,
│ │ │ │ │ - winPageY = win.pageYOffset,
│ │ │ │ │ - x = evt.clientX,
│ │ │ │ │ - y = evt.clientY;
│ │ │ │ │ -
│ │ │ │ │ - if (evt.pageY === 0 && Math.floor(y) > Math.floor(evt.pageY) ||
│ │ │ │ │ - evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) {
│ │ │ │ │ - // iOS4 include scroll offset in clientX/Y
│ │ │ │ │ - x = x - winPageX;
│ │ │ │ │ - y = y - winPageY;
│ │ │ │ │ - } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX)) {
│ │ │ │ │ - // Some Android browsers have totally bogus values for clientX/Y
│ │ │ │ │ - // when scrolling/zooming a page
│ │ │ │ │ - x = evt.pageX - winPageX;
│ │ │ │ │ - y = evt.pageY - winPageY;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - evt.olClientX = x;
│ │ │ │ │ - evt.olClientY = y;
│ │ │ │ │ -
│ │ │ │ │ - return {
│ │ │ │ │ - clientX: x,
│ │ │ │ │ - clientY: y
│ │ │ │ │ - };
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: clearMouseCache
│ │ │ │ │ - * Clear cached data about the mouse position. This should be called any
│ │ │ │ │ - * time the element that events are registered on changes position
│ │ │ │ │ - * within the page.
│ │ │ │ │ - */
│ │ │ │ │ - clearMouseCache: function() {
│ │ │ │ │ - this.element.scrolls = null;
│ │ │ │ │ - this.element.lefttop = null;
│ │ │ │ │ - this.element.offsets = null;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: getMousePosition
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * evt - {Event}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {} The current xy coordinate of the mouse, adjusted
│ │ │ │ │ - * for offsets
│ │ │ │ │ - */
│ │ │ │ │ - getMousePosition: function(evt) {
│ │ │ │ │ - if (!this.includeXY) {
│ │ │ │ │ - this.clearMouseCache();
│ │ │ │ │ - } else if (!this.element.hasScrollEvent) {
│ │ │ │ │ - OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
│ │ │ │ │ - this.element.hasScrollEvent = true;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (!this.element.scrolls) {
│ │ │ │ │ - var viewportElement = OpenLayers.Util.getViewportElement();
│ │ │ │ │ - this.element.scrolls = [
│ │ │ │ │ - window.pageXOffset || viewportElement.scrollLeft,
│ │ │ │ │ - window.pageYOffset || viewportElement.scrollTop
│ │ │ │ │ - ];
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (!this.element.lefttop) {
│ │ │ │ │ - this.element.lefttop = [
│ │ │ │ │ - (document.documentElement.clientLeft || 0),
│ │ │ │ │ - (document.documentElement.clientTop || 0)
│ │ │ │ │ - ];
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (!this.element.offsets) {
│ │ │ │ │ - this.element.offsets = OpenLayers.Util.pagePosition(this.element);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - return new OpenLayers.Pixel(
│ │ │ │ │ - (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] -
│ │ │ │ │ - this.element.lefttop[0],
│ │ │ │ │ - (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] -
│ │ │ │ │ - this.element.lefttop[1]
│ │ │ │ │ - );
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: addMsTouchListener
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on
│ │ │ │ │ - * type - {String} The event type
│ │ │ │ │ - * handler - {Function} the handler
│ │ │ │ │ - */
│ │ │ │ │ - addMsTouchListener: function(element, type, handler) {
│ │ │ │ │ - var eventHandler = this.eventHandler;
│ │ │ │ │ - var touches = this._msTouches;
│ │ │ │ │ -
│ │ │ │ │ - function msHandler(evt) {
│ │ │ │ │ - handler(OpenLayers.Util.applyDefaults({
│ │ │ │ │ - stopPropagation: function() {
│ │ │ │ │ - for (var i = touches.length - 1; i >= 0; --i) {
│ │ │ │ │ - touches[i].stopPropagation();
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ - preventDefault: function() {
│ │ │ │ │ - for (var i = touches.length - 1; i >= 0; --i) {
│ │ │ │ │ - touches[i].preventDefault();
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ - type: type
│ │ │ │ │ - }, evt));
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - switch (type) {
│ │ │ │ │ - case 'touchstart':
│ │ │ │ │ - return this.addMsTouchListenerStart(element, type, msHandler);
│ │ │ │ │ - case 'touchend':
│ │ │ │ │ - return this.addMsTouchListenerEnd(element, type, msHandler);
│ │ │ │ │ - case 'touchmove':
│ │ │ │ │ - return this.addMsTouchListenerMove(element, type, msHandler);
│ │ │ │ │ - default:
│ │ │ │ │ - throw 'Unknown touch event type';
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: addMsTouchListenerStart
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on
│ │ │ │ │ - * type - {String} The event type
│ │ │ │ │ - * handler - {Function} the handler
│ │ │ │ │ - */
│ │ │ │ │ - addMsTouchListenerStart: function(element, type, handler) {
│ │ │ │ │ - var touches = this._msTouches;
│ │ │ │ │ -
│ │ │ │ │ - var cb = function(e) {
│ │ │ │ │ -
│ │ │ │ │ - var alreadyInArray = false;
│ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) {
│ │ │ │ │ - if (touches[i].pointerId == e.pointerId) {
│ │ │ │ │ - alreadyInArray = true;
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - if (!alreadyInArray) {
│ │ │ │ │ - touches.push(e);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - e.touches = touches.slice();
│ │ │ │ │ - handler(e);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerDown', cb);
│ │ │ │ │ -
│ │ │ │ │ - // Need to also listen for end events to keep the _msTouches list
│ │ │ │ │ - // accurate
│ │ │ │ │ - var internalCb = function(e) {
│ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) {
│ │ │ │ │ - if (touches[i].pointerId == e.pointerId) {
│ │ │ │ │ - touches.splice(i, 1);
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - };
│ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerUp', internalCb);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: addMsTouchListenerMove
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on
│ │ │ │ │ - * type - {String} The event type
│ │ │ │ │ - * handler - {Function} the handler
│ │ │ │ │ - */
│ │ │ │ │ - addMsTouchListenerMove: function(element, type, handler) {
│ │ │ │ │ - var touches = this._msTouches;
│ │ │ │ │ - var cb = function(e) {
│ │ │ │ │ -
│ │ │ │ │ - //Don't fire touch moves when mouse isn't down
│ │ │ │ │ - if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) {
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (touches.length == 1 && touches[0].pageX == e.pageX &&
│ │ │ │ │ - touches[0].pageY == e.pageY) {
│ │ │ │ │ - // don't trigger event when pointer has not moved
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) {
│ │ │ │ │ - if (touches[i].pointerId == e.pointerId) {
│ │ │ │ │ - touches[i] = e;
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - e.touches = touches.slice();
│ │ │ │ │ - handler(e);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerMove', cb);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: addMsTouchListenerEnd
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on
│ │ │ │ │ - * type - {String} The event type
│ │ │ │ │ - * handler - {Function} the handler
│ │ │ │ │ - */
│ │ │ │ │ - addMsTouchListenerEnd: function(element, type, handler) {
│ │ │ │ │ - var touches = this._msTouches;
│ │ │ │ │ -
│ │ │ │ │ - var cb = function(e) {
│ │ │ │ │ -
│ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) {
│ │ │ │ │ - if (touches[i].pointerId == e.pointerId) {
│ │ │ │ │ - touches.splice(i, 1);
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - e.touches = touches.slice();
│ │ │ │ │ - handler(e);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerUp', cb);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Events"
│ │ │ │ │ -});
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ - OpenLayers/Handler.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Events.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Class: OpenLayers.Handler
│ │ │ │ │ - * Base class to construct a higher-level handler for event sequences. All
│ │ │ │ │ - * handlers have activate and deactivate methods. In addition, they have
│ │ │ │ │ - * methods named like browser events. When a handler is activated, any
│ │ │ │ │ - * additional methods named like a browser event is registered as a
│ │ │ │ │ - * listener for the corresponding event. When a handler is deactivated,
│ │ │ │ │ - * those same methods are unregistered as event listeners.
│ │ │ │ │ - *
│ │ │ │ │ - * Handlers also typically have a callbacks object with keys named like
│ │ │ │ │ - * the abstracted events or event sequences that they are in charge of
│ │ │ │ │ - * handling. The controls that wrap handlers define the methods that
│ │ │ │ │ - * correspond to these abstract events - so instead of listening for
│ │ │ │ │ - * individual browser events, they only listen for the abstract events
│ │ │ │ │ - * defined by the handler.
│ │ │ │ │ - *
│ │ │ │ │ - * Handlers are created by controls, which ultimately have the responsibility
│ │ │ │ │ - * of making changes to the the state of the application. Handlers
│ │ │ │ │ - * themselves may make temporary changes, but in general are expected to
│ │ │ │ │ - * return the application in the same state that they found it.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: id
│ │ │ │ │ - * {String}
│ │ │ │ │ - */
│ │ │ │ │ - id: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: control
│ │ │ │ │ - * {}. The control that initialized this handler. The
│ │ │ │ │ - * control is assumed to have a valid map property - that map is used
│ │ │ │ │ - * in the handler's own setMap method.
│ │ │ │ │ - */
│ │ │ │ │ - control: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: map
│ │ │ │ │ - * {}
│ │ │ │ │ - */
│ │ │ │ │ - map: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: keyMask
│ │ │ │ │ - * {Integer} Use bitwise operators and one or more of the OpenLayers.Handler
│ │ │ │ │ - * constants to construct a keyMask. The keyMask is used by
│ │ │ │ │ - * . If the keyMask matches the combination of keys
│ │ │ │ │ - * down on an event, checkModifiers returns true.
│ │ │ │ │ - *
│ │ │ │ │ - * Example:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * // handler only responds if the Shift key is down
│ │ │ │ │ - * handler.keyMask = OpenLayers.Handler.MOD_SHIFT;
│ │ │ │ │ - *
│ │ │ │ │ - * // handler only responds if Ctrl-Shift is down
│ │ │ │ │ - * handler.keyMask = OpenLayers.Handler.MOD_SHIFT |
│ │ │ │ │ - * OpenLayers.Handler.MOD_CTRL;
│ │ │ │ │ - * (end)
│ │ │ │ │ - */
│ │ │ │ │ - keyMask: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: active
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - active: false,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: evt
│ │ │ │ │ - * {Event} This property references the last event handled by the handler.
│ │ │ │ │ - * Note that this property is not part of the stable API. Use of the
│ │ │ │ │ - * evt property should be restricted to controls in the library
│ │ │ │ │ - * or other applications that are willing to update with changes to
│ │ │ │ │ - * the OpenLayers code.
│ │ │ │ │ - */
│ │ │ │ │ - evt: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: touch
│ │ │ │ │ - * {Boolean} Indicates the support of touch events. When touch events are
│ │ │ │ │ - * started touch will be true and all mouse related listeners will do
│ │ │ │ │ - * nothing.
│ │ │ │ │ - */
│ │ │ │ │ - touch: false,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Handler
│ │ │ │ │ - * Construct a handler.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * control - {} The control that initialized this
│ │ │ │ │ - * handler. The control is assumed to have a valid map property; that
│ │ │ │ │ - * map is used in the handler's own setMap method. If a map property
│ │ │ │ │ - * is present in the options argument it will be used instead.
│ │ │ │ │ - * callbacks - {Object} An object whose properties correspond to abstracted
│ │ │ │ │ - * events or sequences of browser events. The values for these
│ │ │ │ │ - * properties are functions defined by the control that get called by
│ │ │ │ │ - * the handler.
│ │ │ │ │ - * options - {Object} An optional object whose properties will be set on
│ │ │ │ │ - * the handler.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(control, callbacks, options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.control = control;
│ │ │ │ │ - this.callbacks = callbacks;
│ │ │ │ │ -
│ │ │ │ │ - var map = this.map || control.map;
│ │ │ │ │ - if (map) {
│ │ │ │ │ - this.setMap(map);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: setMap
│ │ │ │ │ - */
│ │ │ │ │ - setMap: function(map) {
│ │ │ │ │ - this.map = map;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: checkModifiers
│ │ │ │ │ - * Check the keyMask on the handler. If no is set, this always
│ │ │ │ │ - * returns true. If a is set and it matches the combination
│ │ │ │ │ - * of keys down on an event, this returns true.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} The keyMask matches the keys down on an event.
│ │ │ │ │ - */
│ │ │ │ │ - checkModifiers: function(evt) {
│ │ │ │ │ - if (this.keyMask == null) {
│ │ │ │ │ - return true;
│ │ │ │ │ - }
│ │ │ │ │ - /* calculate the keyboard modifier mask for this event */
│ │ │ │ │ - var keyModifiers =
│ │ │ │ │ - (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) |
│ │ │ │ │ - (evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) |
│ │ │ │ │ - (evt.altKey ? OpenLayers.Handler.MOD_ALT : 0) |
│ │ │ │ │ - (evt.metaKey ? OpenLayers.Handler.MOD_META : 0);
│ │ │ │ │ -
│ │ │ │ │ - /* if it differs from the handler object's key mask,
│ │ │ │ │ - bail out of the event handler */
│ │ │ │ │ - return (keyModifiers == this.keyMask);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: activate
│ │ │ │ │ - * Turn on the handler. Returns false if the handler was already active.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} The handler was activated.
│ │ │ │ │ - */
│ │ │ │ │ - activate: function() {
│ │ │ │ │ - if (this.active) {
│ │ │ │ │ - return false;
│ │ │ │ │ - }
│ │ │ │ │ - // register for event handlers defined on this class.
│ │ │ │ │ - var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
│ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ - if (this[events[i]]) {
│ │ │ │ │ - this.register(events[i], this[events[i]]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - this.active = true;
│ │ │ │ │ - return true;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: deactivate
│ │ │ │ │ - * Turn off the handler. Returns false if the handler was already inactive.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} The handler was deactivated.
│ │ │ │ │ - */
│ │ │ │ │ - deactivate: function() {
│ │ │ │ │ - if (!this.active) {
│ │ │ │ │ - return false;
│ │ │ │ │ - }
│ │ │ │ │ - // unregister event handlers defined on this class.
│ │ │ │ │ - var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
│ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ - if (this[events[i]]) {
│ │ │ │ │ - this.unregister(events[i], this[events[i]]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - this.touch = false;
│ │ │ │ │ - this.active = false;
│ │ │ │ │ - return true;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: startTouch
│ │ │ │ │ - * Start touch events, this method must be called by subclasses in
│ │ │ │ │ - * "touchstart" method. When touch events are started will be
│ │ │ │ │ - * true and all mouse related listeners will do nothing.
│ │ │ │ │ - */
│ │ │ │ │ - startTouch: function() {
│ │ │ │ │ - if (!this.touch) {
│ │ │ │ │ - this.touch = true;
│ │ │ │ │ - var events = [
│ │ │ │ │ - "mousedown", "mouseup", "mousemove", "click", "dblclick",
│ │ │ │ │ - "mouseout"
│ │ │ │ │ - ];
│ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ - if (this[events[i]]) {
│ │ │ │ │ - this.unregister(events[i], this[events[i]]);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: callback
│ │ │ │ │ - * Trigger the control's named callback with the given arguments
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * name - {String} The key for the callback that is one of the properties
│ │ │ │ │ - * of the handler's callbacks object.
│ │ │ │ │ - * args - {Array(*)} An array of arguments (any type) with which to call
│ │ │ │ │ - * the callback (defined by the control).
│ │ │ │ │ - */
│ │ │ │ │ - callback: function(name, args) {
│ │ │ │ │ - if (name && this.callbacks[name]) {
│ │ │ │ │ - this.callbacks[name].apply(this.control, args);
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: register
│ │ │ │ │ - * register an event on the map
│ │ │ │ │ - */
│ │ │ │ │ - register: function(name, method) {
│ │ │ │ │ - // TODO: deal with registerPriority in 3.0
│ │ │ │ │ - this.map.events.registerPriority(name, this, method);
│ │ │ │ │ - this.map.events.registerPriority(name, this, this.setEvent);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: unregister
│ │ │ │ │ - * unregister an event from the map
│ │ │ │ │ - */
│ │ │ │ │ - unregister: function(name, method) {
│ │ │ │ │ - this.map.events.unregister(name, this, method);
│ │ │ │ │ - this.map.events.unregister(name, this, this.setEvent);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: setEvent
│ │ │ │ │ - * With each registered browser event, the handler sets its own evt
│ │ │ │ │ - * property. This property can be accessed by controls if needed
│ │ │ │ │ - * to get more information about the event that the handler is
│ │ │ │ │ - * processing.
│ │ │ │ │ - *
│ │ │ │ │ - * This allows modifier keys on the event to be checked (alt, shift, ctrl,
│ │ │ │ │ - * and meta cannot be checked with the keyboard handler). For a
│ │ │ │ │ - * control to determine which modifier keys are associated with the
│ │ │ │ │ - * event that a handler is currently processing, it should access
│ │ │ │ │ - * (code)handler.evt.altKey || handler.evt.shiftKey ||
│ │ │ │ │ - * handler.evt.ctrlKey || handler.evt.metaKey(end).
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * evt - {Event} The browser event.
│ │ │ │ │ - */
│ │ │ │ │ - setEvent: function(evt) {
│ │ │ │ │ - this.evt = evt;
│ │ │ │ │ - return true;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: destroy
│ │ │ │ │ - * Deconstruct the handler.
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - // unregister event listeners
│ │ │ │ │ - this.deactivate();
│ │ │ │ │ - // eliminate circular references
│ │ │ │ │ - this.control = this.map = null;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Handler"
│ │ │ │ │ -});
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_NONE
│ │ │ │ │ - * If set as the , returns false if any key is down.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler.MOD_NONE = 0;
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_SHIFT
│ │ │ │ │ - * If set as the , returns false if Shift is down.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler.MOD_SHIFT = 1;
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_CTRL
│ │ │ │ │ - * If set as the , returns false if Ctrl is down.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler.MOD_CTRL = 2;
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_ALT
│ │ │ │ │ - * If set as the , returns false if Alt is down.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler.MOD_ALT = 4;
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_META
│ │ │ │ │ - * If set as the , returns false if Cmd is down.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Handler.MOD_META = 8;
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ - OpenLayers/Strategy.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Class: OpenLayers.Strategy
│ │ │ │ │ - * Abstract vector layer strategy class. Not to be instantiated directly. Use
│ │ │ │ │ - * one of the strategy subclasses instead.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Strategy = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: layer
│ │ │ │ │ - * {} The layer this strategy belongs to.
│ │ │ │ │ - */
│ │ │ │ │ - layer: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: options
│ │ │ │ │ - * {Object} Any options sent to the constructor.
│ │ │ │ │ - */
│ │ │ │ │ - options: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: active
│ │ │ │ │ - * {Boolean} The control is active.
│ │ │ │ │ - */
│ │ │ │ │ - active: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: autoActivate
│ │ │ │ │ - * {Boolean} The creator of the strategy can set autoActivate to false
│ │ │ │ │ - * to fully control when the protocol is activated and deactivated.
│ │ │ │ │ - * Defaults to true.
│ │ │ │ │ - */
│ │ │ │ │ - autoActivate: true,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: autoDestroy
│ │ │ │ │ - * {Boolean} The creator of the strategy can set autoDestroy to false
│ │ │ │ │ - * to fully control when the strategy is destroyed. Defaults to
│ │ │ │ │ - * true.
│ │ │ │ │ - */
│ │ │ │ │ - autoDestroy: true,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Strategy
│ │ │ │ │ - * Abstract class for vector strategies. Create instances of a subclass.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ - * instance.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.options = options;
│ │ │ │ │ - // set the active property here, so that user cannot override it
│ │ │ │ │ - this.active = false;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - * Clean up the strategy.
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - this.deactivate();
│ │ │ │ │ - this.layer = null;
│ │ │ │ │ - this.options = null;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: setLayer
│ │ │ │ │ - * Called to set the property.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * layer - {}
│ │ │ │ │ - */
│ │ │ │ │ - setLayer: function(layer) {
│ │ │ │ │ - this.layer = layer;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: activate
│ │ │ │ │ - * Activate the strategy. Register any listeners, do appropriate setup.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} True if the strategy was successfully activated or false if
│ │ │ │ │ - * the strategy was already active.
│ │ │ │ │ - */
│ │ │ │ │ - activate: function() {
│ │ │ │ │ - if (!this.active) {
│ │ │ │ │ - this.active = true;
│ │ │ │ │ - return true;
│ │ │ │ │ - }
│ │ │ │ │ - return false;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: deactivate
│ │ │ │ │ - * Deactivate the strategy. Unregister any listeners, do appropriate
│ │ │ │ │ - * tear-down.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} True if the strategy was successfully deactivated or false if
│ │ │ │ │ - * the strategy was already inactive.
│ │ │ │ │ - */
│ │ │ │ │ - deactivate: function() {
│ │ │ │ │ - if (this.active) {
│ │ │ │ │ - this.active = false;
│ │ │ │ │ - return true;
│ │ │ │ │ - }
│ │ │ │ │ - return false;
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Strategy"
│ │ │ │ │ -});
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ OpenLayers/Feature.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │ @@ -6799,10597 +5675,14934 @@
│ │ │ │ │
│ │ │ │ │ },
│ │ │ │ │ 'delete': {
│ │ │ │ │ display: "none"
│ │ │ │ │ }
│ │ │ │ │ };
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Style.js
│ │ │ │ │ + OpenLayers/Format.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ -
│ │ │ │ │ /**
│ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ * @requires OpenLayers/Util.js
│ │ │ │ │ - * @requires OpenLayers/Feature/Vector.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.Style
│ │ │ │ │ - * This class represents a UserStyle obtained
│ │ │ │ │ - * from a SLD, containing styling rules.
│ │ │ │ │ + * Class: OpenLayers.Format
│ │ │ │ │ + * Base class for format reading/writing a variety of formats. Subclasses
│ │ │ │ │ + * of OpenLayers.Format are expected to have read and write methods.
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Style = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: id
│ │ │ │ │ - * {String} A unique id for this session.
│ │ │ │ │ - */
│ │ │ │ │ - id: null,
│ │ │ │ │ +OpenLayers.Format = OpenLayers.Class({
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: name
│ │ │ │ │ - * {String}
│ │ │ │ │ + * Property: options
│ │ │ │ │ + * {Object} A reference to options passed to the constructor.
│ │ │ │ │ */
│ │ │ │ │ - name: null,
│ │ │ │ │ + options: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: title
│ │ │ │ │ - * {String} Title of this style (set if included in SLD)
│ │ │ │ │ + * APIProperty: externalProjection
│ │ │ │ │ + * {} When passed a externalProjection and
│ │ │ │ │ + * internalProjection, the format will reproject the geometries it
│ │ │ │ │ + * reads or writes. The externalProjection is the projection used by
│ │ │ │ │ + * the content which is passed into read or which comes out of write.
│ │ │ │ │ + * In order to reproject, a projection transformation function for the
│ │ │ │ │ + * specified projections must be available. This support may be
│ │ │ │ │ + * provided via proj4js or via a custom transformation function. See
│ │ │ │ │ + * {} for more information on
│ │ │ │ │ + * custom transformations.
│ │ │ │ │ */
│ │ │ │ │ - title: null,
│ │ │ │ │ + externalProjection: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: description
│ │ │ │ │ - * {String} Description of this style (set if abstract is included in SLD)
│ │ │ │ │ + * APIProperty: internalProjection
│ │ │ │ │ + * {} When passed a externalProjection and
│ │ │ │ │ + * internalProjection, the format will reproject the geometries it
│ │ │ │ │ + * reads or writes. The internalProjection is the projection used by
│ │ │ │ │ + * the geometries which are returned by read or which are passed into
│ │ │ │ │ + * write. In order to reproject, a projection transformation function
│ │ │ │ │ + * for the specified projections must be available. This support may be
│ │ │ │ │ + * provided via proj4js or via a custom transformation function. See
│ │ │ │ │ + * {} for more information on
│ │ │ │ │ + * custom transformations.
│ │ │ │ │ */
│ │ │ │ │ - description: null,
│ │ │ │ │ + internalProjection: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: layerName
│ │ │ │ │ - * {} name of the layer that this style belongs to, usually
│ │ │ │ │ - * according to the NamedLayer attribute of an SLD document.
│ │ │ │ │ + * APIProperty: data
│ │ │ │ │ + * {Object} When is true, this is the parsed string sent to
│ │ │ │ │ + * .
│ │ │ │ │ */
│ │ │ │ │ - layerName: null,
│ │ │ │ │ + data: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: isDefault
│ │ │ │ │ - * {Boolean}
│ │ │ │ │ - */
│ │ │ │ │ - isDefault: false,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: rules
│ │ │ │ │ - * {Array()}
│ │ │ │ │ + * APIProperty: keepData
│ │ │ │ │ + * {Object} Maintain a reference () to the most recently read data.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ */
│ │ │ │ │ - rules: null,
│ │ │ │ │ + keepData: false,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: context
│ │ │ │ │ - * {Object} An optional object with properties that symbolizers' property
│ │ │ │ │ - * values should be evaluated against. If no context is specified,
│ │ │ │ │ - * feature.attributes will be used
│ │ │ │ │ + * Constructor: OpenLayers.Format
│ │ │ │ │ + * Instances of this class are not useful. See one of the subclasses.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} An optional object with properties to set on the
│ │ │ │ │ + * format
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * keepData - {Boolean} If true, upon , the data property will be
│ │ │ │ │ + * set to the parsed object (e.g. the json or xml object).
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * An instance of OpenLayers.Format
│ │ │ │ │ */
│ │ │ │ │ - context: null,
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.options = options;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: defaultStyle
│ │ │ │ │ - * {Object} hash of style properties to use as default for merging
│ │ │ │ │ - * rule-based style symbolizers onto. If no rules are defined,
│ │ │ │ │ - * createSymbolizer will return this style. If is set to
│ │ │ │ │ - * true, the defaultStyle will only be taken into account if there are
│ │ │ │ │ - * rules defined.
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Clean up.
│ │ │ │ │ */
│ │ │ │ │ - defaultStyle: null,
│ │ │ │ │ + destroy: function() {},
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: defaultsPerSymbolizer
│ │ │ │ │ - * {Boolean} If set to true, the will extend the symbolizer
│ │ │ │ │ - * of every rule. Properties of the will also be used to set
│ │ │ │ │ - * missing symbolizer properties if the symbolizer has stroke, fill or
│ │ │ │ │ - * graphic set to true. Default is false.
│ │ │ │ │ + * Method: read
│ │ │ │ │ + * Read data from a string, and return an object whose type depends on the
│ │ │ │ │ + * subclass.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * data - {string} Data to read/parse.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * Depends on the subclass
│ │ │ │ │ */
│ │ │ │ │ - defaultsPerSymbolizer: false,
│ │ │ │ │ + read: function(data) {
│ │ │ │ │ + throw new Error('Read not implemented.');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: propertyStyles
│ │ │ │ │ - * {Hash of Boolean} cache of style properties that need to be parsed for
│ │ │ │ │ - * propertyNames. Property names are keys, values won't be used.
│ │ │ │ │ - */
│ │ │ │ │ - propertyStyles: null,
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Style
│ │ │ │ │ - * Creates a UserStyle.
│ │ │ │ │ + * Method: write
│ │ │ │ │ + * Accept an object, and return a string.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * style - {Object} Optional hash of style properties that will be
│ │ │ │ │ - * used as default style for this style object. This style
│ │ │ │ │ - * applies if no rules are specified. Symbolizers defined in
│ │ │ │ │ - * rules will extend this default style.
│ │ │ │ │ - * options - {Object} An optional object with properties to set on the
│ │ │ │ │ - * style.
│ │ │ │ │ + * object - {Object} Object to be serialized
│ │ │ │ │ *
│ │ │ │ │ - * Valid options:
│ │ │ │ │ - * rules - {Array()} List of rules to be added to the
│ │ │ │ │ - * style.
│ │ │ │ │ - *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {}
│ │ │ │ │ + * {String} A string representation of the object.
│ │ │ │ │ */
│ │ │ │ │ - initialize: function(style, options) {
│ │ │ │ │ + write: function(object) {
│ │ │ │ │ + throw new Error('Write not implemented.');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.rules = [];
│ │ │ │ │ - if (options && options.rules) {
│ │ │ │ │ - this.addRules(options.rules);
│ │ │ │ │ - }
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Format"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Geometry/Point.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │
│ │ │ │ │ - // use the default style from OpenLayers.Feature.Vector if no style
│ │ │ │ │ - // was given in the constructor
│ │ │ │ │ - this.setDefaultStyle(style ||
│ │ │ │ │ - OpenLayers.Feature.Vector.style["default"]);
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │
│ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ - },
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/Geometry.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Geometry.Point
│ │ │ │ │ + * Point geometry class.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, {
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - * nullify references to prevent circular references and memory leaks
│ │ │ │ │ + * APIProperty: x
│ │ │ │ │ + * {float}
│ │ │ │ │ */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; i++) {
│ │ │ │ │ - this.rules[i].destroy();
│ │ │ │ │ - this.rules[i] = null;
│ │ │ │ │ - }
│ │ │ │ │ - this.rules = null;
│ │ │ │ │ - this.defaultStyle = null;
│ │ │ │ │ - },
│ │ │ │ │ + x: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: y
│ │ │ │ │ + * {float}
│ │ │ │ │ + */
│ │ │ │ │ + y: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: createSymbolizer
│ │ │ │ │ - * creates a style by applying all feature-dependent rules to the base
│ │ │ │ │ - * style.
│ │ │ │ │ - *
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.Point
│ │ │ │ │ + * Construct a point geometry.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * feature - {} feature to evaluate rules for
│ │ │ │ │ + * x - {float}
│ │ │ │ │ + * y - {float}
│ │ │ │ │ *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Object} symbolizer hash
│ │ │ │ │ */
│ │ │ │ │ - createSymbolizer: function(feature) {
│ │ │ │ │ - var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(
│ │ │ │ │ - OpenLayers.Util.extend({}, this.defaultStyle), feature);
│ │ │ │ │ -
│ │ │ │ │ - var rules = this.rules;
│ │ │ │ │ -
│ │ │ │ │ - var rule, context;
│ │ │ │ │ - var elseRules = [];
│ │ │ │ │ - var appliedRules = false;
│ │ │ │ │ - for (var i = 0, len = rules.length; i < len; i++) {
│ │ │ │ │ - rule = rules[i];
│ │ │ │ │ - // does the rule apply?
│ │ │ │ │ - var applies = rule.evaluate(feature);
│ │ │ │ │ + initialize: function(x, y) {
│ │ │ │ │ + OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
│ │ │ │ │
│ │ │ │ │ - if (applies) {
│ │ │ │ │ - if (rule instanceof OpenLayers.Rule && rule.elseFilter) {
│ │ │ │ │ - elseRules.push(rule);
│ │ │ │ │ - } else {
│ │ │ │ │ - appliedRules = true;
│ │ │ │ │ - this.applySymbolizer(rule, style, feature);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ + this.x = parseFloat(x);
│ │ │ │ │ + this.y = parseFloat(y);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - // if no other rules apply, apply the rules with else filters
│ │ │ │ │ - if (appliedRules == false && elseRules.length > 0) {
│ │ │ │ │ - appliedRules = true;
│ │ │ │ │ - for (var i = 0, len = elseRules.length; i < len; i++) {
│ │ │ │ │ - this.applySymbolizer(elseRules[i], style, feature);
│ │ │ │ │ - }
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: clone
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An exact clone of this OpenLayers.Geometry.Point
│ │ │ │ │ + */
│ │ │ │ │ + clone: function(obj) {
│ │ │ │ │ + if (obj == null) {
│ │ │ │ │ + obj = new OpenLayers.Geometry.Point(this.x, this.y);
│ │ │ │ │ }
│ │ │ │ │
│ │ │ │ │ - // don't display if there were rules but none applied
│ │ │ │ │ - if (rules.length > 0 && appliedRules == false) {
│ │ │ │ │ - style.display = "none";
│ │ │ │ │ - }
│ │ │ │ │ + // catch any randomly tagged-on properties
│ │ │ │ │ + OpenLayers.Util.applyDefaults(obj, this);
│ │ │ │ │
│ │ │ │ │ - if (style.label != null && typeof style.label !== "string") {
│ │ │ │ │ - style.label = String(style.label);
│ │ │ │ │ - }
│ │ │ │ │ + return obj;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - return style;
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: calculateBounds
│ │ │ │ │ + * Create a new Bounds based on the lon/lat
│ │ │ │ │ + */
│ │ │ │ │ + calculateBounds: function() {
│ │ │ │ │ + this.bounds = new OpenLayers.Bounds(this.x, this.y,
│ │ │ │ │ + this.x, this.y);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: applySymbolizer
│ │ │ │ │ + * APIMethod: distanceTo
│ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane).
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * rule - {}
│ │ │ │ │ - * style - {Object}
│ │ │ │ │ - * feature - {}
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Optional properties for configuring the distance
│ │ │ │ │ + * calculation.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * details - {Boolean} Return details from the distance calculation.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the
│ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true,
│ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within
│ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever
│ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false,
│ │ │ │ │ + * details cannot be returned.
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Object} A style with new symbolizer applied.
│ │ │ │ │ + * {Number | Object} The distance between this geometry and the target.
│ │ │ │ │ + * If details is true, the return will be an object with distance,
│ │ │ │ │ + * x0, y0, x1, and x2 properties. The x0 and y0 properties represent
│ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1
│ │ │ │ │ + * properties represent the coordinates of the closest point on the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ */
│ │ │ │ │ - applySymbolizer: function(rule, style, feature) {
│ │ │ │ │ - var symbolizerPrefix = feature.geometry ?
│ │ │ │ │ - this.getSymbolizerPrefix(feature.geometry) :
│ │ │ │ │ - OpenLayers.Style.SYMBOLIZER_PREFIXES[0];
│ │ │ │ │ -
│ │ │ │ │ - var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;
│ │ │ │ │ -
│ │ │ │ │ - if (this.defaultsPerSymbolizer === true) {
│ │ │ │ │ - var defaults = this.defaultStyle;
│ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ - pointRadius: defaults.pointRadius
│ │ │ │ │ - });
│ │ │ │ │ - if (symbolizer.stroke === true || symbolizer.graphic === true) {
│ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ - strokeWidth: defaults.strokeWidth,
│ │ │ │ │ - strokeColor: defaults.strokeColor,
│ │ │ │ │ - strokeOpacity: defaults.strokeOpacity,
│ │ │ │ │ - strokeDashstyle: defaults.strokeDashstyle,
│ │ │ │ │ - strokeLinecap: defaults.strokeLinecap
│ │ │ │ │ - });
│ │ │ │ │ - }
│ │ │ │ │ - if (symbolizer.fill === true || symbolizer.graphic === true) {
│ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ - fillColor: defaults.fillColor,
│ │ │ │ │ - fillOpacity: defaults.fillOpacity
│ │ │ │ │ - });
│ │ │ │ │ - }
│ │ │ │ │ - if (symbolizer.graphic === true) {
│ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ - pointRadius: this.defaultStyle.pointRadius,
│ │ │ │ │ - externalGraphic: this.defaultStyle.externalGraphic,
│ │ │ │ │ - graphicName: this.defaultStyle.graphicName,
│ │ │ │ │ - graphicOpacity: this.defaultStyle.graphicOpacity,
│ │ │ │ │ - graphicWidth: this.defaultStyle.graphicWidth,
│ │ │ │ │ - graphicHeight: this.defaultStyle.graphicHeight,
│ │ │ │ │ - graphicXOffset: this.defaultStyle.graphicXOffset,
│ │ │ │ │ - graphicYOffset: this.defaultStyle.graphicYOffset
│ │ │ │ │ - });
│ │ │ │ │ + distanceTo: function(geometry, options) {
│ │ │ │ │ + var edge = !(options && options.edge === false);
│ │ │ │ │ + var details = edge && options && options.details;
│ │ │ │ │ + var distance, x0, y0, x1, y1, result;
│ │ │ │ │ + if (geometry instanceof OpenLayers.Geometry.Point) {
│ │ │ │ │ + x0 = this.x;
│ │ │ │ │ + y0 = this.y;
│ │ │ │ │ + x1 = geometry.x;
│ │ │ │ │ + y1 = geometry.y;
│ │ │ │ │ + distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
│ │ │ │ │ + result = !details ?
│ │ │ │ │ + distance : {
│ │ │ │ │ + x0: x0,
│ │ │ │ │ + y0: y0,
│ │ │ │ │ + x1: x1,
│ │ │ │ │ + y1: y1,
│ │ │ │ │ + distance: distance
│ │ │ │ │ + };
│ │ │ │ │ + } else {
│ │ │ │ │ + result = geometry.distanceTo(this, options);
│ │ │ │ │ + if (details) {
│ │ │ │ │ + // switch coord order since this geom is target
│ │ │ │ │ + result = {
│ │ │ │ │ + x0: result.x1,
│ │ │ │ │ + y0: result.y1,
│ │ │ │ │ + x1: result.x0,
│ │ │ │ │ + y1: result.y0,
│ │ │ │ │ + distance: result.distance
│ │ │ │ │ + };
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ -
│ │ │ │ │ - // merge the style with the current style
│ │ │ │ │ - return this.createLiterals(
│ │ │ │ │ - OpenLayers.Util.extend(style, symbolizer), feature);
│ │ │ │ │ + return result;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: createLiterals
│ │ │ │ │ - * creates literals for all style properties that have an entry in
│ │ │ │ │ - * .
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: equals
│ │ │ │ │ + * Determine whether another geometry is equivalent to this one. Geometries
│ │ │ │ │ + * are considered equivalent if all components have the same coordinates.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * style - {Object} style to create literals for. Will be modified
│ │ │ │ │ - * inline.
│ │ │ │ │ - * feature - {Object}
│ │ │ │ │ - *
│ │ │ │ │ + * geom - {} The geometry to test.
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Object} the modified style
│ │ │ │ │ + * {Boolean} The supplied geometry is equivalent to this geometry.
│ │ │ │ │ */
│ │ │ │ │ - createLiterals: function(style, feature) {
│ │ │ │ │ - var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);
│ │ │ │ │ - OpenLayers.Util.extend(context, this.context);
│ │ │ │ │ -
│ │ │ │ │ - for (var i in this.propertyStyles) {
│ │ │ │ │ - style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i);
│ │ │ │ │ + equals: function(geom) {
│ │ │ │ │ + var equals = false;
│ │ │ │ │ + if (geom != null) {
│ │ │ │ │ + equals = ((this.x == geom.x && this.y == geom.y) ||
│ │ │ │ │ + (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y)));
│ │ │ │ │ }
│ │ │ │ │ - return style;
│ │ │ │ │ + return equals;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: findPropertyStyles
│ │ │ │ │ - * Looks into all rules for this style and the defaultStyle to collect
│ │ │ │ │ - * all the style hash property names containing ${...} strings that have
│ │ │ │ │ - * to be replaced using the createLiteral method before returning them.
│ │ │ │ │ - *
│ │ │ │ │ + * Method: toShortString
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Object} hash of property names that need createLiteral parsing. The
│ │ │ │ │ - * name of the property is the key, and the value is true;
│ │ │ │ │ + * {String} Shortened String representation of Point object.
│ │ │ │ │ + * (ex. "5, 42")
│ │ │ │ │ */
│ │ │ │ │ - findPropertyStyles: function() {
│ │ │ │ │ - var propertyStyles = {};
│ │ │ │ │ -
│ │ │ │ │ - // check the default style
│ │ │ │ │ - var style = this.defaultStyle;
│ │ │ │ │ - this.addPropertyStyles(propertyStyles, style);
│ │ │ │ │ + toShortString: function() {
│ │ │ │ │ + return (this.x + ", " + this.y);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - // walk through all rules to check for properties in their symbolizer
│ │ │ │ │ - var rules = this.rules;
│ │ │ │ │ - var symbolizer, value;
│ │ │ │ │ - for (var i = 0, len = rules.length; i < len; i++) {
│ │ │ │ │ - symbolizer = rules[i].symbolizer;
│ │ │ │ │ - for (var key in symbolizer) {
│ │ │ │ │ - value = symbolizer[key];
│ │ │ │ │ - if (typeof value == "object") {
│ │ │ │ │ - // symbolizer key is "Point", "Line" or "Polygon"
│ │ │ │ │ - this.addPropertyStyles(propertyStyles, value);
│ │ │ │ │ - } else {
│ │ │ │ │ - // symbolizer is a hash of style properties
│ │ │ │ │ - this.addPropertyStyles(propertyStyles, symbolizer);
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - return propertyStyles;
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: move
│ │ │ │ │ + * Moves a geometry by the given displacement along positive x and y axes.
│ │ │ │ │ + * This modifies the position of the geometry and clears the cached
│ │ │ │ │ + * bounds.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * x - {Float} Distance to move geometry in positive x direction.
│ │ │ │ │ + * y - {Float} Distance to move geometry in positive y direction.
│ │ │ │ │ + */
│ │ │ │ │ + move: function(x, y) {
│ │ │ │ │ + this.x = this.x + x;
│ │ │ │ │ + this.y = this.y + y;
│ │ │ │ │ + this.clearBounds();
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: addPropertyStyles
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: rotate
│ │ │ │ │ + * Rotate a point around another.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * propertyStyles - {Object} hash to add new property styles to. Will be
│ │ │ │ │ - * modified inline
│ │ │ │ │ - * symbolizer - {Object} search this symbolizer for property styles
│ │ │ │ │ - *
│ │ │ │ │ + * angle - {Float} Rotation angle in degrees (measured counterclockwise
│ │ │ │ │ + * from the positive x-axis)
│ │ │ │ │ + * origin - {} Center point for the rotation
│ │ │ │ │ + */
│ │ │ │ │ + rotate: function(angle, origin) {
│ │ │ │ │ + angle *= Math.PI / 180;
│ │ │ │ │ + var radius = this.distanceTo(origin);
│ │ │ │ │ + var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x);
│ │ │ │ │ + this.x = origin.x + (radius * Math.cos(theta));
│ │ │ │ │ + this.y = origin.y + (radius * Math.sin(theta));
│ │ │ │ │ + this.clearBounds();
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getCentroid
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Object} propertyStyles hash
│ │ │ │ │ + * {} The centroid of the collection
│ │ │ │ │ */
│ │ │ │ │ - addPropertyStyles: function(propertyStyles, symbolizer) {
│ │ │ │ │ - var property;
│ │ │ │ │ - for (var key in symbolizer) {
│ │ │ │ │ - property = symbolizer[key];
│ │ │ │ │ - if (typeof property == "string" &&
│ │ │ │ │ - property.match(/\$\{\w+\}/)) {
│ │ │ │ │ - propertyStyles[key] = true;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - return propertyStyles;
│ │ │ │ │ + getCentroid: function() {
│ │ │ │ │ + return new OpenLayers.Geometry.Point(this.x, this.y);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: addRules
│ │ │ │ │ - * Adds rules to this style.
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: resize
│ │ │ │ │ + * Resize a point relative to some origin. For points, this has the effect
│ │ │ │ │ + * of scaling a vector (from the origin to the point). This method is
│ │ │ │ │ + * more useful on geometry collection subclasses.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * rules - {Array()}
│ │ │ │ │ + * scale - {Float} Ratio of the new distance from the origin to the old
│ │ │ │ │ + * distance from the origin. A scale of 2 doubles the
│ │ │ │ │ + * distance between the point and origin.
│ │ │ │ │ + * origin - {} Point of origin for resizing
│ │ │ │ │ + * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} - The current geometry.
│ │ │ │ │ */
│ │ │ │ │ - addRules: function(rules) {
│ │ │ │ │ - Array.prototype.push.apply(this.rules, rules);
│ │ │ │ │ - this.propertyStyles = this.findPropertyStyles();
│ │ │ │ │ + resize: function(scale, origin, ratio) {
│ │ │ │ │ + ratio = (ratio == undefined) ? 1 : ratio;
│ │ │ │ │ + this.x = origin.x + (scale * ratio * (this.x - origin.x));
│ │ │ │ │ + this.y = origin.y + (scale * (this.y - origin.y));
│ │ │ │ │ + this.clearBounds();
│ │ │ │ │ + return this;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: setDefaultStyle
│ │ │ │ │ - * Sets the default style for this style object.
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: intersects
│ │ │ │ │ + * Determine if the input geometry intersects this one.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * style - {Object} Hash of style properties
│ │ │ │ │ + * geometry - {} Any type of geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The input geometry intersects this one.
│ │ │ │ │ */
│ │ │ │ │ - setDefaultStyle: function(style) {
│ │ │ │ │ - this.defaultStyle = style;
│ │ │ │ │ - this.propertyStyles = this.findPropertyStyles();
│ │ │ │ │ + intersects: function(geometry) {
│ │ │ │ │ + var intersect = false;
│ │ │ │ │ + if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
│ │ │ │ │ + intersect = this.equals(geometry);
│ │ │ │ │ + } else {
│ │ │ │ │ + intersect = geometry.intersects(this);
│ │ │ │ │ + }
│ │ │ │ │ + return intersect;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: getSymbolizerPrefix
│ │ │ │ │ - * Returns the correct symbolizer prefix according to the
│ │ │ │ │ - * geometry type of the passed geometry
│ │ │ │ │ + * APIMethod: transform
│ │ │ │ │ + * Translate the x,y properties of the point from source to dest.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * geometry - {}
│ │ │ │ │ + * source - {}
│ │ │ │ │ + * dest - {}
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {String} key of the according symbolizer
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - getSymbolizerPrefix: function(geometry) {
│ │ │ │ │ - var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;
│ │ │ │ │ - for (var i = 0, len = prefixes.length; i < len; i++) {
│ │ │ │ │ - if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {
│ │ │ │ │ - return prefixes[i];
│ │ │ │ │ - }
│ │ │ │ │ + transform: function(source, dest) {
│ │ │ │ │ + if ((source && dest)) {
│ │ │ │ │ + OpenLayers.Projection.transform(
│ │ │ │ │ + this, source, dest);
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ }
│ │ │ │ │ + return this;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: clone
│ │ │ │ │ - * Clones this style.
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: getVertices
│ │ │ │ │ + * Return a list of all points in this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are
│ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not
│ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will
│ │ │ │ │ + * be returned.
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} Clone of this style.
│ │ │ │ │ + * {Array} A list of all vertices in the geometry.
│ │ │ │ │ */
│ │ │ │ │ - clone: function() {
│ │ │ │ │ - var options = OpenLayers.Util.extend({}, this);
│ │ │ │ │ - // clone rules
│ │ │ │ │ - if (this.rules) {
│ │ │ │ │ - options.rules = [];
│ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; ++i) {
│ │ │ │ │ - options.rules.push(this.rules[i].clone());
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - // clone context
│ │ │ │ │ - options.context = this.context && OpenLayers.Util.extend({}, this.context);
│ │ │ │ │ - //clone default style
│ │ │ │ │ - var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle);
│ │ │ │ │ - return new OpenLayers.Style(defaultStyle, options);
│ │ │ │ │ + getVertices: function(nodes) {
│ │ │ │ │ + return [this];
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Style"
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Point"
│ │ │ │ │ });
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Function: createLiteral
│ │ │ │ │ - * converts a style value holding a combination of PropertyName and Literal
│ │ │ │ │ - * into a Literal, taking the property values from the passed features.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * value - {String} value to parse. If this string contains a construct like
│ │ │ │ │ - * "foo ${bar}", then "foo " will be taken as literal, and "${bar}"
│ │ │ │ │ - * will be replaced by the value of the "bar" attribute of the passed
│ │ │ │ │ - * feature.
│ │ │ │ │ - * context - {Object} context to take attribute values from
│ │ │ │ │ - * feature - {} optional feature to pass to
│ │ │ │ │ - * for evaluating functions in the
│ │ │ │ │ - * context.
│ │ │ │ │ - * property - {String} optional, name of the property for which the literal is
│ │ │ │ │ - * being created for evaluating functions in the context.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} the parsed value. In the example of the value parameter above, the
│ │ │ │ │ - * result would be "foo valueOfBar", assuming that the passed feature has an
│ │ │ │ │ - * attribute named "bar" with the value "valueOfBar".
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Style.createLiteral = function(value, context, feature, property) {
│ │ │ │ │ - if (typeof value == "string" && value.indexOf("${") != -1) {
│ │ │ │ │ - value = OpenLayers.String.format(value, context, [feature, property]);
│ │ │ │ │ - value = (isNaN(value) || !value) ? value : parseFloat(value);
│ │ │ │ │ - }
│ │ │ │ │ - return value;
│ │ │ │ │ -};
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES
│ │ │ │ │ - * {Array} prefixes of the sld symbolizers. These are the
│ │ │ │ │ - * same as the main geometry types
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text',
│ │ │ │ │ - 'Raster'
│ │ │ │ │ -];
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/StyleMap.js
│ │ │ │ │ + OpenLayers/Geometry/Collection.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Style.js
│ │ │ │ │ - * @requires OpenLayers/Feature/Vector.js
│ │ │ │ │ + * @requires OpenLayers/Geometry.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.StyleMap
│ │ │ │ │ + * Class: OpenLayers.Geometry.Collection
│ │ │ │ │ + * A Collection is exactly what it sounds like: A collection of different
│ │ │ │ │ + * Geometries. These are stored in the local parameter (which
│ │ │ │ │ + * can be passed as a parameter to the constructor).
│ │ │ │ │ + *
│ │ │ │ │ + * As new geometries are added to the collection, they are NOT cloned.
│ │ │ │ │ + * When removing geometries, they need to be specified by reference (ie you
│ │ │ │ │ + * have to pass in the *exact* geometry to be removed).
│ │ │ │ │ + *
│ │ │ │ │ + * The and functions here merely iterate through
│ │ │ │ │ + * the components, summing their respective areas and lengths.
│ │ │ │ │ + *
│ │ │ │ │ + * Create a new instance with the constructor.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.StyleMap = OpenLayers.Class({
│ │ │ │ │ +OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: styles
│ │ │ │ │ - * {Object} Hash of {}, keyed by names of well known
│ │ │ │ │ - * rendering intents (e.g. "default", "temporary", "select", "delete").
│ │ │ │ │ + * APIProperty: components
│ │ │ │ │ + * {Array()} The component parts of this geometry
│ │ │ │ │ */
│ │ │ │ │ - styles: null,
│ │ │ │ │ + components: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: extendDefault
│ │ │ │ │ - * {Boolean} if true, every render intent will extend the symbolizers
│ │ │ │ │ - * specified for the "default" intent at rendering time. Otherwise, every
│ │ │ │ │ - * rendering intent will be treated as a completely independent style.
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null value means the
│ │ │ │ │ + * component types are not restricted.
│ │ │ │ │ */
│ │ │ │ │ - extendDefault: true,
│ │ │ │ │ + componentTypes: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Constructor: OpenLayers.StyleMap
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * style - {Object} Optional. Either a style hash, or a style object, or
│ │ │ │ │ - * a hash of style objects (style hashes) keyed by rendering
│ │ │ │ │ - * intent. If just one style hash or style object is passed,
│ │ │ │ │ - * this will be used for all known render intents (default,
│ │ │ │ │ - * select, temporary)
│ │ │ │ │ - * options - {Object} optional hash of additional options for this
│ │ │ │ │ - * instance
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.Collection
│ │ │ │ │ + * Creates a Geometry Collection -- a list of geoms.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()} Optional array of geometries
│ │ │ │ │ + *
│ │ │ │ │ */
│ │ │ │ │ - initialize: function(style, options) {
│ │ │ │ │ - this.styles = {
│ │ │ │ │ - "default": new OpenLayers.Style(
│ │ │ │ │ - OpenLayers.Feature.Vector.style["default"]),
│ │ │ │ │ - "select": new OpenLayers.Style(
│ │ │ │ │ - OpenLayers.Feature.Vector.style["select"]),
│ │ │ │ │ - "temporary": new OpenLayers.Style(
│ │ │ │ │ - OpenLayers.Feature.Vector.style["temporary"]),
│ │ │ │ │ - "delete": new OpenLayers.Style(
│ │ │ │ │ - OpenLayers.Feature.Vector.style["delete"])
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // take whatever the user passed as style parameter and convert it
│ │ │ │ │ - // into parts of stylemap.
│ │ │ │ │ - if (style instanceof OpenLayers.Style) {
│ │ │ │ │ - // user passed a style object
│ │ │ │ │ - this.styles["default"] = style;
│ │ │ │ │ - this.styles["select"] = style;
│ │ │ │ │ - this.styles["temporary"] = style;
│ │ │ │ │ - this.styles["delete"] = style;
│ │ │ │ │ - } else if (typeof style == "object") {
│ │ │ │ │ - for (var key in style) {
│ │ │ │ │ - if (style[key] instanceof OpenLayers.Style) {
│ │ │ │ │ - // user passed a hash of style objects
│ │ │ │ │ - this.styles[key] = style[key];
│ │ │ │ │ - } else if (typeof style[key] == "object") {
│ │ │ │ │ - // user passsed a hash of style hashes
│ │ │ │ │ - this.styles[key] = new OpenLayers.Style(style[key]);
│ │ │ │ │ - } else {
│ │ │ │ │ - // user passed a style hash (i.e. symbolizer)
│ │ │ │ │ - this.styles["default"] = new OpenLayers.Style(style);
│ │ │ │ │ - this.styles["select"] = new OpenLayers.Style(style);
│ │ │ │ │ - this.styles["temporary"] = new OpenLayers.Style(style);
│ │ │ │ │ - this.styles["delete"] = new OpenLayers.Style(style);
│ │ │ │ │ - break;
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ + initialize: function(components) {
│ │ │ │ │ + OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
│ │ │ │ │ + this.components = [];
│ │ │ │ │ + if (components != null) {
│ │ │ │ │ + this.addComponents(components);
│ │ │ │ │ }
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: destroy
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Destroy this geometry.
│ │ │ │ │ */
│ │ │ │ │ destroy: function() {
│ │ │ │ │ - for (var key in this.styles) {
│ │ │ │ │ - this.styles[key].destroy();
│ │ │ │ │ + this.components.length = 0;
│ │ │ │ │ + this.components = null;
│ │ │ │ │ + OpenLayers.Geometry.prototype.destroy.apply(this, arguments);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: clone
│ │ │ │ │ + * Clone this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An exact clone of this collection
│ │ │ │ │ + */
│ │ │ │ │ + clone: function() {
│ │ │ │ │ + var geometry = eval("new " + this.CLASS_NAME + "()");
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + geometry.addComponent(this.components[i].clone());
│ │ │ │ │ }
│ │ │ │ │ - this.styles = null;
│ │ │ │ │ +
│ │ │ │ │ + // catch any randomly tagged-on properties
│ │ │ │ │ + OpenLayers.Util.applyDefaults(geometry, this);
│ │ │ │ │ +
│ │ │ │ │ + return geometry;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: createSymbolizer
│ │ │ │ │ - * Creates the symbolizer for a feature for a render intent.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * feature - {} The feature to evaluate the rules
│ │ │ │ │ - * of the intended style against.
│ │ │ │ │ - * intent - {String} The intent determines the symbolizer that will be
│ │ │ │ │ - * used to draw the feature. Well known intents are "default"
│ │ │ │ │ - * (for just drawing the features), "select" (for selected
│ │ │ │ │ - * features) and "temporary" (for drawing features).
│ │ │ │ │ + * Method: getComponentsString
│ │ │ │ │ + * Get a string representing the components for this collection
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Object} symbolizer hash
│ │ │ │ │ + * {String} A string representation of the components of this geometry
│ │ │ │ │ */
│ │ │ │ │ - createSymbolizer: function(feature, intent) {
│ │ │ │ │ - if (!feature) {
│ │ │ │ │ - feature = new OpenLayers.Feature.Vector();
│ │ │ │ │ + getComponentsString: function() {
│ │ │ │ │ + var strings = [];
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + strings.push(this.components[i].toShortString());
│ │ │ │ │ }
│ │ │ │ │ - if (!this.styles[intent]) {
│ │ │ │ │ - intent = "default";
│ │ │ │ │ + return strings.join(",");
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: calculateBounds
│ │ │ │ │ + * Recalculate the bounds by iterating through the components and
│ │ │ │ │ + * calling calling extendBounds() on each item.
│ │ │ │ │ + */
│ │ │ │ │ + calculateBounds: function() {
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ + var bounds = new OpenLayers.Bounds();
│ │ │ │ │ + var components = this.components;
│ │ │ │ │ + if (components) {
│ │ │ │ │ + for (var i = 0, len = components.length; i < len; i++) {
│ │ │ │ │ + bounds.extend(components[i].getBounds());
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ - feature.renderIntent = intent;
│ │ │ │ │ - var defaultSymbolizer = {};
│ │ │ │ │ - if (this.extendDefault && intent != "default") {
│ │ │ │ │ - defaultSymbolizer = this.styles["default"].createSymbolizer(feature);
│ │ │ │ │ + // to preserve old behavior, we only set bounds if non-null
│ │ │ │ │ + // in the future, we could add bounds.isEmpty()
│ │ │ │ │ + if (bounds.left != null && bounds.bottom != null &&
│ │ │ │ │ + bounds.right != null && bounds.top != null) {
│ │ │ │ │ + this.setBounds(bounds);
│ │ │ │ │ }
│ │ │ │ │ - return OpenLayers.Util.extend(defaultSymbolizer,
│ │ │ │ │ - this.styles[intent].createSymbolizer(feature));
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: addUniqueValueRules
│ │ │ │ │ - * Convenience method to create comparison rules for unique values of a
│ │ │ │ │ - * property. The rules will be added to the style object for a specified
│ │ │ │ │ - * rendering intent. This method is a shortcut for creating something like
│ │ │ │ │ - * the "unique value legends" familiar from well known desktop GIS systems
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: addComponents
│ │ │ │ │ + * Add components to this geometry.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * renderIntent - {String} rendering intent to add the rules to
│ │ │ │ │ - * property - {String} values of feature attributes to create the
│ │ │ │ │ - * rules for
│ │ │ │ │ - * symbolizers - {Object} Hash of symbolizers, keyed by the desired
│ │ │ │ │ - * property values
│ │ │ │ │ - * context - {Object} An optional object with properties that
│ │ │ │ │ - * symbolizers' property values should be evaluated
│ │ │ │ │ - * against. If no context is specified, feature.attributes
│ │ │ │ │ - * will be used
│ │ │ │ │ + * components - {Array()} An array of geometries to add
│ │ │ │ │ */
│ │ │ │ │ - addUniqueValueRules: function(renderIntent, property, symbolizers, context) {
│ │ │ │ │ - var rules = [];
│ │ │ │ │ - for (var value in symbolizers) {
│ │ │ │ │ - rules.push(new OpenLayers.Rule({
│ │ │ │ │ - symbolizer: symbolizers[value],
│ │ │ │ │ - context: context,
│ │ │ │ │ - filter: new OpenLayers.Filter.Comparison({
│ │ │ │ │ - type: OpenLayers.Filter.Comparison.EQUAL_TO,
│ │ │ │ │ - property: property,
│ │ │ │ │ - value: value
│ │ │ │ │ - })
│ │ │ │ │ - }));
│ │ │ │ │ + addComponents: function(components) {
│ │ │ │ │ + if (!(OpenLayers.Util.isArray(components))) {
│ │ │ │ │ + components = [components];
│ │ │ │ │ + }
│ │ │ │ │ + for (var i = 0, len = components.length; i < len; i++) {
│ │ │ │ │ + this.addComponent(components[i]);
│ │ │ │ │ }
│ │ │ │ │ - this.styles[renderIntent].addRules(rules);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.StyleMap"
│ │ │ │ │ -});
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ - OpenLayers/Icon.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: addComponent
│ │ │ │ │ + * Add a new component (geometry) to the collection. If this.componentTypes
│ │ │ │ │ + * is set, then the component class name must be in the componentTypes array.
│ │ │ │ │ + *
│ │ │ │ │ + * The bounds cache is reset.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * component - {} A geometry to add
│ │ │ │ │ + * index - {int} Optional index into the array to insert the component
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The component geometry was successfully added
│ │ │ │ │ + */
│ │ │ │ │ + addComponent: function(component, index) {
│ │ │ │ │ + var added = false;
│ │ │ │ │ + if (component) {
│ │ │ │ │ + if (this.componentTypes == null ||
│ │ │ │ │ + (OpenLayers.Util.indexOf(this.componentTypes,
│ │ │ │ │ + component.CLASS_NAME) > -1)) {
│ │ │ │ │
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ + if (index != null && (index < this.components.length)) {
│ │ │ │ │ + var components1 = this.components.slice(0, index);
│ │ │ │ │ + var components2 = this.components.slice(index,
│ │ │ │ │ + this.components.length);
│ │ │ │ │ + components1.push(component);
│ │ │ │ │ + this.components = components1.concat(components2);
│ │ │ │ │ + } else {
│ │ │ │ │ + this.components.push(component);
│ │ │ │ │ + }
│ │ │ │ │ + component.parent = this;
│ │ │ │ │ + this.clearBounds();
│ │ │ │ │ + added = true;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return added;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - */
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: removeComponents
│ │ │ │ │ + * Remove components from this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()} The components to be removed
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} A component was removed.
│ │ │ │ │ + */
│ │ │ │ │ + removeComponents: function(components) {
│ │ │ │ │ + var removed = false;
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Class: OpenLayers.Icon
│ │ │ │ │ - *
│ │ │ │ │ - * The icon represents a graphical icon on the screen. Typically used in
│ │ │ │ │ - * conjunction with a to represent markers on a screen.
│ │ │ │ │ - *
│ │ │ │ │ - * An icon has a url, size and position. It also contains an offset which
│ │ │ │ │ - * allows the center point to be represented correctly. This can be
│ │ │ │ │ - * provided either as a fixed offset or a function provided to calculate
│ │ │ │ │ - * the desired offset.
│ │ │ │ │ - *
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Icon = OpenLayers.Class({
│ │ │ │ │ + if (!(OpenLayers.Util.isArray(components))) {
│ │ │ │ │ + components = [components];
│ │ │ │ │ + }
│ │ │ │ │ + for (var i = components.length - 1; i >= 0; --i) {
│ │ │ │ │ + removed = this.removeComponent(components[i]) || removed;
│ │ │ │ │ + }
│ │ │ │ │ + return removed;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: url
│ │ │ │ │ - * {String} image url
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: removeComponent
│ │ │ │ │ + * Remove a component from this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * component - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The component was removed.
│ │ │ │ │ */
│ │ │ │ │ - url: null,
│ │ │ │ │ + removeComponent: function(component) {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: size
│ │ │ │ │ - * {|Object} An OpenLayers.Size or
│ │ │ │ │ - * an object with a 'w' and 'h' properties.
│ │ │ │ │ - */
│ │ │ │ │ - size: null,
│ │ │ │ │ + OpenLayers.Util.removeItem(this.components, component);
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: offset
│ │ │ │ │ - * {|Object} distance in pixels to offset the
│ │ │ │ │ - * image when being rendered. An OpenLayers.Pixel or an object
│ │ │ │ │ - * with a 'x' and 'y' properties.
│ │ │ │ │ - */
│ │ │ │ │ - offset: null,
│ │ │ │ │ + // clearBounds() so that it gets recalculated on the next call
│ │ │ │ │ + // to this.getBounds();
│ │ │ │ │ + this.clearBounds();
│ │ │ │ │ + return true;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: calculateOffset
│ │ │ │ │ - * {Function} Function to calculate the offset (based on the size)
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getLength
│ │ │ │ │ + * Calculate the length of this geometry
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The length of the geometry
│ │ │ │ │ */
│ │ │ │ │ - calculateOffset: null,
│ │ │ │ │ + getLength: function() {
│ │ │ │ │ + var length = 0.0;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + length += this.components[i].getLength();
│ │ │ │ │ + }
│ │ │ │ │ + return length;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: imageDiv
│ │ │ │ │ - * {DOMElement}
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getArea
│ │ │ │ │ + * Calculate the area of this geometry. Note how this function is overridden
│ │ │ │ │ + * in .
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The area of the collection by summing its parts
│ │ │ │ │ */
│ │ │ │ │ - imageDiv: null,
│ │ │ │ │ + getArea: function() {
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + area += this.components[i].getArea();
│ │ │ │ │ + }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: px
│ │ │ │ │ - * {|Object} An OpenLayers.Pixel or an object
│ │ │ │ │ - * with a 'x' and 'y' properties.
│ │ │ │ │ + * APIMethod: getGeodesicArea
│ │ │ │ │ + * Calculate the approximate area of the polygon were it projected onto
│ │ │ │ │ + * the earth.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * projection - {} The spatial reference system
│ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is
│ │ │ │ │ + * assumed.
│ │ │ │ │ + *
│ │ │ │ │ + * Reference:
│ │ │ │ │ + * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
│ │ │ │ │ + * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
│ │ │ │ │ + * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {float} The approximate geodesic area of the geometry in square meters.
│ │ │ │ │ */
│ │ │ │ │ - px: null,
│ │ │ │ │ + getGeodesicArea: function(projection) {
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + area += this.components[i].getGeodesicArea(projection);
│ │ │ │ │ + }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Icon
│ │ │ │ │ - * Creates an icon, which is an image tag in a div.
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getCentroid
│ │ │ │ │ *
│ │ │ │ │ - * url - {String}
│ │ │ │ │ - * size - {|Object} An OpenLayers.Size or an
│ │ │ │ │ - * object with a 'w' and 'h'
│ │ │ │ │ - * properties.
│ │ │ │ │ - * offset - {|Object} An OpenLayers.Pixel or an
│ │ │ │ │ - * object with a 'x' and 'y'
│ │ │ │ │ - * properties.
│ │ │ │ │ - * calculateOffset - {Function}
│ │ │ │ │ + * Compute the centroid for this geometry collection.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * weighted - {Boolean} Perform the getCentroid computation recursively,
│ │ │ │ │ + * returning an area weighted average of all geometries in this collection.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} The centroid of the collection
│ │ │ │ │ */
│ │ │ │ │ - initialize: function(url, size, offset, calculateOffset) {
│ │ │ │ │ - this.url = url;
│ │ │ │ │ - this.size = size || {
│ │ │ │ │ - w: 20,
│ │ │ │ │ - h: 20
│ │ │ │ │ - };
│ │ │ │ │ - this.offset = offset || {
│ │ │ │ │ - x: -(this.size.w / 2),
│ │ │ │ │ - y: -(this.size.h / 2)
│ │ │ │ │ - };
│ │ │ │ │ - this.calculateOffset = calculateOffset;
│ │ │ │ │ + getCentroid: function(weighted) {
│ │ │ │ │ + if (!weighted) {
│ │ │ │ │ + return this.components.length && this.components[0].getCentroid();
│ │ │ │ │ + }
│ │ │ │ │ + var len = this.components.length;
│ │ │ │ │ + if (!len) {
│ │ │ │ │ + return false;
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - var id = OpenLayers.Util.createUniqueID("OL_Icon_");
│ │ │ │ │ - this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
│ │ │ │ │ - },
│ │ │ │ │ + var areas = [];
│ │ │ │ │ + var centroids = [];
│ │ │ │ │ + var areaSum = 0;
│ │ │ │ │ + var minArea = Number.MAX_VALUE;
│ │ │ │ │ + var component;
│ │ │ │ │ + for (var i = 0; i < len; ++i) {
│ │ │ │ │ + component = this.components[i];
│ │ │ │ │ + var area = component.getArea();
│ │ │ │ │ + var centroid = component.getCentroid(true);
│ │ │ │ │ + if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) {
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + areas.push(area);
│ │ │ │ │ + areaSum += area;
│ │ │ │ │ + minArea = (area < minArea && area > 0) ? area : minArea;
│ │ │ │ │ + centroids.push(centroid);
│ │ │ │ │ + }
│ │ │ │ │ + len = areas.length;
│ │ │ │ │ + if (areaSum === 0) {
│ │ │ │ │ + // all the components in this collection have 0 area
│ │ │ │ │ + // probably a collection of points -- weight all the points the same
│ │ │ │ │ + for (var i = 0; i < len; ++i) {
│ │ │ │ │ + areas[i] = 1;
│ │ │ │ │ + }
│ │ │ │ │ + areaSum = areas.length;
│ │ │ │ │ + } else {
│ │ │ │ │ + // normalize all the areas where the smallest area will get
│ │ │ │ │ + // a value of 1
│ │ │ │ │ + for (var i = 0; i < len; ++i) {
│ │ │ │ │ + areas[i] /= minArea;
│ │ │ │ │ + }
│ │ │ │ │ + areaSum /= minArea;
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: destroy
│ │ │ │ │ - * Nullify references and remove event listeners to prevent circular
│ │ │ │ │ - * references and memory leaks
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - // erase any drawn elements
│ │ │ │ │ - this.erase();
│ │ │ │ │ + var xSum = 0,
│ │ │ │ │ + ySum = 0,
│ │ │ │ │ + centroid, area;
│ │ │ │ │ + for (var i = 0; i < len; ++i) {
│ │ │ │ │ + centroid = centroids[i];
│ │ │ │ │ + area = areas[i];
│ │ │ │ │ + xSum += centroid.x * area;
│ │ │ │ │ + ySum += centroid.y * area;
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
│ │ │ │ │ - this.imageDiv.innerHTML = "";
│ │ │ │ │ - this.imageDiv = null;
│ │ │ │ │ + return new OpenLayers.Geometry.Point(xSum / areaSum, ySum / areaSum);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: clone
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getGeodesicLength
│ │ │ │ │ + * Calculate the approximate length of the geometry were it projected onto
│ │ │ │ │ + * the earth.
│ │ │ │ │ + *
│ │ │ │ │ + * projection - {} The spatial reference system
│ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is
│ │ │ │ │ + * assumed.
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} A fresh copy of the icon.
│ │ │ │ │ + * {Float} The appoximate geodesic length of the geometry in meters.
│ │ │ │ │ */
│ │ │ │ │ - clone: function() {
│ │ │ │ │ - return new OpenLayers.Icon(this.url,
│ │ │ │ │ - this.size,
│ │ │ │ │ - this.offset,
│ │ │ │ │ - this.calculateOffset);
│ │ │ │ │ + getGeodesicLength: function(projection) {
│ │ │ │ │ + var length = 0.0;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + length += this.components[i].getGeodesicLength(projection);
│ │ │ │ │ + }
│ │ │ │ │ + return length;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: setSize
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: move
│ │ │ │ │ + * Moves a geometry by the given displacement along positive x and y axes.
│ │ │ │ │ + * This modifies the position of the geometry and clears the cached
│ │ │ │ │ + * bounds.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * size - {|Object} An OpenLayers.Size or
│ │ │ │ │ - * an object with a 'w' and 'h' properties.
│ │ │ │ │ + * x - {Float} Distance to move geometry in positive x direction.
│ │ │ │ │ + * y - {Float} Distance to move geometry in positive y direction.
│ │ │ │ │ */
│ │ │ │ │ - setSize: function(size) {
│ │ │ │ │ - if (size != null) {
│ │ │ │ │ - this.size = size;
│ │ │ │ │ + move: function(x, y) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + this.components[i].move(x, y);
│ │ │ │ │ }
│ │ │ │ │ - this.draw();
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: setUrl
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: rotate
│ │ │ │ │ + * Rotate a geometry around some origin
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * url - {String}
│ │ │ │ │ + * angle - {Float} Rotation angle in degrees (measured counterclockwise
│ │ │ │ │ + * from the positive x-axis)
│ │ │ │ │ + * origin - {} Center point for the rotation
│ │ │ │ │ */
│ │ │ │ │ - setUrl: function(url) {
│ │ │ │ │ - if (url != null) {
│ │ │ │ │ - this.url = url;
│ │ │ │ │ + rotate: function(angle, origin) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + this.components[i].rotate(angle, origin);
│ │ │ │ │ }
│ │ │ │ │ - this.draw();
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: draw
│ │ │ │ │ - * Move the div to the given pixel.
│ │ │ │ │ - *
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: resize
│ │ │ │ │ + * Resize a geometry relative to some origin. Use this method to apply
│ │ │ │ │ + * a uniform scaling to a geometry.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * px - {|Object} An OpenLayers.Pixel or an
│ │ │ │ │ - * object with a 'x' and 'y' properties.
│ │ │ │ │ + * scale - {Float} Factor by which to scale the geometry. A scale of 2
│ │ │ │ │ + * doubles the size of the geometry in each dimension
│ │ │ │ │ + * (lines, for example, will be twice as long, and polygons
│ │ │ │ │ + * will have four times the area).
│ │ │ │ │ + * origin - {} Point of origin for resizing
│ │ │ │ │ + * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {DOMElement} A new DOM Image of this icon set at the location passed-in
│ │ │ │ │ + * {} - The current geometry.
│ │ │ │ │ */
│ │ │ │ │ - draw: function(px) {
│ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,
│ │ │ │ │ - null,
│ │ │ │ │ - null,
│ │ │ │ │ - this.size,
│ │ │ │ │ - this.url,
│ │ │ │ │ - "absolute");
│ │ │ │ │ - this.moveTo(px);
│ │ │ │ │ - return this.imageDiv;
│ │ │ │ │ + resize: function(scale, origin, ratio) {
│ │ │ │ │ + for (var i = 0; i < this.components.length; ++i) {
│ │ │ │ │ + this.components[i].resize(scale, origin, ratio);
│ │ │ │ │ + }
│ │ │ │ │ + return this;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: erase
│ │ │ │ │ - * Erase the underlying image element.
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: distanceTo
│ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane).
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Optional properties for configuring the distance
│ │ │ │ │ + * calculation.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * details - {Boolean} Return details from the distance calculation.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the
│ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true,
│ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within
│ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever
│ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false,
│ │ │ │ │ + * details cannot be returned.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Number | Object} The distance between this geometry and the target.
│ │ │ │ │ + * If details is true, the return will be an object with distance,
│ │ │ │ │ + * x0, y0, x1, and y1 properties. The x0 and y0 properties represent
│ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1
│ │ │ │ │ + * properties represent the coordinates of the closest point on the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ */
│ │ │ │ │ - erase: function() {
│ │ │ │ │ - if (this.imageDiv != null && this.imageDiv.parentNode != null) {
│ │ │ │ │ - OpenLayers.Element.remove(this.imageDiv);
│ │ │ │ │ + distanceTo: function(geometry, options) {
│ │ │ │ │ + var edge = !(options && options.edge === false);
│ │ │ │ │ + var details = edge && options && options.details;
│ │ │ │ │ + var result, best, distance;
│ │ │ │ │ + var min = Number.POSITIVE_INFINITY;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + result = this.components[i].distanceTo(geometry, options);
│ │ │ │ │ + distance = details ? result.distance : result;
│ │ │ │ │ + if (distance < min) {
│ │ │ │ │ + min = distance;
│ │ │ │ │ + best = result;
│ │ │ │ │ + if (min == 0) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ + return best;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: setOpacity
│ │ │ │ │ - * Change the icon's opacity
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: equals
│ │ │ │ │ + * Determine whether another geometry is equivalent to this one. Geometries
│ │ │ │ │ + * are considered equivalent if all components have the same coordinates.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * opacity - {float}
│ │ │ │ │ + * geometry - {} The geometry to test.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The supplied geometry is equivalent to this geometry.
│ │ │ │ │ */
│ │ │ │ │ - setOpacity: function(opacity) {
│ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,
│ │ │ │ │ - null, null, null, null, opacity);
│ │ │ │ │ -
│ │ │ │ │ + equals: function(geometry) {
│ │ │ │ │ + var equivalent = true;
│ │ │ │ │ + if (!geometry || !geometry.CLASS_NAME ||
│ │ │ │ │ + (this.CLASS_NAME != geometry.CLASS_NAME)) {
│ │ │ │ │ + equivalent = false;
│ │ │ │ │ + } else if (!(OpenLayers.Util.isArray(geometry.components)) ||
│ │ │ │ │ + (geometry.components.length != this.components.length)) {
│ │ │ │ │ + equivalent = false;
│ │ │ │ │ + } else {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + if (!this.components[i].equals(geometry.components[i])) {
│ │ │ │ │ + equivalent = false;
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return equivalent;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: moveTo
│ │ │ │ │ - * move icon to passed in px.
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: transform
│ │ │ │ │ + * Reproject the components geometry from source to dest.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * px - {|Object} the pixel position to move to.
│ │ │ │ │ - * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
│ │ │ │ │ + * source - {}
│ │ │ │ │ + * dest - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - moveTo: function(px) {
│ │ │ │ │ - //if no px passed in, use stored location
│ │ │ │ │ - if (px != null) {
│ │ │ │ │ - this.px = px;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (this.imageDiv != null) {
│ │ │ │ │ - if (this.px == null) {
│ │ │ │ │ - this.display(false);
│ │ │ │ │ - } else {
│ │ │ │ │ - if (this.calculateOffset) {
│ │ │ │ │ - this.offset = this.calculateOffset(this.size);
│ │ │ │ │ - }
│ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
│ │ │ │ │ - x: this.px.x + this.offset.x,
│ │ │ │ │ - y: this.px.y + this.offset.y
│ │ │ │ │ - });
│ │ │ │ │ + transform: function(source, dest) {
│ │ │ │ │ + if (source && dest) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) {
│ │ │ │ │ + var component = this.components[i];
│ │ │ │ │ + component.transform(source, dest);
│ │ │ │ │ }
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ }
│ │ │ │ │ + return this;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: display
│ │ │ │ │ - * Hide or show the icon
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: intersects
│ │ │ │ │ + * Determine if the input geometry intersects this one.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * display - {Boolean}
│ │ │ │ │ + * geometry - {} Any type of geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The input geometry intersects this one.
│ │ │ │ │ */
│ │ │ │ │ - display: function(display) {
│ │ │ │ │ - this.imageDiv.style.display = (display) ? "" : "none";
│ │ │ │ │ + intersects: function(geometry) {
│ │ │ │ │ + var intersect = false;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = geometry.intersects(this.components[i]);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return intersect;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ -
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: isDrawn
│ │ │ │ │ - *
│ │ │ │ │ + * APIMethod: getVertices
│ │ │ │ │ + * Return a list of all points in this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are
│ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not
│ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will
│ │ │ │ │ + * be returned.
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {Boolean} Whether or not the icon is drawn.
│ │ │ │ │ + * {Array} A list of all vertices in the geometry.
│ │ │ │ │ */
│ │ │ │ │ - isDrawn: function() {
│ │ │ │ │ - // nodeType 11 for ie, whose nodes *always* have a parentNode
│ │ │ │ │ - // (of type document fragment)
│ │ │ │ │ - var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&
│ │ │ │ │ - (this.imageDiv.parentNode.nodeType != 11));
│ │ │ │ │ -
│ │ │ │ │ - return isDrawn;
│ │ │ │ │ + getVertices: function(nodes) {
│ │ │ │ │ + var vertices = [];
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + Array.prototype.push.apply(
│ │ │ │ │ + vertices, this.components[i].getVertices(nodes)
│ │ │ │ │ + );
│ │ │ │ │ + }
│ │ │ │ │ + return vertices;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Icon"
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Collection"
│ │ │ │ │ });
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Marker.js
│ │ │ │ │ + OpenLayers/Geometry/MultiPoint.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ -
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Events.js
│ │ │ │ │ - * @requires OpenLayers/Icon.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Collection.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Point.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.Marker
│ │ │ │ │ - * Instances of OpenLayers.Marker are a combination of a
│ │ │ │ │ - * and an .
│ │ │ │ │ - *
│ │ │ │ │ - * Markers are generally added to a special layer called
│ │ │ │ │ - * .
│ │ │ │ │ - *
│ │ │ │ │ - * Example:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * var markers = new OpenLayers.Layer.Markers( "Markers" );
│ │ │ │ │ - * map.addLayer(markers);
│ │ │ │ │ - *
│ │ │ │ │ - * var size = new OpenLayers.Size(21,25);
│ │ │ │ │ - * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
│ │ │ │ │ - * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
│ │ │ │ │ - * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
│ │ │ │ │ - * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
│ │ │ │ │ - *
│ │ │ │ │ - * (end)
│ │ │ │ │ + * Class: OpenLayers.Geometry.MultiPoint
│ │ │ │ │ + * MultiPoint is a collection of Points. Create a new instance with the
│ │ │ │ │ + * constructor.
│ │ │ │ │ *
│ │ │ │ │ - * Note that if you pass an icon into the Marker constructor, it will take
│ │ │ │ │ - * that icon and use it. This means that you should not share icons between
│ │ │ │ │ - * markers -- you use them once, but you should clone() for any additional
│ │ │ │ │ - * markers using that same icon.
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Marker = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: icon
│ │ │ │ │ - * {} The icon used by this marker.
│ │ │ │ │ - */
│ │ │ │ │ - icon: null,
│ │ │ │ │ +OpenLayers.Geometry.MultiPoint = OpenLayers.Class(
│ │ │ │ │ + OpenLayers.Geometry.Collection, {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: lonlat
│ │ │ │ │ - * {} location of object
│ │ │ │ │ - */
│ │ │ │ │ - lonlat: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null value means the
│ │ │ │ │ + * component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Point"],
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: events
│ │ │ │ │ - * {} the event handler.
│ │ │ │ │ - */
│ │ │ │ │ - events: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.MultiPoint
│ │ │ │ │ + * Create a new MultiPoint Geometry
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: map
│ │ │ │ │ - * {} the map this marker is attached to
│ │ │ │ │ - */
│ │ │ │ │ - map: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: addPoint
│ │ │ │ │ + * Wrapper for
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {} Point to be added
│ │ │ │ │ + * index - {Integer} Optional index
│ │ │ │ │ + */
│ │ │ │ │ + addPoint: function(point, index) {
│ │ │ │ │ + this.addComponent(point, index);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Marker
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * lonlat - {} the position of this marker
│ │ │ │ │ - * icon - {} the icon for this marker
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(lonlat, icon) {
│ │ │ │ │ - this.lonlat = lonlat;
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: removePoint
│ │ │ │ │ + * Wrapper for
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {} Point to be removed
│ │ │ │ │ + */
│ │ │ │ │ + removePoint: function(point) {
│ │ │ │ │ + this.removeComponent(point);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
│ │ │ │ │ - if (this.icon == null) {
│ │ │ │ │ - this.icon = newIcon;
│ │ │ │ │ - } else {
│ │ │ │ │ - this.icon.url = newIcon.url;
│ │ │ │ │ - this.icon.size = newIcon.size;
│ │ │ │ │ - this.icon.offset = newIcon.offset;
│ │ │ │ │ - this.icon.calculateOffset = newIcon.calculateOffset;
│ │ │ │ │ - }
│ │ │ │ │ - this.events = new OpenLayers.Events(this, this.icon.imageDiv);
│ │ │ │ │ - },
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.MultiPoint"
│ │ │ │ │ + });
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Geometry/Curve.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - * Destroy the marker. You must first remove the marker from any
│ │ │ │ │ - * layer which it has been added to, or you will get buggy behavior.
│ │ │ │ │ - * (This can not be done within the marker since the marker does not
│ │ │ │ │ - * know which layer it is attached to.)
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - // erase any drawn features
│ │ │ │ │ - this.erase();
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │
│ │ │ │ │ - this.map = null;
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/Geometry/MultiPoint.js
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - this.events.destroy();
│ │ │ │ │ - this.events = null;
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Geometry.Curve
│ │ │ │ │ + * A Curve is a MultiPoint, whose points are assumed to be connected. To
│ │ │ │ │ + * this end, we provide a "getLength()" function, which iterates through
│ │ │ │ │ + * the points, summing the distances between them.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits:
│ │ │ │ │ + * -
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, {
│ │ │ │ │
│ │ │ │ │ - if (this.icon != null) {
│ │ │ │ │ - this.icon.destroy();
│ │ │ │ │ - this.icon = null;
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null
│ │ │ │ │ + * value means the component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Point"],
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: draw
│ │ │ │ │ - * Calls draw on the icon, and returns that output.
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.Curve
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * px - {}
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {DOMElement} A new DOM Image with this marker's icon set at the
│ │ │ │ │ - * location passed-in
│ │ │ │ │ + * point - {Array()}
│ │ │ │ │ */
│ │ │ │ │ - draw: function(px) {
│ │ │ │ │ - return this.icon.draw(px);
│ │ │ │ │ - },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: erase
│ │ │ │ │ - * Erases any drawn elements for this marker.
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getLength
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The length of the curve
│ │ │ │ │ */
│ │ │ │ │ - erase: function() {
│ │ │ │ │ - if (this.icon != null) {
│ │ │ │ │ - this.icon.erase();
│ │ │ │ │ + getLength: function() {
│ │ │ │ │ + var length = 0.0;
│ │ │ │ │ + if (this.components && (this.components.length > 1)) {
│ │ │ │ │ + for (var i = 1, len = this.components.length; i < len; i++) {
│ │ │ │ │ + length += this.components[i - 1].distanceTo(this.components[i]);
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ + return length;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: moveTo
│ │ │ │ │ - * Move the marker to the new location.
│ │ │ │ │ + * APIMethod: getGeodesicLength
│ │ │ │ │ + * Calculate the approximate length of the geometry were it projected onto
│ │ │ │ │ + * the earth.
│ │ │ │ │ *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * px - {|Object} the pixel position to move to.
│ │ │ │ │ - * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
│ │ │ │ │ + * projection - {} The spatial reference system
│ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is
│ │ │ │ │ + * assumed.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The appoximate geodesic length of the geometry in meters.
│ │ │ │ │ */
│ │ │ │ │ - moveTo: function(px) {
│ │ │ │ │ - if ((px != null) && (this.icon != null)) {
│ │ │ │ │ - this.icon.moveTo(px);
│ │ │ │ │ + getGeodesicLength: function(projection) {
│ │ │ │ │ + var geom = this; // so we can work with a clone if needed
│ │ │ │ │ + if (projection) {
│ │ │ │ │ + var gg = new OpenLayers.Projection("EPSG:4326");
│ │ │ │ │ + if (!gg.equals(projection)) {
│ │ │ │ │ + geom = this.clone().transform(projection, gg);
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ - this.lonlat = this.map.getLonLatFromLayerPx(px);
│ │ │ │ │ + var length = 0.0;
│ │ │ │ │ + if (geom.components && (geom.components.length > 1)) {
│ │ │ │ │ + var p1, p2;
│ │ │ │ │ + for (var i = 1, len = geom.components.length; i < len; i++) {
│ │ │ │ │ + p1 = geom.components[i - 1];
│ │ │ │ │ + p2 = geom.components[i];
│ │ │ │ │ + // this returns km and requires lon/lat properties
│ │ │ │ │ + length += OpenLayers.Util.distVincenty({
│ │ │ │ │ + lon: p1.x,
│ │ │ │ │ + lat: p1.y
│ │ │ │ │ + }, {
│ │ │ │ │ + lon: p2.x,
│ │ │ │ │ + lat: p2.y
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + // convert to m
│ │ │ │ │ + return length * 1000;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Curve"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Geometry/LineString.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/Geometry/Curve.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Geometry.LineString
│ │ │ │ │ + * A LineString is a Curve which, once two points have been added to it, can
│ │ │ │ │ + * never be less than two points long.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
│ │ │ │ │ +
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: isDrawn
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} Whether or not the marker is drawn.
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.LineString
│ │ │ │ │ + * Create a new LineString geometry
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * points - {Array()} An array of points used to
│ │ │ │ │ + * generate the linestring
│ │ │ │ │ + *
│ │ │ │ │ */
│ │ │ │ │ - isDrawn: function() {
│ │ │ │ │ - var isDrawn = (this.icon && this.icon.isDrawn());
│ │ │ │ │ - return isDrawn;
│ │ │ │ │ - },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: onScreen
│ │ │ │ │ + * APIMethod: removeComponent
│ │ │ │ │ + * Only allows removal of a point if there are three or more points in
│ │ │ │ │ + * the linestring. (otherwise the result would be just a single point)
│ │ │ │ │ *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} Whether or not the marker is currently visible on screen.
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {} The point to be removed
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The component was removed.
│ │ │ │ │ */
│ │ │ │ │ - onScreen: function() {
│ │ │ │ │ -
│ │ │ │ │ - var onScreen = false;
│ │ │ │ │ - if (this.map) {
│ │ │ │ │ - var screenBounds = this.map.getExtent();
│ │ │ │ │ - onScreen = screenBounds.containsLonLat(this.lonlat);
│ │ │ │ │ + removeComponent: function(point) {
│ │ │ │ │ + var removed = this.components && (this.components.length > 2);
│ │ │ │ │ + if (removed) {
│ │ │ │ │ + OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,
│ │ │ │ │ + arguments);
│ │ │ │ │ }
│ │ │ │ │ - return onScreen;
│ │ │ │ │ + return removed;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: inflate
│ │ │ │ │ - * Englarges the markers icon by the specified ratio.
│ │ │ │ │ + * APIMethod: intersects
│ │ │ │ │ + * Test for instersection between two geometries. This is a cheapo
│ │ │ │ │ + * implementation of the Bently-Ottmann algorigithm. It doesn't
│ │ │ │ │ + * really keep track of a sweep line data structure. It is closer
│ │ │ │ │ + * to the brute force method, except that segments are sorted and
│ │ │ │ │ + * potential intersections are only calculated when bounding boxes
│ │ │ │ │ + * intersect.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * inflate - {float} the ratio to enlarge the marker by (passing 2
│ │ │ │ │ - * will double the size).
│ │ │ │ │ - */
│ │ │ │ │ - inflate: function(inflate) {
│ │ │ │ │ - if (this.icon) {
│ │ │ │ │ - this.icon.setSize({
│ │ │ │ │ - w: this.icon.size.w * inflate,
│ │ │ │ │ - h: this.icon.size.h * inflate
│ │ │ │ │ - });
│ │ │ │ │ - }
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: setOpacity
│ │ │ │ │ - * Change the opacity of the marker by changin the opacity of
│ │ │ │ │ - * its icon
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * opacity - {float} Specified as fraction (0.4, etc)
│ │ │ │ │ - */
│ │ │ │ │ - setOpacity: function(opacity) {
│ │ │ │ │ - this.icon.setOpacity(opacity);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: setUrl
│ │ │ │ │ - * Change URL of the Icon Image.
│ │ │ │ │ - *
│ │ │ │ │ - * url - {String}
│ │ │ │ │ - */
│ │ │ │ │ - setUrl: function(url) {
│ │ │ │ │ - this.icon.setUrl(url);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: display
│ │ │ │ │ - * Hide or show the icon
│ │ │ │ │ - *
│ │ │ │ │ - * display - {Boolean}
│ │ │ │ │ + * geometry - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The input geometry intersects this geometry.
│ │ │ │ │ */
│ │ │ │ │ - display: function(display) {
│ │ │ │ │ - this.icon.display(display);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Marker"
│ │ │ │ │ -});
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Function: defaultIcon
│ │ │ │ │ - * Creates a default .
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {} A default OpenLayers.Icon to use for a marker
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Marker.defaultIcon = function() {
│ │ │ │ │ - return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"), {
│ │ │ │ │ - w: 21,
│ │ │ │ │ - h: 25
│ │ │ │ │ - }, {
│ │ │ │ │ - x: -10.5,
│ │ │ │ │ - y: -25
│ │ │ │ │ - });
│ │ │ │ │ -};
│ │ │ │ │ -
│ │ │ │ │ -
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ - OpenLayers/Request/XMLHttpRequest.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)
│ │ │ │ │ -//
│ │ │ │ │ -// Licensed under the Apache License, Version 2.0 (the "License");
│ │ │ │ │ -// you may not use this file except in compliance with the License.
│ │ │ │ │ -// You may obtain a copy of the License at
│ │ │ │ │ -//
│ │ │ │ │ -// http://www.apache.org/licenses/LICENSE-2.0
│ │ │ │ │ -//
│ │ │ │ │ -// Unless required by applicable law or agreed to in writing, software
│ │ │ │ │ -// distributed under the License is distributed on an "AS IS" BASIS,
│ │ │ │ │ -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
│ │ │ │ │ -// See the License for the specific language governing permissions and
│ │ │ │ │ -// limitations under the License.
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/Request.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -(function() {
│ │ │ │ │ -
│ │ │ │ │ - // Save reference to earlier defined object implementation (if any)
│ │ │ │ │ - var oXMLHttpRequest = window.XMLHttpRequest;
│ │ │ │ │ -
│ │ │ │ │ - // Define on browser type
│ │ │ │ │ - var bGecko = !!window.controllers,
│ │ │ │ │ - bIE = window.document.all && !window.opera,
│ │ │ │ │ - bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
│ │ │ │ │ -
│ │ │ │ │ - // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()"
│ │ │ │ │ - function fXMLHttpRequest() {
│ │ │ │ │ - this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
│ │ │ │ │ - this._listeners = [];
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // Constructor
│ │ │ │ │ - function cXMLHttpRequest() {
│ │ │ │ │ - return new fXMLHttpRequest;
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Firefox with Firebug installed would break pages if not executed
│ │ │ │ │ - if (bGecko && oXMLHttpRequest.wrapped)
│ │ │ │ │ - cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
│ │ │ │ │ -
│ │ │ │ │ - // Constants
│ │ │ │ │ - cXMLHttpRequest.UNSENT = 0;
│ │ │ │ │ - cXMLHttpRequest.OPENED = 1;
│ │ │ │ │ - cXMLHttpRequest.HEADERS_RECEIVED = 2;
│ │ │ │ │ - cXMLHttpRequest.LOADING = 3;
│ │ │ │ │ - cXMLHttpRequest.DONE = 4;
│ │ │ │ │ -
│ │ │ │ │ - // Public Properties
│ │ │ │ │ - cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ - cXMLHttpRequest.prototype.responseText = '';
│ │ │ │ │ - cXMLHttpRequest.prototype.responseXML = null;
│ │ │ │ │ - cXMLHttpRequest.prototype.status = 0;
│ │ │ │ │ - cXMLHttpRequest.prototype.statusText = '';
│ │ │ │ │ -
│ │ │ │ │ - // Priority proposal
│ │ │ │ │ - cXMLHttpRequest.prototype.priority = "NORMAL";
│ │ │ │ │ -
│ │ │ │ │ - // Instance-level Events Handlers
│ │ │ │ │ - cXMLHttpRequest.prototype.onreadystatechange = null;
│ │ │ │ │ -
│ │ │ │ │ - // Class-level Events Handlers
│ │ │ │ │ - cXMLHttpRequest.onreadystatechange = null;
│ │ │ │ │ - cXMLHttpRequest.onopen = null;
│ │ │ │ │ - cXMLHttpRequest.onsend = null;
│ │ │ │ │ - cXMLHttpRequest.onabort = null;
│ │ │ │ │ -
│ │ │ │ │ - // Public Methods
│ │ │ │ │ - cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {
│ │ │ │ │ - // Delete headers, required when object is reused
│ │ │ │ │ - delete this._headers;
│ │ │ │ │ -
│ │ │ │ │ - // When bAsync parameter value is omitted, use true as default
│ │ │ │ │ - if (arguments.length < 3)
│ │ │ │ │ - bAsync = true;
│ │ │ │ │ -
│ │ │ │ │ - // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
│ │ │ │ │ - this._async = bAsync;
│ │ │ │ │ -
│ │ │ │ │ - // Set the onreadystatechange handler
│ │ │ │ │ - var oRequest = this,
│ │ │ │ │ - nState = this.readyState,
│ │ │ │ │ - fOnUnload;
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: IE - memory leak on page unload (inter-page leak)
│ │ │ │ │ - if (bIE && bAsync) {
│ │ │ │ │ - fOnUnload = function() {
│ │ │ │ │ - if (nState != cXMLHttpRequest.DONE) {
│ │ │ │ │ - fCleanTransport(oRequest);
│ │ │ │ │ - // Safe to abort here since onreadystatechange handler removed
│ │ │ │ │ - oRequest.abort();
│ │ │ │ │ - }
│ │ │ │ │ - };
│ │ │ │ │ - window.attachEvent("onunload", fOnUnload);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // Add method sniffer
│ │ │ │ │ - if (cXMLHttpRequest.onopen)
│ │ │ │ │ - cXMLHttpRequest.onopen.apply(this, arguments);
│ │ │ │ │ -
│ │ │ │ │ - if (arguments.length > 4)
│ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
│ │ │ │ │ - else
│ │ │ │ │ - if (arguments.length > 3)
│ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync, sUser);
│ │ │ │ │ - else
│ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync);
│ │ │ │ │ -
│ │ │ │ │ - this.readyState = cXMLHttpRequest.OPENED;
│ │ │ │ │ - fReadyStateChange(this);
│ │ │ │ │ -
│ │ │ │ │ - this._object.onreadystatechange = function() {
│ │ │ │ │ - if (bGecko && !bAsync)
│ │ │ │ │ - return;
│ │ │ │ │ -
│ │ │ │ │ - // Synchronize state
│ │ │ │ │ - oRequest.readyState = oRequest._object.readyState;
│ │ │ │ │ -
│ │ │ │ │ - //
│ │ │ │ │ - fSynchronizeValues(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Firefox fires unnecessary DONE when aborting
│ │ │ │ │ - if (oRequest._aborted) {
│ │ │ │ │ - // Reset readyState to UNSENT
│ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ -
│ │ │ │ │ - // Return now
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (oRequest.readyState == cXMLHttpRequest.DONE) {
│ │ │ │ │ - // Free up queue
│ │ │ │ │ - delete oRequest._data;
│ │ │ │ │ - /* if (bAsync)
│ │ │ │ │ - fQueue_remove(oRequest);*/
│ │ │ │ │ - //
│ │ │ │ │ - fCleanTransport(oRequest);
│ │ │ │ │ - // Uncomment this block if you need a fix for IE cache
│ │ │ │ │ - /*
│ │ │ │ │ - // BUGFIX: IE - cache issue
│ │ │ │ │ - if (!oRequest._object.getResponseHeader("Date")) {
│ │ │ │ │ - // Save object to cache
│ │ │ │ │ - oRequest._cached = oRequest._object;
│ │ │ │ │ -
│ │ │ │ │ - // Instantiate a new transport object
│ │ │ │ │ - cXMLHttpRequest.call(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // Re-send request
│ │ │ │ │ - if (sUser) {
│ │ │ │ │ - if (sPassword)
│ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
│ │ │ │ │ - else
│ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync, sUser);
│ │ │ │ │ - }
│ │ │ │ │ - else
│ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync);
│ │ │ │ │ - oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
│ │ │ │ │ - // Copy headers set
│ │ │ │ │ - if (oRequest._headers)
│ │ │ │ │ - for (var sHeader in oRequest._headers)
│ │ │ │ │ - if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions
│ │ │ │ │ - oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
│ │ │ │ │ -
│ │ │ │ │ - oRequest._object.onreadystatechange = function() {
│ │ │ │ │ - // Synchronize state
│ │ │ │ │ - oRequest.readyState = oRequest._object.readyState;
│ │ │ │ │ -
│ │ │ │ │ - if (oRequest._aborted) {
│ │ │ │ │ - //
│ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ -
│ │ │ │ │ - // Return
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - if (oRequest.readyState == cXMLHttpRequest.DONE) {
│ │ │ │ │ - // Clean Object
│ │ │ │ │ - fCleanTransport(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // get cached request
│ │ │ │ │ - if (oRequest.status == 304)
│ │ │ │ │ - oRequest._object = oRequest._cached;
│ │ │ │ │ -
│ │ │ │ │ - //
│ │ │ │ │ - delete oRequest._cached;
│ │ │ │ │ -
│ │ │ │ │ - //
│ │ │ │ │ - fSynchronizeValues(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - //
│ │ │ │ │ - fReadyStateChange(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: IE - memory leak in interrupted
│ │ │ │ │ - if (bIE && bAsync)
│ │ │ │ │ - window.detachEvent("onunload", fOnUnload);
│ │ │ │ │ - }
│ │ │ │ │ - };
│ │ │ │ │ - oRequest._object.send(null);
│ │ │ │ │ -
│ │ │ │ │ - // Return now - wait until re-sent request is finished
│ │ │ │ │ - return;
│ │ │ │ │ - };
│ │ │ │ │ - */
│ │ │ │ │ - // BUGFIX: IE - memory leak in interrupted
│ │ │ │ │ - if (bIE && bAsync)
│ │ │ │ │ - window.detachEvent("onunload", fOnUnload);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
│ │ │ │ │ - if (nState != oRequest.readyState)
│ │ │ │ │ - fReadyStateChange(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - nState = oRequest.readyState;
│ │ │ │ │ - }
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fXMLHttpRequest_send(oRequest) {
│ │ │ │ │ - oRequest._object.send(oRequest._data);
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
│ │ │ │ │ - if (bGecko && !oRequest._async) {
│ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.OPENED;
│ │ │ │ │ -
│ │ │ │ │ - // Synchronize state
│ │ │ │ │ - fSynchronizeValues(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // Simulate missing states
│ │ │ │ │ - while (oRequest.readyState < cXMLHttpRequest.DONE) {
│ │ │ │ │ - oRequest.readyState++;
│ │ │ │ │ - fReadyStateChange(oRequest);
│ │ │ │ │ - // Check if we are aborted
│ │ │ │ │ - if (oRequest._aborted)
│ │ │ │ │ - return;
│ │ │ │ │ + intersects: function(geometry) {
│ │ │ │ │ + var intersect = false;
│ │ │ │ │ + var type = geometry.CLASS_NAME;
│ │ │ │ │ + if (type == "OpenLayers.Geometry.LineString" ||
│ │ │ │ │ + type == "OpenLayers.Geometry.LinearRing" ||
│ │ │ │ │ + type == "OpenLayers.Geometry.Point") {
│ │ │ │ │ + var segs1 = this.getSortedSegments();
│ │ │ │ │ + var segs2;
│ │ │ │ │ + if (type == "OpenLayers.Geometry.Point") {
│ │ │ │ │ + segs2 = [{
│ │ │ │ │ + x1: geometry.x,
│ │ │ │ │ + y1: geometry.y,
│ │ │ │ │ + x2: geometry.x,
│ │ │ │ │ + y2: geometry.y
│ │ │ │ │ + }];
│ │ │ │ │ + } else {
│ │ │ │ │ + segs2 = geometry.getSortedSegments();
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype.send = function(vData) {
│ │ │ │ │ - // Add method sniffer
│ │ │ │ │ - if (cXMLHttpRequest.onsend)
│ │ │ │ │ - cXMLHttpRequest.onsend.apply(this, arguments);
│ │ │ │ │ -
│ │ │ │ │ - if (!arguments.length)
│ │ │ │ │ - vData = null;
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
│ │ │ │ │ - // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
│ │ │ │ │ - // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
│ │ │ │ │ - if (vData && vData.nodeType) {
│ │ │ │ │ - vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
│ │ │ │ │ - if (!this._headers["Content-Type"])
│ │ │ │ │ - this._object.setRequestHeader("Content-Type", "application/xml");
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - this._data = vData;
│ │ │ │ │ - /*
│ │ │ │ │ - // Add to queue
│ │ │ │ │ - if (this._async)
│ │ │ │ │ - fQueue_add(this);
│ │ │ │ │ - else*/
│ │ │ │ │ - fXMLHttpRequest_send(this);
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype.abort = function() {
│ │ │ │ │ - // Add method sniffer
│ │ │ │ │ - if (cXMLHttpRequest.onabort)
│ │ │ │ │ - cXMLHttpRequest.onabort.apply(this, arguments);
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: Gecko - unnecessary DONE when aborting
│ │ │ │ │ - if (this.readyState > cXMLHttpRequest.UNSENT)
│ │ │ │ │ - this._aborted = true;
│ │ │ │ │ -
│ │ │ │ │ - this._object.abort();
│ │ │ │ │ -
│ │ │ │ │ - // BUGFIX: IE - memory leak
│ │ │ │ │ - fCleanTransport(this);
│ │ │ │ │ -
│ │ │ │ │ - this.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ -
│ │ │ │ │ - delete this._data;
│ │ │ │ │ - /* if (this._async)
│ │ │ │ │ - fQueue_remove(this);*/
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
│ │ │ │ │ - return this._object.getAllResponseHeaders();
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
│ │ │ │ │ - return this._object.getResponseHeader(sName);
│ │ │ │ │ - };
│ │ │ │ │ - cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
│ │ │ │ │ - // BUGFIX: IE - cache issue
│ │ │ │ │ - if (!this._headers)
│ │ │ │ │ - this._headers = {};
│ │ │ │ │ - this._headers[sName] = sValue;
│ │ │ │ │ -
│ │ │ │ │ - return this._object.setRequestHeader(sName, sValue);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // EventTarget interface implementation
│ │ │ │ │ - cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {
│ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ - if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
│ │ │ │ │ - return;
│ │ │ │ │ - // Add listener
│ │ │ │ │ - this._listeners.push([sName, fHandler, bUseCapture]);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
│ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ - if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
│ │ │ │ │ - break;
│ │ │ │ │ - // Remove listener
│ │ │ │ │ - if (oListener)
│ │ │ │ │ - this._listeners.splice(nIndex, 1);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
│ │ │ │ │ - var oEventPseudo = {
│ │ │ │ │ - 'type': oEvent.type,
│ │ │ │ │ - 'target': this,
│ │ │ │ │ - 'currentTarget': this,
│ │ │ │ │ - 'eventPhase': 2,
│ │ │ │ │ - 'bubbles': oEvent.bubbles,
│ │ │ │ │ - 'cancelable': oEvent.cancelable,
│ │ │ │ │ - 'timeStamp': oEvent.timeStamp,
│ │ │ │ │ - 'stopPropagation': function() {}, // There is no flow
│ │ │ │ │ - 'preventDefault': function() {}, // There is no default action
│ │ │ │ │ - 'initEvent': function() {} // Original event object should be initialized
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // Execute onreadystatechange
│ │ │ │ │ - if (oEventPseudo.type == "readystatechange" && this.onreadystatechange)
│ │ │ │ │ - (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
│ │ │ │ │ -
│ │ │ │ │ - // Execute listeners
│ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ - if (oListener[0] == oEventPseudo.type && !oListener[2])
│ │ │ │ │ - (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - //
│ │ │ │ │ - cXMLHttpRequest.prototype.toString = function() {
│ │ │ │ │ - return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - cXMLHttpRequest.toString = function() {
│ │ │ │ │ - return '[' + "XMLHttpRequest" + ']';
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // Helper function
│ │ │ │ │ - function fReadyStateChange(oRequest) {
│ │ │ │ │ - // Sniffing code
│ │ │ │ │ - if (cXMLHttpRequest.onreadystatechange)
│ │ │ │ │ - cXMLHttpRequest.onreadystatechange.apply(oRequest);
│ │ │ │ │ -
│ │ │ │ │ - // Fake event
│ │ │ │ │ - oRequest.dispatchEvent({
│ │ │ │ │ - 'type': "readystatechange",
│ │ │ │ │ - 'bubbles': false,
│ │ │ │ │ - 'cancelable': false,
│ │ │ │ │ - 'timeStamp': new Date + 0
│ │ │ │ │ - });
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fGetDocument(oRequest) {
│ │ │ │ │ - var oDocument = oRequest.responseXML,
│ │ │ │ │ - sResponse = oRequest.responseText;
│ │ │ │ │ - // Try parsing responseText
│ │ │ │ │ - if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
│ │ │ │ │ - oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
│ │ │ │ │ - oDocument.async = false;
│ │ │ │ │ - oDocument.validateOnParse = false;
│ │ │ │ │ - oDocument.loadXML(sResponse);
│ │ │ │ │ - }
│ │ │ │ │ - // Check if there is no error in document
│ │ │ │ │ - if (oDocument)
│ │ │ │ │ - if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
│ │ │ │ │ - return null;
│ │ │ │ │ - return oDocument;
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fSynchronizeValues(oRequest) {
│ │ │ │ │ - try {
│ │ │ │ │ - oRequest.responseText = oRequest._object.responseText;
│ │ │ │ │ - } catch (e) {}
│ │ │ │ │ - try {
│ │ │ │ │ - oRequest.responseXML = fGetDocument(oRequest._object);
│ │ │ │ │ - } catch (e) {}
│ │ │ │ │ - try {
│ │ │ │ │ - oRequest.status = oRequest._object.status;
│ │ │ │ │ - } catch (e) {}
│ │ │ │ │ - try {
│ │ │ │ │ - oRequest.statusText = oRequest._object.statusText;
│ │ │ │ │ - } catch (e) {}
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fCleanTransport(oRequest) {
│ │ │ │ │ - // BUGFIX: IE - memory leak (on-page leak)
│ │ │ │ │ - oRequest._object.onreadystatechange = new window.Function;
│ │ │ │ │ - };
│ │ │ │ │ - /*
│ │ │ │ │ - // Queue manager
│ │ │ │ │ - var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
│ │ │ │ │ - aQueueRunning = [];
│ │ │ │ │ - function fQueue_add(oRequest) {
│ │ │ │ │ - oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
│ │ │ │ │ - //
│ │ │ │ │ - setTimeout(fQueue_process);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fQueue_remove(oRequest) {
│ │ │ │ │ - for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
│ │ │ │ │ - if (bFound)
│ │ │ │ │ - aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
│ │ │ │ │ - else
│ │ │ │ │ - if (aQueueRunning[nIndex] == oRequest)
│ │ │ │ │ - bFound = true;
│ │ │ │ │ - if (bFound)
│ │ │ │ │ - aQueueRunning.length--;
│ │ │ │ │ - //
│ │ │ │ │ - setTimeout(fQueue_process);
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - function fQueue_process() {
│ │ │ │ │ - if (aQueueRunning.length < 6) {
│ │ │ │ │ - for (var sPriority in oQueuePending) {
│ │ │ │ │ - if (oQueuePending[sPriority].length) {
│ │ │ │ │ - var oRequest = oQueuePending[sPriority][0];
│ │ │ │ │ - oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);
│ │ │ │ │ - //
│ │ │ │ │ - aQueueRunning.push(oRequest);
│ │ │ │ │ - // Send request
│ │ │ │ │ - fXMLHttpRequest_send(oRequest);
│ │ │ │ │ + var seg1, seg1x1, seg1x2, seg1y1, seg1y2,
│ │ │ │ │ + seg2, seg2y1, seg2y2;
│ │ │ │ │ + // sweep right
│ │ │ │ │ + outer: for (var i = 0, len = segs1.length; i < len; ++i) {
│ │ │ │ │ + seg1 = segs1[i];
│ │ │ │ │ + seg1x1 = seg1.x1;
│ │ │ │ │ + seg1x2 = seg1.x2;
│ │ │ │ │ + seg1y1 = seg1.y1;
│ │ │ │ │ + seg1y2 = seg1.y2;
│ │ │ │ │ + inner: for (var j = 0, jlen = segs2.length; j < jlen; ++j) {
│ │ │ │ │ + seg2 = segs2[j];
│ │ │ │ │ + if (seg2.x1 > seg1x2) {
│ │ │ │ │ + // seg1 still left of seg2
│ │ │ │ │ break;
│ │ │ │ │ }
│ │ │ │ │ + if (seg2.x2 < seg1x1) {
│ │ │ │ │ + // seg2 still left of seg1
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + seg2y1 = seg2.y1;
│ │ │ │ │ + seg2y2 = seg2.y2;
│ │ │ │ │ + if (Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) {
│ │ │ │ │ + // seg2 above seg1
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + if (Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) {
│ │ │ │ │ + // seg2 below seg1
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + if (OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) {
│ │ │ │ │ + intersect = true;
│ │ │ │ │ + break outer;
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ - };
│ │ │ │ │ - */
│ │ │ │ │ - // Internet Explorer 5.0 (missing apply)
│ │ │ │ │ - if (!window.Function.prototype.apply) {
│ │ │ │ │ - window.Function.prototype.apply = function(oRequest, oArguments) {
│ │ │ │ │ - if (!oArguments)
│ │ │ │ │ - oArguments = [];
│ │ │ │ │ - oRequest.__func = this;
│ │ │ │ │ - oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
│ │ │ │ │ - delete oRequest.__func;
│ │ │ │ │ - };
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // Register new object with window
│ │ │ │ │ - /**
│ │ │ │ │ - * Class: OpenLayers.Request.XMLHttpRequest
│ │ │ │ │ - * Standard-compliant (W3C) cross-browser implementation of the
│ │ │ │ │ - * XMLHttpRequest object. From
│ │ │ │ │ - * http://code.google.com/p/xmlhttprequest/.
│ │ │ │ │ - */
│ │ │ │ │ - if (!OpenLayers.Request) {
│ │ │ │ │ - /**
│ │ │ │ │ - * This allows for OpenLayers/Request.js to be included
│ │ │ │ │ - * before or after this script.
│ │ │ │ │ - */
│ │ │ │ │ - OpenLayers.Request = {};
│ │ │ │ │ - }
│ │ │ │ │ - OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;
│ │ │ │ │ -})();
│ │ │ │ │ -/* ======================================================================
│ │ │ │ │ - OpenLayers/Request.js
│ │ │ │ │ - ====================================================================== */
│ │ │ │ │ -
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * @requires OpenLayers/Events.js
│ │ │ │ │ - * @requires OpenLayers/Request/XMLHttpRequest.js
│ │ │ │ │ - */
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * TODO: deprecate me
│ │ │ │ │ - * Use OpenLayers.Request.proxy instead.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.ProxyHost = "";
│ │ │ │ │ -
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Request
│ │ │ │ │ - * The OpenLayers.Request namespace contains convenience methods for working
│ │ │ │ │ - * with XMLHttpRequests. These methods work with a cross-browser
│ │ │ │ │ - * W3C compliant class.
│ │ │ │ │ - */
│ │ │ │ │ -if (!OpenLayers.Request) {
│ │ │ │ │ - /**
│ │ │ │ │ - * This allows for OpenLayers/Request/XMLHttpRequest.js to be included
│ │ │ │ │ - * before or after this script.
│ │ │ │ │ - */
│ │ │ │ │ - OpenLayers.Request = {};
│ │ │ │ │ -}
│ │ │ │ │ -OpenLayers.Util.extend(OpenLayers.Request, {
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Constant: DEFAULT_CONFIG
│ │ │ │ │ - * {Object} Default configuration for all requests.
│ │ │ │ │ - */
│ │ │ │ │ - DEFAULT_CONFIG: {
│ │ │ │ │ - method: "GET",
│ │ │ │ │ - url: window.location.href,
│ │ │ │ │ - async: true,
│ │ │ │ │ - user: undefined,
│ │ │ │ │ - password: undefined,
│ │ │ │ │ - params: null,
│ │ │ │ │ - proxy: OpenLayers.ProxyHost,
│ │ │ │ │ - headers: {},
│ │ │ │ │ - data: null,
│ │ │ │ │ - callback: function() {},
│ │ │ │ │ - success: null,
│ │ │ │ │ - failure: null,
│ │ │ │ │ - scope: null
│ │ │ │ │ + } else {
│ │ │ │ │ + intersect = geometry.intersects(this);
│ │ │ │ │ + }
│ │ │ │ │ + return intersect;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Constant: URL_SPLIT_REGEX
│ │ │ │ │ - */
│ │ │ │ │ - URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: events
│ │ │ │ │ - * {} An events object that handles all
│ │ │ │ │ - * events on the {} object.
│ │ │ │ │ - *
│ │ │ │ │ - * All event listeners will receive an event object with three properties:
│ │ │ │ │ - * request - {} The request object.
│ │ │ │ │ - * config - {Object} The config object sent to the specific request method.
│ │ │ │ │ - * requestUrl - {String} The request url.
│ │ │ │ │ - *
│ │ │ │ │ - * Supported event types:
│ │ │ │ │ - * complete - Triggered when we have a response from the request, if a
│ │ │ │ │ - * listener returns false, no further response processing will take
│ │ │ │ │ - * place.
│ │ │ │ │ - * success - Triggered when the HTTP response has a success code (200-299).
│ │ │ │ │ - * failure - Triggered when the HTTP response does not have a success code.
│ │ │ │ │ - */
│ │ │ │ │ - events: new OpenLayers.Events(this),
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: makeSameOrigin
│ │ │ │ │ - * Using the specified proxy, returns a same origin url of the provided url.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * url - {String} An arbitrary url
│ │ │ │ │ - * proxy {String|Function} The proxy to use to make the provided url a
│ │ │ │ │ - * same origin url.
│ │ │ │ │ + * Method: getSortedSegments
│ │ │ │ │ *
│ │ │ │ │ - * Returns
│ │ │ │ │ - * {String} the same origin url. If no proxy is provided, the returned url
│ │ │ │ │ - * will be the same as the provided url.
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} An array of segment objects. Segment objects have properties
│ │ │ │ │ + * x1, y1, x2, and y2. The start point is represented by x1 and y1.
│ │ │ │ │ + * The end point is represented by x2 and y2. Start and end are
│ │ │ │ │ + * ordered so that x1 < x2.
│ │ │ │ │ */
│ │ │ │ │ - makeSameOrigin: function(url, proxy) {
│ │ │ │ │ - var sameOrigin = url.indexOf("http") !== 0;
│ │ │ │ │ - var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX);
│ │ │ │ │ - if (urlParts) {
│ │ │ │ │ - var location = window.location;
│ │ │ │ │ - sameOrigin =
│ │ │ │ │ - urlParts[1] == location.protocol &&
│ │ │ │ │ - urlParts[3] == location.hostname;
│ │ │ │ │ - var uPort = urlParts[4],
│ │ │ │ │ - lPort = location.port;
│ │ │ │ │ - if (uPort != 80 && uPort != "" || lPort != "80" && lPort != "") {
│ │ │ │ │ - sameOrigin = sameOrigin && uPort == lPort;
│ │ │ │ │ + getSortedSegments: function() {
│ │ │ │ │ + var numSeg = this.components.length - 1;
│ │ │ │ │ + var segments = new Array(numSeg),
│ │ │ │ │ + point1, point2;
│ │ │ │ │ + for (var i = 0; i < numSeg; ++i) {
│ │ │ │ │ + point1 = this.components[i];
│ │ │ │ │ + point2 = this.components[i + 1];
│ │ │ │ │ + if (point1.x < point2.x) {
│ │ │ │ │ + segments[i] = {
│ │ │ │ │ + x1: point1.x,
│ │ │ │ │ + y1: point1.y,
│ │ │ │ │ + x2: point2.x,
│ │ │ │ │ + y2: point2.y
│ │ │ │ │ + };
│ │ │ │ │ + } else {
│ │ │ │ │ + segments[i] = {
│ │ │ │ │ + x1: point2.x,
│ │ │ │ │ + y1: point2.y,
│ │ │ │ │ + x2: point1.x,
│ │ │ │ │ + y2: point1.y
│ │ │ │ │ + };
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ - if (!sameOrigin) {
│ │ │ │ │ - if (proxy) {
│ │ │ │ │ - if (typeof proxy == "function") {
│ │ │ │ │ - url = proxy(url);
│ │ │ │ │ - } else {
│ │ │ │ │ - url = proxy + encodeURIComponent(url);
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ + // more efficient to define this somewhere static
│ │ │ │ │ + function byX1(seg1, seg2) {
│ │ │ │ │ + return seg1.x1 - seg2.x1;
│ │ │ │ │ }
│ │ │ │ │ - return url;
│ │ │ │ │ + return segments.sort(byX1);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: issue
│ │ │ │ │ - * Create a new XMLHttpRequest object, open it, set any headers, bind
│ │ │ │ │ - * a callback to done state, and send any data. It is recommended that
│ │ │ │ │ - * you use one , , , , , or .
│ │ │ │ │ - * This method is only documented to provide detail on the configuration
│ │ │ │ │ - * options available to all request methods.
│ │ │ │ │ + * Method: splitWithSegment
│ │ │ │ │ + * Split this geometry with the given segment.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * config - {Object} Object containing properties for configuring the
│ │ │ │ │ - * request. Allowed configuration properties are described below.
│ │ │ │ │ - * This object is modified and should not be reused.
│ │ │ │ │ + * seg - {Object} An object with x1, y1, x2, and y2 properties referencing
│ │ │ │ │ + * segment endpoint coordinates.
│ │ │ │ │ + * options - {Object} Properties of this object will be used to determine
│ │ │ │ │ + * how the split is conducted.
│ │ │ │ │ *
│ │ │ │ │ - * Allowed config properties:
│ │ │ │ │ - * method - {String} One of GET, POST, PUT, DELETE, HEAD, or
│ │ │ │ │ - * OPTIONS. Default is GET.
│ │ │ │ │ - * url - {String} URL for the request.
│ │ │ │ │ - * async - {Boolean} Open an asynchronous request. Default is true.
│ │ │ │ │ - * user - {String} User for relevant authentication scheme. Set
│ │ │ │ │ - * to null to clear current user.
│ │ │ │ │ - * password - {String} Password for relevant authentication scheme.
│ │ │ │ │ - * Set to null to clear current password.
│ │ │ │ │ - * proxy - {String} Optional proxy. Defaults to
│ │ │ │ │ - * .
│ │ │ │ │ - * params - {Object} Any key:value pairs to be appended to the
│ │ │ │ │ - * url as a query string. Assumes url doesn't already include a query
│ │ │ │ │ - * string or hash. Typically, this is only appropriate for
│ │ │ │ │ - * requests where the query string will be appended to the url.
│ │ │ │ │ - * Parameter values that are arrays will be
│ │ │ │ │ - * concatenated with a comma (note that this goes against form-encoding)
│ │ │ │ │ - * as is done with .
│ │ │ │ │ - * headers - {Object} Object with header:value pairs to be set on
│ │ │ │ │ - * the request.
│ │ │ │ │ - * data - {String | Document} Optional data to send with the request.
│ │ │ │ │ - * Typically, this is only used with and requests.
│ │ │ │ │ - * Make sure to provide the appropriate "Content-Type" header for your
│ │ │ │ │ - * data. For and requests, the content type defaults to
│ │ │ │ │ - * "application-xml". If your data is a different content type, or
│ │ │ │ │ - * if you are using a different HTTP method, set the "Content-Type"
│ │ │ │ │ - * header to match your data type.
│ │ │ │ │ - * callback - {Function} Function to call when request is done.
│ │ │ │ │ - * To determine if the request failed, check request.status (200
│ │ │ │ │ - * indicates success).
│ │ │ │ │ - * success - {Function} Optional function to call if request status is in
│ │ │ │ │ - * the 200s. This will be called in addition to callback above and
│ │ │ │ │ - * would typically only be used as an alternative.
│ │ │ │ │ - * failure - {Function} Optional function to call if request status is not
│ │ │ │ │ - * in the 200s. This will be called in addition to callback above and
│ │ │ │ │ - * would typically only be used as an alternative.
│ │ │ │ │ - * scope - {Object} If callback is a public method on some object,
│ │ │ │ │ - * set the scope to that object.
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is
│ │ │ │ │ + * true. If false, a vertex on the source segment must be within the
│ │ │ │ │ + * tolerance distance of the intersection to be considered a split.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, intersections
│ │ │ │ │ + * within the tolerance distance of one of the source segment's
│ │ │ │ │ + * endpoints will be assumed to occur at the endpoint.
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object. To abort the request before a response
│ │ │ │ │ - * is received, call abort() on the request object.
│ │ │ │ │ + * {Object} An object with *lines* and *points* properties. If the given
│ │ │ │ │ + * segment intersects this linestring, the lines array will reference
│ │ │ │ │ + * geometries that result from the split. The points array will contain
│ │ │ │ │ + * all intersection points. Intersection points are sorted along the
│ │ │ │ │ + * segment (in order from x1,y1 to x2,y2).
│ │ │ │ │ */
│ │ │ │ │ - issue: function(config) {
│ │ │ │ │ - // apply default config - proxy host may have changed
│ │ │ │ │ - var defaultConfig = OpenLayers.Util.extend(
│ │ │ │ │ - this.DEFAULT_CONFIG, {
│ │ │ │ │ - proxy: OpenLayers.ProxyHost
│ │ │ │ │ - }
│ │ │ │ │ - );
│ │ │ │ │ - config = config || {};
│ │ │ │ │ - config.headers = config.headers || {};
│ │ │ │ │ - config = OpenLayers.Util.applyDefaults(config, defaultConfig);
│ │ │ │ │ - config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers);
│ │ │ │ │ - // Always set the "X-Requested-With" header to signal that this request
│ │ │ │ │ - // was issued through the XHR-object. Since header keys are case
│ │ │ │ │ - // insensitive and we want to allow overriding of the "X-Requested-With"
│ │ │ │ │ - // header through the user we cannot use applyDefaults, but have to
│ │ │ │ │ - // check manually whether we were called with a "X-Requested-With"
│ │ │ │ │ - // header.
│ │ │ │ │ - var customRequestedWithHeader = false,
│ │ │ │ │ - headerKey;
│ │ │ │ │ - for (headerKey in config.headers) {
│ │ │ │ │ - if (config.headers.hasOwnProperty(headerKey)) {
│ │ │ │ │ - if (headerKey.toLowerCase() === 'x-requested-with') {
│ │ │ │ │ - customRequestedWithHeader = true;
│ │ │ │ │ + splitWithSegment: function(seg, options) {
│ │ │ │ │ + var edge = !(options && options.edge === false);
│ │ │ │ │ + var tolerance = options && options.tolerance;
│ │ │ │ │ + var lines = [];
│ │ │ │ │ + var verts = this.getVertices();
│ │ │ │ │ + var points = [];
│ │ │ │ │ + var intersections = [];
│ │ │ │ │ + var split = false;
│ │ │ │ │ + var vert1, vert2, point;
│ │ │ │ │ + var node, vertex, target;
│ │ │ │ │ + var interOptions = {
│ │ │ │ │ + point: true,
│ │ │ │ │ + tolerance: tolerance
│ │ │ │ │ + };
│ │ │ │ │ + var result = null;
│ │ │ │ │ + for (var i = 0, stop = verts.length - 2; i <= stop; ++i) {
│ │ │ │ │ + vert1 = verts[i];
│ │ │ │ │ + points.push(vert1.clone());
│ │ │ │ │ + vert2 = verts[i + 1];
│ │ │ │ │ + target = {
│ │ │ │ │ + x1: vert1.x,
│ │ │ │ │ + y1: vert1.y,
│ │ │ │ │ + x2: vert2.x,
│ │ │ │ │ + y2: vert2.y
│ │ │ │ │ + };
│ │ │ │ │ + point = OpenLayers.Geometry.segmentsIntersect(
│ │ │ │ │ + seg, target, interOptions
│ │ │ │ │ + );
│ │ │ │ │ + if (point instanceof OpenLayers.Geometry.Point) {
│ │ │ │ │ + if ((point.x === seg.x1 && point.y === seg.y1) ||
│ │ │ │ │ + (point.x === seg.x2 && point.y === seg.y2) ||
│ │ │ │ │ + point.equals(vert1) || point.equals(vert2)) {
│ │ │ │ │ + vertex = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + vertex = false;
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ - }
│ │ │ │ │ - if (customRequestedWithHeader === false) {
│ │ │ │ │ - // we did not have a custom "X-Requested-With" header
│ │ │ │ │ - config.headers['X-Requested-With'] = 'XMLHttpRequest';
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // create request, open, and set headers
│ │ │ │ │ - var request = new OpenLayers.Request.XMLHttpRequest();
│ │ │ │ │ - var url = OpenLayers.Util.urlAppend(config.url,
│ │ │ │ │ - OpenLayers.Util.getParameterString(config.params || {}));
│ │ │ │ │ - url = OpenLayers.Request.makeSameOrigin(url, config.proxy);
│ │ │ │ │ - request.open(
│ │ │ │ │ - config.method, url, config.async, config.user, config.password
│ │ │ │ │ - );
│ │ │ │ │ - for (var header in config.headers) {
│ │ │ │ │ - request.setRequestHeader(header, config.headers[header]);
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - var events = this.events;
│ │ │ │ │ -
│ │ │ │ │ - // we want to execute runCallbacks with "this" as the
│ │ │ │ │ - // execution scope
│ │ │ │ │ - var self = this;
│ │ │ │ │ -
│ │ │ │ │ - request.onreadystatechange = function() {
│ │ │ │ │ - if (request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
│ │ │ │ │ - var proceed = events.triggerEvent(
│ │ │ │ │ - "complete", {
│ │ │ │ │ - request: request,
│ │ │ │ │ - config: config,
│ │ │ │ │ - requestUrl: url
│ │ │ │ │ + if (vertex || edge) {
│ │ │ │ │ + // push intersections different than the previous
│ │ │ │ │ + if (!point.equals(intersections[intersections.length - 1])) {
│ │ │ │ │ + intersections.push(point.clone());
│ │ │ │ │ }
│ │ │ │ │ - );
│ │ │ │ │ - if (proceed !== false) {
│ │ │ │ │ - self.runCallbacks({
│ │ │ │ │ - request: request,
│ │ │ │ │ - config: config,
│ │ │ │ │ - requestUrl: url
│ │ │ │ │ - });
│ │ │ │ │ + if (i === 0) {
│ │ │ │ │ + if (point.equals(vert1)) {
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (point.equals(vert2)) {
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + split = true;
│ │ │ │ │ + if (!point.equals(vert1)) {
│ │ │ │ │ + points.push(point);
│ │ │ │ │ + }
│ │ │ │ │ + lines.push(new OpenLayers.Geometry.LineString(points));
│ │ │ │ │ + points = [point.clone()];
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ - };
│ │ │ │ │ -
│ │ │ │ │ - // send request (optionally with data) and return
│ │ │ │ │ - // call in a timeout for asynchronous requests so the return is
│ │ │ │ │ - // available before readyState == 4 for cached docs
│ │ │ │ │ - if (config.async === false) {
│ │ │ │ │ - request.send(config.data);
│ │ │ │ │ - } else {
│ │ │ │ │ - window.setTimeout(function() {
│ │ │ │ │ - if (request.readyState !== 0) { // W3C: 0-UNSENT
│ │ │ │ │ - request.send(config.data);
│ │ │ │ │ - }
│ │ │ │ │ - }, 0);
│ │ │ │ │ }
│ │ │ │ │ - return request;
│ │ │ │ │ + if (split) {
│ │ │ │ │ + points.push(vert2.clone());
│ │ │ │ │ + lines.push(new OpenLayers.Geometry.LineString(points));
│ │ │ │ │ + }
│ │ │ │ │ + if (intersections.length > 0) {
│ │ │ │ │ + // sort intersections along segment
│ │ │ │ │ + var xDir = seg.x1 < seg.x2 ? 1 : -1;
│ │ │ │ │ + var yDir = seg.y1 < seg.y2 ? 1 : -1;
│ │ │ │ │ + result = {
│ │ │ │ │ + lines: lines,
│ │ │ │ │ + points: intersections.sort(function(p1, p2) {
│ │ │ │ │ + return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);
│ │ │ │ │ + })
│ │ │ │ │ + };
│ │ │ │ │ + }
│ │ │ │ │ + return result;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Method: runCallbacks
│ │ │ │ │ - * Calls the complete, success and failure callbacks. Application
│ │ │ │ │ - * can listen to the "complete" event, have the listener
│ │ │ │ │ - * display a confirm window and always return false, and
│ │ │ │ │ - * execute OpenLayers.Request.runCallbacks if the user
│ │ │ │ │ - * hits "yes" in the confirm window.
│ │ │ │ │ - *
│ │ │ │ │ + * Method: split
│ │ │ │ │ + * Use this geometry (the source) to attempt to split a target geometry.
│ │ │ │ │ + *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * options - {Object} Hash containing request, config and requestUrl keys
│ │ │ │ │ + * target - {} The target geometry.
│ │ │ │ │ + * options - {Object} Properties of this object will be used to determine
│ │ │ │ │ + * how the split is conducted.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * mutual - {Boolean} Split the source geometry in addition to the target
│ │ │ │ │ + * geometry. Default is false.
│ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is
│ │ │ │ │ + * true. If false, a vertex on the source must be within the tolerance
│ │ │ │ │ + * distance of the intersection to be considered a split.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, intersections
│ │ │ │ │ + * within the tolerance distance of an existing vertex on the source
│ │ │ │ │ + * will be assumed to occur at the vertex.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} A list of geometries (of this same type as the target) that
│ │ │ │ │ + * result from splitting the target with the source geometry. The
│ │ │ │ │ + * source and target geometry will remain unmodified. If no split
│ │ │ │ │ + * results, null will be returned. If mutual is true and a split
│ │ │ │ │ + * results, return will be an array of two arrays - the first will be
│ │ │ │ │ + * all geometries that result from splitting the source geometry and
│ │ │ │ │ + * the second will be all geometries that result from splitting the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ */
│ │ │ │ │ - runCallbacks: function(options) {
│ │ │ │ │ - var request = options.request;
│ │ │ │ │ - var config = options.config;
│ │ │ │ │ -
│ │ │ │ │ - // bind callbacks to readyState 4 (done)
│ │ │ │ │ - var complete = (config.scope) ?
│ │ │ │ │ - OpenLayers.Function.bind(config.callback, config.scope) :
│ │ │ │ │ - config.callback;
│ │ │ │ │ -
│ │ │ │ │ - // optional success callback
│ │ │ │ │ - var success;
│ │ │ │ │ - if (config.success) {
│ │ │ │ │ - success = (config.scope) ?
│ │ │ │ │ - OpenLayers.Function.bind(config.success, config.scope) :
│ │ │ │ │ - config.success;
│ │ │ │ │ - }
│ │ │ │ │ -
│ │ │ │ │ - // optional failure callback
│ │ │ │ │ - var failure;
│ │ │ │ │ - if (config.failure) {
│ │ │ │ │ - failure = (config.scope) ?
│ │ │ │ │ - OpenLayers.Function.bind(config.failure, config.scope) :
│ │ │ │ │ - config.failure;
│ │ │ │ │ + split: function(target, options) {
│ │ │ │ │ + var results = null;
│ │ │ │ │ + var mutual = options && options.mutual;
│ │ │ │ │ + var sourceSplit, targetSplit, sourceParts, targetParts;
│ │ │ │ │ + if (target instanceof OpenLayers.Geometry.LineString) {
│ │ │ │ │ + var verts = this.getVertices();
│ │ │ │ │ + var vert1, vert2, seg, splits, lines, point;
│ │ │ │ │ + var points = [];
│ │ │ │ │ + sourceParts = [];
│ │ │ │ │ + for (var i = 0, stop = verts.length - 2; i <= stop; ++i) {
│ │ │ │ │ + vert1 = verts[i];
│ │ │ │ │ + vert2 = verts[i + 1];
│ │ │ │ │ + seg = {
│ │ │ │ │ + x1: vert1.x,
│ │ │ │ │ + y1: vert1.y,
│ │ │ │ │ + x2: vert2.x,
│ │ │ │ │ + y2: vert2.y
│ │ │ │ │ + };
│ │ │ │ │ + targetParts = targetParts || [target];
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + points.push(vert1.clone());
│ │ │ │ │ + }
│ │ │ │ │ + for (var j = 0; j < targetParts.length; ++j) {
│ │ │ │ │ + splits = targetParts[j].splitWithSegment(seg, options);
│ │ │ │ │ + if (splits) {
│ │ │ │ │ + // splice in new features
│ │ │ │ │ + lines = splits.lines;
│ │ │ │ │ + if (lines.length > 0) {
│ │ │ │ │ + lines.unshift(j, 1);
│ │ │ │ │ + Array.prototype.splice.apply(targetParts, lines);
│ │ │ │ │ + j += lines.length - 2;
│ │ │ │ │ + }
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + for (var k = 0, len = splits.points.length; k < len; ++k) {
│ │ │ │ │ + point = splits.points[k];
│ │ │ │ │ + if (!point.equals(vert1)) {
│ │ │ │ │ + points.push(point);
│ │ │ │ │ + sourceParts.push(new OpenLayers.Geometry.LineString(points));
│ │ │ │ │ + if (point.equals(vert2)) {
│ │ │ │ │ + points = [];
│ │ │ │ │ + } else {
│ │ │ │ │ + points = [point.clone()];
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (mutual && sourceParts.length > 0 && points.length > 0) {
│ │ │ │ │ + points.push(vert2.clone());
│ │ │ │ │ + sourceParts.push(new OpenLayers.Geometry.LineString(points));
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + results = target.splitWith(this, options);
│ │ │ │ │ }
│ │ │ │ │ -
│ │ │ │ │ - if (OpenLayers.Util.createUrlObject(config.url).protocol == "file:" &&
│ │ │ │ │ - request.responseText) {
│ │ │ │ │ - request.status = 200;
│ │ │ │ │ + if (targetParts && targetParts.length > 1) {
│ │ │ │ │ + targetSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + targetParts = [];
│ │ │ │ │ }
│ │ │ │ │ - complete(request);
│ │ │ │ │ -
│ │ │ │ │ - if (!request.status || (request.status >= 200 && request.status < 300)) {
│ │ │ │ │ - this.events.triggerEvent("success", options);
│ │ │ │ │ - if (success) {
│ │ │ │ │ - success(request);
│ │ │ │ │ - }
│ │ │ │ │ + if (sourceParts && sourceParts.length > 1) {
│ │ │ │ │ + sourceSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + sourceParts = [];
│ │ │ │ │ }
│ │ │ │ │ - if (request.status && (request.status < 200 || request.status >= 300)) {
│ │ │ │ │ - this.events.triggerEvent("failure", options);
│ │ │ │ │ - if (failure) {
│ │ │ │ │ - failure(request);
│ │ │ │ │ + if (targetSplit || sourceSplit) {
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + results = [sourceParts, targetParts];
│ │ │ │ │ + } else {
│ │ │ │ │ + results = targetParts;
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ + return results;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: GET
│ │ │ │ │ - * Send an HTTP GET request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to GET.
│ │ │ │ │ + * Method: splitWith
│ │ │ │ │ + * Split this geometry (the target) with the given geometry (the source).
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties.
│ │ │ │ │ - * This object is modified and should not be reused.
│ │ │ │ │ + * geometry - {} A geometry used to split this
│ │ │ │ │ + * geometry (the source).
│ │ │ │ │ + * options - {Object} Properties of this object will be used to determine
│ │ │ │ │ + * how the split is conducted.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * mutual - {Boolean} Split the source geometry in addition to the target
│ │ │ │ │ + * geometry. Default is false.
│ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is
│ │ │ │ │ + * true. If false, a vertex on the source must be within the tolerance
│ │ │ │ │ + * distance of the intersection to be considered a split.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, intersections
│ │ │ │ │ + * within the tolerance distance of an existing vertex on the source
│ │ │ │ │ + * will be assumed to occur at the vertex.
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ + * {Array} A list of geometries (of this same type as the target) that
│ │ │ │ │ + * result from splitting the target with the source geometry. The
│ │ │ │ │ + * source and target geometry will remain unmodified. If no split
│ │ │ │ │ + * results, null will be returned. If mutual is true and a split
│ │ │ │ │ + * results, return will be an array of two arrays - the first will be
│ │ │ │ │ + * all geometries that result from splitting the source geometry and
│ │ │ │ │ + * the second will be all geometries that result from splitting the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ */
│ │ │ │ │ - GET: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "GET"
│ │ │ │ │ - });
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ + splitWith: function(geometry, options) {
│ │ │ │ │ + return geometry.split(this, options);
│ │ │ │ │ +
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: POST
│ │ │ │ │ - * Send a POST request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to POST and "Content-Type" header set to "application/xml".
│ │ │ │ │ + * APIMethod: getVertices
│ │ │ │ │ + * Return a list of all points in this geometry.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties. The
│ │ │ │ │ - * default "Content-Type" header will be set to "application-xml" if
│ │ │ │ │ - * none is provided. This object is modified and should not be reused.
│ │ │ │ │ - *
│ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are
│ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not
│ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will
│ │ │ │ │ + * be returned.
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ + * {Array} A list of all vertices in the geometry.
│ │ │ │ │ */
│ │ │ │ │ - POST: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "POST"
│ │ │ │ │ - });
│ │ │ │ │ - // set content type to application/xml if it isn't already set
│ │ │ │ │ - config.headers = config.headers ? config.headers : {};
│ │ │ │ │ - if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
│ │ │ │ │ - config.headers["Content-Type"] = "application/xml";
│ │ │ │ │ + getVertices: function(nodes) {
│ │ │ │ │ + var vertices;
│ │ │ │ │ + if (nodes === true) {
│ │ │ │ │ + vertices = [
│ │ │ │ │ + this.components[0],
│ │ │ │ │ + this.components[this.components.length - 1]
│ │ │ │ │ + ];
│ │ │ │ │ + } else if (nodes === false) {
│ │ │ │ │ + vertices = this.components.slice(1, this.components.length - 1);
│ │ │ │ │ + } else {
│ │ │ │ │ + vertices = this.components.slice();
│ │ │ │ │ }
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ + return vertices;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: PUT
│ │ │ │ │ - * Send an HTTP PUT request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to PUT and "Content-Type" header set to "application/xml".
│ │ │ │ │ + * APIMethod: distanceTo
│ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane).
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties. The
│ │ │ │ │ - * default "Content-Type" header will be set to "application-xml" if
│ │ │ │ │ - * none is provided. This object is modified and should not be reused.
│ │ │ │ │ - *
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Optional properties for configuring the distance
│ │ │ │ │ + * calculation.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * details - {Boolean} Return details from the distance calculation.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the
│ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true,
│ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within
│ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever
│ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false,
│ │ │ │ │ + * details cannot be returned.
│ │ │ │ │ + *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ + * {Number | Object} The distance between this geometry and the target.
│ │ │ │ │ + * If details is true, the return will be an object with distance,
│ │ │ │ │ + * x0, y0, x1, and x2 properties. The x0 and y0 properties represent
│ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1
│ │ │ │ │ + * properties represent the coordinates of the closest point on the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ */
│ │ │ │ │ - PUT: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "PUT"
│ │ │ │ │ - });
│ │ │ │ │ - // set content type to application/xml if it isn't already set
│ │ │ │ │ - config.headers = config.headers ? config.headers : {};
│ │ │ │ │ - if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
│ │ │ │ │ - config.headers["Content-Type"] = "application/xml";
│ │ │ │ │ + distanceTo: function(geometry, options) {
│ │ │ │ │ + var edge = !(options && options.edge === false);
│ │ │ │ │ + var details = edge && options && options.details;
│ │ │ │ │ + var result, best = {};
│ │ │ │ │ + var min = Number.POSITIVE_INFINITY;
│ │ │ │ │ + if (geometry instanceof OpenLayers.Geometry.Point) {
│ │ │ │ │ + var segs = this.getSortedSegments();
│ │ │ │ │ + var x = geometry.x;
│ │ │ │ │ + var y = geometry.y;
│ │ │ │ │ + var seg;
│ │ │ │ │ + for (var i = 0, len = segs.length; i < len; ++i) {
│ │ │ │ │ + seg = segs[i];
│ │ │ │ │ + result = OpenLayers.Geometry.distanceToSegment(geometry, seg);
│ │ │ │ │ + if (result.distance < min) {
│ │ │ │ │ + min = result.distance;
│ │ │ │ │ + best = result;
│ │ │ │ │ + if (min === 0) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + // if distance increases and we cross y0 to the right of x0, no need to keep looking.
│ │ │ │ │ + if (seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (details) {
│ │ │ │ │ + best = {
│ │ │ │ │ + distance: best.distance,
│ │ │ │ │ + x0: best.x,
│ │ │ │ │ + y0: best.y,
│ │ │ │ │ + x1: x,
│ │ │ │ │ + y1: y
│ │ │ │ │ + };
│ │ │ │ │ + } else {
│ │ │ │ │ + best = best.distance;
│ │ │ │ │ + }
│ │ │ │ │ + } else if (geometry instanceof OpenLayers.Geometry.LineString) {
│ │ │ │ │ + var segs0 = this.getSortedSegments();
│ │ │ │ │ + var segs1 = geometry.getSortedSegments();
│ │ │ │ │ + var seg0, seg1, intersection, x0, y0;
│ │ │ │ │ + var len1 = segs1.length;
│ │ │ │ │ + var interOptions = {
│ │ │ │ │ + point: true
│ │ │ │ │ + };
│ │ │ │ │ + outer: for (var i = 0, len = segs0.length; i < len; ++i) {
│ │ │ │ │ + seg0 = segs0[i];
│ │ │ │ │ + x0 = seg0.x1;
│ │ │ │ │ + y0 = seg0.y1;
│ │ │ │ │ + for (var j = 0; j < len1; ++j) {
│ │ │ │ │ + seg1 = segs1[j];
│ │ │ │ │ + intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);
│ │ │ │ │ + if (intersection) {
│ │ │ │ │ + min = 0;
│ │ │ │ │ + best = {
│ │ │ │ │ + distance: 0,
│ │ │ │ │ + x0: intersection.x,
│ │ │ │ │ + y0: intersection.y,
│ │ │ │ │ + x1: intersection.x,
│ │ │ │ │ + y1: intersection.y
│ │ │ │ │ + };
│ │ │ │ │ + break outer;
│ │ │ │ │ + } else {
│ │ │ │ │ + result = OpenLayers.Geometry.distanceToSegment({
│ │ │ │ │ + x: x0,
│ │ │ │ │ + y: y0
│ │ │ │ │ + }, seg1);
│ │ │ │ │ + if (result.distance < min) {
│ │ │ │ │ + min = result.distance;
│ │ │ │ │ + best = {
│ │ │ │ │ + distance: min,
│ │ │ │ │ + x0: x0,
│ │ │ │ │ + y0: y0,
│ │ │ │ │ + x1: result.x,
│ │ │ │ │ + y1: result.y
│ │ │ │ │ + };
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!details) {
│ │ │ │ │ + best = best.distance;
│ │ │ │ │ + }
│ │ │ │ │ + if (min !== 0) {
│ │ │ │ │ + // check the final vertex in this line's sorted segments
│ │ │ │ │ + if (seg0) {
│ │ │ │ │ + result = geometry.distanceTo(
│ │ │ │ │ + new OpenLayers.Geometry.Point(seg0.x2, seg0.y2),
│ │ │ │ │ + options
│ │ │ │ │ + );
│ │ │ │ │ + var dist = details ? result.distance : result;
│ │ │ │ │ + if (dist < min) {
│ │ │ │ │ + if (details) {
│ │ │ │ │ + best = {
│ │ │ │ │ + distance: min,
│ │ │ │ │ + x0: result.x1,
│ │ │ │ │ + y0: result.y1,
│ │ │ │ │ + x1: result.x0,
│ │ │ │ │ + y1: result.y0
│ │ │ │ │ + };
│ │ │ │ │ + } else {
│ │ │ │ │ + best = dist;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + best = geometry.distanceTo(this, options);
│ │ │ │ │ + // swap since target comes from this line
│ │ │ │ │ + if (details) {
│ │ │ │ │ + best = {
│ │ │ │ │ + distance: best.distance,
│ │ │ │ │ + x0: best.x1,
│ │ │ │ │ + y0: best.y1,
│ │ │ │ │ + x1: best.x0,
│ │ │ │ │ + y1: best.y0
│ │ │ │ │ + };
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ + return best;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: DELETE
│ │ │ │ │ - * Send an HTTP DELETE request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to DELETE.
│ │ │ │ │ + * APIMethod: simplify
│ │ │ │ │ + * This function will return a simplified LineString.
│ │ │ │ │ + * Simplification is based on the Douglas-Peucker algorithm.
│ │ │ │ │ *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties.
│ │ │ │ │ - * This object is modified and should not be reused.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ - */
│ │ │ │ │ - DELETE: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "DELETE"
│ │ │ │ │ - });
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: HEAD
│ │ │ │ │ - * Send an HTTP HEAD request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to HEAD.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties.
│ │ │ │ │ - * This object is modified and should not be reused.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ - */
│ │ │ │ │ - HEAD: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "HEAD"
│ │ │ │ │ - });
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ - },
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: OPTIONS
│ │ │ │ │ - * Send an HTTP OPTIONS request. Additional configuration properties are
│ │ │ │ │ - * documented in the method, with the method property set
│ │ │ │ │ - * to OPTIONS.
│ │ │ │ │ + * tolerance - {number} threshhold for simplification in map units
│ │ │ │ │ *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ - * See the method for documentation of allowed properties.
│ │ │ │ │ - * This object is modified and should not be reused.
│ │ │ │ │ - *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {XMLHttpRequest} Request object.
│ │ │ │ │ + * {OpenLayers.Geometry.LineString} the simplified LineString
│ │ │ │ │ */
│ │ │ │ │ - OPTIONS: function(config) {
│ │ │ │ │ - config = OpenLayers.Util.extend(config, {
│ │ │ │ │ - method: "OPTIONS"
│ │ │ │ │ - });
│ │ │ │ │ - return OpenLayers.Request.issue(config);
│ │ │ │ │ - }
│ │ │ │ │ + simplify: function(tolerance) {
│ │ │ │ │ + if (this && this !== null) {
│ │ │ │ │ + var points = this.getVertices();
│ │ │ │ │ + if (points.length < 3) {
│ │ │ │ │ + return this;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + var compareNumbers = function(a, b) {
│ │ │ │ │ + return (a - b);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Private function doing the Douglas-Peucker reduction
│ │ │ │ │ + */
│ │ │ │ │ + var douglasPeuckerReduction = function(points, firstPoint, lastPoint, tolerance) {
│ │ │ │ │ + var maxDistance = 0;
│ │ │ │ │ + var indexFarthest = 0;
│ │ │ │ │ +
│ │ │ │ │ + for (var index = firstPoint, distance; index < lastPoint; index++) {
│ │ │ │ │ + distance = perpendicularDistance(points[firstPoint], points[lastPoint], points[index]);
│ │ │ │ │ + if (distance > maxDistance) {
│ │ │ │ │ + maxDistance = distance;
│ │ │ │ │ + indexFarthest = index;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (maxDistance > tolerance && indexFarthest != firstPoint) {
│ │ │ │ │ + //Add the largest point that exceeds the tolerance
│ │ │ │ │ + pointIndexsToKeep.push(indexFarthest);
│ │ │ │ │ + douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance);
│ │ │ │ │ + douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance);
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Private function calculating the perpendicular distance
│ │ │ │ │ + * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower
│ │ │ │ │ + */
│ │ │ │ │ + var perpendicularDistance = function(point1, point2, point) {
│ │ │ │ │ + //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle
│ │ │ │ │ + //Base = v((x1-x2)²+(x1-x2)²) *Base of Triangle*
│ │ │ │ │ + //Area = .5*Base*H *Solve for height
│ │ │ │ │ + //Height = Area/.5/Base
│ │ │ │ │ +
│ │ │ │ │ + var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y));
│ │ │ │ │ + var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
│ │ │ │ │ + var height = area / bottom * 2;
│ │ │ │ │ +
│ │ │ │ │ + return height;
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + var firstPoint = 0;
│ │ │ │ │ + var lastPoint = points.length - 1;
│ │ │ │ │ + var pointIndexsToKeep = [];
│ │ │ │ │ +
│ │ │ │ │ + //Add the first and last index to the keepers
│ │ │ │ │ + pointIndexsToKeep.push(firstPoint);
│ │ │ │ │ + pointIndexsToKeep.push(lastPoint);
│ │ │ │ │ +
│ │ │ │ │ + //The first and the last point cannot be the same
│ │ │ │ │ + while (points[firstPoint].equals(points[lastPoint])) {
│ │ │ │ │ + lastPoint--;
│ │ │ │ │ + //Addition: the first point not equal to first point in the LineString is kept as well
│ │ │ │ │ + pointIndexsToKeep.push(lastPoint);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance);
│ │ │ │ │ + var returnPoints = [];
│ │ │ │ │ + pointIndexsToKeep.sort(compareNumbers);
│ │ │ │ │ + for (var index = 0; index < pointIndexsToKeep.length; index++) {
│ │ │ │ │ + returnPoints.push(points[pointIndexsToKeep[index]]);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Geometry.LineString(returnPoints);
│ │ │ │ │ +
│ │ │ │ │ + } else {
│ │ │ │ │ + return this;
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.LineString"
│ │ │ │ │ });
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Format.js
│ │ │ │ │ + OpenLayers/Geometry/MultiLineString.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Util.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Collection.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/LineString.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.Format
│ │ │ │ │ - * Base class for format reading/writing a variety of formats. Subclasses
│ │ │ │ │ - * of OpenLayers.Format are expected to have read and write methods.
│ │ │ │ │ + * Class: OpenLayers.Geometry.MultiLineString
│ │ │ │ │ + * A MultiLineString is a geometry with multiple
│ │ │ │ │ + * components.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Format = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: options
│ │ │ │ │ - * {Object} A reference to options passed to the constructor.
│ │ │ │ │ - */
│ │ │ │ │ - options: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: externalProjection
│ │ │ │ │ - * {} When passed a externalProjection and
│ │ │ │ │ - * internalProjection, the format will reproject the geometries it
│ │ │ │ │ - * reads or writes. The externalProjection is the projection used by
│ │ │ │ │ - * the content which is passed into read or which comes out of write.
│ │ │ │ │ - * In order to reproject, a projection transformation function for the
│ │ │ │ │ - * specified projections must be available. This support may be
│ │ │ │ │ - * provided via proj4js or via a custom transformation function. See
│ │ │ │ │ - * {} for more information on
│ │ │ │ │ - * custom transformations.
│ │ │ │ │ - */
│ │ │ │ │ - externalProjection: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: internalProjection
│ │ │ │ │ - * {} When passed a externalProjection and
│ │ │ │ │ - * internalProjection, the format will reproject the geometries it
│ │ │ │ │ - * reads or writes. The internalProjection is the projection used by
│ │ │ │ │ - * the geometries which are returned by read or which are passed into
│ │ │ │ │ - * write. In order to reproject, a projection transformation function
│ │ │ │ │ - * for the specified projections must be available. This support may be
│ │ │ │ │ - * provided via proj4js or via a custom transformation function. See
│ │ │ │ │ - * {} for more information on
│ │ │ │ │ - * custom transformations.
│ │ │ │ │ - */
│ │ │ │ │ - internalProjection: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: data
│ │ │ │ │ - * {Object} When is true, this is the parsed string sent to
│ │ │ │ │ - * .
│ │ │ │ │ - */
│ │ │ │ │ - data: null,
│ │ │ │ │ +OpenLayers.Geometry.MultiLineString = OpenLayers.Class(
│ │ │ │ │ + OpenLayers.Geometry.Collection, {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: keepData
│ │ │ │ │ - * {Object} Maintain a reference () to the most recently read data.
│ │ │ │ │ - * Default is false.
│ │ │ │ │ - */
│ │ │ │ │ - keepData: false,
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null value means the
│ │ │ │ │ + * component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.LineString"],
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Format
│ │ │ │ │ - * Instances of this class are not useful. See one of the subclasses.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * options - {Object} An optional object with properties to set on the
│ │ │ │ │ - * format
│ │ │ │ │ - *
│ │ │ │ │ - * Valid options:
│ │ │ │ │ - * keepData - {Boolean} If true, upon , the data property will be
│ │ │ │ │ - * set to the parsed object (e.g. the json or xml object).
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * An instance of OpenLayers.Format
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.options = options;
│ │ │ │ │ - },
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.MultiLineString
│ │ │ │ │ + * Constructor for a MultiLineString Geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()}
│ │ │ │ │ + *
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - * Clean up.
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {},
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: split
│ │ │ │ │ + * Use this geometry (the source) to attempt to split a target geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Properties of this object will be used to determine
│ │ │ │ │ + * how the split is conducted.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * mutual - {Boolean} Split the source geometry in addition to the target
│ │ │ │ │ + * geometry. Default is false.
│ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is
│ │ │ │ │ + * true. If false, a vertex on the source must be within the tolerance
│ │ │ │ │ + * distance of the intersection to be considered a split.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, intersections
│ │ │ │ │ + * within the tolerance distance of an existing vertex on the source
│ │ │ │ │ + * will be assumed to occur at the vertex.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} A list of geometries (of this same type as the target) that
│ │ │ │ │ + * result from splitting the target with the source geometry. The
│ │ │ │ │ + * source and target geometry will remain unmodified. If no split
│ │ │ │ │ + * results, null will be returned. If mutual is true and a split
│ │ │ │ │ + * results, return will be an array of two arrays - the first will be
│ │ │ │ │ + * all geometries that result from splitting the source geometry and
│ │ │ │ │ + * the second will be all geometries that result from splitting the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ + */
│ │ │ │ │ + split: function(geometry, options) {
│ │ │ │ │ + var results = null;
│ │ │ │ │ + var mutual = options && options.mutual;
│ │ │ │ │ + var splits, sourceLine, sourceLines, sourceSplit, targetSplit;
│ │ │ │ │ + var sourceParts = [];
│ │ │ │ │ + var targetParts = [geometry];
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + sourceLine = this.components[i];
│ │ │ │ │ + sourceSplit = false;
│ │ │ │ │ + for (var j = 0; j < targetParts.length; ++j) {
│ │ │ │ │ + splits = sourceLine.split(targetParts[j], options);
│ │ │ │ │ + if (splits) {
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + sourceLines = splits[0];
│ │ │ │ │ + for (var k = 0, klen = sourceLines.length; k < klen; ++k) {
│ │ │ │ │ + if (k === 0 && sourceParts.length) {
│ │ │ │ │ + sourceParts[sourceParts.length - 1].addComponent(
│ │ │ │ │ + sourceLines[k]
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + sourceParts.push(
│ │ │ │ │ + new OpenLayers.Geometry.MultiLineString([
│ │ │ │ │ + sourceLines[k]
│ │ │ │ │ + ])
│ │ │ │ │ + );
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + sourceSplit = true;
│ │ │ │ │ + splits = splits[1];
│ │ │ │ │ + }
│ │ │ │ │ + if (splits.length) {
│ │ │ │ │ + // splice in new target parts
│ │ │ │ │ + splits.unshift(j, 1);
│ │ │ │ │ + Array.prototype.splice.apply(targetParts, splits);
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!sourceSplit) {
│ │ │ │ │ + // source line was not hit
│ │ │ │ │ + if (sourceParts.length) {
│ │ │ │ │ + // add line to existing multi
│ │ │ │ │ + sourceParts[sourceParts.length - 1].addComponent(
│ │ │ │ │ + sourceLine.clone()
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + // create a fresh multi
│ │ │ │ │ + sourceParts = [
│ │ │ │ │ + new OpenLayers.Geometry.MultiLineString(
│ │ │ │ │ + sourceLine.clone()
│ │ │ │ │ + )
│ │ │ │ │ + ];
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (sourceParts && sourceParts.length > 1) {
│ │ │ │ │ + sourceSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + sourceParts = [];
│ │ │ │ │ + }
│ │ │ │ │ + if (targetParts && targetParts.length > 1) {
│ │ │ │ │ + targetSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + targetParts = [];
│ │ │ │ │ + }
│ │ │ │ │ + if (sourceSplit || targetSplit) {
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + results = [sourceParts, targetParts];
│ │ │ │ │ + } else {
│ │ │ │ │ + results = targetParts;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return results;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: read
│ │ │ │ │ - * Read data from a string, and return an object whose type depends on the
│ │ │ │ │ - * subclass.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * data - {string} Data to read/parse.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * Depends on the subclass
│ │ │ │ │ - */
│ │ │ │ │ - read: function(data) {
│ │ │ │ │ - throw new Error('Read not implemented.');
│ │ │ │ │ - },
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: splitWith
│ │ │ │ │ + * Split this geometry (the target) with the given geometry (the source).
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} A geometry used to split this
│ │ │ │ │ + * geometry (the source).
│ │ │ │ │ + * options - {Object} Properties of this object will be used to determine
│ │ │ │ │ + * how the split is conducted.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * mutual - {Boolean} Split the source geometry in addition to the target
│ │ │ │ │ + * geometry. Default is false.
│ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is
│ │ │ │ │ + * true. If false, a vertex on the source must be within the tolerance
│ │ │ │ │ + * distance of the intersection to be considered a split.
│ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, intersections
│ │ │ │ │ + * within the tolerance distance of an existing vertex on the source
│ │ │ │ │ + * will be assumed to occur at the vertex.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} A list of geometries (of this same type as the target) that
│ │ │ │ │ + * result from splitting the target with the source geometry. The
│ │ │ │ │ + * source and target geometry will remain unmodified. If no split
│ │ │ │ │ + * results, null will be returned. If mutual is true and a split
│ │ │ │ │ + * results, return will be an array of two arrays - the first will be
│ │ │ │ │ + * all geometries that result from splitting the source geometry and
│ │ │ │ │ + * the second will be all geometries that result from splitting the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ + */
│ │ │ │ │ + splitWith: function(geometry, options) {
│ │ │ │ │ + var results = null;
│ │ │ │ │ + var mutual = options && options.mutual;
│ │ │ │ │ + var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;
│ │ │ │ │ + if (geometry instanceof OpenLayers.Geometry.LineString) {
│ │ │ │ │ + targetParts = [];
│ │ │ │ │ + sourceParts = [geometry];
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + targetSplit = false;
│ │ │ │ │ + targetLine = this.components[i];
│ │ │ │ │ + for (var j = 0; j < sourceParts.length; ++j) {
│ │ │ │ │ + splits = sourceParts[j].split(targetLine, options);
│ │ │ │ │ + if (splits) {
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + sourceLines = splits[0];
│ │ │ │ │ + if (sourceLines.length) {
│ │ │ │ │ + // splice in new source parts
│ │ │ │ │ + sourceLines.unshift(j, 1);
│ │ │ │ │ + Array.prototype.splice.apply(sourceParts, sourceLines);
│ │ │ │ │ + j += sourceLines.length - 2;
│ │ │ │ │ + }
│ │ │ │ │ + splits = splits[1];
│ │ │ │ │ + if (splits.length === 0) {
│ │ │ │ │ + splits = [targetLine.clone()];
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + for (var k = 0, klen = splits.length; k < klen; ++k) {
│ │ │ │ │ + if (k === 0 && targetParts.length) {
│ │ │ │ │ + targetParts[targetParts.length - 1].addComponent(
│ │ │ │ │ + splits[k]
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + targetParts.push(
│ │ │ │ │ + new OpenLayers.Geometry.MultiLineString([
│ │ │ │ │ + splits[k]
│ │ │ │ │ + ])
│ │ │ │ │ + );
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + targetSplit = true;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!targetSplit) {
│ │ │ │ │ + // target component was not hit
│ │ │ │ │ + if (targetParts.length) {
│ │ │ │ │ + // add it to any existing multi-line
│ │ │ │ │ + targetParts[targetParts.length - 1].addComponent(
│ │ │ │ │ + targetLine.clone()
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + // or start with a fresh multi-line
│ │ │ │ │ + targetParts = [
│ │ │ │ │ + new OpenLayers.Geometry.MultiLineString([
│ │ │ │ │ + targetLine.clone()
│ │ │ │ │ + ])
│ │ │ │ │ + ];
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: write
│ │ │ │ │ - * Accept an object, and return a string.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * object - {Object} Object to be serialized
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} A string representation of the object.
│ │ │ │ │ - */
│ │ │ │ │ - write: function(object) {
│ │ │ │ │ - throw new Error('Write not implemented.');
│ │ │ │ │ - },
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + results = geometry.split(this);
│ │ │ │ │ + }
│ │ │ │ │ + if (sourceParts && sourceParts.length > 1) {
│ │ │ │ │ + sourceSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + sourceParts = [];
│ │ │ │ │ + }
│ │ │ │ │ + if (targetParts && targetParts.length > 1) {
│ │ │ │ │ + targetSplit = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + targetParts = [];
│ │ │ │ │ + }
│ │ │ │ │ + if (sourceSplit || targetSplit) {
│ │ │ │ │ + if (mutual) {
│ │ │ │ │ + results = [sourceParts, targetParts];
│ │ │ │ │ + } else {
│ │ │ │ │ + results = targetParts;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return results;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Format"
│ │ │ │ │ -});
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.MultiLineString"
│ │ │ │ │ + });
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Util/vendorPrefix.js
│ │ │ │ │ + OpenLayers/Geometry/LinearRing.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/SingleFile.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/LineString.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ -OpenLayers.Util = OpenLayers.Util || {};
│ │ │ │ │ /**
│ │ │ │ │ - * Namespace: OpenLayers.Util.vendorPrefix
│ │ │ │ │ - * A collection of utility functions to detect vendor prefixed features
│ │ │ │ │ + * Class: OpenLayers.Geometry.LinearRing
│ │ │ │ │ + *
│ │ │ │ │ + * A Linear Ring is a special LineString which is closed. It closes itself
│ │ │ │ │ + * automatically on every addPoint/removePoint by adding a copy of the first
│ │ │ │ │ + * point as the last point.
│ │ │ │ │ + *
│ │ │ │ │ + * Also, as it is the first in the line family to close itself, a getArea()
│ │ │ │ │ + * function is defined to calculate the enclosed area of the linearRing
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits:
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Util.vendorPrefix = (function() {
│ │ │ │ │ - "use strict";
│ │ │ │ │ +OpenLayers.Geometry.LinearRing = OpenLayers.Class(
│ │ │ │ │ + OpenLayers.Geometry.LineString, {
│ │ │ │ │
│ │ │ │ │ - var VENDOR_PREFIXES = ["", "O", "ms", "Moz", "Webkit"],
│ │ │ │ │ - divStyle = document.createElement("div").style,
│ │ │ │ │ - cssCache = {},
│ │ │ │ │ - jsCache = {};
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null
│ │ │ │ │ + * value means the component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Point"],
│ │ │ │ │
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.LinearRing
│ │ │ │ │ + * Linear rings are constructed with an array of points. This array
│ │ │ │ │ + * can represent a closed or open ring. If the ring is open (the last
│ │ │ │ │ + * point does not equal the first point), the constructor will close
│ │ │ │ │ + * the ring. If the ring is already closed (the last point does equal
│ │ │ │ │ + * the first point), it will be left closed.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * points - {Array()} points
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Function: domToCss
│ │ │ │ │ - * Converts a upper camel case DOM style property name to a CSS property
│ │ │ │ │ - * i.e. transformOrigin -> transform-origin
│ │ │ │ │ - * or WebkitTransformOrigin -> -webkit-transform-origin
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * prefixedDom - {String} The property to convert
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The CSS property
│ │ │ │ │ - */
│ │ │ │ │ - function domToCss(prefixedDom) {
│ │ │ │ │ - if (!prefixedDom) {
│ │ │ │ │ - return null;
│ │ │ │ │ - }
│ │ │ │ │ - return prefixedDom.
│ │ │ │ │ - replace(/([A-Z])/g, function(c) {
│ │ │ │ │ - return "-" + c.toLowerCase();
│ │ │ │ │ - }).
│ │ │ │ │ - replace(/^ms-/, "-ms-");
│ │ │ │ │ - }
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: addComponent
│ │ │ │ │ + * Adds a point to geometry components. If the point is to be added to
│ │ │ │ │ + * the end of the components array and it is the same as the last point
│ │ │ │ │ + * already in that array, the duplicate point is not added. This has
│ │ │ │ │ + * the effect of closing the ring if it is not already closed, and
│ │ │ │ │ + * doing the right thing if it is already closed. This behavior can
│ │ │ │ │ + * be overridden by calling the method with a non-null index as the
│ │ │ │ │ + * second argument.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {}
│ │ │ │ │ + * index - {Integer} Index into the array to insert the component
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Was the Point successfully added?
│ │ │ │ │ + */
│ │ │ │ │ + addComponent: function(point, index) {
│ │ │ │ │ + var added = false;
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: css
│ │ │ │ │ - * Detect which property is used for a CSS property
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * property - {String} The standard (unprefixed) CSS property name
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The standard CSS property, prefixed property or null if not
│ │ │ │ │ - * supported
│ │ │ │ │ - */
│ │ │ │ │ - function css(property) {
│ │ │ │ │ - if (cssCache[property] === undefined) {
│ │ │ │ │ - var domProperty = property.
│ │ │ │ │ - replace(/(-[\s\S])/g, function(c) {
│ │ │ │ │ - return c.charAt(1).toUpperCase();
│ │ │ │ │ - });
│ │ │ │ │ - var prefixedDom = style(domProperty);
│ │ │ │ │ - cssCache[property] = domToCss(prefixedDom);
│ │ │ │ │ - }
│ │ │ │ │ - return cssCache[property];
│ │ │ │ │ - }
│ │ │ │ │ + //remove last point
│ │ │ │ │ + var lastPoint = this.components.pop();
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: js
│ │ │ │ │ - * Detect which property is used for a JS property/method
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * obj - {Object} The object to test on
│ │ │ │ │ - * property - {String} The standard (unprefixed) JS property name
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The standard JS property, prefixed property or null if not
│ │ │ │ │ - * supported
│ │ │ │ │ - */
│ │ │ │ │ - function js(obj, property) {
│ │ │ │ │ - if (jsCache[property] === undefined) {
│ │ │ │ │ - var tmpProp,
│ │ │ │ │ - i = 0,
│ │ │ │ │ - l = VENDOR_PREFIXES.length,
│ │ │ │ │ - prefix,
│ │ │ │ │ - isStyleObj = (typeof obj.cssText !== "undefined");
│ │ │ │ │ + // given an index, add the point
│ │ │ │ │ + // without an index only add non-duplicate points
│ │ │ │ │ + if (index != null || !point.equals(lastPoint)) {
│ │ │ │ │ + added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,
│ │ │ │ │ + arguments);
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - jsCache[property] = null;
│ │ │ │ │ - for (; i < l; i++) {
│ │ │ │ │ - prefix = VENDOR_PREFIXES[i];
│ │ │ │ │ - if (prefix) {
│ │ │ │ │ - if (!isStyleObj) {
│ │ │ │ │ - // js prefix should be lower-case, while style
│ │ │ │ │ - // properties have upper case on first character
│ │ │ │ │ - prefix = prefix.toLowerCase();
│ │ │ │ │ + //append copy of first point
│ │ │ │ │ + var firstPoint = this.components[0];
│ │ │ │ │ + OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,
│ │ │ │ │ + [firstPoint]);
│ │ │ │ │ +
│ │ │ │ │ + return added;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: removeComponent
│ │ │ │ │ + * Removes a point from geometry components.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The component was removed.
│ │ │ │ │ + */
│ │ │ │ │ + removeComponent: function(point) {
│ │ │ │ │ + var removed = this.components && (this.components.length > 3);
│ │ │ │ │ + if (removed) {
│ │ │ │ │ + //remove last point
│ │ │ │ │ + this.components.pop();
│ │ │ │ │ +
│ │ │ │ │ + //remove our point
│ │ │ │ │ + OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,
│ │ │ │ │ + arguments);
│ │ │ │ │ + //append copy of first point
│ │ │ │ │ + var firstPoint = this.components[0];
│ │ │ │ │ + OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,
│ │ │ │ │ + [firstPoint]);
│ │ │ │ │ + }
│ │ │ │ │ + return removed;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: move
│ │ │ │ │ + * Moves a geometry by the given displacement along positive x and y axes.
│ │ │ │ │ + * This modifies the position of the geometry and clears the cached
│ │ │ │ │ + * bounds.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * x - {Float} Distance to move geometry in positive x direction.
│ │ │ │ │ + * y - {Float} Distance to move geometry in positive y direction.
│ │ │ │ │ + */
│ │ │ │ │ + move: function(x, y) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len - 1; i++) {
│ │ │ │ │ + this.components[i].move(x, y);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: rotate
│ │ │ │ │ + * Rotate a geometry around some origin
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * angle - {Float} Rotation angle in degrees (measured counterclockwise
│ │ │ │ │ + * from the positive x-axis)
│ │ │ │ │ + * origin - {} Center point for the rotation
│ │ │ │ │ + */
│ │ │ │ │ + rotate: function(angle, origin) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len - 1; ++i) {
│ │ │ │ │ + this.components[i].rotate(angle, origin);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: resize
│ │ │ │ │ + * Resize a geometry relative to some origin. Use this method to apply
│ │ │ │ │ + * a uniform scaling to a geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * scale - {Float} Factor by which to scale the geometry. A scale of 2
│ │ │ │ │ + * doubles the size of the geometry in each dimension
│ │ │ │ │ + * (lines, for example, will be twice as long, and polygons
│ │ │ │ │ + * will have four times the area).
│ │ │ │ │ + * origin - {} Point of origin for resizing
│ │ │ │ │ + * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} - The current geometry.
│ │ │ │ │ + */
│ │ │ │ │ + resize: function(scale, origin, ratio) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len - 1; ++i) {
│ │ │ │ │ + this.components[i].resize(scale, origin, ratio);
│ │ │ │ │ + }
│ │ │ │ │ + return this;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: transform
│ │ │ │ │ + * Reproject the components geometry from source to dest.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * source - {}
│ │ │ │ │ + * dest - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │ + transform: function(source, dest) {
│ │ │ │ │ + if (source && dest) {
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len - 1; i++) {
│ │ │ │ │ + var component = this.components[i];
│ │ │ │ │ + component.transform(source, dest);
│ │ │ │ │ + }
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ + }
│ │ │ │ │ + return this;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getCentroid
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} The centroid of the collection
│ │ │ │ │ + */
│ │ │ │ │ + getCentroid: function() {
│ │ │ │ │ + if (this.components) {
│ │ │ │ │ + var len = this.components.length;
│ │ │ │ │ + if (len > 0 && len <= 2) {
│ │ │ │ │ + return this.components[0].clone();
│ │ │ │ │ + } else if (len > 2) {
│ │ │ │ │ + var sumX = 0.0;
│ │ │ │ │ + var sumY = 0.0;
│ │ │ │ │ + var x0 = this.components[0].x;
│ │ │ │ │ + var y0 = this.components[0].y;
│ │ │ │ │ + var area = -1 * this.getArea();
│ │ │ │ │ + if (area != 0) {
│ │ │ │ │ + for (var i = 0; i < len - 1; i++) {
│ │ │ │ │ + var b = this.components[i];
│ │ │ │ │ + var c = this.components[i + 1];
│ │ │ │ │ + sumX += (b.x + c.x - 2 * x0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));
│ │ │ │ │ + sumY += (b.y + c.y - 2 * y0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));
│ │ │ │ │ + }
│ │ │ │ │ + var x = x0 + sumX / (6 * area);
│ │ │ │ │ + var y = y0 + sumY / (6 * area);
│ │ │ │ │ + } else {
│ │ │ │ │ + for (var i = 0; i < len - 1; i++) {
│ │ │ │ │ + sumX += this.components[i].x;
│ │ │ │ │ + sumY += this.components[i].y;
│ │ │ │ │ + }
│ │ │ │ │ + var x = sumX / (len - 1);
│ │ │ │ │ + var y = sumY / (len - 1);
│ │ │ │ │ }
│ │ │ │ │ - tmpProp = prefix + property.charAt(0).toUpperCase() + property.slice(1);
│ │ │ │ │ + return new OpenLayers.Geometry.Point(x, y);
│ │ │ │ │ } else {
│ │ │ │ │ - tmpProp = property;
│ │ │ │ │ + return null;
│ │ │ │ │ }
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - if (obj[tmpProp] !== undefined) {
│ │ │ │ │ - jsCache[property] = tmpProp;
│ │ │ │ │ - break;
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getArea
│ │ │ │ │ + * Note - The area is positive if the ring is oriented CW, otherwise
│ │ │ │ │ + * it will be negative.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The signed area for a ring.
│ │ │ │ │ + */
│ │ │ │ │ + getArea: function() {
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + if (this.components && (this.components.length > 2)) {
│ │ │ │ │ + var sum = 0.0;
│ │ │ │ │ + for (var i = 0, len = this.components.length; i < len - 1; i++) {
│ │ │ │ │ + var b = this.components[i];
│ │ │ │ │ + var c = this.components[i + 1];
│ │ │ │ │ + sum += (b.x + c.x) * (c.y - b.y);
│ │ │ │ │ }
│ │ │ │ │ + area = -sum / 2.0;
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ - return jsCache[property];
│ │ │ │ │ - }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: style
│ │ │ │ │ - * Detect which property is used for a DOM style property
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * property - {String} The standard (unprefixed) style property name
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The standard style property, prefixed property or null if not
│ │ │ │ │ - * supported
│ │ │ │ │ - */
│ │ │ │ │ - function style(property) {
│ │ │ │ │ - return js(divStyle, property);
│ │ │ │ │ - }
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getGeodesicArea
│ │ │ │ │ + * Calculate the approximate area of the polygon were it projected onto
│ │ │ │ │ + * the earth. Note that this area will be positive if ring is oriented
│ │ │ │ │ + * clockwise, otherwise it will be negative.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * projection - {} The spatial reference system
│ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is
│ │ │ │ │ + * assumed.
│ │ │ │ │ + *
│ │ │ │ │ + * Reference:
│ │ │ │ │ + * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
│ │ │ │ │ + * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
│ │ │ │ │ + * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {float} The approximate signed geodesic area of the polygon in square
│ │ │ │ │ + * meters.
│ │ │ │ │ + */
│ │ │ │ │ + getGeodesicArea: function(projection) {
│ │ │ │ │ + var ring = this; // so we can work with a clone if needed
│ │ │ │ │ + if (projection) {
│ │ │ │ │ + var gg = new OpenLayers.Projection("EPSG:4326");
│ │ │ │ │ + if (!gg.equals(projection)) {
│ │ │ │ │ + ring = this.clone().transform(projection, gg);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + var len = ring.components && ring.components.length;
│ │ │ │ │ + if (len > 2) {
│ │ │ │ │ + var p1, p2;
│ │ │ │ │ + for (var i = 0; i < len - 1; i++) {
│ │ │ │ │ + p1 = ring.components[i];
│ │ │ │ │ + p2 = ring.components[i + 1];
│ │ │ │ │ + area += OpenLayers.Util.rad(p2.x - p1.x) *
│ │ │ │ │ + (2 + Math.sin(OpenLayers.Util.rad(p1.y)) +
│ │ │ │ │ + Math.sin(OpenLayers.Util.rad(p2.y)));
│ │ │ │ │ + }
│ │ │ │ │ + area = area * 6378137.0 * 6378137.0 / 2.0;
│ │ │ │ │ + }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - return {
│ │ │ │ │ - css: css,
│ │ │ │ │ - js: js,
│ │ │ │ │ - style: style,
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: containsPoint
│ │ │ │ │ + * Test if a point is inside a linear ring. For the case where a point
│ │ │ │ │ + * is coincident with a linear ring edge, returns 1. Otherwise,
│ │ │ │ │ + * returns boolean.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean | Number} The point is inside the linear ring. Returns 1 if
│ │ │ │ │ + * the point is coincident with an edge. Returns boolean otherwise.
│ │ │ │ │ + */
│ │ │ │ │ + containsPoint: function(point) {
│ │ │ │ │ + var approx = OpenLayers.Number.limitSigDigs;
│ │ │ │ │ + var digs = 14;
│ │ │ │ │ + var px = approx(point.x, digs);
│ │ │ │ │ + var py = approx(point.y, digs);
│ │ │ │ │
│ │ │ │ │ - // used for testing
│ │ │ │ │ - cssCache: cssCache,
│ │ │ │ │ - jsCache: jsCache
│ │ │ │ │ - };
│ │ │ │ │ -}());
│ │ │ │ │ + function getX(y, x1, y1, x2, y2) {
│ │ │ │ │ + return (y - y2) * ((x2 - x1) / (y2 - y1)) + x2;
│ │ │ │ │ + }
│ │ │ │ │ + var numSeg = this.components.length - 1;
│ │ │ │ │ + var start, end, x1, y1, x2, y2, cx, cy;
│ │ │ │ │ + var crosses = 0;
│ │ │ │ │ + for (var i = 0; i < numSeg; ++i) {
│ │ │ │ │ + start = this.components[i];
│ │ │ │ │ + x1 = approx(start.x, digs);
│ │ │ │ │ + y1 = approx(start.y, digs);
│ │ │ │ │ + end = this.components[i + 1];
│ │ │ │ │ + x2 = approx(end.x, digs);
│ │ │ │ │ + y2 = approx(end.y, digs);
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * The following conditions enforce five edge-crossing rules:
│ │ │ │ │ + * 1. points coincident with edges are considered contained;
│ │ │ │ │ + * 2. an upward edge includes its starting endpoint, and
│ │ │ │ │ + * excludes its final endpoint;
│ │ │ │ │ + * 3. a downward edge excludes its starting endpoint, and
│ │ │ │ │ + * includes its final endpoint;
│ │ │ │ │ + * 4. horizontal edges are excluded; and
│ │ │ │ │ + * 5. the edge-ray intersection point must be strictly right
│ │ │ │ │ + * of the point P.
│ │ │ │ │ + */
│ │ │ │ │ + if (y1 == y2) {
│ │ │ │ │ + // horizontal edge
│ │ │ │ │ + if (py == y1) {
│ │ │ │ │ + // point on horizontal line
│ │ │ │ │ + if (x1 <= x2 && (px >= x1 && px <= x2) || // right or vert
│ │ │ │ │ + x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert
│ │ │ │ │ + // point on edge
│ │ │ │ │ + crosses = -1;
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + // ignore other horizontal edges
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + cx = approx(getX(py, x1, y1, x2, y2), digs);
│ │ │ │ │ + if (cx == px) {
│ │ │ │ │ + // point on line
│ │ │ │ │ + if (y1 < y2 && (py >= y1 && py <= y2) || // upward
│ │ │ │ │ + y1 > y2 && (py <= y1 && py >= y2)) { // downward
│ │ │ │ │ + // point on edge
│ │ │ │ │ + crosses = -1;
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (cx <= px) {
│ │ │ │ │ + // no crossing to the right
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + if (x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {
│ │ │ │ │ + // no crossing
│ │ │ │ │ + continue;
│ │ │ │ │ + }
│ │ │ │ │ + if (y1 < y2 && (py >= y1 && py < y2) || // upward
│ │ │ │ │ + y1 > y2 && (py < y1 && py >= y2)) { // downward
│ │ │ │ │ + ++crosses;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + var contained = (crosses == -1) ?
│ │ │ │ │ + // on edge
│ │ │ │ │ + 1 :
│ │ │ │ │ + // even (out) or odd (in)
│ │ │ │ │ + !!(crosses & 1);
│ │ │ │ │ +
│ │ │ │ │ + return contained;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: intersects
│ │ │ │ │ + * Determine if the input geometry intersects this one.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} Any type of geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The input geometry intersects this one.
│ │ │ │ │ + */
│ │ │ │ │ + intersects: function(geometry) {
│ │ │ │ │ + var intersect = false;
│ │ │ │ │ + if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
│ │ │ │ │ + intersect = this.containsPoint(geometry);
│ │ │ │ │ + } else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
│ │ │ │ │ + intersect = geometry.intersects(this);
│ │ │ │ │ + } else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
│ │ │ │ │ + intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply(
│ │ │ │ │ + this, [geometry]
│ │ │ │ │ + );
│ │ │ │ │ + } else {
│ │ │ │ │ + // check for component intersections
│ │ │ │ │ + for (var i = 0, len = geometry.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = geometry.components[i].intersects(this);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return intersect;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getVertices
│ │ │ │ │ + * Return a list of all points in this geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are
│ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not
│ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will
│ │ │ │ │ + * be returned.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array} A list of all vertices in the geometry.
│ │ │ │ │ + */
│ │ │ │ │ + getVertices: function(nodes) {
│ │ │ │ │ + return (nodes === true) ? [] : this.components.slice(0, this.components.length - 1);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.LinearRing"
│ │ │ │ │ + });
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Animation.js
│ │ │ │ │ + OpenLayers/Geometry/Polygon.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/SingleFile.js
│ │ │ │ │ - * @requires OpenLayers/Util/vendorPrefix.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Collection.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/LinearRing.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Namespace: OpenLayers.Animation
│ │ │ │ │ - * A collection of utility functions for executing methods that repaint a
│ │ │ │ │ - * portion of the browser window. These methods take advantage of the
│ │ │ │ │ - * browser's scheduled repaints where requestAnimationFrame is available.
│ │ │ │ │ + * Class: OpenLayers.Geometry.Polygon
│ │ │ │ │ + * Polygon is a collection of Geometry.LinearRings.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Animation = (function(window) {
│ │ │ │ │ +OpenLayers.Geometry.Polygon = OpenLayers.Class(
│ │ │ │ │ + OpenLayers.Geometry.Collection, {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: isNative
│ │ │ │ │ - * {Boolean} true if a native requestAnimationFrame function is available
│ │ │ │ │ - */
│ │ │ │ │ - var requestAnimationFrame = OpenLayers.Util.vendorPrefix.js(window, "requestAnimationFrame");
│ │ │ │ │ - var isNative = !!(requestAnimationFrame);
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null value means the
│ │ │ │ │ + * component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.LinearRing"],
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Function: requestFrame
│ │ │ │ │ - * Schedule a function to be called at the next available animation frame.
│ │ │ │ │ - * Uses the native method where available. Where requestAnimationFrame is
│ │ │ │ │ - * not available, setTimeout will be called with a 16ms delay.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * callback - {Function} The function to be called at the next animation frame.
│ │ │ │ │ - * element - {DOMElement} Optional element that visually bounds the animation.
│ │ │ │ │ - */
│ │ │ │ │ - var requestFrame = (function() {
│ │ │ │ │ - var request = window[requestAnimationFrame] ||
│ │ │ │ │ - function(callback, element) {
│ │ │ │ │ - window.setTimeout(callback, 16);
│ │ │ │ │ - };
│ │ │ │ │ - // bind to window to avoid illegal invocation of native function
│ │ │ │ │ - return function(callback, element) {
│ │ │ │ │ - request.apply(window, [callback, element]);
│ │ │ │ │ - };
│ │ │ │ │ - })();
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.Polygon
│ │ │ │ │ + * Constructor for a Polygon geometry.
│ │ │ │ │ + * The first ring (this.component[0])is the outer bounds of the polygon and
│ │ │ │ │ + * all subsequent rings (this.component[1-n]) are internal holes.
│ │ │ │ │ + *
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()}
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - // private variables for animation loops
│ │ │ │ │ - var counter = 0;
│ │ │ │ │ - var loops = {};
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getArea
│ │ │ │ │ + * Calculated by subtracting the areas of the internal holes from the
│ │ │ │ │ + * area of the outer hole.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {float} The area of the geometry
│ │ │ │ │ + */
│ │ │ │ │ + getArea: function() {
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + if (this.components && (this.components.length > 0)) {
│ │ │ │ │ + area += Math.abs(this.components[0].getArea());
│ │ │ │ │ + for (var i = 1, len = this.components.length; i < len; i++) {
│ │ │ │ │ + area -= Math.abs(this.components[i].getArea());
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Function: start
│ │ │ │ │ - * Executes a method with in series for some
│ │ │ │ │ - * duration.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * callback - {Function} The function to be called at the next animation frame.
│ │ │ │ │ - * duration - {Number} Optional duration for the loop. If not provided, the
│ │ │ │ │ - * animation loop will execute indefinitely.
│ │ │ │ │ - * element - {DOMElement} Optional element that visually bounds the animation.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Number} Identifier for the animation loop. Used to stop animations with
│ │ │ │ │ - * .
│ │ │ │ │ - */
│ │ │ │ │ - function start(callback, duration, element) {
│ │ │ │ │ - duration = duration > 0 ? duration : Number.POSITIVE_INFINITY;
│ │ │ │ │ - var id = ++counter;
│ │ │ │ │ - var start = +new Date;
│ │ │ │ │ - loops[id] = function() {
│ │ │ │ │ - if (loops[id] && +new Date - start <= duration) {
│ │ │ │ │ - callback();
│ │ │ │ │ - if (loops[id]) {
│ │ │ │ │ - requestFrame(loops[id], element);
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getGeodesicArea
│ │ │ │ │ + * Calculate the approximate area of the polygon were it projected onto
│ │ │ │ │ + * the earth.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * projection - {} The spatial reference system
│ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is
│ │ │ │ │ + * assumed.
│ │ │ │ │ + *
│ │ │ │ │ + * Reference:
│ │ │ │ │ + * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
│ │ │ │ │ + * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
│ │ │ │ │ + * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {float} The approximate geodesic area of the polygon in square meters.
│ │ │ │ │ + */
│ │ │ │ │ + getGeodesicArea: function(projection) {
│ │ │ │ │ + var area = 0.0;
│ │ │ │ │ + if (this.components && (this.components.length > 0)) {
│ │ │ │ │ + area += Math.abs(this.components[0].getGeodesicArea(projection));
│ │ │ │ │ + for (var i = 1, len = this.components.length; i < len; i++) {
│ │ │ │ │ + area -= Math.abs(this.components[i].getGeodesicArea(projection));
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return area;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: containsPoint
│ │ │ │ │ + * Test if a point is inside a polygon. Points on a polygon edge are
│ │ │ │ │ + * considered inside.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean | Number} The point is inside the polygon. Returns 1 if the
│ │ │ │ │ + * point is on an edge. Returns boolean otherwise.
│ │ │ │ │ + */
│ │ │ │ │ + containsPoint: function(point) {
│ │ │ │ │ + var numRings = this.components.length;
│ │ │ │ │ + var contained = false;
│ │ │ │ │ + if (numRings > 0) {
│ │ │ │ │ + // check exterior ring - 1 means on edge, boolean otherwise
│ │ │ │ │ + contained = this.components[0].containsPoint(point);
│ │ │ │ │ + if (contained !== 1) {
│ │ │ │ │ + if (contained && numRings > 1) {
│ │ │ │ │ + // check interior rings
│ │ │ │ │ + var hole;
│ │ │ │ │ + for (var i = 1; i < numRings; ++i) {
│ │ │ │ │ + hole = this.components[i].containsPoint(point);
│ │ │ │ │ + if (hole) {
│ │ │ │ │ + if (hole === 1) {
│ │ │ │ │ + // on edge
│ │ │ │ │ + contained = 1;
│ │ │ │ │ + } else {
│ │ │ │ │ + // in hole
│ │ │ │ │ + contained = false;
│ │ │ │ │ + }
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return contained;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: intersects
│ │ │ │ │ + * Determine if the input geometry intersects this one.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} Any type of geometry.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The input geometry intersects this one.
│ │ │ │ │ + */
│ │ │ │ │ + intersects: function(geometry) {
│ │ │ │ │ + var intersect = false;
│ │ │ │ │ + var i, len;
│ │ │ │ │ + if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
│ │ │ │ │ + intersect = this.containsPoint(geometry);
│ │ │ │ │ + } else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
│ │ │ │ │ + geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
│ │ │ │ │ + // check if rings/linestrings intersect
│ │ │ │ │ + for (i = 0, len = this.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = geometry.intersects(this.components[i]);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!intersect) {
│ │ │ │ │ + // check if this poly contains points of the ring/linestring
│ │ │ │ │ + for (i = 0, len = geometry.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = this.containsPoint(geometry.components[i]);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ } else {
│ │ │ │ │ - delete loops[id];
│ │ │ │ │ + for (i = 0, len = geometry.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = this.intersects(geometry.components[i]);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ }
│ │ │ │ │ - };
│ │ │ │ │ - requestFrame(loops[id], element);
│ │ │ │ │ - return id;
│ │ │ │ │ - }
│ │ │ │ │ + // check case where this poly is wholly contained by another
│ │ │ │ │ + if (!intersect && geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
│ │ │ │ │ + // exterior ring points will be contained in the other geometry
│ │ │ │ │ + var ring = this.components[0];
│ │ │ │ │ + for (i = 0, len = ring.components.length; i < len; ++i) {
│ │ │ │ │ + intersect = geometry.containsPoint(ring.components[i]);
│ │ │ │ │ + if (intersect) {
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return intersect;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Function: stop
│ │ │ │ │ - * Terminates an animation loop started with .
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * id - {Number} Identifier returned from .
│ │ │ │ │ - */
│ │ │ │ │ - function stop(id) {
│ │ │ │ │ - delete loops[id];
│ │ │ │ │ - }
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: distanceTo
│ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane).
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} The target geometry.
│ │ │ │ │ + * options - {Object} Optional properties for configuring the distance
│ │ │ │ │ + * calculation.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * details - {Boolean} Return details from the distance calculation.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the
│ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true,
│ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within
│ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever
│ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false,
│ │ │ │ │ + * details cannot be returned.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Number | Object} The distance between this geometry and the target.
│ │ │ │ │ + * If details is true, the return will be an object with distance,
│ │ │ │ │ + * x0, y0, x1, and y1 properties. The x0 and y0 properties represent
│ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1
│ │ │ │ │ + * properties represent the coordinates of the closest point on the
│ │ │ │ │ + * target geometry.
│ │ │ │ │ + */
│ │ │ │ │ + distanceTo: function(geometry, options) {
│ │ │ │ │ + var edge = !(options && options.edge === false);
│ │ │ │ │ + var result;
│ │ │ │ │ + // this is the case where we might not be looking for distance to edge
│ │ │ │ │ + if (!edge && this.intersects(geometry)) {
│ │ │ │ │ + result = 0;
│ │ │ │ │ + } else {
│ │ │ │ │ + result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(
│ │ │ │ │ + this, [geometry, options]
│ │ │ │ │ + );
│ │ │ │ │ + }
│ │ │ │ │ + return result;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - return {
│ │ │ │ │ - isNative: isNative,
│ │ │ │ │ - requestFrame: requestFrame,
│ │ │ │ │ - start: start,
│ │ │ │ │ - stop: stop
│ │ │ │ │ - };
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Polygon"
│ │ │ │ │ + });
│ │ │ │ │
│ │ │ │ │ -})(window);
│ │ │ │ │ +/**
│ │ │ │ │ + * APIMethod: createRegularPolygon
│ │ │ │ │ + * Create a regular polygon around a radius. Useful for creating circles
│ │ │ │ │ + * and the like.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * origin - {} center of polygon.
│ │ │ │ │ + * radius - {Float} distance to vertex, in map units.
│ │ │ │ │ + * sides - {Integer} Number of sides. 20 approximates a circle.
│ │ │ │ │ + * rotation - {Float} original angle of rotation, in degrees.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {
│ │ │ │ │ + var angle = Math.PI * ((1 / sides) - (1 / 2));
│ │ │ │ │ + if (rotation) {
│ │ │ │ │ + angle += (rotation / 180) * Math.PI;
│ │ │ │ │ + }
│ │ │ │ │ + var rotatedAngle, x, y;
│ │ │ │ │ + var points = [];
│ │ │ │ │ + for (var i = 0; i < sides; ++i) {
│ │ │ │ │ + rotatedAngle = angle + (i * 2 * Math.PI / sides);
│ │ │ │ │ + x = origin.x + (radius * Math.cos(rotatedAngle));
│ │ │ │ │ + y = origin.y + (radius * Math.sin(rotatedAngle));
│ │ │ │ │ + points.push(new OpenLayers.Geometry.Point(x, y));
│ │ │ │ │ + }
│ │ │ │ │ + var ring = new OpenLayers.Geometry.LinearRing(points);
│ │ │ │ │ + return new OpenLayers.Geometry.Polygon([ring]);
│ │ │ │ │ +};
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Protocol.js
│ │ │ │ │ + OpenLayers/Geometry/MultiPolygon.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Collection.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Polygon.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.Protocol
│ │ │ │ │ - * Abstract vector layer protocol class. Not to be instantiated directly. Use
│ │ │ │ │ - * one of the protocol subclasses instead.
│ │ │ │ │ + * Class: OpenLayers.Geometry.MultiPolygon
│ │ │ │ │ + * MultiPolygon is a geometry with multiple
│ │ │ │ │ + * components. Create a new instance with the
│ │ │ │ │ + * constructor.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Protocol = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: format
│ │ │ │ │ - * {} The format used by this protocol.
│ │ │ │ │ - */
│ │ │ │ │ - format: null,
│ │ │ │ │ +OpenLayers.Geometry.MultiPolygon = OpenLayers.Class(
│ │ │ │ │ + OpenLayers.Geometry.Collection, {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: options
│ │ │ │ │ - * {Object} Any options sent to the constructor.
│ │ │ │ │ - */
│ │ │ │ │ - options: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: componentTypes
│ │ │ │ │ + * {Array(String)} An array of class names representing the types of
│ │ │ │ │ + * components that the collection can include. A null value means the
│ │ │ │ │ + * component types are not restricted.
│ │ │ │ │ + */
│ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Polygon"],
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: autoDestroy
│ │ │ │ │ - * {Boolean} The creator of the protocol can set autoDestroy to false
│ │ │ │ │ - * to fully control when the protocol is destroyed. Defaults to
│ │ │ │ │ - * true.
│ │ │ │ │ - */
│ │ │ │ │ - autoDestroy: true,
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Geometry.MultiPolygon
│ │ │ │ │ + * Create a new MultiPolygon geometry
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * components - {Array()} An array of polygons
│ │ │ │ │ + * used to generate the MultiPolygon
│ │ │ │ │ + *
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: defaultFilter
│ │ │ │ │ - * {} Optional default filter to read requests
│ │ │ │ │ - */
│ │ │ │ │ - defaultFilter: null,
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.MultiPolygon"
│ │ │ │ │ + });
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Format/WKT.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Protocol
│ │ │ │ │ - * Abstract class for vector protocols. Create instances of a subclass.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ - * instance.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(options) {
│ │ │ │ │ - options = options || {};
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.options = options;
│ │ │ │ │ - },
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: mergeWithDefaultFilter
│ │ │ │ │ - * Merge filter passed to the read method with the default one
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * filter - {}
│ │ │ │ │ - */
│ │ │ │ │ - mergeWithDefaultFilter: function(filter) {
│ │ │ │ │ - var merged;
│ │ │ │ │ - if (filter && this.defaultFilter) {
│ │ │ │ │ - merged = new OpenLayers.Filter.Logical({
│ │ │ │ │ - type: OpenLayers.Filter.Logical.AND,
│ │ │ │ │ - filters: [this.defaultFilter, filter]
│ │ │ │ │ - });
│ │ │ │ │ - } else {
│ │ │ │ │ - merged = filter || this.defaultFilter || undefined;
│ │ │ │ │ - }
│ │ │ │ │ - return merged;
│ │ │ │ │ - },
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/Format.js
│ │ │ │ │ + * @requires OpenLayers/Feature/Vector.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Point.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/MultiPoint.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/LineString.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/MultiLineString.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/Polygon.js
│ │ │ │ │ + * @requires OpenLayers/Geometry/MultiPolygon.js
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: destroy
│ │ │ │ │ - * Clean up the protocol.
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - this.options = null;
│ │ │ │ │ - this.format = null;
│ │ │ │ │ - },
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Format.WKT
│ │ │ │ │ + * Class for reading and writing Well-Known Text. Create a new instance
│ │ │ │ │ + * with the constructor.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: read
│ │ │ │ │ - * Construct a request for reading new features.
│ │ │ │ │ + * Constructor: OpenLayers.Format.WKT
│ │ │ │ │ + * Create a new parser for WKT
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + * options - {Object} An optional object whose properties will be set on
│ │ │ │ │ + * this instance
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} An
│ │ │ │ │ - * object, the same object will be passed to the callback function passed
│ │ │ │ │ - * if one exists in the options object.
│ │ │ │ │ + * {} A new WKT parser.
│ │ │ │ │ */
│ │ │ │ │ - read: function(options) {
│ │ │ │ │ - options = options || {};
│ │ │ │ │ - options.filter = this.mergeWithDefaultFilter(options.filter);
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + this.regExes = {
│ │ │ │ │ + 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
│ │ │ │ │ + 'spaces': /\s+/,
│ │ │ │ │ + 'parenComma': /\)\s*,\s*\(/,
│ │ │ │ │ + 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here
│ │ │ │ │ + 'trimParens': /^\s*\(?(.*?)\)?\s*$/
│ │ │ │ │ + };
│ │ │ │ │ + OpenLayers.Format.prototype.initialize.apply(this, [options]);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ -
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: create
│ │ │ │ │ - * Construct a request for writing newly created features.
│ │ │ │ │ + * APIMethod: read
│ │ │ │ │ + * Deserialize a WKT string and return a vector feature or an
│ │ │ │ │ + * array of vector features. Supports WKT for POINT, MULTIPOINT,
│ │ │ │ │ + * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
│ │ │ │ │ + * GEOMETRYCOLLECTION.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * features - {Array({})} or
│ │ │ │ │ - * {}
│ │ │ │ │ - * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + * wkt - {String} A WKT string
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} An
│ │ │ │ │ - * object, the same object will be passed to the callback function passed
│ │ │ │ │ - * if one exists in the options object.
│ │ │ │ │ + * {|Array} A feature or array of features for
│ │ │ │ │ + * GEOMETRYCOLLECTION WKT.
│ │ │ │ │ */
│ │ │ │ │ - create: function() {},
│ │ │ │ │ + read: function(wkt) {
│ │ │ │ │ + var features, type, str;
│ │ │ │ │ + wkt = wkt.replace(/[\n\r]/g, " ");
│ │ │ │ │ + var matches = this.regExes.typeStr.exec(wkt);
│ │ │ │ │ + if (matches) {
│ │ │ │ │ + type = matches[1].toLowerCase();
│ │ │ │ │ + str = matches[2];
│ │ │ │ │ + if (this.parse[type]) {
│ │ │ │ │ + features = this.parse[type].apply(this, [str]);
│ │ │ │ │ + }
│ │ │ │ │ + if (this.internalProjection && this.externalProjection) {
│ │ │ │ │ + if (features &&
│ │ │ │ │ + features.CLASS_NAME == "OpenLayers.Feature.Vector") {
│ │ │ │ │ + features.geometry.transform(this.externalProjection,
│ │ │ │ │ + this.internalProjection);
│ │ │ │ │ + } else if (features &&
│ │ │ │ │ + type != "geometrycollection" &&
│ │ │ │ │ + typeof features == "object") {
│ │ │ │ │ + for (var i = 0, len = features.length; i < len; i++) {
│ │ │ │ │ + var component = features[i];
│ │ │ │ │ + component.geometry.transform(this.externalProjection,
│ │ │ │ │ + this.internalProjection);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return features;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: update
│ │ │ │ │ - * Construct a request updating modified features.
│ │ │ │ │ + * APIMethod: write
│ │ │ │ │ + * Serialize a feature or array of features into a WKT string.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * features - {Array({})} or
│ │ │ │ │ - * {}
│ │ │ │ │ - * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + * features - {|Array} A feature or array of
│ │ │ │ │ + * features
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} An
│ │ │ │ │ - * object, the same object will be passed to the callback function passed
│ │ │ │ │ - * if one exists in the options object.
│ │ │ │ │ + * {String} The WKT string representation of the input geometries
│ │ │ │ │ */
│ │ │ │ │ - update: function() {},
│ │ │ │ │ + write: function(features) {
│ │ │ │ │ + var collection, geometry, isCollection;
│ │ │ │ │ + if (features.constructor == Array) {
│ │ │ │ │ + collection = features;
│ │ │ │ │ + isCollection = true;
│ │ │ │ │ + } else {
│ │ │ │ │ + collection = [features];
│ │ │ │ │ + isCollection = false;
│ │ │ │ │ + }
│ │ │ │ │ + var pieces = [];
│ │ │ │ │ + if (isCollection) {
│ │ │ │ │ + pieces.push('GEOMETRYCOLLECTION(');
│ │ │ │ │ + }
│ │ │ │ │ + for (var i = 0, len = collection.length; i < len; ++i) {
│ │ │ │ │ + if (isCollection && i > 0) {
│ │ │ │ │ + pieces.push(',');
│ │ │ │ │ + }
│ │ │ │ │ + geometry = collection[i].geometry;
│ │ │ │ │ + pieces.push(this.extractGeometry(geometry));
│ │ │ │ │ + }
│ │ │ │ │ + if (isCollection) {
│ │ │ │ │ + pieces.push(')');
│ │ │ │ │ + }
│ │ │ │ │ + return pieces.join('');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: delete
│ │ │ │ │ - * Construct a request deleting a removed feature.
│ │ │ │ │ + * Method: extractGeometry
│ │ │ │ │ + * Entry point to construct the WKT for a single Geometry object.
│ │ │ │ │ *
│ │ │ │ │ * Parameters:
│ │ │ │ │ - * feature - {}
│ │ │ │ │ - * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + * geometry - {}
│ │ │ │ │ *
│ │ │ │ │ * Returns:
│ │ │ │ │ - * {} An
│ │ │ │ │ - * object, the same object will be passed to the callback function passed
│ │ │ │ │ - * if one exists in the options object.
│ │ │ │ │ + * {String} A WKT string of representing the geometry
│ │ │ │ │ */
│ │ │ │ │ - "delete": function() {},
│ │ │ │ │ + extractGeometry: function(geometry) {
│ │ │ │ │ + var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
│ │ │ │ │ + if (!this.extract[type]) {
│ │ │ │ │ + return null;
│ │ │ │ │ + }
│ │ │ │ │ + if (this.internalProjection && this.externalProjection) {
│ │ │ │ │ + geometry = geometry.clone();
│ │ │ │ │ + geometry.transform(this.internalProjection, this.externalProjection);
│ │ │ │ │ + }
│ │ │ │ │ + var wktType = type == 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase();
│ │ │ │ │ + var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')';
│ │ │ │ │ + return data;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIMethod: commit
│ │ │ │ │ - * Go over the features and for each take action
│ │ │ │ │ - * based on the feature state. Possible actions are create,
│ │ │ │ │ - * update and delete.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * features - {Array({})}
│ │ │ │ │ - * options - {Object} Object whose possible keys are "create", "update",
│ │ │ │ │ - * "delete", "callback" and "scope", the values referenced by the
│ │ │ │ │ - * first three are objects as passed to the "create", "update", and
│ │ │ │ │ - * "delete" methods, the value referenced by the "callback" key is
│ │ │ │ │ - * a function which is called when the commit operation is complete
│ │ │ │ │ - * using the scope referenced by the "scope" key.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Array({})} An array of
│ │ │ │ │ - * objects.
│ │ │ │ │ + * Object with properties corresponding to the geometry types.
│ │ │ │ │ + * Property values are functions that do the actual data extraction.
│ │ │ │ │ */
│ │ │ │ │ - commit: function() {},
│ │ │ │ │ + extract: {
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a space delimited string of point coordinates.
│ │ │ │ │ + * @param {OpenLayers.Geometry.Point} point
│ │ │ │ │ + * @returns {String} A string of coordinates representing the point
│ │ │ │ │ + */
│ │ │ │ │ + 'point': function(point) {
│ │ │ │ │ + return point.x + ' ' + point.y;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: abort
│ │ │ │ │ - * Abort an ongoing request.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * response - {}
│ │ │ │ │ - */
│ │ │ │ │ - abort: function(response) {},
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a comma delimited string of point coordinates from a multipoint.
│ │ │ │ │ + * @param {OpenLayers.Geometry.MultiPoint} multipoint
│ │ │ │ │ + * @returns {String} A string of point coordinate strings representing
│ │ │ │ │ + * the multipoint
│ │ │ │ │ + */
│ │ │ │ │ + 'multipoint': function(multipoint) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = multipoint.components.length; i < len; ++i) {
│ │ │ │ │ + array.push('(' +
│ │ │ │ │ + this.extract.point.apply(this, [multipoint.components[i]]) +
│ │ │ │ │ + ')');
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: createCallback
│ │ │ │ │ - * Returns a function that applies the given public method with resp and
│ │ │ │ │ - * options arguments.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * method - {Function} The method to be applied by the callback.
│ │ │ │ │ - * response - {} The protocol response object.
│ │ │ │ │ - * options - {Object} Options sent to the protocol method
│ │ │ │ │ - */
│ │ │ │ │ - createCallback: function(method, response, options) {
│ │ │ │ │ - return OpenLayers.Function.bind(function() {
│ │ │ │ │ - method.apply(this, [response, options]);
│ │ │ │ │ - }, this);
│ │ │ │ │ - },
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a comma delimited string of point coordinates from a line.
│ │ │ │ │ + * @param {OpenLayers.Geometry.LineString} linestring
│ │ │ │ │ + * @returns {String} A string of point coordinate strings representing
│ │ │ │ │ + * the linestring
│ │ │ │ │ + */
│ │ │ │ │ + 'linestring': function(linestring) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = linestring.components.length; i < len; ++i) {
│ │ │ │ │ + array.push(this.extract.point.apply(this, [linestring.components[i]]));
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Protocol"
│ │ │ │ │ -});
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a comma delimited string of linestring strings from a multilinestring.
│ │ │ │ │ + * @param {OpenLayers.Geometry.MultiLineString} multilinestring
│ │ │ │ │ + * @returns {String} A string of of linestring strings representing
│ │ │ │ │ + * the multilinestring
│ │ │ │ │ + */
│ │ │ │ │ + 'multilinestring': function(multilinestring) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = multilinestring.components.length; i < len; ++i) {
│ │ │ │ │ + array.push('(' +
│ │ │ │ │ + this.extract.linestring.apply(this, [multilinestring.components[i]]) +
│ │ │ │ │ + ')');
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Class: OpenLayers.Protocol.Response
│ │ │ │ │ - * Protocols return Response objects to their users.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Protocol.Response = OpenLayers.Class({
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: code
│ │ │ │ │ - * {Number} - OpenLayers.Protocol.Response.SUCCESS or
│ │ │ │ │ - * OpenLayers.Protocol.Response.FAILURE
│ │ │ │ │ - */
│ │ │ │ │ - code: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a comma delimited string of linear ring arrays from a polygon.
│ │ │ │ │ + * @param {OpenLayers.Geometry.Polygon} polygon
│ │ │ │ │ + * @returns {String} An array of linear ring arrays representing the polygon
│ │ │ │ │ + */
│ │ │ │ │ + 'polygon': function(polygon) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = polygon.components.length; i < len; ++i) {
│ │ │ │ │ + array.push('(' +
│ │ │ │ │ + this.extract.linestring.apply(this, [polygon.components[i]]) +
│ │ │ │ │ + ')');
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: requestType
│ │ │ │ │ - * {String} The type of request this response corresponds to. Either
│ │ │ │ │ - * "create", "read", "update" or "delete".
│ │ │ │ │ - */
│ │ │ │ │ - requestType: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return an array of polygon arrays from a multipolygon.
│ │ │ │ │ + * @param {OpenLayers.Geometry.MultiPolygon} multipolygon
│ │ │ │ │ + * @returns {String} An array of polygon arrays representing
│ │ │ │ │ + * the multipolygon
│ │ │ │ │ + */
│ │ │ │ │ + 'multipolygon': function(multipolygon) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = multipolygon.components.length; i < len; ++i) {
│ │ │ │ │ + array.push('(' +
│ │ │ │ │ + this.extract.polygon.apply(this, [multipolygon.components[i]]) +
│ │ │ │ │ + ')');
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: last
│ │ │ │ │ - * {Boolean} - true if this is the last response expected in a commit,
│ │ │ │ │ - * false otherwise, defaults to true.
│ │ │ │ │ - */
│ │ │ │ │ - last: true,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an
│ │ │ │ │ + * @param {OpenLayers.Geometry.Collection} collection
│ │ │ │ │ + * @returns {String} internal WKT representation of the collection
│ │ │ │ │ + */
│ │ │ │ │ + 'collection': function(collection) {
│ │ │ │ │ + var array = [];
│ │ │ │ │ + for (var i = 0, len = collection.components.length; i < len; ++i) {
│ │ │ │ │ + array.push(this.extractGeometry.apply(this, [collection.components[i]]));
│ │ │ │ │ + }
│ │ │ │ │ + return array.join(',');
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: features
│ │ │ │ │ - * {Array({})} or {}
│ │ │ │ │ - * The features returned in the response by the server. Depending on the
│ │ │ │ │ - * protocol's read payload, either features or data will be populated.
│ │ │ │ │ - */
│ │ │ │ │ - features: null,
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: data
│ │ │ │ │ - * {Object}
│ │ │ │ │ - * The data returned in the response by the server. Depending on the
│ │ │ │ │ - * protocol's read payload, either features or data will be populated.
│ │ │ │ │ + * Object with properties corresponding to the geometry types.
│ │ │ │ │ + * Property values are functions that do the actual parsing.
│ │ │ │ │ */
│ │ │ │ │ - data: null,
│ │ │ │ │ + parse: {
│ │ │ │ │ + /**
│ │ │ │ │ + * Return point feature given a point WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the point
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A point feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'point': function(str) {
│ │ │ │ │ + var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.Point(coords[0], coords[1])
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: reqFeatures
│ │ │ │ │ - * {Array({})} or {}
│ │ │ │ │ - * The features provided by the user and placed in the request by the
│ │ │ │ │ - * protocol.
│ │ │ │ │ - */
│ │ │ │ │ - reqFeatures: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a multipoint feature given a multipoint WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the multipoint
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A multipoint feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'multipoint': function(str) {
│ │ │ │ │ + var point;
│ │ │ │ │ + var points = OpenLayers.String.trim(str).split(',');
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = points.length; i < len; ++i) {
│ │ │ │ │ + point = points[i].replace(this.regExes.trimParens, '$1');
│ │ │ │ │ + components.push(this.parse.point.apply(this, [point]).geometry);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.MultiPoint(components)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: priv
│ │ │ │ │ - */
│ │ │ │ │ - priv: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a linestring feature given a linestring WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the linestring
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A linestring feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'linestring': function(str) {
│ │ │ │ │ + var points = OpenLayers.String.trim(str).split(',');
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = points.length; i < len; ++i) {
│ │ │ │ │ + components.push(this.parse.point.apply(this, [points[i]]).geometry);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.LineString(components)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: error
│ │ │ │ │ - * {Object} The error object in case a service exception was encountered.
│ │ │ │ │ - */
│ │ │ │ │ - error: null,
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a multilinestring feature given a multilinestring WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the multilinestring
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A multilinestring feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'multilinestring': function(str) {
│ │ │ │ │ + var line;
│ │ │ │ │ + var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = lines.length; i < len; ++i) {
│ │ │ │ │ + line = lines[i].replace(this.regExes.trimParens, '$1');
│ │ │ │ │ + components.push(this.parse.linestring.apply(this, [line]).geometry);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.MultiLineString(components)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Protocol.Response
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ - * instance.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - },
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a polygon feature given a polygon WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the polygon
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A polygon feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'polygon': function(str) {
│ │ │ │ │ + var ring, linestring, linearring;
│ │ │ │ │ + var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = rings.length; i < len; ++i) {
│ │ │ │ │ + ring = rings[i].replace(this.regExes.trimParens, '$1');
│ │ │ │ │ + linestring = this.parse.linestring.apply(this, [ring]).geometry;
│ │ │ │ │ + linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
│ │ │ │ │ + components.push(linearring);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.Polygon(components)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Return a multipolygon feature given a multipolygon WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the multipolygon
│ │ │ │ │ + * @returns {OpenLayers.Feature.Vector} A multipolygon feature
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'multipolygon': function(str) {
│ │ │ │ │ + var polygon;
│ │ │ │ │ + var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = polygons.length; i < len; ++i) {
│ │ │ │ │ + polygon = polygons[i].replace(this.regExes.trimParens, '$1');
│ │ │ │ │ + components.push(this.parse.polygon.apply(this, [polygon]).geometry);
│ │ │ │ │ + }
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + new OpenLayers.Geometry.MultiPolygon(components)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Return an array of features given a geometrycollection WKT fragment.
│ │ │ │ │ + * @param {String} str A WKT fragment representing the geometrycollection
│ │ │ │ │ + * @returns {Array} An array of OpenLayers.Feature.Vector
│ │ │ │ │ + * @private
│ │ │ │ │ + */
│ │ │ │ │ + 'geometrycollection': function(str) {
│ │ │ │ │ + // separate components of the collection with |
│ │ │ │ │ + str = str.replace(/,\s*([A-Za-z])/g, '|$1');
│ │ │ │ │ + var wktArray = OpenLayers.String.trim(str).split('|');
│ │ │ │ │ + var components = [];
│ │ │ │ │ + for (var i = 0, len = wktArray.length; i < len; ++i) {
│ │ │ │ │ + components.push(OpenLayers.Format.WKT.prototype.read.apply(this, [wktArray[i]]));
│ │ │ │ │ + }
│ │ │ │ │ + return components;
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: success
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} - true on success, false otherwise
│ │ │ │ │ - */
│ │ │ │ │ - success: function() {
│ │ │ │ │ - return this.code > 0;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Protocol.Response"
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Format.WKT"
│ │ │ │ │ });
│ │ │ │ │ -
│ │ │ │ │ -OpenLayers.Protocol.Response.SUCCESS = 1;
│ │ │ │ │ -OpenLayers.Protocol.Response.FAILURE = 0;
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Tween.js
│ │ │ │ │ + OpenLayers/Format/JSON.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Animation.js
│ │ │ │ │ + * Note:
│ │ │ │ │ + * This work draws heavily from the public domain JSON serializer/deserializer
│ │ │ │ │ + * at http://www.json.org/json.js. Rewritten so that it doesn't modify
│ │ │ │ │ + * basic data prototypes.
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Namespace: OpenLayers.Tween
│ │ │ │ │ + * @requires OpenLayers/Format.js
│ │ │ │ │ */
│ │ │ │ │ -OpenLayers.Tween = OpenLayers.Class({
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: easing
│ │ │ │ │ - * {(Function)} Easing equation used for the animation
│ │ │ │ │ - * Defaultly set to OpenLayers.Easing.Expo.easeOut
│ │ │ │ │ - */
│ │ │ │ │ - easing: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: begin
│ │ │ │ │ - * {Object} Values to start the animation with
│ │ │ │ │ - */
│ │ │ │ │ - begin: null,
│ │ │ │ │ -
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: finish
│ │ │ │ │ - * {Object} Values to finish the animation with
│ │ │ │ │ - */
│ │ │ │ │ - finish: null,
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Format.JSON
│ │ │ │ │ + * A parser to read/write JSON safely. Create a new instance with the
│ │ │ │ │ + *