From 77cd0b99b0c76f88b7ee754faacf9f822b9b8626 Mon Sep 17 00:00:00 2001 From: ExtremoBlando Date: Mon, 10 Dec 2018 16:34:47 +0100 Subject: [PATCH 1/2] Update leaflet.polylineoffset.js --- leaflet.polylineoffset.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/leaflet.polylineoffset.js b/leaflet.polylineoffset.js index 855abad..d7cba53 100644 --- a/leaflet.polylineoffset.js +++ b/leaflet.polylineoffset.js @@ -101,10 +101,9 @@ var PolylineOffset = { return offsetSegments; }, - - offsetPoints: function(pts, offset) { - var offsetSegments = this.offsetPointLine(pts, offset); - return this.joinLineSegments(offsetSegments, offset); + offsetPoints: function(pts, options) { + var offsetSegments = this.offsetPointLine(L.LineUtil.simplify(pts, options.smoothFactor), options.offset); + return this.joinLineSegments(offsetSegments, options.offset); }, /** @@ -199,7 +198,7 @@ L.Polyline.include({ // Offset management hack --- if (this.options.offset) { - ring = L.PolylineOffset.offsetPoints(ring, this.options.offset); + ring = L.PolylineOffset.offsetPoints(ring, this.options); } // Offset management hack END --- From a225d0406c28d8bd240da0e20ef1cdb4160ce0ba Mon Sep 17 00:00:00 2001 From: ExtremoBlando Date: Fri, 18 Jan 2019 17:52:52 +0100 Subject: [PATCH 2/2] Fixed rendering issue on zoomout --- leaflet.polylineoffset.js | 374 +++++++++++++++++++------------------- 1 file changed, 190 insertions(+), 184 deletions(-) diff --git a/leaflet.polylineoffset.js b/leaflet.polylineoffset.js index d7cba53..f6f7b67 100644 --- a/leaflet.polylineoffset.js +++ b/leaflet.polylineoffset.js @@ -9,218 +9,224 @@ } }(function (L) { -function forEachPair(list, callback) { - if (!list || list.length < 1) { return; } - for (var i = 1, l = list.length; i < l; i++) { - callback(list[i-1], list[i]); - } -} - -/** -Find the coefficients (a,b) of a line of equation y = a.x + b, -or the constant x for vertical lines -Return null if there's no equation possible -*/ -function lineEquation(pt1, pt2) { - if (pt1.x === pt2.x) { - return pt1.y === pt2.y ? null : { x: pt1.x }; + function forEachPair(list, callback) { + if (!list || list.length < 1) { return; } + for (var i = 1, l = list.length; i < l; i++) { + callback(list[i-1], list[i]); + } } - var a = (pt2.y - pt1.y) / (pt2.x - pt1.x); - return { - a: a, - b: pt1.y - a * pt1.x, - }; -} - -/** -Return the intersection point of two lines defined by two points each -Return null when there's no unique intersection -*/ -function intersection(l1a, l1b, l2a, l2b) { - var line1 = lineEquation(l1a, l1b); - var line2 = lineEquation(l2a, l2b); - - if (line1 === null || line2 === null) { - return null; - } + /** + Find the coefficients (a,b) of a line of equation y = a.x + b, + or the constant x for vertical lines + Return null if there's no equation possible + */ + function lineEquation(pt1, pt2) { + if (pt1.x === pt2.x) { + return pt1.y === pt2.y ? null : { x: pt1.x }; + } - if (line1.hasOwnProperty('x')) { - return line2.hasOwnProperty('x') - ? null - : { - x: line1.x, - y: line2.a * line1.x + line2.b, - }; - } - if (line2.hasOwnProperty('x')) { + var a = (pt2.y - pt1.y) / (pt2.x - pt1.x); return { - x: line2.x, - y: line1.a * line2.x + line1.b, + a: a, + b: pt1.y - a * pt1.x, }; } - if (line1.a === line2.a) { - return null; - } + /** + Return the intersection point of two lines defined by two points each + Return null when there's no unique intersection + */ + function intersection(l1a, l1b, l2a, l2b) { + var line1 = lineEquation(l1a, l1b); + var line2 = lineEquation(l2a, l2b); + + if (line1 === null || line2 === null) { + return null; + } - var x = (line2.b - line1.b) / (line1.a - line2.a); - return { - x: x, - y: line1.a * x + line1.b, - }; -} - -function translatePoint(pt, dist, heading) { - return { - x: pt.x + dist * Math.cos(heading), - y: pt.y + dist * Math.sin(heading), - }; -} - -var PolylineOffset = { - offsetPointLine: function(points, distance) { - var offsetSegments = []; - - forEachPair(points, L.bind(function(a, b) { - if (a.x === b.x && a.y === b.y) { return; } - - // angles in (-PI, PI] - var segmentAngle = Math.atan2(a.y - b.y, a.x - b.x); - var offsetAngle = segmentAngle - Math.PI/2; - - offsetSegments.push({ - offsetAngle: offsetAngle, - original: [a, b], - offset: [ - translatePoint(a, distance, offsetAngle), - translatePoint(b, distance, offsetAngle) - ] - }); - }, this)); - - return offsetSegments; - }, - offsetPoints: function(pts, options) { - var offsetSegments = this.offsetPointLine(L.LineUtil.simplify(pts, options.smoothFactor), options.offset); - return this.joinLineSegments(offsetSegments, options.offset); - }, + if (line1.hasOwnProperty('x')) { + return line2.hasOwnProperty('x') + ? null + : { + x: line1.x, + y: line2.a * line1.x + line2.b, + }; + } + if (line2.hasOwnProperty('x')) { + return { + x: line2.x, + y: line1.a * line2.x + line1.b, + }; + } - /** - Join 2 line segments defined by 2 points each with a circular arc - */ - joinSegments: function(s1, s2, offset) { - // TODO: different join styles - return this.circularArc(s1, s2, offset) - .filter(function(x) { return x; }) - }, - - joinLineSegments: function(segments, offset) { - var joinedPoints = []; - var first = segments[0]; - var last = segments[segments.length - 1]; - - if (first && last) { - joinedPoints.push(first.offset[0]); - forEachPair(segments, L.bind(function(s1, s2) { - joinedPoints = joinedPoints.concat(this.joinSegments(s1, s2, offset)); - }, this)); - joinedPoints.push(last.offset[1]); + if (line1.a === line2.a) { + return null; } - return joinedPoints; - }, + var x = (line2.b - line1.b) / (line1.a - line2.a); + return { + x: x, + y: line1.a * x + line1.b, + }; + } + + function translatePoint(pt, dist, heading) { + + var reductor = function (dist) { + return dist / Math.pow(2, 18 - Window.map.getZoom()) + }; - segmentAsVector: function(s) { return { - x: s[1].x - s[0].x, - y: s[1].y - s[0].y, + x: pt.x + reductor(dist) * Math.cos(heading), + y: pt.y + reductor(dist) * Math.sin(heading), }; - }, + } - getSignedAngle: function(s1, s2) { - const a = this.segmentAsVector(s1); - const b = this.segmentAsVector(s2); - return Math.atan2(a.x * b.y - a.y * b.x, a.x * b.x + a.y * b.y); - }, + var PolylineOffset = { + offsetPointLine: function(points, distance) { + var offsetSegments = []; + + forEachPair(points, L.bind(function(a, b) { + if (a.x === b.x && a.y === b.y) { return; } + + // angles in (-PI, PI] + var segmentAngle = Math.atan2(a.y - b.y, a.x - b.x); + var offsetAngle = segmentAngle - Math.PI/2; + + offsetSegments.push({ + offsetAngle: offsetAngle, + original: [a, b], + offset: [ + translatePoint(a, distance, offsetAngle), + translatePoint(b, distance, offsetAngle) + ] + }); + }, this)); - /** - Interpolates points between two offset segments in a circular form - */ - circularArc: function(s1, s2, distance) { - // if the segments are the same angle, - // there should be a single join point - if (s1.offsetAngle === s2.offsetAngle) { - return [s1.offset[1]]; - } + return offsetSegments; + }, + + offsetPoints: function(pts, options) { + var offsetSegments = this.offsetPointLine(L.LineUtil.simplify(pts, options.smoothFactor), options.offset); + return this.joinLineSegments(offsetSegments, options.offset); + }, + + /** + Join 2 line segments defined by 2 points each with a circular arc + */ + joinSegments: function(s1, s2, offset) { + // TODO: different join styles + return this.circularArc(s1, s2, offset) + .filter(function(x) { return x; }) + }, + + joinLineSegments: function(segments, offset) { + var joinedPoints = []; + var first = segments[0]; + var last = segments[segments.length - 1]; + + if (first && last) { + joinedPoints.push(first.offset[0]); + forEachPair(segments, L.bind(function(s1, s2) { + joinedPoints = joinedPoints.concat(this.joinSegments(s1, s2, offset)); + }, this)); + joinedPoints.push(last.offset[1]); + } - const signedAngle = this.getSignedAngle(s1.offset, s2.offset); - // for inner angles, just find the offset segments intersection - if ((signedAngle * distance > 0) && - (signedAngle * this.getSignedAngle(s1.offset, [s1.offset[0], s2.offset[1]]) > 0)) { - return [intersection(s1.offset[0], s1.offset[1], s2.offset[0], s2.offset[1])]; - } + return joinedPoints; + }, - // draws a circular arc with R = offset distance, C = original meeting point - var points = []; - var center = s1.original[1]; - // ensure angles go in the anti-clockwise direction - var rightOffset = distance > 0; - var startAngle = rightOffset ? s2.offsetAngle : s1.offsetAngle; - var endAngle = rightOffset ? s1.offsetAngle : s2.offsetAngle; - // and that the end angle is bigger than the start angle - if (endAngle < startAngle) { - endAngle += Math.PI * 2; - } - var step = Math.PI / 8; - for (var alpha = startAngle; alpha < endAngle; alpha += step) { - points.push(translatePoint(center, distance, alpha)); - } - points.push(translatePoint(center, distance, endAngle)); + segmentAsVector: function(s) { + return { + x: s[1].x - s[0].x, + y: s[1].y - s[0].y, + }; + }, + + getSignedAngle: function(s1, s2) { + const a = this.segmentAsVector(s1); + const b = this.segmentAsVector(s2); + return Math.atan2(a.x * b.y - a.y * b.x, a.x * b.x + a.y * b.y); + }, + + /** + Interpolates points between two offset segments in a circular form + */ + circularArc: function(s1, s2, distance) { + // if the segments are the same angle, + // there should be a single join point + if (s1.offsetAngle === s2.offsetAngle) { + return [s1.offset[1]]; + } + + const signedAngle = this.getSignedAngle(s1.offset, s2.offset); + // for inner angles, just find the offset segments intersection + if ((signedAngle * distance > 0) && + (signedAngle * this.getSignedAngle(s1.offset, [s1.offset[0], s2.offset[1]]) > 0)) { + return [intersection(s1.offset[0], s1.offset[1], s2.offset[0], s2.offset[1])]; + } + + // draws a circular arc with R = offset distance, C = original meeting point + var points = []; + var center = s1.original[1]; + // ensure angles go in the anti-clockwise direction + var rightOffset = distance > 0; + var startAngle = rightOffset ? s2.offsetAngle : s1.offsetAngle; + var endAngle = rightOffset ? s1.offsetAngle : s2.offsetAngle; + // and that the end angle is bigger than the start angle + if (endAngle < startAngle) { + endAngle += Math.PI * 2; + } + var step = Math.PI / 8; + for (var alpha = startAngle; alpha < endAngle; alpha += step) { + points.push(translatePoint(center, distance, alpha)); + } + points.push(translatePoint(center, distance, endAngle)); - return rightOffset ? points.reverse() : points; + return rightOffset ? points.reverse() : points; + } } -} // Modify the L.Polyline class by overwriting the projection function -L.Polyline.include({ - _projectLatlngs: function (latlngs, result, projectedBounds) { - var isFlat = latlngs.length > 0 && latlngs[0] instanceof L.LatLng; - - if (isFlat) { - var ring = latlngs.map(L.bind(function(ll) { - var point = this._map.latLngToLayerPoint(ll); - if (projectedBounds) { - projectedBounds.extend(point); + L.Polyline.include({ + _projectLatlngs: function (latlngs, result, projectedBounds) { + var isFlat = latlngs.length > 0 && latlngs[0] instanceof L.LatLng; + + if (isFlat) { + var ring = latlngs.map(L.bind(function(ll) { + var point = this._map.latLngToLayerPoint(ll); + if (projectedBounds) { + projectedBounds.extend(point); + } + return point; + }, this)); + + // Offset management hack --- + if (this.options.offset) { + ring = L.PolylineOffset.offsetPoints(ring, this.options); } - return point; - }, this)); - - // Offset management hack --- - if (this.options.offset) { - ring = L.PolylineOffset.offsetPoints(ring, this.options); - } - // Offset management hack END --- + // Offset management hack END --- - result.push(ring.map(function (xy) { + result.push(ring.map(function (xy) { return L.point(xy.x, xy.y); })); - } else { - latlngs.forEach(L.bind(function(ll) { - this._projectLatlngs(ll, result, projectedBounds); - }, this)); + } else { + latlngs.forEach(L.bind(function(ll) { + this._projectLatlngs(ll, result, projectedBounds); + }, this)); + } } - } -}); + }); -L.Polyline.include({ - setOffset: function(offset) { - this.options.offset = offset; - this.redraw(); - return this; - } -}); + L.Polyline.include({ + setOffset: function(offset) { + this.options.offset = offset; + this.redraw(); + return this; + } + }); -return PolylineOffset; + return PolylineOffset; }, window));