Add ol.geom.GeometryCollection

This commit is contained in:
Tom Payne
2013-12-11 15:54:29 +01:00
parent 802d1644bb
commit d7eb4db69e
4 changed files with 323 additions and 3 deletions

View File

@@ -1,5 +1,3 @@
// FIXME add GeometryCollection
goog.provide('ol.geom.Geometry');
goog.require('goog.asserts');
@@ -18,7 +16,8 @@ ol.geom.GeometryType = {
POLYGON: 'Polygon',
MULTI_POINT: 'MultiPoint',
MULTI_LINE_STRING: 'MultiLineString',
MULTI_POLYGON: 'MultiPolygon'
MULTI_POLYGON: 'MultiPolygon',
GEOMETRY_COLLECTION: 'GeometryCollection'
};

View File

@@ -0,0 +1,7 @@
@exportSymbol ol.geom.GeometryCollection
@exportProperty ol.geom.GeometryCollection.prototype.clone
@exportProperty ol.geom.GeometryCollection.prototype.getExtent
@exportProperty ol.geom.GeometryCollection.prototype.getGeometries
@exportProperty ol.geom.GeometryCollection.prototype.getSimplifiedGeometry
@exportProperty ol.geom.GeometryCollection.prototype.getType
@exportProperty ol.geom.GeometryCollection.prototype.setGeometries

View File

@@ -0,0 +1,204 @@
goog.provide('ol.geom.GeometryCollection');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.object');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
/**
* @constructor
* @extends {ol.geom.Geometry}
* @param {Array.<ol.geom.Geometry>=} opt_geometries Geometries.
*/
ol.geom.GeometryCollection = function(opt_geometries) {
goog.base(this);
/**
* @private
* @type {Array.<ol.geom.Geometry>}
*/
this.geometries_ = goog.isDef(opt_geometries) ? opt_geometries : null;
};
goog.inherits(ol.geom.GeometryCollection, ol.geom.Geometry);
/**
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
* @private
* @return {Array.<ol.geom.Geometry>} Cloned geometries.
*/
ol.geom.GeometryCollection.cloneGeometries_ = function(geometries) {
var clonedGeometries = [];
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
clonedGeometries.push(geometries[i].clone());
}
return clonedGeometries;
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.clone = function() {
var geometryCollection = new ol.geom.GeometryCollection(null);
geometryCollection.setGeometries(this.geometries_);
return geometryCollection;
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.closestPointXY =
function(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance <
ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
}
var geometries = this.geometries_;
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
minSquaredDistance = geometries[i].closestPointXY(
x, y, closestPoint, minSquaredDistance);
}
return minSquaredDistance;
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.containsXY = function(x, y) {
var geometries = this.geometries_;
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
if (geometries[i].containsXY(x, y)) {
return true;
}
}
return false;
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.getExtent = function(opt_extent) {
if (this.extentRevision != this.revision) {
var extent = ol.extent.createOrUpdateEmpty(this.extent);
var geometries = this.geometries_;
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
ol.extent.extend(extent, geometries[i].getExtent());
}
this.extent = extent;
this.extentRevision = this.revision;
}
goog.asserts.assert(goog.isDef(this.extent));
return ol.extent.returnOrUpdate(this.extent, opt_extent);
};
/**
* @return {Array.<ol.geom.Geometry>} Geometries.
*/
ol.geom.GeometryCollection.prototype.getGeometries = function() {
return ol.geom.GeometryCollection.cloneGeometries_(this.geometries_);
};
/**
* @return {Array.<ol.geom.Geometry>} Geometries.
*/
ol.geom.GeometryCollection.prototype.getGeometriesArray = function() {
return this.geometries_;
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.getSimplifiedGeometry =
function(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.revision) {
goog.object.clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = this.revision;
}
if (squaredTolerance < 0 ||
(this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
squaredTolerance < this.simplifiedGeometryMaxMinSquaredTolerance)) {
return this;
}
var key = squaredTolerance.toString();
if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
return this.simplifiedGeometryCache[key];
} else {
var simplifiedGeometries = [];
var geometries = this.geometries_;
var simplified = false;
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
var geometry = geometries[i];
var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
simplifiedGeometries.push(simplifiedGeometry);
if (simplifiedGeometry !== geometry) {
simplified = true;
}
}
if (simplified) {
var simplifiedGeometryCollection = new ol.geom.GeometryCollection(null);
simplifiedGeometryCollection.setGeometriesArray(simplifiedGeometries);
this.simplifiedGeometryCache[key] = simplifiedGeometryCollection;
return simplifiedGeometryCollection;
} else {
this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
return this;
}
}
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.getType = function() {
return ol.geom.GeometryType.GEOMETRY_COLLECTION;
};
/**
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
*/
ol.geom.GeometryCollection.prototype.setGeometries = function(geometries) {
this.setGeometriesArray(
ol.geom.GeometryCollection.cloneGeometries_(geometries));
};
/**
* @param {Array.<ol.geom.Geometry>} geometries Geometries.
*/
ol.geom.GeometryCollection.prototype.setGeometriesArray = function(geometries) {
this.geometries_ = geometries;
this.dispatchChangeEvent();
};
/**
* @inheritDoc
*/
ol.geom.GeometryCollection.prototype.transform = function(transformFn) {
var geometries = this.geometries_;
var i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
geometries[i].transform(transformFn);
}
this.dispatchChangeEvent();
};

