🏃 implementing polyline simplification, label buffering, cleanup

This commit is contained in:
Michael Straßburger 2016-11-10 06:11:14 +01:00
parent caea4c6aec
commit ae65f95e24
2 changed files with 50 additions and 64 deletions

View File

@ -4,9 +4,9 @@
The Console Vector Tile renderer - bäm! The Console Vector Tile renderer - bäm!
### ###
tilebelt = require 'tilebelt'
Promise = require 'bluebird' Promise = require 'bluebird'
x256 = require 'x256' x256 = require 'x256'
simplify = require 'simplify-js'
Canvas = require './Canvas' Canvas = require './Canvas'
LabelBuffer = require './LabelBuffer' LabelBuffer = require './LabelBuffer'
@ -14,8 +14,6 @@ Styler = require './Styler'
Tile = require './Tile' Tile = require './Tile'
utils = require './utils' utils = require './utils'
#simplify = require 'simplify-js'
module.exports = class Renderer module.exports = class Renderer
config: config:
language: 'en' language: 'en'
@ -87,19 +85,19 @@ module.exports = class Renderer
_visibleTiles: (center, zoom) -> _visibleTiles: (center, zoom) ->
z = Math.min @config.maxZoom, Math.max 0, Math.floor zoom z = Math.min @config.maxZoom, Math.max 0, Math.floor zoom
xyz = tilebelt.pointToTileFraction center.lon, center.lat, z center = utils.ll2tile center.lon, center.lat, z
tiles = [] tiles = []
scale = @_scaleAtZoom zoom scale = @_scaleAtZoom zoom
tileSize = @config.tileSize / scale tileSize = @config.tileSize / scale
for y in [Math.floor(xyz[1])-1..Math.floor(xyz[1])+1] for y in [Math.floor(center.y)-1..Math.floor(center.y)+1]
for x in [Math.floor(xyz[0])-1..Math.floor(xyz[0])+1] for x in [Math.floor(center.x)-1..Math.floor(center.x)+1]
tile = x: x, y: y, z: z tile = x: x, y: y, z: z
position = position =
x: @width/2-(xyz[0]-tile.x)*tileSize x: @width/2-(center.x-tile.x)*tileSize
y: @height/2-(xyz[1]-tile.y)*tileSize y: @height/2-(center.y-tile.y)*tileSize
gridSize = Math.pow 2, z gridSize = Math.pow 2, z
@ -175,7 +173,8 @@ module.exports = class Renderer
_drawFeature: (tile, feature) -> _drawFeature: (tile, feature) ->
if feature.style.minzoom and tile.zoom < feature.style.minzoom if feature.style.minzoom and tile.zoom < feature.style.minzoom
return false return false
else if feature.style.maxzoom and tile.zoom > feature.style.maxzoom
return false
switch feature.style.type switch feature.style.type
when "line" when "line"
@ -197,53 +196,49 @@ module.exports = class Renderer
feature.properties["name_en"] or feature.properties["name_en"] or
feature.properties["name"] or feature.properties["name"] or
feature.properties.house_num or feature.properties.house_num or
"" genericSymbol = ""
points = @_scaleAndReduce tile, feature, feature.points return false if @_seen[text] and not genericSymbol
for point in points
x = point[0] - text.length placed = false
for point in @_scaleAndReduce tile, feature, feature.points
x = point.x - text.length
margin = @config.layers[feature.layer]?.margin or @config.labelMargin margin = @config.layers[feature.layer]?.margin or @config.labelMargin
if @labelBuffer.writeIfPossible text, x, point[1], feature, margin if @labelBuffer.writeIfPossible text, x, point.y, feature, margin
@canvas.text text, x, point[1], feature.color @canvas.text text, x, point.y, feature.color
placed = true
break break
else if @config.layers[feature.layer]?.cluster and else if @config.layers[feature.layer]?.cluster and
@labelBuffer.writeIfPossible "X", point[0], point[1], feature, 3 @labelBuffer.writeIfPossible "", point.x, point.y, feature, 3
@canvas.text "", point[0], point[1], feature.color @canvas.text "", point.x, point.y, feature.color
placed = true
break break
@_seen[text] = true if placed
true true
_seen: {}
_scaleAndReduce: (tile, feature, points, filter = true) -> _scaleAndReduce: (tile, feature, points, filter = true) ->
lastX = null lastX = lastY = outside = null
lastY = null
outside = false
scaled = [] scaled = []
# seen = {}
minX = minY = -@tilePadding
maxX = @width+@tilePadding
maxY = @height+@tilePadding
for point in points for point in points
x = Math.floor tile.position.x+(point.x/tile.scale) x = Math.floor tile.position.x+(point.x/tile.scale)
y = Math.floor tile.position.y+(point.y/tile.scale) y = Math.floor tile.position.y+(point.y/tile.scale)
if lastX is x and lastY is y continue if lastX is x and lastY is y
continue
lastY = y lastY = y
lastX = x lastX = x
# TODO: benchmark
# continue if seen[idx = (y<<8)+x]
# seen[idx] = true
if filter if filter
if ( if x < minX or x > maxX or y < minY or y > maxY
x < -@tilePadding or
y < -@tilePadding or
x > @width+@tilePadding or
y > @height+@tilePadding
)
continue if outside continue if outside
outside = true outside = true
else else
@ -251,23 +246,15 @@ module.exports = class Renderer
outside = null outside = null
scaled.push [lastX, lastY] scaled.push [lastX, lastY]
scaled.push [x, y] #x: x, y: y scaled.push x: x, y: y
if scaled.length < 2 if feature.style.type isnt "symbol"
if feature.style.type isnt "symbol" if scaled.length < 2
return [] return []
# else
# scaled = ([point.x, point.y] for point in simplify scaled, 2, false)
#
# if filter
# if scaled.length is 2
# if @_seen[ka = (scaled[0]<<8)+scaled[1]] or
# @_seen[kb = (scaled[1]<<8)+scaled[0]]
# return []
#
# @_seen[ka] = @_seen[kb] = true
scaled simplify scaled, .5
else
scaled
_generateDrawOrder: (zoom) -> _generateDrawOrder: (zoom) ->
if zoom < 2 if zoom < 2

