loleaflet/src/layer/tile/TileLayer.js | 174 +++++++++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 11 deletions(-)
New commits: commit bcdf048d6d2cd089ef5fdb1b8b3af0eb0e214682 Author: Mihai Varga <mihai.va...@collabora.com> Date: Mon May 25 16:54:29 2015 +0300 Merge adjacent selection rectangles into a single polygon + the document is scrolled to the average center of the rectangles if that is out of the viewing area diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js index 8875565..1afc87d 100644 --- a/loleaflet/src/layer/tile/TileLayer.js +++ b/loleaflet/src/layer/tile/TileLayer.js @@ -152,21 +152,32 @@ L.TileLayer = L.GridLayer.extend({ this._clearSelections(); if (strTwips != null) { this._map.fire('searchfound'); + var rectangles = []; + var selectionCenter = new L.Point(0,0); for (var i = 0; i < strTwips.length; i += 4) { var topLeftTwips = new L.Point(parseInt(strTwips[i]), parseInt(strTwips[i+1])); var offset = new L.Point(parseInt(strTwips[i+2]), parseInt(strTwips[i+3])); + var topRightTwips = topLeftTwips.add(new L.Point(offset.x, 0)); + var bottomLeftTwips = topLeftTwips.add(new L.Point(0, offset.y)); var bottomRightTwips = topLeftTwips.add(offset); - var bounds = new L.LatLngBounds( - this._twipsToLatLng(topLeftTwips), - this._twipsToLatLng(bottomRightTwips)); - if (!this._map.getBounds().contains(bounds.getCenter())) { - var center = this._map.project(bounds.getCenter()); - center = center.subtract(this._map.getSize().divideBy(2)); - center.x = center.x < 0 ? 0 : center.x; - center.y = center.y < 0 ? 0 : center.y; - $('#scroll-container').mCustomScrollbar('scrollTo', [center.y, center.x]); - } - var selection = new L.Rectangle(bounds, { + rectangles.push([bottomLeftTwips, bottomRightTwips, topLeftTwips, topRightTwips]); + selectionCenter = selectionCenter.add(topLeftTwips); + selectionCenter = selectionCenter.add(offset.divideBy(2)); + } + // average of all rectangles' centers + selectionCenter = selectionCenter.divideBy(strTwips.length / 4); + selectionCenter = this._twipsToLatLng(selectionCenter); + if (!this._map.getBounds().contains(selectionCenter)) { + var center = this._map.project(selectionCenter); + center = center.subtract(this._map.getSize().divideBy(2)); + center.x = center.x < 0 ? 0 : center.x; + center.y = center.y < 0 ? 0 : center.y; + $('#scroll-container').mCustomScrollbar('scrollTo', [center.y, center.x]); + } + + var polygons = this._rectanglesToPolygons(rectangles); + for (var i = 0; i < polygons.length; i++) { + var selection = new L.Polygon(polygons[i], { fillColor: '#43ACE8', fillOpacity: 0.25, weight: 2, @@ -256,6 +267,147 @@ L.TileLayer = L.GridLayer.extend({ } }, + _rectanglesToPolygons: function(rectangles) { + // algorithm found here http://stackoverflow.com/questions/13746284/merging-multiple-adjacent-rectangles-into-one-polygon + var eps = 20; + // Glue rectangles if the space between them is less then eps + for (var i = 0; i < rectangles.length - 1; i++) { + for (var j = i + 1; j < rectangles.length; j++) { + for (var k = 0; k < rectangles[i].length; k++) { + for (var l = 0; l < rectangles[j].length; l++) { + if (Math.abs(rectangles[i][k].x - rectangles[j][l].x) < eps) { + rectangles[j][l].x = rectangles[i][k].x; + } + if (Math.abs(rectangles[i][k].y - rectangles[j][l].y) < eps) { + rectangles[j][l].y = rectangles[i][k].y; + } + } + } + } + } + + points = {}; + for (var i = 0; i < rectangles.length; i++) { + for (var j = 0; j < rectangles[i].length; j++) { + if (points[rectangles[i][j]]) { + delete points[rectangles[i][j]]; + } + else { + points[rectangles[i][j]] = rectangles[i][j]; + } + } + } + + function getKeys(points) { + keys = []; + for (var key in points) { + if (points.hasOwnProperty(key)) { + keys.push(key); + } + } + return keys; + } + + function x_then_y(a_str, b_str) { + a = a_str.match(/\d+/g); + a[0] = parseInt(a[0]); + a[1] = parseInt(a[1]); + b = b_str.match(/\d+/g); + b[0] = parseInt(b[0]); + b[1] = parseInt(b[1]); + + if (a[0] < b[0] || (a[0] == b[0] && a[1] < b[1])) { + return -1; + } + else if (a[0] == b[0] && a[1] == b[1]) { + return 0; + } + else { + return 1; + } + } + + function y_then_x(a_str, b_str) { + a = a_str.match(/\d+/g); + a[0] = parseInt(a[0]); + a[1] = parseInt(a[1]); + b = b_str.match(/\d+/g); + b[0] = parseInt(b[0]); + b[1] = parseInt(b[1]); + + if (a[1] < b[1] || (a[1] == b[1] && a[0] < b[0])) { + return -1; + } + else if (a[0] == b[0] && a[1] == b[1]) { + return 0; + } + else { + return 1; + } + } + + sort_x = getKeys(points).sort(x_then_y); + sort_y = getKeys(points).sort(y_then_x); + + edges_h = {}; + edges_v = {}; + + var len = getKeys(points).length; + var i = 0; + while (i < len) { + var curr_y = points[sort_y[i]].y; + while (i < len && points[sort_y[i]].y === curr_y) { + edges_h[sort_y[i]] = sort_y[i+1]; + edges_h[sort_y[i+1]] = sort_y[i]; + i += 2; + } + } + + i = 0; + while (i < len) { + var curr_x = points[sort_x[i]].x; + while (i < len && points[sort_x[i]].x === curr_x) { + edges_v[sort_x[i]] = sort_x[i+1]; + edges_v[sort_x[i+1]] = sort_x[i]; + i += 2; + } + } + + var polygons = []; + var edges_h_keys = getKeys(edges_h); + while (edges_h_keys.length > 0) { + var p = [[edges_h_keys[0], 0]]; + while (true) { + var curr = p[p.length - 1][0]; + var e = p[p.length - 1][1]; + if (e === 0) { + var next_vertex = edges_v[curr]; + delete edges_v[curr]; + p.push([next_vertex, 1]); + } + else { + var next_vertex = edges_h[curr]; + delete edges_h[curr]; + p.push([next_vertex, 0]); + } + if (p[p.length - 1][0] === p[0][0] && p[p.length - 1][1] === p[0][1]) { + p.pop(); + break; + } + } + var polygon = []; + for (var i = 0; i < p.length; i++) { + polygon.push(this._twipsToLatLng(points[p[i][0]])); + delete edges_h[p[i][0]]; + delete edges_v[p[i][0]]; + } + polygon.push(this._twipsToLatLng(points[p[0][0]])); + edges_h_keys = getKeys(edges_h); + polygons.push(polygon); + } + return polygons; + }, + _clearSelections: function () { this._selections.clearLayers(); }, _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits