Initial implementation for cardinality position.

This commit is contained in:
Ashish Jain
2020-08-07 14:52:42 +02:00
parent a5b01c3f6f
commit 61993a032a
5 changed files with 208 additions and 1 deletions

View File

@@ -20,7 +20,7 @@
</head> </head>
<body> <body>
<h1>info below</h1> <h1>info below</h1>
<div class="mermaid" style="width: 100%; height: 20%;"> <div class="mermaid2" style="width: 100%; height: 20%;">
classDiagram-v2 classDiagram-v2
class BankAccount{ class BankAccount{
+String owner +String owner
@@ -42,6 +42,15 @@
&lt;&lt;interface&gt;&gt; classB &lt;&lt;interface&gt;&gt; classB
classB : method2() int classB : method2() int
</div> </div>
<div class="mermaid" style="width: 100%; height: 20%;">
classDiagram-v2
classA -- classB : Inheritance
classA -- classC : link
classC -- classD : link
classB -- classD
</div>
<script src="./mermaid.js"></script> <script src="./mermaid.js"></script>
<script> <script>
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {

View File

@@ -6,9 +6,11 @@ import utils from '../utils';
// import { calcLabelPosition } from '../utils'; // import { calcLabelPosition } from '../utils';
let edgeLabels = {}; let edgeLabels = {};
let terminalLabels = {};
export const clear = () => { export const clear = () => {
edgeLabels = {}; edgeLabels = {};
terminalLabels = {};
}; };
export const insertEdgeLabel = (elem, edge) => { export const insertEdgeLabel = (elem, edge) => {
@@ -39,6 +41,66 @@ export const insertEdgeLabel = (elem, edge) => {
// Update the abstract data of the edge with the new information about its width and height // Update the abstract data of the edge with the new information about its width and height
edge.width = bbox.width; edge.width = bbox.width;
edge.height = bbox.height; edge.height = bbox.height;
if (edge.startLabelLeft) {
// Create the actual text element
const startLabelElement = createLabel(edge.startLabelLeft, edge.labelStyle);
const startEdgeLabelLeft = elem.insert('g').attr('class', 'edgeTerminals');
const inner = startEdgeLabelLeft.insert('g').attr('class', 'inner');
inner.node().appendChild(startLabelElement);
const slBox = startLabelElement.getBBox();
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
if (!terminalLabels[edge.id]) {
terminalLabels[edge.id] = {};
}
terminalLabels[edge.id].startLeft = startEdgeLabelLeft;
}
if (edge.startLabelRight) {
// Create the actual text element
const startLabelElement = createLabel(edge.startLabelRight, edge.labelStyle);
const startEdgeLabelRight = elem.insert('g').attr('class', 'edgeTerminals');
const inner = startEdgeLabelRight.insert('g').attr('class', 'inner');
startEdgeLabelRight.node().appendChild(startLabelElement);
inner.node().appendChild(startLabelElement);
const slBox = startLabelElement.getBBox();
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
if (!terminalLabels[edge.id]) {
terminalLabels[edge.id] = {};
}
terminalLabels[edge.id].startRight = startEdgeLabelRight;
}
if (edge.endLabelLeft) {
// Create the actual text element
const endLabelElement = createLabel(edge.endLabelLeft, edge.labelStyle);
const endEdgeLabelLeft = elem.insert('g').attr('class', 'edgeTerminals');
const inner = endEdgeLabelLeft.insert('g').attr('class', 'inner');
inner.node().appendChild(endLabelElement);
const slBox = endLabelElement.getBBox();
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
endEdgeLabelLeft.node().appendChild(endLabelElement);
if (!terminalLabels[edge.id]) {
terminalLabels[edge.id] = {};
}
terminalLabels[edge.id].endLeft = endEdgeLabelLeft;
}
if (edge.endLabelRight) {
// Create the actual text element
const endLabelElement = createLabel(edge.endLabelRight, edge.labelStyle);
const endEdgeLabelRight = elem.insert('g').attr('class', 'edgeTerminals');
const inner = endEdgeLabelRight.insert('g').attr('class', 'inner');
inner.node().appendChild(endLabelElement);
const slBox = endLabelElement.getBBox();
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
endEdgeLabelRight.node().appendChild(endLabelElement);
if (!terminalLabels[edge.id]) {
terminalLabels[edge.id] = {};
}
terminalLabels[edge.id].endRight = endEdgeLabelRight;
}
}; };
export const positionEdgeLabel = (edge, points) => { export const positionEdgeLabel = (edge, points) => {
@@ -55,6 +117,55 @@ export const positionEdgeLabel = (edge, points) => {
} }
el.attr('transform', 'translate(' + x + ', ' + y + ')'); el.attr('transform', 'translate(' + x + ', ' + y + ')');
} }
if (edge.startLabelLeft) {
const el = terminalLabels[edge.id].startLeft;
let x = edge.x;
let y = edge.y;
if (points) {
// debugger;
const pos = utils.calcTerminalLabelPosition(0, 'start_left', points);
x = pos.x;
y = pos.y;
}
el.attr('transform', 'translate(' + x + ', ' + y + ')');
}
if (edge.startLabelRight) {
const el = terminalLabels[edge.id].startRight;
let x = edge.x;
let y = edge.y;
if (points) {
// debugger;
const pos = utils.calcTerminalLabelPosition(0, 'start_right', points);
x = pos.x;
y = pos.y;
}
el.attr('transform', 'translate(' + x + ', ' + y + ')');
}
if (edge.endLabelLeft) {
const el = terminalLabels[edge.id].endLeft;
let x = edge.x;
let y = edge.y;
if (points) {
// debugger;
const pos = utils.calcTerminalLabelPosition(0, 'end_left', points);
x = pos.x;
y = pos.y;
}
el.attr('transform', 'translate(' + x + ', ' + y + ')');
}
if (edge.endLabelRight) {
const el = terminalLabels[edge.id].endRight;
let x = edge.x;
let y = edge.y;
if (points) {
// debugger;
const pos = utils.calcTerminalLabelPosition(0, 'end_right', points);
x = pos.x;
y = pos.y;
}
el.attr('transform', 'translate(' + x + ', ' + y + ')');
}
}; };
// const getRelationType = function(type) { // const getRelationType = function(type) {
@@ -357,5 +468,7 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
if (pointsHasChanged) { if (pointsHasChanged) {
return points; return points;
} else {
return edge.points;
} }
}; };

