mirror of
https://github.com/rastapasta/mapscii.git
synced 2025-02-16 09:29:13 +01:00
🎨 adding simplify-js to readme, adapting canvas
This commit is contained in:
parent
ae65f95e24
commit
2d7cff71eb
@ -58,10 +58,9 @@ If your terminal supports mouse events you can drag the map and use your scroll
|
|||||||
|
|
||||||
#### Juggling the vectors and numbers
|
#### Juggling the vectors and numbers
|
||||||
* [`earcut`](https://github.com/mapbox/earcut) for polygon triangulation
|
* [`earcut`](https://github.com/mapbox/earcut) for polygon triangulation
|
||||||
* [`rbush`](https://github.com/mourner/rbush) for 2D spatial indexing based label and mouse collision detection
|
* [`rbush`](https://github.com/mourner/rbush) for 2D spatial indexing of geo and label data
|
||||||
* [`breseham`](https://github.com/madbence/node-bresenham) for line calculations
|
* [`breseham`](https://github.com/madbence/node-bresenham) for line point calculations
|
||||||
* [`sphericalmercator`](https://github.com/mapbox/node-sphericalmercator) for [EPSG:3857](http://spatialreference.org/ref/sr-org/6864/) <> [WGS84](http://spatialreference.org/ref/epsg/wgs-84/) conversions
|
* [`simplify-js`](https://github.com/mourner/simplify-js) for polyline simplifications
|
||||||
* [`tilebelt`](https://github.com/mapbox/tilebelt) for some [slippy map tilename](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) calculations
|
|
||||||
|
|
||||||
#### Handling the flow
|
#### Handling the flow
|
||||||
* [`bluebird`](https://github.com/petkaantonov/bluebird) for all the asynchronous [Promise](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise) magic
|
* [`bluebird`](https://github.com/petkaantonov/bluebird) for all the asynchronous [Promise](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise) magic
|
||||||
|
@ -35,9 +35,8 @@
|
|||||||
"rbush": "^2.0.1",
|
"rbush": "^2.0.1",
|
||||||
"request": "^2.76.0",
|
"request": "^2.76.0",
|
||||||
"request-promise": "^4.1.1",
|
"request-promise": "^4.1.1",
|
||||||
"sphericalmercator": "^1.0.5",
|
"simplify-js": "^1.2.1",
|
||||||
"term-mouse": "^0.1.1",
|
"term-mouse": "^0.1.1",
|
||||||
"tilebelt": "^1.0.1",
|
|
||||||
"userhome": "^1.0.0",
|
"userhome": "^1.0.0",
|
||||||
"vector-tile": "^1.3.0",
|
"vector-tile": "^1.3.0",
|
||||||
"x256": "0.0.2"
|
"x256": "0.0.2"
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
###
|
###
|
||||||
|
|
||||||
bresenham = require 'bresenham'
|
bresenham = require 'bresenham'
|
||||||
|
simplify = require 'simplify-js'
|
||||||
|
|
||||||
earcut = require 'earcut'
|
earcut = require 'earcut'
|
||||||
BrailleBuffer = require './BrailleBuffer'
|
BrailleBuffer = require './BrailleBuffer'
|
||||||
utils = require './utils'
|
utils = require './utils'
|
||||||
@ -32,11 +34,11 @@ module.exports = class Canvas
|
|||||||
@buffer.writeText text, x, y, color, center
|
@buffer.writeText text, x, y, color, center
|
||||||
|
|
||||||
line: (from, to, color, width = 1) ->
|
line: (from, to, color, width = 1) ->
|
||||||
@_line from, to, color, width
|
@_line from.x, from.y, to.x, to.y, color, width
|
||||||
|
|
||||||
polyline: (points, color, width = 1) ->
|
polyline: (points, color, width = 1) ->
|
||||||
for i in [1...points.length]
|
for i in [1...points.length]
|
||||||
@_line points[i-1], points[i], width, color
|
@_line points[i-1].x, points[i-1].y, points[i].x, points[i].y, width, color
|
||||||
|
|
||||||
setBackground: (color) ->
|
setBackground: (color) ->
|
||||||
@buffer.setGlobalBackground color
|
@buffer.setGlobalBackground color
|
||||||
@ -53,37 +55,38 @@ module.exports = class Canvas
|
|||||||
continue if ring.length < 3
|
continue if ring.length < 3
|
||||||
holes.push vertices.length/2
|
holes.push vertices.length/2
|
||||||
else
|
else
|
||||||
return if ring.length < 3
|
return false if ring.length < 3
|
||||||
|
|
||||||
for point in ring
|
for point in ring
|
||||||
vertices = vertices.concat point
|
vertices.push point.x
|
||||||
|
vertices.push point.y
|
||||||
|
|
||||||
try
|
try
|
||||||
triangles = earcut vertices, holes
|
triangles = earcut vertices, holes
|
||||||
catch e
|
catch e
|
||||||
return false
|
return false
|
||||||
|
|
||||||
extract = (pointId) ->
|
|
||||||
[vertices[pointId*2], vertices[pointId*2+1]]
|
|
||||||
|
|
||||||
for i in [0...triangles.length] by 3
|
for i in [0...triangles.length] by 3
|
||||||
pa = extract(triangles[i])
|
pa = @_polygonExtract vertices, triangles[i]
|
||||||
pb = extract(triangles[i+1])
|
pb = @_polygonExtract vertices, triangles[i+1]
|
||||||
pc = extract(triangles[i+2])
|
pc = @_polygonExtract vertices, triangles[i+2]
|
||||||
|
|
||||||
@_filledTriangle pa, pb, pc, color
|
@_filledTriangle pa, pb, pc, color
|
||||||
|
|
||||||
|
true
|
||||||
|
|
||||||
|
_polygonExtract: (vertices, pointId) ->
|
||||||
|
[vertices[pointId*2], vertices[pointId*2+1]]
|
||||||
|
|
||||||
# Inspired by Alois Zingl's "The Beauty of Bresenham's Algorithm"
|
# Inspired by Alois Zingl's "The Beauty of Bresenham's Algorithm"
|
||||||
# -> http://members.chello.at/~easyfilter/bresenham.html
|
# -> http://members.chello.at/~easyfilter/bresenham.html
|
||||||
_line: (pointA, pointB, width, color) ->
|
_line: (x0, y0, x1, y1, width, color) ->
|
||||||
|
|
||||||
# Fall back to width-less bresenham algorithm if we dont have a width
|
# Fall back to width-less bresenham algorithm if we dont have a width
|
||||||
unless width = Math.max 0, width-1
|
unless width = Math.max 0, width-1
|
||||||
return bresenham pointA[0], pointA[1], pointB[0], pointB[1],
|
return bresenham x0, y0, x1, y1,
|
||||||
(x, y) => @buffer.setPixel x, y, color
|
(x, y) => @buffer.setPixel x, y, color
|
||||||
|
|
||||||
[x0, y0] = pointA
|
|
||||||
[x1, y1] = pointB
|
|
||||||
dx = Math.abs x1-x0
|
dx = Math.abs x1-x0
|
||||||
sx = if x0 < x1 then 1 else -1
|
sx = if x0 < x1 then 1 else -1
|
||||||
dy = Math.abs y1-y0
|
dy = Math.abs y1-y0
|
||||||
@ -138,16 +141,9 @@ module.exports = class Canvas
|
|||||||
b = @_bresenham pointA, pointC
|
b = @_bresenham pointA, pointC
|
||||||
c = @_bresenham pointA, pointB
|
c = @_bresenham pointA, pointB
|
||||||
|
|
||||||
# Filter out any points outside of the visible area
|
|
||||||
# TODO: benchmark - is it more effective to filter double points, or does
|
|
||||||
# it req more computing time than actually setting points multiple times?
|
|
||||||
last = null
|
|
||||||
points = a.concat(b).concat(c)
|
points = a.concat(b).concat(c)
|
||||||
.filter (point) => 0 <= point.y < @height
|
.filter (point) => 0 <= point.y < @height
|
||||||
.sort (a, b) -> if a.y is b.y then a.x - b.x else a.y-b.y
|
.sort (a, b) -> if a.y is b.y then a.x - b.x else a.y-b.y
|
||||||
.filter (point) ->
|
|
||||||
[lastPoint, last] = [last, point]
|
|
||||||
not lastPoint or lastPoint.x isnt point.x or lastPoint.y isnt point.y
|
|
||||||
|
|
||||||
for i in [0...points.length]
|
for i in [0...points.length]
|
||||||
point = points[i]
|
point = points[i]
|
||||||
@ -155,8 +151,8 @@ module.exports = class Canvas
|
|||||||
|
|
||||||
if point.y is next?.y
|
if point.y is next?.y
|
||||||
left = Math.max 0, point.x
|
left = Math.max 0, point.x
|
||||||
right = Math.min @width, next.x
|
right = Math.min @width-1, next.x
|
||||||
if left and right
|
if left >= 0 and right <= @width
|
||||||
@buffer.setPixel x, point.y, color for x in [left..right]
|
@buffer.setPixel x, point.y, color for x in [left..right]
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
methods used all around
|
methods used all around
|
||||||
###
|
###
|
||||||
mercator = new (require('sphericalmercator'))()
|
|
||||||
|
|
||||||
constants =
|
constants =
|
||||||
RADIUS: 6378137
|
RADIUS: 6378137
|
||||||
|
|
||||||
@ -13,29 +11,14 @@ utils =
|
|||||||
clamp: (num, min, max) ->
|
clamp: (num, min, max) ->
|
||||||
if num <= min then min else if num >= max then max else num
|
if num <= min then min else if num >= max then max else num
|
||||||
|
|
||||||
# Based on W. Randolph Franklin (WRF)'s Point Inclusion in Polygon Test
|
deg2rad: (angle) ->
|
||||||
# https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
# (angle / 180) * Math.PI
|
||||||
pointInPolygon: (polygon, point) ->
|
angle * 0.017453292519943295
|
||||||
inside = false
|
|
||||||
j = polygon.length-1
|
|
||||||
for i in [0...polygon.length]
|
|
||||||
if (polygon[i][1]>point[1]) isnt (polygon[j][1]>point[1]) and
|
|
||||||
point[0] < (polygon[j][0]-polygon[i][0]) * (point[1]-polygon[i][1]) / (polygon[j][1]-polygon[i][1]) + polygon[i][0]
|
|
||||||
inside = !inside
|
|
||||||
j = i
|
|
||||||
inside
|
|
||||||
|
|
||||||
ll2xy: (lon, lat) ->
|
|
||||||
[
|
|
||||||
utils.deg2rad(lon)*constants.RADIUS,
|
|
||||||
Math.log(Math.tan(Math.PI/4 + utils.deg2rad(lat)/2)) * constants.RADIUS
|
|
||||||
]
|
|
||||||
|
|
||||||
ll2tile: (lon, lat, zoom) ->
|
ll2tile: (lon, lat, zoom) ->
|
||||||
[
|
x: (lon+180)/360*Math.pow(2, zoom)
|
||||||
Math.floor (lon+180)/360*Math.pow(2, zoom)
|
y: (1-Math.log(Math.tan(lat*Math.PI/180)+1/Math.cos(lat*Math.PI/180))/Math.PI)/2*Math.pow(2, zoom)
|
||||||
Math.floor (1-Math.log(Math.tan(lat*Math.PI/180)+1/Math.cos(lat*Math.PI/180))/Math.PI)/2*Math.pow(2, zoom)
|
z: zoom
|
||||||
]
|
|
||||||
|
|
||||||
tile2ll: (x, y, zoom) ->
|
tile2ll: (x, y, zoom) ->
|
||||||
n = Math.PI - 2*Math.PI*y/Math.pow(2, zoom)
|
n = Math.PI - 2*Math.PI*y/Math.pow(2, zoom)
|
||||||
@ -43,32 +26,9 @@ utils =
|
|||||||
lon: x/Math.pow(2, zoom)*360-180
|
lon: x/Math.pow(2, zoom)*360-180
|
||||||
lat: 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n)))
|
lat: 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n)))
|
||||||
|
|
||||||
geoBBox: (center, zoom, width, height) ->
|
|
||||||
[x, y] = utils.ll2xy center.lon, center.lat
|
|
||||||
meterPerPixel = utils.metersPerPixel zoom, center.lat
|
|
||||||
|
|
||||||
width *= meterPerPixel
|
|
||||||
height *= meterPerPixel
|
|
||||||
|
|
||||||
west = x - width*.5
|
|
||||||
east = x + width*.5
|
|
||||||
south = y + height*.5
|
|
||||||
north = y - height*.5
|
|
||||||
|
|
||||||
box = mercator
|
|
||||||
.inverse([west+1, south])
|
|
||||||
.concat mercator.inverse([east-1, north])
|
|
||||||
|
|
||||||
metersPerPixel: (zoom, lat = 0) ->
|
metersPerPixel: (zoom, lat = 0) ->
|
||||||
(Math.cos(lat * Math.PI/180) * 2 * Math.PI * constants.RADIUS) / (256 * Math.pow(2, zoom))
|
(Math.cos(lat * Math.PI/180) * 2 * Math.PI * constants.RADIUS) / (256 * Math.pow(2, zoom))
|
||||||
|
|
||||||
deg2rad: (angle) ->
|
|
||||||
# (angle / 180) * Math.PI
|
|
||||||
angle * 0.017453292519943295
|
|
||||||
|
|
||||||
rad2deg: (angle) ->
|
|
||||||
angle / Math.PI * 180
|
|
||||||
|
|
||||||
hex2rgb: (color) ->
|
hex2rgb: (color) ->
|
||||||
return [255, 0, 0] unless color?.match
|
return [255, 0, 0] unless color?.match
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user