1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 1× 1× 7× 7× 7× 7× 7× 23× 7× 1× 11× 31× 4× 7× 7× 7× 7× 7× 2× 5× 5× 5× 11× | import { pointDistance } from './Geometry'; import intersectPaths from 'path-intersection'; var round = Math.round, max = Math.max; function circlePath(center, r) { var x = center.x, y = center.y; return [ ['M', x, y], ['m', 0, -r], ['a', r, r, 0, 1, 1, 0, 2 * r], ['a', r, r, 0, 1, 1, 0, -2 * r], ['z'] ]; } function linePath(points) { var segments = []; points.forEach(function(p, idx) { segments.push([ idx === 0 ? 'M' : 'L', p.x, p.y ]); }); return segments; } var INTERSECTION_THRESHOLD = 10; function getBendpointIntersection(waypoints, reference) { var i, w; for (i = 0; (w = waypoints[i]); i++) { if (pointDistance(w, reference) <= INTERSECTION_THRESHOLD) { return { point: waypoints[i], bendpoint: true, index: i }; } } return null; } function getPathIntersection(waypoints, reference) { var intersections = intersectPaths(circlePath(reference, INTERSECTION_THRESHOLD), linePath(waypoints)); var a = intersections[0], b = intersections[intersections.length - 1], idx; if (!a) { // no intersection return null; } Eif (a !== b) { Iif (a.segment2 !== b.segment2) { // we use the bendpoint in between both segments // as the intersection point idx = max(a.segment2, b.segment2) - 1; return { point: waypoints[idx], bendpoint: true, index: idx }; } return { point: { x: (round(a.x + b.x) / 2), y: (round(a.y + b.y) / 2) }, index: a.segment2 }; } return { point: { x: round(a.x), y: round(a.y) }, index: a.segment2 }; } /** * Returns the closest point on the connection towards a given reference point. * * @param {Array<Point>} waypoints * @param {Point} reference * * @return {Object} intersection data (segment, point) */ export function getApproxIntersection(waypoints, reference) { return getBendpointIntersection(waypoints, reference) || getPathIntersection(waypoints, reference); } |