From 2d7cff71ebf26f2a5ae0bc6294d791ca550ca2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Stra=C3=9Fburger?= Date: Thu, 10 Nov 2016 06:14:20 +0100 Subject: [PATCH] :art: adding simplify-js to readme, adapting canvas --- README.md | 7 +++---- package.json | 3 +-- src/Canvas.coffee | 42 +++++++++++++++++--------------------- src/utils.coffee | 52 ++++++----------------------------------------- 4 files changed, 29 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 800f3fc..a2b7c6b 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,9 @@ If your terminal supports mouse events you can drag the map and use your scroll #### Juggling the vectors and numbers * [`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 -* [`breseham`](https://github.com/madbence/node-bresenham) for line 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 -* [`tilebelt`](https://github.com/mapbox/tilebelt) for some [slippy map tilename](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) calculations +* [`rbush`](https://github.com/mourner/rbush) for 2D spatial indexing of geo and label data +* [`breseham`](https://github.com/madbence/node-bresenham) for line point calculations +* [`simplify-js`](https://github.com/mourner/simplify-js) for polyline simplifications #### 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 diff --git a/package.json b/package.json index ad24171..a75ccd0 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,8 @@ "rbush": "^2.0.1", "request": "^2.76.0", "request-promise": "^4.1.1", - "sphericalmercator": "^1.0.5", + "simplify-js": "^1.2.1", "term-mouse": "^0.1.1", - "tilebelt": "^1.0.1", "userhome": "^1.0.0", "vector-tile": "^1.3.0", "x256": "0.0.2" diff --git a/src/Canvas.coffee b/src/Canvas.coffee index 64c53d5..af12beb 100644 --- a/src/Canvas.coffee +++ b/src/Canvas.coffee @@ -12,6 +12,8 @@ ### bresenham = require 'bresenham' +simplify = require 'simplify-js' + earcut = require 'earcut' BrailleBuffer = require './BrailleBuffer' utils = require './utils' @@ -32,11 +34,11 @@ module.exports = class Canvas @buffer.writeText text, x, y, color, center 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) -> 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) -> @buffer.setGlobalBackground color @@ -53,37 +55,38 @@ module.exports = class Canvas continue if ring.length < 3 holes.push vertices.length/2 else - return if ring.length < 3 + return false if ring.length < 3 for point in ring - vertices = vertices.concat point + vertices.push point.x + vertices.push point.y try triangles = earcut vertices, holes catch e return false - extract = (pointId) -> - [vertices[pointId*2], vertices[pointId*2+1]] - for i in [0...triangles.length] by 3 - pa = extract(triangles[i]) - pb = extract(triangles[i+1]) - pc = extract(triangles[i+2]) + pa = @_polygonExtract vertices, triangles[i] + pb = @_polygonExtract vertices, triangles[i+1] + pc = @_polygonExtract vertices, triangles[i+2] @_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" # -> 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 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 - [x0, y0] = pointA - [x1, y1] = pointB dx = Math.abs x1-x0 sx = if x0 < x1 then 1 else -1 dy = Math.abs y1-y0 @@ -138,16 +141,9 @@ module.exports = class Canvas b = @_bresenham pointA, pointC 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) .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 - .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] point = points[i] @@ -155,8 +151,8 @@ module.exports = class Canvas if point.y is next?.y left = Math.max 0, point.x - right = Math.min @width, next.x - if left and right + right = Math.min @width-1, next.x + if left >= 0 and right <= @width @buffer.setPixel x, point.y, color for x in [left..right] else diff --git a/src/utils.coffee b/src/utils.coffee index 7dd55bf..3f5b84c 100644 --- a/src/utils.coffee +++ b/src/utils.coffee @@ -4,8 +4,6 @@ methods used all around ### -mercator = new (require('sphericalmercator'))() - constants = RADIUS: 6378137 @@ -13,29 +11,14 @@ utils = clamp: (num, min, max) -> 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 - # https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html - pointInPolygon: (polygon, point) -> - 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 - ] + deg2rad: (angle) -> + # (angle / 180) * Math.PI + angle * 0.017453292519943295 ll2tile: (lon, lat, zoom) -> - [ - Math.floor (lon+180)/360*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) - ] + x: (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) + z: zoom tile2ll: (x, y, 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 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) -> (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) -> return [255, 0, 0] unless color?.match