diff --git a/packages/web/src/designer/DiagramDesignerReference.svelte b/packages/web/src/designer/DiagramDesignerReference.svelte index b753722f4..982ccfc57 100644 --- a/packages/web/src/designer/DiagramDesignerReference.svelte +++ b/packages/web/src/designer/DiagramDesignerReference.svelte @@ -41,7 +41,7 @@ y: (targetRect.top + targetRect.bottom) / 2, }; - arrowPt = intersectLineBox(src, dst, targetRect); + arrowPt = intersectLineBox(src, dst, targetRect)[0]; arrowAngle = Math.atan2(dst.y - src.y, dst.x - src.x); } diff --git a/packages/web/src/designer/SpringyAlg.ts b/packages/web/src/designer/SpringyAlg.ts index 2cf35bab5..4f7841391 100644 --- a/packages/web/src/designer/SpringyAlg.ts +++ b/packages/web/src/designer/SpringyAlg.ts @@ -11,6 +11,7 @@ const STEP_COUNT = 100; const TIMESTEP = 0.2; const MAX_OVERLAPS_MOVES = 100; const SOLVE_OVERLAPS_FROM_STEP = 90; +const OVERLAP_DISTANCE_ADD = 15; export interface ISpringyNodePosition { nodeData: any; @@ -331,6 +332,8 @@ export class ForceDirectedLayout { }); } + attractFromLines() {} + updateVelocity(timestep: number) { this.eachNode((node, point) => { // Is this, along with updatePosition below, the only places that your @@ -354,7 +357,7 @@ export class ForceDirectedLayout { solveOverlaps() { this.eachNode((n1, point1) => { for (let i = 0; i < MAX_OVERLAPS_MOVES; i += 1) { - let overlap = false; + let overlapDistance = null; this.eachNode((n2, point2) => { if (n1 == n2) return; const distance = rectangle_distance( @@ -368,13 +371,19 @@ export class ForceDirectedLayout { point2.position.y + n2.height / 2 ); if (distance == null) { - overlap = true; + overlapDistance = 0; + } + if (distance < OVERLAP_DISTANCE_ADD) { + if (overlapDistance == null || distance < overlapDistance) overlapDistance = distance; } }); - if (!overlap) { + if (overlapDistance == null) { break; } - point1.position = point1.position.add(point1.velocity.multiply(TIMESTEP)); + point1.position = point1.position.add( + point1.velocity.normalise().multiply(OVERLAP_DISTANCE_ADD - overlapDistance) + ); + point1.velocity = point1.velocity.multiply(0.9); } }); } @@ -431,6 +440,7 @@ export class ForceDirectedLayout { this.applyCoulombsLaw(); this.applyHookesLaw(); this.attractToCentre(); + this.attractFromLines(); this.updateVelocity(timestep); this.updatePosition(timestep); if (stepNumber >= SOLVE_OVERLAPS_FROM_STEP) { diff --git a/packages/web/src/designer/designerMath.ts b/packages/web/src/designer/designerMath.ts index 94b3bac3d..34984020c 100644 --- a/packages/web/src/designer/designerMath.ts +++ b/packages/web/src/designer/designerMath.ts @@ -12,15 +12,15 @@ interface IBoxBounds { // helpers for figuring out where to draw arrows export function intersectLineLine(p1: IPoint, p2: IPoint, p3: IPoint, p4: IPoint): IPoint { - var denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y); + const denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y); // lines are parallel if (denom === 0) { return null; } - var ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom; - var ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom; + const ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom; + const ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom; if (ua < 0 || ua > 1 || ub < 0 || ub > 1) { return null; @@ -32,25 +32,26 @@ export function intersectLineLine(p1: IPoint, p2: IPoint, p3: IPoint, p4: IPoint }; } -export function intersectLineBox(p1: IPoint, p2: IPoint, box: IBoxBounds): IPoint { - var tl = { x: box.left, y: box.top }; - var tr = { x: box.right, y: box.top }; - var bl = { x: box.left, y: box.bottom }; - var br = { x: box.right, y: box.bottom }; +export function intersectLineBox(p1: IPoint, p2: IPoint, box: IBoxBounds): IPoint[] { + const tl = { x: box.left, y: box.top }; + const tr = { x: box.right, y: box.top }; + const bl = { x: box.left, y: box.bottom }; + const br = { x: box.right, y: box.bottom }; - var result; - if ((result = intersectLineLine(p1, p2, tl, tr))) { - return result; + const res = []; + let item; + if ((item = intersectLineLine(p1, p2, tl, tr))) { + res.push(item); } // top - if ((result = intersectLineLine(p1, p2, tr, br))) { - return result; + if ((item = intersectLineLine(p1, p2, tr, br))) { + res.push(item); } // right - if ((result = intersectLineLine(p1, p2, br, bl))) { - return result; + if ((item = intersectLineLine(p1, p2, br, bl))) { + res.push(item); } // bottom - if ((result = intersectLineLine(p1, p2, bl, tl))) { - return result; + if ((item = intersectLineLine(p1, p2, bl, tl))) { + res.push(item); } // left - return null; + return res; }