sprotty
Version:
A next-gen framework for graphical views
132 lines • 6.18 kB
JavaScript
;
/********************************************************************************
* Copyright (c) 2019 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiamondAnchor = exports.RectangleAnchor = exports.EllipseAnchor = void 0;
const anchor_1 = require("./anchor");
const geometry_1 = require("../../utils/geometry");
const inversify_1 = require("inversify");
const polyline_edge_router_1 = require("./polyline-edge-router");
const geometry_2 = require("sprotty-protocol/lib/utils/geometry");
let EllipseAnchor = class EllipseAnchor {
get kind() {
return polyline_edge_router_1.PolylineEdgeRouter.KIND + ':' + anchor_1.ELLIPTIC_ANCHOR_KIND;
}
getAnchor(connectable, refPoint, offset = 0) {
const bounds = connectable.bounds;
const c = geometry_2.Bounds.center(bounds);
const dx = c.x - refPoint.x;
const dy = c.y - refPoint.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const normX = (dx / distance) || 0;
const normY = (dy / distance) || 0;
return {
x: c.x - normX * (0.5 * bounds.width + offset),
y: c.y - normY * (0.5 * bounds.height + offset)
};
}
};
exports.EllipseAnchor = EllipseAnchor;
exports.EllipseAnchor = EllipseAnchor = __decorate([
(0, inversify_1.injectable)()
], EllipseAnchor);
let RectangleAnchor = class RectangleAnchor {
get kind() {
return polyline_edge_router_1.PolylineEdgeRouter.KIND + ':' + anchor_1.RECTANGULAR_ANCHOR_KIND;
}
getAnchor(connectable, refPoint, offset = 0) {
const bounds = connectable.bounds;
const c = geometry_2.Bounds.center(bounds);
const finder = new NearestPointFinder(c, refPoint);
if (!(0, geometry_2.almostEquals)(c.y, refPoint.y)) {
const xTop = this.getXIntersection(bounds.y, c, refPoint);
if (xTop >= bounds.x && xTop <= bounds.x + bounds.width)
finder.addCandidate(xTop, bounds.y - offset);
const xBottom = this.getXIntersection(bounds.y + bounds.height, c, refPoint);
if (xBottom >= bounds.x && xBottom <= bounds.x + bounds.width)
finder.addCandidate(xBottom, bounds.y + bounds.height + offset);
}
if (!(0, geometry_2.almostEquals)(c.x, refPoint.x)) {
const yLeft = this.getYIntersection(bounds.x, c, refPoint);
if (yLeft >= bounds.y && yLeft <= bounds.y + bounds.height)
finder.addCandidate(bounds.x - offset, yLeft);
const yRight = this.getYIntersection(bounds.x + bounds.width, c, refPoint);
if (yRight >= bounds.y && yRight <= bounds.y + bounds.height)
finder.addCandidate(bounds.x + bounds.width + offset, yRight);
}
return finder.best;
}
getXIntersection(yIntersection, centerPoint, point) {
const t = (yIntersection - centerPoint.y) / (point.y - centerPoint.y);
return (point.x - centerPoint.x) * t + centerPoint.x;
}
getYIntersection(xIntersection, centerPoint, point) {
const t = (xIntersection - centerPoint.x) / (point.x - centerPoint.x);
return (point.y - centerPoint.y) * t + centerPoint.y;
}
};
exports.RectangleAnchor = RectangleAnchor;
exports.RectangleAnchor = RectangleAnchor = __decorate([
(0, inversify_1.injectable)()
], RectangleAnchor);
class NearestPointFinder {
constructor(centerPoint, refPoint) {
this.centerPoint = centerPoint;
this.refPoint = refPoint;
this.currentDist = -1;
}
addCandidate(x, y) {
const dx = this.refPoint.x - x;
const dy = this.refPoint.y - y;
const dist = dx * dx + dy * dy;
if (this.currentDist < 0 || dist < this.currentDist) {
this.currentBest = {
x: x,
y: y
};
this.currentDist = dist;
}
}
get best() {
if (this.currentBest === undefined)
return this.centerPoint;
else
return this.currentBest;
}
}
let DiamondAnchor = class DiamondAnchor {
get kind() {
return polyline_edge_router_1.PolylineEdgeRouter.KIND + ':' + anchor_1.DIAMOND_ANCHOR_KIND;
}
getAnchor(connectable, refPoint, offset) {
const bounds = connectable.bounds;
const referenceLine = new geometry_1.PointToPointLine(geometry_2.Bounds.center(bounds), refPoint);
const closestDiamondSide = new geometry_1.Diamond(bounds).closestSideLine(refPoint);
const anchorPoint = (0, geometry_1.intersection)(closestDiamondSide, referenceLine);
return geometry_2.Point.shiftTowards(anchorPoint, refPoint, offset);
}
};
exports.DiamondAnchor = DiamondAnchor;
exports.DiamondAnchor = DiamondAnchor = __decorate([
(0, inversify_1.injectable)()
], DiamondAnchor);
//# sourceMappingURL=polyline-anchors.js.map