diff --git a/README.md b/README.md index bd6c141..a0b93d0 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Discover the world in your console! * [`node-mbtiles`](https://github.com/mapbox/node-mbtiles) for MBTiles parsing * [`pbf`](https://github.com/mapbox/pbf) for Protobuf decoding * [`vector-tile-js`](https://github.com/mapbox/vector-tile-js) for [VectorTile](https://github.com/mapbox/vector-tile-spec/tree/master/2.1) parsing +* [`rbush`](https://github.com/mourner/rbush) for 2D spatial indexing * [`sphericalmercator`](https://github.com/mapbox/node-sphericalmercator) for EPSG:3857 <> WGS84 conversions ## Wishlist @@ -41,8 +42,11 @@ Discover the world in your console! * [ ] mapping of view to tiles to show * [ ] label drawing * [x] support for point labels - * [ ] dynamic decluttering of labels + * [x] dynamic decluttering of labels + * [ ] centering text labels * [ ] lat/lng-center + zoom based viewport + * [ ] bbox awareness + * [ ] zoom -> scale calculation * [ ] TileSource class (abstracting URL, mbtiles, single vector tile source) * [ ] tile request system * [ ] from local mbtiles diff --git a/package.json b/package.json index e6b662c..3245a7a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "drawille-canvas-blessed-contrib": "^0.1.3", "keypress": "^0.2.1", "pbf": "^3.0.0", + "rbush": "^2.0.1", "sphericalmercator": "^1.0.5", "term-mouse": "^0.1.1", "vector-tile": "^1.3.0" diff --git a/src/LabelBuffer.coffee b/src/LabelBuffer.coffee new file mode 100644 index 0000000..2c46f29 --- /dev/null +++ b/src/LabelBuffer.coffee @@ -0,0 +1,27 @@ +rbush = require 'rbush' + +module.exports = class LabelBuffer + tree: null + margin: 1 + + constructor: (@width, @height) -> + @tree = rbush() + + project: (x, y) -> + [Math.floor(x/2), Math.floor(y/4)] + + writeIfPossible: (text, x, y) -> + point = @project x, y + + return false unless @_hasSpace text, point[0], point[1] + @tree.insert @_calculateArea text, point[0], point[1] + true + + _hasSpace: (text, x, y) -> + not @tree.collides @_calculateArea text, x, y + + _calculateArea: (text, x, y) -> + minX: x-@margin + minY: y-@margin + maxX: x+@margin+text.length + maxY: y+@margin diff --git a/termap.coffee b/termap.coffee index 109943e..5b1f25b 100644 --- a/termap.coffee +++ b/termap.coffee @@ -6,6 +6,7 @@ fs = require 'fs' zlib = require 'zlib' TermMouse = require 'term-mouse' mercator = new (require('sphericalmercator'))() +LabelBuffer = require __dirname+'/src/LabelBuffer' utils = deg2rad: (angle) -> @@ -16,12 +17,10 @@ utils = digits: (number, digits) -> Math.floor(number*Math.pow(10, digits))/Math.pow(10, digits) + metersPerPixel: (zoom, lat = 0) -> utils.rad2deg(40075017*Math.cos(utils.deg2rad(lat))/Math.pow(2, zoom+8)) -console.log utils.metersPerPixel(16, 180) -process.exit 0 - class Termap config: @@ -84,7 +83,7 @@ class Termap lat: 49.019855 lng: 12.096956 - zoom: 0 + zoom: 2 view: [-400, -80] scale: 4 @@ -198,6 +197,9 @@ class Termap scale = Math.pow 2, @zoom + drawn = [] + labelBuffer = new LabelBuffer() + for layer in @config.drawOrder continue unless @features?[layer] @@ -212,25 +214,30 @@ class Termap visible = false points = for point in points p = [point.x/scale, point.y/scale] - if not visible and - p[0]+@view[0]>=4 and - p[0]+@view[0]<@width-4 and - p[1]+@view[1]>=0 and - p[1]+@view[1]<@height - visible = true + if not visible and @_isOnScreen p + visible = true p continue unless visible + wasDrawn = false switch feature.type when "polygon", "line" @canvas.beginPath() @canvas.moveTo points.shift()... @canvas.lineTo point... for point in points @canvas.stroke() + wasDrawn = true when "point" text = feature.properties.house_num or @config.icons[feature.properties.maki] or "◉" - @canvas.fillText text, point... for point in points + + for point in points + if labelBuffer.writeIfPossible text, point... + @canvas.fillText text, point... + wasDrawn = true + + if wasDrawn + drawn.push feature @canvas.restore() @@ -239,6 +246,12 @@ class Termap @isDrawing = false + _isOnScreen: (point) -> + point[0]+@view[0]>=4 and + point[0]+@view[0]<@width-4 and + point[1]+@view[1]>=0 and + point[1]+@view[1]<@height + _write: (text) -> process.stdout.write text diff --git a/tiles/europe.pbf.gz b/tiles/europe.pbf.gz new file mode 100644 index 0000000..03664c4 Binary files /dev/null and b/tiles/europe.pbf.gz differ