Skip to content

Commit

Permalink
[routing] elliptic and diamond anchors for manhattan routing
Browse files Browse the repository at this point in the history
Fixes #67
  • Loading branch information
JanKoehnlein committed Feb 18, 2019
1 parent 8b297c5 commit 6bae21d
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/features/routing/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { ContainerModule } from "inversify";
import { TYPES } from "../../base/types";
import { ManhattanEdgeRouter } from "./manhattan-edge-router";
import { PolylineEdgeRouter } from "./polyline-edge-router";
import { ManhattanRectangularAnchor } from "./manhattan-anchors";
import { ManhattanRectangularAnchor, ManhattanEllipticAnchor, ManhattanDiamondAnchor } from "./manhattan-anchors";
import { RectangleAnchor, EllipseAnchor, DiamondAnchor } from "./polyline-anchors";
import { AnchorComputerRegistry } from "./anchor";
import { EdgeRouterRegistry } from "./routing";
Expand All @@ -30,7 +30,9 @@ const routingModule = new ContainerModule(bind => {

bind(ManhattanEdgeRouter).toSelf().inSingletonScope();
bind(TYPES.IEdgeRouter).toService(ManhattanEdgeRouter);
bind(TYPES.IAnchorComputer).to(ManhattanEllipticAnchor).inSingletonScope();
bind(TYPES.IAnchorComputer).to(ManhattanRectangularAnchor).inSingletonScope();
bind(TYPES.IAnchorComputer).to(ManhattanDiamondAnchor).inSingletonScope();

bind(PolylineEdgeRouter).toSelf().inSingletonScope();
bind(TYPES.IEdgeRouter).toService(PolylineEdgeRouter);
Expand Down
101 changes: 99 additions & 2 deletions src/features/routing/manhattan-anchors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { center, Point, Bounds } from "../../utils/geometry";
import { RECTANGULAR_ANCHOR_KIND, IAnchorComputer } from "./anchor";
import { center, Point, Bounds, Line, PointToPointLine, intersection, subtract } from "../../utils/geometry";
import { RECTANGULAR_ANCHOR_KIND, IAnchorComputer, DIAMOND_ANCHOR_KIND, ELLIPTIC_ANCHOR_KIND } from "./anchor";
import { ManhattanEdgeRouter } from "./manhattan-edge-router";
import { SConnectableElement } from "./model";
import { injectable } from "inversify";
Expand Down Expand Up @@ -54,3 +54,100 @@ export class ManhattanRectangularAnchor implements IAnchorComputer {
return center(bounds);
}
}

@injectable()
export class ManhattanDiamondAnchor implements IAnchorComputer {

static KIND = ManhattanEdgeRouter.KIND + ':' + DIAMOND_ANCHOR_KIND;

get kind() {
return ManhattanDiamondAnchor.KIND;
}

getAnchor(connectable: SConnectableElement, refPoint: Point, offset: number = 0): Point {
const b = connectable.bounds;
const bounds = {
x: b.x - offset,
y: b.y - offset,
width: b.width + 2 * offset,
height: b.height + 2 * offset
};
const c = center(bounds);

let outline: Line | undefined = undefined;
let refLine: Line | undefined = undefined;
if (refPoint.x >= bounds.x && refPoint.x <= bounds.x + bounds.width) {
if (bounds.x + 0.5 * bounds.width >= refPoint.x) {
refLine = new PointToPointLine(refPoint, { x: refPoint.x, y: c.y });
if (refPoint.y < c.y)
outline = new PointToPointLine({ x: bounds.x, y: c.y }, { x: c.x, y: bounds.y });
else
outline = new PointToPointLine({ x: bounds.x, y: c.y }, { x: c.x, y: bounds.y + bounds.height });
} else {
refLine = new PointToPointLine(refPoint, { x: refPoint.x, y: c.y });
if (refPoint.y < c.y)
outline = new PointToPointLine({ x: bounds.x + bounds.width, y: c.y }, { x: c.x, y: bounds.y });
else
outline = new PointToPointLine({ x: bounds.x + bounds.width, y: c.y }, { x: c.x, y: bounds.y + bounds.height });
}
} else if (refPoint.y >= bounds.y && refPoint.y <= bounds.y + bounds.height) {
if (bounds.y + 0.5 * bounds.height >= refPoint.y) {
refLine = new PointToPointLine(refPoint, { x: c.x , y: refPoint.y });
if (refPoint.x < c.x)
outline = new PointToPointLine({ x: bounds.x, y: c.y }, { x: c.x, y: bounds.y });
else
outline = new PointToPointLine({ x: bounds.x + bounds.width, y: c.y }, { x: c.x, y: bounds.y });
} else {
refLine = new PointToPointLine(refPoint, { x: c.x , y: refPoint.y });
if (refPoint.x < c.x)
outline = new PointToPointLine({ x: bounds.x, y: c.y }, { x: c.x, y: bounds.y + bounds.height });
else
outline = new PointToPointLine({ x: bounds.x + bounds.width, y: c.y }, { x: c.x, y: bounds.y + bounds.height });
}
}
if (!!refLine && !!outline)
return intersection(outline, refLine);
else
return c;
}
}

@injectable()
export class ManhattanEllipticAnchor implements IAnchorComputer {

static KIND = ManhattanEdgeRouter.KIND + ':' + ELLIPTIC_ANCHOR_KIND;

get kind() {
return ManhattanEllipticAnchor.KIND;
}

getAnchor(connectable: SConnectableElement, refPoint: Point, offset: number = 0): Point {
const b = connectable.bounds;
const bounds = {
x: b.x - offset,
y: b.y - offset,
width: b.width + 2 * offset,
height: b.height + 2 * offset
};
const c = center(bounds);
const refRelative = subtract(refPoint, c);
let x = c.x;
let y = c.y;
if (refPoint.x >= bounds.x && bounds.x + bounds.width >= refPoint.x) {
x += refRelative.x;
const dy = 0.5 * bounds.height * Math.sqrt(1 - (refRelative.x * refRelative.x) / (0.25 * bounds.width * bounds.width));
if (refPoint.y < c.y)
y -= dy;
else
y += dy;
} else if (refPoint.y >= bounds.y && bounds.y + bounds.height >= refPoint.y) {
y += refRelative.y;
const dx = 0.5 * bounds.width * Math.sqrt(1 - (refRelative.y * refRelative.y) / (0.25 * bounds.height * bounds.height));
if (refPoint.y < c.y)
x -= dx;
else
x += dx;
}
return { x, y };
}
}

0 comments on commit 6bae21d

Please sign in to comment.