View File

@@ -155,6 +155,13 @@ export const addRelations = function(relations, g) {
} }
logger.info(edgeData, edge); logger.info(edgeData, edge);
//Set edge extra labels
edgeData.startLabelLeft = 'TL';
edgeData.startLabelRight = 'TR';
edgeData.endLabelLeft = 'BL';
edgeData.endLabelRight = 'BR';
//Set relation arrow types //Set relation arrow types
edgeData.arrowTypeStart = getArrowMarker(edge.relation.type1); edgeData.arrowTypeStart = getArrowMarker(edge.relation.type1);
edgeData.arrowTypeEnd = getArrowMarker(edge.relation.type2); edgeData.arrowTypeEnd = getArrowMarker(edge.relation.type2);

View File

@@ -109,6 +109,11 @@ g.classGroup line {
stroke: ${options.lineColor} !important; stroke: ${options.lineColor} !important;
stroke-width: 1; stroke-width: 1;
} }
.edgeTerminals {
font-size: 11px;
}
`; `;
export default getStyles; export default getStyles;

View File

@@ -334,6 +334,7 @@ const calcLabelPosition = points => {
const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => { const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => {
let prevPoint; let prevPoint;
let totalDistance = 0; // eslint-disable-line let totalDistance = 0; // eslint-disable-line
logger.info('our points', points);
if (points[0] !== initialPosition) { if (points[0] !== initialPosition) {
points = points.reverse(); points = points.reverse();
} }
@@ -380,6 +381,77 @@ const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition)
return cardinalityPosition; return cardinalityPosition;
}; };
/**
* position ['start_left', 'start_right', 'end_left', 'end_right']
*/
const calcTerminalLabelPosition = (terminalMarkerSize, position, _points) => {
// Todo looking to faster cloning method
let points = JSON.parse(JSON.stringify(_points));
let prevPoint;
let totalDistance = 0; // eslint-disable-line
logger.info('our points', points);
if (position !== 'start_left' && position !== 'start_right') {
points = points.reverse();
}
points.forEach(point => {
totalDistance += distance(point, prevPoint);
prevPoint = point;
});
// Traverse only 25 total distance along points to find cardinality point
const distanceToCardinalityPoint = 25;
let remainingDistance = distanceToCardinalityPoint;
let center;
prevPoint = undefined;
points.forEach(point => {
if (prevPoint && !center) {
const vectorDistance = distance(point, prevPoint);
if (vectorDistance < remainingDistance) {
remainingDistance -= vectorDistance;
} else {
// The point is remainingDistance from prevPoint in the vector between prevPoint and point
// Calculate the coordinates
const distanceRatio = remainingDistance / vectorDistance;
if (distanceRatio <= 0) center = prevPoint;
if (distanceRatio >= 1) center = { x: point.x, y: point.y };
if (distanceRatio > 0 && distanceRatio < 1) {
center = {
x: (1 - distanceRatio) * prevPoint.x + distanceRatio * point.x,
y: (1 - distanceRatio) * prevPoint.y + distanceRatio * point.y
};
}
}
}
prevPoint = point;
});
// if relation is present (Arrows will be added), change cardinality point off-set distance (d)
let d = 10;
//Calculate Angle for x and y axis
let angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);
let cardinalityPosition = { x: 0, y: 0 };
//Calculation cardinality position using angle, center point on the line/curve but pendicular and with offset-distance
cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2;
cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2;
if (position === 'start_left') {
cardinalityPosition.x = Math.sin(angle + Math.PI) * d + (points[0].x + center.x) / 2;
cardinalityPosition.y = -Math.cos(angle + Math.PI) * d + (points[0].y + center.y) / 2;
}
if (position === 'end_right') {
cardinalityPosition.x = Math.sin(angle - Math.PI) * d + (points[0].x + center.x) / 2 - 5;
cardinalityPosition.y = -Math.cos(angle - Math.PI) * d + (points[0].y + center.y) / 2 - 5;
}
if (position === 'end_left') {
cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2 - 5;
cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2 - 5;
}
return cardinalityPosition;
};
export const getStylesFromArray = arr => { export const getStylesFromArray = arr => {
let style = ''; let style = '';
let labelStyle = ''; let labelStyle = '';
@@ -708,6 +780,7 @@ export default {
interpolateToCurve, interpolateToCurve,
calcLabelPosition, calcLabelPosition,
calcCardinalityPosition, calcCardinalityPosition,
calcTerminalLabelPosition,
formatUrl, formatUrl,
getStylesFromArray, getStylesFromArray,
generateId, generateId,