🔮 abstracting tile handling, preparing usage of spatial indexing

This commit is contained in:
Michael Straßburger 2016-09-22 05:09:07 +02:00
parent 0877eaca86
commit 11c2f1f544
4 changed files with 84 additions and 58 deletions

View File

@ -12,10 +12,12 @@ require('coffee-script/register');
const fs = require('fs');
const Termap = require(__dirname+'/src/Termap');
const Tile = require(__dirname+'/src/Tile')
termap = new Termap();
// TODO: abstracing this class, create loader class
data = fs.readFileSync(__dirname+"/tiles/regensburg.pbf.gz");
termap.renderer.features = termap.renderer._getFeatures(termap.renderer._parseTile(data));
tile = new Tile(data);
termap.renderer.features = tile.layers
termap._draw();

View File

@ -5,9 +5,6 @@
The Console Vector Tile renderer - bäm!
###
x256 = require 'x256'
Protobuf = require 'pbf'
VectorTile = require('vector-tile').VectorTile
zlib = require 'zlib'
triangulator = new (require('pnltri')).Triangulator()
Canvas = require './Canvas'
@ -66,29 +63,6 @@ module.exports = class Renderer
setSize: (@width, @height) ->
@canvas = new Canvas @width, @height
_parseTile: (buffer) ->
# extract, decode and parse a given tile buffer
new VectorTile new Protobuf zlib.gunzipSync buffer
_getFeatures: (tile) ->
features = {}
for name,layer of tile.layers
continue unless @config.layers[name]
features[name] = for i in [0...layer.length]
feature = layer.feature i
type = [undefined, "Point", "LineString", "Polygon"][feature.type]
properties = feature.properties
properties.$type = type
id: feature.id
type: type
properties: properties
points: feature.loadGeometry()
features
draw: (@view, @zoom) ->
return if @isDrawing
@isDrawing = true
@ -118,51 +92,34 @@ module.exports = class Renderer
process.stdout.write output
_drawLayers: ->
drawn = []
for layer in @config.drawOrder
continue unless @features?[layer]
@notify "rendering #{layer}..."
scale = Math.pow 2, @zoom
continue unless @features?[layer]
if @config.layers[layer].minZoom and @zoom > @config.layers[layer].minZoom
continue
@canvas.strokeStyle = @canvas.fillStyle = @config.layers[layer].color
for feature in @features[layer]
if @_drawFeature layer, feature, scale
drawn.push feature
drawn
for feature in @features[layer].tree.search(minX: 0, minY: 0, maxX: 4096, maxY: 4096)
@_drawFeature layer, feature.data, scale
_drawFeature: (layer, feature, scale) ->
# TODO: this is ugly :) need to be fixed @style
#return false if feature.properties.class is "ferry"
feature.type = "LineString" if layer is "building" or layer is "road"
toDraw = []
for idx, points of feature.points
visible = false
projectedPoints = for point in points
projectedPoint =
x: point.x/scale
y: point.y/scale
visible = true if not visible and @_isOnScreen projectedPoint
projectedPoint
if idx is 0 and not visible
return false
continue unless visible
toDraw.push projectedPoints
# TODO: zoom level
unless style = @styler.getStyleFor layer, feature, 14
return false
color = style.paint['line-color'] or style.paint['fill-color'] or style.paint['text-color']
toDraw = for points in feature.points
for point in points
x: point.x/scale
y: point.y/scale
# TODO: zoom calculation todo for perfect styling
if color instanceof Object
color = color.stops[0][1]

View File

@ -39,10 +39,7 @@ module.exports = class Styler
false
_compileFilter: (filter) ->
if not filter or not filter.length
return -> true
switch filter[0]
switch filter?[0]
when "all"
filters = (@_compileFilter subFilter for subFilter in filter[1..])
(feature) ->
@ -64,3 +61,6 @@ module.exports = class Styler
(feature) ->
return false for value in filter[2..] when feature.properties[filter[1]] is value
true
else
-> true

67
src/Tile.coffee Normal file
View File

@ -0,0 +1,67 @@
###
termap - Terminal Map Viewer
by Michael Strassburger <codepoet@cpan.org>
Handling of and access to single VectorTiles
###
VectorTile = require('vector-tile').VectorTile
Protobuf = require 'pbf'
zlib = require 'zlib'
Rbush = require('rbush')
module.exports = class Tile
tree: null
layers: {}
constructor: (buffer, @styler = null) ->
@tree = new Rbush()
@tile = @_loadTile buffer
@_loadFeatures()
_loadTile: (buffer) ->
buffer = zlib.gunzipSync buffer if @_isGzipped buffer
new VectorTile new Protobuf buffer
_isGzipped: (buffer) ->
buffer.slice(0,2).indexOf(Buffer.from([0x1f, 0x8b])) is 0
_loadFeatures: ->
for name, layer of @tile.layers
tree = new Rbush()
features = for i in [0...layer.length]
# TODO: caching of similar attributes to avoid looking up the style each time
continue if @styler and not @styler.getStyleFor layer, feature
feature = layer.feature i
type = feature.properties.$type =
[undefined, "Point", "LineString", "Polygon"][feature.type]
data =
points: feature.loadGeometry()
properties: feature.properties
id: feature.id
type: type
@_addToTree tree, data
data
@layers[name] = tree: tree, features: features
_addToTree: (tree, data) ->
[minX, maxX, minY, maxY] = [Infinity, -Infinity, Infinity, -Infinity]
for outer in data.points
for p in outer
minX = p.x if p.x < minX
maxX = p.x if p.x > maxX
minY = p.y if p.y < minY
maxY = p.y if p.y > maxY
tree.insert
minX: minX
maxX: maxX
minY: minY
maxY: maxY
data: data