@quartic/bokehjs
Version:
Interactive, novel data visualization
95 lines (75 loc) • 2.99 kB
text/coffeescript
import {XYGlyph, XYGlyphView} from "./xy_glyph"
import * as hittest from "core/hittest"
import * as p from "core/properties"
import {angle_between} from "core/util/math"
export class WedgeView extends XYGlyphView
_map_data: () ->
if .properties.radius.units == "data"
=
else
=
_render: (ctx, indices, {sx, sy, sradius, _start_angle, _end_angle}) ->
direction = .properties.direction.value()
for i in indices
if isNaN(sx[i]+sy[i]+sradius[i]+_start_angle[i]+_end_angle[i])
continue
ctx.beginPath()
ctx.arc(sx[i], sy[i], sradius[i], _start_angle[i], _end_angle[i], direction)
ctx.lineTo(sx[i], sy[i])
ctx.closePath()
if .fill.doit
.fill.set_vectorize(ctx, i)
ctx.fill()
if .line.doit
.line.set_vectorize(ctx, i)
ctx.stroke()
_hit_point: (geometry) ->
[vx, vy] = [geometry.vx, geometry.vy]
x = .xmapper.map_from_target(vx, true)
y = .ymapper.map_from_target(vy, true)
# check radius first
if .properties.radius.units == "data"
x0 = x -
x1 = x +
y0 = y -
y1 = y +
else
vx0 = vx -
vx1 = vx +
[x0, x1] = .xmapper.v_map_from_target([vx0, vx1], true)
vy0 = vy -
vy1 = vy +
[y0, y1] = .ymapper.v_map_from_target([vy0, vy1], true)
candidates = []
bbox = hittest.validate_bbox_coords([x0, x1], [y0, y1])
for i in .indices(bbox)
r2 = Math.pow([i], 2)
sx0 = .xmapper.map_to_target(x, true)
sx1 = .xmapper.map_to_target([i], true)
sy0 = .ymapper.map_to_target(y, true)
sy1 = .ymapper.map_to_target([i], true)
dist = Math.pow(sx0-sx1, 2) + Math.pow(sy0-sy1, 2)
if dist <= r2
candidates.push([i, dist])
direction = .properties.direction.value()
hits = []
for [i, dist] in candidates
sx = .plot_view.canvas.vx_to_sx(vx)
sy = .plot_view.canvas.vy_to_sy(vy)
# NOTE: minus the angle because JS uses non-mathy convention for angles
angle = Math.atan2(sy-[i], sx-[i])
if angle_between(-angle, -[i], -[i], direction)
hits.push([i, dist])
return hittest.create_1d_hit_test_result(hits)
draw_legend_for_index: (ctx, x0, x1, y0, y1, index) ->
export class Wedge extends XYGlyph
default_view: WedgeView
type: 'Wedge'
['line', 'fill']
{
direction: [ p.Direction, 'anticlock' ]
radius: [ p.DistanceSpec ]
start_angle: [ p.AngleSpec ]
end_angle: [ p.AngleSpec ]
}