View File

@@ -0,0 +1,110 @@
goog.provide('ol.test.geom.GeometryCollection');
describe('ol.geom.GeometryCollection', function() {
var outer = [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
inner1 = [[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]],
inner2 = [[8, 8], [9, 8], [9, 9], [8, 9], [8, 8]];
describe('constructor', function() {
it('creates a geometry collection from an array of geometries', function() {
var point = new ol.geom.Point([10, 20]);
var line = new ol.geom.LineString([[10, 20], [30, 40]]);
var poly = new ol.geom.Polygon([outer, inner1, inner2]);
var multi = new ol.geom.GeometryCollection([point, line, poly]);
expect(multi).to.be.a(ol.geom.GeometryCollection);
expect(multi).to.be.a(ol.geom.Geometry);
});
});
describe('#getGeometries', function() {
it('returns a collection of geometries', function() {
var point = new ol.geom.Point([10, 20]);
var line = new ol.geom.LineString([[10, 20], [30, 40]]);
var poly = new ol.geom.Polygon([outer, inner1, inner2]);
var multi = new ol.geom.GeometryCollection([point, line, poly]);
var geometries = multi.getGeometries();
expect(geometries).to.be.an(Array);
expect(geometries).to.have.length(3);
expect(geometries[0]).to.be.a(ol.geom.Point);
expect(geometries[1]).to.be.a(ol.geom.LineString);
expect(geometries[2]).to.be.a(ol.geom.Polygon);
});
});
describe('#clone()', function() {
it('has a working clone method', function() {
var point = new ol.geom.Point([10, 20]);
var line = new ol.geom.LineString([[10, 20], [30, 40]]);
var poly = new ol.geom.Polygon([outer, inner1, inner2]);
var multi = new ol.geom.GeometryCollection([point, line, poly]);
var clone = multi.clone();
expect(clone).to.not.be(multi);
var geometries = clone.getGeometries();
expect(geometries[0].getCoordinates()).to.eql([10, 20]);
expect(geometries[1].getCoordinates()).to.eql([[10, 20], [30, 40]]);
expect(geometries[2].getCoordinates()).to.eql([outer, inner1, inner2]);
});
});
describe('#getExtent()', function() {
it('returns the bounding extent', function() {
var point = new ol.geom.Point([10, 2]);
var line = new ol.geom.LineString([[1, 20], [30, 40]]);
var multi = new ol.geom.GeometryCollection([point, line]);
var extent = multi.getExtent();
expect(extent[0]).to.be(1);
expect(extent[2]).to.be(30);
expect(extent[1]).to.be(2);
expect(extent[3]).to.be(40);
});
});
describe('#setGeometries', function() {
var line, multi, point, poly;
beforeEach(function() {
point = new ol.geom.Point([10, 20]);
line = new ol.geom.LineString([[10, 20], [30, 40]]);
poly = new ol.geom.Polygon([outer, inner1, inner2]);
multi = new ol.geom.GeometryCollection([point, line, poly]);
});
it('fires a change event', function() {
var listener = sinon.spy();
multi.on('change', listener);
point.setCoordinates([15, 25]);
expect(listener.calledOnce).to.be(false);
multi.setGeometries([point, line, poly]);
expect(listener.calledOnce).to.be(true);
});
it('updates the extent', function() {
expect(multi.getExtent()).to.eql([0, 0, 30, 40]);
line.setCoordinates([[10, 20], [300, 400]]);
expect(multi.getExtent()).to.eql([0, 0, 30, 40]);
multi.setGeometries([point, line, poly]);
expect(multi.getExtent()).to.eql([0, 0, 300, 400]);
});
});
});
goog.require('ol.Collection');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryCollection');
goog.require('ol.geom.LineString');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');