Better label placement for polygons
Using the y-coordinate of the polygon's bounding box, this simple algorithm intersects the polygon with the horizontal center line of its bounding box. The x-coordinate of the label point is the center of the longest segment of this intersection that is inside the polygon.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
goog.provide('ol.geom.Polygon');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
@@ -35,6 +36,12 @@ ol.geom.Polygon = function(coordinates, opt_shared) {
|
||||
vertices = new ol.geom.SharedVertices({dimension: dimension});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.labelPoint_ = null;
|
||||
|
||||
/**
|
||||
* @type {ol.geom.SharedVertices}
|
||||
*/
|
||||
@@ -126,3 +133,48 @@ ol.geom.Polygon.prototype.containsCoordinate = function(coordinate) {
|
||||
}
|
||||
return containsCoordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates a label point that is guaranteed to be inside the polygon.
|
||||
* @return {ol.Coordinate} The label point.
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getLabelPoint = function() {
|
||||
if (goog.isNull(this.labelPoint_)) {
|
||||
var center = ol.extent.getCenter(this.getBounds()),
|
||||
resultY = center[1],
|
||||
vertices = this.rings[0].getCoordinates(),
|
||||
intersections = [],
|
||||
maxLength = 0,
|
||||
i, vertex1, vertex2, x, segmentLength, resultX;
|
||||
|
||||
// Calculate intersections with the horizontal bounding box center line
|
||||
for (i = vertices.length - 1; i >= 1; --i) {
|
||||
vertex1 = vertices[i];
|
||||
vertex2 = vertices[i - 1];
|
||||
if ((vertex1[1] >= resultY && vertex2[1] <= resultY) ||
|
||||
(vertex1[1] <= resultY && vertex2[1] >= resultY)) {
|
||||
x = (resultY - vertex1[1]) / (vertex2[1] - vertex1[1]) *
|
||||
(vertex2[0] - vertex1[0]) + vertex1[0];
|
||||
intersections.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the longest segment of the horizontal bounding box center line that
|
||||
// has its center point inside the polygon
|
||||
intersections.sort();
|
||||
for (i = intersections.length - 1; i >= 1; --i) {
|
||||
segmentLength = Math.abs(intersections[i] - intersections[i - 1]);
|
||||
if (segmentLength > maxLength) {
|
||||
x = (intersections[i] + intersections[i - 1]) / 2;
|
||||
if (this.containsCoordinate([x, resultY])) {
|
||||
maxLength = segmentLength;
|
||||
resultX = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.labelPoint_ = [resultX, resultY];
|
||||
}
|
||||
|
||||
return this.labelPoint_;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@ goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.AbstractCollection');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
@@ -446,8 +445,7 @@ ol.renderer.canvas.VectorRenderer.getLabelVectors = function(geometry) {
|
||||
return [[geometry.get(0), geometry.get(1), 0]];
|
||||
}
|
||||
if (type == ol.geom.GeometryType.POLYGON) {
|
||||
// TODO: better label placement
|
||||
var coordinates = ol.extent.getCenter(geometry.getBounds());
|
||||
var coordinates = geometry.getLabelPoint();
|
||||
return [[coordinates[0], coordinates[1], 0]];
|
||||
}
|
||||
throw new Error('Label rendering not implemented for geometry type: ' +
|
||||
|
||||
Reference in New Issue
Block a user