mirror of
https://github.com/rastapasta/mapscii.git
synced 2024-11-21 23:53:08 +01:00
🔥 initial commit!
This commit is contained in:
parent
14fa2a66bc
commit
44192bbbd0
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
bundle*
|
||||||
|
*.log
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# termap - Terminal Map
|
||||||
|
|
||||||
|
Discover the world in your console - render vector tile maps from any source!
|
||||||
|
|
||||||
|
## TODOs
|
||||||
|
* [ ] mapping of view to tiles to show
|
||||||
|
* [ ] tile request system
|
||||||
|
* [ ] from local mbtiles
|
||||||
|
* [ ] from remote url
|
||||||
|
* [ ] label drawing
|
||||||
|
* [ ] center+zoom based viewport
|
||||||
|
* [ ] zoom while keeping center
|
||||||
|
* [ ] API
|
||||||
|
* [ ] setCenter
|
||||||
|
* [ ] setZoom
|
||||||
|
* [x] accurate mouse drag&drop
|
||||||
|
|
||||||
|
## Wishlist
|
||||||
|
* node-gyp binding to [libdrawille](https://github.com/Huulivoide/libdrawille) for speed refactor possibilities + filled polygons
|
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "termap",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "OSM Terminal Map",
|
||||||
|
"main": "termap.coffee",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"console",
|
||||||
|
"map",
|
||||||
|
"terminal",
|
||||||
|
"map",
|
||||||
|
"osm",
|
||||||
|
"vector",
|
||||||
|
"tiles",
|
||||||
|
"mbtiles"
|
||||||
|
],
|
||||||
|
"author": "Michael Straßburger <codepoet@cpan.org>",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"drawille-canvas-blessed-contrib": "^0.1.3",
|
||||||
|
"keypress": "^0.2.1",
|
||||||
|
"pbf": "^3.0.0",
|
||||||
|
"term-mouse": "^0.1.1",
|
||||||
|
"vector-tile": "^1.3.0"
|
||||||
|
}
|
||||||
|
}
|
114
termap.coffee
Normal file
114
termap.coffee
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
Canvas = require 'drawille-canvas-blessed-contrib'
|
||||||
|
VectorTile = require('vector-tile').VectorTile
|
||||||
|
Protobuf = require 'pbf'
|
||||||
|
keypress = require 'keypress'
|
||||||
|
fs = require 'fs'
|
||||||
|
zlib = require 'zlib'
|
||||||
|
mouse = require('term-mouse')()
|
||||||
|
|
||||||
|
keypress process.stdin
|
||||||
|
|
||||||
|
width = Math.floor((process.stdout.columns-1)/2)*2*2;
|
||||||
|
height = Math.ceil(process.stdout.rows/4)*4*4;
|
||||||
|
|
||||||
|
drawOrder = ["admin", "water", "landuse", "building", "road"]
|
||||||
|
layers =
|
||||||
|
road: "white"
|
||||||
|
landuse: "green"
|
||||||
|
water: "blue"
|
||||||
|
admin: "red"
|
||||||
|
building: 8
|
||||||
|
|
||||||
|
canvas = new Canvas width, height
|
||||||
|
|
||||||
|
features = {}
|
||||||
|
data = fs.readFileSync __dirname+"/tiles/regensburg.pbf.gz"
|
||||||
|
zlib.gunzip data, (err, buffer) ->
|
||||||
|
throw new Error err if err
|
||||||
|
|
||||||
|
tile = new VectorTile new Protobuf buffer
|
||||||
|
for name,layer of tile.layers
|
||||||
|
if layers[name]
|
||||||
|
features[name] = []
|
||||||
|
for i in [0...layer.length]
|
||||||
|
features[name].push layer.feature(i).loadGeometry()
|
||||||
|
|
||||||
|
draw()
|
||||||
|
|
||||||
|
zoom = 0
|
||||||
|
view = [-400, -80]
|
||||||
|
size = 4
|
||||||
|
|
||||||
|
flush = ->
|
||||||
|
process.stdout.write canvas._canvas.frame()
|
||||||
|
|
||||||
|
draw = ->
|
||||||
|
canvas.clearRect(0, 0, width, height)
|
||||||
|
|
||||||
|
canvas.save()
|
||||||
|
|
||||||
|
canvas.translate view[0], view[1]
|
||||||
|
for layer in drawOrder
|
||||||
|
continue unless features[layer]
|
||||||
|
|
||||||
|
canvas.strokeStyle = layers[layer]
|
||||||
|
for feature in features[layer]
|
||||||
|
for line in feature
|
||||||
|
found = false
|
||||||
|
points = for point in line
|
||||||
|
p = [point.x/size, point.y/size]
|
||||||
|
if not found and p[0]+view[0]>=0 and p[0]+view[0]<width and p[1]+view[1]>=0 and p[1]+view[1]<height
|
||||||
|
found = true
|
||||||
|
p
|
||||||
|
continue unless found
|
||||||
|
|
||||||
|
canvas.beginPath()
|
||||||
|
canvas.moveTo points.shift()...
|
||||||
|
canvas.lineTo point... for point in points
|
||||||
|
canvas.stroke()
|
||||||
|
|
||||||
|
canvas.restore()
|
||||||
|
flush()
|
||||||
|
|
||||||
|
|
||||||
|
moving = null
|
||||||
|
process.stdin.on 'mousepress', (info) ->
|
||||||
|
# TODO: file bug @keypress, fails after x>95 / sequence: '\u001b[M#B'
|
||||||
|
if info.x > 2048
|
||||||
|
info.x = 100
|
||||||
|
|
||||||
|
switch info.scroll
|
||||||
|
when -1
|
||||||
|
size -= .2
|
||||||
|
when 1
|
||||||
|
size += .2
|
||||||
|
|
||||||
|
if info.button is 0
|
||||||
|
moving = info
|
||||||
|
|
||||||
|
else if moving and info.release
|
||||||
|
view[0] -= (moving.x-info.x)*2
|
||||||
|
view[1] -= (moving.y-info.y)*4
|
||||||
|
moving = null
|
||||||
|
|
||||||
|
draw()
|
||||||
|
|
||||||
|
process.stdin.on 'keypress', (ch, key) ->
|
||||||
|
result = switch key?.name
|
||||||
|
when "q"
|
||||||
|
process.exit 0
|
||||||
|
|
||||||
|
when "a" then size += 1
|
||||||
|
when "z" then size -= 1
|
||||||
|
when "left" then view[0] += 5
|
||||||
|
when "right" then view[0] -= 5
|
||||||
|
when "up" then view[1]+= 5
|
||||||
|
when "down" then view[1]-= 5
|
||||||
|
|
||||||
|
else
|
||||||
|
false
|
||||||
|
|
||||||
|
draw() if result
|
||||||
|
|
||||||
|
process.stdin.setRawMode(true)
|
||||||
|
process.stdin.resume()
|
BIN
tiles/regensburg.pbf.gz
Normal file
BIN
tiles/regensburg.pbf.gz
Normal file
Binary file not shown.
BIN
tiles/world.pbf.gz
Normal file
BIN
tiles/world.pbf.gz
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user