UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

105 lines 3.83 kB
export function point_in_poly(x, y, px, py) { let inside = false; let x1 = px[px.length - 1]; let y1 = py[py.length - 1]; for (let i = 0; i < px.length; i++) { const x2 = px[i]; const y2 = py[i]; if ((y1 < y) != (y2 < y)) { if ((x1 + (y - y1) / (y2 - y1) * (x2 - x1)) < x) { inside = !inside; } } x1 = x2; y1 = y2; } return inside; } export function point_in_ellipse(x, y, angle, b, a, x0, y0) { const A = ((Math.cos(angle) / a) ** 2 + (Math.sin(angle) / b) ** 2); const B = 2 * Math.cos(angle) * Math.sin(angle) * ((1 / a) ** 2 - (1 / b) ** 2); const C = ((Math.cos(angle) / b) ** 2 + (Math.sin(angle) / a) ** 2); const eqn = A * (x - x0) ** 2 + B * (x - x0) * (y - y0) + C * (y - y0) ** 2; const inside = eqn <= 1; return inside; } export function dist_2_pts(p0, p1) { return (p0.x - p1.x) ** 2 + (p0.y - p1.y) ** 2; } export function dist_to_segment_squared(p, v, w) { const l2 = dist_2_pts(v, w); if (l2 == 0) { return dist_2_pts(p, v); } const t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; if (t < 0) { return dist_2_pts(p, v); } if (t > 1) { return dist_2_pts(p, w); } const q = { x: v.x + t * (w.x - v.x), y: v.y + t * (w.y - v.y) }; return dist_2_pts(p, q); } export function dist_to_segment(p, v, w) { return Math.sqrt(dist_to_segment_squared(p, v, w)); } export function check_2_segments_intersect(l0_x0, l0_y0, l0_x1, l0_y1, l1_x0, l1_y0, l1_x1, l1_y1) { /* * Check if 2 segments (l0 and l1) intersect. Returns a structure with * the following attributes: * * hit (boolean): whether the 2 segments intersect * * x (float): x coordinate of the intersection point * * y (float): y coordinate of the intersection point */ const den = ((l1_y1 - l1_y0) * (l0_x1 - l0_x0)) - ((l1_x1 - l1_x0) * (l0_y1 - l0_y0)); if (den == 0) { return { hit: false, x: null, y: null }; } else { let a = l0_y0 - l1_y0; let b = l0_x0 - l1_x0; const num1 = ((l1_x1 - l1_x0) * a) - ((l1_y1 - l1_y0) * b); const num2 = ((l0_x1 - l0_x0) * a) - ((l0_y1 - l0_y0) * b); a = num1 / den; b = num2 / den; const x = l0_x0 + (a * (l0_x1 - l0_x0)); const y = l0_y0 + (a * (l0_y1 - l0_y0)); return { hit: (a > 0 && a < 1) && (b > 0 && b < 1), x, y }; } } // Given two polygons, is any vertex of one inside the other export function vertex_overlap(x0, y0, x1, y1) { // need to check "both directions" to handle total inclusion cases for (let i = 0; i < x0.length; i++) { if (point_in_poly(x0[i], y0[i], x1, y1)) { return true; } } for (let i = 0; i < x1.length; i++) { if (point_in_poly(x1[i], y1[i], x0, y0)) { return true; } } return false; } // Given two polygons, do any pair of edges intersect export function edge_intersection(x0, y0, x1, y1) { for (let i = 0; i < x0.length - 1; i++) { for (let j = 0; j < x1.length - 1; j++) { if (check_2_segments_intersect(x0[i], y0[i], x0[i + 1], y0[i + 1], x1[j], y1[j], x1[j + 1], y1[j + 1]).hit) { return true; } } // consider x1, y1 "closing" segment if (check_2_segments_intersect(x0[i], y0[i], x0[i + 1], y0[i + 1], x1[x1.length - 1], y1[x1.length - 1], x1[0], y1[0]).hit) { return true; } } // consider x0, y0, "closing" segment if (check_2_segments_intersect(x0[x0.length - 1], y0[x0.length - 1], x0[0], y0[0], x1[x1.length - 1], y1[x1.length - 1], x1[0], y1[0]).hit) { return true; } return false; } //# sourceMappingURL=hittest.js.map