diff --git a/src/ol/coordinate.js b/src/ol/coordinate.js
index 85f0b5318e..a0eebcde74 100644
--- a/src/ol/coordinate.js
+++ b/src/ol/coordinate.js
@@ -42,6 +42,45 @@ ol.coordinate.add = function(coordinate, delta) {
};
+/**
+ * Calculates the point closest to the passed coordinate on the passed segment.
+ * This is the foot of the perpendicular of the coordinate to the segment when
+ * the foot is on the segment, or the closest segment coordinate when the foot
+ * is outside the segment.
+ *
+ * @param {ol.Coordinate} coordinate The coordinate.
+ * @param {Array.
} segment The two coordinates of the segment.
+ * @return {ol.Coordinate} The foot of the perpendicular of the coordinate to
+ * the segment.
+ */
+ol.coordinate.closestOnSegment = function(coordinate, segment) {
+ var x0 = coordinate[0];
+ var y0 = coordinate[1];
+ var start = segment[0];
+ var end = segment[1];
+ var x1 = start[0];
+ var y1 = start[1];
+ var x2 = end[0];
+ var y2 = end[1];
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var along = (dx == 0 && dy == 0) ? 0 :
+ ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0);
+ var x, y;
+ if (along <= 0) {
+ x = x1;
+ y = y1;
+ } else if (along >= 1) {
+ x = x2;
+ y = y2;
+ } else {
+ x = x1 + along * dx;
+ y = y1 + along * dy;
+ }
+ return [x, y];
+};
+
+
/**
* @param {number=} opt_fractionDigits The number of digits to include
* after the decimal point. Default is `0`.
@@ -136,6 +175,19 @@ ol.coordinate.squaredDistance = function(coord1, coord2) {
};
+/**
+ * Calculate the squared distance from a coordinate to a line segment.
+ *
+ * @param {ol.Coordinate} coordinate Coordinate of the point.
+ * @param {Array.} segment Line segment (2 coordinates).
+ * @return {number} Squared distance from the point to the line segment.
+ */
+ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
+ return ol.coordinate.squaredDistance(coordinate,
+ ol.coordinate.closestOnSegment(coordinate, segment));
+};
+
+
/**
* @param {ol.Coordinate|undefined} coordinate Coordinate.
* @return {string} Hemisphere, degrees, minutes and seconds.
diff --git a/src/ol/geom/base.js b/src/ol/geom/base.js
deleted file mode 100644
index 9950aab807..0000000000
--- a/src/ol/geom/base.js
+++ /dev/null
@@ -1,31 +0,0 @@
-goog.provide('ol.geom');
-
-goog.require('ol.coordinate');
-
-
-/**
- * Calculate the squared distance from a point to a line segment.
- *
- * @param {ol.Coordinate} coordinate Coordinate of the point.
- * @param {Array.} segment Line segment (2 coordinates).
- * @return {number} Squared distance from the point to the line segment.
- */
-ol.geom.squaredDistanceToSegment = function(coordinate, segment) {
- // http://de.softuses.com/103478, Kommentar #1
- var v = segment[0];
- var w = segment[1];
- var l2 = ol.coordinate.squaredDistance(v, w);
- if (l2 === 0) {
- return ol.coordinate.squaredDistance(coordinate, v);
- }
- var t = ((coordinate[0] - v[0]) * (w[0] - v[0]) +
- (coordinate[1] - v[1]) * (w[1] - v[1])) / l2;
- if (t < 0) {
- return ol.coordinate.squaredDistance(coordinate, v);
- }
- if (t > 1) {
- return ol.coordinate.squaredDistance(coordinate, w);
- }
- return ol.coordinate.squaredDistance(coordinate,
- [v[0] + t * (w[0] - v[0]), v[1] + t * (w[1] - v[1])]);
-};
diff --git a/src/ol/geom/linestring.js b/src/ol/geom/linestring.js
index 11b2fd3e05..e7ed07843b 100644
--- a/src/ol/geom/linestring.js
+++ b/src/ol/geom/linestring.js
@@ -3,8 +3,8 @@ goog.provide('ol.geom.LineString');
goog.require('goog.asserts');
goog.require('goog.events.EventType');
goog.require('ol.CoordinateArray');
+goog.require('ol.coordinate');
goog.require('ol.extent');
-goog.require('ol.geom');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryEvent');
goog.require('ol.geom.GeometryType');
@@ -104,7 +104,7 @@ ol.geom.LineString.prototype.distanceFromCoordinate = function(coordinate) {
var coordinates = this.getCoordinates();
var dist2 = Infinity;
for (var i = 0, j = 1, len = coordinates.length; j < len; i = j++) {
- dist2 = Math.min(dist2, ol.geom.squaredDistanceToSegment(coordinate,
+ dist2 = Math.min(dist2, ol.coordinate.squaredDistanceToSegment(coordinate,
[coordinates[i], coordinates[j]]));
}
return Math.sqrt(dist2);
diff --git a/test/spec/ol/coordinate.test.js b/test/spec/ol/coordinate.test.js
new file mode 100644
index 0000000000..baee06d42d
--- /dev/null
+++ b/test/spec/ol/coordinate.test.js
@@ -0,0 +1,42 @@
+goog.provide('ol.test.coordinate');
+
+describe.only('ol.coordinate', function() {
+
+ describe('#closestOnSegment', function() {
+ it('can handle points where the foot of the perpendicular is closest',
+ function() {
+ var point = [2, 5];
+ var segment = [[-5, 0], [10, 0]];
+ expect(ol.coordinate.closestOnSegment(point, segment))
+ .to.eql([2, 0]);
+ });
+ it('can handle points where the foot of the perpendicular is not closest',
+ function() {
+ var point = [0, -6];
+ var segment = [[-5, 0], [0, -1]];
+ expect(ol.coordinate.closestOnSegment(point, segment))
+ .to.eql([0, -1]);
+ });
+ });
+
+ describe('#squaredDistanceToSegment', function() {
+ it('can handle points where the foot of the perpendicular is closest',
+ function() {
+ var point = [2, 5];
+ var segment = [[-5, 0], [10, 0]];
+ expect(ol.coordinate.squaredDistanceToSegment(point, segment))
+ .to.eql(25);
+ });
+ it('can handle points where the foot of the perpendicular is not closest',
+ function() {
+ var point = [0, -6];
+ var segment = [[-5, 0], [0, -1]];
+ expect(ol.coordinate.squaredDistanceToSegment(point, segment))
+ .to.eql(25);
+ });
+
+ });
+
+});
+
+goog.require('ol.coordinate');