mirror of
https://github.com/rastapasta/mapscii.git
synced 2024-11-22 08:03:07 +01:00
🏃 implementing polyline simplification, label buffering, cleanup
This commit is contained in:
parent
caea4c6aec
commit
ae65f95e24
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user