polyline-normals
Version:
gets miter normals for a 2D polyline
98 lines (81 loc) • 2.67 kB
JavaScript
require('canvas-testbed')(render, { once: true })
var vec = require('gl-vec2')
var getNormals = require('./')
var arc = require('arc-to')
var curve = require('adaptive-bezier-curve')
var paths = []
paths.push( [ [40, 40], [80, 30], [80, 60], [125, 33], [115, 100], [50, 120], [70, 150] ] )
paths.push( { path: circle(130, 120, 25), closed: true } )
paths.push( curve([40, 40], [70, 100], [120, 20], [200, 40], 5) )
paths.push( { path: [ [0, 122], [0, 190], [90, 190] ], closed: true } )
paths.push( { path: [ [50, 50], [100, 50], [100, 100], [50, 100] ], closed: true } )
paths.push( [ [30, -60], [80, 10] ] )
function circle(x, y, radius) {
//in this case arc-to closes itself by making the
//last point equal to the first. we want to fix this
//to pass in a more typical polyline and get the right normals
var c = arc(x, y, radius, 0, Math.PI*2, false)
c.pop()
return c
}
function render(ctx, width, height) {
ctx.clearRect(0,0,width,height)
//draw each path with a bit of an offset
ctx.save()
paths.forEach(function(data, i) {
var path = Array.isArray(data) ? data : data.path
var closed = typeof data === 'object' && data.closed
var cols = 3
var x = i % cols,
y = ~~(i / cols)
ctx.translate(x * 50, y * 50)
draw(ctx, path, closed)
})
ctx.restore()
}
function draw(ctx, path, closed) {
var thick = 25,
halfThick = thick / 2
var psize = 4
var tmp = [0,0]
var top = []
var bot = []
//get the normals of the path
var normals = getNormals(path, closed)
//for drawing the join, we can just add the first point
if (closed) {
path.push(path[0])
normals.push(normals[0])
}
//draw our expanded vertices for each point in the path
ctx.globalAlpha = 0.15
path.forEach(function(p, i) {
var attrib = normals[i]
var norm = attrib[0]
var len = attrib[1]
ctx.fillStyle = 'black'
ctx.fillRect(p[0]-psize/2, p[1]-psize/2, psize, psize)
ctx.beginPath()
vec.scaleAndAdd(tmp, p, norm, len*halfThick)
ctx.moveTo(p[0], p[1])
ctx.lineTo(tmp[0], tmp[1])
top.push(tmp.slice())
vec.scaleAndAdd(tmp, p, norm, -len*halfThick)
ctx.moveTo(p[0], p[1])
ctx.lineTo(tmp[0], tmp[1])
ctx.stroke()
bot.push(tmp.slice())
})
//edges
ctx.globalAlpha = 1
ctx.beginPath()
top.forEach(function(t) {
ctx.lineTo(t[0], t[1])
})
ctx.stroke()
ctx.beginPath()
bot.forEach(function(t) {
ctx.lineTo(t[0], t[1])
})
ctx.stroke()
}