UNPKG

diagram-js

Version:

A toolbox for displaying and modifying diagrams on the web

136 lines (106 loc) 2.44 kB
import { pointDistance } from './Geometry'; import intersectPaths from 'path-intersection'; /** * @typedef {import('../util/Types').Point} Point * * @typedef { { * bendpoint?: boolean; * index: number; * point: Point; * } } 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; /** * @param {Point[]} waypoints * @param {Point} reference * * @return {Intersection|null} */ 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; } /** * @param {Point[]} waypoints * @param {Point} reference * * @return {Intersection|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; } if (a !== b) { if (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 {Point[]} waypoints * @param {Point} reference * * @return {Intersection|null} */ export function getApproxIntersection(waypoints, reference) { return getBendpointIntersection(waypoints, reference) || getPathIntersection(waypoints, reference); }