169 lines
5.3 KiB
JavaScript
169 lines
5.3 KiB
JavaScript
var Glyph, Line, LineView, _, hittest,
|
|
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
_ = require("underscore");
|
|
|
|
Glyph = require("./glyph");
|
|
|
|
hittest = require("../../common/hittest");
|
|
|
|
LineView = (function(superClass) {
|
|
extend(LineView, superClass);
|
|
|
|
function LineView() {
|
|
return LineView.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
LineView.prototype._index_data = function() {
|
|
return this._xy_index();
|
|
};
|
|
|
|
LineView.prototype._render = function(ctx, indices, arg) {
|
|
var drawing, i, j, len, sx, sy;
|
|
sx = arg.sx, sy = arg.sy;
|
|
drawing = false;
|
|
this.visuals.line.set_value(ctx);
|
|
for (j = 0, len = indices.length; j < len; j++) {
|
|
i = indices[j];
|
|
if (!isFinite(sx[i] + sy[i]) && drawing) {
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
drawing = false;
|
|
continue;
|
|
}
|
|
if (drawing) {
|
|
ctx.lineTo(sx[i], sy[i]);
|
|
} else {
|
|
ctx.beginPath();
|
|
ctx.moveTo(sx[i], sy[i]);
|
|
drawing = true;
|
|
}
|
|
}
|
|
if (drawing) {
|
|
return ctx.stroke();
|
|
}
|
|
};
|
|
|
|
LineView.prototype._hit_point = function(geometry) {
|
|
|
|
/* Check if the point geometry hits this line glyph and return an object
|
|
that describes the hit result:
|
|
Args:
|
|
* geometry (object): object with the following keys
|
|
* vx (float): view x coordinate of the point
|
|
* vy (float): view y coordinate of the point
|
|
* type (str): type of geometry (in this case it's a point)
|
|
Output:
|
|
Object with the following keys:
|
|
* 0d (bool): whether the point hits the glyph or not
|
|
* 1d (array(int)): array with the indices hit by the point
|
|
*/
|
|
var dist, i, j, p0, p1, point, ref, ref1, result, shortest, threshold;
|
|
result = hittest.create_hit_test_result();
|
|
point = {
|
|
x: this.renderer.plot_view.canvas.vx_to_sx(geometry.vx),
|
|
y: this.renderer.plot_view.canvas.vy_to_sy(geometry.vy)
|
|
};
|
|
shortest = 9999;
|
|
threshold = Math.max(2, this.visuals.line.line_width.value() / 2);
|
|
for (i = j = 0, ref = this.sx.length - 1; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
|
ref1 = [
|
|
{
|
|
x: this.sx[i],
|
|
y: this.sy[i]
|
|
}, {
|
|
x: this.sx[i + 1],
|
|
y: this.sy[i + 1]
|
|
}
|
|
], p0 = ref1[0], p1 = ref1[1];
|
|
dist = hittest.dist_to_segment(point, p0, p1);
|
|
if (dist < threshold && dist < shortest) {
|
|
shortest = dist;
|
|
result['0d'].glyph = this.model;
|
|
result['0d'].get_view = (function() {
|
|
return this;
|
|
}).bind(this);
|
|
result['0d'].flag = true;
|
|
result['0d'].indices = [i];
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LineView.prototype._hit_span = function(geometry) {
|
|
var i, j, ref, ref1, result, val, values, vx, vy;
|
|
ref = [geometry.vx, geometry.vy], vx = ref[0], vy = ref[1];
|
|
result = hittest.create_hit_test_result();
|
|
if (geometry.direction === 'v') {
|
|
val = this.renderer.ymapper.map_from_target(vy);
|
|
values = this._y;
|
|
} else {
|
|
val = this.renderer.xmapper.map_from_target(vx);
|
|
values = this._x;
|
|
}
|
|
for (i = j = 0, ref1 = values.length - 1; 0 <= ref1 ? j < ref1 : j > ref1; i = 0 <= ref1 ? ++j : --j) {
|
|
if ((values[i] <= val && val <= values[i + 1])) {
|
|
result['0d'].glyph = this.model;
|
|
result['0d'].get_view = (function() {
|
|
return this;
|
|
}).bind(this);
|
|
result['0d'].flag = true;
|
|
result['0d'].indices.push(i);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LineView.prototype.get_interpolation_hit = function(i, geometry) {
|
|
var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, res, vx, vy, x0, x1, x2, x3, y0, y1, y2, y3;
|
|
ref = [geometry.vx, geometry.vy], vx = ref[0], vy = ref[1];
|
|
ref1 = [this._x[i], this._y[i], this._x[i + 1], this._y[i + 1]], x2 = ref1[0], y2 = ref1[1], x3 = ref1[2], y3 = ref1[3];
|
|
if (geometry.type === 'point') {
|
|
ref2 = this.renderer.ymapper.v_map_from_target([vy - 1, vy + 1]), y0 = ref2[0], y1 = ref2[1];
|
|
ref3 = this.renderer.xmapper.v_map_from_target([vx - 1, vx + 1]), x0 = ref3[0], x1 = ref3[1];
|
|
} else {
|
|
if (geometry.direction === 'v') {
|
|
ref4 = this.renderer.ymapper.v_map_from_target([vy, vy]), y0 = ref4[0], y1 = ref4[1];
|
|
ref5 = [x2, x3], x0 = ref5[0], x1 = ref5[1];
|
|
} else {
|
|
ref6 = this.renderer.xmapper.v_map_from_target([vx, vx]), x0 = ref6[0], x1 = ref6[1];
|
|
ref7 = [y2, y3], y0 = ref7[0], y1 = ref7[1];
|
|
}
|
|
}
|
|
res = hittest.check_2_segments_intersect(x0, y0, x1, y1, x2, y2, x3, y3);
|
|
return [res.x, res.y];
|
|
};
|
|
|
|
LineView.prototype.draw_legend = function(ctx, x0, x1, y0, y1) {
|
|
return this._generic_line_legend(ctx, x0, x1, y0, y1);
|
|
};
|
|
|
|
return LineView;
|
|
|
|
})(Glyph.View);
|
|
|
|
Line = (function(superClass) {
|
|
extend(Line, superClass);
|
|
|
|
function Line() {
|
|
return Line.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
Line.prototype.default_view = LineView;
|
|
|
|
Line.prototype.type = 'Line';
|
|
|
|
Line.coords([['x', 'y']]);
|
|
|
|
Line.mixins(['line']);
|
|
|
|
return Line;
|
|
|
|
})(Glyph.Model);
|
|
|
|
module.exports = {
|
|
Model: Line,
|
|
View: LineView
|
|
};
|