UNPKG

tldraw

Version:

A tiny little drawing editor.

649 lines (648 loc) • 25.7 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var getElbowArrowInfo_exports = {}; __export(getElbowArrowInfo_exports, { getEdgeFromNormalizedAnchor: () => getEdgeFromNormalizedAnchor, getElbowArrowInfo: () => getElbowArrowInfo, getRouteHandlePath: () => getRouteHandlePath, getUsableEdge: () => getUsableEdge }); module.exports = __toCommonJS(getElbowArrowInfo_exports); var import_editor = require("@tldraw/editor"); var import_shared = require("../shared"); var import_definitions = require("./definitions"); var import_range = require("./range"); var import_ElbowArrowWorkingInfo = require("./routes/ElbowArrowWorkingInfo"); var import_routeArrowWithAutoEdgePicking = require("./routes/routeArrowWithAutoEdgePicking"); function getElbowArrowInfo(editor, arrow, bindings) { const shapeOptions = editor.getShapeUtil(arrow.type).options; const options = { elbowMidpoint: arrow.props.elbowMidPoint, expandElbowLegLength: shapeOptions.expandElbowLegLength[arrow.props.size] * arrow.props.scale, minElbowLegLength: shapeOptions.minElbowLegLength[arrow.props.size] * arrow.props.scale }; let startTerminal = getElbowArrowTerminalInfo(editor, arrow, bindings.start, arrow.props.start); let endTerminal = getElbowArrowTerminalInfo(editor, arrow, bindings.end, arrow.props.end); startTerminal = adjustTerminalForUnclosedPathIfNeeded(startTerminal, endTerminal, options); endTerminal = adjustTerminalForUnclosedPathIfNeeded(endTerminal, startTerminal, options); const swapOrder = !!(!startTerminal.side && endTerminal.side); let { aTerminal, bTerminal } = swapOrder ? { aTerminal: endTerminal, bTerminal: startTerminal } : { aTerminal: startTerminal, bTerminal: endTerminal }; let edgesA = { top: getUsableEdge(aTerminal, bTerminal, "top", options), right: getUsableEdge(aTerminal, bTerminal, "right", options), bottom: getUsableEdge(aTerminal, bTerminal, "bottom", options), left: getUsableEdge(aTerminal, bTerminal, "left", options) }; let edgesB = { top: getUsableEdge(bTerminal, aTerminal, "top", options), right: getUsableEdge(bTerminal, aTerminal, "right", options), bottom: getUsableEdge(bTerminal, aTerminal, "bottom", options), left: getUsableEdge(bTerminal, aTerminal, "left", options) }; const aIsUsable = hasUsableEdge(edgesA, aTerminal.side); const bIsUsable = hasUsableEdge(edgesB, bTerminal.side); let needsNewEdges = false; if (!aIsUsable || !bIsUsable) { needsNewEdges = true; if (!aIsUsable) { bTerminal = convertTerminalToPoint(bTerminal); } if (!bIsUsable) { aTerminal = convertTerminalToPoint(aTerminal); } if (bTerminal.bounds.containsPoint(aTerminal.target, options.expandElbowLegLength)) { bTerminal = convertTerminalToPoint(bTerminal); } if (aTerminal.bounds.containsPoint(bTerminal.target, options.expandElbowLegLength)) { aTerminal = convertTerminalToPoint(aTerminal); } } if (needsNewEdges) { edgesA = { top: getUsableEdge(aTerminal, bTerminal, "top", options), right: getUsableEdge(aTerminal, bTerminal, "right", options), bottom: getUsableEdge(aTerminal, bTerminal, "bottom", options), left: getUsableEdge(aTerminal, bTerminal, "left", options) }; edgesB = { top: getUsableEdge(bTerminal, aTerminal, "top", options), right: getUsableEdge(bTerminal, aTerminal, "right", options), bottom: getUsableEdge(bTerminal, aTerminal, "bottom", options), left: getUsableEdge(bTerminal, aTerminal, "left", options) }; } const expandedA = aTerminal.isPoint ? aTerminal.bounds : aTerminal.bounds.clone().expandBy(options.expandElbowLegLength); const expandedB = bTerminal.isPoint ? bTerminal.bounds : bTerminal.bounds.clone().expandBy(options.expandElbowLegLength); const common = { original: import_editor.Box.Common([aTerminal.bounds, bTerminal.bounds]), expanded: import_editor.Box.Common([expandedA, expandedB]) }; let gapX = bTerminal.bounds.minX - aTerminal.bounds.maxX; if (gapX < 0) { gapX = aTerminal.bounds.minX - bTerminal.bounds.maxX; if (gapX < 0) { gapX = 0; } gapX = -gapX; } let gapY = bTerminal.bounds.minY - aTerminal.bounds.maxY; if (gapY < 0) { gapY = aTerminal.bounds.minY - bTerminal.bounds.maxY; if (gapY < 0) { gapY = 0; } gapY = -gapY; } const aMinLength = aTerminal.minEndSegmentLength * 3; const bMinLength = bTerminal.minEndSegmentLength * 3; const minLegDistanceNeeded = (aTerminal.isPoint ? aMinLength : options.minElbowLegLength) + (bTerminal.isPoint ? bMinLength : options.minElbowLegLength); let mxRange = null; if (gapX > minLegDistanceNeeded) { mxRange = { a: aTerminal.isPoint ? aTerminal.bounds.maxX + aMinLength : expandedA.maxX, b: bTerminal.isPoint ? bTerminal.bounds.minX - bMinLength : expandedB.minX }; } else if (gapX < -minLegDistanceNeeded) { mxRange = { a: aTerminal.isPoint ? aTerminal.bounds.minX - aMinLength : expandedA.minX, b: bTerminal.isPoint ? bTerminal.bounds.maxX + bMinLength : expandedB.maxX }; } let myRange = null; if (gapY > minLegDistanceNeeded) { myRange = { a: aTerminal.isPoint ? aTerminal.bounds.maxY + aMinLength : expandedA.maxY, b: bTerminal.isPoint ? bTerminal.bounds.minY - bMinLength : expandedB.minY }; } else if (gapY < -minLegDistanceNeeded) { myRange = { a: aTerminal.isPoint ? aTerminal.bounds.minY - aMinLength : expandedA.minY, b: bTerminal.isPoint ? bTerminal.bounds.maxY + bMinLength : expandedB.maxY }; } const midpoint = swapOrder ? 1 - options.elbowMidpoint : options.elbowMidpoint; const mx = mxRange ? (0, import_editor.lerp)(mxRange.a, mxRange.b, midpoint) : null; const my = myRange ? (0, import_editor.lerp)(myRange.a, myRange.b, midpoint) : null; const info = { options, swapOrder, A: { isPoint: aTerminal.isPoint, target: aTerminal.target, isExact: aTerminal.isExact, arrowheadOffset: aTerminal.arrowheadOffset, minEndSegmentLength: aTerminal.minEndSegmentLength, original: aTerminal.bounds, expanded: expandedA, edges: edgesA, geometry: aTerminal.geometry }, B: { isPoint: bTerminal.isPoint, target: bTerminal.target, isExact: bTerminal.isExact, arrowheadOffset: bTerminal.arrowheadOffset, minEndSegmentLength: bTerminal.minEndSegmentLength, original: bTerminal.bounds, expanded: expandedB, edges: edgesB, geometry: bTerminal.geometry }, common, gapX, gapY, midX: mx, midY: my }; const workingInfo = new import_ElbowArrowWorkingInfo.ElbowArrowWorkingInfo(info); const aSide = getSideToUse(aTerminal, bTerminal, info.A.edges); const bSide = getSideToUse(bTerminal, aTerminal, info.B.edges); let route; if (aSide && bSide) { route = (0, import_routeArrowWithAutoEdgePicking.routeArrowWithManualEdgePicking)(workingInfo, aSide, bSide); } else if (aSide && !bSide) { route = (0, import_routeArrowWithAutoEdgePicking.routeArrowWithPartialEdgePicking)(workingInfo, aSide); } if (!route) { route = (0, import_routeArrowWithAutoEdgePicking.routeArrowWithAutoEdgePicking)(workingInfo, aSide || bSide ? "fallback" : "auto"); } if (route) { castPathSegmentIntoGeometry("first", info.A, info.B, route); castPathSegmentIntoGeometry("last", info.B, info.A, route); fixTinyEndNubs(route, aTerminal, bTerminal); if (swapOrder) route.points.reverse(); } return { ...info, route, midXRange: mxRange ? swapOrder ? { lo: mxRange.b, hi: mxRange.a } : { lo: mxRange.a, hi: mxRange.b } : null, midYRange: myRange ? swapOrder ? { lo: myRange.b, hi: myRange.a } : { lo: myRange.a, hi: myRange.b } : null }; } function getRouteHandlePath(info, route) { const startTarget = info.swapOrder ? info.B.target : info.A.target; const endTarget = info.swapOrder ? info.A.target : info.B.target; const firstSegmentLength = import_editor.Vec.ManhattanDist(route.points[0], route.points[1]); const lastSegmentLength = import_editor.Vec.ManhattanDist( route.points[route.points.length - 2], route.points[route.points.length - 1] ); const newFirstSegmentLength = import_editor.Vec.ManhattanDist(startTarget, route.points[1]); const newLastSegmentLength = import_editor.Vec.ManhattanDist(route.points[route.points.length - 2], endTarget); const firstSegmentLengthChange = firstSegmentLength - newFirstSegmentLength; const lastSegmentLengthChange = lastSegmentLength - newLastSegmentLength; const newPoints = [startTarget, ...route.points, endTarget]; return { name: route.name, distance: route.distance + firstSegmentLengthChange + lastSegmentLengthChange, points: newPoints.filter((p) => !route.skipPointsWhenDrawing.has(p)), aEdgePicking: route.aEdgePicking, bEdgePicking: route.bEdgePicking, skipPointsWhenDrawing: route.skipPointsWhenDrawing, midpointHandle: route.midpointHandle }; } function getEdgeFromNormalizedAnchor(normalizedAnchor) { if ((0, import_editor.approximately)(normalizedAnchor.x, 0.5) && (0, import_editor.approximately)(normalizedAnchor.y, 0.5)) { return null; } if (Math.abs(normalizedAnchor.x - 0.5) > // slightly bias towards x arrows to prevent flickering when the anchor is right on the line // between the two directions Math.abs(normalizedAnchor.y - 0.5) - 1e-4) { return normalizedAnchor.x < 0.5 ? "left" : "right"; } return normalizedAnchor.y < 0.5 ? "top" : "bottom"; } function getElbowArrowTerminalInfo(editor, arrow, binding, point) { const arrowStrokeSize = import_shared.STROKE_SIZES[arrow.props.size] * arrow.props.scale / 2; const minEndSegmentLength = arrowStrokeSize * 3; if (binding) { const target = editor.getShape(binding.toId); const geometry = getBindingGeometryInArrowSpace(editor, arrow, binding.toId, binding.props); if (geometry && target) { let arrowheadOffset = 0; const arrowheadProp = binding.props.terminal === "start" ? "arrowheadStart" : "arrowheadEnd"; if (arrow.props[arrowheadProp] !== "none") { const targetScale = "scale" in target.props ? target.props.scale : 1; const targetStrokeSize = "size" in target.props ? (import_shared.STROKE_SIZES[target.props.size] ?? 0) * targetScale / 2 : 0; arrowheadOffset = arrowStrokeSize + targetStrokeSize + import_shared.BOUND_ARROW_OFFSET * arrow.props.scale; } let side = null; const targetPoint = geometry.target; if (binding.props.isPrecise) { side = getEdgeFromNormalizedAnchor( import_editor.Vec.RotWith( binding.props.normalizedAnchor, { x: 0.5, y: 0.5 }, geometry.shapeToArrowTransform.rotation() ) ); } return { targetShapeId: binding.toId, isPoint: false, isExact: binding.props.isExact, bounds: geometry.bounds, geometry: geometry.geometry, target: targetPoint, arrowheadOffset, minEndSegmentLength, side, snap: binding.props.snap }; } } return { targetShapeId: null, bounds: import_editor.Box.FromCenter(point, { x: 0, y: 0 }), geometry: null, isExact: false, isPoint: true, target: import_editor.Vec.From(point), arrowheadOffset: 0, minEndSegmentLength, side: null, snap: "none" }; } function getBindingGeometryInArrowSpace(editor, arrow, targetId, bindingProps) { const hasArrowhead = bindingProps.terminal === "start" ? arrow.props.arrowheadStart !== "none" : arrow.props.arrowheadEnd !== "none"; const targetGeometryInTargetSpace = editor.getShapeGeometry( targetId, hasArrowhead ? void 0 : { context: "@tldraw/arrow-without-arrowhead" } ); if (!targetGeometryInTargetSpace) { return null; } const arrowTransform = editor.getShapePageTransform(arrow.id); const shapeTransform = editor.getShapePageTransform(targetId); const shapeToArrowTransform = arrowTransform.clone().invert().multiply(shapeTransform); const targetGeometryInArrowSpace = targetGeometryInTargetSpace.transform(shapeToArrowTransform); const center = { x: 0.5, y: 0.5 }; const normalizedAnchor = bindingProps.isPrecise ? bindingProps.normalizedAnchor : center; const targetInShapeSpace = { x: (0, import_editor.lerp)( targetGeometryInTargetSpace.bounds.minX, targetGeometryInTargetSpace.bounds.maxX, normalizedAnchor.x ), y: (0, import_editor.lerp)( targetGeometryInTargetSpace.bounds.minY, targetGeometryInTargetSpace.bounds.maxY, normalizedAnchor.y ) }; const centerInShapeSpace = { x: (0, import_editor.lerp)( targetGeometryInTargetSpace.bounds.minX, targetGeometryInTargetSpace.bounds.maxX, center.x ), y: (0, import_editor.lerp)( targetGeometryInTargetSpace.bounds.minY, targetGeometryInTargetSpace.bounds.maxY, center.y ) }; const targetInArrowSpace = import_editor.Mat.applyToPoint(shapeToArrowTransform, targetInShapeSpace); const centerInArrowSpace = import_editor.Mat.applyToPoint(shapeToArrowTransform, centerInShapeSpace); return { bounds: targetGeometryInArrowSpace.bounds, geometry: targetGeometryInArrowSpace, target: targetInArrowSpace, center: centerInArrowSpace, shapeToArrowTransform }; } const sideProps = { top: { expand: -1, main: "minY", opposite: "maxY", crossMid: "midX", crossMin: "minX", crossMax: "maxX", bRangeExpand: "max", crossAxis: "x" }, bottom: { expand: 1, main: "maxY", opposite: "minY", crossMid: "midX", crossMin: "minX", crossMax: "maxX", bRangeExpand: "min", crossAxis: "x" }, left: { expand: -1, main: "minX", opposite: "maxX", crossMid: "midY", crossMin: "minY", crossMax: "maxY", bRangeExpand: "max", crossAxis: "y" }, right: { expand: 1, main: "maxX", opposite: "minX", crossMid: "midY", crossMin: "minY", crossMax: "maxY", bRangeExpand: "min", crossAxis: "y" } }; function getUsableEdge(a, b, side, options) { const props = sideProps[side]; const isSelfBoundAndShouldRouteExternal = a.targetShapeId === b.targetShapeId && a.targetShapeId !== null && (a.snap === "edge" || a.snap === "edge-point") && (b.snap === "edge" || b.snap === "edge-point"); const aValue = a.bounds[props.main]; const aExpanded = a.isPoint ? null : aValue + props.expand * options.expandElbowLegLength; const originalACrossRange = (0, import_range.createRange)(a.bounds[props.crossMin], a.bounds[props.crossMax]); let aCrossRange = originalACrossRange; if (!aCrossRange) { return null; } (0, import_editor.assert)(originalACrossRange); const bRange = (0, import_range.createRange)(b.bounds[props.main], b.bounds[props.opposite]); if (!b.isPoint) { bRange[props.bRangeExpand] -= options.minElbowLegLength * 2 * props.expand; } const bCrossRange = (0, import_range.expandRange)( (0, import_range.createRange)(b.bounds[props.crossMin], b.bounds[props.crossMax]), options.expandElbowLegLength ); (0, import_editor.assert)(bRange && bCrossRange); let isPartial = false; if ((0, import_range.isWithinRange)(aValue, bRange) && !a.isPoint && !b.isPoint && !isSelfBoundAndShouldRouteExternal) { const subtracted = (0, import_range.subtractRange)(aCrossRange, bCrossRange); switch (subtracted.length) { case 0: return null; case 1: isPartial = subtracted[0] !== aCrossRange; aCrossRange = subtracted[0]; break; case 2: isPartial = true; aCrossRange = (0, import_range.rangeSize)(subtracted[0]) > (0, import_range.rangeSize)(subtracted[1]) ? subtracted[0] : subtracted[1]; break; default: (0, import_editor.exhaustiveSwitchError)(subtracted); } } if (!(0, import_range.isWithinRange)(a.target[props.crossAxis], aCrossRange)) { return null; } const crossTarget = a.target[props.crossAxis]; return { value: aValue, expanded: aExpanded, cross: aCrossRange, crossTarget, isPartial }; } function hasUsableEdge(edges, side) { if (side === null) { return !!(edges.bottom || edges.left || edges.right || edges.top); } if (side === "x") { return !!edges.left || !!edges.right; } if (side === "y") { return !!edges.top || !!edges.bottom; } return !!edges[side]; } function getSideToUse(binding, other, edges) { switch (binding.side) { case null: return null; case "x": if (binding.bounds.center.x > other.bounds.center.x && edges?.left) { return "left"; } else if (edges?.right) { return "right"; } return null; case "y": if (binding.bounds.center.y > other.bounds.center.y && edges?.top) { return "top"; } else if (edges?.bottom) { return "bottom"; } return null; default: return binding.side; } } function convertTerminalToPoint(terminal) { if (terminal.isPoint) return terminal; let side = null; let arrowheadOffset = 0; if (terminal.snap === "edge" || terminal.snap === "edge-point") { arrowheadOffset = terminal.arrowheadOffset; if (terminal.side === "x" || terminal.side === "left" || terminal.side === "right") { side = "x"; } if (terminal.side === "y" || terminal.side === "top" || terminal.side === "bottom") { side = "y"; } } return { targetShapeId: terminal.targetShapeId, side, bounds: new import_editor.Box(terminal.target.x, terminal.target.y, 0, 0), geometry: terminal.geometry, target: terminal.target, arrowheadOffset, minEndSegmentLength: terminal.minEndSegmentLength, isExact: terminal.isExact, isPoint: true, snap: terminal.snap }; } function castPathSegmentIntoGeometry(segment, target, other, route) { if (!target.geometry) return; const point1 = segment === "first" ? route.points[0] : route.points[route.points.length - 1]; const point2 = segment === "first" ? route.points[1] : route.points[route.points.length - 2]; const pointToFindClosestIntersectionTo = target.geometry.isClosed ? point2 : target.target; const initialDistance = import_editor.Vec.ManhattanDist(point1, pointToFindClosestIntersectionTo); let nearestIntersectionToPoint2 = null; let nearestDistanceToPoint2 = Infinity; if (target.isExact) { nearestIntersectionToPoint2 = target.target; } else if (target.geometry) { const intersections = target.geometry.intersectLineSegment(point2, target.target, { includeLabels: false, includeInternal: false }); if (target.geometry.hitTestPoint( target.target, Math.max(1, target.arrowheadOffset), true, import_editor.Geometry2dFilters.EXCLUDE_NON_STANDARD )) { intersections.push(target.target); } for (const intersection of intersections) { const point2Distance = import_editor.Vec.ManhattanDist(pointToFindClosestIntersectionTo, intersection); if (point2Distance < nearestDistanceToPoint2) { nearestDistanceToPoint2 = point2Distance; nearestIntersectionToPoint2 = intersection; } } } if (nearestIntersectionToPoint2) { let offset = target.arrowheadOffset; const currentFinalSegmentLength = import_editor.Vec.ManhattanDist(point2, nearestIntersectionToPoint2); const minLength = target.arrowheadOffset * 2; if (currentFinalSegmentLength < minLength) { const targetLength = minLength - target.arrowheadOffset; offset = currentFinalSegmentLength - targetLength; } if (offset < target.minEndSegmentLength) { if (target.geometry.bounds.containsPoint(other.target)) { offset = Math.max(0, offset); } else { offset = -target.arrowheadOffset; } } let nudgedPoint = nearestIntersectionToPoint2; let shouldAddExtraPointForNudge = false; if (!target.isExact && offset !== 0) { const nudged = import_editor.Vec.Nudge(nearestIntersectionToPoint2, point2, offset); nudgedPoint = nudged; if (offset < 0 && !target.geometry.hitTestPoint(nudged, 0, true, import_editor.Geometry2dFilters.EXCLUDE_NON_STANDARD)) { nudgedPoint = nearestIntersectionToPoint2; } else { if (offset < 0) { shouldAddExtraPointForNudge = true; } nudgedPoint = nudged; } } const newDistance = import_editor.Vec.ManhattanDist(point2, nudgedPoint); route.distance += newDistance - initialDistance; point1.x = nudgedPoint.x; point1.y = nudgedPoint.y; if (shouldAddExtraPointForNudge) { const midPoint = import_editor.Vec.Lrp(point2, point1, 0.5); route.skipPointsWhenDrawing.add(midPoint); route.points.splice(segment === "first" ? 1 : route.points.length - 1, 0, midPoint); } } } function fixTinyEndNubs(route, aTerminal, bTerminal) { if (!route) return; if (route.points.length >= 3) { const a = route.points[0]; const b = route.points[1]; const firstSegmentLength = import_editor.Vec.ManhattanDist(a, b); if (firstSegmentLength < aTerminal.minEndSegmentLength) { route.points.splice(1, 1); if (route.points.length >= 3) { const matchAxis = (0, import_editor.approximately)(a.x, b.x) ? "y" : "x"; route.points[1][matchAxis] = a[matchAxis]; } } } if (route.points.length >= 3) { const a = route.points[route.points.length - 1]; const b = route.points[route.points.length - 2]; const lastSegmentLength = import_editor.Vec.ManhattanDist(a, b); if (lastSegmentLength < bTerminal.minEndSegmentLength) { route.points.splice(route.points.length - 2, 1); if (route.points.length >= 3) { const matchAxis = (0, import_editor.approximately)(a.x, b.x) ? "y" : "x"; route.points[route.points.length - 2][matchAxis] = a[matchAxis]; } } } } function adjustTerminalForUnclosedPathIfNeeded(terminal, otherTerminal, options) { if (!terminal.geometry || terminal.geometry.isClosed) return terminal; const normalizedPointAlongPath = terminal.geometry.uninterpolateAlongEdge( terminal.target, import_editor.Geometry2dFilters.EXCLUDE_NON_STANDARD ); const prev = terminal.geometry.interpolateAlongEdge( normalizedPointAlongPath - 0.01 / terminal.geometry.length ); const next = terminal.geometry.interpolateAlongEdge( normalizedPointAlongPath + 0.01 / terminal.geometry.length ); const normal = next.sub(prev).per().uni(); const axis = Math.abs(normal.x) > Math.abs(normal.y) ? import_definitions.ElbowArrowAxes.x : import_definitions.ElbowArrowAxes.y; if (terminal.geometry.bounds.containsPoint(otherTerminal.target, options.expandElbowLegLength)) { terminal.side = axis.self; return convertTerminalToPoint(terminal); } const min = axis.v( terminal.target[axis.self] - terminal.bounds[axis.size] * 2, terminal.target[axis.cross] ); const max = axis.v( terminal.target[axis.self] + terminal.bounds[axis.size] * 2, terminal.target[axis.cross] ); let furthestIntersectionTowardsMin = null; let furthestIntersectionTowardsMinDistance = 0; let furthestIntersectionTowardsMax = null; let furthestIntersectionTowardsMaxDistance = 0; let side = axis.self; for (const intersection of terminal.geometry.intersectLineSegment( min, max, import_editor.Geometry2dFilters.EXCLUDE_NON_STANDARD )) { if (Math.abs(intersection[axis.self] - terminal.target[axis.self]) < 1) { continue; } if (intersection[axis.self] < terminal.target[axis.self]) { if (import_editor.Vec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMinDistance) { furthestIntersectionTowardsMinDistance = import_editor.Vec.ManhattanDist(intersection, terminal.target); furthestIntersectionTowardsMin = intersection; } } else { if (import_editor.Vec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMaxDistance) { furthestIntersectionTowardsMaxDistance = import_editor.Vec.ManhattanDist(intersection, terminal.target); furthestIntersectionTowardsMax = intersection; } } } if (furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) { if (furthestIntersectionTowardsMinDistance > furthestIntersectionTowardsMaxDistance) { side = axis.hiEdge; } else { side = axis.loEdge; } } else if (furthestIntersectionTowardsMin && !furthestIntersectionTowardsMax) { side = axis.hiEdge; } else if (!furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) { side = axis.loEdge; } terminal.side = side; return terminal; } //# sourceMappingURL=getElbowArrowInfo.js.map