Add optional parameter for result rounding in L.PolyUtil.clipPolygon and L.LineUtil.clipSegment

This commit is contained in:
Alexander Parshin 2014-09-30 09:57:53 +04:00
parent f83915aa3b
commit 3a5d45d62e
6 changed files with 39 additions and 9 deletions

View File

@ -33,6 +33,21 @@ describe('LineUtil', function () {
expect(segment).to.be(false); 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 () { describe('#pointToSegmentDistance & #closestPointOnSegment', function () {

View File

@ -10,6 +10,7 @@ describe('PolyUtil', function () {
new L.Point(10, 15) new L.Point(10, 15)
]; ];
//check clip without rounding
var clipped = L.PolyUtil.clipPolygon(points, bounds); var clipped = L.PolyUtil.clipPolygon(points, bounds);
for (var i = 0, len = clipped.length; i < len; i++) { for (var i = 0, len = clipped.length; i < len; i++) {
@ -17,6 +18,20 @@ describe('PolyUtil', function () {
} }
expect(clipped).to.eql([ 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(8, 10),
new L.Point(5, 5), new L.Point(5, 5),
new L.Point(10, 8), new L.Point(10, 8),

View File

@ -99,7 +99,7 @@ L.LineUtil = {
// Cohen-Sutherland line clipping algorithm. // Cohen-Sutherland line clipping algorithm.
// Used to avoid rendering parts of a polyline that are not currently visible. // 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), var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds),
codeB = this._getBitCode(b, bounds), codeB = this._getBitCode(b, bounds),
@ -118,7 +118,7 @@ L.LineUtil = {
// other cases // other cases
} else { } else {
codeOut = codeA || codeB; codeOut = codeA || codeB;
p = this._getEdgeIntersection(a, b, codeOut, bounds); p = this._getEdgeIntersection(a, b, codeOut, bounds, round);
newCode = this._getBitCode(p, bounds); newCode = this._getBitCode(p, bounds);
if (codeOut === codeA) { 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, var dx = b.x - a.x,
dy = b.y - a.y, dy = b.y - a.y,
min = bounds.min, min = bounds.min,
@ -156,7 +156,7 @@ L.LineUtil = {
y = a.y + dy * (min.x - a.x) / dx; 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) { _getBitCode: function (/*Point*/ p, bounds) {

View File

@ -10,7 +10,7 @@ L.PolyUtil = {};
* Sutherland-Hodgeman polygon clipping algorithm. * Sutherland-Hodgeman polygon clipping algorithm.
* Used to avoid rendering parts of a polygon that are not currently visible. * 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, var clippedPoints,
edges = [1, 4, 2, 8], edges = [1, 4, 2, 8],
i, j, k, i, j, k,
@ -35,7 +35,7 @@ L.PolyUtil.clipPolygon = function (points, bounds) {
if (!(a._code & edge)) { if (!(a._code & edge)) {
// if b is outside the clip window (a->b goes out of screen) // if b is outside the clip window (a->b goes out of screen)
if (b._code & edge) { 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); p._code = lu._getBitCode(p, bounds);
clippedPoints.push(p); 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 is inside the clip window (a->b enters the screen)
} else if (!(b._code & edge)) { } 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); p._code = lu._getBitCode(p, bounds);
clippedPoints.push(p); clippedPoints.push(p);
} }

View File

@ -58,7 +58,7 @@ L.Polygon = L.Polyline.extend({
this._parts = []; this._parts = [];
for (var i = 0, len = this._rings.length, clipped; i < len; i++) { 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) { if (clipped.length) {
this._parts.push(clipped); this._parts.push(clipped);
} }

View File

@ -179,7 +179,7 @@ L.Polyline = L.Path.extend({
points = this._rings[i]; points = this._rings[i];
for (j = 0, len2 = points.length; j < len2 - 1; j++) { 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; } if (!segment) { continue; }