diff --git a/spec/suites/geometry/LineUtilSpec.js b/spec/suites/geometry/LineUtilSpec.js index b7251a0f..c8873e6a 100644 --- a/spec/suites/geometry/LineUtilSpec.js +++ b/spec/suites/geometry/LineUtilSpec.js @@ -33,6 +33,21 @@ describe('LineUtil', function () { expect(segment).to.be(false); }); + + it('can round numbers in clipped bounds', function () { + var a = new L.Point(4, 5); + var b = new L.Point(8, 6); + + var segment1 = L.LineUtil.clipSegment(a, b, bounds); + + expect(segment1[0]).to.eql(new L.Point(5, 5.25)); + expect(segment1[1]).to.eql(b); + + var segment2 = L.LineUtil.clipSegment(a, b, bounds, false, true); + + expect(segment2[0]).to.eql(new L.Point(5, 5)); + expect(segment2[1]).to.eql(b); + }); }); describe('#pointToSegmentDistance & #closestPointOnSegment', function () { diff --git a/spec/suites/geometry/PolyUtilSpec.js b/spec/suites/geometry/PolyUtilSpec.js index 0cd382ee..6dcf7839 100644 --- a/spec/suites/geometry/PolyUtilSpec.js +++ b/spec/suites/geometry/PolyUtilSpec.js @@ -10,6 +10,7 @@ describe('PolyUtil', function () { new L.Point(10, 15) ]; + //check clip without rounding var clipped = L.PolyUtil.clipPolygon(points, bounds); for (var i = 0, len = clipped.length; i < len; i++) { @@ -17,6 +18,20 @@ describe('PolyUtil', function () { } expect(clipped).to.eql([ + new L.Point(7.5, 10), + new L.Point(5, 5), + new L.Point(10, 7.5), + new L.Point(10, 10) + ]); + + //check clip with rounding + var clippedRounded = L.PolyUtil.clipPolygon(points, bounds, true); + + for (i = 0, len = clippedRounded.length; i < len; i++) { + delete clippedRounded[i]._code; + } + + expect(clippedRounded).to.eql([ new L.Point(8, 10), new L.Point(5, 5), new L.Point(10, 8), diff --git a/src/geometry/LineUtil.js b/src/geometry/LineUtil.js index ab6a7b6c..28f44475 100644 --- a/src/geometry/LineUtil.js +++ b/src/geometry/LineUtil.js @@ -99,7 +99,7 @@ L.LineUtil = { // Cohen-Sutherland line clipping algorithm. // Used to avoid rendering parts of a polyline that are not currently visible. - clipSegment: function (a, b, bounds, useLastCode) { + clipSegment: function (a, b, bounds, useLastCode, round) { var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), codeB = this._getBitCode(b, bounds), @@ -118,7 +118,7 @@ L.LineUtil = { // other cases } else { codeOut = codeA || codeB; - p = this._getEdgeIntersection(a, b, codeOut, bounds); + p = this._getEdgeIntersection(a, b, codeOut, bounds, round); newCode = this._getBitCode(p, bounds); if (codeOut === codeA) { @@ -132,7 +132,7 @@ L.LineUtil = { } }, - _getEdgeIntersection: function (a, b, code, bounds) { + _getEdgeIntersection: function (a, b, code, bounds, round) { var dx = b.x - a.x, dy = b.y - a.y, min = bounds.min, @@ -156,7 +156,7 @@ L.LineUtil = { y = a.y + dy * (min.x - a.x) / dx; } - return new L.Point(x, y, true); + return new L.Point(x, y, round); }, _getBitCode: function (/*Point*/ p, bounds) { diff --git a/src/geometry/PolyUtil.js b/src/geometry/PolyUtil.js index 68aa36d8..9b3b24e0 100644 --- a/src/geometry/PolyUtil.js +++ b/src/geometry/PolyUtil.js @@ -10,7 +10,7 @@ L.PolyUtil = {}; * Sutherland-Hodgeman polygon clipping algorithm. * Used to avoid rendering parts of a polygon that are not currently visible. */ -L.PolyUtil.clipPolygon = function (points, bounds) { +L.PolyUtil.clipPolygon = function (points, bounds, round) { var clippedPoints, edges = [1, 4, 2, 8], i, j, k, @@ -35,7 +35,7 @@ L.PolyUtil.clipPolygon = function (points, bounds) { if (!(a._code & edge)) { // if b is outside the clip window (a->b goes out of screen) if (b._code & edge) { - p = lu._getEdgeIntersection(b, a, edge, bounds); + p = lu._getEdgeIntersection(b, a, edge, bounds, round); p._code = lu._getBitCode(p, bounds); clippedPoints.push(p); } @@ -43,7 +43,7 @@ L.PolyUtil.clipPolygon = function (points, bounds) { // else if b is inside the clip window (a->b enters the screen) } else if (!(b._code & edge)) { - p = lu._getEdgeIntersection(b, a, edge, bounds); + p = lu._getEdgeIntersection(b, a, edge, bounds, round); p._code = lu._getBitCode(p, bounds); clippedPoints.push(p); } diff --git a/src/layer/vector/Polygon.js b/src/layer/vector/Polygon.js index 03438887..f35bc6df 100644 --- a/src/layer/vector/Polygon.js +++ b/src/layer/vector/Polygon.js @@ -58,7 +58,7 @@ L.Polygon = L.Polyline.extend({ this._parts = []; for (var i = 0, len = this._rings.length, clipped; i < len; i++) { - clipped = L.PolyUtil.clipPolygon(this._rings[i], bounds); + clipped = L.PolyUtil.clipPolygon(this._rings[i], bounds, true); if (clipped.length) { this._parts.push(clipped); } diff --git a/src/layer/vector/Polyline.js b/src/layer/vector/Polyline.js index a045b28a..9f2209fc 100644 --- a/src/layer/vector/Polyline.js +++ b/src/layer/vector/Polyline.js @@ -179,7 +179,7 @@ L.Polyline = L.Path.extend({ points = this._rings[i]; for (j = 0, len2 = points.length; j < len2 - 1; j++) { - segment = L.LineUtil.clipSegment(points[j], points[j + 1], bounds, j); + segment = L.LineUtil.clipSegment(points[j], points[j + 1], bounds, j, true); if (!segment) { continue; }