Files
openlayers/lib/OpenLayers/Geometry/Collection.js

294 lines
8.9 KiB
JavaScript

/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Geometry.js
*
* Class: OpenLayers.Geometry.Collection
* A Collection is exactly what it sounds like: A collection of different
* Geometries. These are stored in the local parameter <components> (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 <getArea> and <getLength> functions here merely iterate through
* the components, summing their respective areas and lengths.
*
* Create a new instance with the <OpenLayers.Geometry.Collection> constructor.
*
* Inerhits from:
* - <OpenLayers.Geometry>
*/
OpenLayers.Geometry.Collection = OpenLayers.Class.create();
OpenLayers.Geometry.Collection.prototype =
OpenLayers.Class.inherit( OpenLayers.Geometry, {
/**
* APIProperty: components
* {Array(<OpenLayers.Geometry>)} The component parts of this geometry
*/
components: 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: null,
/**
* Constructor: OpenLayers.Geometry.Collection
* Creates a Geometry Collection -- a list of geoms.
*
* Parameters:
* components - {Array(<OpenLayers.Geometry>)} Optional array of geometries
*
*/
initialize: function (components) {
OpenLayers.Geometry.prototype.initialize.apply(this, arguments);
this.components = new Array();
if (components != null) {
this.addComponents(components);
}
},
/**
* APIMethod: destroy
* Destroy this geometry.
*/
destroy: function () {
this.components.length = 0;
this.components = null;
},
/**
* APIMethod: clone
* Clone this geometry.
*
* Return:
* {<OpenLayers.Geometry.Collection>} An exact clone of this collection
*/
clone: function() {
var geometry = eval("new " + this.CLASS_NAME + "()");
for(var i=0; i<this.components.length; i++) {
geometry.addComponent(this.components[i].clone());
}
// catch any randomly tagged-on properties
OpenLayers.Util.applyDefaults(geometry, this);
return geometry;
},
/**
* Method: getComponentsString
* Get a string representing the components for this collection
*
* Return:
* {String} A string representation of the components of this geometry
*/
getComponentsString: function(){
var strings = [];
for(var i = 0; i < this.components.length; i++) {
strings.push(this.components[i].toShortString());
}
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;
if ( !this.components || (this.components.length > 0)) {
this.setBounds(this.components[0].getBounds());
for (var i = 1; i < this.components.length; i++) {
this.extendBounds(this.components[i].getBounds());
}
}
},
/**
* APIMethod: addComponents
* Add components to this geometry.
*
* Parameters:
* components - {Array(<OpenLayers.Geometry>)} An array of geometries to add
*/
addComponents: function(components){
if(!(components instanceof Array)) {
components = [components];
}
for(var i=0; i < components.length; i++) {
this.addComponent(components[i]);
}
},
/**
* 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 - {<OpenLayers.Geometry>} A geometry to add
* index - {int} Optional index into the array to insert the component
*
* Return:
* {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)) {
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;
},
/**
* APIMethod: removeComponents
* Remove components from this geometry.
*
* Parameters:
* components - {Array(<OpenLayers.Geometry>)} The components to be removed
*/
removeComponents: function(components) {
if(!(components instanceof Array)) {
components = [components];
}
for (var i = 0; i < components.length; i++) {
this.removeComponent(components[i]);
}
},
/**
* Method: removeComponent
* Remove a component from this geometry.
*
* Parameters:
* component - {<OpenLayers.Geometry>}
*/
removeComponent: function(component) {
OpenLayers.Util.removeItem(this.components, component);
// clearBounds() so that it gets recalculated on the next call
// to this.getBounds();
this.clearBounds();
},
/**
* APIMethod: getLength
* Calculate the length of this geometry
*
* Return:
* {Float} The length of the geometry
*/
getLength: function() {
var length = 0.0;
for (var i = 0; i < this.components.length; i++) {
length += this.components[i].getLength();
}
return length;
},
/**
* APIMethod: getArea
* Calculate the area of this geometry. Note how this function is overridden
* in <OpenLayers.Geometry.Polygon>.
*
* Return:
* {Float} The area of the collection by summing its parts
*/
getArea: function() {
var area = 0.0;
for (var i = 0; i < this.components.length; i++) {
area += this.components[i].getArea();
}
return area;
},
/**
* APIMethod: move
* Moves a collection in place
*
* Parameters:
* x - {Float} The x-displacement (in map units)
* y - {Float} The y-displacement (in map units)
*/
move: function(x, y) {
for(var i = 0; i < this.components.length; i++) {
this.components[i].move(x, y);
}
},
/**
* APIMethod: rotate
* Rotate a geometry around some origin
*
* Parameters:
* angle - {Float} Rotation angle in radians (measured counterclockwise
* from the positive x-axis)
* origin - {OpenLayers.Geometry.Point} Center point for the rotation
*/
rotate: function(angle, origin) {
for(var i=0; i<this.components.length; ++i) {
this.components[i].rotate(angle, origin);
}
},
/**
* APIMethod: equals
* Tests for equivalent geometries
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
*
* Return:
* {Boolean} The coordinates are equivalent
*/
equals: function(geometry) {
var equivalent = true;
if(!geometry.CLASS_NAME || (this.CLASS_NAME != geometry.CLASS_NAME)) {
equivalent = false;
} else if(!(geometry.components instanceof Array) ||
(geometry.components.length != this.components.length)) {
equivalent = false;
} else {
for(var i=0; i<this.components.length; ++i) {
if(!this.components[i].equals(geometry.components[i])) {
equivalent = false;
break;
}
}
}
return equivalent;
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Geometry.Collection"
});