🏃 using rbush's bulk load (2-3 times faster), working on polygon speed

This commit is contained in:
Michael Straßburger 2016-11-07 16:23:22 +01:00
parent 7ed86ceed4
commit 461a4ab049
4 changed files with 58 additions and 43 deletions

View File

@ -74,7 +74,14 @@ module.exports = class Canvas
[vertices[pointId*2], vertices[pointId*2+1]] [vertices[pointId*2], vertices[pointId*2+1]]
for i in [0...triangles.length] by 3 for i in [0...triangles.length] by 3
@_filledTriangle extract(triangles[i]), extract(triangles[i+1]), extract(triangles[i+2]), color pa = extract(triangles[i])
pb = extract(triangles[i+1])
pc = extract(triangles[i+2])
if (0 <= pa[0] < @width and 0 <= pa[1] < @height) or
(0 <= pb[0] < @width and 0 <= pb[1] < @height) or
(0 <= pc[0] < @width and 0 <= pc[1] < @height)
@_filledTriangle pa, pb, pc, color
# 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

View File

@ -210,20 +210,19 @@ module.exports = class Renderer
if feature.style.minzoom and tile.zoom < feature.style.minzoom if feature.style.minzoom and tile.zoom < feature.style.minzoom
return false return false
points = @_scaleAndReduce tile, feature
unless points.length
return false
switch feature.style.type switch feature.style.type
when "line" when "line"
points = @_scaleAndReduce tile, feature, feature.points
width = feature.style.paint['line-width'] width = feature.style.paint['line-width']
width = width.stops[0][1] if width instanceof Object width = width.stops[0][1] if width instanceof Object
@canvas.polyline points, feature.color, width @canvas.polyline points, feature.color, width if points.length
when "fill" when "fill"
@canvas.polygon points, feature.color vertices = (@_scaleAndReduce tile, feature, points, false for points in feature.points)
@canvas.polygon vertices[0], feature.color
true
when "symbol" when "symbol"
text = feature.properties["name_"+@config.language] or text = feature.properties["name_"+@config.language] or
@ -233,6 +232,7 @@ module.exports = class Renderer
#@config.icons[feature.properties.maki] or #@config.icons[feature.properties.maki] or
"" ""
points = @_scaleAndReduce tile, feature, feature.points
for point in points for point in points
x = point[0] - text.length x = point[0] - text.length
margin = @config.layers[feature.layer]?.margin or @config.labelMargin margin = @config.layers[feature.layer]?.margin or @config.labelMargin
@ -243,13 +243,13 @@ module.exports = class Renderer
@canvas.text "", point[0], point[1], feature.color @canvas.text "", point[0], point[1], feature.color
_seen: {} _seen: {}
_scaleAndReduce: (tile, feature) -> _scaleAndReduce: (tile, feature, points, filter = true) ->
lastX = null lastX = null
lastY = null lastY = null
outside = false outside = false
scaled = [] scaled = []
for point in feature.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)
@ -259,29 +259,31 @@ module.exports = class Renderer
lastY = y lastY = y
lastX = x lastX = x
if tile.xyz.z > 1 and ( if filter
x < -@tilePadding or if tile.xyz.z > 1 and (
y < -@tilePadding or x < -@tilePadding or
x > @width+@tilePadding or y < -@tilePadding or
y > @height+@tilePadding x > @width+@tilePadding or
) y > @height+@tilePadding
continue if outside )
outside = true continue if outside
else outside = true
if outside else
outside = null if outside
scaled.push [lastX, lastY] outside = null
scaled.push [lastX, lastY]
scaled.push [x, y] scaled.push [x, y]
if scaled.length is 2 if filter
if @_seen[ka = scaled[0].concat(scaled[1]).join '-'] or if scaled.length is 2
@_seen[kb = scaled[1].concat(scaled[0]).join '-'] if @_seen[ka = scaled[0].concat(scaled[1]).join '-'] or
@_seen[kb = scaled[1].concat(scaled[0]).join '-']
return []
@_seen[ka] = @_seen[kb] = true
if scaled.length < 2 and feature.style.type isnt "symbol"
return [] return []
@_seen[ka] = @_seen[kb] = true
if scaled.length < 2 and feature.style.type isnt "symbol"
return []
scaled scaled

View File

@ -24,7 +24,7 @@ module.exports = class Termap
initialZoom: null initialZoom: null
maxZoom: 17 maxZoom: 17
zoomStep: 0.2 zoomStep: 0.1
headless: false headless: false
# size: # size:

View File

@ -45,7 +45,7 @@ class Tile
colorCache = {} colorCache = {}
for name, layer of tile.layers for name, layer of tile.layers
tree = rbush() nodes = []
for i in [0...layer.length] for i in [0...layer.length]
# TODO: caching of similar attributes to avoid looking up the style each time # TODO: caching of similar attributes to avoid looking up the style each time
#continue if @styler and not @styler.getStyleFor layer, feature #continue if @styler and not @styler.getStyleFor layer, feature
@ -74,17 +74,17 @@ class Tile
# TODO: handling polygon holes, only handling outer area for now # TODO: handling polygon holes, only handling outer area for now
if style.type is "fill" if style.type is "fill"
@_addToTree tree, nodes.push @_addBoundaries
id: feature.id id: feature.id
layer: name layer: name
style: style style: style
properties: feature.properties properties: feature.properties
points: geometries[0] points: geometries
color: colorCode color: colorCode
else else
for points in geometries for points in geometries
@_addToTree tree, nodes.push @_addBoundaries
id: feature.id id: feature.id
layer: name layer: name
style: style style: style
@ -92,25 +92,31 @@ class Tile
points: points points: points
color: colorCode color: colorCode
tree = rbush()
tree.load nodes
layers[name] = tree layers[name] = tree
@layers = layers @layers = layers
_addToTree: (tree, data) -> _addBoundaries: (data) ->
[minX, maxX, minY, maxY] = [Infinity, -Infinity, Infinity, -Infinity] [minX, maxX, minY, maxY] = [Infinity, -Infinity, Infinity, -Infinity]
minMax = (points) ->
for p in points
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
for p in data.points if data.points[0] instanceof Array
minX = p.x if p.x < minX minMax points for points in data.points
maxX = p.x if p.x > maxX else
minY = p.y if p.y < minY minMax data.points
maxY = p.y if p.y > maxY
data.minX = minX data.minX = minX
data.maxX = maxX data.maxX = maxX
data.minY = minY data.minY = minY
data.maxY = maxY data.maxY = maxY
data
tree.insert data
_reduceGeometry: (feature, factor) -> _reduceGeometry: (feature, factor) ->
for points, i in feature.loadGeometry() for points, i in feature.loadGeometry()