@quartic/bokehjs
Version:
Interactive, novel data visualization
115 lines (90 loc) • 3.54 kB
text/coffeescript
import {XYGlyph, XYGlyphView} from "../glyphs/xy_glyph"
import * as hittest from "core/hittest"
import * as p from "core/properties"
export class MarkerView extends XYGlyphView
draw_legend_for_index: (ctx, x0, x1, y0, y1, index) ->
# using objects like this seems a little wonky, since the keys are coerced to
# stings, but it works
indices = [index]
sx = { }
sx[index] = (x0+x1)/2
sy = { }
sy[index] = (y0+y1)/2
size = { }
size[index] = Math.min(Math.abs(x1-x0), Math.abs(y1-y0))*0.4
angle = { }
angle[index] = [index]
data = {sx:sx, sy:sy, _size: size, _angle: angle}
_render: (ctx, indices, {sx, sy, _size, _angle}) ->
for i in indices
if isNaN(sx[i]+sy[i]+_size[i]+_angle[i])
continue
r = _size[i]/2
ctx.beginPath()
ctx.translate(sx[i], sy[i])
if _angle[i]
ctx.rotate(_angle[i])
if _angle[i]
ctx.rotate(-_angle[i])
ctx.translate(-sx[i], -sy[i])
_mask_data: (all_indices) ->
# dilate the inner screen region by max_size and map back to data space for use in
# spatial query
hr = .plot_view.frame.h_range
vx0 = hr.start -
vx1 = hr.end +
[x0, x1] = .xmapper.v_map_from_target([vx0, vx1], true)
vr = .plot_view.frame.v_range
vy0 = vr.start -
vy1 = vr.end +
[y0, y1] = .ymapper.v_map_from_target([vy0, vy1], true)
bbox = hittest.validate_bbox_coords([x0, x1], [y0, y1])
return .indices(bbox)
_hit_point: (geometry) ->
[vx, vy] = [geometry.vx, geometry.vy]
sx = .plot_view.canvas.vx_to_sx(vx)
sy = .plot_view.canvas.vy_to_sy(vy)
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)
bbox = hittest.validate_bbox_coords([x0, x1], [y0, y1])
candidates = .indices(bbox)
hits = []
for i in candidates
s2 = [i]/2
dist = Math.abs([i]-sx) + Math.abs([i]-sy)
if Math.abs([i]-sx) <= s2 and Math.abs([i]-sy) <= s2
hits.push([i, dist])
return hittest.create_1d_hit_test_result(hits)
_hit_rect: (geometry) ->
[x0, x1] = .xmapper.v_map_from_target([geometry.vx0, geometry.vx1], true)
[y0, y1] = .ymapper.v_map_from_target([geometry.vy0, geometry.vy1], true)
bbox = hittest.validate_bbox_coords([x0, x1], [y0, y1])
result = hittest.create_hit_test_result()
result['1d'].indices = .indices(bbox)
return result
_hit_poly: (geometry) ->
[vx, vy] = [geometry.vx, geometry.vy]
sx = .plot_view.canvas.v_vx_to_sx(vx)
sy = .plot_view.canvas.v_vy_to_sy(vy)
# TODO (bev) use spatial index to pare candidate list
candidates = [0....length]
hits = []
for i in [0...candidates.length]
idx = candidates[i]
if hittest.point_in_poly([i], [i], sx, sy)
hits.push(idx)
result = hittest.create_hit_test_result()
result['1d'].indices = hits
return result
export class Marker extends XYGlyph
['line', 'fill']
{
size: [ p.DistanceSpec, { units: "screen", value: 4 } ]
angle: [ p.AngleSpec, 0 ]
}