Add method Polyline.closestLayerPoint
Also fix method L.LineUtil.simplify for empty geometry
This commit is contained in:
parent
cf83c2e146
commit
263a5b9b5f
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
<!-- /layer -->
|
<!-- /layer -->
|
||||||
<script type="text/javascript" src="suites/layer/TileLayerSpec.js"></script>
|
<script type="text/javascript" src="suites/layer/TileLayerSpec.js"></script>
|
||||||
|
<script type="text/javascript" src="suites/layer/vector/PolylineGeometrySpec.js"></script>
|
||||||
|
|
||||||
<!-- /map -->
|
<!-- /map -->
|
||||||
<script type="text/javascript" src="suites/map/MapSpec.js"></script>
|
<script type="text/javascript" src="suites/map/MapSpec.js"></script>
|
||||||
|
@ -3,3 +3,26 @@ function noSpecs() {
|
|||||||
expect('specs').toBe();
|
expect('specs').toBe();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Array.prototype.map) {
|
||||||
|
Array.prototype.map = function(fun /*, thisp */) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (this === void 0 || this === null)
|
||||||
|
throw new TypeError();
|
||||||
|
|
||||||
|
var t = Object(this);
|
||||||
|
var len = t.length >>> 0;
|
||||||
|
if (typeof fun !== "function")
|
||||||
|
throw new TypeError();
|
||||||
|
|
||||||
|
var res = new Array(len);
|
||||||
|
var thisp = arguments[1];
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
if (i in t)
|
||||||
|
res[i] = fun.call(thisp, t[i], i, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
}
|
35
spec/suites/layer/vector/PolylineGeometrySpec.js
Normal file
35
spec/suites/layer/vector/PolylineGeometrySpec.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
describe('PolylineGeometry', function() {
|
||||||
|
|
||||||
|
var c = document.createElement('div');
|
||||||
|
c.style.width = '400px';
|
||||||
|
c.style.height = '400px';
|
||||||
|
var map = new L.Map(c);
|
||||||
|
map.setView(new L.LatLng(55.8, 37.6), 6);
|
||||||
|
|
||||||
|
describe("#distanceTo", function() {
|
||||||
|
it("should calculate correct distances to points", function() {
|
||||||
|
var p1 = map.latLngToLayerPoint(new L.LatLng(55.8, 37.6));
|
||||||
|
var p2 = map.latLngToLayerPoint(new L.LatLng(57.123076977278, 44.861962891635));
|
||||||
|
var latlngs = [[56.485503424111, 35.545556640339], [55.972522915346, 36.116845702918], [55.502459116923, 34.930322265253], [55.31534617509, 38.973291015816]]
|
||||||
|
.map(function(ll) {
|
||||||
|
return new L.LatLng(ll[0], ll[1]);
|
||||||
|
});
|
||||||
|
var polyline = new L.Polyline([], {
|
||||||
|
'noClip': true
|
||||||
|
});
|
||||||
|
map.addLayer(polyline);
|
||||||
|
|
||||||
|
expect(polyline.closestLayerPoint(p1)).toEqual(null);
|
||||||
|
|
||||||
|
polyline.setLatLngs(latlngs);
|
||||||
|
var point = polyline.closestLayerPoint(p1);
|
||||||
|
expect(point).not.toEqual(null);
|
||||||
|
expect(point.distance).not.toEqual(Infinity);
|
||||||
|
expect(point.distance).not.toEqual(NaN);
|
||||||
|
|
||||||
|
var point2 = polyline.closestLayerPoint(p2);
|
||||||
|
|
||||||
|
expect(point.distance).toBeLessThan(point2.distance);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -9,7 +9,7 @@ L.LineUtil = {
|
|||||||
* Improves rendering performance dramatically by lessening the number of points to draw.
|
* Improves rendering performance dramatically by lessening the number of points to draw.
|
||||||
*/
|
*/
|
||||||
simplify: function(/*Point[]*/ points, /*Number*/ tolerance) {
|
simplify: function(/*Point[]*/ points, /*Number*/ tolerance) {
|
||||||
if (!tolerance) return points.slice();
|
if (!tolerance || !points.length) return points.slice();
|
||||||
|
|
||||||
// stage 1: vertex reduction
|
// stage 1: vertex reduction
|
||||||
points = this.reducePoints(points, tolerance);
|
points = this.reducePoints(points, tolerance);
|
||||||
@ -25,6 +25,12 @@ L.LineUtil = {
|
|||||||
return Math.sqrt(this._sqPointToSegmentDist(p, p1, p2));
|
return Math.sqrt(this._sqPointToSegmentDist(p, p1, p2));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
closestPointOnSegment: function(/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
|
||||||
|
var point = this._sqClosestPointOnSegment(p, p1, p2);
|
||||||
|
point.distance = Math.sqrt(point._sqDist);
|
||||||
|
return point;
|
||||||
|
},
|
||||||
|
|
||||||
// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
|
// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
|
||||||
simplifyDP: function(points, tol) {
|
simplifyDP: function(points, tol) {
|
||||||
var maxDist2 = 0,
|
var maxDist2 = 0,
|
||||||
@ -140,8 +146,10 @@ L.LineUtil = {
|
|||||||
return dx * dx + dy * dy;
|
return dx * dx + dy * dy;
|
||||||
},
|
},
|
||||||
|
|
||||||
// square distance from point to a segment
|
/**
|
||||||
_sqPointToSegmentDist: function(p, p1, p2) {
|
* @return L.Point point on segment with attribute _sqDist - square distance to segment
|
||||||
|
*/
|
||||||
|
_sqClosestPointOnSegment: function(p, p1, p2) {
|
||||||
var x2 = p2.x - p1.x,
|
var x2 = p2.x - p1.x,
|
||||||
y2 = p2.y - p1.y;
|
y2 = p2.y - p1.y;
|
||||||
|
|
||||||
@ -150,10 +158,18 @@ L.LineUtil = {
|
|||||||
var dot = (p.x - p1.x) * x2 + (p.y - p1.y) * y2,
|
var dot = (p.x - p1.x) * x2 + (p.y - p1.y) * y2,
|
||||||
t = dot / this._sqDist(p1, p2);
|
t = dot / this._sqDist(p1, p2);
|
||||||
|
|
||||||
if (t < 0) return this._sqDist(p, p1);
|
var apoint = p1;
|
||||||
if (t > 1) return this._sqDist(p, p2);
|
if (t > 1) {
|
||||||
|
apoint = p2;
|
||||||
|
} else if (t > 0) {
|
||||||
|
apoint = new L.Point(p1.x + x2 * t, p1.y + y2 * t);
|
||||||
|
}
|
||||||
|
apoint._sqDist = this._sqDist(p, apoint);
|
||||||
|
return apoint;
|
||||||
|
},
|
||||||
|
|
||||||
var proj = new L.Point(p1.x + x2 * t, p1.y + y2 * t);
|
// distance from a point to a segment between two points
|
||||||
return this._sqDist(p, proj);
|
_sqPointToSegmentDist: function(p, p1, p2) {
|
||||||
|
return this._sqClosestPointOnSegment(p, p1, p2)._sqDist;
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -51,6 +51,25 @@ L.Polyline = L.Path.extend({
|
|||||||
return removed;
|
return removed;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
closestLayerPoint: function(p) {
|
||||||
|
var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null;
|
||||||
|
|
||||||
|
for (var j = 0, jLen = parts.length; j < jLen; j++) {
|
||||||
|
var points = parts[j];
|
||||||
|
for (var i = 1, len = points.length; i < len; i++) {
|
||||||
|
p1 = points[i-1];
|
||||||
|
p2 = points[i];
|
||||||
|
var point = L.LineUtil._sqClosestPointOnSegment(p, p1, p2);
|
||||||
|
if (point._sqDist < minDistance) {
|
||||||
|
minDistance = point._sqDist;
|
||||||
|
minPoint = point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (minPoint) minPoint.distance = Math.sqrt(minDistance);
|
||||||
|
return minPoint;
|
||||||
|
},
|
||||||
|
|
||||||
_getPathPartStr: function(points) {
|
_getPathPartStr: function(points) {
|
||||||
var round = L.Path.VML;
|
var round = L.Path.VML;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user