@syncfusion/ej2-diagrams
Version:
Feature-rich diagram control to create diagrams like flow charts, organizational charts, mind maps, and BPMN diagrams. Its rich feature set includes built-in shapes, editing, serializing, exporting, printing, overview, data binding, and automatic layouts.
476 lines (475 loc) • 22.4 kB
JavaScript
/* eslint-disable jsdoc/require-returns */
/* eslint-disable valid-jsdoc */
import { Point } from '../primitives/point';
import { Rect } from '../primitives/rect';
import { intersect2 } from '../utility/diagram-util';
import { canBridge } from '../utility/constraints-util';
/**
* ConnectorBridging defines the bridging behavior
*/
/** @private */
var ConnectorBridging = /** @class */ (function () {
/**
* Constructor for the bridging module
*
* @private
*/
function ConnectorBridging() {
//constructs the bridging module
}
/**
* @param {Connector}conn - provide the target value.
* @param {Diagram}diagram - provide the target value.
* @private
*/
ConnectorBridging.prototype.updateBridging = function (conn, diagram) {
var lastBridge = [];
var bounds;
conn.bridges = [];
if (canBridge(conn, diagram)) {
// if (this.canBridge(conn, diagram)) {
var points1 = this.getPoints(conn);
bounds = Rect.toBounds(points1);
var bridgeSpacing = conn.bridgeSpace;
var bgedir = diagram.bridgeDirection || 'Top';
var count = -1;
var quads = diagram.connectors;
for (var q = 0; q < quads.length; q++) {
var connector1 = quads[parseInt(q.toString(), 10)];
//EJ2-868564- Bridging is enabled when connector visibility is set to False
if (conn && connector1 && conn.id !== connector1.id && connector1.visible) {
var points2 = this.getPoints(connector1);
var bounds1 = Rect.toBounds(points2);
if (this.intersectsRect(bounds, bounds1)) {
var intersectPts = this.intersect(points1, points2, false, bgedir, true);
if (intersectPts.length > 0) {
for (var i = 0; i < intersectPts.length; i++) {
var fullLength = 0;
var length_1 = 0;
var segmentIndex = 0;
var pointIndex = 0;
var obj = this.getLengthAtFractionPoint(conn, intersectPts[parseInt(i.toString(), 10)]);
if (obj.pointIndex !== -1) {
length_1 = obj.lengthFractionIndex;
fullLength = obj.fullLength;
segmentIndex = obj.segmentIndex;
pointIndex = obj.pointIndex;
var stBridge = this.getPointAtLength((length_1 - (bridgeSpacing / 2)), points1);
var enBridge = this.getPointAtLength((length_1 + (bridgeSpacing / 2)), points1);
var fractLength = (length_1 - (bridgeSpacing / 2)) / fullLength;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fractLength = (length_1 + (bridgeSpacing / 2)) / fullLength;
if (this.isEmptyPoint(enBridge)) {
enBridge = stBridge;
}
var end = void 0;
var start = conn.sourcePoint;
if (conn.type === 'Straight') {
end = conn.targetPoint;
}
else {
end = conn.intermediatePoints[parseInt(pointIndex.toString(), 10)];
}
var angle = this.angleCalculation(start, end);
if (lastBridge.length) {
var fixedPoint = conn.sourcePoint;
var fix = Math.abs(this.lengthCalculation(fixedPoint, enBridge));
var var1 = 0;
var insertAt = -1;
count = -1;
for (var k = 0; k < lastBridge[parseInt(segmentIndex.toString(), 10)].bridges.length; k++) {
count++;
var arcSeg = lastBridge[parseInt(segmentIndex.toString(), 10)].bridges[parseInt(k.toString(), 10)];
var1 = Math.abs(this.lengthCalculation(fixedPoint, arcSeg.endPoint));
if (fix < var1) {
insertAt = count;
break;
}
}
if (insertAt >= 0) {
//let paths: ArcSegment;
// eslint-disable-next-line max-len
var paths = this.createSegment(stBridge, enBridge, angle, bgedir, pointIndex, conn, diagram);
paths.target = connector1.id;
lastBridge[parseInt(segmentIndex.toString(), 10)].bridges.splice(insertAt, 0, paths);
lastBridge[parseInt(segmentIndex.toString(), 10)].bridges.join();
lastBridge[parseInt(segmentIndex.toString(), 10)].bridgeStartPoint.splice(insertAt, 0, stBridge);
lastBridge[parseInt(segmentIndex.toString(), 10)].bridgeStartPoint.join();
lastBridge[parseInt(segmentIndex.toString(), 10)].segmentIndex = segmentIndex;
}
else {
//let paths: ArcSegment;
// eslint-disable-next-line max-len
var paths = this.createSegment(stBridge, enBridge, angle, bgedir, pointIndex, conn, diagram);
paths.target = connector1.id;
lastBridge[parseInt(segmentIndex.toString(), 10)].bridges.push(paths);
lastBridge[parseInt(segmentIndex.toString(), 10)].bridgeStartPoint.push(stBridge);
lastBridge[parseInt(segmentIndex.toString(), 10)].segmentIndex = segmentIndex;
}
}
else {
if (!isNaN(stBridge.x) && !isNaN(stBridge.y) && !this.isEmptyPoint(enBridge)) {
//let arcs: ArcSegment;
var bges = [];
var bgept = [];
// eslint-disable-next-line max-len
var arcs = this.createSegment(stBridge, enBridge, angle, bgedir, pointIndex, conn, diagram);
var bgseg = {
bridges: bges, bridgeStartPoint: bgept, segmentIndex: segmentIndex
};
arcs.target = connector1.id;
var stPoints = [];
var edPoints = [];
stPoints.push(stBridge);
edPoints.push(enBridge);
lastBridge[parseInt(segmentIndex.toString(), 10)] = bgseg;
lastBridge[parseInt(segmentIndex.toString(), 10)].bridges.push(arcs);
lastBridge[parseInt(segmentIndex.toString(), 10)].bridgeStartPoint = stPoints;
lastBridge[parseInt(segmentIndex.toString(), 10)].segmentIndex = segmentIndex;
}
}
}
}
}
}
}
}
if (lastBridge.length !== 0) {
this.firstBridge(lastBridge, conn, bridgeSpacing);
}
}
};
/**
* @param {BridgeSegment[]}bridgeList - provide the bridgeList value.
* @param {Connector}connector - provide the connector value.
* @param {number}bridgeSpacing - provide the bridgeSpacing value.
* @private
*/
ConnectorBridging.prototype.firstBridge = function (bridgeList, connector, bridgeSpacing) {
for (var i = 0; i < bridgeList.length; i++) {
var bridge = bridgeList[parseInt(i.toString(), 10)];
for (var k = 1; k < bridge.bridges.length; k++) {
if (Point.findLength(bridge.bridges[parseInt(k.toString(), 10)].endPoint, bridge.bridges[k - 1].endPoint) < bridgeSpacing) {
bridge.bridges[k - 1].endPoint = bridge.bridges[parseInt(k.toString(), 10)].endPoint;
var subBridge = bridge.bridges[k - 1];
var arc = this.createBridgeSegment(subBridge.startPoint, subBridge.endPoint, subBridge.angle, bridgeSpacing, subBridge.sweep);
bridge.bridges[k - 1].path = arc;
bridge.bridges.splice(k, 1);
bridge.bridgeStartPoint.splice(k, 1);
k--;
}
}
var pre = connector.sourcePoint;
for (var j = 0; j < bridge.bridges.length; j++) {
var subBridge = bridge.bridges[parseInt(j.toString(), 10)]; //const preventChecking: boolean = true;
pre = subBridge.endPoint;
connector.bridges.push(subBridge);
}
}
};
/**
* @returns { ArcSegment } checkSourcePointInTarget method .\
* @param {PointModel}st- provide the st value.
* @param {PointModel}end- provide the end value.
* @param {number}angle- provide the angle value.
* @param {BridgeDirection}direction- provide the direction value.
* @param {number}index- provide the index value.
* @param {Connector}conn- provide the conn value.
* @param {Diagram} diagram- provide the diagram value.
* @private
*/
ConnectorBridging.prototype.createSegment = function (st, end, angle, direction, index, conn, diagram) {
//let arc: string;
//let sweep: number;
var path = {
angle: 0, endPoint: { x: 0, y: 0 }, target: '', path: '',
segmentPointIndex: -1, startPoint: { x: 0, y: 0 }, sweep: 1, rendered: false
};
var sweep = this.sweepDirection(angle, direction, conn, diagram);
var arc = this.createBridgeSegment(st, end, angle, conn.bridgeSpace, sweep);
path.path = arc;
path.startPoint = st;
path.endPoint = end;
path.angle = angle;
path.segmentPointIndex = index;
path.sweep = sweep;
return path;
};
/**
* @param {PointModel}startPt- provide the startPt value.
* @param {PointModel}endPt- provide the endPt value.
* @param {number}angle- provide the angle value.
* @param {number}bridgeSpace- provide the bridgeSpace value.
* @param {number}sweep- provide the sweep value.
* @private
*/
ConnectorBridging.prototype.createBridgeSegment = function (startPt, endPt, angle, bridgeSpace, sweep) {
var path = 'A ' + bridgeSpace / 2 + ' ' + bridgeSpace / 2 + ' ' + angle + ' , 1 ' + sweep + ' ' + endPt.x + ',' + endPt.y;
return path;
};
/**
* @param {number}angle- provide the source value.
* @param {BridgeDirection}bridgeDirection- provide the source value.
* @param {Connector}connector- provide the source value.
* @param {Diagram}diagram- provide the source value.
* @private
*/
ConnectorBridging.prototype.sweepDirection = function (angle, bridgeDirection, connector, diagram) {
var angle1 = Math.abs(angle);
var sweep;
switch (bridgeDirection) {
case 'Top':
case 'Bottom':
sweep = 1;
if (angle1 >= 0 && angle1 <= 90) {
sweep = 0;
}
break;
case 'Left':
case 'Right':
sweep = 1;
if (angle < 0 && angle >= -180) {
sweep = 0;
}
break;
}
if (bridgeDirection === 'Right' || bridgeDirection === 'Bottom') {
if (sweep === 0) {
sweep = 1;
}
else {
sweep = 0;
}
}
return sweep;
};
/** @private */
ConnectorBridging.prototype.getPointAtLength = function (length, pts) {
var run = 0;
var pre;
var found = { x: 0, y: 0 };
for (var i = 0; i < pts.length; i++) {
var pt = pts[parseInt(i.toString(), 10)];
if (!pre) {
pre = pt;
continue;
}
else {
var l = this.lengthCalculation(pre, pt);
if (run + l > length) {
var r = length - run;
var deg = Point.findAngle(pre, pt);
var x = r * Math.cos(deg * Math.PI / 180);
var y = r * Math.sin(deg * Math.PI / 180);
found = { x: pre.x + x, y: pre.y + y };
break;
}
else {
run += l;
}
}
pre = pt;
}
return found;
};
/**
* @param {PointModel[]}connector- provide the source value.
* @private
*/
ConnectorBridging.prototype.getPoints = function (connector) {
var points = [];
if (connector.intermediatePoints && (connector.type === 'Straight' || connector.type === 'Orthogonal')) {
for (var j = 0; j < connector.intermediatePoints.length; j++) {
points.push(connector.intermediatePoints[parseInt(j.toString(), 10)]);
}
}
return points;
};
ConnectorBridging.prototype.intersectsRect = function (rect1, rect2) {
return ((((rect2.x < (rect1.x + rect1.width)) && (rect1.x < (rect2.x + rect2.width)))
&& (rect2.y < (rect1.y + rect1.height))) && (rect1.y < (rect2.y + rect2.height)));
};
/**
* @param {PointModel[]}points1- provide the source value.
* @param {PointModel[]}points2- provide the source value.
* @param {boolean}self- provide the source value.
* @param {BridgeDirection}bridgeDirection- provide the source value.
* @param {PointModel[]}zOrder- provide the source value.
* @private
*/
ConnectorBridging.prototype.intersect = function (points1, points2, self, bridgeDirection, zOrder) {
if (self && points2.length >= 2) {
points2.splice(0, 1);
points2.splice(0, 1);
}
var points = [];
for (var i = 0; i < points1.length - 1; i++) {
var pt = this.inter1(points1[parseInt(i.toString(), 10)], points1[i + 1], points2, zOrder, bridgeDirection);
if (pt.length > 0) {
for (var k = 0; k < pt.length; k++) {
points.push(pt[parseInt(k.toString(), 10)]);
}
}
if (self && points2.length >= 1) {
points2.splice(0, 1);
}
}
return points;
};
/**
* @param {PointModel}startPt- provide the target value.
* @param {PointModel}endPt- provide the target value.
* @param {PointModel[]}pts- provide the target value.
* @param {boolean}zOrder- provide the target value.
* @param {BridgeDirection}bridgeDirection- provide the target value.
* @private
*/
ConnectorBridging.prototype.inter1 = function (startPt, endPt, pts, zOrder, bridgeDirection) {
var points1 = [];
for (var i = 0; i < pts.length - 1; i++) {
var point = intersect2(startPt, endPt, pts[parseInt(i.toString(), 10)], pts[i + 1]);
if (!this.isEmptyPoint(point)) {
var angle = this.angleCalculation(startPt, endPt);
var angle1 = this.angleCalculation(pts[parseInt(i.toString(), 10)], pts[i + 1]);
angle = this.checkForHorizontalLine(angle);
angle1 = this.checkForHorizontalLine(angle1);
switch (bridgeDirection) {
case 'Left':
case 'Right':
if (angle > angle1) {
points1.push(point);
}
break;
case 'Top':
case 'Bottom':
if (angle < angle1) {
points1.push(point);
}
break;
}
if (angle === angle1 && zOrder) {
points1.push(point);
}
}
}
return points1;
};
ConnectorBridging.prototype.checkForHorizontalLine = function (angle) {
var temp = 0;
var roundedAngle = Math.abs(angle);
if (roundedAngle > 90) {
temp = 180 - roundedAngle;
}
else {
temp = roundedAngle;
}
return temp;
};
ConnectorBridging.prototype.isEmptyPoint = function (point) {
return point.x === 0 && point.y === 0;
};
ConnectorBridging.prototype.getLengthAtFractionPoint = function (connector, pointAt) {
var confirm = 100;
var pointIndex = -1;
var fullLength = 0;
var segmentIndex = -1;
var count = 0;
var lengthAtFractionPt = 0;
var pt1 = connector.sourcePoint;
var previouspt2 = pt1;
var points = [];
for (var i = 0; i < connector.intermediatePoints.length; i++) {
var point2 = connector.intermediatePoints[parseInt(i.toString(), 10)];
points.push(point2);
}
for (var j = 0; j < points.length; j++) {
var pt2 = points[parseInt(j.toString(), 10)];
var suspect = this.getSlope(pt2, pt1, pointAt, connector);
if (suspect < confirm) {
confirm = suspect;
lengthAtFractionPt = fullLength + this.lengthCalculation(pointAt, previouspt2);
segmentIndex = count;
pointIndex = j;
}
fullLength += Point.findLength(pt2, pt1);
pt1 = pt2;
previouspt2 = pt2;
}
count++;
var lengthFraction = {
lengthFractionIndex: lengthAtFractionPt, fullLength: fullLength,
segmentIndex: segmentIndex, pointIndex: pointIndex
};
return lengthFraction;
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ConnectorBridging.prototype.getSlope = function (startPt, endPt, point, connector) {
var three = 3.0;
var delX = Math.abs(startPt.x - endPt.x);
var delY = Math.abs(startPt.y - endPt.y);
var lhs = ((point.y - startPt.y) / (endPt.y - startPt.y));
var rhs = ((point.x - startPt.x) / (endPt.x - startPt.x));
if (!isFinite(lhs) || !isFinite(rhs) || isNaN(lhs) || isNaN(rhs)) {
if (startPt.x === endPt.x) {
if (startPt.y === endPt.y) {
return 10000;
}
else if (((startPt.y > point.y) && (point.y > endPt.y)) || ((startPt.y < point.y) && (point.y < endPt.y))) {
return Math.abs(startPt.x - point.x);
}
}
else if (startPt.y === endPt.y) {
if (((startPt.x > point.x) && (point.x > endPt.x)) || ((startPt.x < point.x) && (point.x < endPt.x))) {
return Math.abs(startPt.y - point.y);
}
}
}
else {
if ((startPt.x >= point.x && point.x >= endPt.x) || (startPt.x <= point.x && point.x <= endPt.x) || delX < three) {
if ((startPt.y >= point.y && point.y >= endPt.y) || (startPt.y <= point.y && point.y <= endPt.y) || delY < three) {
return Math.abs(lhs - rhs);
}
}
}
return 10000;
};
/**
* @param {PointModel}startPt- provide the target value.
* @param {PointModel}endPt- provide the target value.
* @private
*/
ConnectorBridging.prototype.angleCalculation = function (startPt, endPt) {
var xDiff = startPt.x - endPt.x;
var yDiff = startPt.y - endPt.y;
return Math.atan2(yDiff, xDiff) * (180 / Math.PI);
};
ConnectorBridging.prototype.lengthCalculation = function (startPt, endPt) {
//removed a try catch from here
var len = Math.sqrt(((startPt.x - endPt.x) * (startPt.x - endPt.x)) + ((startPt.y - endPt.y) * (startPt.y - endPt.y)));
return len;
};
/**
*To destroy the ruler
*
* @returns {void} To destroy the ruler
*/
ConnectorBridging.prototype.destroy = function () {
/**
* Destroys the bridging module
*/
};
/**
* Core method to return the component name.
*
* @returns {string} Core method to return the component name.
* @private
*/
ConnectorBridging.prototype.getModuleName = function () {
/**
* Returns the module name
*/
return 'Bridging';
};
return ConnectorBridging;
}());
export { ConnectorBridging };