Giving the getCentroid method on geometry collections a 'weighted' argument. If true, the centroid will be calculated based on the weighted average of all component centroids. Thanks for the great patch dzwarg. r=me (closes #2469)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@10652 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -261,22 +261,67 @@ OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {
|
|||||||
/**
|
/**
|
||||||
* APIMethod: getCentroid
|
* APIMethod: getCentroid
|
||||||
*
|
*
|
||||||
|
* 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:
|
* Returns:
|
||||||
* {<OpenLayers.Geometry.Point>} The centroid of the collection
|
* {<OpenLayers.Geometry.Point>} The centroid of the collection
|
||||||
*/
|
*/
|
||||||
getCentroid: function() {
|
getCentroid: function(weighted) {
|
||||||
return this.components.length && this.components[0].getCentroid();
|
if (!weighted) {
|
||||||
/*
|
return this.components.length && this.components[0].getCentroid();
|
||||||
var centroid;
|
|
||||||
for (var i=0, len=this.components.length; i<len; i++) {
|
|
||||||
if (!centroid) {
|
|
||||||
centroid = this.components[i].getCentroid();
|
|
||||||
} else {
|
|
||||||
centroid.resize(this.components[i].getCentroid(), 0.5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return centroid;
|
var len = this.components.length;
|
||||||
*/
|
if (!len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OpenLayers.Geometry.Point(xSum/areaSum, ySum/areaSum);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -250,6 +250,148 @@
|
|||||||
t.eq(multipoint.bounds, null, "multipoint component bounds cleared");
|
t.eq(multipoint.bounds, null, "multipoint component bounds cleared");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_getCentroid_pts_only(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
coll = new OpenLayers.Geometry.Collection();
|
||||||
|
coll.addComponent(new OpenLayers.Geometry.Point(0,0));
|
||||||
|
coll.addComponent(new OpenLayers.Geometry.Point(1,1));
|
||||||
|
|
||||||
|
centroid = coll.getCentroid(true);
|
||||||
|
t.ok(centroid != null, 'The centroid is not null.');
|
||||||
|
t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
|
||||||
|
t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
|
||||||
|
|
||||||
|
coll.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getCentroid_poly_nonrecursive(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
coll = new OpenLayers.Geometry.Collection();
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(0,0),
|
||||||
|
new OpenLayers.Geometry.Point(0,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,0)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
// performing non-recursive getCentroid means this next polygon
|
||||||
|
// is excluded from the centroid computation
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(2,2),
|
||||||
|
new OpenLayers.Geometry.Point(2,3),
|
||||||
|
new OpenLayers.Geometry.Point(3,3),
|
||||||
|
new OpenLayers.Geometry.Point(3,2)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
centroid = coll.getCentroid();
|
||||||
|
t.ok(centroid != null, 'The centroid is not null.');
|
||||||
|
t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
|
||||||
|
t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
|
||||||
|
|
||||||
|
coll.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getCentroid_poly_only(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
coll = new OpenLayers.Geometry.Collection();
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(0,0),
|
||||||
|
new OpenLayers.Geometry.Point(0,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,0)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
centroid = coll.getCentroid(true);
|
||||||
|
t.ok(centroid != null, 'The centroid is not null.');
|
||||||
|
t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
|
||||||
|
t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
|
||||||
|
|
||||||
|
coll.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getCentroid_poly_and_pts(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
coll = new OpenLayers.Geometry.Collection();
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(0,0),
|
||||||
|
new OpenLayers.Geometry.Point(0,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,0)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// since the polygon above has an area of 1 and these
|
||||||
|
// points have an area of 0, they should not change the centroid
|
||||||
|
coll.addComponent( new OpenLayers.Geometry.Point(2,2) );
|
||||||
|
coll.addComponent( new OpenLayers.Geometry.Point(4,4) );
|
||||||
|
|
||||||
|
centroid = coll.getCentroid(true);
|
||||||
|
t.ok(centroid != null, 'The centroid is not null.');
|
||||||
|
t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
|
||||||
|
t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
|
||||||
|
|
||||||
|
coll.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getCentroid_poly_big_and_small(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
coll = new OpenLayers.Geometry.Collection();
|
||||||
|
// polygon w/area=1, centroid=0.5,0.5
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(0,0),
|
||||||
|
new OpenLayers.Geometry.Point(0,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,1),
|
||||||
|
new OpenLayers.Geometry.Point(1,0)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// since the polygon above has an area of 1 and this
|
||||||
|
// polygon has an area of 4, the center is weighted 20% toward
|
||||||
|
// the first polygon
|
||||||
|
|
||||||
|
// polygon w/area=4, centroid=5.5,5.5
|
||||||
|
coll.addComponent(
|
||||||
|
new OpenLayers.Geometry.Polygon([
|
||||||
|
new OpenLayers.Geometry.LinearRing([
|
||||||
|
new OpenLayers.Geometry.Point(4.5,-0.5),
|
||||||
|
new OpenLayers.Geometry.Point(4.5,1.5),
|
||||||
|
new OpenLayers.Geometry.Point(6.5,1.5),
|
||||||
|
new OpenLayers.Geometry.Point(6.5,-0.5)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
centroid = coll.getCentroid(true);
|
||||||
|
t.ok(centroid != null, 'The centroid is not null.');
|
||||||
|
t.eq(centroid.x, 4.5, 'The centroid x coordinate is good.');
|
||||||
|
t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
|
||||||
|
|
||||||
|
coll.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function test_Collection_destroy(t) {
|
function test_Collection_destroy(t) {
|
||||||
t.plan( 3 );
|
t.plan( 3 );
|
||||||
|
|||||||
Reference in New Issue
Block a user