UNPKG

@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
/* 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 };