View File

@ -191,18 +191,12 @@ module.exports = class Termap
setImmediate => @_draw() setImmediate => @_draw()
_getFooter: -> _getFooter: ->
# features = @renderer.featuresAt @mousePosition.x-1-(@view[0]>>1), @mousePosition.y-1-(@view[1]>>2) # tile = utils.ll2tile @center.lon, @center.lat, @zoom
# "features: ["+features.map((f) -> # "tile: #{utils.digits tile.x, 3}, #{utils.digits tile.x, 3} "+
# JSON.stringify
# name: f.feature.properties.name
# type: f.feature.properties.type
# rank: f.feature.properties.scalerank
# ).join(", ")+"] "+
#{}"#{@mousePosition.x} #{@mousePosition.y} " +
# bbox = @_getBBox()
# tiles = @_tilesInBBox(bbox)
"center: #{utils.digits @center.lat, 3}, #{utils.digits @center.lon, 3} "+ "center: #{utils.digits @center.lat, 3}, #{utils.digits @center.lon, 3} "+
"zoom: #{utils.digits @zoom, 2} " "zoom: #{utils.digits @zoom, 2} "+
"mouse: #{@mousePosition.x} #{@mousePosition.y} "+
notify: (text) -> notify: (text) ->
@_write "\r\x1B[K"+text unless @config.headless @_write "\r\x1B[K"+text unless @config.headless
@ -217,9 +211,14 @@ module.exports = class Termap
@zoom += step @zoom += step
moveBy: (lat, lon) -> moveBy: (lat, lon) ->
@center.lat += lat @setCenter @center.lat+lat, @center.lon+lon
@center.lon += lon
@center.lon = (@center.lon+180)%360-180 setCenter: (lat, lon) ->
@center.lat = 85.0511 if @center.lat > 85.0511 lon += 360 if lon < -180
@center.lat = -85.0511 if @center.lat < -85.0511 lon -= 360 if lon > 180
lat = 85.0511 if lat > 85.0511
lat = -85.0511 if lat < -85.0511
@center.lat = lat
@center.lon = lon