UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

145 lines 5.55 kB
import { RadialGlyph, RadialGlyphView } from "./radial_glyph"; import * as hittest from "../../core/hittest"; import { minmax2 } from "../../core/util/arrayable"; import { Selection } from "../selections/selection"; export class CircleView extends RadialGlyphView { static __name__ = "CircleView"; async load_glglyph() { const { CircleGL } = await import("./webgl/circle"); return CircleGL; } _paint(ctx, indices, data) { const { sx, sy, sradius } = { ...this, ...data }; for (const i of indices) { const sx_i = sx[i]; const sy_i = sy[i]; const sradius_i = sradius[i]; if (!isFinite(sx_i + sy_i + sradius_i)) { continue; } ctx.beginPath(); ctx.arc(sx_i, sy_i, sradius_i, 0, 2 * Math.PI, false); this.visuals.fill.apply(ctx, i); this.visuals.hatch.apply(ctx, i); this.visuals.line.apply(ctx, i); } } _hit_point(geometry) { const { sx, sy } = geometry; const x = this.renderer.xscale.invert(sx); const y = this.renderer.yscale.invert(sy); const { hit_dilation } = this.model; const [x0, x1, y0, y1] = (() => { if (this.model.properties.radius.units == "data") { const dr = this.max_radius * hit_dilation; const x0 = x - dr; const x1 = x + dr; const y0 = y - dr; const y1 = y + dr; return [x0, x1, y0, y1]; } else { const ds = this.max_radius * hit_dilation; const sx0 = sx - ds; const sx1 = sx + ds; const sy0 = sy - ds; const sy1 = sy + ds; const [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1); const [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1); return [x0, x1, y0, y1]; } })(); const candidates = this.index.indices({ x0, x1, y0, y1 }); const indices = []; if (this.model.properties.radius.units == "data") { for (const i of candidates) { const r2 = (this.sradius[i] * hit_dilation) ** 2; const [sx0, sx1] = this.renderer.xscale.r_compute(x, this.x[i]); const [sy0, sy1] = this.renderer.yscale.r_compute(y, this.y[i]); const dist = (sx0 - sx1) ** 2 + (sy0 - sy1) ** 2; if (dist <= r2) { indices.push(i); } } } else { for (const i of candidates) { const r2 = (this.sradius[i] * hit_dilation) ** 2; const dist = (this.sx[i] - sx) ** 2 + (this.sy[i] - sy) ** 2; if (dist <= r2) { indices.push(i); } } } return new Selection({ indices }); } _hit_span(geometry) { const { sx, sy } = geometry; const bounds = this.bounds(); const [x0, x1, y0, y1] = (() => { const dr = this.max_radius; if (geometry.direction == "h") { // use circle bounds instead of current pointer y coordinates const sx0 = sx - dr; const sx1 = sx + dr; const [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1); const { y0, y1 } = bounds; return [x0, x1, y0, y1]; } else { // use circle bounds instead of current pointer x coordinates const sy0 = sy - dr; const sy1 = sy + dr; const { x0, x1 } = bounds; const [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1); return [x0, x1, y0, y1]; } })(); const indices = [...this.index.indices({ x0, x1, y0, y1 })]; return new Selection({ indices }); } _hit_rect(geometry) { const { sx0, sx1, sy0, sy1 } = geometry; const [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1); const [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1); const candidates = this.index.indices({ x0, x1, y0, y1 }); const indices = []; for (const i of candidates) { const sx_i = this.sx[i]; const sy_i = this.sy[i]; if (sx0 <= sx_i && sx_i <= sx1 && sy0 <= sy_i && sy_i <= sy1) { indices.push(i); } } return new Selection({ indices }); } _hit_poly(geometry) { const { sx: sxs, sy: sys } = geometry; const candidates = (() => { const [sx0, sx1, sy0, sy1] = minmax2(sxs, sys); const [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1); const [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1); return this.index.indices({ x0, x1, y0, y1 }); })(); const indices = []; for (const i of candidates) { if (hittest.point_in_poly(this.sx[i], this.sy[i], sxs, sys)) { indices.push(i); } } return new Selection({ indices }); } } export class Circle extends RadialGlyph { static __name__ = "Circle"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = CircleView; this.define(({ Float }) => ({ hit_dilation: [Float, 1.0], })); } } //# sourceMappingURL=circle.js.map